1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25 /*
26 * Copyright 2010 Nexenta Systems, Inc. All rights reserved.
27 */
28
29 /*
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
35 *
36 * PM - (device) Power Management
37 *
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.
41 *
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.
55 *
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.
58 *
59 * For non-bc devices, the driver describes the components by exporting a
60 * pm-components(9P) property that tells how many components there are,
61 * tells what each component's power state values are, and provides human
62 * readable strings (currently unused) for each component name and power state.
63 * Devices which export pm-components(9P) are automatically power managed
64 * whenever autopm is enabled (via PM_START_PM ioctl issued by pmconfig(1M)
65 * after parsing power.conf(4)). The exception to this rule is that power
66 * manageable CPU devices may be automatically managed independently of autopm
67 * by either enabling or disabling (via PM_START_CPUPM and PM_STOP_CPUPM
68 * ioctls) cpupm. If the CPU devices are not managed independently, then they
69 * are managed by autopm. In either case, for automatically power managed
70 * devices, all components are considered independent of each other, and it is
71 * up to the driver to decide when a transition requires saving or restoring
72 * hardware state.
73 *
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.
78 *
79 * The PM framework provides several functions:
80 * -implement PM policy as described in power.conf(4)
81 * Policy is set by pmconfig(1M) issuing pm ioctls based on power.conf(4).
82 * Policies consist of:
83 * -set threshold values (defaults if none provided by pmconfig)
84 * -set dependencies among devices
85 * -enable/disable autopm
86 * -enable/disable cpupm
87 * -turn down idle components based on thresholds (if autopm or cpupm is
88 * enabled) (aka scanning)
89 * -maintain power states based on dependencies among devices
90 * -upon request, or when the frame buffer powers off, attempt to turn off
91 * all components that are idle or become idle over the next (10 sec)
92 * period in an attempt to get down to an EnergyStar compliant state
93 * -prevent powering off of a device which exported the
94 * pm-no-involuntary-power-cycles property without active involvement of
95 * the device's driver (so no removing power when the device driver is
96 * not attached)
97 * -provide a mechanism for a device driver to request that a device's component
98 * be brought back to the power level necessary for the use of the device
99 * -allow a process to directly control the power levels of device components
100 * (via ioctls issued to /dev/pm--see usr/src/uts/common/io/pm.c)
101 * -ensure that the console frame buffer is powered up before being referenced
102 * via prom_printf() or other prom calls that might generate console output
103 * -maintain implicit dependencies (e.g. parent must be powered up if child is)
104 * -provide "backwards compatible" behavior for devices without pm-components
105 * property
106 *
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.
112 *
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.
118 *
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.
124 *
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.
134 *
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.
142 *
143 */
144
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>
183
184
185 /*
186 * PM LOCKING
187 * The list of locks:
188 * Global pm mutex locks.
189 *
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.
194 *
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.
200 *
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.
209 *
210 * ppm_lock: protects the list of registered ppm drivers
211 * Lock ordering:
212 * ppm_lock -> ppm driver unit_lock
213 *
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.
219 *
220 * pm_dep_thread_lock:
221 * Protects work list for pm_dep_thread. Not taken concurrently
222 * with any other pm lock.
223 *
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.
230 *
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.
236 *
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.
245 *
246 * Global PM rwlocks
247 *
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
253 *
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.
257 *
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
263 *
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
269 *
270 * per-dip locks:
271 *
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)
274 *
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
284 *
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.
294 *
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.
304 *
305 */
306
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 */
316
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;
320
321 #define PM_MIN_SCAN(dip) (PM_ISCPU(dip) ? pm_cpu_min_scan : \
322 pm_default_min_scan)
323
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);
330
331 /*
332 * Dependency Processing is done thru a seperate thread.
333 */
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;
338
339 /*
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.
343 */
344 int autopm_enabled;
345
346 /*
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.
350 */
351 pm_cpupm_t cpupm = PM_CPUPM_NOTSET;
352
353 /*
354 * Defines the default mode of operation for CPU power management,
355 * either the polling implementation, or the event based dispatcher driven
356 * implementation.
357 */
358 pm_cpupm_t cpupm_default_mode = PM_CPUPM_EVENT;
359
360 /*
361 * AutoS3 depends on autopm being enabled, and must be enabled by
362 * PM_START_AUTOS3 command.
363 */
364 int autoS3_enabled;
365
366 #if !defined(__sparc)
367 /*
368 * on sparc these live in fillsysinfo.c
369 *
370 * If this variable is non-zero, cpr should return "not supported" when
371 * it is queried even though it would normally be supported on this platform.
372 */
373 int cpr_supported_override;
374
375 /*
376 * Some platforms may need to support CPR even in the absence of
377 * having the correct platform id information. If this
378 * variable is non-zero, cpr should proceed even in the absence
379 * of otherwise being qualified.
380 */
381 int cpr_platform_enable = 0;
382
383 #endif
384
385 /*
386 * pm_S3_enabled indicates that we believe the platform can support S3,
387 * which we get from pmconfig(1M)
388 */
389 int pm_S3_enabled;
390
391 /*
392 * This flag is true while processes are stopped for a checkpoint/resume.
393 * Controlling processes of direct pm'd devices are not available to
394 * participate in power level changes, so we bypass them when this is set.
395 */
396 static int pm_processes_stopped;
397
398 #ifdef DEBUG
399
400 /*
401 * see common/sys/epm.h for PMD_* values
402 */
403
404 uint_t pm_debug = 0;
405
406 /*
407 * If pm_divertdebug is set, then no prom_printf calls will be made by
408 * PMD(), which will prevent debug output from bringing up the console
409 * frame buffer. Clearing this variable before setting pm_debug will result
410 * in PMD output going to the console.
411 *
412 * pm_divertdebug is incremented in pm_set_power() if dip == cfb_dip to avoid
413 * deadlocks and decremented at the end of pm_set_power()
414 */
415 uint_t pm_divertdebug = 1;
416 volatile uint_t pm_debug_to_console = 0;
417 kmutex_t pm_debug_lock; /* protects pm_divertdebug */
418
419 void prdeps(char *);
420 #endif
421
422 /* Globals */
423
424 /*
425 * List of recorded thresholds and dependencies
426 */
427 pm_thresh_rec_t *pm_thresh_head;
428 krwlock_t pm_thresh_rwlock;
429
430 pm_pdr_t *pm_dep_head;
431 static int pm_unresolved_deps = 0;
432 static int pm_prop_deps = 0;
433
434 /*
435 * List of devices that exported no-involuntary-power-cycles property
436 */
437 pm_noinvol_t *pm_noinvol_head;
438
439 /*
440 * Locks used in noinvol processing
441 */
442 krwlock_t pm_noinvol_rwlock;
443 kmutex_t pm_remdrv_lock;
444
445 int pm_default_idle_threshold = PM_DEFAULT_SYS_IDLENESS;
446 int pm_system_idle_threshold;
447 int pm_cpu_idle_threshold;
448
449 /*
450 * By default nexus has 0 threshold, and depends on its children to keep it up
451 */
452 int pm_default_nexus_threshold = 0;
453
454 /*
455 * Data structures shared with common/io/pm.c
456 */
457 kmutex_t pm_clone_lock;
458 kcondvar_t pm_clones_cv[PM_MAX_CLONE];
459 uint_t pm_poll_cnt[PM_MAX_CLONE]; /* count of events for poll */
460 unsigned char pm_interest[PM_MAX_CLONE];
461 struct pollhead pm_pollhead;
462
463 /*
464 * Data structures shared with common/io/srn.c
465 */
466 kmutex_t srn_clone_lock; /* protects srn_signal, srn_inuse */
467 void (*srn_signal)(int type, int event);
468 int srn_inuse; /* stop srn detach */
469
470 extern int hz;
471 extern char *platform_module_list[];
472
473 /*
474 * Wrappers for use in ddi_walk_devs
475 */
476
477 static int pm_set_dev_thr_walk(dev_info_t *, void *);
478 static int pm_restore_direct_lvl_walk(dev_info_t *, void *);
479 static int pm_save_direct_lvl_walk(dev_info_t *, void *);
480 static int pm_discard_dep_walk(dev_info_t *, void *);
481 #ifdef DEBUG
482 static int pm_desc_pwrchk_walk(dev_info_t *, void *);
483 #endif
484
485 /*
486 * Routines for managing noinvol devices
487 */
488 int pm_noinvol_update(int, int, int, char *, dev_info_t *);
489 void pm_noinvol_update_node(dev_info_t *,
490 pm_bp_noinvol_t *req);
491
492 kmutex_t pm_rsvp_lock;
493 kmutex_t pm_compcnt_lock;
494 krwlock_t pm_pscc_direct_rwlock;
495 krwlock_t pm_pscc_interest_rwlock;
496
497 #define PSC_INTEREST 0 /* belongs to interest psc list */
498 #define PSC_DIRECT 1 /* belongs to direct psc list */
499
500 pscc_t *pm_pscc_interest;
501 pscc_t *pm_pscc_direct;
502
503 #define PM_MAJOR(dip) ddi_driver_major(dip)
504 #define PM_IS_NEXUS(dip) ((PM_MAJOR(dip) == DDI_MAJOR_T_NONE) ? 0 : \
505 NEXUS_DRV(devopsp[PM_MAJOR(dip)]))
506 #define POWERING_ON(old, new) ((old) == 0 && (new) != 0)
507 #define POWERING_OFF(old, new) ((old) != 0 && (new) == 0)
508
509 #define PM_INCR_NOTLOWEST(dip) { \
510 mutex_enter(&pm_compcnt_lock); \
511 if (!PM_IS_NEXUS(dip) || \
512 (DEVI(dip)->devi_pm_flags & (PMC_DEV_THRESH|PMC_COMP_THRESH))) {\
513 if (pm_comps_notlowest == 0) \
514 pm_ppm_notify_all_lowest(dip, PM_NOT_ALL_LOWEST);\
515 pm_comps_notlowest++; \
516 PMD(PMD_LEVEL, ("%s: %s@%s(%s#%d) incr notlowest->%d\n",\
517 pmf, PM_DEVICE(dip), pm_comps_notlowest)) \
518 } \
519 mutex_exit(&pm_compcnt_lock); \
520 }
521 #define PM_DECR_NOTLOWEST(dip) { \
522 mutex_enter(&pm_compcnt_lock); \
523 if (!PM_IS_NEXUS(dip) || \
524 (DEVI(dip)->devi_pm_flags & (PMC_DEV_THRESH|PMC_COMP_THRESH))) {\
525 ASSERT(pm_comps_notlowest); \
526 pm_comps_notlowest--; \
527 PMD(PMD_LEVEL, ("%s: %s@%s(%s#%d) decr notlowest to " \
528 "%d\n", pmf, PM_DEVICE(dip), pm_comps_notlowest))\
529 if (pm_comps_notlowest == 0) \
530 pm_ppm_notify_all_lowest(dip, PM_ALL_LOWEST); \
531 } \
532 mutex_exit(&pm_compcnt_lock); \
533 }
534
535 /*
536 * console frame-buffer power-management is not enabled when
537 * debugging services are present. to override, set pm_cfb_override
538 * to non-zero.
539 */
540 uint_t pm_cfb_comps_off = 0; /* PM_LEVEL_UNKNOWN is considered on */
541 kmutex_t pm_cfb_lock;
542 int pm_cfb_enabled = 1; /* non-zero allows pm of console frame buffer */
543 #ifdef DEBUG
544 int pm_cfb_override = 1; /* non-zero allows pm of cfb with debuggers */
545 #else
546 int pm_cfb_override = 0; /* non-zero allows pm of cfb with debuggers */
547 #endif
548
549 static dev_info_t *cfb_dip = 0;
550 static dev_info_t *cfb_dip_detaching = 0;
551 uint_t cfb_inuse = 0;
552 static ddi_softintr_t pm_soft_id;
553 static boolean_t pm_soft_pending;
554 int pm_scans_disabled = 0;
555
556 /*
557 * A structure to record the fact that one thread has borrowed a lock held
558 * by another thread. The context requires that the lender block on the
559 * completion of the borrower.
560 */
561 typedef struct lock_loan {
562 struct lock_loan *pmlk_next;
563 kthread_t *pmlk_borrower;
564 kthread_t *pmlk_lender;
565 dev_info_t *pmlk_dip;
566 } lock_loan_t;
567 static lock_loan_t lock_loan_head; /* list head is a dummy element */
568
569 #ifdef DEBUG
570 #ifdef PMDDEBUG
571 #define PMD_FUNC(func, name) char *(func) = (name);
572 #else /* !PMDDEBUG */
573 #define PMD_FUNC(func, name)
574 #endif /* PMDDEBUG */
575 #else /* !DEBUG */
576 #define PMD_FUNC(func, name)
577 #endif /* DEBUG */
578
579
580 /*
581 * Must be called before first device (including pseudo) attach
582 */
583 void
pm_init_locks(void)584 pm_init_locks(void)
585 {
586 mutex_init(&pm_scan_lock, NULL, MUTEX_DRIVER, NULL);
587 mutex_init(&pm_rsvp_lock, NULL, MUTEX_DRIVER, NULL);
588 mutex_init(&pm_compcnt_lock, NULL, MUTEX_DRIVER, NULL);
589 mutex_init(&pm_dep_thread_lock, NULL, MUTEX_DRIVER, NULL);
590 mutex_init(&pm_remdrv_lock, NULL, MUTEX_DRIVER, NULL);
591 mutex_init(&pm_loan_lock, NULL, MUTEX_DRIVER, NULL);
592 rw_init(&pm_thresh_rwlock, NULL, RW_DEFAULT, NULL);
593 rw_init(&pm_noinvol_rwlock, NULL, RW_DEFAULT, NULL);
594 cv_init(&pm_dep_thread_cv, NULL, CV_DEFAULT, NULL);
595 }
596
597 static int pm_reset_timestamps(dev_info_t *, void *);
598
599 static boolean_t
pm_cpr_callb(void * arg,int code)600 pm_cpr_callb(void *arg, int code)
601 {
602 _NOTE(ARGUNUSED(arg))
603 static int auto_save;
604 static pm_cpupm_t cpupm_save;
605
606 switch (code) {
607 case CB_CODE_CPR_CHKPT:
608 /*
609 * Cancel scan or wait for scan in progress to finish
610 * Other threads may be trying to restart the scan, so we
611 * have to keep at it unil it sticks
612 */
613 mutex_enter(&pm_scan_lock);
614 ASSERT(!pm_scans_disabled);
615 pm_scans_disabled = 1;
616 auto_save = autopm_enabled;
617 autopm_enabled = 0;
618 cpupm_save = cpupm;
619 cpupm = PM_CPUPM_NOTSET;
620 mutex_exit(&pm_scan_lock);
621 ddi_walk_devs(ddi_root_node(), pm_scan_stop_walk, NULL);
622 break;
623
624 case CB_CODE_CPR_RESUME:
625 ASSERT(!autopm_enabled);
626 ASSERT(cpupm == PM_CPUPM_NOTSET);
627 ASSERT(pm_scans_disabled);
628 pm_scans_disabled = 0;
629 /*
630 * Call pm_reset_timestamps to reset timestamps of each
631 * device to the time when the system is resumed so that their
632 * idleness can be re-calculated. That's to avoid devices from
633 * being powered down right after resume if the system was in
634 * suspended mode long enough.
635 */
636 ddi_walk_devs(ddi_root_node(), pm_reset_timestamps, NULL);
637
638 autopm_enabled = auto_save;
639 cpupm = cpupm_save;
640 /*
641 * If there is any auto-pm device, get the scanning
642 * going. Otherwise don't bother.
643 */
644 ddi_walk_devs(ddi_root_node(), pm_rescan_walk, NULL);
645 break;
646 }
647 return (B_TRUE);
648 }
649
650 /*
651 * This callback routine is called when there is a system panic. This function
652 * exists for prototype matching.
653 */
654 static boolean_t
pm_panic_callb(void * arg,int code)655 pm_panic_callb(void *arg, int code)
656 {
657 _NOTE(ARGUNUSED(arg, code))
658 void pm_cfb_check_and_powerup(void);
659 PMD(PMD_CFB, ("pm_panic_callb\n"))
660 pm_cfb_check_and_powerup();
661 return (B_TRUE);
662 }
663
664 static boolean_t
pm_halt_callb(void * arg,int code)665 pm_halt_callb(void *arg, int code)
666 {
667 _NOTE(ARGUNUSED(arg, code))
668 return (B_TRUE);
669 }
670
671 static void pm_dep_thread(void);
672
673 /*
674 * This needs to be called after the root and platform drivers are loaded
675 * and be single-threaded with respect to driver attach/detach
676 */
677 void
pm_init(void)678 pm_init(void)
679 {
680 PMD_FUNC(pmf, "pm_init")
681 char **mod;
682 extern pri_t minclsyspri;
683
684 pm_comps_notlowest = 0;
685 pm_system_idle_threshold = pm_default_idle_threshold;
686 pm_cpu_idle_threshold = 0;
687
688 pm_cpr_cb_id = callb_add(pm_cpr_callb, (void *)NULL,
689 CB_CL_CPR_PM, "pm_cpr");
690 pm_panic_cb_id = callb_add(pm_panic_callb, (void *)NULL,
691 CB_CL_PANIC, "pm_panic");
692 pm_halt_cb_id = callb_add(pm_halt_callb, (void *)NULL,
693 CB_CL_HALT, "pm_halt");
694
695 /*
696 * Create a thread to do dependency processing.
697 */
698 (void) thread_create(NULL, 0, (void (*)())pm_dep_thread, NULL, 0, &p0,
699 TS_RUN, minclsyspri);
700
701 /*
702 * loadrootmodules already loaded these ppm drivers, now get them
703 * attached so they can claim the root drivers as they attach
704 */
705 for (mod = platform_module_list; *mod; mod++) {
706 if (i_ddi_attach_hw_nodes(*mod) != DDI_SUCCESS) {
707 cmn_err(CE_WARN, "!cannot load platform pm driver %s\n",
708 *mod);
709 } else {
710 PMD(PMD_DHR, ("%s: %s (%s)\n", pmf, *mod,
711 ddi_major_to_name(ddi_name_to_major(*mod))))
712 }
713 }
714 }
715
716 /*
717 * pm_scan_init - create pm scan data structure. Called (if autopm or cpupm
718 * enabled) when device becomes power managed or after a failed detach and
719 * when autopm is started via PM_START_PM or PM_START_CPUPM ioctls, and after
720 * a CPR resume to get all the devices scanning again.
721 */
722 void
pm_scan_init(dev_info_t * dip)723 pm_scan_init(dev_info_t *dip)
724 {
725 PMD_FUNC(pmf, "scan_init")
726 pm_scan_t *scanp;
727
728 ASSERT(!PM_ISBC(dip));
729
730 PM_LOCK_DIP(dip);
731 scanp = PM_GET_PM_SCAN(dip);
732 if (!scanp) {
733 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): create scan data\n",
734 pmf, PM_DEVICE(dip)))
735 scanp = kmem_zalloc(sizeof (pm_scan_t), KM_SLEEP);
736 DEVI(dip)->devi_pm_scan = scanp;
737 } else if (scanp->ps_scan_flags & PM_SCAN_STOP) {
738 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): "
739 "clear PM_SCAN_STOP flag\n", pmf, PM_DEVICE(dip)))
740 scanp->ps_scan_flags &= ~PM_SCAN_STOP;
741 }
742 PM_UNLOCK_DIP(dip);
743 }
744
745 /*
746 * pm_scan_fini - remove pm scan data structure when stopping pm on the device
747 */
748 void
pm_scan_fini(dev_info_t * dip)749 pm_scan_fini(dev_info_t *dip)
750 {
751 PMD_FUNC(pmf, "scan_fini")
752 pm_scan_t *scanp;
753
754 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
755 ASSERT(!PM_ISBC(dip));
756 PM_LOCK_DIP(dip);
757 scanp = PM_GET_PM_SCAN(dip);
758 if (!scanp) {
759 PM_UNLOCK_DIP(dip);
760 return;
761 }
762
763 ASSERT(!scanp->ps_scan_id && !(scanp->ps_scan_flags &
764 (PM_SCANNING | PM_SCAN_DISPATCHED | PM_SCAN_AGAIN)));
765
766 kmem_free(scanp, sizeof (pm_scan_t));
767 DEVI(dip)->devi_pm_scan = NULL;
768 PM_UNLOCK_DIP(dip);
769 }
770
771 /*
772 * Given a pointer to a component struct, return the current power level
773 * (struct contains index unless it is a continuous level).
774 * Located here in hopes of getting both this and dev_is_needed into the
775 * cache together
776 */
777 static int
cur_power(pm_component_t * cp)778 cur_power(pm_component_t *cp)
779 {
780 if (cp->pmc_cur_pwr == PM_LEVEL_UNKNOWN)
781 return (cp->pmc_cur_pwr);
782
783 return (cp->pmc_comp.pmc_lvals[cp->pmc_cur_pwr]);
784 }
785
786 static char *
pm_decode_direction(int direction)787 pm_decode_direction(int direction)
788 {
789 switch (direction) {
790 case PM_LEVEL_UPONLY:
791 return ("up");
792
793 case PM_LEVEL_EXACT:
794 return ("exact");
795
796 case PM_LEVEL_DOWNONLY:
797 return ("down");
798
799 default:
800 return ("INVALID DIRECTION");
801 }
802 }
803
804 char *
pm_decode_op(pm_bus_power_op_t op)805 pm_decode_op(pm_bus_power_op_t op)
806 {
807 switch (op) {
808 case BUS_POWER_CHILD_PWRCHG:
809 return ("CHILD_PWRCHG");
810 case BUS_POWER_NEXUS_PWRUP:
811 return ("NEXUS_PWRUP");
812 case BUS_POWER_PRE_NOTIFICATION:
813 return ("PRE_NOTIFICATION");
814 case BUS_POWER_POST_NOTIFICATION:
815 return ("POST_NOTIFICATION");
816 case BUS_POWER_HAS_CHANGED:
817 return ("HAS_CHANGED");
818 case BUS_POWER_NOINVOL:
819 return ("NOINVOL");
820 default:
821 return ("UNKNOWN OP");
822 }
823 }
824
825 /*
826 * Returns true if level is a possible (valid) power level for component
827 */
828 int
e_pm_valid_power(dev_info_t * dip,int cmpt,int level)829 e_pm_valid_power(dev_info_t *dip, int cmpt, int level)
830 {
831 PMD_FUNC(pmf, "e_pm_valid_power")
832 pm_component_t *cp = PM_CP(dip, cmpt);
833 int i;
834 int *ip = cp->pmc_comp.pmc_lvals;
835 int limit = cp->pmc_comp.pmc_numlevels;
836
837 if (level < 0)
838 return (0);
839 for (i = 0; i < limit; i++) {
840 if (level == *ip++)
841 return (1);
842 }
843 #ifdef DEBUG
844 if (pm_debug & PMD_FAIL) {
845 ip = cp->pmc_comp.pmc_lvals;
846
847 for (i = 0; i < limit; i++)
848 PMD(PMD_FAIL, ("%s: index=%d, level=%d\n",
849 pmf, i, *ip++))
850 }
851 #endif
852 return (0);
853 }
854
855 static int pm_start(dev_info_t *dip);
856 /*
857 * Returns true if device is pm'd (after calling pm_start if need be)
858 */
859 int
e_pm_valid_info(dev_info_t * dip,pm_info_t ** infop)860 e_pm_valid_info(dev_info_t *dip, pm_info_t **infop)
861 {
862 pm_info_t *info;
863
864 /*
865 * Check if the device is power managed if not.
866 * To make the common case (device is power managed already)
867 * fast, we check without the lock. If device is not already
868 * power managed, then we take the lock and the long route through
869 * go get it managed. Devices never go unmanaged until they
870 * detach.
871 */
872 info = PM_GET_PM_INFO(dip);
873 if (!info) {
874 if (!DEVI_IS_ATTACHING(dip)) {
875 return (0);
876 }
877 if (pm_start(dip) != DDI_SUCCESS) {
878 return (0);
879 }
880 info = PM_GET_PM_INFO(dip);
881 }
882 ASSERT(info);
883 if (infop != NULL)
884 *infop = info;
885 return (1);
886 }
887
888 int
e_pm_valid_comp(dev_info_t * dip,int cmpt,pm_component_t ** cpp)889 e_pm_valid_comp(dev_info_t *dip, int cmpt, pm_component_t **cpp)
890 {
891 if (cmpt >= 0 && cmpt < PM_NUMCMPTS(dip)) {
892 if (cpp != NULL)
893 *cpp = PM_CP(dip, cmpt);
894 return (1);
895 } else {
896 return (0);
897 }
898 }
899
900 /*
901 * Internal guts of ddi_dev_is_needed and pm_raise/lower_power
902 */
903 static int
dev_is_needed(dev_info_t * dip,int cmpt,int level,int direction)904 dev_is_needed(dev_info_t *dip, int cmpt, int level, int direction)
905 {
906 PMD_FUNC(pmf, "din")
907 pm_component_t *cp;
908 char *pathbuf;
909 int result;
910
911 ASSERT(direction == PM_LEVEL_UPONLY || direction == PM_LEVEL_DOWNONLY);
912 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, cmpt, &cp) ||
913 !e_pm_valid_power(dip, cmpt, level))
914 return (DDI_FAILURE);
915
916 PMD(PMD_DIN, ("%s: %s@%s(%s#%d) cmpt=%d, dir=%s, new=%d, cur=%d\n",
917 pmf, PM_DEVICE(dip), cmpt, pm_decode_direction(direction),
918 level, cur_power(cp)))
919
920 if (pm_set_power(dip, cmpt, level, direction,
921 PM_CANBLOCK_BLOCK, 0, &result) != DDI_SUCCESS) {
922 if (direction == PM_LEVEL_UPONLY) {
923 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
924 (void) ddi_pathname(dip, pathbuf);
925 cmn_err(CE_WARN, "Device %s failed to power up.",
926 pathbuf);
927 kmem_free(pathbuf, MAXPATHLEN);
928 }
929 PMD(PMD_DIN | PMD_FAIL, ("%s: %s@%s(%s#%d) [%d] %s->%d failed, "
930 "errno %d\n", pmf, PM_DEVICE(dip), cmpt,
931 pm_decode_direction(direction), level, result))
932 return (DDI_FAILURE);
933 }
934
935 PMD(PMD_RESCAN | PMD_DIN, ("%s: pm_rescan %s@%s(%s#%d)\n", pmf,
936 PM_DEVICE(dip)))
937 pm_rescan(dip);
938 return (DDI_SUCCESS);
939 }
940
941 /*
942 * We can get multiple pm_rescan() threads, if one of them discovers
943 * that no scan is running at the moment, it kicks it into action.
944 * Otherwise, it tells the current scanning thread to scan again when
945 * it is done by asserting the PM_SCAN_AGAIN flag. The PM_SCANNING and
946 * PM_SCAN_AGAIN flags are used to regulate scan, to make sure only one
947 * thread at a time runs the pm_scan_dev() code.
948 */
949 void
pm_rescan(void * arg)950 pm_rescan(void *arg)
951 {
952 PMD_FUNC(pmf, "rescan")
953 dev_info_t *dip = (dev_info_t *)arg;
954 pm_info_t *info;
955 pm_scan_t *scanp;
956 timeout_id_t scanid;
957
958 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
959 PM_LOCK_DIP(dip);
960 info = PM_GET_PM_INFO(dip);
961 scanp = PM_GET_PM_SCAN(dip);
962 if (pm_scans_disabled || !PM_SCANABLE(dip) || !info || !scanp ||
963 (scanp->ps_scan_flags & PM_SCAN_STOP)) {
964 PM_UNLOCK_DIP(dip);
965 return;
966 }
967 if (scanp->ps_scan_flags & PM_SCANNING) {
968 scanp->ps_scan_flags |= PM_SCAN_AGAIN;
969 PM_UNLOCK_DIP(dip);
970 return;
971 } else if (scanp->ps_scan_id) {
972 scanid = scanp->ps_scan_id;
973 scanp->ps_scan_id = 0;
974 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): cancel timeout scanid %lx\n",
975 pmf, PM_DEVICE(dip), (ulong_t)scanid))
976 PM_UNLOCK_DIP(dip);
977 (void) untimeout(scanid);
978 PM_LOCK_DIP(dip);
979 }
980
981 /*
982 * Dispatching pm_scan during attach time is risky due to the fact that
983 * attach might soon fail and dip dissolved, and panic may happen while
984 * attempting to stop scan. So schedule a pm_rescan instead.
985 * (Note that if either of the first two terms are true, taskq_dispatch
986 * will not be invoked).
987 *
988 * Multiple pm_scan dispatching is unecessary and costly to keep track
989 * of. The PM_SCAN_DISPATCHED flag is used between pm_rescan and pm_scan
990 * to regulate the dispatching.
991 *
992 * Scan is stopped before the device is detached (in pm_detaching())
993 * but it may get re-started during the post_detach processing if the
994 * driver fails to detach.
995 */
996 if (DEVI_IS_ATTACHING(dip) ||
997 (scanp->ps_scan_flags & PM_SCAN_DISPATCHED) ||
998 !taskq_dispatch(system_taskq, pm_scan, (void *)dip, TQ_NOSLEEP)) {
999 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): attaching, pm_scan already "
1000 "dispatched or dispatching failed\n", pmf, PM_DEVICE(dip)))
1001 if (scanp->ps_scan_id) {
1002 scanid = scanp->ps_scan_id;
1003 scanp->ps_scan_id = 0;
1004 PM_UNLOCK_DIP(dip);
1005 (void) untimeout(scanid);
1006 PM_LOCK_DIP(dip);
1007 if (scanp->ps_scan_id) {
1008 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): a competing "
1009 "thread scheduled pm_rescan, scanid %lx\n",
1010 pmf, PM_DEVICE(dip),
1011 (ulong_t)scanp->ps_scan_id))
1012 PM_UNLOCK_DIP(dip);
1013 return;
1014 }
1015 }
1016 scanp->ps_scan_id = timeout(pm_rescan, (void *)dip,
1017 (scanp->ps_idle_down ? pm_id_ticks :
1018 (PM_MIN_SCAN(dip) * hz)));
1019 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): scheduled next pm_rescan, "
1020 "scanid %lx\n", pmf, PM_DEVICE(dip),
1021 (ulong_t)scanp->ps_scan_id))
1022 } else {
1023 PMD(PMD_SCAN, ("%s: dispatched pm_scan for %s@%s(%s#%d)\n",
1024 pmf, PM_DEVICE(dip)))
1025 scanp->ps_scan_flags |= PM_SCAN_DISPATCHED;
1026 }
1027 PM_UNLOCK_DIP(dip);
1028 }
1029
1030 void
pm_scan(void * arg)1031 pm_scan(void *arg)
1032 {
1033 PMD_FUNC(pmf, "scan")
1034 dev_info_t *dip = (dev_info_t *)arg;
1035 pm_scan_t *scanp;
1036 time_t nextscan;
1037
1038 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
1039
1040 PM_LOCK_DIP(dip);
1041 scanp = PM_GET_PM_SCAN(dip);
1042 ASSERT(scanp && PM_GET_PM_INFO(dip));
1043
1044 if (pm_scans_disabled || !PM_SCANABLE(dip) ||
1045 (scanp->ps_scan_flags & PM_SCAN_STOP)) {
1046 scanp->ps_scan_flags &= ~(PM_SCAN_AGAIN | PM_SCAN_DISPATCHED);
1047 PM_UNLOCK_DIP(dip);
1048 return;
1049 }
1050
1051 if (scanp->ps_idle_down) {
1052 /*
1053 * make sure we remember idledown was in affect until
1054 * we've completed the scan
1055 */
1056 PMID_SET_SCANS(scanp->ps_idle_down)
1057 PMD(PMD_IDLEDOWN, ("%s: %s@%s(%s#%d): idledown starts "
1058 "(pmid %x)\n", pmf, PM_DEVICE(dip), scanp->ps_idle_down))
1059 }
1060
1061 /* possible having two threads running pm_scan() */
1062 if (scanp->ps_scan_flags & PM_SCANNING) {
1063 scanp->ps_scan_flags |= PM_SCAN_AGAIN;
1064 PMD(PMD_SCAN, ("%s: scanning, will scan %s@%s(%s#%d) again\n",
1065 pmf, PM_DEVICE(dip)))
1066 scanp->ps_scan_flags &= ~PM_SCAN_DISPATCHED;
1067 PM_UNLOCK_DIP(dip);
1068 return;
1069 }
1070
1071 scanp->ps_scan_flags |= PM_SCANNING;
1072 scanp->ps_scan_flags &= ~PM_SCAN_DISPATCHED;
1073 do {
1074 scanp->ps_scan_flags &= ~PM_SCAN_AGAIN;
1075 PM_UNLOCK_DIP(dip);
1076 nextscan = pm_scan_dev(dip);
1077 PM_LOCK_DIP(dip);
1078 } while (scanp->ps_scan_flags & PM_SCAN_AGAIN);
1079
1080 ASSERT(scanp->ps_scan_flags & PM_SCANNING);
1081 scanp->ps_scan_flags &= ~PM_SCANNING;
1082
1083 if (scanp->ps_idle_down) {
1084 scanp->ps_idle_down &= ~PMID_SCANS;
1085 PMD(PMD_IDLEDOWN, ("%s: %s@%s(%s#%d): idledown ends "
1086 "(pmid %x)\n", pmf, PM_DEVICE(dip), scanp->ps_idle_down))
1087 }
1088
1089 /* schedule for next idle check */
1090 if (nextscan != LONG_MAX) {
1091 if (nextscan > (LONG_MAX / hz))
1092 nextscan = (LONG_MAX - 1) / hz;
1093 if (scanp->ps_scan_id) {
1094 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): while scanning "
1095 "another rescan scheduled scanid(%lx)\n", pmf,
1096 PM_DEVICE(dip), (ulong_t)scanp->ps_scan_id))
1097 PM_UNLOCK_DIP(dip);
1098 return;
1099 } else if (!(scanp->ps_scan_flags & PM_SCAN_STOP)) {
1100 scanp->ps_scan_id = timeout(pm_rescan, (void *)dip,
1101 (clock_t)(nextscan * hz));
1102 PMD(PMD_SCAN, ("%s: nextscan for %s@%s(%s#%d) in "
1103 "%lx sec, scanid(%lx) \n", pmf, PM_DEVICE(dip),
1104 (ulong_t)nextscan, (ulong_t)scanp->ps_scan_id))
1105 }
1106 }
1107 PM_UNLOCK_DIP(dip);
1108 }
1109
1110 void
pm_get_timestamps(dev_info_t * dip,time_t * valuep)1111 pm_get_timestamps(dev_info_t *dip, time_t *valuep)
1112 {
1113 int components = PM_NUMCMPTS(dip);
1114 int i;
1115
1116 ASSERT(components > 0);
1117 PM_LOCK_BUSY(dip); /* so we get a consistent view */
1118 for (i = 0; i < components; i++) {
1119 valuep[i] = PM_CP(dip, i)->pmc_timestamp;
1120 }
1121 PM_UNLOCK_BUSY(dip);
1122 }
1123
1124 /*
1125 * Returns true if device needs to be kept up because it exported the
1126 * "no-involuntary-power-cycles" property or we're pretending it did (console
1127 * fb case) or it is an ancestor of such a device and has used up the "one
1128 * free cycle" allowed when all such leaf nodes have voluntarily powered down
1129 * upon detach
1130 */
1131 int
pm_noinvol(dev_info_t * dip)1132 pm_noinvol(dev_info_t *dip)
1133 {
1134 PMD_FUNC(pmf, "noinvol")
1135
1136 /*
1137 * This doesn't change over the life of a driver, so no locking needed
1138 */
1139 if (PM_IS_CFB(dip)) {
1140 PMD(PMD_NOINVOL | PMD_CFB, ("%s: inhibits CFB %s@%s(%s#%d)\n",
1141 pmf, PM_DEVICE(dip)))
1142 return (1);
1143 }
1144 /*
1145 * Not an issue if no such kids
1146 */
1147 if (DEVI(dip)->devi_pm_noinvolpm == 0) {
1148 #ifdef DEBUG
1149 if (DEVI(dip)->devi_pm_volpmd != 0) {
1150 dev_info_t *pdip = dip;
1151 do {
1152 PMD(PMD_NOINVOL, ("%s: %s@%s(%s#%d) noinvol %d "
1153 "volpmd %d\n", pmf, PM_DEVICE(pdip),
1154 DEVI(pdip)->devi_pm_noinvolpm,
1155 DEVI(pdip)->devi_pm_volpmd))
1156 pdip = ddi_get_parent(pdip);
1157 } while (pdip);
1158 }
1159 #endif
1160 ASSERT(DEVI(dip)->devi_pm_volpmd == 0);
1161 return (0);
1162 }
1163
1164 /*
1165 * Since we now maintain the counts correct at every node, we no longer
1166 * need to look up the tree. An ancestor cannot use up the free cycle
1167 * without the children getting their counts adjusted.
1168 */
1169
1170 #ifdef DEBUG
1171 if (DEVI(dip)->devi_pm_noinvolpm != DEVI(dip)->devi_pm_volpmd)
1172 PMD(PMD_NOINVOL, ("%s: (%d != %d) inhibits %s@%s(%s#%d)\n", pmf,
1173 DEVI(dip)->devi_pm_noinvolpm, DEVI(dip)->devi_pm_volpmd,
1174 PM_DEVICE(dip)))
1175 #endif
1176 return (DEVI(dip)->devi_pm_noinvolpm != DEVI(dip)->devi_pm_volpmd);
1177 }
1178
1179 static int cur_threshold(dev_info_t *, int);
1180 static int pm_next_lower_power(pm_component_t *, int);
1181
1182 /*
1183 * This function performs the actual scanning of the device.
1184 * It attempts to power off the indicated device's components if they have
1185 * been idle and other restrictions are met.
1186 * pm_scan_dev calculates and returns when the next scan should happen for
1187 * this device.
1188 */
1189 time_t
pm_scan_dev(dev_info_t * dip)1190 pm_scan_dev(dev_info_t *dip)
1191 {
1192 PMD_FUNC(pmf, "scan_dev")
1193 pm_scan_t *scanp;
1194 time_t *timestamp, idletime, now, thresh;
1195 time_t timeleft = 0;
1196 #ifdef PMDDEBUG
1197 int curpwr;
1198 #endif
1199 int i, nxtpwr, pwrndx, unused;
1200 size_t size;
1201 pm_component_t *cp;
1202 dev_info_t *pdip = ddi_get_parent(dip);
1203 int circ;
1204 clock_t min_scan = pm_default_min_scan;
1205
1206 /*
1207 * skip attaching device
1208 */
1209 if (DEVI_IS_ATTACHING(dip)) {
1210 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) is attaching, timeleft(%lx)\n",
1211 pmf, PM_DEVICE(dip), min_scan))
1212 return (min_scan);
1213 }
1214
1215 PM_LOCK_DIP(dip);
1216 scanp = PM_GET_PM_SCAN(dip);
1217 min_scan = PM_MIN_SCAN(dip);
1218 ASSERT(scanp && PM_GET_PM_INFO(dip));
1219
1220 PMD(PMD_SCAN, ("%s: [BEGIN %s@%s(%s#%d)]\n", pmf, PM_DEVICE(dip)))
1221 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d): kuc is %d\n", pmf, PM_DEVICE(dip),
1222 PM_KUC(dip)))
1223
1224 /* no scan under the following conditions */
1225 if (pm_scans_disabled || !PM_SCANABLE(dip) ||
1226 (scanp->ps_scan_flags & PM_SCAN_STOP) ||
1227 (PM_KUC(dip) != 0) ||
1228 PM_ISDIRECT(dip) || pm_noinvol(dip)) {
1229 PM_UNLOCK_DIP(dip);
1230 PMD(PMD_SCAN, ("%s: [END, %s@%s(%s#%d)] no scan, "
1231 "scan_disabled(%d), apm_enabled(%d), cpupm(%d), "
1232 "kuc(%d), %s directpm, %s pm_noinvol\n",
1233 pmf, PM_DEVICE(dip), pm_scans_disabled, autopm_enabled,
1234 cpupm, PM_KUC(dip),
1235 PM_ISDIRECT(dip) ? "is" : "is not",
1236 pm_noinvol(dip) ? "is" : "is not"))
1237 return (LONG_MAX);
1238 }
1239 PM_UNLOCK_DIP(dip);
1240
1241 if (!ndi_devi_tryenter(pdip, &circ)) {
1242 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) can't hold pdip",
1243 pmf, PM_DEVICE(pdip)))
1244 return ((time_t)1);
1245 }
1246 now = gethrestime_sec();
1247 size = PM_NUMCMPTS(dip) * sizeof (time_t);
1248 timestamp = kmem_alloc(size, KM_SLEEP);
1249 pm_get_timestamps(dip, timestamp);
1250
1251 /*
1252 * Since we removed support for backwards compatible devices,
1253 * (see big comment at top of file)
1254 * it is no longer required to deal with component 0 last.
1255 */
1256 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
1257 /*
1258 * If already off (an optimization, perhaps)
1259 */
1260 cp = PM_CP(dip, i);
1261 pwrndx = cp->pmc_cur_pwr;
1262 #ifdef PMDDEBUG
1263 curpwr = (pwrndx == PM_LEVEL_UNKNOWN) ?
1264 PM_LEVEL_UNKNOWN :
1265 cp->pmc_comp.pmc_lvals[pwrndx];
1266 #endif
1267
1268 if (pwrndx == 0) {
1269 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d off or "
1270 "lowest\n", pmf, PM_DEVICE(dip), i))
1271 /* skip device if off or at its lowest */
1272 continue;
1273 }
1274
1275 thresh = cur_threshold(dip, i); /* comp i threshold */
1276 if ((timestamp[i] == 0) || (cp->pmc_busycount > 0)) {
1277 /* were busy or newly became busy by another thread */
1278 if (timeleft == 0)
1279 timeleft = max(thresh, min_scan);
1280 else
1281 timeleft = min(
1282 timeleft, max(thresh, min_scan));
1283 continue;
1284 }
1285
1286 idletime = now - timestamp[i]; /* idle time */
1287 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d idle time %lx\n",
1288 pmf, PM_DEVICE(dip), i, idletime))
1289 if (idletime >= thresh || PM_IS_PID(dip)) {
1290 nxtpwr = pm_next_lower_power(cp, pwrndx);
1291 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d, %d->%d\n",
1292 pmf, PM_DEVICE(dip), i, curpwr, nxtpwr))
1293 if (pm_set_power(dip, i, nxtpwr, PM_LEVEL_DOWNONLY,
1294 PM_CANBLOCK_FAIL, 1, &unused) != DDI_SUCCESS &&
1295 PM_CURPOWER(dip, i) != nxtpwr) {
1296 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d, "
1297 "%d->%d Failed\n", pmf, PM_DEVICE(dip),
1298 i, curpwr, nxtpwr))
1299 timeleft = min_scan;
1300 continue;
1301 } else {
1302 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d, "
1303 "%d->%d, GOOD curpwr %d\n", pmf,
1304 PM_DEVICE(dip), i, curpwr, nxtpwr,
1305 cur_power(cp)))
1306
1307 if (nxtpwr == 0) /* component went off */
1308 continue;
1309
1310 /*
1311 * scan to next lower level
1312 */
1313 if (timeleft == 0)
1314 timeleft = max(
1315 1, cur_threshold(dip, i));
1316 else
1317 timeleft = min(timeleft,
1318 max(1, cur_threshold(dip, i)));
1319 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d, "
1320 "timeleft(%lx)\n", pmf, PM_DEVICE(dip),
1321 i, timeleft))
1322 }
1323 } else { /* comp not idle long enough */
1324 if (timeleft == 0)
1325 timeleft = thresh - idletime;
1326 else
1327 timeleft = min(timeleft, (thresh - idletime));
1328 PMD(PMD_SCAN, ("%s: %s@%s(%s#%d) comp %d, timeleft="
1329 "%lx\n", pmf, PM_DEVICE(dip), i, timeleft))
1330 }
1331 }
1332 ndi_devi_exit(pdip, circ);
1333 kmem_free(timestamp, size);
1334 PMD(PMD_SCAN, ("%s: [END %s@%s(%s#%d)] timeleft(%lx)\n", pmf,
1335 PM_DEVICE(dip), timeleft))
1336
1337 /*
1338 * if components are already at lowest level, timeleft is left 0
1339 */
1340 return ((timeleft == 0) ? LONG_MAX : timeleft);
1341 }
1342
1343 /*
1344 * pm_scan_stop - cancel scheduled pm_rescan,
1345 * wait for termination of dispatched pm_scan thread
1346 * and active pm_scan_dev thread.
1347 */
1348 void
pm_scan_stop(dev_info_t * dip)1349 pm_scan_stop(dev_info_t *dip)
1350 {
1351 PMD_FUNC(pmf, "scan_stop")
1352 pm_scan_t *scanp;
1353 timeout_id_t scanid;
1354
1355 PMD(PMD_SCAN, ("%s: [BEGIN %s@%s(%s#%d)]\n", pmf, PM_DEVICE(dip)))
1356 PM_LOCK_DIP(dip);
1357 scanp = PM_GET_PM_SCAN(dip);
1358 if (!scanp) {
1359 PMD(PMD_SCAN, ("%s: [END %s@%s(%s#%d)] scan not initialized\n",
1360 pmf, PM_DEVICE(dip)))
1361 PM_UNLOCK_DIP(dip);
1362 return;
1363 }
1364 scanp->ps_scan_flags |= PM_SCAN_STOP;
1365
1366 /* cancel scheduled scan taskq */
1367 while (scanp->ps_scan_id) {
1368 scanid = scanp->ps_scan_id;
1369 scanp->ps_scan_id = 0;
1370 PM_UNLOCK_DIP(dip);
1371 (void) untimeout(scanid);
1372 PM_LOCK_DIP(dip);
1373 }
1374
1375 while (scanp->ps_scan_flags & (PM_SCANNING | PM_SCAN_DISPATCHED)) {
1376 PM_UNLOCK_DIP(dip);
1377 delay(1);
1378 PM_LOCK_DIP(dip);
1379 }
1380 PM_UNLOCK_DIP(dip);
1381 PMD(PMD_SCAN, ("%s: [END %s@%s(%s#%d)]\n", pmf, PM_DEVICE(dip)))
1382 }
1383
1384 int
pm_scan_stop_walk(dev_info_t * dip,void * arg)1385 pm_scan_stop_walk(dev_info_t *dip, void *arg)
1386 {
1387 _NOTE(ARGUNUSED(arg))
1388
1389 if (!PM_GET_PM_SCAN(dip))
1390 return (DDI_WALK_CONTINUE);
1391 ASSERT(!PM_ISBC(dip));
1392 pm_scan_stop(dip);
1393 return (DDI_WALK_CONTINUE);
1394 }
1395
1396 /*
1397 * Converts a power level value to its index
1398 */
1399 static int
power_val_to_index(pm_component_t * cp,int val)1400 power_val_to_index(pm_component_t *cp, int val)
1401 {
1402 int limit, i, *ip;
1403
1404 ASSERT(val != PM_LEVEL_UPONLY && val != PM_LEVEL_DOWNONLY &&
1405 val != PM_LEVEL_EXACT);
1406 /* convert power value into index (i) */
1407 limit = cp->pmc_comp.pmc_numlevels;
1408 ip = cp->pmc_comp.pmc_lvals;
1409 for (i = 0; i < limit; i++)
1410 if (val == *ip++)
1411 return (i);
1412 return (-1);
1413 }
1414
1415 /*
1416 * Converts a numeric power level to a printable string
1417 */
1418 static char *
power_val_to_string(pm_component_t * cp,int val)1419 power_val_to_string(pm_component_t *cp, int val)
1420 {
1421 int index;
1422
1423 if (val == PM_LEVEL_UPONLY)
1424 return ("<UPONLY>");
1425
1426 if (val == PM_LEVEL_UNKNOWN ||
1427 (index = power_val_to_index(cp, val)) == -1)
1428 return ("<LEVEL_UNKNOWN>");
1429
1430 return (cp->pmc_comp.pmc_lnames[index]);
1431 }
1432
1433 /*
1434 * Return true if this node has been claimed by a ppm.
1435 */
1436 static int
pm_ppm_claimed(dev_info_t * dip)1437 pm_ppm_claimed(dev_info_t *dip)
1438 {
1439 return (PPM(dip) != NULL);
1440 }
1441
1442 /*
1443 * A node which was voluntarily power managed has just used up its "free cycle"
1444 * and need is volpmd field cleared, and the same done to all its descendents
1445 */
1446 static void
pm_clear_volpm_dip(dev_info_t * dip)1447 pm_clear_volpm_dip(dev_info_t *dip)
1448 {
1449 PMD_FUNC(pmf, "clear_volpm_dip")
1450
1451 if (dip == NULL)
1452 return;
1453 PMD(PMD_NOINVOL, ("%s: clear volpm from %s@%s(%s#%d)\n", pmf,
1454 PM_DEVICE(dip)))
1455 DEVI(dip)->devi_pm_volpmd = 0;
1456 for (dip = ddi_get_child(dip); dip; dip = ddi_get_next_sibling(dip)) {
1457 pm_clear_volpm_dip(dip);
1458 }
1459 }
1460
1461 /*
1462 * A node which was voluntarily power managed has used up the "free cycles"
1463 * for the subtree that it is the root of. Scan through the list of detached
1464 * nodes and adjust the counts of any that are descendents of the node.
1465 */
1466 static void
pm_clear_volpm_list(dev_info_t * dip)1467 pm_clear_volpm_list(dev_info_t *dip)
1468 {
1469 PMD_FUNC(pmf, "clear_volpm_list")
1470 char *pathbuf;
1471 size_t len;
1472 pm_noinvol_t *ip;
1473
1474 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1475 (void) ddi_pathname(dip, pathbuf);
1476 len = strlen(pathbuf);
1477 PMD(PMD_NOINVOL, ("%s: clear volpm list %s\n", pmf, pathbuf))
1478 rw_enter(&pm_noinvol_rwlock, RW_WRITER);
1479 for (ip = pm_noinvol_head; ip; ip = ip->ni_next) {
1480 PMD(PMD_NOINVOL, ("%s: clear volpm: ni_path %s\n", pmf,
1481 ip->ni_path))
1482 if (strncmp(pathbuf, ip->ni_path, len) == 0 &&
1483 ip->ni_path[len] == '/') {
1484 PMD(PMD_NOINVOL, ("%s: clear volpm: %s\n", pmf,
1485 ip->ni_path))
1486 ip->ni_volpmd = 0;
1487 ip->ni_wasvolpmd = 0;
1488 }
1489 }
1490 kmem_free(pathbuf, MAXPATHLEN);
1491 rw_exit(&pm_noinvol_rwlock);
1492 }
1493
1494 /*
1495 * Powers a device, suspending or resuming the driver if it is a backward
1496 * compatible device, calling into ppm to change power level.
1497 * Called with the component's power lock held.
1498 */
1499 static int
power_dev(dev_info_t * dip,int comp,int level,int old_level,pm_canblock_t canblock,pm_ppm_devlist_t ** devlist)1500 power_dev(dev_info_t *dip, int comp, int level, int old_level,
1501 pm_canblock_t canblock, pm_ppm_devlist_t **devlist)
1502 {
1503 PMD_FUNC(pmf, "power_dev")
1504 power_req_t power_req;
1505 int power_op_ret; /* DDI_SUCCESS or DDI_FAILURE */
1506 int resume_needed = 0;
1507 int suspended = 0;
1508 int result;
1509 #ifdef PMDDEBUG
1510 struct pm_component *cp = PM_CP(dip, comp);
1511 #endif
1512 int bc = PM_ISBC(dip);
1513 int pm_all_components_off(dev_info_t *);
1514 int clearvolpmd = 0;
1515 char pathbuf[MAXNAMELEN];
1516 #ifdef PMDDEBUG
1517 char *ppmname, *ppmaddr;
1518 #endif
1519 /*
1520 * If this is comp 0 of a backwards compat device and we are
1521 * going to take the power away, we need to detach it with
1522 * DDI_PM_SUSPEND command.
1523 */
1524 if (bc && comp == 0 && POWERING_OFF(old_level, level)) {
1525 if (devi_detach(dip, DDI_PM_SUSPEND) != DDI_SUCCESS) {
1526 /* We could not suspend before turning cmpt zero off */
1527 PMD(PMD_ERROR, ("%s: could not suspend %s@%s(%s#%d)\n",
1528 pmf, PM_DEVICE(dip)))
1529 return (DDI_FAILURE);
1530 } else {
1531 DEVI(dip)->devi_pm_flags |= PMC_SUSPENDED;
1532 suspended++;
1533 }
1534 }
1535 power_req.request_type = PMR_PPM_SET_POWER;
1536 power_req.req.ppm_set_power_req.who = dip;
1537 power_req.req.ppm_set_power_req.cmpt = comp;
1538 power_req.req.ppm_set_power_req.old_level = old_level;
1539 power_req.req.ppm_set_power_req.new_level = level;
1540 power_req.req.ppm_set_power_req.canblock = canblock;
1541 power_req.req.ppm_set_power_req.cookie = NULL;
1542 #ifdef PMDDEBUG
1543 if (pm_ppm_claimed(dip)) {
1544 ppmname = PM_NAME(PPM(dip));
1545 ppmaddr = PM_ADDR(PPM(dip));
1546
1547 } else {
1548 ppmname = "noppm";
1549 ppmaddr = "0";
1550 }
1551 PMD(PMD_PPM, ("%s: %s@%s(%s#%d):%s[%d] %s (%d) -> %s (%d) via %s@%s\n",
1552 pmf, PM_DEVICE(dip), cp->pmc_comp.pmc_name, comp,
1553 power_val_to_string(cp, old_level), old_level,
1554 power_val_to_string(cp, level), level, ppmname, ppmaddr))
1555 #endif
1556 /*
1557 * If non-bc noinvolpm device is turning first comp on, or noinvolpm
1558 * bc device comp 0 is powering on, then we count it as a power cycle
1559 * against its voluntary count.
1560 */
1561 if (DEVI(dip)->devi_pm_volpmd &&
1562 (!bc && pm_all_components_off(dip) && level != 0) ||
1563 (bc && comp == 0 && POWERING_ON(old_level, level)))
1564 clearvolpmd = 1;
1565 if ((power_op_ret = pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER,
1566 &power_req, &result)) == DDI_SUCCESS) {
1567 /*
1568 * Now do involuntary pm accounting; If we've just cycled power
1569 * on a voluntarily pm'd node, and by inference on its entire
1570 * subtree, we need to set the subtree (including those nodes
1571 * already detached) volpmd counts to 0, and subtract out the
1572 * value of the current node's volpmd count from the ancestors
1573 */
1574 if (clearvolpmd) {
1575 int volpmd = DEVI(dip)->devi_pm_volpmd;
1576 pm_clear_volpm_dip(dip);
1577 pm_clear_volpm_list(dip);
1578 if (volpmd) {
1579 (void) ddi_pathname(dip, pathbuf);
1580 (void) pm_noinvol_update(PM_BP_NOINVOL_POWER,
1581 volpmd, 0, pathbuf, dip);
1582 }
1583 }
1584 } else {
1585 PMD(PMD_FAIL, ("%s: can't set comp %d (%s) of %s@%s(%s#%d) "
1586 "to level %d (%s)\n", pmf, comp, cp->pmc_comp.pmc_name,
1587 PM_DEVICE(dip), level, power_val_to_string(cp, level)))
1588 }
1589 /*
1590 * If some other devices were also powered up (e.g. other cpus in
1591 * the same domain) return a pointer to that list
1592 */
1593 if (devlist) {
1594 *devlist = (pm_ppm_devlist_t *)
1595 power_req.req.ppm_set_power_req.cookie;
1596 }
1597 /*
1598 * We will have to resume the device if the device is backwards compat
1599 * device and either of the following is true:
1600 * -This is comp 0 and we have successfully powered it up
1601 * -This is comp 0 and we have failed to power it down. Resume is
1602 * needed because we have suspended it above
1603 */
1604
1605 if (bc && comp == 0) {
1606 ASSERT(PM_ISDIRECT(dip) || DEVI_IS_DETACHING(dip));
1607 if (power_op_ret == DDI_SUCCESS) {
1608 if (POWERING_ON(old_level, level)) {
1609 /*
1610 * It must be either suspended or resumed
1611 * via pm_power_has_changed path
1612 */
1613 ASSERT((DEVI(dip)->devi_pm_flags &
1614 PMC_SUSPENDED) ||
1615 (PM_CP(dip, comp)->pmc_flags &
1616 PM_PHC_WHILE_SET_POWER));
1617
1618 resume_needed = suspended;
1619 }
1620 } else {
1621 if (POWERING_OFF(old_level, level)) {
1622 /*
1623 * It must be either suspended or resumed
1624 * via pm_power_has_changed path
1625 */
1626 ASSERT((DEVI(dip)->devi_pm_flags &
1627 PMC_SUSPENDED) ||
1628 (PM_CP(dip, comp)->pmc_flags &
1629 PM_PHC_WHILE_SET_POWER));
1630
1631 resume_needed = suspended;
1632 }
1633 }
1634 }
1635 if (resume_needed) {
1636 ASSERT(DEVI(dip)->devi_pm_flags & PMC_SUSPENDED);
1637 /* ppm is not interested in DDI_PM_RESUME */
1638 if ((power_op_ret = devi_attach(dip, DDI_PM_RESUME)) ==
1639 DDI_SUCCESS) {
1640 DEVI(dip)->devi_pm_flags &= ~PMC_SUSPENDED;
1641 } else
1642 cmn_err(CE_WARN, "!pm: Can't resume %s@%s(%s#%d)",
1643 PM_DEVICE(dip));
1644 }
1645 return (power_op_ret);
1646 }
1647
1648 /*
1649 * Return true if we are the owner or a borrower of the devi lock. See
1650 * pm_lock_power_single() about borrowing the lock.
1651 */
1652 static int
pm_devi_lock_held(dev_info_t * dip)1653 pm_devi_lock_held(dev_info_t *dip)
1654 {
1655 lock_loan_t *cur;
1656
1657 if (DEVI_BUSY_OWNED(dip))
1658 return (1);
1659
1660 /* return false if no locks borrowed */
1661 if (lock_loan_head.pmlk_next == NULL)
1662 return (0);
1663
1664 mutex_enter(&pm_loan_lock);
1665 /* see if our thread is registered as a lock borrower. */
1666 for (cur = lock_loan_head.pmlk_next; cur; cur = cur->pmlk_next)
1667 if (cur->pmlk_borrower == curthread)
1668 break;
1669 mutex_exit(&pm_loan_lock);
1670
1671 return (cur != NULL && cur->pmlk_lender == DEVI(dip)->devi_busy_thread);
1672 }
1673
1674 /*
1675 * pm_set_power: adjusts power level of device. Assumes device is power
1676 * manageable & component exists.
1677 *
1678 * Cases which require us to bring up devices we keep up ("wekeepups") for
1679 * backwards compatible devices:
1680 * component 0 is off and we're bringing it up from 0
1681 * bring up wekeepup first
1682 * and recursively when component 0 is off and we bring some other
1683 * component up from 0
1684 * For devices which are not backward compatible, our dependency notion is much
1685 * simpler. Unless all components are off, then wekeeps must be on.
1686 * We don't treat component 0 differently.
1687 * Canblock tells how to deal with a direct pm'd device.
1688 * Scan arg tells us if we were called from scan, in which case we don't need
1689 * to go back to the root node and walk down to change power.
1690 */
1691 int
pm_set_power(dev_info_t * dip,int comp,int level,int direction,pm_canblock_t canblock,int scan,int * retp)1692 pm_set_power(dev_info_t *dip, int comp, int level, int direction,
1693 pm_canblock_t canblock, int scan, int *retp)
1694 {
1695 PMD_FUNC(pmf, "set_power")
1696 char *pathbuf;
1697 pm_bp_child_pwrchg_t bpc;
1698 pm_sp_misc_t pspm;
1699 int ret = DDI_SUCCESS;
1700 int unused = DDI_SUCCESS;
1701 dev_info_t *pdip = ddi_get_parent(dip);
1702
1703 #ifdef DEBUG
1704 int diverted = 0;
1705
1706 /*
1707 * This prevents operations on the console from calling prom_printf and
1708 * either deadlocking or bringing up the console because of debug
1709 * output
1710 */
1711 if (dip == cfb_dip) {
1712 diverted++;
1713 mutex_enter(&pm_debug_lock);
1714 pm_divertdebug++;
1715 mutex_exit(&pm_debug_lock);
1716 }
1717 #endif
1718 ASSERT(direction == PM_LEVEL_UPONLY || direction == PM_LEVEL_DOWNONLY ||
1719 direction == PM_LEVEL_EXACT);
1720 PMD(PMD_SET, ("%s: %s@%s(%s#%d), comp=%d, dir=%s, new=%d\n",
1721 pmf, PM_DEVICE(dip), comp, pm_decode_direction(direction), level))
1722 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
1723 (void) ddi_pathname(dip, pathbuf);
1724 bpc.bpc_dip = dip;
1725 bpc.bpc_path = pathbuf;
1726 bpc.bpc_comp = comp;
1727 bpc.bpc_olevel = PM_CURPOWER(dip, comp);
1728 bpc.bpc_nlevel = level;
1729 pspm.pspm_direction = direction;
1730 pspm.pspm_errnop = retp;
1731 pspm.pspm_canblock = canblock;
1732 pspm.pspm_scan = scan;
1733 bpc.bpc_private = &pspm;
1734
1735 /*
1736 * If a config operation is being done (we've locked the parent) or
1737 * we already hold the power lock (we've locked the node)
1738 * then we can operate directly on the node because we have already
1739 * brought up all the ancestors, otherwise, we have to go back to the
1740 * top of the tree.
1741 */
1742 if (pm_devi_lock_held(pdip) || pm_devi_lock_held(dip))
1743 ret = pm_busop_set_power(dip, NULL, BUS_POWER_CHILD_PWRCHG,
1744 (void *)&bpc, (void *)&unused);
1745 else
1746 ret = pm_busop_bus_power(ddi_root_node(), NULL,
1747 BUS_POWER_CHILD_PWRCHG, (void *)&bpc, (void *)&unused);
1748 #ifdef DEBUG
1749 if (ret != DDI_SUCCESS || *retp != DDI_SUCCESS) {
1750 PMD(PMD_ERROR, ("%s: %s@%s(%s#%d) can't change power, ret=%d, "
1751 "errno=%d\n", pmf, PM_DEVICE(dip), ret, *retp))
1752 }
1753 if (diverted) {
1754 mutex_enter(&pm_debug_lock);
1755 pm_divertdebug--;
1756 mutex_exit(&pm_debug_lock);
1757 }
1758 #endif
1759 kmem_free(pathbuf, MAXPATHLEN);
1760 return (ret);
1761 }
1762
1763 /*
1764 * If holddip is set, then if a dip is found we return with the node held.
1765 *
1766 * This code uses the same locking scheme as e_ddi_hold_devi_by_path
1767 * (resolve_pathname), but it does not drive attach.
1768 */
1769 dev_info_t *
pm_name_to_dip(char * pathname,int holddip)1770 pm_name_to_dip(char *pathname, int holddip)
1771 {
1772 struct pathname pn;
1773 char *component;
1774 dev_info_t *parent, *child;
1775 int circ;
1776
1777 if ((pathname == NULL) || (*pathname != '/'))
1778 return (NULL);
1779
1780 /* setup pathname and allocate component */
1781 if (pn_get(pathname, UIO_SYSSPACE, &pn))
1782 return (NULL);
1783 component = kmem_alloc(MAXNAMELEN, KM_SLEEP);
1784
1785 /* start at top, process '/' component */
1786 parent = child = ddi_root_node();
1787 ndi_hold_devi(parent);
1788 pn_skipslash(&pn);
1789 ASSERT(i_ddi_devi_attached(parent));
1790
1791 /* process components of pathname */
1792 while (pn_pathleft(&pn)) {
1793 (void) pn_getcomponent(&pn, component);
1794
1795 /* enter parent and search for component child */
1796 ndi_devi_enter(parent, &circ);
1797 child = ndi_devi_findchild(parent, component);
1798 if ((child == NULL) || !i_ddi_devi_attached(child)) {
1799 child = NULL;
1800 ndi_devi_exit(parent, circ);
1801 ndi_rele_devi(parent);
1802 goto out;
1803 }
1804
1805 /* attached child found, hold child and release parent */
1806 ndi_hold_devi(child);
1807 ndi_devi_exit(parent, circ);
1808 ndi_rele_devi(parent);
1809
1810 /* child becomes parent, and process next component */
1811 parent = child;
1812 pn_skipslash(&pn);
1813
1814 /* loop with active ndi_devi_hold of child->parent */
1815 }
1816
1817 out:
1818 pn_free(&pn);
1819 kmem_free(component, MAXNAMELEN);
1820
1821 /* if we are not asked to return with hold, drop current hold */
1822 if (child && !holddip)
1823 ndi_rele_devi(child);
1824 return (child);
1825 }
1826
1827 /*
1828 * Search for a dependency and mark it unsatisfied
1829 */
1830 static void
pm_unsatisfy(char * keeper,char * kept)1831 pm_unsatisfy(char *keeper, char *kept)
1832 {
1833 PMD_FUNC(pmf, "unsatisfy")
1834 pm_pdr_t *dp;
1835
1836 PMD(PMD_KEEPS, ("%s: keeper=%s, kept=%s\n", pmf, keeper, kept))
1837 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
1838 if (!dp->pdr_isprop) {
1839 if (strcmp(dp->pdr_keeper, keeper) == 0 &&
1840 (dp->pdr_kept_count > 0) &&
1841 strcmp(dp->pdr_kept_paths[0], kept) == 0) {
1842 if (dp->pdr_satisfied) {
1843 dp->pdr_satisfied = 0;
1844 pm_unresolved_deps++;
1845 PMD(PMD_KEEPS, ("%s: clear satisfied, "
1846 "pm_unresolved_deps now %d\n", pmf,
1847 pm_unresolved_deps))
1848 }
1849 }
1850 }
1851 }
1852 }
1853
1854 /*
1855 * Device dip is being un power managed, it keeps up count other devices.
1856 * We need to release any hold we have on the kept devices, and also
1857 * mark the dependency no longer satisfied.
1858 */
1859 static void
pm_unkeeps(int count,char * keeper,char ** keptpaths,int pwr)1860 pm_unkeeps(int count, char *keeper, char **keptpaths, int pwr)
1861 {
1862 PMD_FUNC(pmf, "unkeeps")
1863 int i, j;
1864 dev_info_t *kept;
1865 dev_info_t *dip;
1866 struct pm_component *cp;
1867 int keeper_on = 0, circ;
1868
1869 PMD(PMD_KEEPS, ("%s: count=%d, keeper=%s, keptpaths=%p\n", pmf, count,
1870 keeper, (void *)keptpaths))
1871 /*
1872 * Try to grab keeper. Keeper may have gone away by now,
1873 * in this case, used the passed in value pwr
1874 */
1875 dip = pm_name_to_dip(keeper, 1);
1876 for (i = 0; i < count; i++) {
1877 /* Release power hold */
1878 kept = pm_name_to_dip(keptpaths[i], 1);
1879 if (kept) {
1880 PMD(PMD_KEEPS, ("%s: %s@%s(%s#%d)[%d]\n", pmf,
1881 PM_DEVICE(kept), i))
1882 /*
1883 * We need to check if we skipped a bringup here
1884 * because we could have failed the bringup
1885 * (ie DIRECT PM device) and have
1886 * not increment the count.
1887 */
1888 if ((dip != NULL) && (PM_GET_PM_INFO(dip) != NULL)) {
1889 keeper_on = 0;
1890 PM_LOCK_POWER(dip, &circ);
1891 for (j = 0; j < PM_NUMCMPTS(dip); j++) {
1892 cp = &DEVI(dip)->devi_pm_components[j];
1893 if (cur_power(cp)) {
1894 keeper_on++;
1895 break;
1896 }
1897 }
1898 if (keeper_on && (PM_SKBU(kept) == 0)) {
1899 pm_rele_power(kept);
1900 DEVI(kept)->devi_pm_flags
1901 &= ~PMC_SKIP_BRINGUP;
1902 }
1903 PM_UNLOCK_POWER(dip, circ);
1904 } else if (pwr) {
1905 if (PM_SKBU(kept) == 0) {
1906 pm_rele_power(kept);
1907 DEVI(kept)->devi_pm_flags
1908 &= ~PMC_SKIP_BRINGUP;
1909 }
1910 }
1911 ddi_release_devi(kept);
1912 }
1913 /*
1914 * mark this dependency not satisfied
1915 */
1916 pm_unsatisfy(keeper, keptpaths[i]);
1917 }
1918 if (dip)
1919 ddi_release_devi(dip);
1920 }
1921
1922 /*
1923 * Device kept is being un power managed, it is kept up by keeper.
1924 * We need to mark the dependency no longer satisfied.
1925 */
1926 static void
pm_unkepts(char * kept,char * keeper)1927 pm_unkepts(char *kept, char *keeper)
1928 {
1929 PMD_FUNC(pmf, "unkepts")
1930 PMD(PMD_KEEPS, ("%s: kept=%s, keeper=%s\n", pmf, kept, keeper))
1931 ASSERT(keeper != NULL);
1932 /*
1933 * mark this dependency not satisfied
1934 */
1935 pm_unsatisfy(keeper, kept);
1936 }
1937
1938 /*
1939 * Removes dependency information and hold on the kepts, if the path is a
1940 * path of a keeper.
1941 */
1942 static void
pm_free_keeper(char * path,int pwr)1943 pm_free_keeper(char *path, int pwr)
1944 {
1945 pm_pdr_t *dp;
1946 int i;
1947 size_t length;
1948
1949 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
1950 if (strcmp(dp->pdr_keeper, path) != 0)
1951 continue;
1952 /*
1953 * Remove all our kept holds and the dependency records,
1954 * then free up the kept lists.
1955 */
1956 pm_unkeeps(dp->pdr_kept_count, path, dp->pdr_kept_paths, pwr);
1957 if (dp->pdr_kept_count) {
1958 for (i = 0; i < dp->pdr_kept_count; i++) {
1959 length = strlen(dp->pdr_kept_paths[i]);
1960 kmem_free(dp->pdr_kept_paths[i], length + 1);
1961 }
1962 kmem_free(dp->pdr_kept_paths,
1963 dp->pdr_kept_count * sizeof (char **));
1964 dp->pdr_kept_paths = NULL;
1965 dp->pdr_kept_count = 0;
1966 }
1967 }
1968 }
1969
1970 /*
1971 * Removes the device represented by path from the list of kepts, if the
1972 * path is a path of a kept
1973 */
1974 static void
pm_free_kept(char * path)1975 pm_free_kept(char *path)
1976 {
1977 pm_pdr_t *dp;
1978 int i;
1979 int j, count;
1980 size_t length;
1981 char **paths;
1982
1983 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
1984 if (dp->pdr_kept_count == 0)
1985 continue;
1986 count = dp->pdr_kept_count;
1987 /* Remove this device from the kept path lists */
1988 for (i = 0; i < count; i++) {
1989 if (strcmp(dp->pdr_kept_paths[i], path) == 0) {
1990 pm_unkepts(path, dp->pdr_keeper);
1991 length = strlen(dp->pdr_kept_paths[i]) + 1;
1992 kmem_free(dp->pdr_kept_paths[i], length);
1993 dp->pdr_kept_paths[i] = NULL;
1994 dp->pdr_kept_count--;
1995 }
1996 }
1997 /* Compact the kept paths array */
1998 if (dp->pdr_kept_count) {
1999 length = dp->pdr_kept_count * sizeof (char **);
2000 paths = kmem_zalloc(length, KM_SLEEP);
2001 j = 0;
2002 for (i = 0; i < count; i++) {
2003 if (dp->pdr_kept_paths[i] != NULL) {
2004 paths[j] = dp->pdr_kept_paths[i];
2005 j++;
2006 }
2007 }
2008 ASSERT(j == dp->pdr_kept_count);
2009 }
2010 /* Now free the old array and point to the new one */
2011 kmem_free(dp->pdr_kept_paths, count * sizeof (char **));
2012 if (dp->pdr_kept_count)
2013 dp->pdr_kept_paths = paths;
2014 else
2015 dp->pdr_kept_paths = NULL;
2016 }
2017 }
2018
2019 /*
2020 * Free the dependency information for a device.
2021 */
2022 void
pm_free_keeps(char * path,int pwr)2023 pm_free_keeps(char *path, int pwr)
2024 {
2025 PMD_FUNC(pmf, "free_keeps")
2026
2027 #ifdef DEBUG
2028 int doprdeps = 0;
2029 void prdeps(char *);
2030
2031 PMD(PMD_KEEPS, ("%s: %s\n", pmf, path))
2032 if (pm_debug & PMD_KEEPS) {
2033 doprdeps = 1;
2034 prdeps("pm_free_keeps before");
2035 }
2036 #endif
2037 /*
2038 * First assume we are a keeper and remove all our kepts.
2039 */
2040 pm_free_keeper(path, pwr);
2041 /*
2042 * Now assume we a kept device, and remove all our records.
2043 */
2044 pm_free_kept(path);
2045 #ifdef DEBUG
2046 if (doprdeps) {
2047 prdeps("pm_free_keeps after");
2048 }
2049 #endif
2050 }
2051
2052 static int
pm_is_kept(char * path)2053 pm_is_kept(char *path)
2054 {
2055 pm_pdr_t *dp;
2056 int i;
2057
2058 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
2059 if (dp->pdr_kept_count == 0)
2060 continue;
2061 for (i = 0; i < dp->pdr_kept_count; i++) {
2062 if (strcmp(dp->pdr_kept_paths[i], path) == 0)
2063 return (1);
2064 }
2065 }
2066 return (0);
2067 }
2068
2069 static void
e_pm_hold_rele_power(dev_info_t * dip,int cnt)2070 e_pm_hold_rele_power(dev_info_t *dip, int cnt)
2071 {
2072 PMD_FUNC(pmf, "hold_rele_power")
2073 int circ;
2074
2075 if ((dip == NULL) ||
2076 (PM_GET_PM_INFO(dip) == NULL) || PM_ISBC(dip))
2077 return;
2078
2079 PM_LOCK_POWER(dip, &circ);
2080 ASSERT(cnt >= 0 && PM_KUC(dip) >= 0 || cnt < 0 && PM_KUC(dip) > 0);
2081 PMD(PMD_KIDSUP, ("%s: kidsupcnt for %s@%s(%s#%d) %d->%d\n", pmf,
2082 PM_DEVICE(dip), PM_KUC(dip), (PM_KUC(dip) + cnt)))
2083
2084 PM_KUC(dip) += cnt;
2085
2086 ASSERT(PM_KUC(dip) >= 0);
2087 PM_UNLOCK_POWER(dip, circ);
2088
2089 if (cnt < 0 && PM_KUC(dip) == 0)
2090 pm_rescan(dip);
2091 }
2092
2093 #define MAX_PPM_HANDLERS 4
2094
2095 kmutex_t ppm_lock; /* in case we ever do multi-threaded startup */
2096
2097 struct ppm_callbacks {
2098 int (*ppmc_func)(dev_info_t *);
2099 dev_info_t *ppmc_dip;
2100 } ppm_callbacks[MAX_PPM_HANDLERS + 1];
2101
2102
2103 /*
2104 * This routine calls into all the registered ppms to notify them
2105 * that either all components of power-managed devices are at their
2106 * lowest levels or no longer all are at their lowest levels.
2107 */
2108 static void
pm_ppm_notify_all_lowest(dev_info_t * dip,int mode)2109 pm_ppm_notify_all_lowest(dev_info_t *dip, int mode)
2110 {
2111 struct ppm_callbacks *ppmcp;
2112 power_req_t power_req;
2113 int result = 0;
2114
2115 power_req.request_type = PMR_PPM_ALL_LOWEST;
2116 power_req.req.ppm_all_lowest_req.mode = mode;
2117 mutex_enter(&ppm_lock);
2118 for (ppmcp = ppm_callbacks; ppmcp->ppmc_func; ppmcp++)
2119 (void) pm_ctlops((dev_info_t *)ppmcp->ppmc_dip, dip,
2120 DDI_CTLOPS_POWER, &power_req, &result);
2121 mutex_exit(&ppm_lock);
2122 if (mode == PM_ALL_LOWEST) {
2123 if (autoS3_enabled) {
2124 PMD(PMD_SX, ("pm_ppm_notify_all_lowest triggering "
2125 "autos3\n"))
2126 mutex_enter(&srn_clone_lock);
2127 if (srn_signal) {
2128 srn_inuse++;
2129 PMD(PMD_SX, ("(*srn_signal)(AUTOSX, 3)\n"))
2130 (*srn_signal)(SRN_TYPE_AUTOSX, 3);
2131 srn_inuse--;
2132 } else {
2133 PMD(PMD_SX, ("srn_signal NULL\n"))
2134 }
2135 mutex_exit(&srn_clone_lock);
2136 } else {
2137 PMD(PMD_SX, ("pm_ppm_notify_all_lowest autos3 "
2138 "disabled\n"));
2139 }
2140 }
2141 }
2142
2143 static void
pm_set_pm_info(dev_info_t * dip,void * value)2144 pm_set_pm_info(dev_info_t *dip, void *value)
2145 {
2146 DEVI(dip)->devi_pm_info = value;
2147 }
2148
2149 pm_rsvp_t *pm_blocked_list;
2150
2151 /*
2152 * Look up an entry in the blocked list by dip and component
2153 */
2154 static pm_rsvp_t *
pm_rsvp_lookup(dev_info_t * dip,int comp)2155 pm_rsvp_lookup(dev_info_t *dip, int comp)
2156 {
2157 pm_rsvp_t *p;
2158 ASSERT(MUTEX_HELD(&pm_rsvp_lock));
2159 for (p = pm_blocked_list; p; p = p->pr_next)
2160 if (p->pr_dip == dip && p->pr_comp == comp) {
2161 return (p);
2162 }
2163 return (NULL);
2164 }
2165
2166 /*
2167 * Called when a device which is direct power managed (or the parent or
2168 * dependent of such a device) changes power, or when a pm clone is closed
2169 * that was direct power managing a device. This call results in pm_blocked()
2170 * (below) returning.
2171 */
2172 void
pm_proceed(dev_info_t * dip,int cmd,int comp,int newlevel)2173 pm_proceed(dev_info_t *dip, int cmd, int comp, int newlevel)
2174 {
2175 PMD_FUNC(pmf, "proceed")
2176 pm_rsvp_t *found = NULL;
2177 pm_rsvp_t *p;
2178
2179 mutex_enter(&pm_rsvp_lock);
2180 switch (cmd) {
2181 /*
2182 * we're giving up control, let any pending op continue
2183 */
2184 case PMP_RELEASE:
2185 for (p = pm_blocked_list; p; p = p->pr_next) {
2186 if (dip == p->pr_dip) {
2187 p->pr_retval = PMP_RELEASE;
2188 PMD(PMD_DPM, ("%s: RELEASE %s@%s(%s#%d)\n",
2189 pmf, PM_DEVICE(dip)))
2190 cv_signal(&p->pr_cv);
2191 }
2192 }
2193 break;
2194
2195 /*
2196 * process has done PM_SET_CURRENT_POWER; let a matching request
2197 * succeed and a non-matching request for the same device fail
2198 */
2199 case PMP_SETPOWER:
2200 found = pm_rsvp_lookup(dip, comp);
2201 if (!found) /* if driver not waiting */
2202 break;
2203 /*
2204 * This cannot be pm_lower_power, since that can only happen
2205 * during detach or probe
2206 */
2207 if (found->pr_newlevel <= newlevel) {
2208 found->pr_retval = PMP_SUCCEED;
2209 PMD(PMD_DPM, ("%s: SUCCEED %s@%s(%s#%d)\n", pmf,
2210 PM_DEVICE(dip)))
2211 } else {
2212 found->pr_retval = PMP_FAIL;
2213 PMD(PMD_DPM, ("%s: FAIL %s@%s(%s#%d)\n", pmf,
2214 PM_DEVICE(dip)))
2215 }
2216 cv_signal(&found->pr_cv);
2217 break;
2218
2219 default:
2220 panic("pm_proceed unknown cmd %d", cmd);
2221 }
2222 mutex_exit(&pm_rsvp_lock);
2223 }
2224
2225 /*
2226 * This routine dispatches new work to the dependency thread. Caller must
2227 * be prepared to block for memory if necessary.
2228 */
2229 void
pm_dispatch_to_dep_thread(int cmd,char * keeper,char * kept,int wait,int * res,int cached_pwr)2230 pm_dispatch_to_dep_thread(int cmd, char *keeper, char *kept, int wait,
2231 int *res, int cached_pwr)
2232 {
2233 pm_dep_wk_t *new_work;
2234
2235 new_work = kmem_zalloc(sizeof (pm_dep_wk_t), KM_SLEEP);
2236 new_work->pdw_type = cmd;
2237 new_work->pdw_wait = wait;
2238 new_work->pdw_done = 0;
2239 new_work->pdw_ret = 0;
2240 new_work->pdw_pwr = cached_pwr;
2241 cv_init(&new_work->pdw_cv, NULL, CV_DEFAULT, NULL);
2242 if (keeper != NULL) {
2243 new_work->pdw_keeper = kmem_zalloc(strlen(keeper) + 1,
2244 KM_SLEEP);
2245 (void) strcpy(new_work->pdw_keeper, keeper);
2246 }
2247 if (kept != NULL) {
2248 new_work->pdw_kept = kmem_zalloc(strlen(kept) + 1, KM_SLEEP);
2249 (void) strcpy(new_work->pdw_kept, kept);
2250 }
2251 mutex_enter(&pm_dep_thread_lock);
2252 if (pm_dep_thread_workq == NULL) {
2253 pm_dep_thread_workq = new_work;
2254 pm_dep_thread_tail = new_work;
2255 new_work->pdw_next = NULL;
2256 } else {
2257 pm_dep_thread_tail->pdw_next = new_work;
2258 pm_dep_thread_tail = new_work;
2259 new_work->pdw_next = NULL;
2260 }
2261 cv_signal(&pm_dep_thread_cv);
2262 /* If caller asked for it, wait till it is done. */
2263 if (wait) {
2264 while (!new_work->pdw_done)
2265 cv_wait(&new_work->pdw_cv, &pm_dep_thread_lock);
2266 /*
2267 * Pass return status, if any, back.
2268 */
2269 if (res != NULL)
2270 *res = new_work->pdw_ret;
2271 /*
2272 * If we asked to wait, it is our job to free the request
2273 * structure.
2274 */
2275 if (new_work->pdw_keeper)
2276 kmem_free(new_work->pdw_keeper,
2277 strlen(new_work->pdw_keeper) + 1);
2278 if (new_work->pdw_kept)
2279 kmem_free(new_work->pdw_kept,
2280 strlen(new_work->pdw_kept) + 1);
2281 kmem_free(new_work, sizeof (pm_dep_wk_t));
2282 }
2283 mutex_exit(&pm_dep_thread_lock);
2284 }
2285
2286 /*
2287 * Release the pm resource for this device.
2288 */
2289 void
pm_rem_info(dev_info_t * dip)2290 pm_rem_info(dev_info_t *dip)
2291 {
2292 PMD_FUNC(pmf, "rem_info")
2293 int i, count = 0;
2294 pm_info_t *info = PM_GET_PM_INFO(dip);
2295 dev_info_t *pdip = ddi_get_parent(dip);
2296 char *pathbuf;
2297 int work_type = PM_DEP_WK_DETACH;
2298
2299 ASSERT(info);
2300
2301 ASSERT(!PM_IAM_LOCKING_DIP(dip));
2302 if (PM_ISDIRECT(dip)) {
2303 info->pmi_dev_pm_state &= ~PM_DIRECT;
2304 ASSERT(info->pmi_clone);
2305 info->pmi_clone = 0;
2306 pm_proceed(dip, PMP_RELEASE, -1, -1);
2307 }
2308 ASSERT(!PM_GET_PM_SCAN(dip));
2309
2310 /*
2311 * Now adjust parent's kidsupcnt. BC nodes we check only comp 0,
2312 * Others we check all components. BC node that has already
2313 * called pm_destroy_components() has zero component count.
2314 * Parents that get notification are not adjusted because their
2315 * kidsupcnt is always 0 (or 1 during configuration).
2316 */
2317 PMD(PMD_KEEPS, ("%s: %s@%s(%s#%d) has %d components\n", pmf,
2318 PM_DEVICE(dip), PM_NUMCMPTS(dip)))
2319
2320 /* node is detached, so we can examine power without locking */
2321 if (PM_ISBC(dip)) {
2322 count = (PM_CURPOWER(dip, 0) != 0);
2323 } else {
2324 for (i = 0; i < PM_NUMCMPTS(dip); i++)
2325 count += (PM_CURPOWER(dip, i) != 0);
2326 }
2327
2328 if (PM_NUMCMPTS(dip) && pdip && !PM_WANTS_NOTIFICATION(pdip))
2329 e_pm_hold_rele_power(pdip, -count);
2330
2331 /* Schedule a request to clean up dependency records */
2332 pathbuf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
2333 (void) ddi_pathname(dip, pathbuf);
2334 pm_dispatch_to_dep_thread(work_type, pathbuf, pathbuf,
2335 PM_DEP_NOWAIT, NULL, (count > 0));
2336 kmem_free(pathbuf, MAXPATHLEN);
2337
2338 /*
2339 * Adjust the pm_comps_notlowest count since this device is
2340 * not being power-managed anymore.
2341 */
2342 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
2343 pm_component_t *cp = PM_CP(dip, i);
2344 if (cp->pmc_cur_pwr != 0)
2345 PM_DECR_NOTLOWEST(dip)
2346 }
2347 /*
2348 * Once we clear the info pointer, it looks like it is not power
2349 * managed to everybody else.
2350 */
2351 pm_set_pm_info(dip, NULL);
2352 kmem_free(info, sizeof (pm_info_t));
2353 }
2354
2355 int
pm_get_norm_pwrs(dev_info_t * dip,int ** valuep,size_t * length)2356 pm_get_norm_pwrs(dev_info_t *dip, int **valuep, size_t *length)
2357 {
2358 int components = PM_NUMCMPTS(dip);
2359 int *bufp;
2360 size_t size;
2361 int i;
2362
2363 if (components <= 0) {
2364 cmn_err(CE_NOTE, "!pm: %s@%s(%s#%d) has no components, "
2365 "can't get normal power values\n", PM_DEVICE(dip));
2366 return (DDI_FAILURE);
2367 } else {
2368 size = components * sizeof (int);
2369 bufp = kmem_alloc(size, KM_SLEEP);
2370 for (i = 0; i < components; i++) {
2371 bufp[i] = pm_get_normal_power(dip, i);
2372 }
2373 }
2374 *length = size;
2375 *valuep = bufp;
2376 return (DDI_SUCCESS);
2377 }
2378
2379 static int
pm_reset_timestamps(dev_info_t * dip,void * arg)2380 pm_reset_timestamps(dev_info_t *dip, void *arg)
2381 {
2382 _NOTE(ARGUNUSED(arg))
2383
2384 int components;
2385 int i;
2386
2387 if (!PM_GET_PM_INFO(dip))
2388 return (DDI_WALK_CONTINUE);
2389 components = PM_NUMCMPTS(dip);
2390 ASSERT(components > 0);
2391 PM_LOCK_BUSY(dip);
2392 for (i = 0; i < components; i++) {
2393 struct pm_component *cp;
2394 /*
2395 * If the component was not marked as busy,
2396 * reset its timestamp to now.
2397 */
2398 cp = PM_CP(dip, i);
2399 if (cp->pmc_timestamp)
2400 cp->pmc_timestamp = gethrestime_sec();
2401 }
2402 PM_UNLOCK_BUSY(dip);
2403 return (DDI_WALK_CONTINUE);
2404 }
2405
2406 /*
2407 * Convert a power level to an index into the levels array (or
2408 * just PM_LEVEL_UNKNOWN in that special case).
2409 */
2410 static int
pm_level_to_index(dev_info_t * dip,pm_component_t * cp,int level)2411 pm_level_to_index(dev_info_t *dip, pm_component_t *cp, int level)
2412 {
2413 PMD_FUNC(pmf, "level_to_index")
2414 int i;
2415 int limit = cp->pmc_comp.pmc_numlevels;
2416 int *ip = cp->pmc_comp.pmc_lvals;
2417
2418 if (level == PM_LEVEL_UNKNOWN)
2419 return (level);
2420
2421 for (i = 0; i < limit; i++) {
2422 if (level == *ip++) {
2423 PMD(PMD_LEVEL, ("%s: %s@%s(%s#%d)[%d] to %x\n",
2424 pmf, PM_DEVICE(dip),
2425 (int)(cp - DEVI(dip)->devi_pm_components), level))
2426 return (i);
2427 }
2428 }
2429 panic("pm_level_to_index: level %d not found for device "
2430 "%s@%s(%s#%d)", level, PM_DEVICE(dip));
2431 /*NOTREACHED*/
2432 }
2433
2434 /*
2435 * Internal function to set current power level
2436 */
2437 static void
e_pm_set_cur_pwr(dev_info_t * dip,pm_component_t * cp,int level)2438 e_pm_set_cur_pwr(dev_info_t *dip, pm_component_t *cp, int level)
2439 {
2440 PMD_FUNC(pmf, "set_cur_pwr")
2441 int curpwr = (cp->pmc_flags & PM_PHC_WHILE_SET_POWER ?
2442 cp->pmc_phc_pwr : cp->pmc_cur_pwr);
2443
2444 /*
2445 * Nothing to adjust if current & new levels are the same.
2446 */
2447 if (curpwr != PM_LEVEL_UNKNOWN &&
2448 level == cp->pmc_comp.pmc_lvals[curpwr])
2449 return;
2450
2451 /*
2452 * Keep the count for comps doing transition to/from lowest
2453 * level.
2454 */
2455 if (curpwr == 0) {
2456 PM_INCR_NOTLOWEST(dip);
2457 } else if (level == cp->pmc_comp.pmc_lvals[0]) {
2458 PM_DECR_NOTLOWEST(dip);
2459 }
2460 cp->pmc_phc_pwr = PM_LEVEL_UNKNOWN;
2461 cp->pmc_cur_pwr = pm_level_to_index(dip, cp, level);
2462 }
2463
2464 static int pm_phc_impl(dev_info_t *, int, int, int);
2465
2466 /*
2467 * This is the default method of setting the power of a device if no ppm
2468 * driver has claimed it.
2469 */
2470 int
pm_power(dev_info_t * dip,int comp,int level)2471 pm_power(dev_info_t *dip, int comp, int level)
2472 {
2473 PMD_FUNC(pmf, "power")
2474 struct dev_ops *ops;
2475 int (*fn)(dev_info_t *, int, int);
2476 struct pm_component *cp = PM_CP(dip, comp);
2477 int retval;
2478 pm_info_t *info = PM_GET_PM_INFO(dip);
2479
2480 PMD(PMD_KIDSUP, ("%s: %s@%s(%s#%d), comp=%d, level=%d\n", pmf,
2481 PM_DEVICE(dip), comp, level))
2482 if (!(ops = ddi_get_driver(dip))) {
2483 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) has no ops\n", pmf,
2484 PM_DEVICE(dip)))
2485 return (DDI_FAILURE);
2486 }
2487 if ((ops->devo_rev < 2) || !(fn = ops->devo_power)) {
2488 PMD(PMD_FAIL, ("%s: %s%s\n", pmf,
2489 (ops->devo_rev < 2 ? " wrong devo_rev" : ""),
2490 (!fn ? " devo_power NULL" : "")))
2491 return (DDI_FAILURE);
2492 }
2493 cp->pmc_flags |= PM_POWER_OP;
2494 retval = (*fn)(dip, comp, level);
2495 cp->pmc_flags &= ~PM_POWER_OP;
2496 if (retval == DDI_SUCCESS) {
2497 e_pm_set_cur_pwr(dip, PM_CP(dip, comp), level);
2498 return (DDI_SUCCESS);
2499 }
2500
2501 /*
2502 * If pm_power_has_changed() detected a deadlock with pm_power() it
2503 * updated only the power level of the component. If our attempt to
2504 * set the device new to a power level above has failed we sync the
2505 * total power state via phc code now.
2506 */
2507 if (cp->pmc_flags & PM_PHC_WHILE_SET_POWER) {
2508 int phc_lvl =
2509 cp->pmc_comp.pmc_lvals[cp->pmc_cur_pwr];
2510
2511 ASSERT(info);
2512 (void) pm_phc_impl(dip, comp, phc_lvl, 0);
2513 PMD(PMD_PHC, ("%s: phc %s@%s(%s#%d) comp=%d level=%d\n",
2514 pmf, PM_DEVICE(dip), comp, phc_lvl))
2515 }
2516
2517 PMD(PMD_FAIL, ("%s: can't set comp=%d (%s) of %s@%s(%s#%d) to "
2518 "level=%d (%s)\n", pmf, comp, cp->pmc_comp.pmc_name, PM_DEVICE(dip),
2519 level, power_val_to_string(cp, level)));
2520 return (DDI_FAILURE);
2521 }
2522
2523 int
pm_unmanage(dev_info_t * dip)2524 pm_unmanage(dev_info_t *dip)
2525 {
2526 PMD_FUNC(pmf, "unmanage")
2527 power_req_t power_req;
2528 int result, retval = 0;
2529
2530 ASSERT(!PM_IAM_LOCKING_DIP(dip));
2531 PMD(PMD_REMDEV | PMD_KIDSUP, ("%s: %s@%s(%s#%d)\n", pmf,
2532 PM_DEVICE(dip)))
2533 power_req.request_type = PMR_PPM_UNMANAGE;
2534 power_req.req.ppm_config_req.who = dip;
2535 if (pm_ppm_claimed(dip))
2536 retval = pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER,
2537 &power_req, &result);
2538 #ifdef DEBUG
2539 else
2540 retval = pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER,
2541 &power_req, &result);
2542 #endif
2543 ASSERT(retval == DDI_SUCCESS);
2544 pm_rem_info(dip);
2545 return (retval);
2546 }
2547
2548 int
pm_raise_power(dev_info_t * dip,int comp,int level)2549 pm_raise_power(dev_info_t *dip, int comp, int level)
2550 {
2551 if (level < 0)
2552 return (DDI_FAILURE);
2553 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, comp, NULL) ||
2554 !e_pm_valid_power(dip, comp, level))
2555 return (DDI_FAILURE);
2556
2557 return (dev_is_needed(dip, comp, level, PM_LEVEL_UPONLY));
2558 }
2559
2560 int
pm_lower_power(dev_info_t * dip,int comp,int level)2561 pm_lower_power(dev_info_t *dip, int comp, int level)
2562 {
2563 PMD_FUNC(pmf, "pm_lower_power")
2564
2565 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, comp, NULL) ||
2566 !e_pm_valid_power(dip, comp, level)) {
2567 PMD(PMD_FAIL, ("%s: validation checks failed for %s@%s(%s#%d) "
2568 "comp=%d level=%d\n", pmf, PM_DEVICE(dip), comp, level))
2569 return (DDI_FAILURE);
2570 }
2571
2572 if (!DEVI_IS_DETACHING(dip)) {
2573 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) not detaching\n",
2574 pmf, PM_DEVICE(dip)))
2575 return (DDI_FAILURE);
2576 }
2577
2578 /*
2579 * If we don't care about saving power, or we're treating this node
2580 * specially, then this is a no-op
2581 */
2582 if (!PM_SCANABLE(dip) || pm_noinvol(dip)) {
2583 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) %s%s%s%s\n",
2584 pmf, PM_DEVICE(dip),
2585 !autopm_enabled ? "!autopm_enabled " : "",
2586 !PM_POLLING_CPUPM ? "!cpupm_polling " : "",
2587 PM_CPUPM_DISABLED ? "cpupm_disabled " : "",
2588 pm_noinvol(dip) ? "pm_noinvol()" : ""))
2589 return (DDI_SUCCESS);
2590 }
2591
2592 if (dev_is_needed(dip, comp, level, PM_LEVEL_DOWNONLY) != DDI_SUCCESS) {
2593 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) dev_is_needed failed\n", pmf,
2594 PM_DEVICE(dip)))
2595 return (DDI_FAILURE);
2596 }
2597 return (DDI_SUCCESS);
2598 }
2599
2600 /*
2601 * Find the entries struct for a given dip in the blocked list, return it locked
2602 */
2603 static psce_t *
pm_psc_dip_to_direct(dev_info_t * dip,pscc_t ** psccp)2604 pm_psc_dip_to_direct(dev_info_t *dip, pscc_t **psccp)
2605 {
2606 pscc_t *p;
2607 psce_t *psce;
2608
2609 rw_enter(&pm_pscc_direct_rwlock, RW_READER);
2610 for (p = pm_pscc_direct; p; p = p->pscc_next) {
2611 if (p->pscc_dip == dip) {
2612 *psccp = p;
2613 psce = p->pscc_entries;
2614 mutex_enter(&psce->psce_lock);
2615 ASSERT(psce);
2616 rw_exit(&pm_pscc_direct_rwlock);
2617 return (psce);
2618 }
2619 }
2620 rw_exit(&pm_pscc_direct_rwlock);
2621 panic("sunpm: no entry for dip %p in direct list", (void *)dip);
2622 /*NOTREACHED*/
2623 }
2624
2625 /*
2626 * Write an entry indicating a power level change (to be passed to a process
2627 * later) in the given psce.
2628 * If we were called in the path that brings up the console fb in the
2629 * case of entering the prom, we don't want to sleep. If the alloc fails, then
2630 * we create a record that has a size of -1, a physaddr of NULL, and that
2631 * has the overflow flag set.
2632 */
2633 static int
psc_entry(ushort_t event,psce_t * psce,dev_info_t * dip,int comp,int new,int old,int which,pm_canblock_t canblock)2634 psc_entry(ushort_t event, psce_t *psce, dev_info_t *dip, int comp, int new,
2635 int old, int which, pm_canblock_t canblock)
2636 {
2637 char buf[MAXNAMELEN];
2638 pm_state_change_t *p;
2639 size_t size;
2640 caddr_t physpath = NULL;
2641 int overrun = 0;
2642
2643 ASSERT(MUTEX_HELD(&psce->psce_lock));
2644 (void) ddi_pathname(dip, buf);
2645 size = strlen(buf) + 1;
2646 p = psce->psce_in;
2647 if (canblock == PM_CANBLOCK_BYPASS) {
2648 physpath = kmem_alloc(size, KM_NOSLEEP);
2649 if (physpath == NULL) {
2650 /*
2651 * mark current entry as overrun
2652 */
2653 p->flags |= PSC_EVENT_LOST;
2654 size = (size_t)-1;
2655 }
2656 } else
2657 physpath = kmem_alloc(size, KM_SLEEP);
2658 if (p->size) { /* overflow; mark the next entry */
2659 if (p->size != (size_t)-1)
2660 kmem_free(p->physpath, p->size);
2661 ASSERT(psce->psce_out == p);
2662 if (p == psce->psce_last) {
2663 psce->psce_first->flags |= PSC_EVENT_LOST;
2664 psce->psce_out = psce->psce_first;
2665 } else {
2666 (p + 1)->flags |= PSC_EVENT_LOST;
2667 psce->psce_out = (p + 1);
2668 }
2669 overrun++;
2670 } else if (physpath == NULL) { /* alloc failed, mark this entry */
2671 p->flags |= PSC_EVENT_LOST;
2672 p->size = 0;
2673 p->physpath = NULL;
2674 }
2675 if (which == PSC_INTEREST) {
2676 mutex_enter(&pm_compcnt_lock);
2677 if (pm_comps_notlowest == 0)
2678 p->flags |= PSC_ALL_LOWEST;
2679 else
2680 p->flags &= ~PSC_ALL_LOWEST;
2681 mutex_exit(&pm_compcnt_lock);
2682 }
2683 p->event = event;
2684 p->timestamp = gethrestime_sec();
2685 p->component = comp;
2686 p->old_level = old;
2687 p->new_level = new;
2688 p->physpath = physpath;
2689 p->size = size;
2690 if (physpath != NULL)
2691 (void) strcpy(p->physpath, buf);
2692 if (p == psce->psce_last)
2693 psce->psce_in = psce->psce_first;
2694 else
2695 psce->psce_in = ++p;
2696 mutex_exit(&psce->psce_lock);
2697 return (overrun);
2698 }
2699
2700 /*
2701 * Find the next entry on the interest list. We keep a pointer to the item we
2702 * last returned in the user's cooke. Returns a locked entries struct.
2703 */
2704 static psce_t *
psc_interest(void ** cookie,pscc_t ** psccp)2705 psc_interest(void **cookie, pscc_t **psccp)
2706 {
2707 pscc_t *pscc;
2708 pscc_t **cookiep = (pscc_t **)cookie;
2709
2710 if (*cookiep == NULL)
2711 pscc = pm_pscc_interest;
2712 else
2713 pscc = (*cookiep)->pscc_next;
2714 if (pscc) {
2715 *cookiep = pscc;
2716 *psccp = pscc;
2717 mutex_enter(&pscc->pscc_entries->psce_lock);
2718 return (pscc->pscc_entries);
2719 } else {
2720 return (NULL);
2721 }
2722 }
2723
2724 /*
2725 * Create an entry for a process to pick up indicating a power level change.
2726 */
2727 static void
pm_enqueue_notify(ushort_t cmd,dev_info_t * dip,int comp,int newlevel,int oldlevel,pm_canblock_t canblock)2728 pm_enqueue_notify(ushort_t cmd, dev_info_t *dip, int comp,
2729 int newlevel, int oldlevel, pm_canblock_t canblock)
2730 {
2731 PMD_FUNC(pmf, "enqueue_notify")
2732 pscc_t *pscc;
2733 psce_t *psce;
2734 void *cookie = NULL;
2735 int overrun;
2736
2737 ASSERT(MUTEX_HELD(&pm_rsvp_lock));
2738 switch (cmd) {
2739 case PSC_PENDING_CHANGE: /* only for controlling process */
2740 PMD(PMD_DPM, ("%s: PENDING %s@%s(%s#%d), comp %d, %d -> %d\n",
2741 pmf, PM_DEVICE(dip), comp, oldlevel, newlevel))
2742 psce = pm_psc_dip_to_direct(dip, &pscc);
2743 ASSERT(psce);
2744 PMD(PMD_IOCTL, ("%s: PENDING: %s@%s(%s#%d) pm_poll_cnt[%d] "
2745 "%d\n", pmf, PM_DEVICE(dip), pscc->pscc_clone,
2746 pm_poll_cnt[pscc->pscc_clone]))
2747 overrun = psc_entry(cmd, psce, dip, comp, newlevel, oldlevel,
2748 PSC_DIRECT, canblock);
2749 PMD(PMD_DPM, ("%s: sig %d\n", pmf, pscc->pscc_clone))
2750 mutex_enter(&pm_clone_lock);
2751 if (!overrun)
2752 pm_poll_cnt[pscc->pscc_clone]++;
2753 cv_signal(&pm_clones_cv[pscc->pscc_clone]);
2754 pollwakeup(&pm_pollhead, (POLLRDNORM | POLLIN));
2755 mutex_exit(&pm_clone_lock);
2756 break;
2757 case PSC_HAS_CHANGED:
2758 PMD(PMD_DPM, ("%s: HAS %s@%s(%s#%d), comp %d, %d -> %d\n",
2759 pmf, PM_DEVICE(dip), comp, oldlevel, newlevel))
2760 if (PM_ISDIRECT(dip) && canblock != PM_CANBLOCK_BYPASS) {
2761 psce = pm_psc_dip_to_direct(dip, &pscc);
2762 PMD(PMD_IOCTL, ("%s: HAS: %s@%s(%s#%d) pm_poll_cnt[%d] "
2763 "%d\n", pmf, PM_DEVICE(dip), pscc->pscc_clone,
2764 pm_poll_cnt[pscc->pscc_clone]))
2765 overrun = psc_entry(cmd, psce, dip, comp, newlevel,
2766 oldlevel, PSC_DIRECT, canblock);
2767 PMD(PMD_DPM, ("%s: sig %d\n", pmf, pscc->pscc_clone))
2768 mutex_enter(&pm_clone_lock);
2769 if (!overrun)
2770 pm_poll_cnt[pscc->pscc_clone]++;
2771 cv_signal(&pm_clones_cv[pscc->pscc_clone]);
2772 pollwakeup(&pm_pollhead, (POLLRDNORM | POLLIN));
2773 mutex_exit(&pm_clone_lock);
2774 }
2775 mutex_enter(&pm_clone_lock);
2776 rw_enter(&pm_pscc_interest_rwlock, RW_READER);
2777 while ((psce = psc_interest(&cookie, &pscc)) != NULL) {
2778 (void) psc_entry(cmd, psce, dip, comp, newlevel,
2779 oldlevel, PSC_INTEREST, canblock);
2780 cv_signal(&pm_clones_cv[pscc->pscc_clone]);
2781 }
2782 rw_exit(&pm_pscc_interest_rwlock);
2783 mutex_exit(&pm_clone_lock);
2784 break;
2785 #ifdef DEBUG
2786 default:
2787 ASSERT(0);
2788 #endif
2789 }
2790 }
2791
2792 static void
pm_enqueue_notify_others(pm_ppm_devlist_t ** listp,pm_canblock_t canblock)2793 pm_enqueue_notify_others(pm_ppm_devlist_t **listp, pm_canblock_t canblock)
2794 {
2795 if (listp) {
2796 pm_ppm_devlist_t *p, *next = NULL;
2797
2798 for (p = *listp; p; p = next) {
2799 next = p->ppd_next;
2800 pm_enqueue_notify(PSC_HAS_CHANGED, p->ppd_who,
2801 p->ppd_cmpt, p->ppd_new_level, p->ppd_old_level,
2802 canblock);
2803 kmem_free(p, sizeof (pm_ppm_devlist_t));
2804 }
2805 *listp = NULL;
2806 }
2807 }
2808
2809 /*
2810 * Try to get the power locks of the parent node and target (child)
2811 * node. Return true if successful (with both locks held) or false
2812 * (with no locks held).
2813 */
2814 static int
pm_try_parent_child_locks(dev_info_t * pdip,dev_info_t * dip,int * pcircp,int * circp)2815 pm_try_parent_child_locks(dev_info_t *pdip,
2816 dev_info_t *dip, int *pcircp, int *circp)
2817 {
2818 if (ndi_devi_tryenter(pdip, pcircp))
2819 if (PM_TRY_LOCK_POWER(dip, circp)) {
2820 return (1);
2821 } else {
2822 ndi_devi_exit(pdip, *pcircp);
2823 }
2824 return (0);
2825 }
2826
2827 /*
2828 * Determine if the power lock owner is blocked by current thread.
2829 * returns :
2830 * 1 - If the thread owning the effective power lock (the first lock on
2831 * which a thread blocks when it does PM_LOCK_POWER) is blocked by
2832 * a mutex held by the current thread.
2833 *
2834 * 0 - otherwise
2835 *
2836 * Note : This function is called by pm_power_has_changed to determine whether
2837 * it is executing in parallel with pm_set_power.
2838 */
2839 static int
pm_blocked_by_us(dev_info_t * dip)2840 pm_blocked_by_us(dev_info_t *dip)
2841 {
2842 power_req_t power_req;
2843 kthread_t *owner;
2844 int result;
2845 kmutex_t *mp;
2846 dev_info_t *ppm = (dev_info_t *)DEVI(dip)->devi_pm_ppm;
2847
2848 power_req.request_type = PMR_PPM_POWER_LOCK_OWNER;
2849 power_req.req.ppm_power_lock_owner_req.who = dip;
2850 if (pm_ctlops(ppm, dip, DDI_CTLOPS_POWER, &power_req, &result) !=
2851 DDI_SUCCESS) {
2852 /*
2853 * It is assumed that if the device is claimed by ppm, ppm
2854 * will always implement this request type and it'll always
2855 * return success. We panic here, if it fails.
2856 */
2857 panic("pm: Can't determine power lock owner of %s@%s(%s#%d)\n",
2858 PM_DEVICE(dip));
2859 /*NOTREACHED*/
2860 }
2861
2862 if ((owner = power_req.req.ppm_power_lock_owner_req.owner) != NULL &&
2863 owner->t_state == TS_SLEEP &&
2864 owner->t_sobj_ops &&
2865 SOBJ_TYPE(owner->t_sobj_ops) == SOBJ_MUTEX &&
2866 (mp = (kmutex_t *)owner->t_wchan) &&
2867 mutex_owner(mp) == curthread)
2868 return (1);
2869
2870 return (0);
2871 }
2872
2873 /*
2874 * Notify parent which wants to hear about a child's power changes.
2875 */
2876 static void
pm_notify_parent(dev_info_t * dip,dev_info_t * pdip,int comp,int old_level,int level)2877 pm_notify_parent(dev_info_t *dip,
2878 dev_info_t *pdip, int comp, int old_level, int level)
2879 {
2880 pm_bp_has_changed_t bphc;
2881 pm_sp_misc_t pspm;
2882 char *pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
2883 int result = DDI_SUCCESS;
2884
2885 bphc.bphc_dip = dip;
2886 bphc.bphc_path = ddi_pathname(dip, pathbuf);
2887 bphc.bphc_comp = comp;
2888 bphc.bphc_olevel = old_level;
2889 bphc.bphc_nlevel = level;
2890 pspm.pspm_canblock = PM_CANBLOCK_BLOCK;
2891 pspm.pspm_scan = 0;
2892 bphc.bphc_private = &pspm;
2893 (void) (*PM_BUS_POWER_FUNC(pdip))(pdip, NULL,
2894 BUS_POWER_HAS_CHANGED, (void *)&bphc, (void *)&result);
2895 kmem_free(pathbuf, MAXPATHLEN);
2896 }
2897
2898 /*
2899 * Check if we need to resume a BC device, and make the attach call as required.
2900 */
2901 static int
pm_check_and_resume(dev_info_t * dip,int comp,int old_level,int level)2902 pm_check_and_resume(dev_info_t *dip, int comp, int old_level, int level)
2903 {
2904 int ret = DDI_SUCCESS;
2905
2906 if (PM_ISBC(dip) && comp == 0 && old_level == 0 && level != 0) {
2907 ASSERT(DEVI(dip)->devi_pm_flags & PMC_SUSPENDED);
2908 /* ppm is not interested in DDI_PM_RESUME */
2909 if ((ret = devi_attach(dip, DDI_PM_RESUME)) != DDI_SUCCESS)
2910 /* XXX Should we mark it resumed, */
2911 /* even though it failed? */
2912 cmn_err(CE_WARN, "!pm: Can't resume %s@%s",
2913 PM_NAME(dip), PM_ADDR(dip));
2914 DEVI(dip)->devi_pm_flags &= ~PMC_SUSPENDED;
2915 }
2916
2917 return (ret);
2918 }
2919
2920 /*
2921 * Tests outside the lock to see if we should bother to enqueue an entry
2922 * for any watching process. If yes, then caller will take the lock and
2923 * do the full protocol
2924 */
2925 static int
pm_watchers()2926 pm_watchers()
2927 {
2928 if (pm_processes_stopped)
2929 return (0);
2930 return (pm_pscc_direct || pm_pscc_interest);
2931 }
2932
2933 static int pm_phc_impl(dev_info_t *, int, int, int);
2934
2935 /*
2936 * A driver is reporting that the power of one of its device's components
2937 * has changed. Update the power state accordingly.
2938 */
2939 int
pm_power_has_changed(dev_info_t * dip,int comp,int level)2940 pm_power_has_changed(dev_info_t *dip, int comp, int level)
2941 {
2942 PMD_FUNC(pmf, "pm_power_has_changed")
2943 int ret;
2944 dev_info_t *pdip = ddi_get_parent(dip);
2945 struct pm_component *cp;
2946 int blocked, circ, pcirc, old_level;
2947
2948 if (level < 0) {
2949 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d): bad level=%d\n", pmf,
2950 PM_DEVICE(dip), level))
2951 return (DDI_FAILURE);
2952 }
2953
2954 PMD(PMD_KIDSUP | PMD_DEP, ("%s: %s@%s(%s#%d), comp=%d, level=%d\n", pmf,
2955 PM_DEVICE(dip), comp, level))
2956
2957 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, comp, &cp) ||
2958 !e_pm_valid_power(dip, comp, level))
2959 return (DDI_FAILURE);
2960
2961 /*
2962 * A driver thread calling pm_power_has_changed and another thread
2963 * calling pm_set_power can deadlock. The problem is not resolvable
2964 * by changing lock order, so we use pm_blocked_by_us() to detect
2965 * this specific deadlock. If we can't get the lock immediately
2966 * and we are deadlocked, just update the component's level, do
2967 * notifications, and return. We intend to update the total power
2968 * state later (if the other thread fails to set power to the
2969 * desired level). If we were called because of a power change on a
2970 * component that isn't involved in a set_power op, update all state
2971 * immediately.
2972 */
2973 cp = PM_CP(dip, comp);
2974 while (!pm_try_parent_child_locks(pdip, dip, &pcirc, &circ)) {
2975 if (((blocked = pm_blocked_by_us(dip)) != 0) &&
2976 (cp->pmc_flags & PM_POWER_OP)) {
2977 if (pm_watchers()) {
2978 mutex_enter(&pm_rsvp_lock);
2979 pm_enqueue_notify(PSC_HAS_CHANGED, dip, comp,
2980 level, cur_power(cp), PM_CANBLOCK_BLOCK);
2981 mutex_exit(&pm_rsvp_lock);
2982 }
2983 if (pdip && PM_WANTS_NOTIFICATION(pdip))
2984 pm_notify_parent(dip,
2985 pdip, comp, cur_power(cp), level);
2986 (void) pm_check_and_resume(dip,
2987 comp, cur_power(cp), level);
2988
2989 /*
2990 * Stash the old power index, update curpwr, and flag
2991 * that the total power state needs to be synched.
2992 */
2993 cp->pmc_flags |= PM_PHC_WHILE_SET_POWER;
2994 /*
2995 * Several pm_power_has_changed calls could arrive
2996 * while the set power path remains blocked. Keep the
2997 * oldest old power and the newest new power of any
2998 * sequence of phc calls which arrive during deadlock.
2999 */
3000 if (cp->pmc_phc_pwr == PM_LEVEL_UNKNOWN)
3001 cp->pmc_phc_pwr = cp->pmc_cur_pwr;
3002 cp->pmc_cur_pwr =
3003 pm_level_to_index(dip, cp, level);
3004 PMD(PMD_PHC, ("%s: deadlock for %s@%s(%s#%d), comp=%d, "
3005 "level=%d\n", pmf, PM_DEVICE(dip), comp, level))
3006 return (DDI_SUCCESS);
3007 } else
3008 if (blocked) { /* blocked, but different cmpt? */
3009 if (!ndi_devi_tryenter(pdip, &pcirc)) {
3010 cmn_err(CE_NOTE,
3011 "!pm: parent kuc not updated due "
3012 "to possible deadlock.\n");
3013 return (pm_phc_impl(dip,
3014 comp, level, 1));
3015 }
3016 old_level = cur_power(cp);
3017 if (pdip && !PM_WANTS_NOTIFICATION(pdip) &&
3018 (!PM_ISBC(dip) || comp == 0) &&
3019 POWERING_ON(old_level, level))
3020 pm_hold_power(pdip);
3021 ret = pm_phc_impl(dip, comp, level, 1);
3022 if (pdip && !PM_WANTS_NOTIFICATION(pdip)) {
3023 if ((!PM_ISBC(dip) ||
3024 comp == 0) && level == 0 &&
3025 old_level != PM_LEVEL_UNKNOWN)
3026 pm_rele_power(pdip);
3027 }
3028 ndi_devi_exit(pdip, pcirc);
3029 /* child lock not held: deadlock */
3030 return (ret);
3031 }
3032 delay(1);
3033 PMD(PMD_PHC, ("%s: try lock again\n", pmf))
3034 }
3035
3036 /* non-deadlock case */
3037 old_level = cur_power(cp);
3038 if (pdip && !PM_WANTS_NOTIFICATION(pdip) &&
3039 (!PM_ISBC(dip) || comp == 0) && POWERING_ON(old_level, level))
3040 pm_hold_power(pdip);
3041 ret = pm_phc_impl(dip, comp, level, 1);
3042 if (pdip && !PM_WANTS_NOTIFICATION(pdip)) {
3043 if ((!PM_ISBC(dip) || comp == 0) && level == 0 &&
3044 old_level != PM_LEVEL_UNKNOWN)
3045 pm_rele_power(pdip);
3046 }
3047 PM_UNLOCK_POWER(dip, circ);
3048 ndi_devi_exit(pdip, pcirc);
3049 return (ret);
3050 }
3051
3052 /*
3053 * Account for power changes to a component of the the console frame buffer.
3054 * If lowering power from full (or "unkown", which is treatd as full)
3055 * we will increment the "components off" count of the fb device.
3056 * Subsequent lowering of the same component doesn't affect the count. If
3057 * raising a component back to full power, we will decrement the count.
3058 *
3059 * Return: the increment value for pm_cfb_comps_off (-1, 0, or 1)
3060 */
3061 static int
calc_cfb_comps_incr(dev_info_t * dip,int cmpt,int old,int new)3062 calc_cfb_comps_incr(dev_info_t *dip, int cmpt, int old, int new)
3063 {
3064 struct pm_component *cp = PM_CP(dip, cmpt);
3065 int on = (old == PM_LEVEL_UNKNOWN || old == cp->pmc_norm_pwr);
3066 int want_normal = (new == cp->pmc_norm_pwr);
3067 int incr = 0;
3068
3069 if (on && !want_normal)
3070 incr = 1;
3071 else if (!on && want_normal)
3072 incr = -1;
3073 return (incr);
3074 }
3075
3076 /*
3077 * Adjust the count of console frame buffer components < full power.
3078 */
3079 static void
update_comps_off(int incr,dev_info_t * dip)3080 update_comps_off(int incr, dev_info_t *dip)
3081 {
3082 mutex_enter(&pm_cfb_lock);
3083 pm_cfb_comps_off += incr;
3084 ASSERT(pm_cfb_comps_off <= PM_NUMCMPTS(dip));
3085 mutex_exit(&pm_cfb_lock);
3086 }
3087
3088 /*
3089 * Update the power state in the framework (via the ppm). The 'notify'
3090 * argument tells whether to notify watchers. Power lock is already held.
3091 */
3092 static int
pm_phc_impl(dev_info_t * dip,int comp,int level,int notify)3093 pm_phc_impl(dev_info_t *dip, int comp, int level, int notify)
3094 {
3095 PMD_FUNC(pmf, "phc_impl")
3096 power_req_t power_req;
3097 int i, dodeps = 0;
3098 dev_info_t *pdip = ddi_get_parent(dip);
3099 int result;
3100 int old_level;
3101 struct pm_component *cp;
3102 int incr = 0;
3103 dev_info_t *ppm = (dev_info_t *)DEVI(dip)->devi_pm_ppm;
3104 int work_type = 0;
3105 char *pathbuf;
3106
3107 /* Must use "official" power level for this test. */
3108 cp = PM_CP(dip, comp);
3109 old_level = (cp->pmc_flags & PM_PHC_WHILE_SET_POWER ?
3110 cp->pmc_phc_pwr : cp->pmc_cur_pwr);
3111 if (old_level != PM_LEVEL_UNKNOWN)
3112 old_level = cp->pmc_comp.pmc_lvals[old_level];
3113
3114 if (level == old_level) {
3115 PMD(PMD_SET, ("%s: %s@%s(%s#%d), comp=%d is already at "
3116 "level=%d\n", pmf, PM_DEVICE(dip), comp, level))
3117 return (DDI_SUCCESS);
3118 }
3119
3120 /*
3121 * Tell ppm about this.
3122 */
3123 power_req.request_type = PMR_PPM_POWER_CHANGE_NOTIFY;
3124 power_req.req.ppm_notify_level_req.who = dip;
3125 power_req.req.ppm_notify_level_req.cmpt = comp;
3126 power_req.req.ppm_notify_level_req.new_level = level;
3127 power_req.req.ppm_notify_level_req.old_level = old_level;
3128 if (pm_ctlops(ppm, dip, DDI_CTLOPS_POWER, &power_req,
3129 &result) == DDI_FAILURE) {
3130 PMD(PMD_FAIL, ("%s: pm_ctlops %s@%s(%s#%d) to %d failed\n",
3131 pmf, PM_DEVICE(dip), level))
3132 return (DDI_FAILURE);
3133 }
3134
3135 if (PM_IS_CFB(dip)) {
3136 incr = calc_cfb_comps_incr(dip, comp, old_level, level);
3137
3138 if (incr) {
3139 update_comps_off(incr, dip);
3140 PMD(PMD_CFB, ("%s: %s@%s(%s#%d) comp=%d %d->%d "
3141 "cfb_comps_off->%d\n", pmf, PM_DEVICE(dip),
3142 comp, old_level, level, pm_cfb_comps_off))
3143 }
3144 }
3145 e_pm_set_cur_pwr(dip, PM_CP(dip, comp), level);
3146 result = DDI_SUCCESS;
3147
3148 if (notify) {
3149 if (pdip && PM_WANTS_NOTIFICATION(pdip))
3150 pm_notify_parent(dip, pdip, comp, old_level, level);
3151 (void) pm_check_and_resume(dip, comp, old_level, level);
3152 }
3153
3154 /*
3155 * Decrement the dependency kidsup count if we turn a device
3156 * off.
3157 */
3158 if (POWERING_OFF(old_level, level)) {
3159 dodeps = 1;
3160 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
3161 cp = PM_CP(dip, i);
3162 if (cur_power(cp)) {
3163 dodeps = 0;
3164 break;
3165 }
3166 }
3167 if (dodeps)
3168 work_type = PM_DEP_WK_POWER_OFF;
3169 }
3170
3171 /*
3172 * Increment if we turn it on. Check to see
3173 * if other comps are already on, if so,
3174 * dont increment.
3175 */
3176 if (POWERING_ON(old_level, level)) {
3177 dodeps = 1;
3178 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
3179 cp = PM_CP(dip, i);
3180 if (comp == i)
3181 continue;
3182 /* -1 also treated as 0 in this case */
3183 if (cur_power(cp) > 0) {
3184 dodeps = 0;
3185 break;
3186 }
3187 }
3188 if (dodeps)
3189 work_type = PM_DEP_WK_POWER_ON;
3190 }
3191
3192 if (dodeps) {
3193 pathbuf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
3194 (void) ddi_pathname(dip, pathbuf);
3195 pm_dispatch_to_dep_thread(work_type, pathbuf, NULL,
3196 PM_DEP_NOWAIT, NULL, 0);
3197 kmem_free(pathbuf, MAXPATHLEN);
3198 }
3199
3200 if (notify && (level != old_level) && pm_watchers()) {
3201 mutex_enter(&pm_rsvp_lock);
3202 pm_enqueue_notify(PSC_HAS_CHANGED, dip, comp, level, old_level,
3203 PM_CANBLOCK_BLOCK);
3204 mutex_exit(&pm_rsvp_lock);
3205 }
3206
3207 PMD(PMD_RESCAN, ("%s: %s@%s(%s#%d): pm_rescan\n", pmf, PM_DEVICE(dip)))
3208 pm_rescan(dip);
3209 return (DDI_SUCCESS);
3210 }
3211
3212 /*
3213 * This function is called at startup time to notify pm of the existence
3214 * of any platform power managers for this platform. As a result of
3215 * this registration, each function provided will be called each time
3216 * a device node is attached, until one returns true, and it must claim the
3217 * device node (by returning non-zero) if it wants to be involved in the
3218 * node's power management. If it does claim the node, then it will
3219 * subsequently be notified of attach and detach events.
3220 *
3221 */
3222
3223 int
pm_register_ppm(int (* func)(dev_info_t *),dev_info_t * dip)3224 pm_register_ppm(int (*func)(dev_info_t *), dev_info_t *dip)
3225 {
3226 PMD_FUNC(pmf, "register_ppm")
3227 struct ppm_callbacks *ppmcp;
3228 pm_component_t *cp;
3229 int i, pwr, result, circ;
3230 power_req_t power_req;
3231 struct ppm_notify_level_req *p = &power_req.req.ppm_notify_level_req;
3232 void pm_ppm_claim(dev_info_t *);
3233
3234 mutex_enter(&ppm_lock);
3235 ppmcp = ppm_callbacks;
3236 for (i = 0; i < MAX_PPM_HANDLERS; i++, ppmcp++) {
3237 if (ppmcp->ppmc_func == NULL) {
3238 ppmcp->ppmc_func = func;
3239 ppmcp->ppmc_dip = dip;
3240 break;
3241 }
3242 }
3243 mutex_exit(&ppm_lock);
3244
3245 if (i >= MAX_PPM_HANDLERS)
3246 return (DDI_FAILURE);
3247 while ((dip = ddi_get_parent(dip)) != NULL) {
3248 if (dip != ddi_root_node() && PM_GET_PM_INFO(dip) == NULL)
3249 continue;
3250 pm_ppm_claim(dip);
3251 /* don't bother with the not power-manageable nodes */
3252 if (pm_ppm_claimed(dip) && PM_GET_PM_INFO(dip)) {
3253 /*
3254 * Tell ppm about this.
3255 */
3256 power_req.request_type = PMR_PPM_POWER_CHANGE_NOTIFY;
3257 p->old_level = PM_LEVEL_UNKNOWN;
3258 p->who = dip;
3259 PM_LOCK_POWER(dip, &circ);
3260 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
3261 cp = PM_CP(dip, i);
3262 pwr = cp->pmc_cur_pwr;
3263 if (pwr != PM_LEVEL_UNKNOWN) {
3264 p->cmpt = i;
3265 p->new_level = cur_power(cp);
3266 p->old_level = PM_LEVEL_UNKNOWN;
3267 if (pm_ctlops(PPM(dip), dip,
3268 DDI_CTLOPS_POWER, &power_req,
3269 &result) == DDI_FAILURE) {
3270 PMD(PMD_FAIL, ("%s: pc "
3271 "%s@%s(%s#%d) to %d "
3272 "fails\n", pmf,
3273 PM_DEVICE(dip), pwr))
3274 }
3275 }
3276 }
3277 PM_UNLOCK_POWER(dip, circ);
3278 }
3279 }
3280 return (DDI_SUCCESS);
3281 }
3282
3283 /*
3284 * Call the ppm's that have registered and adjust the devinfo struct as
3285 * appropriate. First one to claim it gets it. The sets of devices claimed
3286 * by each ppm are assumed to be disjoint.
3287 */
3288 void
pm_ppm_claim(dev_info_t * dip)3289 pm_ppm_claim(dev_info_t *dip)
3290 {
3291 struct ppm_callbacks *ppmcp;
3292
3293 if (PPM(dip)) {
3294 return;
3295 }
3296 mutex_enter(&ppm_lock);
3297 for (ppmcp = ppm_callbacks; ppmcp->ppmc_func; ppmcp++) {
3298 if ((*ppmcp->ppmc_func)(dip)) {
3299 DEVI(dip)->devi_pm_ppm =
3300 (struct dev_info *)ppmcp->ppmc_dip;
3301 mutex_exit(&ppm_lock);
3302 return;
3303 }
3304 }
3305 mutex_exit(&ppm_lock);
3306 }
3307
3308 /*
3309 * Node is being detached so stop autopm until we see if it succeeds, in which
3310 * case pm_stop will be called. For backwards compatible devices we bring the
3311 * device up to full power on the assumption the detach will succeed.
3312 */
3313 void
pm_detaching(dev_info_t * dip)3314 pm_detaching(dev_info_t *dip)
3315 {
3316 PMD_FUNC(pmf, "detaching")
3317 pm_info_t *info = PM_GET_PM_INFO(dip);
3318 int iscons;
3319
3320 PMD(PMD_REMDEV, ("%s: %s@%s(%s#%d), %d comps\n", pmf, PM_DEVICE(dip),
3321 PM_NUMCMPTS(dip)))
3322 if (info == NULL)
3323 return;
3324 ASSERT(DEVI_IS_DETACHING(dip));
3325 PM_LOCK_DIP(dip);
3326 info->pmi_dev_pm_state |= PM_DETACHING;
3327 PM_UNLOCK_DIP(dip);
3328 if (!PM_ISBC(dip))
3329 pm_scan_stop(dip);
3330
3331 /*
3332 * console and old-style devices get brought up when detaching.
3333 */
3334 iscons = PM_IS_CFB(dip);
3335 if (iscons || PM_ISBC(dip)) {
3336 (void) pm_all_to_normal(dip, PM_CANBLOCK_BYPASS);
3337 if (iscons) {
3338 mutex_enter(&pm_cfb_lock);
3339 while (cfb_inuse) {
3340 mutex_exit(&pm_cfb_lock);
3341 PMD(PMD_CFB, ("%s: delay; cfb_inuse\n", pmf))
3342 delay(1);
3343 mutex_enter(&pm_cfb_lock);
3344 }
3345 ASSERT(cfb_dip_detaching == NULL);
3346 ASSERT(cfb_dip);
3347 cfb_dip_detaching = cfb_dip; /* case detach fails */
3348 cfb_dip = NULL;
3349 mutex_exit(&pm_cfb_lock);
3350 }
3351 }
3352 }
3353
3354 /*
3355 * Node failed to detach. If it used to be autopm'd, make it so again.
3356 */
3357 void
pm_detach_failed(dev_info_t * dip)3358 pm_detach_failed(dev_info_t *dip)
3359 {
3360 PMD_FUNC(pmf, "detach_failed")
3361 pm_info_t *info = PM_GET_PM_INFO(dip);
3362 int pm_all_at_normal(dev_info_t *);
3363
3364 if (info == NULL)
3365 return;
3366 ASSERT(DEVI_IS_DETACHING(dip));
3367 if (info->pmi_dev_pm_state & PM_DETACHING) {
3368 info->pmi_dev_pm_state &= ~PM_DETACHING;
3369 if (info->pmi_dev_pm_state & PM_ALLNORM_DEFERRED) {
3370 /* Make sure the operation is still needed */
3371 if (!pm_all_at_normal(dip)) {
3372 if (pm_all_to_normal(dip,
3373 PM_CANBLOCK_FAIL) != DDI_SUCCESS) {
3374 PMD(PMD_ERROR, ("%s: could not bring "
3375 "%s@%s(%s#%d) to normal\n", pmf,
3376 PM_DEVICE(dip)))
3377 }
3378 }
3379 info->pmi_dev_pm_state &= ~PM_ALLNORM_DEFERRED;
3380 }
3381 }
3382 if (!PM_ISBC(dip)) {
3383 mutex_enter(&pm_scan_lock);
3384 if (PM_SCANABLE(dip))
3385 pm_scan_init(dip);
3386 mutex_exit(&pm_scan_lock);
3387 pm_rescan(dip);
3388 }
3389 }
3390
3391 /* generic Backwards Compatible component */
3392 static char *bc_names[] = {"off", "on"};
3393
3394 static pm_comp_t bc_comp = {"unknown", 2, NULL, NULL, &bc_names[0]};
3395
3396 static void
e_pm_default_levels(dev_info_t * dip,pm_component_t * cp,int norm)3397 e_pm_default_levels(dev_info_t *dip, pm_component_t *cp, int norm)
3398 {
3399 pm_comp_t *pmc;
3400 pmc = &cp->pmc_comp;
3401 pmc->pmc_numlevels = 2;
3402 pmc->pmc_lvals[0] = 0;
3403 pmc->pmc_lvals[1] = norm;
3404 e_pm_set_cur_pwr(dip, cp, norm);
3405 }
3406
3407 static void
e_pm_default_components(dev_info_t * dip,int cmpts)3408 e_pm_default_components(dev_info_t *dip, int cmpts)
3409 {
3410 int i;
3411 pm_component_t *p = DEVI(dip)->devi_pm_components;
3412
3413 p = DEVI(dip)->devi_pm_components;
3414 for (i = 0; i < cmpts; i++, p++) {
3415 p->pmc_comp = bc_comp; /* struct assignment */
3416 p->pmc_comp.pmc_lvals = kmem_zalloc(2 * sizeof (int),
3417 KM_SLEEP);
3418 p->pmc_comp.pmc_thresh = kmem_alloc(2 * sizeof (int),
3419 KM_SLEEP);
3420 p->pmc_comp.pmc_numlevels = 2;
3421 p->pmc_comp.pmc_thresh[0] = INT_MAX;
3422 p->pmc_comp.pmc_thresh[1] = INT_MAX;
3423 }
3424 }
3425
3426 /*
3427 * Called from functions that require components to exist already to allow
3428 * for their creation by parsing the pm-components property.
3429 * Device will not be power managed as a result of this call
3430 * No locking needed because we're single threaded by the ndi_devi_enter
3431 * done while attaching, and the device isn't visible until after it has
3432 * attached
3433 */
3434 int
pm_premanage(dev_info_t * dip,int style)3435 pm_premanage(dev_info_t *dip, int style)
3436 {
3437 PMD_FUNC(pmf, "premanage")
3438 pm_comp_t *pcp, *compp;
3439 int cmpts, i, norm, error;
3440 pm_component_t *p = DEVI(dip)->devi_pm_components;
3441 pm_comp_t *pm_autoconfig(dev_info_t *, int *);
3442
3443 ASSERT(!PM_IAM_LOCKING_DIP(dip));
3444 /*
3445 * If this dip has already been processed, don't mess with it
3446 */
3447 if (DEVI(dip)->devi_pm_flags & PMC_COMPONENTS_DONE)
3448 return (DDI_SUCCESS);
3449 if (DEVI(dip)->devi_pm_flags & PMC_COMPONENTS_FAILED) {
3450 return (DDI_FAILURE);
3451 }
3452 /*
3453 * Look up pm-components property and create components accordingly
3454 * If that fails, fall back to backwards compatibility
3455 */
3456 if ((compp = pm_autoconfig(dip, &error)) == NULL) {
3457 /*
3458 * If error is set, the property existed but was not well formed
3459 */
3460 if (error || (style == PM_STYLE_NEW)) {
3461 DEVI(dip)->devi_pm_flags |= PMC_COMPONENTS_FAILED;
3462 return (DDI_FAILURE);
3463 }
3464 /*
3465 * If they don't have the pm-components property, then we
3466 * want the old "no pm until PM_SET_DEVICE_THRESHOLDS ioctl"
3467 * behavior driver must have called pm_create_components, and
3468 * we need to flesh out dummy components
3469 */
3470 if ((cmpts = PM_NUMCMPTS(dip)) == 0) {
3471 /*
3472 * Not really failure, but we don't want the
3473 * caller to treat it as success
3474 */
3475 return (DDI_FAILURE);
3476 }
3477 DEVI(dip)->devi_pm_flags |= PMC_BC;
3478 e_pm_default_components(dip, cmpts);
3479 for (i = 0; i < cmpts; i++) {
3480 /*
3481 * if normal power not set yet, we don't really know
3482 * what *ANY* of the power values are. If normal
3483 * power is set, then we assume for this backwards
3484 * compatible case that the values are 0, normal power.
3485 */
3486 norm = pm_get_normal_power(dip, i);
3487 if (norm == (uint_t)-1) {
3488 PMD(PMD_ERROR, ("%s: %s@%s(%s#%d)[%d]\n", pmf,
3489 PM_DEVICE(dip), i))
3490 return (DDI_FAILURE);
3491 }
3492 /*
3493 * Components of BC devices start at their normal power,
3494 * so count them to be not at their lowest power.
3495 */
3496 PM_INCR_NOTLOWEST(dip);
3497 e_pm_default_levels(dip, PM_CP(dip, i), norm);
3498 }
3499 } else {
3500 /*
3501 * e_pm_create_components was called from pm_autoconfig(), it
3502 * creates components with no descriptions (or known levels)
3503 */
3504 cmpts = PM_NUMCMPTS(dip);
3505 ASSERT(cmpts != 0);
3506 pcp = compp;
3507 p = DEVI(dip)->devi_pm_components;
3508 for (i = 0; i < cmpts; i++, p++) {
3509 p->pmc_comp = *pcp++; /* struct assignment */
3510 ASSERT(PM_CP(dip, i)->pmc_cur_pwr == 0);
3511 e_pm_set_cur_pwr(dip, PM_CP(dip, i), PM_LEVEL_UNKNOWN);
3512 }
3513 if (DEVI(dip)->devi_pm_flags & PMC_CPU_THRESH)
3514 pm_set_device_threshold(dip, pm_cpu_idle_threshold,
3515 PMC_CPU_THRESH);
3516 else
3517 pm_set_device_threshold(dip, pm_system_idle_threshold,
3518 PMC_DEF_THRESH);
3519 kmem_free(compp, cmpts * sizeof (pm_comp_t));
3520 }
3521 return (DDI_SUCCESS);
3522 }
3523
3524 /*
3525 * Called from during or after the device's attach to let us know it is ready
3526 * to play autopm. Look up the pm model and manage the device accordingly.
3527 * Returns system call errno value.
3528 * If DDI_ATTACH and DDI_DETACH were in same namespace, this would be
3529 * a little cleaner
3530 *
3531 * Called with dip lock held, return with dip lock unheld.
3532 */
3533
3534 int
e_pm_manage(dev_info_t * dip,int style)3535 e_pm_manage(dev_info_t *dip, int style)
3536 {
3537 PMD_FUNC(pmf, "e_manage")
3538 pm_info_t *info;
3539 dev_info_t *pdip = ddi_get_parent(dip);
3540 int pm_thresh_specd(dev_info_t *);
3541 int count;
3542 char *pathbuf;
3543
3544 if (pm_premanage(dip, style) != DDI_SUCCESS) {
3545 return (DDI_FAILURE);
3546 }
3547 PMD(PMD_KIDSUP, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
3548 ASSERT(PM_GET_PM_INFO(dip) == NULL);
3549 info = kmem_zalloc(sizeof (pm_info_t), KM_SLEEP);
3550
3551 /*
3552 * Now set up parent's kidsupcnt. BC nodes are assumed to start
3553 * out at their normal power, so they are "up", others start out
3554 * unknown, which is effectively "up". Parent which want notification
3555 * get kidsupcnt of 0 always.
3556 */
3557 count = (PM_ISBC(dip)) ? 1 : PM_NUMCMPTS(dip);
3558 if (count && pdip && !PM_WANTS_NOTIFICATION(pdip))
3559 e_pm_hold_rele_power(pdip, count);
3560
3561 pm_set_pm_info(dip, info);
3562 /*
3563 * Apply any recorded thresholds
3564 */
3565 (void) pm_thresh_specd(dip);
3566
3567 /*
3568 * Do dependency processing.
3569 */
3570 pathbuf = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
3571 (void) ddi_pathname(dip, pathbuf);
3572 pm_dispatch_to_dep_thread(PM_DEP_WK_ATTACH, pathbuf, pathbuf,
3573 PM_DEP_NOWAIT, NULL, 0);
3574 kmem_free(pathbuf, MAXPATHLEN);
3575
3576 if (!PM_ISBC(dip)) {
3577 mutex_enter(&pm_scan_lock);
3578 if (PM_SCANABLE(dip)) {
3579 pm_scan_init(dip);
3580 mutex_exit(&pm_scan_lock);
3581 pm_rescan(dip);
3582 } else {
3583 mutex_exit(&pm_scan_lock);
3584 }
3585 }
3586 return (0);
3587 }
3588
3589 /*
3590 * This is the obsolete exported interface for a driver to find out its
3591 * "normal" (max) power.
3592 * We only get components destroyed while no power management is
3593 * going on (and the device is detached), so we don't need a mutex here
3594 */
3595 int
pm_get_normal_power(dev_info_t * dip,int comp)3596 pm_get_normal_power(dev_info_t *dip, int comp)
3597 {
3598
3599 if (comp >= 0 && comp < PM_NUMCMPTS(dip)) {
3600 return (PM_CP(dip, comp)->pmc_norm_pwr);
3601 }
3602 return (DDI_FAILURE);
3603 }
3604
3605 /*
3606 * Fetches the current power level. Return DDI_SUCCESS or DDI_FAILURE.
3607 */
3608 int
pm_get_current_power(dev_info_t * dip,int comp,int * levelp)3609 pm_get_current_power(dev_info_t *dip, int comp, int *levelp)
3610 {
3611 if (comp >= 0 && comp < PM_NUMCMPTS(dip)) {
3612 *levelp = PM_CURPOWER(dip, comp);
3613 return (DDI_SUCCESS);
3614 }
3615 return (DDI_FAILURE);
3616 }
3617
3618 /*
3619 * Returns current threshold of indicated component
3620 */
3621 static int
cur_threshold(dev_info_t * dip,int comp)3622 cur_threshold(dev_info_t *dip, int comp)
3623 {
3624 pm_component_t *cp = PM_CP(dip, comp);
3625 int pwr;
3626
3627 if (PM_ISBC(dip)) {
3628 /*
3629 * backwards compatible nodes only have one threshold
3630 */
3631 return (cp->pmc_comp.pmc_thresh[1]);
3632 }
3633 pwr = cp->pmc_cur_pwr;
3634 if (pwr == PM_LEVEL_UNKNOWN) {
3635 int thresh;
3636 if (DEVI(dip)->devi_pm_flags & PMC_NEXDEF_THRESH)
3637 thresh = pm_default_nexus_threshold;
3638 else if (DEVI(dip)->devi_pm_flags & PMC_CPU_THRESH)
3639 thresh = pm_cpu_idle_threshold;
3640 else
3641 thresh = pm_system_idle_threshold;
3642 return (thresh);
3643 }
3644 ASSERT(cp->pmc_comp.pmc_thresh);
3645 return (cp->pmc_comp.pmc_thresh[pwr]);
3646 }
3647
3648 /*
3649 * Compute next lower component power level given power index.
3650 */
3651 static int
pm_next_lower_power(pm_component_t * cp,int pwrndx)3652 pm_next_lower_power(pm_component_t *cp, int pwrndx)
3653 {
3654 int nxt_pwr;
3655
3656 if (pwrndx == PM_LEVEL_UNKNOWN) {
3657 nxt_pwr = cp->pmc_comp.pmc_lvals[0];
3658 } else {
3659 pwrndx--;
3660 ASSERT(pwrndx >= 0);
3661 nxt_pwr = cp->pmc_comp.pmc_lvals[pwrndx];
3662 }
3663 return (nxt_pwr);
3664 }
3665
3666 /*
3667 * Update the maxpower (normal) power of a component. Note that the
3668 * component's power level is only changed if it's current power level
3669 * is higher than the new max power.
3670 */
3671 int
pm_update_maxpower(dev_info_t * dip,int comp,int level)3672 pm_update_maxpower(dev_info_t *dip, int comp, int level)
3673 {
3674 PMD_FUNC(pmf, "update_maxpower")
3675 int old;
3676 int result;
3677
3678 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, comp, NULL) ||
3679 !e_pm_valid_power(dip, comp, level)) {
3680 PMD(PMD_FAIL, ("%s: validation checks failed for %s@%s(%s#%d) "
3681 "comp=%d level=%d\n", pmf, PM_DEVICE(dip), comp, level))
3682 return (DDI_FAILURE);
3683 }
3684 old = e_pm_get_max_power(dip, comp);
3685 e_pm_set_max_power(dip, comp, level);
3686
3687 if (pm_set_power(dip, comp, level, PM_LEVEL_DOWNONLY,
3688 PM_CANBLOCK_BLOCK, 0, &result) != DDI_SUCCESS) {
3689 e_pm_set_max_power(dip, comp, old);
3690 PMD(PMD_FAIL, ("%s: %s@%s(%s#%d) pm_set_power failed\n", pmf,
3691 PM_DEVICE(dip)))
3692 return (DDI_FAILURE);
3693 }
3694 return (DDI_SUCCESS);
3695 }
3696
3697 /*
3698 * Bring all components of device to normal power
3699 */
3700 int
pm_all_to_normal(dev_info_t * dip,pm_canblock_t canblock)3701 pm_all_to_normal(dev_info_t *dip, pm_canblock_t canblock)
3702 {
3703 PMD_FUNC(pmf, "all_to_normal")
3704 int *normal;
3705 int i, ncomps, result;
3706 size_t size;
3707 int changefailed = 0;
3708
3709 PMD(PMD_ALLNORM, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
3710 ASSERT(PM_GET_PM_INFO(dip));
3711 if (pm_get_norm_pwrs(dip, &normal, &size) != DDI_SUCCESS) {
3712 PMD(PMD_ALLNORM, ("%s: can't get norm pwrs for "
3713 "%s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
3714 return (DDI_FAILURE);
3715 }
3716 ncomps = PM_NUMCMPTS(dip);
3717 for (i = 0; i < ncomps; i++) {
3718 if (pm_set_power(dip, i, normal[i],
3719 PM_LEVEL_UPONLY, canblock, 0, &result) != DDI_SUCCESS) {
3720 changefailed++;
3721 PMD(PMD_ALLNORM | PMD_FAIL, ("%s: failed to set "
3722 "%s@%s(%s#%d)[%d] to %d, errno %d\n", pmf,
3723 PM_DEVICE(dip), i, normal[i], result))
3724 }
3725 }
3726 kmem_free(normal, size);
3727 if (changefailed) {
3728 PMD(PMD_FAIL, ("%s: failed to set %d comps %s@%s(%s#%d) "
3729 "to full power\n", pmf, changefailed, PM_DEVICE(dip)))
3730 return (DDI_FAILURE);
3731 }
3732 return (DDI_SUCCESS);
3733 }
3734
3735 /*
3736 * Returns true if all components of device are at normal power
3737 */
3738 int
pm_all_at_normal(dev_info_t * dip)3739 pm_all_at_normal(dev_info_t *dip)
3740 {
3741 PMD_FUNC(pmf, "all_at_normal")
3742 int *normal;
3743 int i;
3744 size_t size;
3745
3746 PMD(PMD_ALLNORM, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
3747 if (pm_get_norm_pwrs(dip, &normal, &size) != DDI_SUCCESS) {
3748 PMD(PMD_ALLNORM, ("%s: can't get normal power\n", pmf))
3749 return (DDI_FAILURE);
3750 }
3751 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
3752 int current = PM_CURPOWER(dip, i);
3753 if (normal[i] > current) {
3754 PMD(PMD_ALLNORM, ("%s: %s@%s(%s#%d) comp=%d, "
3755 "norm=%d, cur=%d\n", pmf, PM_DEVICE(dip), i,
3756 normal[i], current))
3757 break;
3758 }
3759 }
3760 kmem_free(normal, size);
3761 if (i != PM_NUMCMPTS(dip)) {
3762 return (0);
3763 }
3764 return (1);
3765 }
3766
3767 static void bring_pmdep_up(dev_info_t *, int);
3768
3769 static void
bring_wekeeps_up(char * keeper)3770 bring_wekeeps_up(char *keeper)
3771 {
3772 PMD_FUNC(pmf, "bring_wekeeps_up")
3773 int i;
3774 pm_pdr_t *dp;
3775 pm_info_t *wku_info;
3776 char *kept_path;
3777 dev_info_t *kept;
3778
3779 if (panicstr) {
3780 return;
3781 }
3782 /*
3783 * We process the request even if the keeper detaches because
3784 * detach processing expects this to increment kidsupcnt of kept.
3785 */
3786 PMD(PMD_BRING, ("%s: keeper= %s\n", pmf, keeper))
3787 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
3788 if (strcmp(dp->pdr_keeper, keeper) != 0)
3789 continue;
3790 for (i = 0; i < dp->pdr_kept_count; i++) {
3791 kept_path = dp->pdr_kept_paths[i];
3792 if (kept_path == NULL)
3793 continue;
3794 ASSERT(kept_path[0] != '\0');
3795 if ((kept = pm_name_to_dip(kept_path, 1)) == NULL)
3796 continue;
3797 wku_info = PM_GET_PM_INFO(kept);
3798 if (wku_info == NULL) {
3799 if (kept)
3800 ddi_release_devi(kept);
3801 continue;
3802 }
3803 /*
3804 * Don't mess with it if it is being detached, it isn't
3805 * safe to call its power entry point
3806 */
3807 if (wku_info->pmi_dev_pm_state & PM_DETACHING) {
3808 if (kept)
3809 ddi_release_devi(kept);
3810 continue;
3811 }
3812 bring_pmdep_up(kept, 1);
3813 ddi_release_devi(kept);
3814 }
3815 }
3816 }
3817
3818 /*
3819 * Bring up the 'kept' device passed as argument
3820 */
3821 static void
bring_pmdep_up(dev_info_t * kept_dip,int hold)3822 bring_pmdep_up(dev_info_t *kept_dip, int hold)
3823 {
3824 PMD_FUNC(pmf, "bring_pmdep_up")
3825 int is_all_at_normal = 0;
3826
3827 /*
3828 * If the kept device has been unmanaged, do nothing.
3829 */
3830 if (!PM_GET_PM_INFO(kept_dip))
3831 return;
3832
3833 /* Just ignore DIRECT PM device till they are released. */
3834 if (!pm_processes_stopped && PM_ISDIRECT(kept_dip) &&
3835 !(is_all_at_normal = pm_all_at_normal(kept_dip))) {
3836 PMD(PMD_BRING, ("%s: can't bring up PM_DIRECT %s@%s(%s#%d) "
3837 "controlling process did something else\n", pmf,
3838 PM_DEVICE(kept_dip)))
3839 DEVI(kept_dip)->devi_pm_flags |= PMC_SKIP_BRINGUP;
3840 return;
3841 }
3842 /* if we got here the keeper had a transition from OFF->ON */
3843 if (hold)
3844 pm_hold_power(kept_dip);
3845
3846 if (!is_all_at_normal)
3847 (void) pm_all_to_normal(kept_dip, PM_CANBLOCK_FAIL);
3848 }
3849
3850 /*
3851 * A bunch of stuff that belongs only to the next routine (or two)
3852 */
3853
3854 static const char namestr[] = "NAME=";
3855 static const int nameln = sizeof (namestr) - 1;
3856 static const char pmcompstr[] = "pm-components";
3857
3858 struct pm_comp_pkg {
3859 pm_comp_t *comp;
3860 struct pm_comp_pkg *next;
3861 };
3862
3863 #define isdigit(ch) ((ch) >= '0' && (ch) <= '9')
3864
3865 #define isxdigit(ch) (isdigit(ch) || ((ch) >= 'a' && (ch) <= 'f') || \
3866 ((ch) >= 'A' && (ch) <= 'F'))
3867
3868 /*
3869 * Rather than duplicate this code ...
3870 * (this code excerpted from the function that follows it)
3871 */
3872 #define FINISH_COMP { \
3873 ASSERT(compp); \
3874 compp->pmc_lnames_sz = size; \
3875 tp = compp->pmc_lname_buf = kmem_alloc(size, KM_SLEEP); \
3876 compp->pmc_numlevels = level; \
3877 compp->pmc_lnames = kmem_alloc(level * sizeof (char *), KM_SLEEP); \
3878 compp->pmc_lvals = kmem_alloc(level * sizeof (int), KM_SLEEP); \
3879 compp->pmc_thresh = kmem_alloc(level * sizeof (int), KM_SLEEP); \
3880 /* copy string out of prop array into buffer */ \
3881 for (j = 0; j < level; j++) { \
3882 compp->pmc_thresh[j] = INT_MAX; /* only [0] sticks */ \
3883 compp->pmc_lvals[j] = lvals[j]; \
3884 (void) strcpy(tp, lnames[j]); \
3885 compp->pmc_lnames[j] = tp; \
3886 tp += lszs[j]; \
3887 } \
3888 ASSERT(tp > compp->pmc_lname_buf && tp <= \
3889 compp->pmc_lname_buf + compp->pmc_lnames_sz); \
3890 }
3891
3892 /*
3893 * Create (empty) component data structures.
3894 */
3895 static void
e_pm_create_components(dev_info_t * dip,int num_components)3896 e_pm_create_components(dev_info_t *dip, int num_components)
3897 {
3898 struct pm_component *compp, *ocompp;
3899 int i, size = 0;
3900
3901 ASSERT(!PM_IAM_LOCKING_DIP(dip));
3902 ASSERT(!DEVI(dip)->devi_pm_components);
3903 ASSERT(!(DEVI(dip)->devi_pm_flags & PMC_COMPONENTS_DONE));
3904 size = sizeof (struct pm_component) * num_components;
3905
3906 compp = kmem_zalloc(size, KM_SLEEP);
3907 ocompp = compp;
3908 DEVI(dip)->devi_pm_comp_size = size;
3909 DEVI(dip)->devi_pm_num_components = num_components;
3910 PM_LOCK_BUSY(dip);
3911 for (i = 0; i < num_components; i++) {
3912 compp->pmc_timestamp = gethrestime_sec();
3913 compp->pmc_norm_pwr = (uint_t)-1;
3914 compp++;
3915 }
3916 PM_UNLOCK_BUSY(dip);
3917 DEVI(dip)->devi_pm_components = ocompp;
3918 DEVI(dip)->devi_pm_flags |= PMC_COMPONENTS_DONE;
3919 }
3920
3921 /*
3922 * Parse hex or decimal value from char string
3923 */
3924 static char *
pm_parsenum(char * cp,int * valp)3925 pm_parsenum(char *cp, int *valp)
3926 {
3927 int ch, offset;
3928 char numbuf[256];
3929 char *np = numbuf;
3930 int value = 0;
3931
3932 ch = *cp++;
3933 if (isdigit(ch)) {
3934 if (ch == '0') {
3935 if ((ch = *cp++) == 'x' || ch == 'X') {
3936 ch = *cp++;
3937 while (isxdigit(ch)) {
3938 *np++ = (char)ch;
3939 ch = *cp++;
3940 }
3941 *np = 0;
3942 cp--;
3943 goto hexval;
3944 } else {
3945 goto digit;
3946 }
3947 } else {
3948 digit:
3949 while (isdigit(ch)) {
3950 *np++ = (char)ch;
3951 ch = *cp++;
3952 }
3953 *np = 0;
3954 cp--;
3955 goto decval;
3956 }
3957 } else
3958 return (NULL);
3959
3960 hexval:
3961 for (np = numbuf; *np; np++) {
3962 if (*np >= 'a' && *np <= 'f')
3963 offset = 'a' - 10;
3964 else if (*np >= 'A' && *np <= 'F')
3965 offset = 'A' - 10;
3966 else if (*np >= '0' && *np <= '9')
3967 offset = '0';
3968 value *= 16;
3969 value += *np - offset;
3970 }
3971 *valp = value;
3972 return (cp);
3973
3974 decval:
3975 offset = '0';
3976 for (np = numbuf; *np; np++) {
3977 value *= 10;
3978 value += *np - offset;
3979 }
3980 *valp = value;
3981 return (cp);
3982 }
3983
3984 /*
3985 * Set max (previously documented as "normal") power.
3986 */
3987 static void
e_pm_set_max_power(dev_info_t * dip,int component_number,int level)3988 e_pm_set_max_power(dev_info_t *dip, int component_number, int level)
3989 {
3990 PM_CP(dip, component_number)->pmc_norm_pwr = level;
3991 }
3992
3993 /*
3994 * Get max (previously documented as "normal") power.
3995 */
3996 static int
e_pm_get_max_power(dev_info_t * dip,int component_number)3997 e_pm_get_max_power(dev_info_t *dip, int component_number)
3998 {
3999 return (PM_CP(dip, component_number)->pmc_norm_pwr);
4000 }
4001
4002 /*
4003 * Internal routine for destroying components
4004 * It is called even when there might not be any, so it must be forgiving.
4005 */
4006 static void
e_pm_destroy_components(dev_info_t * dip)4007 e_pm_destroy_components(dev_info_t *dip)
4008 {
4009 int i;
4010 struct pm_component *cp;
4011
4012 ASSERT(!PM_IAM_LOCKING_DIP(dip));
4013 if (PM_NUMCMPTS(dip) == 0)
4014 return;
4015 cp = DEVI(dip)->devi_pm_components;
4016 ASSERT(cp);
4017 for (i = 0; i < PM_NUMCMPTS(dip); i++, cp++) {
4018 int nlevels = cp->pmc_comp.pmc_numlevels;
4019 kmem_free(cp->pmc_comp.pmc_lvals, nlevels * sizeof (int));
4020 kmem_free(cp->pmc_comp.pmc_thresh, nlevels * sizeof (int));
4021 /*
4022 * For BC nodes, the rest is static in bc_comp, so skip it
4023 */
4024 if (PM_ISBC(dip))
4025 continue;
4026 kmem_free(cp->pmc_comp.pmc_name, cp->pmc_comp.pmc_name_sz);
4027 kmem_free(cp->pmc_comp.pmc_lnames, nlevels * sizeof (char *));
4028 kmem_free(cp->pmc_comp.pmc_lname_buf,
4029 cp->pmc_comp.pmc_lnames_sz);
4030 }
4031 kmem_free(DEVI(dip)->devi_pm_components, DEVI(dip)->devi_pm_comp_size);
4032 DEVI(dip)->devi_pm_components = NULL;
4033 DEVI(dip)->devi_pm_num_components = 0;
4034 DEVI(dip)->devi_pm_flags &=
4035 ~(PMC_COMPONENTS_DONE | PMC_COMPONENTS_FAILED);
4036 }
4037
4038 /*
4039 * Read the pm-components property (if there is one) and use it to set up
4040 * components. Returns a pointer to an array of component structures if
4041 * pm-components found and successfully parsed, else returns NULL.
4042 * Sets error return *errp to true to indicate a failure (as opposed to no
4043 * property being present).
4044 */
4045 pm_comp_t *
pm_autoconfig(dev_info_t * dip,int * errp)4046 pm_autoconfig(dev_info_t *dip, int *errp)
4047 {
4048 PMD_FUNC(pmf, "autoconfig")
4049 uint_t nelems;
4050 char **pp;
4051 pm_comp_t *compp = NULL;
4052 int i, j, level, components = 0;
4053 size_t size = 0;
4054 struct pm_comp_pkg *p, *ptail;
4055 struct pm_comp_pkg *phead = NULL;
4056 int *lvals = NULL;
4057 int *lszs = NULL;
4058 int *np = NULL;
4059 int npi = 0;
4060 char **lnames = NULL;
4061 char *cp, *tp;
4062 pm_comp_t *ret = NULL;
4063
4064 ASSERT(!PM_IAM_LOCKING_DIP(dip));
4065 *errp = 0; /* assume success */
4066 if (ddi_prop_lookup_string_array(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS,
4067 (char *)pmcompstr, &pp, &nelems) != DDI_PROP_SUCCESS) {
4068 return (NULL);
4069 }
4070
4071 if (nelems < 3) { /* need at least one name and two levels */
4072 goto errout;
4073 }
4074
4075 /*
4076 * pm_create_components is no longer allowed
4077 */
4078 if (PM_NUMCMPTS(dip) != 0) {
4079 PMD(PMD_ERROR, ("%s: %s@%s(%s#%d) has %d comps\n",
4080 pmf, PM_DEVICE(dip), PM_NUMCMPTS(dip)))
4081 goto errout;
4082 }
4083
4084 lvals = kmem_alloc(nelems * sizeof (int), KM_SLEEP);
4085 lszs = kmem_alloc(nelems * sizeof (int), KM_SLEEP);
4086 lnames = kmem_alloc(nelems * sizeof (char *), KM_SLEEP);
4087 np = kmem_alloc(nelems * sizeof (int), KM_SLEEP);
4088
4089 level = 0;
4090 phead = NULL;
4091 for (i = 0; i < nelems; i++) {
4092 cp = pp[i];
4093 if (!isdigit(*cp)) { /* must be name */
4094 if (strncmp(cp, namestr, nameln) != 0) {
4095 goto errout;
4096 }
4097 if (i != 0) {
4098 if (level == 0) { /* no level spec'd */
4099 PMD(PMD_ERROR, ("%s: no level spec'd\n",
4100 pmf))
4101 goto errout;
4102 }
4103 np[npi++] = lvals[level - 1];
4104 /* finish up previous component levels */
4105 FINISH_COMP;
4106 }
4107 cp += nameln;
4108 if (!*cp) {
4109 PMD(PMD_ERROR, ("%s: nsa\n", pmf))
4110 goto errout;
4111 }
4112 p = kmem_zalloc(sizeof (*phead), KM_SLEEP);
4113 if (phead == NULL) {
4114 phead = ptail = p;
4115 } else {
4116 ptail->next = p;
4117 ptail = p;
4118 }
4119 compp = p->comp = kmem_zalloc(sizeof (pm_comp_t),
4120 KM_SLEEP);
4121 compp->pmc_name_sz = strlen(cp) + 1;
4122 compp->pmc_name = kmem_zalloc(compp->pmc_name_sz,
4123 KM_SLEEP);
4124 (void) strncpy(compp->pmc_name, cp, compp->pmc_name_sz);
4125 components++;
4126 level = 0;
4127 } else { /* better be power level <num>=<name> */
4128 #ifdef DEBUG
4129 tp = cp;
4130 #endif
4131 if (i == 0 ||
4132 (cp = pm_parsenum(cp, &lvals[level])) == NULL) {
4133 PMD(PMD_ERROR, ("%s: parsenum(%s)\n", pmf, tp))
4134 goto errout;
4135 }
4136 #ifdef DEBUG
4137 tp = cp;
4138 #endif
4139 if (*cp++ != '=' || !*cp) {
4140 PMD(PMD_ERROR, ("%s: ex =, got %s\n", pmf, tp))
4141 goto errout;
4142 }
4143
4144 lszs[level] = strlen(cp) + 1;
4145 size += lszs[level];
4146 lnames[level] = cp; /* points into prop string */
4147 level++;
4148 }
4149 }
4150 np[npi++] = lvals[level - 1];
4151 if (level == 0) { /* ended with a name */
4152 PMD(PMD_ERROR, ("%s: ewn\n", pmf))
4153 goto errout;
4154 }
4155 FINISH_COMP;
4156
4157
4158 /*
4159 * Now we have a list of components--we have to return instead an
4160 * array of them, but we can just copy the top level and leave
4161 * the rest as is
4162 */
4163 (void) e_pm_create_components(dip, components);
4164 for (i = 0; i < components; i++)
4165 e_pm_set_max_power(dip, i, np[i]);
4166
4167 ret = kmem_zalloc(components * sizeof (pm_comp_t), KM_SLEEP);
4168 for (i = 0, p = phead; i < components; i++) {
4169 ASSERT(p);
4170 /*
4171 * Now sanity-check values: levels must be monotonically
4172 * increasing
4173 */
4174 if (p->comp->pmc_numlevels < 2) {
4175 PMD(PMD_ERROR, ("%s: comp %s of %s@%s(%s#%d) only %d "
4176 "levels\n", pmf,
4177 p->comp->pmc_name, PM_DEVICE(dip),
4178 p->comp->pmc_numlevels))
4179 goto errout;
4180 }
4181 for (j = 0; j < p->comp->pmc_numlevels; j++) {
4182 if ((p->comp->pmc_lvals[j] < 0) || ((j > 0) &&
4183 (p->comp->pmc_lvals[j] <=
4184 p->comp->pmc_lvals[j - 1]))) {
4185 PMD(PMD_ERROR, ("%s: comp %s of %s@%s(%s#%d) "
4186 "not mono. incr, %d follows %d\n", pmf,
4187 p->comp->pmc_name, PM_DEVICE(dip),
4188 p->comp->pmc_lvals[j],
4189 p->comp->pmc_lvals[j - 1]))
4190 goto errout;
4191 }
4192 }
4193 ret[i] = *p->comp; /* struct assignment */
4194 for (j = 0; j < i; j++) {
4195 /*
4196 * Test for unique component names
4197 */
4198 if (strcmp(ret[j].pmc_name, ret[i].pmc_name) == 0) {
4199 PMD(PMD_ERROR, ("%s: %s of %s@%s(%s#%d) not "
4200 "unique\n", pmf, ret[j].pmc_name,
4201 PM_DEVICE(dip)))
4202 goto errout;
4203 }
4204 }
4205 ptail = p;
4206 p = p->next;
4207 phead = p; /* errout depends on phead making sense */
4208 kmem_free(ptail->comp, sizeof (*ptail->comp));
4209 kmem_free(ptail, sizeof (*ptail));
4210 }
4211 out:
4212 ddi_prop_free(pp);
4213 if (lvals)
4214 kmem_free(lvals, nelems * sizeof (int));
4215 if (lszs)
4216 kmem_free(lszs, nelems * sizeof (int));
4217 if (lnames)
4218 kmem_free(lnames, nelems * sizeof (char *));
4219 if (np)
4220 kmem_free(np, nelems * sizeof (int));
4221 return (ret);
4222
4223 errout:
4224 e_pm_destroy_components(dip);
4225 *errp = 1; /* signal failure */
4226 cmn_err(CE_CONT, "!pm: %s property ", pmcompstr);
4227 for (i = 0; i < nelems - 1; i++)
4228 cmn_err(CE_CONT, "!'%s', ", pp[i]);
4229 if (nelems != 0)
4230 cmn_err(CE_CONT, "!'%s'", pp[nelems - 1]);
4231 cmn_err(CE_CONT, "! for %s@%s(%s#%d) is ill-formed.\n", PM_DEVICE(dip));
4232 for (p = phead; p; ) {
4233 pm_comp_t *pp;
4234 int n;
4235
4236 ptail = p;
4237 /*
4238 * Free component data structures
4239 */
4240 pp = p->comp;
4241 n = pp->pmc_numlevels;
4242 if (pp->pmc_name_sz) {
4243 kmem_free(pp->pmc_name, pp->pmc_name_sz);
4244 }
4245 if (pp->pmc_lnames_sz) {
4246 kmem_free(pp->pmc_lname_buf, pp->pmc_lnames_sz);
4247 }
4248 if (pp->pmc_lnames) {
4249 kmem_free(pp->pmc_lnames, n * (sizeof (char *)));
4250 }
4251 if (pp->pmc_thresh) {
4252 kmem_free(pp->pmc_thresh, n * (sizeof (int)));
4253 }
4254 if (pp->pmc_lvals) {
4255 kmem_free(pp->pmc_lvals, n * (sizeof (int)));
4256 }
4257 p = ptail->next;
4258 kmem_free(ptail, sizeof (*ptail));
4259 }
4260 if (ret != NULL)
4261 kmem_free(ret, components * sizeof (pm_comp_t));
4262 ret = NULL;
4263 goto out;
4264 }
4265
4266 /*
4267 * Set threshold values for a devices components by dividing the target
4268 * threshold (base) by the number of transitions and assign each transition
4269 * that threshold. This will get the entire device down in the target time if
4270 * all components are idle and even if there are dependencies among components.
4271 *
4272 * Devices may well get powered all the way down before the target time, but
4273 * at least the EPA will be happy.
4274 */
4275 void
pm_set_device_threshold(dev_info_t * dip,int base,int flag)4276 pm_set_device_threshold(dev_info_t *dip, int base, int flag)
4277 {
4278 PMD_FUNC(pmf, "set_device_threshold")
4279 int target_threshold = (base * 95) / 100;
4280 int level, comp; /* loop counters */
4281 int transitions = 0;
4282 int ncomp = PM_NUMCMPTS(dip);
4283 int thresh;
4284 int remainder;
4285 pm_comp_t *pmc;
4286 int i, circ;
4287
4288 ASSERT(!PM_IAM_LOCKING_DIP(dip));
4289 PM_LOCK_DIP(dip);
4290 /*
4291 * First we handle the easy one. If we're setting the default
4292 * threshold for a node with children, then we set it to the
4293 * default nexus threshold (currently 0) and mark it as default
4294 * nexus threshold instead
4295 */
4296 if (PM_IS_NEXUS(dip)) {
4297 if (flag == PMC_DEF_THRESH) {
4298 PMD(PMD_THRESH, ("%s: [%s@%s(%s#%d) NEXDEF]\n", pmf,
4299 PM_DEVICE(dip)))
4300 thresh = pm_default_nexus_threshold;
4301 for (comp = 0; comp < ncomp; comp++) {
4302 pmc = &PM_CP(dip, comp)->pmc_comp;
4303 for (level = 1; level < pmc->pmc_numlevels;
4304 level++) {
4305 pmc->pmc_thresh[level] = thresh;
4306 }
4307 }
4308 DEVI(dip)->devi_pm_dev_thresh =
4309 pm_default_nexus_threshold;
4310 /*
4311 * If the nexus node is being reconfigured back to
4312 * the default threshold, adjust the notlowest count.
4313 */
4314 if (DEVI(dip)->devi_pm_flags &
4315 (PMC_DEV_THRESH|PMC_COMP_THRESH)) {
4316 PM_LOCK_POWER(dip, &circ);
4317 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
4318 if (PM_CURPOWER(dip, i) == 0)
4319 continue;
4320 mutex_enter(&pm_compcnt_lock);
4321 ASSERT(pm_comps_notlowest);
4322 pm_comps_notlowest--;
4323 PMD(PMD_LEVEL, ("%s: %s@%s(%s#%d) decr "
4324 "notlowest to %d\n", pmf,
4325 PM_DEVICE(dip), pm_comps_notlowest))
4326 if (pm_comps_notlowest == 0)
4327 pm_ppm_notify_all_lowest(dip,
4328 PM_ALL_LOWEST);
4329 mutex_exit(&pm_compcnt_lock);
4330 }
4331 PM_UNLOCK_POWER(dip, circ);
4332 }
4333 DEVI(dip)->devi_pm_flags &= PMC_THRESH_NONE;
4334 DEVI(dip)->devi_pm_flags |= PMC_NEXDEF_THRESH;
4335 PM_UNLOCK_DIP(dip);
4336 return;
4337 } else if (DEVI(dip)->devi_pm_flags & PMC_NEXDEF_THRESH) {
4338 /*
4339 * If the nexus node is being configured for a
4340 * non-default threshold, include that node in
4341 * the notlowest accounting.
4342 */
4343 PM_LOCK_POWER(dip, &circ);
4344 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
4345 if (PM_CURPOWER(dip, i) == 0)
4346 continue;
4347 mutex_enter(&pm_compcnt_lock);
4348 if (pm_comps_notlowest == 0)
4349 pm_ppm_notify_all_lowest(dip,
4350 PM_NOT_ALL_LOWEST);
4351 pm_comps_notlowest++;
4352 PMD(PMD_LEVEL, ("%s: %s@%s(%s#%d) incr "
4353 "notlowest to %d\n", pmf,
4354 PM_DEVICE(dip), pm_comps_notlowest))
4355 mutex_exit(&pm_compcnt_lock);
4356 }
4357 PM_UNLOCK_POWER(dip, circ);
4358 }
4359 }
4360 /*
4361 * Compute the total number of transitions for all components
4362 * of the device. Distribute the threshold evenly over them
4363 */
4364 for (comp = 0; comp < ncomp; comp++) {
4365 pmc = &PM_CP(dip, comp)->pmc_comp;
4366 ASSERT(pmc->pmc_numlevels > 1);
4367 transitions += pmc->pmc_numlevels - 1;
4368 }
4369 ASSERT(transitions);
4370 thresh = target_threshold / transitions;
4371
4372 for (comp = 0; comp < ncomp; comp++) {
4373 pmc = &PM_CP(dip, comp)->pmc_comp;
4374 for (level = 1; level < pmc->pmc_numlevels; level++) {
4375 pmc->pmc_thresh[level] = thresh;
4376 }
4377 }
4378
4379 #ifdef DEBUG
4380 for (comp = 0; comp < ncomp; comp++) {
4381 pmc = &PM_CP(dip, comp)->pmc_comp;
4382 for (level = 1; level < pmc->pmc_numlevels; level++) {
4383 PMD(PMD_THRESH, ("%s: thresh before %s@%s(%s#%d) "
4384 "comp=%d, level=%d, %d\n", pmf, PM_DEVICE(dip),
4385 comp, level, pmc->pmc_thresh[level]))
4386 }
4387 }
4388 #endif
4389 /*
4390 * Distribute any remainder till they are all gone
4391 */
4392 remainder = target_threshold - thresh * transitions;
4393 level = 1;
4394 #ifdef DEBUG
4395 PMD(PMD_THRESH, ("%s: remainder=%d target_threshold=%d thresh=%d "
4396 "trans=%d\n", pmf, remainder, target_threshold, thresh,
4397 transitions))
4398 #endif
4399 while (remainder > 0) {
4400 comp = 0;
4401 while (remainder && (comp < ncomp)) {
4402 pmc = &PM_CP(dip, comp)->pmc_comp;
4403 if (level < pmc->pmc_numlevels) {
4404 pmc->pmc_thresh[level] += 1;
4405 remainder--;
4406 }
4407 comp++;
4408 }
4409 level++;
4410 }
4411 #ifdef DEBUG
4412 for (comp = 0; comp < ncomp; comp++) {
4413 pmc = &PM_CP(dip, comp)->pmc_comp;
4414 for (level = 1; level < pmc->pmc_numlevels; level++) {
4415 PMD(PMD_THRESH, ("%s: thresh after %s@%s(%s#%d) "
4416 "comp=%d level=%d, %d\n", pmf, PM_DEVICE(dip),
4417 comp, level, pmc->pmc_thresh[level]))
4418 }
4419 }
4420 #endif
4421 ASSERT(PM_IAM_LOCKING_DIP(dip));
4422 DEVI(dip)->devi_pm_dev_thresh = base;
4423 DEVI(dip)->devi_pm_flags &= PMC_THRESH_NONE;
4424 DEVI(dip)->devi_pm_flags |= flag;
4425 PM_UNLOCK_DIP(dip);
4426 }
4427
4428 /*
4429 * Called when there is no old-style platform power management driver
4430 */
4431 static int
ddi_no_platform_power(power_req_t * req)4432 ddi_no_platform_power(power_req_t *req)
4433 {
4434 _NOTE(ARGUNUSED(req))
4435 return (DDI_FAILURE);
4436 }
4437
4438 /*
4439 * This function calls the entry point supplied by the platform-specific
4440 * pm driver to bring the device component 'pm_cmpt' to power level 'pm_level'.
4441 * The use of global for getting the function name from platform-specific
4442 * pm driver is not ideal, but it is simple and efficient.
4443 * The previous property lookup was being done in the idle loop on swift
4444 * systems without pmc chips and hurt deskbench performance as well as
4445 * violating scheduler locking rules
4446 */
4447 int (*pm_platform_power)(power_req_t *) = ddi_no_platform_power;
4448
4449 /*
4450 * Old obsolete interface for a device to request a power change (but only
4451 * an increase in power)
4452 */
4453 int
ddi_dev_is_needed(dev_info_t * dip,int cmpt,int level)4454 ddi_dev_is_needed(dev_info_t *dip, int cmpt, int level)
4455 {
4456 return (pm_raise_power(dip, cmpt, level));
4457 }
4458
4459 /*
4460 * The old obsolete interface to platform power management. Only used by
4461 * Gypsy platform and APM on X86.
4462 */
4463 int
ddi_power(dev_info_t * dip,int pm_cmpt,int pm_level)4464 ddi_power(dev_info_t *dip, int pm_cmpt, int pm_level)
4465 {
4466 power_req_t request;
4467
4468 request.request_type = PMR_SET_POWER;
4469 request.req.set_power_req.who = dip;
4470 request.req.set_power_req.cmpt = pm_cmpt;
4471 request.req.set_power_req.level = pm_level;
4472 return (ddi_ctlops(dip, dip, DDI_CTLOPS_POWER, &request, NULL));
4473 }
4474
4475 /*
4476 * A driver can invoke this from its detach routine when DDI_SUSPEND is
4477 * passed. Returns true if subsequent processing could result in power being
4478 * removed from the device. The arg is not currently used because it is
4479 * implicit in the operation of cpr/DR.
4480 */
4481 int
ddi_removing_power(dev_info_t * dip)4482 ddi_removing_power(dev_info_t *dip)
4483 {
4484 _NOTE(ARGUNUSED(dip))
4485 return (pm_powering_down);
4486 }
4487
4488 /*
4489 * Returns true if a device indicates that its parent handles suspend/resume
4490 * processing for it.
4491 */
4492 int
e_ddi_parental_suspend_resume(dev_info_t * dip)4493 e_ddi_parental_suspend_resume(dev_info_t *dip)
4494 {
4495 return (DEVI(dip)->devi_pm_flags & PMC_PARENTAL_SR);
4496 }
4497
4498 /*
4499 * Called for devices which indicate that their parent does suspend/resume
4500 * handling for them
4501 */
4502 int
e_ddi_suspend(dev_info_t * dip,ddi_detach_cmd_t cmd)4503 e_ddi_suspend(dev_info_t *dip, ddi_detach_cmd_t cmd)
4504 {
4505 power_req_t request;
4506 request.request_type = PMR_SUSPEND;
4507 request.req.suspend_req.who = dip;
4508 request.req.suspend_req.cmd = cmd;
4509 return (ddi_ctlops(dip, dip, DDI_CTLOPS_POWER, &request, NULL));
4510 }
4511
4512 /*
4513 * Called for devices which indicate that their parent does suspend/resume
4514 * handling for them
4515 */
4516 int
e_ddi_resume(dev_info_t * dip,ddi_attach_cmd_t cmd)4517 e_ddi_resume(dev_info_t *dip, ddi_attach_cmd_t cmd)
4518 {
4519 power_req_t request;
4520 request.request_type = PMR_RESUME;
4521 request.req.resume_req.who = dip;
4522 request.req.resume_req.cmd = cmd;
4523 return (ddi_ctlops(dip, dip, DDI_CTLOPS_POWER, &request, NULL));
4524 }
4525
4526 /*
4527 * Old obsolete exported interface for drivers to create components.
4528 * This is now handled by exporting the pm-components property.
4529 */
4530 int
pm_create_components(dev_info_t * dip,int num_components)4531 pm_create_components(dev_info_t *dip, int num_components)
4532 {
4533 PMD_FUNC(pmf, "pm_create_components")
4534
4535 if (num_components < 1)
4536 return (DDI_FAILURE);
4537
4538 if (!DEVI_IS_ATTACHING(dip)) {
4539 return (DDI_FAILURE);
4540 }
4541
4542 /* don't need to lock dip because attach is single threaded */
4543 if (DEVI(dip)->devi_pm_components) {
4544 PMD(PMD_ERROR, ("%s: %s@%s(%s#%d) already has %d\n", pmf,
4545 PM_DEVICE(dip), PM_NUMCMPTS(dip)))
4546 return (DDI_FAILURE);
4547 }
4548 e_pm_create_components(dip, num_components);
4549 DEVI(dip)->devi_pm_flags |= PMC_BC;
4550 e_pm_default_components(dip, num_components);
4551 return (DDI_SUCCESS);
4552 }
4553
4554 /*
4555 * Obsolete interface previously called by drivers to destroy their components
4556 * at detach time. This is now done automatically. However, we need to keep
4557 * this for the old drivers.
4558 */
4559 void
pm_destroy_components(dev_info_t * dip)4560 pm_destroy_components(dev_info_t *dip)
4561 {
4562 PMD_FUNC(pmf, "pm_destroy_components")
4563 dev_info_t *pdip = ddi_get_parent(dip);
4564
4565 PMD(PMD_REMDEV | PMD_KIDSUP, ("%s: %s@%s(%s#%d)\n", pmf,
4566 PM_DEVICE(dip)))
4567 ASSERT(DEVI_IS_DETACHING(dip));
4568 #ifdef DEBUG
4569 if (!PM_ISBC(dip))
4570 cmn_err(CE_WARN, "!driver exporting pm-components property "
4571 "(%s@%s) calls pm_destroy_components", PM_NAME(dip),
4572 PM_ADDR(dip));
4573 #endif
4574 /*
4575 * We ignore this unless this is an old-style driver, except for
4576 * printing the message above
4577 */
4578 if (PM_NUMCMPTS(dip) == 0 || !PM_ISBC(dip)) {
4579 PMD(PMD_REMDEV, ("%s: ignore %s@%s(%s#%d)\n", pmf,
4580 PM_DEVICE(dip)))
4581 return;
4582 }
4583 ASSERT(PM_GET_PM_INFO(dip));
4584
4585 /*
4586 * pm_unmanage will clear info pointer later, after dealing with
4587 * dependencies
4588 */
4589 ASSERT(!PM_GET_PM_SCAN(dip)); /* better be gone already */
4590 /*
4591 * Now adjust parent's kidsupcnt. We check only comp 0.
4592 * Parents that get notification are not adjusted because their
4593 * kidsupcnt is always 0 (or 1 during probe and attach).
4594 */
4595 if ((PM_CURPOWER(dip, 0) != 0) && pdip && !PM_WANTS_NOTIFICATION(pdip))
4596 pm_rele_power(pdip);
4597 #ifdef DEBUG
4598 else {
4599 PMD(PMD_KIDSUP, ("%s: kuc stays %s@%s(%s#%d) comps gone\n",
4600 pmf, PM_DEVICE(dip)))
4601 }
4602 #endif
4603 e_pm_destroy_components(dip);
4604 /*
4605 * Forget we ever knew anything about the components of this device
4606 */
4607 DEVI(dip)->devi_pm_flags &=
4608 ~(PMC_BC | PMC_COMPONENTS_DONE | PMC_COMPONENTS_FAILED);
4609 }
4610
4611 /*
4612 * Exported interface for a driver to set a component busy.
4613 */
4614 int
pm_busy_component(dev_info_t * dip,int cmpt)4615 pm_busy_component(dev_info_t *dip, int cmpt)
4616 {
4617 struct pm_component *cp;
4618
4619 ASSERT(dip != NULL);
4620 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, cmpt, &cp))
4621 return (DDI_FAILURE);
4622 PM_LOCK_BUSY(dip);
4623 cp->pmc_busycount++;
4624 cp->pmc_timestamp = 0;
4625 PM_UNLOCK_BUSY(dip);
4626 return (DDI_SUCCESS);
4627 }
4628
4629 /*
4630 * Exported interface for a driver to set a component idle.
4631 */
4632 int
pm_idle_component(dev_info_t * dip,int cmpt)4633 pm_idle_component(dev_info_t *dip, int cmpt)
4634 {
4635 PMD_FUNC(pmf, "pm_idle_component")
4636 struct pm_component *cp;
4637 pm_scan_t *scanp = PM_GET_PM_SCAN(dip);
4638
4639 if (!e_pm_valid_info(dip, NULL) || !e_pm_valid_comp(dip, cmpt, &cp))
4640 return (DDI_FAILURE);
4641
4642 PM_LOCK_BUSY(dip);
4643 if (cp->pmc_busycount) {
4644 if (--(cp->pmc_busycount) == 0)
4645 cp->pmc_timestamp = gethrestime_sec();
4646 } else {
4647 cp->pmc_timestamp = gethrestime_sec();
4648 }
4649
4650 PM_UNLOCK_BUSY(dip);
4651
4652 /*
4653 * if device becomes idle during idle down period, try scan it down
4654 */
4655 if (scanp && PM_IS_PID(dip)) {
4656 PMD(PMD_IDLEDOWN, ("%s: %s@%s(%s#%d) idle.\n", pmf,
4657 PM_DEVICE(dip)))
4658 pm_rescan(dip);
4659 return (DDI_SUCCESS);
4660 }
4661
4662 /*
4663 * handle scan not running with nexus threshold == 0
4664 */
4665
4666 if (PM_IS_NEXUS(dip) && (cp->pmc_busycount == 0)) {
4667 pm_rescan(dip);
4668 }
4669
4670 return (DDI_SUCCESS);
4671 }
4672
4673 /*
4674 * This is the old obsolete interface called by drivers to set their normal
4675 * power. Thus we can't fix its behavior or return a value.
4676 * This functionality is replaced by the pm-component property.
4677 * We'll only get components destroyed while no power management is
4678 * going on (and the device is detached), so we don't need a mutex here
4679 */
4680 void
pm_set_normal_power(dev_info_t * dip,int comp,int level)4681 pm_set_normal_power(dev_info_t *dip, int comp, int level)
4682 {
4683 PMD_FUNC(pmf, "set_normal_power")
4684 #ifdef DEBUG
4685 if (!PM_ISBC(dip))
4686 cmn_err(CE_WARN, "!call to pm_set_normal_power() by %s@%s "
4687 "(driver exporting pm-components property) ignored",
4688 PM_NAME(dip), PM_ADDR(dip));
4689 #endif
4690 if (PM_ISBC(dip)) {
4691 PMD(PMD_NORM, ("%s: %s@%s(%s#%d) set normal power comp=%d, "
4692 "level=%d\n", pmf, PM_DEVICE(dip), comp, level))
4693 e_pm_set_max_power(dip, comp, level);
4694 e_pm_default_levels(dip, PM_CP(dip, comp), level);
4695 }
4696 }
4697
4698 /*
4699 * Called on a successfully detached driver to free pm resources
4700 */
4701 static void
pm_stop(dev_info_t * dip)4702 pm_stop(dev_info_t *dip)
4703 {
4704 PMD_FUNC(pmf, "stop")
4705 dev_info_t *pdip = ddi_get_parent(dip);
4706
4707 ASSERT(!PM_IAM_LOCKING_DIP(dip));
4708 /* stopping scan, destroy scan data structure */
4709 if (!PM_ISBC(dip)) {
4710 pm_scan_stop(dip);
4711 pm_scan_fini(dip);
4712 }
4713
4714 if (PM_GET_PM_INFO(dip) != NULL) {
4715 if (pm_unmanage(dip) == DDI_SUCCESS) {
4716 /*
4717 * Old style driver may have called
4718 * pm_destroy_components already, but just in case ...
4719 */
4720 e_pm_destroy_components(dip);
4721 } else {
4722 PMD(PMD_FAIL, ("%s: can't pm_unmanage %s@%s(%s#%d)\n",
4723 pmf, PM_DEVICE(dip)))
4724 }
4725 } else {
4726 if (PM_NUMCMPTS(dip))
4727 e_pm_destroy_components(dip);
4728 else {
4729 if (DEVI(dip)->devi_pm_flags & PMC_NOPMKID) {
4730 DEVI(dip)->devi_pm_flags &= ~PMC_NOPMKID;
4731 if (pdip && !PM_WANTS_NOTIFICATION(pdip)) {
4732 pm_rele_power(pdip);
4733 } else if (pdip &&
4734 MDI_VHCI(pdip) && MDI_CLIENT(dip)) {
4735 (void) mdi_power(pdip,
4736 MDI_PM_RELE_POWER,
4737 (void *)dip, NULL, 0);
4738 }
4739 }
4740 }
4741 }
4742 }
4743
4744 /*
4745 * The node is the subject of a reparse pm props ioctl. Throw away the old
4746 * info and start over.
4747 */
4748 int
e_new_pm_props(dev_info_t * dip)4749 e_new_pm_props(dev_info_t *dip)
4750 {
4751 if (PM_GET_PM_INFO(dip) != NULL) {
4752 pm_stop(dip);
4753
4754 if (e_pm_manage(dip, PM_STYLE_NEW) != DDI_SUCCESS) {
4755 return (DDI_FAILURE);
4756 }
4757 }
4758 e_pm_props(dip);
4759 return (DDI_SUCCESS);
4760 }
4761
4762 /*
4763 * Device has been attached, so process its pm properties
4764 */
4765 void
e_pm_props(dev_info_t * dip)4766 e_pm_props(dev_info_t *dip)
4767 {
4768 char *pp;
4769 int len;
4770 int flags = 0;
4771 int propflag = DDI_PROP_DONTPASS|DDI_PROP_CANSLEEP;
4772
4773 /*
4774 * It doesn't matter if we do this more than once, we should always
4775 * get the same answers, and if not, then the last one in is the
4776 * best one.
4777 */
4778 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, propflag, "pm-hardware-state",
4779 (caddr_t)&pp, &len) == DDI_PROP_SUCCESS) {
4780 if (strcmp(pp, "needs-suspend-resume") == 0) {
4781 flags = PMC_NEEDS_SR;
4782 } else if (strcmp(pp, "no-suspend-resume") == 0) {
4783 flags = PMC_NO_SR;
4784 } else if (strcmp(pp, "parental-suspend-resume") == 0) {
4785 flags = PMC_PARENTAL_SR;
4786 } else {
4787 cmn_err(CE_NOTE, "!device %s@%s has unrecognized "
4788 "%s property value '%s'", PM_NAME(dip),
4789 PM_ADDR(dip), "pm-hardware-state", pp);
4790 }
4791 kmem_free(pp, len);
4792 }
4793 /*
4794 * This next segment (PMC_WANTS_NOTIFY) is in
4795 * support of nexus drivers which will want to be involved in
4796 * (or at least notified of) their child node's power level transitions.
4797 * "pm-want-child-notification?" is defined by the parent.
4798 */
4799 if (ddi_prop_exists(DDI_DEV_T_ANY, dip, propflag,
4800 "pm-want-child-notification?") && PM_HAS_BUS_POWER(dip))
4801 flags |= PMC_WANTS_NOTIFY;
4802 ASSERT(PM_HAS_BUS_POWER(dip) || !ddi_prop_exists(DDI_DEV_T_ANY,
4803 dip, propflag, "pm-want-child-notification?"));
4804 if (ddi_prop_exists(DDI_DEV_T_ANY, dip, propflag,
4805 "no-involuntary-power-cycles"))
4806 flags |= PMC_NO_INVOL;
4807 /*
4808 * Is the device a CPU device?
4809 */
4810 if (ddi_getlongprop(DDI_DEV_T_ANY, dip, propflag, "pm-class",
4811 (caddr_t)&pp, &len) == DDI_PROP_SUCCESS) {
4812 if (strcmp(pp, "CPU") == 0) {
4813 flags |= PMC_CPU_DEVICE;
4814 } else {
4815 cmn_err(CE_NOTE, "!device %s@%s has unrecognized "
4816 "%s property value '%s'", PM_NAME(dip),
4817 PM_ADDR(dip), "pm-class", pp);
4818 }
4819 kmem_free(pp, len);
4820 }
4821 /* devfs single threads us */
4822 DEVI(dip)->devi_pm_flags |= flags;
4823 }
4824
4825 /*
4826 * This is the DDI_CTLOPS_POWER handler that is used when there is no ppm
4827 * driver which has claimed a node.
4828 * Sets old_power in arg struct.
4829 */
4830 static int
pm_default_ctlops(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t ctlop,void * arg,void * result)4831 pm_default_ctlops(dev_info_t *dip, dev_info_t *rdip,
4832 ddi_ctl_enum_t ctlop, void *arg, void *result)
4833 {
4834 _NOTE(ARGUNUSED(dip))
4835 PMD_FUNC(pmf, "ctlops")
4836 power_req_t *reqp = (power_req_t *)arg;
4837 int retval;
4838 dev_info_t *target_dip;
4839 int new_level, old_level, cmpt;
4840 #ifdef PMDDEBUG
4841 char *format;
4842 #endif
4843
4844 /*
4845 * The interface for doing the actual power level changes is now
4846 * through the DDI_CTLOPS_POWER bus_ctl, so that we can plug in
4847 * different platform-specific power control drivers.
4848 *
4849 * This driver implements the "default" version of this interface.
4850 * If no ppm driver has been installed then this interface is called
4851 * instead.
4852 */
4853 ASSERT(dip == NULL);
4854 switch (ctlop) {
4855 case DDI_CTLOPS_POWER:
4856 switch (reqp->request_type) {
4857 case PMR_PPM_SET_POWER:
4858 {
4859 target_dip = reqp->req.ppm_set_power_req.who;
4860 ASSERT(target_dip == rdip);
4861 new_level = reqp->req.ppm_set_power_req.new_level;
4862 cmpt = reqp->req.ppm_set_power_req.cmpt;
4863 /* pass back old power for the PM_LEVEL_UNKNOWN case */
4864 old_level = PM_CURPOWER(target_dip, cmpt);
4865 reqp->req.ppm_set_power_req.old_level = old_level;
4866 retval = pm_power(target_dip, cmpt, new_level);
4867 PMD(PMD_PPM, ("%s: PPM_SET_POWER %s@%s(%s#%d)[%d] %d->"
4868 "%d %s\n", pmf, PM_DEVICE(target_dip), cmpt,
4869 old_level, new_level, (retval == DDI_SUCCESS ?
4870 "chd" : "no chg")))
4871 return (retval);
4872 }
4873
4874 case PMR_PPM_PRE_DETACH:
4875 case PMR_PPM_POST_DETACH:
4876 case PMR_PPM_PRE_ATTACH:
4877 case PMR_PPM_POST_ATTACH:
4878 case PMR_PPM_PRE_PROBE:
4879 case PMR_PPM_POST_PROBE:
4880 case PMR_PPM_PRE_RESUME:
4881 case PMR_PPM_INIT_CHILD:
4882 case PMR_PPM_UNINIT_CHILD:
4883 #ifdef PMDDEBUG
4884 switch (reqp->request_type) {
4885 case PMR_PPM_PRE_DETACH:
4886 format = "%s: PMR_PPM_PRE_DETACH "
4887 "%s@%s(%s#%d)\n";
4888 break;
4889 case PMR_PPM_POST_DETACH:
4890 format = "%s: PMR_PPM_POST_DETACH "
4891 "%s@%s(%s#%d) rets %d\n";
4892 break;
4893 case PMR_PPM_PRE_ATTACH:
4894 format = "%s: PMR_PPM_PRE_ATTACH "
4895 "%s@%s(%s#%d)\n";
4896 break;
4897 case PMR_PPM_POST_ATTACH:
4898 format = "%s: PMR_PPM_POST_ATTACH "
4899 "%s@%s(%s#%d) rets %d\n";
4900 break;
4901 case PMR_PPM_PRE_PROBE:
4902 format = "%s: PMR_PPM_PRE_PROBE "
4903 "%s@%s(%s#%d)\n";
4904 break;
4905 case PMR_PPM_POST_PROBE:
4906 format = "%s: PMR_PPM_POST_PROBE "
4907 "%s@%s(%s#%d) rets %d\n";
4908 break;
4909 case PMR_PPM_PRE_RESUME:
4910 format = "%s: PMR_PPM_PRE_RESUME "
4911 "%s@%s(%s#%d) rets %d\n";
4912 break;
4913 case PMR_PPM_INIT_CHILD:
4914 format = "%s: PMR_PPM_INIT_CHILD "
4915 "%s@%s(%s#%d)\n";
4916 break;
4917 case PMR_PPM_UNINIT_CHILD:
4918 format = "%s: PMR_PPM_UNINIT_CHILD "
4919 "%s@%s(%s#%d)\n";
4920 break;
4921 default:
4922 break;
4923 }
4924 PMD(PMD_PPM, (format, pmf, PM_DEVICE(rdip),
4925 reqp->req.ppm_config_req.result))
4926 #endif
4927 return (DDI_SUCCESS);
4928
4929 case PMR_PPM_POWER_CHANGE_NOTIFY:
4930 /*
4931 * Nothing for us to do
4932 */
4933 ASSERT(reqp->req.ppm_notify_level_req.who == rdip);
4934 PMD(PMD_PPM, ("%s: PMR_PPM_POWER_CHANGE_NOTIFY "
4935 "%s@%s(%s#%d)[%d] %d->%d\n", pmf,
4936 PM_DEVICE(reqp->req.ppm_notify_level_req.who),
4937 reqp->req.ppm_notify_level_req.cmpt,
4938 PM_CURPOWER(reqp->req.ppm_notify_level_req.who,
4939 reqp->req.ppm_notify_level_req.cmpt),
4940 reqp->req.ppm_notify_level_req.new_level))
4941 return (DDI_SUCCESS);
4942
4943 case PMR_PPM_UNMANAGE:
4944 PMD(PMD_PPM, ("%s: PMR_PPM_UNMANAGE %s@%s(%s#%d)\n",
4945 pmf, PM_DEVICE(rdip)))
4946 return (DDI_SUCCESS);
4947
4948 case PMR_PPM_LOCK_POWER:
4949 pm_lock_power_single(reqp->req.ppm_lock_power_req.who,
4950 reqp->req.ppm_lock_power_req.circp);
4951 return (DDI_SUCCESS);
4952
4953 case PMR_PPM_UNLOCK_POWER:
4954 pm_unlock_power_single(
4955 reqp->req.ppm_unlock_power_req.who,
4956 reqp->req.ppm_unlock_power_req.circ);
4957 return (DDI_SUCCESS);
4958
4959 case PMR_PPM_TRY_LOCK_POWER:
4960 *(int *)result = pm_try_locking_power_single(
4961 reqp->req.ppm_lock_power_req.who,
4962 reqp->req.ppm_lock_power_req.circp);
4963 return (DDI_SUCCESS);
4964
4965 case PMR_PPM_POWER_LOCK_OWNER:
4966 target_dip = reqp->req.ppm_power_lock_owner_req.who;
4967 ASSERT(target_dip == rdip);
4968 reqp->req.ppm_power_lock_owner_req.owner =
4969 DEVI(rdip)->devi_busy_thread;
4970 return (DDI_SUCCESS);
4971 default:
4972 PMD(PMD_ERROR, ("%s: default!\n", pmf))
4973 return (DDI_FAILURE);
4974 }
4975
4976 default:
4977 PMD(PMD_ERROR, ("%s: unknown\n", pmf))
4978 return (DDI_FAILURE);
4979 }
4980 }
4981
4982 /*
4983 * We overload the bus_ctl ops here--perhaps we ought to have a distinct
4984 * power_ops struct for this functionality instead?
4985 * However, we only ever do this on a ppm driver.
4986 */
4987 int
pm_ctlops(dev_info_t * d,dev_info_t * r,ddi_ctl_enum_t op,void * a,void * v)4988 pm_ctlops(dev_info_t *d, dev_info_t *r, ddi_ctl_enum_t op, void *a, void *v)
4989 {
4990 int (*fp)();
4991
4992 /* if no ppm handler, call the default routine */
4993 if (d == NULL) {
4994 return (pm_default_ctlops(d, r, op, a, v));
4995 }
4996 if (!d || !r)
4997 return (DDI_FAILURE);
4998 ASSERT(DEVI(d)->devi_ops && DEVI(d)->devi_ops->devo_bus_ops &&
4999 DEVI(d)->devi_ops->devo_bus_ops->bus_ctl);
5000
5001 fp = DEVI(d)->devi_ops->devo_bus_ops->bus_ctl;
5002 return ((*fp)(d, r, op, a, v));
5003 }
5004
5005 /*
5006 * Called on a node when attach completes or the driver makes its first pm
5007 * call (whichever comes first).
5008 * In the attach case, device may not be power manageable at all.
5009 * Don't need to lock the dip because we're single threaded by the devfs code
5010 */
5011 static int
pm_start(dev_info_t * dip)5012 pm_start(dev_info_t *dip)
5013 {
5014 PMD_FUNC(pmf, "start")
5015 int ret;
5016 dev_info_t *pdip = ddi_get_parent(dip);
5017 int e_pm_manage(dev_info_t *, int);
5018 void pm_noinvol_specd(dev_info_t *dip);
5019
5020 e_pm_props(dip);
5021 pm_noinvol_specd(dip);
5022 /*
5023 * If this dip has already been processed, don't mess with it
5024 * (but decrement the speculative count we did above, as whatever
5025 * code put it under pm already will have dealt with it)
5026 */
5027 if (PM_GET_PM_INFO(dip)) {
5028 PMD(PMD_KIDSUP, ("%s: pm already done for %s@%s(%s#%d)\n",
5029 pmf, PM_DEVICE(dip)))
5030 return (0);
5031 }
5032 ret = e_pm_manage(dip, PM_STYLE_UNKNOWN);
5033
5034 if (PM_GET_PM_INFO(dip) == NULL) {
5035 /*
5036 * keep the kidsupcount increment as is
5037 */
5038 DEVI(dip)->devi_pm_flags |= PMC_NOPMKID;
5039 if (pdip && !PM_WANTS_NOTIFICATION(pdip)) {
5040 pm_hold_power(pdip);
5041 } else if (pdip && MDI_VHCI(pdip) && MDI_CLIENT(dip)) {
5042 (void) mdi_power(pdip, MDI_PM_HOLD_POWER,
5043 (void *)dip, NULL, 0);
5044 }
5045
5046 PMD(PMD_KIDSUP, ("%s: pm of %s@%s(%s#%d) failed, parent "
5047 "left up\n", pmf, PM_DEVICE(dip)))
5048 }
5049
5050 return (ret);
5051 }
5052
5053 /*
5054 * Keep a list of recorded thresholds. For now we just keep a list and
5055 * search it linearly. We don't expect too many entries. Can always hash it
5056 * later if we need to.
5057 */
5058 void
pm_record_thresh(pm_thresh_rec_t * rp)5059 pm_record_thresh(pm_thresh_rec_t *rp)
5060 {
5061 pm_thresh_rec_t *pptr, *ptr;
5062
5063 ASSERT(*rp->ptr_physpath);
5064 rw_enter(&pm_thresh_rwlock, RW_WRITER);
5065 for (pptr = NULL, ptr = pm_thresh_head;
5066 ptr; pptr = ptr, ptr = ptr->ptr_next) {
5067 if (strcmp(rp->ptr_physpath, ptr->ptr_physpath) == 0) {
5068 /* replace this one */
5069 rp->ptr_next = ptr->ptr_next;
5070 if (pptr) {
5071 pptr->ptr_next = rp;
5072 } else {
5073 pm_thresh_head = rp;
5074 }
5075 rw_exit(&pm_thresh_rwlock);
5076 kmem_free(ptr, ptr->ptr_size);
5077 return;
5078 }
5079 continue;
5080 }
5081 /*
5082 * There was not a match in the list, insert this one in front
5083 */
5084 if (pm_thresh_head) {
5085 rp->ptr_next = pm_thresh_head;
5086 pm_thresh_head = rp;
5087 } else {
5088 rp->ptr_next = NULL;
5089 pm_thresh_head = rp;
5090 }
5091 rw_exit(&pm_thresh_rwlock);
5092 }
5093
5094 /*
5095 * Create a new dependency record and hang a new dependency entry off of it
5096 */
5097 pm_pdr_t *
newpdr(char * kept,char * keeps,int isprop)5098 newpdr(char *kept, char *keeps, int isprop)
5099 {
5100 size_t size = strlen(kept) + strlen(keeps) + 2 + sizeof (pm_pdr_t);
5101 pm_pdr_t *p = kmem_zalloc(size, KM_SLEEP);
5102 p->pdr_size = size;
5103 p->pdr_isprop = isprop;
5104 p->pdr_kept_paths = NULL;
5105 p->pdr_kept_count = 0;
5106 p->pdr_kept = (char *)((intptr_t)p + sizeof (pm_pdr_t));
5107 (void) strcpy(p->pdr_kept, kept);
5108 p->pdr_keeper = (char *)((intptr_t)p->pdr_kept + strlen(kept) + 1);
5109 (void) strcpy(p->pdr_keeper, keeps);
5110 ASSERT((intptr_t)p->pdr_keeper + strlen(p->pdr_keeper) + 1 <=
5111 (intptr_t)p + size);
5112 ASSERT((intptr_t)p->pdr_kept + strlen(p->pdr_kept) + 1 <=
5113 (intptr_t)p + size);
5114 return (p);
5115 }
5116
5117 /*
5118 * Keep a list of recorded dependencies. We only keep the
5119 * keeper -> kept list for simplification. At this point We do not
5120 * care about whether the devices are attached or not yet,
5121 * this would be done in pm_keeper() and pm_kept().
5122 * If a PM_RESET_PM happens, then we tear down and forget the dependencies,
5123 * and it is up to the user to issue the ioctl again if they want it
5124 * (e.g. pmconfig)
5125 * Returns true if dependency already exists in the list.
5126 */
5127 int
pm_record_keeper(char * kept,char * keeper,int isprop)5128 pm_record_keeper(char *kept, char *keeper, int isprop)
5129 {
5130 PMD_FUNC(pmf, "record_keeper")
5131 pm_pdr_t *npdr, *ppdr, *pdr;
5132
5133 PMD(PMD_KEEPS, ("%s: %s, %s\n", pmf, kept, keeper))
5134 ASSERT(kept && keeper);
5135 #ifdef DEBUG
5136 if (pm_debug & PMD_KEEPS)
5137 prdeps("pm_record_keeper entry");
5138 #endif
5139 for (ppdr = NULL, pdr = pm_dep_head; pdr;
5140 ppdr = pdr, pdr = pdr->pdr_next) {
5141 PMD(PMD_KEEPS, ("%s: check %s, %s\n", pmf, pdr->pdr_kept,
5142 pdr->pdr_keeper))
5143 if (strcmp(kept, pdr->pdr_kept) == 0 &&
5144 strcmp(keeper, pdr->pdr_keeper) == 0) {
5145 PMD(PMD_KEEPS, ("%s: match\n", pmf))
5146 return (1);
5147 }
5148 }
5149 /*
5150 * We did not find any match, so we have to make an entry
5151 */
5152 npdr = newpdr(kept, keeper, isprop);
5153 if (ppdr) {
5154 ASSERT(ppdr->pdr_next == NULL);
5155 ppdr->pdr_next = npdr;
5156 } else {
5157 ASSERT(pm_dep_head == NULL);
5158 pm_dep_head = npdr;
5159 }
5160 #ifdef DEBUG
5161 if (pm_debug & PMD_KEEPS)
5162 prdeps("pm_record_keeper after new record");
5163 #endif
5164 if (!isprop)
5165 pm_unresolved_deps++;
5166 else
5167 pm_prop_deps++;
5168 return (0);
5169 }
5170
5171 /*
5172 * Look up this device in the set of devices we've seen ioctls for
5173 * to see if we are holding a threshold spec for it. If so, make it so.
5174 * At ioctl time, we were given the physical path of the device.
5175 */
5176 int
pm_thresh_specd(dev_info_t * dip)5177 pm_thresh_specd(dev_info_t *dip)
5178 {
5179 void pm_apply_recorded_thresh(dev_info_t *, pm_thresh_rec_t *);
5180 char *path = 0;
5181 char pathbuf[MAXNAMELEN];
5182 pm_thresh_rec_t *rp;
5183
5184 path = ddi_pathname(dip, pathbuf);
5185
5186 rw_enter(&pm_thresh_rwlock, RW_READER);
5187 for (rp = pm_thresh_head; rp; rp = rp->ptr_next) {
5188 if (strcmp(rp->ptr_physpath, path) != 0)
5189 continue;
5190 pm_apply_recorded_thresh(dip, rp);
5191 rw_exit(&pm_thresh_rwlock);
5192 return (1);
5193 }
5194 rw_exit(&pm_thresh_rwlock);
5195 return (0);
5196 }
5197
5198 static int
pm_set_keeping(dev_info_t * keeper,dev_info_t * kept)5199 pm_set_keeping(dev_info_t *keeper, dev_info_t *kept)
5200 {
5201 PMD_FUNC(pmf, "set_keeping")
5202 int j, up = 0, circ;
5203 void prdeps(char *);
5204
5205 PMD(PMD_KEEPS, ("%s: keeper=%s@%s(%s#%d), kept=%s@%s(%s#%d)\n", pmf,
5206 PM_DEVICE(keeper), PM_DEVICE(kept)))
5207 #ifdef DEBUG
5208 if (pm_debug & PMD_KEEPS)
5209 prdeps("Before PAD\n");
5210 #endif
5211 ASSERT(keeper != kept);
5212 if (PM_GET_PM_INFO(keeper) == NULL) {
5213 cmn_err(CE_CONT, "!device %s@%s(%s#%d) keeps up device "
5214 "%s@%s(%s#%d), but the former is not power managed",
5215 PM_DEVICE(keeper), PM_DEVICE(kept));
5216 PMD((PMD_FAIL | PMD_KEEPS), ("%s: keeper %s@%s(%s#%d) is not"
5217 "power managed\n", pmf, PM_DEVICE(keeper)))
5218 return (0);
5219 }
5220 if (PM_GET_PM_INFO(kept) == NULL) {
5221 cmn_err(CE_CONT, "!device %s@%s(%s#%d) keeps up device "
5222 "%s@%s(%s#%d), but the latter is not power managed",
5223 PM_DEVICE(keeper), PM_DEVICE(kept));
5224 PMD((PMD_FAIL | PMD_KEEPS), ("%s: kept %s@%s(%s#%d) is not"
5225 "power managed\n", pmf, PM_DEVICE(kept)))
5226 return (0);
5227 }
5228
5229 PM_LOCK_POWER(keeper, &circ);
5230 for (j = 0; j < PM_NUMCMPTS(keeper); j++) {
5231 if (PM_CURPOWER(keeper, j)) {
5232 up++;
5233 break;
5234 }
5235 }
5236 if (up) {
5237 /* Bringup and maintain a hold on the kept */
5238 PMD(PMD_KEEPS, ("%s: place a hold on kept %s@%s(%s#%d)\n", pmf,
5239 PM_DEVICE(kept)))
5240 bring_pmdep_up(kept, 1);
5241 }
5242 PM_UNLOCK_POWER(keeper, circ);
5243 #ifdef DEBUG
5244 if (pm_debug & PMD_KEEPS)
5245 prdeps("After PAD\n");
5246 #endif
5247 return (1);
5248 }
5249
5250 /*
5251 * Should this device keep up another device?
5252 * Look up this device in the set of devices we've seen ioctls for
5253 * to see if we are holding a dependency spec for it. If so, make it so.
5254 * Because we require the kept device to be attached already in order to
5255 * make the list entry (and hold it), we only need to look for keepers.
5256 * At ioctl time, we were given the physical path of the device.
5257 */
5258 int
pm_keeper(char * keeper)5259 pm_keeper(char *keeper)
5260 {
5261 PMD_FUNC(pmf, "keeper")
5262 int pm_apply_recorded_dep(dev_info_t *, pm_pdr_t *);
5263 dev_info_t *dip;
5264 pm_pdr_t *dp;
5265 dev_info_t *kept = NULL;
5266 int ret = 0;
5267 int i;
5268
5269 if (!pm_unresolved_deps && !pm_prop_deps)
5270 return (0);
5271 ASSERT(keeper != NULL);
5272 dip = pm_name_to_dip(keeper, 1);
5273 if (dip == NULL)
5274 return (0);
5275 PMD(PMD_KEEPS, ("%s: keeper=%s\n", pmf, keeper))
5276 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
5277 if (!dp->pdr_isprop) {
5278 if (!pm_unresolved_deps)
5279 continue;
5280 PMD(PMD_KEEPS, ("%s: keeper %s\n", pmf, dp->pdr_keeper))
5281 if (dp->pdr_satisfied) {
5282 PMD(PMD_KEEPS, ("%s: satisfied\n", pmf))
5283 continue;
5284 }
5285 if (strcmp(dp->pdr_keeper, keeper) == 0) {
5286 ret += pm_apply_recorded_dep(dip, dp);
5287 }
5288 } else {
5289 if (strcmp(dp->pdr_keeper, keeper) != 0)
5290 continue;
5291 for (i = 0; i < dp->pdr_kept_count; i++) {
5292 if (dp->pdr_kept_paths[i] == NULL)
5293 continue;
5294 kept = pm_name_to_dip(dp->pdr_kept_paths[i], 1);
5295 if (kept == NULL)
5296 continue;
5297 ASSERT(ddi_prop_exists(DDI_DEV_T_ANY, kept,
5298 DDI_PROP_DONTPASS, dp->pdr_kept));
5299 PMD(PMD_KEEPS, ("%s: keeper=%s@%s(%s#%d), "
5300 "kept=%s@%s(%s#%d) keptcnt=%d\n",
5301 pmf, PM_DEVICE(dip), PM_DEVICE(kept),
5302 dp->pdr_kept_count))
5303 if (kept != dip) {
5304 ret += pm_set_keeping(dip, kept);
5305 }
5306 ddi_release_devi(kept);
5307 }
5308
5309 }
5310 }
5311 ddi_release_devi(dip);
5312 return (ret);
5313 }
5314
5315 /*
5316 * Should this device be kept up by another device?
5317 * Look up all dependency recorded from PM_ADD_DEPENDENT and
5318 * PM_ADD_DEPENDENT_PROPERTY ioctls. Record down on the keeper's
5319 * kept device lists.
5320 */
5321 static int
pm_kept(char * keptp)5322 pm_kept(char *keptp)
5323 {
5324 PMD_FUNC(pmf, "kept")
5325 pm_pdr_t *dp;
5326 int found = 0;
5327 int ret = 0;
5328 dev_info_t *keeper;
5329 dev_info_t *kept;
5330 size_t length;
5331 int i;
5332 char **paths;
5333 char *path;
5334
5335 ASSERT(keptp != NULL);
5336 kept = pm_name_to_dip(keptp, 1);
5337 if (kept == NULL)
5338 return (0);
5339 PMD(PMD_KEEPS, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(kept)))
5340 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
5341 if (dp->pdr_isprop) {
5342 PMD(PMD_KEEPS, ("%s: property %s\n", pmf, dp->pdr_kept))
5343 if (ddi_prop_exists(DDI_DEV_T_ANY, kept,
5344 DDI_PROP_DONTPASS, dp->pdr_kept)) {
5345 /*
5346 * Dont allow self dependency.
5347 */
5348 if (strcmp(dp->pdr_keeper, keptp) == 0)
5349 continue;
5350 keeper = pm_name_to_dip(dp->pdr_keeper, 1);
5351 if (keeper == NULL)
5352 continue;
5353 PMD(PMD_KEEPS, ("%s: adding to kepts path list "
5354 "%p\n", pmf, (void *)kept))
5355 #ifdef DEBUG
5356 if (pm_debug & PMD_DEP)
5357 prdeps("Before Adding from pm_kept\n");
5358 #endif
5359 /*
5360 * Add ourselves to the dip list.
5361 */
5362 if (dp->pdr_kept_count == 0) {
5363 length = strlen(keptp) + 1;
5364 path =
5365 kmem_alloc(length, KM_SLEEP);
5366 paths = kmem_alloc(sizeof (char **),
5367 KM_SLEEP);
5368 (void) strcpy(path, keptp);
5369 paths[0] = path;
5370 dp->pdr_kept_paths = paths;
5371 dp->pdr_kept_count++;
5372 } else {
5373 /* Check to see if already on list */
5374 for (i = 0; i < dp->pdr_kept_count;
5375 i++) {
5376 if (strcmp(keptp,
5377 dp->pdr_kept_paths[i])
5378 == 0) {
5379 found++;
5380 break;
5381 }
5382 }
5383 if (found) {
5384 ddi_release_devi(keeper);
5385 continue;
5386 }
5387 length = dp->pdr_kept_count *
5388 sizeof (char **);
5389 paths = kmem_alloc(
5390 length + sizeof (char **),
5391 KM_SLEEP);
5392 if (dp->pdr_kept_count) {
5393 bcopy(dp->pdr_kept_paths,
5394 paths, length);
5395 kmem_free(dp->pdr_kept_paths,
5396 length);
5397 }
5398 dp->pdr_kept_paths = paths;
5399 length = strlen(keptp) + 1;
5400 path =
5401 kmem_alloc(length, KM_SLEEP);
5402 (void) strcpy(path, keptp);
5403 dp->pdr_kept_paths[i] = path;
5404 dp->pdr_kept_count++;
5405 }
5406 #ifdef DEBUG
5407 if (pm_debug & PMD_DEP)
5408 prdeps("After from pm_kept\n");
5409 #endif
5410 if (keeper) {
5411 ret += pm_set_keeping(keeper, kept);
5412 ddi_release_devi(keeper);
5413 }
5414 }
5415 } else {
5416 /*
5417 * pm_keeper would be called later to do
5418 * the actual pm_set_keeping.
5419 */
5420 PMD(PMD_KEEPS, ("%s: adding to kepts path list %p\n",
5421 pmf, (void *)kept))
5422 #ifdef DEBUG
5423 if (pm_debug & PMD_DEP)
5424 prdeps("Before Adding from pm_kept\n");
5425 #endif
5426 if (strcmp(keptp, dp->pdr_kept) == 0) {
5427 if (dp->pdr_kept_paths == NULL) {
5428 length = strlen(keptp) + 1;
5429 path =
5430 kmem_alloc(length, KM_SLEEP);
5431 paths = kmem_alloc(sizeof (char **),
5432 KM_SLEEP);
5433 (void) strcpy(path, keptp);
5434 paths[0] = path;
5435 dp->pdr_kept_paths = paths;
5436 dp->pdr_kept_count++;
5437 }
5438 }
5439 #ifdef DEBUG
5440 if (pm_debug & PMD_DEP)
5441 prdeps("After from pm_kept\n");
5442 #endif
5443 }
5444 }
5445 ddi_release_devi(kept);
5446 return (ret);
5447 }
5448
5449 /*
5450 * Apply a recorded dependency. dp specifies the dependency, and
5451 * keeper is already known to be the device that keeps up the other (kept) one.
5452 * We have to the whole tree for the "kept" device, then apply
5453 * the dependency (which may already be applied).
5454 */
5455 int
pm_apply_recorded_dep(dev_info_t * keeper,pm_pdr_t * dp)5456 pm_apply_recorded_dep(dev_info_t *keeper, pm_pdr_t *dp)
5457 {
5458 PMD_FUNC(pmf, "apply_recorded_dep")
5459 dev_info_t *kept = NULL;
5460 int ret = 0;
5461 char *keptp = NULL;
5462
5463 /*
5464 * Device to Device dependency can only be 1 to 1.
5465 */
5466 if (dp->pdr_kept_paths == NULL)
5467 return (0);
5468 keptp = dp->pdr_kept_paths[0];
5469 if (keptp == NULL)
5470 return (0);
5471 ASSERT(*keptp != '\0');
5472 kept = pm_name_to_dip(keptp, 1);
5473 if (kept == NULL)
5474 return (0);
5475 if (kept) {
5476 PMD(PMD_KEEPS, ("%s: keeper=%s, kept=%s\n", pmf,
5477 dp->pdr_keeper, keptp))
5478 if (pm_set_keeping(keeper, kept)) {
5479 ASSERT(dp->pdr_satisfied == 0);
5480 dp->pdr_satisfied = 1;
5481 ASSERT(pm_unresolved_deps);
5482 pm_unresolved_deps--;
5483 ret++;
5484 }
5485 }
5486 ddi_release_devi(kept);
5487
5488 return (ret);
5489 }
5490
5491 /*
5492 * Called from common/io/pm.c
5493 */
5494 int
pm_cur_power(pm_component_t * cp)5495 pm_cur_power(pm_component_t *cp)
5496 {
5497 return (cur_power(cp));
5498 }
5499
5500 /*
5501 * External interface to sanity-check a power level.
5502 */
5503 int
pm_valid_power(dev_info_t * dip,int comp,int level)5504 pm_valid_power(dev_info_t *dip, int comp, int level)
5505 {
5506 PMD_FUNC(pmf, "valid_power")
5507
5508 if (comp >= 0 && comp < PM_NUMCMPTS(dip) && level >= 0)
5509 return (e_pm_valid_power(dip, comp, level));
5510 else {
5511 PMD(PMD_FAIL, ("%s: comp=%d, ncomp=%d, level=%d\n",
5512 pmf, comp, PM_NUMCMPTS(dip), level))
5513 return (0);
5514 }
5515 }
5516
5517 /*
5518 * Called when a device that is direct power managed needs to change state.
5519 * This routine arranges to block the request until the process managing
5520 * the device makes the change (or some other incompatible change) or
5521 * the process closes /dev/pm.
5522 */
5523 static int
pm_block(dev_info_t * dip,int comp,int newpower,int oldpower)5524 pm_block(dev_info_t *dip, int comp, int newpower, int oldpower)
5525 {
5526 pm_rsvp_t *new = kmem_zalloc(sizeof (*new), KM_SLEEP);
5527 int ret = 0;
5528 void pm_dequeue_blocked(pm_rsvp_t *);
5529 void pm_enqueue_blocked(pm_rsvp_t *);
5530
5531 ASSERT(!pm_processes_stopped);
5532 ASSERT(PM_IAM_LOCKING_DIP(dip));
5533 new->pr_dip = dip;
5534 new->pr_comp = comp;
5535 new->pr_newlevel = newpower;
5536 new->pr_oldlevel = oldpower;
5537 cv_init(&new->pr_cv, NULL, CV_DEFAULT, NULL);
5538 mutex_enter(&pm_rsvp_lock);
5539 pm_enqueue_blocked(new);
5540 pm_enqueue_notify(PSC_PENDING_CHANGE, dip, comp, newpower, oldpower,
5541 PM_CANBLOCK_BLOCK);
5542 PM_UNLOCK_DIP(dip);
5543 /*
5544 * truss may make the cv_wait_sig return prematurely
5545 */
5546 while (ret == 0) {
5547 /*
5548 * Normally there will be no user context involved, but if
5549 * there is (e.g. we are here via an ioctl call to a driver)
5550 * then we should allow the process to abort the request,
5551 * or we get an unkillable process if the same thread does
5552 * PM_DIRECT_PM and pm_raise_power
5553 */
5554 if (cv_wait_sig(&new->pr_cv, &pm_rsvp_lock) == 0) {
5555 ret = PMP_FAIL;
5556 } else {
5557 ret = new->pr_retval;
5558 }
5559 }
5560 pm_dequeue_blocked(new);
5561 mutex_exit(&pm_rsvp_lock);
5562 cv_destroy(&new->pr_cv);
5563 kmem_free(new, sizeof (*new));
5564 return (ret);
5565 }
5566
5567 /*
5568 * Returns true if the process is interested in power level changes (has issued
5569 * PM_GET_STATE_CHANGE ioctl).
5570 */
5571 int
pm_interest_registered(int clone)5572 pm_interest_registered(int clone)
5573 {
5574 ASSERT(clone >= 0 && clone < PM_MAX_CLONE - 1);
5575 return (pm_interest[clone]);
5576 }
5577
5578 static void pm_enqueue_pscc(pscc_t *, pscc_t **);
5579
5580 /*
5581 * Process with clone has just done PM_DIRECT_PM on dip, or has asked to
5582 * watch all state transitions (dip == NULL). Set up data
5583 * structs to communicate with process about state changes.
5584 */
5585 void
pm_register_watcher(int clone,dev_info_t * dip)5586 pm_register_watcher(int clone, dev_info_t *dip)
5587 {
5588 pscc_t *p;
5589 psce_t *psce;
5590
5591 /*
5592 * We definitely need a control struct, then we have to search to see
5593 * there is already an entries struct (in the dip != NULL case).
5594 */
5595 pscc_t *pscc = kmem_zalloc(sizeof (*pscc), KM_SLEEP);
5596 pscc->pscc_clone = clone;
5597 pscc->pscc_dip = dip;
5598
5599 if (dip) {
5600 int found = 0;
5601 rw_enter(&pm_pscc_direct_rwlock, RW_WRITER);
5602 for (p = pm_pscc_direct; p; p = p->pscc_next) {
5603 /*
5604 * Already an entry for this clone, so just use it
5605 * for the new one (for the case where a single
5606 * process is watching multiple devices)
5607 */
5608 if (p->pscc_clone == clone) {
5609 pscc->pscc_entries = p->pscc_entries;
5610 pscc->pscc_entries->psce_references++;
5611 found++;
5612 break;
5613 }
5614 }
5615 if (!found) { /* create a new one */
5616 psce = kmem_zalloc(sizeof (psce_t), KM_SLEEP);
5617 mutex_init(&psce->psce_lock, NULL, MUTEX_DEFAULT, NULL);
5618 psce->psce_first =
5619 kmem_zalloc(sizeof (pm_state_change_t) * PSCCOUNT,
5620 KM_SLEEP);
5621 psce->psce_in = psce->psce_out = psce->psce_first;
5622 psce->psce_last = &psce->psce_first[PSCCOUNT - 1];
5623 psce->psce_references = 1;
5624 pscc->pscc_entries = psce;
5625 }
5626 pm_enqueue_pscc(pscc, &pm_pscc_direct);
5627 rw_exit(&pm_pscc_direct_rwlock);
5628 } else {
5629 ASSERT(!pm_interest_registered(clone));
5630 rw_enter(&pm_pscc_interest_rwlock, RW_WRITER);
5631 #ifdef DEBUG
5632 for (p = pm_pscc_interest; p; p = p->pscc_next) {
5633 /*
5634 * Should not be an entry for this clone!
5635 */
5636 ASSERT(p->pscc_clone != clone);
5637 }
5638 #endif
5639 psce = kmem_zalloc(sizeof (psce_t), KM_SLEEP);
5640 psce->psce_first = kmem_zalloc(sizeof (pm_state_change_t) *
5641 PSCCOUNT, KM_SLEEP);
5642 psce->psce_in = psce->psce_out = psce->psce_first;
5643 psce->psce_last = &psce->psce_first[PSCCOUNT - 1];
5644 psce->psce_references = 1;
5645 pscc->pscc_entries = psce;
5646 pm_enqueue_pscc(pscc, &pm_pscc_interest);
5647 pm_interest[clone] = 1;
5648 rw_exit(&pm_pscc_interest_rwlock);
5649 }
5650 }
5651
5652 /*
5653 * Remove the given entry from the blocked list
5654 */
5655 void
pm_dequeue_blocked(pm_rsvp_t * p)5656 pm_dequeue_blocked(pm_rsvp_t *p)
5657 {
5658 ASSERT(MUTEX_HELD(&pm_rsvp_lock));
5659 if (pm_blocked_list == p) {
5660 ASSERT(p->pr_prev == NULL);
5661 if (p->pr_next != NULL)
5662 p->pr_next->pr_prev = NULL;
5663 pm_blocked_list = p->pr_next;
5664 } else {
5665 ASSERT(p->pr_prev != NULL);
5666 p->pr_prev->pr_next = p->pr_next;
5667 if (p->pr_next != NULL)
5668 p->pr_next->pr_prev = p->pr_prev;
5669 }
5670 }
5671
5672 /*
5673 * Remove the given control struct from the given list
5674 */
5675 static void
pm_dequeue_pscc(pscc_t * p,pscc_t ** list)5676 pm_dequeue_pscc(pscc_t *p, pscc_t **list)
5677 {
5678 if (*list == p) {
5679 ASSERT(p->pscc_prev == NULL);
5680 if (p->pscc_next != NULL)
5681 p->pscc_next->pscc_prev = NULL;
5682 *list = p->pscc_next;
5683 } else {
5684 ASSERT(p->pscc_prev != NULL);
5685 p->pscc_prev->pscc_next = p->pscc_next;
5686 if (p->pscc_next != NULL)
5687 p->pscc_next->pscc_prev = p->pscc_prev;
5688 }
5689 }
5690
5691 /*
5692 * Stick the control struct specified on the front of the list
5693 */
5694 static void
pm_enqueue_pscc(pscc_t * p,pscc_t ** list)5695 pm_enqueue_pscc(pscc_t *p, pscc_t **list)
5696 {
5697 pscc_t *h; /* entry at head of list */
5698 if ((h = *list) == NULL) {
5699 *list = p;
5700 ASSERT(p->pscc_next == NULL);
5701 ASSERT(p->pscc_prev == NULL);
5702 } else {
5703 p->pscc_next = h;
5704 ASSERT(h->pscc_prev == NULL);
5705 h->pscc_prev = p;
5706 ASSERT(p->pscc_prev == NULL);
5707 *list = p;
5708 }
5709 }
5710
5711 /*
5712 * If dip is NULL, process is closing "clone" clean up all its registrations.
5713 * Otherwise only clean up those for dip because process is just giving up
5714 * control of a direct device.
5715 */
5716 void
pm_deregister_watcher(int clone,dev_info_t * dip)5717 pm_deregister_watcher(int clone, dev_info_t *dip)
5718 {
5719 pscc_t *p, *pn;
5720 psce_t *psce;
5721 int found = 0;
5722
5723 if (dip == NULL) {
5724 rw_enter(&pm_pscc_interest_rwlock, RW_WRITER);
5725 for (p = pm_pscc_interest; p; p = pn) {
5726 pn = p->pscc_next;
5727 if (p->pscc_clone == clone) {
5728 pm_dequeue_pscc(p, &pm_pscc_interest);
5729 psce = p->pscc_entries;
5730 ASSERT(psce->psce_references == 1);
5731 mutex_destroy(&psce->psce_lock);
5732 kmem_free(psce->psce_first,
5733 sizeof (pm_state_change_t) * PSCCOUNT);
5734 kmem_free(psce, sizeof (*psce));
5735 kmem_free(p, sizeof (*p));
5736 }
5737 }
5738 pm_interest[clone] = 0;
5739 rw_exit(&pm_pscc_interest_rwlock);
5740 }
5741 found = 0;
5742 rw_enter(&pm_pscc_direct_rwlock, RW_WRITER);
5743 for (p = pm_pscc_direct; p; p = pn) {
5744 pn = p->pscc_next;
5745 if ((dip && p->pscc_dip == dip) ||
5746 (dip == NULL && clone == p->pscc_clone)) {
5747 ASSERT(clone == p->pscc_clone);
5748 found++;
5749 /*
5750 * Remove from control list
5751 */
5752 pm_dequeue_pscc(p, &pm_pscc_direct);
5753 /*
5754 * If we're the last reference, free the
5755 * entries struct.
5756 */
5757 psce = p->pscc_entries;
5758 ASSERT(psce);
5759 if (psce->psce_references == 1) {
5760 kmem_free(psce->psce_first,
5761 PSCCOUNT * sizeof (pm_state_change_t));
5762 kmem_free(psce, sizeof (*psce));
5763 } else {
5764 psce->psce_references--;
5765 }
5766 kmem_free(p, sizeof (*p));
5767 }
5768 }
5769 ASSERT(dip == NULL || found);
5770 rw_exit(&pm_pscc_direct_rwlock);
5771 }
5772
5773 /*
5774 * Search the indicated list for an entry that matches clone, and return a
5775 * pointer to it. To be interesting, the entry must have something ready to
5776 * be passed up to the controlling process.
5777 * The returned entry will be locked upon return from this call.
5778 */
5779 static psce_t *
pm_psc_find_clone(int clone,pscc_t ** list,krwlock_t * lock)5780 pm_psc_find_clone(int clone, pscc_t **list, krwlock_t *lock)
5781 {
5782 pscc_t *p;
5783 psce_t *psce;
5784 rw_enter(lock, RW_READER);
5785 for (p = *list; p; p = p->pscc_next) {
5786 if (clone == p->pscc_clone) {
5787 psce = p->pscc_entries;
5788 mutex_enter(&psce->psce_lock);
5789 if (psce->psce_out->size) {
5790 rw_exit(lock);
5791 return (psce);
5792 } else {
5793 mutex_exit(&psce->psce_lock);
5794 }
5795 }
5796 }
5797 rw_exit(lock);
5798 return (NULL);
5799 }
5800
5801 static psce_t *pm_psc_find_clone(int, pscc_t **, krwlock_t *);
5802 /*
5803 * Find an entry for a particular clone in the direct list.
5804 */
5805 psce_t *
pm_psc_clone_to_direct(int clone)5806 pm_psc_clone_to_direct(int clone)
5807 {
5808 return (pm_psc_find_clone(clone, &pm_pscc_direct,
5809 &pm_pscc_direct_rwlock));
5810 }
5811
5812 /*
5813 * Find an entry for a particular clone in the interest list.
5814 */
5815 psce_t *
pm_psc_clone_to_interest(int clone)5816 pm_psc_clone_to_interest(int clone)
5817 {
5818 return (pm_psc_find_clone(clone, &pm_pscc_interest,
5819 &pm_pscc_interest_rwlock));
5820 }
5821
5822 /*
5823 * Put the given entry at the head of the blocked list
5824 */
5825 void
pm_enqueue_blocked(pm_rsvp_t * p)5826 pm_enqueue_blocked(pm_rsvp_t *p)
5827 {
5828 ASSERT(MUTEX_HELD(&pm_rsvp_lock));
5829 ASSERT(p->pr_next == NULL);
5830 ASSERT(p->pr_prev == NULL);
5831 if (pm_blocked_list != NULL) {
5832 p->pr_next = pm_blocked_list;
5833 ASSERT(pm_blocked_list->pr_prev == NULL);
5834 pm_blocked_list->pr_prev = p;
5835 pm_blocked_list = p;
5836 } else {
5837 pm_blocked_list = p;
5838 }
5839 }
5840
5841 /*
5842 * Sets every power managed device back to its default threshold
5843 */
5844 void
pm_all_to_default_thresholds(void)5845 pm_all_to_default_thresholds(void)
5846 {
5847 ddi_walk_devs(ddi_root_node(), pm_set_dev_thr_walk,
5848 (void *) &pm_system_idle_threshold);
5849 }
5850
5851 static int
pm_set_dev_thr_walk(dev_info_t * dip,void * arg)5852 pm_set_dev_thr_walk(dev_info_t *dip, void *arg)
5853 {
5854 int thr = (int)(*(int *)arg);
5855
5856 if (!PM_GET_PM_INFO(dip))
5857 return (DDI_WALK_CONTINUE);
5858 pm_set_device_threshold(dip, thr, PMC_DEF_THRESH);
5859 return (DDI_WALK_CONTINUE);
5860 }
5861
5862 /*
5863 * Returns the current threshold value (in seconds) for the indicated component
5864 */
5865 int
pm_current_threshold(dev_info_t * dip,int comp,int * threshp)5866 pm_current_threshold(dev_info_t *dip, int comp, int *threshp)
5867 {
5868 if (comp < 0 || comp >= PM_NUMCMPTS(dip)) {
5869 return (DDI_FAILURE);
5870 } else {
5871 *threshp = cur_threshold(dip, comp);
5872 return (DDI_SUCCESS);
5873 }
5874 }
5875
5876 /*
5877 * To be called when changing the power level of a component of a device.
5878 * On some platforms, changing power on one device may require that power
5879 * be changed on other, related devices in the same transaction. Thus, we
5880 * always pass this request to the platform power manager so that all the
5881 * affected devices will be locked.
5882 */
5883 void
pm_lock_power(dev_info_t * dip,int * circp)5884 pm_lock_power(dev_info_t *dip, int *circp)
5885 {
5886 power_req_t power_req;
5887 int result;
5888
5889 power_req.request_type = PMR_PPM_LOCK_POWER;
5890 power_req.req.ppm_lock_power_req.who = dip;
5891 power_req.req.ppm_lock_power_req.circp = circp;
5892 (void) pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER, &power_req, &result);
5893 }
5894
5895 /*
5896 * Release the lock (or locks) acquired to change the power of a device.
5897 * See comments for pm_lock_power.
5898 */
5899 void
pm_unlock_power(dev_info_t * dip,int circ)5900 pm_unlock_power(dev_info_t *dip, int circ)
5901 {
5902 power_req_t power_req;
5903 int result;
5904
5905 power_req.request_type = PMR_PPM_UNLOCK_POWER;
5906 power_req.req.ppm_unlock_power_req.who = dip;
5907 power_req.req.ppm_unlock_power_req.circ = circ;
5908 (void) pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER, &power_req, &result);
5909 }
5910
5911
5912 /*
5913 * Attempt (without blocking) to acquire the lock(s) needed to change the
5914 * power of a component of a device. See comments for pm_lock_power.
5915 *
5916 * Return: 1 if lock(s) acquired, 0 if not.
5917 */
5918 int
pm_try_locking_power(dev_info_t * dip,int * circp)5919 pm_try_locking_power(dev_info_t *dip, int *circp)
5920 {
5921 power_req_t power_req;
5922 int result;
5923
5924 power_req.request_type = PMR_PPM_TRY_LOCK_POWER;
5925 power_req.req.ppm_lock_power_req.who = dip;
5926 power_req.req.ppm_lock_power_req.circp = circp;
5927 (void) pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER, &power_req, &result);
5928 return (result);
5929 }
5930
5931
5932 /*
5933 * Lock power state of a device.
5934 *
5935 * The implementation handles a special case where another thread may have
5936 * acquired the lock and created/launched this thread to do the work. If
5937 * the lock cannot be acquired immediately, we check to see if this thread
5938 * is registered as a borrower of the lock. If so, we may proceed without
5939 * the lock. This assumes that the lending thread blocks on the completion
5940 * of this thread.
5941 *
5942 * Note 1: for use by ppm only.
5943 *
5944 * Note 2: On failing to get the lock immediately, we search lock_loan list
5945 * for curthread (as borrower of the lock). On a hit, we check that the
5946 * lending thread already owns the lock we want. It is safe to compare
5947 * devi_busy_thread and thread id of the lender because in the == case (the
5948 * only one we care about) we know that the owner is blocked. Similarly,
5949 * If we find that curthread isn't registered as a lock borrower, it is safe
5950 * to use the blocking call (ndi_devi_enter) because we know that if we
5951 * weren't already listed as a borrower (upstream on the call stack) we won't
5952 * become one.
5953 */
5954 void
pm_lock_power_single(dev_info_t * dip,int * circp)5955 pm_lock_power_single(dev_info_t *dip, int *circp)
5956 {
5957 lock_loan_t *cur;
5958
5959 /* if the lock is available, we are done. */
5960 if (ndi_devi_tryenter(dip, circp))
5961 return;
5962
5963 mutex_enter(&pm_loan_lock);
5964 /* see if our thread is registered as a lock borrower. */
5965 for (cur = lock_loan_head.pmlk_next; cur; cur = cur->pmlk_next)
5966 if (cur->pmlk_borrower == curthread)
5967 break;
5968 mutex_exit(&pm_loan_lock);
5969
5970 /* if this thread not already registered, it is safe to block */
5971 if (cur == NULL)
5972 ndi_devi_enter(dip, circp);
5973 else {
5974 /* registered: does lender own the lock we want? */
5975 if (cur->pmlk_lender == DEVI(dip)->devi_busy_thread) {
5976 ASSERT(cur->pmlk_dip == NULL || cur->pmlk_dip == dip);
5977 cur->pmlk_dip = dip;
5978 } else /* no: just block for it */
5979 ndi_devi_enter(dip, circp);
5980
5981 }
5982 }
5983
5984 /*
5985 * Drop the lock on the device's power state. See comment for
5986 * pm_lock_power_single() for special implementation considerations.
5987 *
5988 * Note: for use by ppm only.
5989 */
5990 void
pm_unlock_power_single(dev_info_t * dip,int circ)5991 pm_unlock_power_single(dev_info_t *dip, int circ)
5992 {
5993 lock_loan_t *cur;
5994
5995 /* optimization: mutex not needed to check empty list */
5996 if (lock_loan_head.pmlk_next == NULL) {
5997 ndi_devi_exit(dip, circ);
5998 return;
5999 }
6000
6001 mutex_enter(&pm_loan_lock);
6002 /* see if our thread is registered as a lock borrower. */
6003 for (cur = lock_loan_head.pmlk_next; cur; cur = cur->pmlk_next)
6004 if (cur->pmlk_borrower == curthread)
6005 break;
6006 mutex_exit(&pm_loan_lock);
6007
6008 if (cur == NULL || cur->pmlk_dip != dip)
6009 /* we acquired the lock directly, so return it */
6010 ndi_devi_exit(dip, circ);
6011 }
6012
6013 /*
6014 * Try to take the lock for changing the power level of a component.
6015 *
6016 * Note: for use by ppm only.
6017 */
6018 int
pm_try_locking_power_single(dev_info_t * dip,int * circp)6019 pm_try_locking_power_single(dev_info_t *dip, int *circp)
6020 {
6021 return (ndi_devi_tryenter(dip, circp));
6022 }
6023
6024 #ifdef DEBUG
6025 /*
6026 * The following are used only to print out data structures for debugging
6027 */
6028 void
prdeps(char * msg)6029 prdeps(char *msg)
6030 {
6031
6032 pm_pdr_t *rp;
6033 int i;
6034
6035 pm_log("pm_dep_head %s %p\n", msg, (void *)pm_dep_head);
6036 for (rp = pm_dep_head; rp; rp = rp->pdr_next) {
6037 pm_log("%p: %s keeper %s, kept %s, kept count %d, next %p\n",
6038 (void *)rp, (rp->pdr_isprop ? "property" : "device"),
6039 rp->pdr_keeper, rp->pdr_kept, rp->pdr_kept_count,
6040 (void *)rp->pdr_next);
6041 if (rp->pdr_kept_count != 0) {
6042 pm_log("kept list = ");
6043 i = 0;
6044 while (i < rp->pdr_kept_count) {
6045 pm_log("%s ", rp->pdr_kept_paths[i]);
6046 i++;
6047 }
6048 pm_log("\n");
6049 }
6050 }
6051 }
6052
6053 void
pr_noinvol(char * hdr)6054 pr_noinvol(char *hdr)
6055 {
6056 pm_noinvol_t *ip;
6057
6058 pm_log("%s\n", hdr);
6059 rw_enter(&pm_noinvol_rwlock, RW_READER);
6060 for (ip = pm_noinvol_head; ip; ip = ip->ni_next)
6061 pm_log("\tmaj %d, flags %x, noinvolpm %d %s\n",
6062 ip->ni_major, ip->ni_flags, ip->ni_noinvolpm, ip->ni_path);
6063 rw_exit(&pm_noinvol_rwlock);
6064 }
6065 #endif
6066
6067 /*
6068 * Attempt to apply the thresholds indicated by rp to the node specified by
6069 * dip.
6070 */
6071 void
pm_apply_recorded_thresh(dev_info_t * dip,pm_thresh_rec_t * rp)6072 pm_apply_recorded_thresh(dev_info_t *dip, pm_thresh_rec_t *rp)
6073 {
6074 PMD_FUNC(pmf, "apply_recorded_thresh")
6075 int i, j;
6076 int comps = PM_NUMCMPTS(dip);
6077 struct pm_component *cp;
6078 pm_pte_t *ep;
6079 int pm_valid_thresh(dev_info_t *, pm_thresh_rec_t *);
6080
6081 PMD(PMD_THRESH, ("%s: part: %s@%s(%s#%d), rp %p, %s\n", pmf,
6082 PM_DEVICE(dip), (void *)rp, rp->ptr_physpath))
6083 PM_LOCK_DIP(dip);
6084 if (!PM_GET_PM_INFO(dip) || PM_ISBC(dip) || !pm_valid_thresh(dip, rp)) {
6085 PMD(PMD_FAIL, ("%s: part: %s@%s(%s#%d) PM_GET_PM_INFO %p\n",
6086 pmf, PM_DEVICE(dip), (void*)PM_GET_PM_INFO(dip)))
6087 PMD(PMD_FAIL, ("%s: part: %s@%s(%s#%d) PM_ISBC %d\n",
6088 pmf, PM_DEVICE(dip), PM_ISBC(dip)))
6089 PMD(PMD_FAIL, ("%s: part: %s@%s(%s#%d) pm_valid_thresh %d\n",
6090 pmf, PM_DEVICE(dip), pm_valid_thresh(dip, rp)))
6091 PM_UNLOCK_DIP(dip);
6092 return;
6093 }
6094
6095 ep = rp->ptr_entries;
6096 /*
6097 * Here we do the special case of a device threshold
6098 */
6099 if (rp->ptr_numcomps == 0) { /* PM_SET_DEVICE_THRESHOLD product */
6100 ASSERT(ep && ep->pte_numthresh == 1);
6101 PMD(PMD_THRESH, ("%s: set dev thr %s@%s(%s#%d) to 0x%x\n",
6102 pmf, PM_DEVICE(dip), ep->pte_thresh[0]))
6103 PM_UNLOCK_DIP(dip);
6104 pm_set_device_threshold(dip, ep->pte_thresh[0], PMC_DEV_THRESH);
6105 if (PM_SCANABLE(dip))
6106 pm_rescan(dip);
6107 return;
6108 }
6109 for (i = 0; i < comps; i++) {
6110 cp = PM_CP(dip, i);
6111 for (j = 0; j < ep->pte_numthresh; j++) {
6112 PMD(PMD_THRESH, ("%s: set thr %d for %s@%s(%s#%d)[%d] "
6113 "to %x\n", pmf, j, PM_DEVICE(dip),
6114 i, ep->pte_thresh[j]))
6115 cp->pmc_comp.pmc_thresh[j + 1] = ep->pte_thresh[j];
6116 }
6117 ep++;
6118 }
6119 DEVI(dip)->devi_pm_flags &= PMC_THRESH_NONE;
6120 DEVI(dip)->devi_pm_flags |= PMC_COMP_THRESH;
6121 PM_UNLOCK_DIP(dip);
6122
6123 if (PM_SCANABLE(dip))
6124 pm_rescan(dip);
6125 }
6126
6127 /*
6128 * Returns true if the threshold specified by rp could be applied to dip
6129 * (that is, the number of components and transitions are the same)
6130 */
6131 int
pm_valid_thresh(dev_info_t * dip,pm_thresh_rec_t * rp)6132 pm_valid_thresh(dev_info_t *dip, pm_thresh_rec_t *rp)
6133 {
6134 PMD_FUNC(pmf, "valid_thresh")
6135 int comps, i;
6136 pm_component_t *cp;
6137 pm_pte_t *ep;
6138
6139 if (!PM_GET_PM_INFO(dip) || PM_ISBC(dip)) {
6140 PMD(PMD_ERROR, ("%s: %s: no pm_info or BC\n", pmf,
6141 rp->ptr_physpath))
6142 return (0);
6143 }
6144 /*
6145 * Special case: we represent the PM_SET_DEVICE_THRESHOLD case by
6146 * an entry with numcomps == 0, (since we don't know how many
6147 * components there are in advance). This is always a valid
6148 * spec.
6149 */
6150 if (rp->ptr_numcomps == 0) {
6151 ASSERT(rp->ptr_entries && rp->ptr_entries->pte_numthresh == 1);
6152 return (1);
6153 }
6154 if (rp->ptr_numcomps != (comps = PM_NUMCMPTS(dip))) {
6155 PMD(PMD_ERROR, ("%s: comp # mm (dip %d cmd %d) for %s\n",
6156 pmf, PM_NUMCMPTS(dip), rp->ptr_numcomps, rp->ptr_physpath))
6157 return (0);
6158 }
6159 ep = rp->ptr_entries;
6160 for (i = 0; i < comps; i++) {
6161 cp = PM_CP(dip, i);
6162 if ((ep + i)->pte_numthresh !=
6163 cp->pmc_comp.pmc_numlevels - 1) {
6164 PMD(PMD_ERROR, ("%s: %s[%d]: thresh=%d, record=%d\n",
6165 pmf, rp->ptr_physpath, i,
6166 cp->pmc_comp.pmc_numlevels - 1,
6167 (ep + i)->pte_numthresh))
6168 return (0);
6169 }
6170 }
6171 return (1);
6172 }
6173
6174 /*
6175 * Remove any recorded threshold for device physpath
6176 * We know there will be at most one.
6177 */
6178 void
pm_unrecord_threshold(char * physpath)6179 pm_unrecord_threshold(char *physpath)
6180 {
6181 pm_thresh_rec_t *pptr, *ptr;
6182
6183 rw_enter(&pm_thresh_rwlock, RW_WRITER);
6184 for (pptr = NULL, ptr = pm_thresh_head; ptr; ptr = ptr->ptr_next) {
6185 if (strcmp(physpath, ptr->ptr_physpath) == 0) {
6186 if (pptr) {
6187 pptr->ptr_next = ptr->ptr_next;
6188 } else {
6189 ASSERT(pm_thresh_head == ptr);
6190 pm_thresh_head = ptr->ptr_next;
6191 }
6192 kmem_free(ptr, ptr->ptr_size);
6193 break;
6194 }
6195 pptr = ptr;
6196 }
6197 rw_exit(&pm_thresh_rwlock);
6198 }
6199
6200 /*
6201 * Discard all recorded thresholds. We are returning to the default pm state.
6202 */
6203 void
pm_discard_thresholds(void)6204 pm_discard_thresholds(void)
6205 {
6206 pm_thresh_rec_t *rp;
6207 rw_enter(&pm_thresh_rwlock, RW_WRITER);
6208 while (pm_thresh_head) {
6209 rp = pm_thresh_head;
6210 pm_thresh_head = rp->ptr_next;
6211 kmem_free(rp, rp->ptr_size);
6212 }
6213 rw_exit(&pm_thresh_rwlock);
6214 }
6215
6216 /*
6217 * Discard all recorded dependencies. We are returning to the default pm state.
6218 */
6219 void
pm_discard_dependencies(void)6220 pm_discard_dependencies(void)
6221 {
6222 pm_pdr_t *rp;
6223 int i;
6224 size_t length;
6225
6226 #ifdef DEBUG
6227 if (pm_debug & PMD_DEP)
6228 prdeps("Before discard\n");
6229 #endif
6230 ddi_walk_devs(ddi_root_node(), pm_discard_dep_walk, NULL);
6231
6232 #ifdef DEBUG
6233 if (pm_debug & PMD_DEP)
6234 prdeps("After discard\n");
6235 #endif
6236 while (pm_dep_head) {
6237 rp = pm_dep_head;
6238 if (!rp->pdr_isprop) {
6239 ASSERT(rp->pdr_satisfied == 0);
6240 ASSERT(pm_unresolved_deps);
6241 pm_unresolved_deps--;
6242 } else {
6243 ASSERT(pm_prop_deps);
6244 pm_prop_deps--;
6245 }
6246 pm_dep_head = rp->pdr_next;
6247 if (rp->pdr_kept_count) {
6248 for (i = 0; i < rp->pdr_kept_count; i++) {
6249 length = strlen(rp->pdr_kept_paths[i]) + 1;
6250 kmem_free(rp->pdr_kept_paths[i], length);
6251 }
6252 kmem_free(rp->pdr_kept_paths,
6253 rp->pdr_kept_count * sizeof (char **));
6254 }
6255 kmem_free(rp, rp->pdr_size);
6256 }
6257 }
6258
6259
6260 static int
pm_discard_dep_walk(dev_info_t * dip,void * arg)6261 pm_discard_dep_walk(dev_info_t *dip, void *arg)
6262 {
6263 _NOTE(ARGUNUSED(arg))
6264 char *pathbuf;
6265
6266 if (PM_GET_PM_INFO(dip) == NULL)
6267 return (DDI_WALK_CONTINUE);
6268 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
6269 (void) ddi_pathname(dip, pathbuf);
6270 pm_free_keeper(pathbuf, 0);
6271 kmem_free(pathbuf, MAXPATHLEN);
6272 return (DDI_WALK_CONTINUE);
6273 }
6274
6275 static int
pm_kept_walk(dev_info_t * dip,void * arg)6276 pm_kept_walk(dev_info_t *dip, void *arg)
6277 {
6278 _NOTE(ARGUNUSED(arg))
6279 char *pathbuf;
6280
6281 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
6282 (void) ddi_pathname(dip, pathbuf);
6283 (void) pm_kept(pathbuf);
6284 kmem_free(pathbuf, MAXPATHLEN);
6285
6286 return (DDI_WALK_CONTINUE);
6287 }
6288
6289 static int
pm_keeper_walk(dev_info_t * dip,void * arg)6290 pm_keeper_walk(dev_info_t *dip, void *arg)
6291 {
6292 _NOTE(ARGUNUSED(arg))
6293 char *pathbuf;
6294
6295 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
6296 (void) ddi_pathname(dip, pathbuf);
6297 (void) pm_keeper(pathbuf);
6298 kmem_free(pathbuf, MAXPATHLEN);
6299
6300 return (DDI_WALK_CONTINUE);
6301 }
6302
6303 static char *
pdw_type_decode(int type)6304 pdw_type_decode(int type)
6305 {
6306 switch (type) {
6307 case PM_DEP_WK_POWER_ON:
6308 return ("power on");
6309 case PM_DEP_WK_POWER_OFF:
6310 return ("power off");
6311 case PM_DEP_WK_DETACH:
6312 return ("detach");
6313 case PM_DEP_WK_REMOVE_DEP:
6314 return ("remove dep");
6315 case PM_DEP_WK_BRINGUP_SELF:
6316 return ("bringup self");
6317 case PM_DEP_WK_RECORD_KEEPER:
6318 return ("add dependent");
6319 case PM_DEP_WK_RECORD_KEEPER_PROP:
6320 return ("add dependent property");
6321 case PM_DEP_WK_KEPT:
6322 return ("kept");
6323 case PM_DEP_WK_KEEPER:
6324 return ("keeper");
6325 case PM_DEP_WK_ATTACH:
6326 return ("attach");
6327 case PM_DEP_WK_CHECK_KEPT:
6328 return ("check kept");
6329 case PM_DEP_WK_CPR_SUSPEND:
6330 return ("suspend");
6331 case PM_DEP_WK_CPR_RESUME:
6332 return ("resume");
6333 default:
6334 return ("unknown");
6335 }
6336
6337 }
6338
6339 static void
pm_rele_dep(char * keeper)6340 pm_rele_dep(char *keeper)
6341 {
6342 PMD_FUNC(pmf, "rele_dep")
6343 pm_pdr_t *dp;
6344 char *kept_path = NULL;
6345 dev_info_t *kept = NULL;
6346 int count = 0;
6347
6348 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
6349 if (strcmp(dp->pdr_keeper, keeper) != 0)
6350 continue;
6351 for (count = 0; count < dp->pdr_kept_count; count++) {
6352 kept_path = dp->pdr_kept_paths[count];
6353 if (kept_path == NULL)
6354 continue;
6355 kept = pm_name_to_dip(kept_path, 1);
6356 if (kept) {
6357 PMD(PMD_KEEPS, ("%s: release kept=%s@%s(%s#%d) "
6358 "of keeper=%s\n", pmf, PM_DEVICE(kept),
6359 keeper))
6360 ASSERT(DEVI(kept)->devi_pm_kidsupcnt > 0);
6361 pm_rele_power(kept);
6362 ddi_release_devi(kept);
6363 }
6364 }
6365 }
6366 }
6367
6368 /*
6369 * Called when we are just released from direct PM. Bring ourself up
6370 * if our keeper is up since dependency is not honored while a kept
6371 * device is under direct PM.
6372 */
6373 static void
pm_bring_self_up(char * keptpath)6374 pm_bring_self_up(char *keptpath)
6375 {
6376 PMD_FUNC(pmf, "bring_self_up")
6377 dev_info_t *kept;
6378 dev_info_t *keeper;
6379 pm_pdr_t *dp;
6380 int i, j;
6381 int up = 0, circ;
6382
6383 kept = pm_name_to_dip(keptpath, 1);
6384 if (kept == NULL)
6385 return;
6386 PMD(PMD_KEEPS, ("%s: kept=%s@%s(%s#%d)\n", pmf, PM_DEVICE(kept)))
6387 for (dp = pm_dep_head; dp; dp = dp->pdr_next) {
6388 if (dp->pdr_kept_count == 0)
6389 continue;
6390 for (i = 0; i < dp->pdr_kept_count; i++) {
6391 if (strcmp(dp->pdr_kept_paths[i], keptpath) != 0)
6392 continue;
6393 keeper = pm_name_to_dip(dp->pdr_keeper, 1);
6394 if (keeper) {
6395 PMD(PMD_KEEPS, ("%s: keeper=%s@%s(%s#%d)\n",
6396 pmf, PM_DEVICE(keeper)))
6397 PM_LOCK_POWER(keeper, &circ);
6398 for (j = 0; j < PM_NUMCMPTS(keeper);
6399 j++) {
6400 if (PM_CURPOWER(keeper, j)) {
6401 PMD(PMD_KEEPS, ("%s: comp="
6402 "%d is up\n", pmf, j))
6403 up++;
6404 }
6405 }
6406 if (up) {
6407 if (PM_SKBU(kept))
6408 DEVI(kept)->devi_pm_flags &=
6409 ~PMC_SKIP_BRINGUP;
6410 bring_pmdep_up(kept, 1);
6411 }
6412 PM_UNLOCK_POWER(keeper, circ);
6413 ddi_release_devi(keeper);
6414 }
6415 }
6416 }
6417 ddi_release_devi(kept);
6418 }
6419
6420 static void
pm_process_dep_request(pm_dep_wk_t * work)6421 pm_process_dep_request(pm_dep_wk_t *work)
6422 {
6423 PMD_FUNC(pmf, "dep_req")
6424 int ret;
6425
6426 PMD(PMD_DEP, ("%s: work=%s\n", pmf,
6427 pdw_type_decode(work->pdw_type)))
6428 PMD(PMD_DEP, ("%s: keeper=%s, kept=%s\n", pmf,
6429 (work->pdw_keeper ? work->pdw_keeper : "NULL"),
6430 (work->pdw_kept ? work->pdw_kept : "NULL")))
6431
6432 switch (work->pdw_type) {
6433 case PM_DEP_WK_POWER_ON:
6434 /* Bring up the kept devices and put a hold on them */
6435 bring_wekeeps_up(work->pdw_keeper);
6436 break;
6437 case PM_DEP_WK_POWER_OFF:
6438 /* Release the kept devices */
6439 pm_rele_dep(work->pdw_keeper);
6440 break;
6441 case PM_DEP_WK_DETACH:
6442 pm_free_keeps(work->pdw_keeper, work->pdw_pwr);
6443 break;
6444 case PM_DEP_WK_REMOVE_DEP:
6445 pm_discard_dependencies();
6446 break;
6447 case PM_DEP_WK_BRINGUP_SELF:
6448 /*
6449 * We deferred satisfying our dependency till now, so satisfy
6450 * it again and bring ourselves up.
6451 */
6452 pm_bring_self_up(work->pdw_kept);
6453 break;
6454 case PM_DEP_WK_RECORD_KEEPER:
6455 (void) pm_record_keeper(work->pdw_kept, work->pdw_keeper, 0);
6456 ddi_walk_devs(ddi_root_node(), pm_kept_walk, NULL);
6457 ddi_walk_devs(ddi_root_node(), pm_keeper_walk, NULL);
6458 break;
6459 case PM_DEP_WK_RECORD_KEEPER_PROP:
6460 (void) pm_record_keeper(work->pdw_kept, work->pdw_keeper, 1);
6461 ddi_walk_devs(ddi_root_node(), pm_keeper_walk, NULL);
6462 ddi_walk_devs(ddi_root_node(), pm_kept_walk, NULL);
6463 break;
6464 case PM_DEP_WK_KEPT:
6465 ret = pm_kept(work->pdw_kept);
6466 PMD(PMD_DEP, ("%s: PM_DEP_WK_KEPT: pm_kept returns %d\n", pmf,
6467 ret))
6468 break;
6469 case PM_DEP_WK_KEEPER:
6470 ret = pm_keeper(work->pdw_keeper);
6471 PMD(PMD_DEP, ("%s: PM_DEP_WK_KEEPER: pm_keeper returns %d\n",
6472 pmf, ret))
6473 break;
6474 case PM_DEP_WK_ATTACH:
6475 ret = pm_keeper(work->pdw_keeper);
6476 PMD(PMD_DEP, ("%s: PM_DEP_WK_ATTACH: pm_keeper returns %d\n",
6477 pmf, ret))
6478 ret = pm_kept(work->pdw_kept);
6479 PMD(PMD_DEP, ("%s: PM_DEP_WK_ATTACH: pm_kept returns %d\n",
6480 pmf, ret))
6481 break;
6482 case PM_DEP_WK_CHECK_KEPT:
6483 ret = pm_is_kept(work->pdw_kept);
6484 PMD(PMD_DEP, ("%s: PM_DEP_WK_CHECK_KEPT: kept=%s, ret=%d\n",
6485 pmf, work->pdw_kept, ret))
6486 break;
6487 case PM_DEP_WK_CPR_SUSPEND:
6488 pm_discard_dependencies();
6489 break;
6490 case PM_DEP_WK_CPR_RESUME:
6491 ddi_walk_devs(ddi_root_node(), pm_kept_walk, NULL);
6492 ddi_walk_devs(ddi_root_node(), pm_keeper_walk, NULL);
6493 break;
6494 default:
6495 ASSERT(0);
6496 break;
6497 }
6498 /*
6499 * Free the work structure if the requester is not waiting
6500 * Otherwise it is the requester's responsiblity to free it.
6501 */
6502 if (!work->pdw_wait) {
6503 if (work->pdw_keeper)
6504 kmem_free(work->pdw_keeper,
6505 strlen(work->pdw_keeper) + 1);
6506 if (work->pdw_kept)
6507 kmem_free(work->pdw_kept, strlen(work->pdw_kept) + 1);
6508 kmem_free(work, sizeof (pm_dep_wk_t));
6509 } else {
6510 /*
6511 * Notify requester if it is waiting for it.
6512 */
6513 work->pdw_ret = ret;
6514 work->pdw_done = 1;
6515 cv_signal(&work->pdw_cv);
6516 }
6517 }
6518
6519 /*
6520 * Process PM dependency requests.
6521 */
6522 static void
pm_dep_thread(void)6523 pm_dep_thread(void)
6524 {
6525 pm_dep_wk_t *work;
6526 callb_cpr_t cprinfo;
6527
6528 CALLB_CPR_INIT(&cprinfo, &pm_dep_thread_lock, callb_generic_cpr,
6529 "pm_dep_thread");
6530 for (;;) {
6531 mutex_enter(&pm_dep_thread_lock);
6532 if (pm_dep_thread_workq == NULL) {
6533 CALLB_CPR_SAFE_BEGIN(&cprinfo);
6534 cv_wait(&pm_dep_thread_cv, &pm_dep_thread_lock);
6535 CALLB_CPR_SAFE_END(&cprinfo, &pm_dep_thread_lock);
6536 }
6537 work = pm_dep_thread_workq;
6538 pm_dep_thread_workq = work->pdw_next;
6539 if (pm_dep_thread_tail == work)
6540 pm_dep_thread_tail = work->pdw_next;
6541 mutex_exit(&pm_dep_thread_lock);
6542 pm_process_dep_request(work);
6543
6544 }
6545 /*NOTREACHED*/
6546 }
6547
6548 /*
6549 * Set the power level of the indicated device to unknown (if it is not a
6550 * backwards compatible device), as it has just been resumed, and it won't
6551 * know if the power was removed or not. Adjust parent's kidsupcnt if necessary.
6552 */
6553 void
pm_forget_power_level(dev_info_t * dip)6554 pm_forget_power_level(dev_info_t *dip)
6555 {
6556 dev_info_t *pdip = ddi_get_parent(dip);
6557 int i, count = 0;
6558
6559 if (!PM_ISBC(dip)) {
6560 for (i = 0; i < PM_NUMCMPTS(dip); i++)
6561 count += (PM_CURPOWER(dip, i) == 0);
6562
6563 if (count && pdip && !PM_WANTS_NOTIFICATION(pdip))
6564 e_pm_hold_rele_power(pdip, count);
6565
6566 /*
6567 * Count this as a power cycle if we care
6568 */
6569 if (DEVI(dip)->devi_pm_volpmd &&
6570 PM_CP(dip, 0)->pmc_cur_pwr == 0)
6571 DEVI(dip)->devi_pm_volpmd = 0;
6572 for (i = 0; i < PM_NUMCMPTS(dip); i++)
6573 e_pm_set_cur_pwr(dip, PM_CP(dip, i), PM_LEVEL_UNKNOWN);
6574 }
6575 }
6576
6577 /*
6578 * This function advises the caller whether it should make a power-off
6579 * transition at this time or not. If the transition is not advised
6580 * at this time, the time that the next power-off transition can
6581 * be made from now is returned through "intervalp" pointer.
6582 * This function returns:
6583 *
6584 * 1 power-off advised
6585 * 0 power-off not advised, intervalp will point to seconds from
6586 * now that a power-off is advised. If it is passed the number
6587 * of years that policy specifies the device should last,
6588 * a large number is returned as the time interval.
6589 * -1 error
6590 */
6591 int
pm_trans_check(struct pm_trans_data * datap,time_t * intervalp)6592 pm_trans_check(struct pm_trans_data *datap, time_t *intervalp)
6593 {
6594 PMD_FUNC(pmf, "pm_trans_check")
6595 char dbuf[DC_SCSI_MFR_LEN];
6596 struct pm_scsi_cycles *scp;
6597 int service_years, service_weeks, full_years;
6598 time_t now, service_seconds, tdiff;
6599 time_t within_year, when_allowed;
6600 char *ptr;
6601 int lower_bound_cycles, upper_bound_cycles, cycles_allowed;
6602 int cycles_diff, cycles_over;
6603 struct pm_smart_count *smart_p;
6604
6605 if (datap == NULL) {
6606 PMD(PMD_TCHECK, ("%s: NULL data pointer!\n", pmf))
6607 return (-1);
6608 }
6609
6610 if (datap->format == DC_SCSI_FORMAT) {
6611 /*
6612 * Power cycles of the scsi drives are distributed
6613 * over 5 years with the following percentage ratio:
6614 *
6615 * 30%, 25%, 20%, 15%, and 10%
6616 *
6617 * The power cycle quota for each year is distributed
6618 * linearly through out the year. The equation for
6619 * determining the expected cycles is:
6620 *
6621 * e = a * (n / y)
6622 *
6623 * e = expected cycles
6624 * a = allocated cycles for this year
6625 * n = number of seconds since beginning of this year
6626 * y = number of seconds in a year
6627 *
6628 * Note that beginning of the year starts the day that
6629 * the drive has been put on service.
6630 *
6631 * If the drive has passed its expected cycles, we
6632 * can determine when it can start to power cycle
6633 * again to keep it on track to meet the 5-year
6634 * life expectancy. The equation for determining
6635 * when to power cycle is:
6636 *
6637 * w = y * (c / a)
6638 *
6639 * w = when it can power cycle again
6640 * y = number of seconds in a year
6641 * c = current number of cycles
6642 * a = allocated cycles for the year
6643 *
6644 */
6645 char pcnt[DC_SCSI_NPY] = { 30, 55, 75, 90, 100 };
6646
6647 scp = &datap->un.scsi_cycles;
6648 PMD(PMD_TCHECK, ("%s: format=%d, lifemax=%d, ncycles=%d, "
6649 "svc_date=%s, svc_flag=%d\n", pmf, datap->format,
6650 scp->lifemax, scp->ncycles, scp->svc_date, scp->flag))
6651 if (scp->ncycles < 0 || scp->flag != 0) {
6652 PMD(PMD_TCHECK, ("%s: ncycles < 0 || flag != 0\n", pmf))
6653 return (-1);
6654 }
6655
6656 if (scp->ncycles > scp->lifemax) {
6657 *intervalp = (LONG_MAX / hz);
6658 return (0);
6659 }
6660
6661 /*
6662 * convert service date to time_t
6663 */
6664 bcopy(scp->svc_date, dbuf, DC_SCSI_YEAR_LEN);
6665 dbuf[DC_SCSI_YEAR_LEN] = '\0';
6666 ptr = dbuf;
6667 service_years = stoi(&ptr) - EPOCH_YEAR;
6668 bcopy(&scp->svc_date[DC_SCSI_YEAR_LEN], dbuf,
6669 DC_SCSI_WEEK_LEN);
6670 dbuf[DC_SCSI_WEEK_LEN] = '\0';
6671
6672 /*
6673 * scsi standard does not specify WW data,
6674 * could be (00-51) or (01-52)
6675 */
6676 ptr = dbuf;
6677 service_weeks = stoi(&ptr);
6678 if (service_years < 0 ||
6679 service_weeks < 0 || service_weeks > 52) {
6680 PMD(PMD_TCHECK, ("%s: service year %d and week %d\n",
6681 pmf, service_years, service_weeks))
6682 return (-1);
6683 }
6684
6685 /*
6686 * calculate service date in seconds-since-epoch,
6687 * adding one day for each leap-year.
6688 *
6689 * (years-since-epoch + 2) fixes integer truncation,
6690 * example: (8) leap-years during [1972, 2000]
6691 * (2000 - 1970) = 30; and (30 + 2) / 4 = 8;
6692 */
6693 service_seconds = (service_years * DC_SPY) +
6694 (service_weeks * DC_SPW) +
6695 (((service_years + 2) / 4) * DC_SPD);
6696
6697 now = gethrestime_sec();
6698 /*
6699 * since the granularity of 'svc_date' is day not second,
6700 * 'now' should be rounded up to full day.
6701 */
6702 now = ((now + DC_SPD -1) / DC_SPD) * DC_SPD;
6703 if (service_seconds > now) {
6704 PMD(PMD_TCHECK, ("%s: service date (%ld) later "
6705 "than now (%ld)!\n", pmf, service_seconds, now))
6706 return (-1);
6707 }
6708
6709 tdiff = now - service_seconds;
6710 PMD(PMD_TCHECK, ("%s: age is %ld sec\n", pmf, tdiff))
6711
6712 /*
6713 * NOTE - Leap years are not considered in the calculations
6714 * below.
6715 */
6716 full_years = (tdiff / DC_SPY);
6717 if ((full_years >= DC_SCSI_NPY) &&
6718 (scp->ncycles <= scp->lifemax))
6719 return (1);
6720
6721 /*
6722 * Determine what is the normal cycle usage for the
6723 * device at the beginning and the end of this year.
6724 */
6725 lower_bound_cycles = (!full_years) ? 0 :
6726 ((scp->lifemax * pcnt[full_years - 1]) / 100);
6727 upper_bound_cycles = (scp->lifemax * pcnt[full_years]) / 100;
6728
6729 if (scp->ncycles <= lower_bound_cycles)
6730 return (1);
6731
6732 /*
6733 * The linear slope that determines how many cycles
6734 * are allowed this year is number of seconds
6735 * passed this year over total number of seconds in a year.
6736 */
6737 cycles_diff = (upper_bound_cycles - lower_bound_cycles);
6738 within_year = (tdiff % DC_SPY);
6739 cycles_allowed = lower_bound_cycles +
6740 (((uint64_t)cycles_diff * (uint64_t)within_year) / DC_SPY);
6741 PMD(PMD_TCHECK, ("%s: lived %d yrs and %ld secs\n", pmf,
6742 full_years, within_year))
6743 PMD(PMD_TCHECK, ("%s: # of cycles allowed %d\n", pmf,
6744 cycles_allowed))
6745
6746 if (scp->ncycles <= cycles_allowed)
6747 return (1);
6748
6749 /*
6750 * The transition is not advised now but we can
6751 * determine when the next transition can be made.
6752 *
6753 * Depending on how many cycles the device has been
6754 * over-used, we may need to skip years with
6755 * different percentage quota in order to determine
6756 * when the next transition can be made.
6757 */
6758 cycles_over = (scp->ncycles - lower_bound_cycles);
6759 while (cycles_over > cycles_diff) {
6760 full_years++;
6761 if (full_years >= DC_SCSI_NPY) {
6762 *intervalp = (LONG_MAX / hz);
6763 return (0);
6764 }
6765 cycles_over -= cycles_diff;
6766 lower_bound_cycles = upper_bound_cycles;
6767 upper_bound_cycles =
6768 (scp->lifemax * pcnt[full_years]) / 100;
6769 cycles_diff = (upper_bound_cycles - lower_bound_cycles);
6770 }
6771
6772 /*
6773 * The linear slope that determines when the next transition
6774 * can be made is the relative position of used cycles within a
6775 * year over total number of cycles within that year.
6776 */
6777 when_allowed = service_seconds + (full_years * DC_SPY) +
6778 (((uint64_t)DC_SPY * (uint64_t)cycles_over) / cycles_diff);
6779 *intervalp = (when_allowed - now);
6780 if (*intervalp > (LONG_MAX / hz))
6781 *intervalp = (LONG_MAX / hz);
6782 PMD(PMD_TCHECK, ("%s: no cycle is allowed in %ld secs\n", pmf,
6783 *intervalp))
6784 return (0);
6785 } else if (datap->format == DC_SMART_FORMAT) {
6786 /*
6787 * power cycles of SATA disks are reported from SMART
6788 * attributes.
6789 */
6790 smart_p = &datap->un.smart_count;
6791 if (smart_p->consumed >= smart_p->allowed) {
6792 *intervalp = (LONG_MAX / hz);
6793 PMD(PMD_TCHECK, ("%s: exceeded lifemax cycles.\n", pmf))
6794 return (0);
6795 } else
6796 return (1);
6797 }
6798
6799 PMD(PMD_TCHECK, ("%s: unknown format!\n", pmf))
6800 return (-1);
6801 }
6802
6803 /*
6804 * Nexus drivers call into pm framework to indicate which child driver is about
6805 * to be installed. In some platforms, ppm may need to configure the hardware
6806 * for successful installation of a driver.
6807 */
6808 int
pm_init_child(dev_info_t * dip)6809 pm_init_child(dev_info_t *dip)
6810 {
6811 power_req_t power_req;
6812
6813 ASSERT(ddi_binding_name(dip));
6814 ASSERT(ddi_get_name_addr(dip));
6815 pm_ppm_claim(dip);
6816 if (pm_ppm_claimed(dip)) { /* if ppm driver claims the node */
6817 power_req.request_type = PMR_PPM_INIT_CHILD;
6818 power_req.req.ppm_config_req.who = dip;
6819 ASSERT(PPM(dip) != NULL);
6820 return (pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER, &power_req,
6821 NULL));
6822 } else {
6823 #ifdef DEBUG
6824 /* pass it to the default handler so we can debug things */
6825 power_req.request_type = PMR_PPM_INIT_CHILD;
6826 power_req.req.ppm_config_req.who = dip;
6827 (void) pm_ctlops(NULL, dip,
6828 DDI_CTLOPS_POWER, &power_req, NULL);
6829 #endif
6830 }
6831 return (DDI_SUCCESS);
6832 }
6833
6834 /*
6835 * Bring parent of a node that is about to be probed up to full power, and
6836 * arrange for it to stay up until pm_post_probe() or pm_post_attach() decide
6837 * it is time to let it go down again
6838 */
6839 void
pm_pre_probe(dev_info_t * dip,pm_ppm_cookie_t * cp)6840 pm_pre_probe(dev_info_t *dip, pm_ppm_cookie_t *cp)
6841 {
6842 int result;
6843 power_req_t power_req;
6844
6845 bzero(cp, sizeof (*cp));
6846 cp->ppc_dip = dip;
6847
6848 pm_ppm_claim(dip);
6849 if (pm_ppm_claimed(dip)) { /* if ppm driver claims the node */
6850 power_req.request_type = PMR_PPM_PRE_PROBE;
6851 power_req.req.ppm_config_req.who = dip;
6852 ASSERT(PPM(dip) != NULL);
6853 (void) pm_ctlops(PPM(dip), dip,
6854 DDI_CTLOPS_POWER, &power_req, &result);
6855 cp->ppc_ppm = PPM(dip);
6856 } else {
6857 #ifdef DEBUG
6858 /* pass it to the default handler so we can debug things */
6859 power_req.request_type = PMR_PPM_PRE_PROBE;
6860 power_req.req.ppm_config_req.who = dip;
6861 (void) pm_ctlops(NULL, dip,
6862 DDI_CTLOPS_POWER, &power_req, &result);
6863 #endif
6864 cp->ppc_ppm = NULL;
6865 }
6866 }
6867
6868 int
pm_pre_config(dev_info_t * dip,char * devnm)6869 pm_pre_config(dev_info_t *dip, char *devnm)
6870 {
6871 PMD_FUNC(pmf, "pre_config")
6872 int ret;
6873
6874 if (MDI_VHCI(dip)) {
6875 PMD(PMD_SET, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
6876 ret = mdi_power(dip, MDI_PM_PRE_CONFIG, NULL, devnm, 0);
6877 return (ret == MDI_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
6878 } else if (!PM_GET_PM_INFO(dip))
6879 return (DDI_SUCCESS);
6880
6881 PMD(PMD_SET, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
6882 pm_hold_power(dip);
6883 ret = pm_all_to_normal(dip, PM_CANBLOCK_BLOCK);
6884 if (ret != DDI_SUCCESS)
6885 pm_rele_power(dip);
6886 return (ret);
6887 }
6888
6889 /*
6890 * This routine is called by devfs during its walk to unconfigue a node.
6891 * If the call is due to auto mod_unloads and the dip is not at its
6892 * full power, we return DDI_FAILURE to terminate the walk, otherwise
6893 * return DDI_SUCCESS.
6894 */
6895 int
pm_pre_unconfig(dev_info_t * dip,int flags,int * held,char * devnm)6896 pm_pre_unconfig(dev_info_t *dip, int flags, int *held, char *devnm)
6897 {
6898 PMD_FUNC(pmf, "pre_unconfig")
6899 int ret;
6900
6901 if (MDI_VHCI(dip)) {
6902 PMD(PMD_SET, ("%s: %s@%s(%s#%d), flags=%x\n", pmf,
6903 PM_DEVICE(dip), flags))
6904 ret = mdi_power(dip, MDI_PM_PRE_UNCONFIG, held, devnm, flags);
6905 return (ret == MDI_SUCCESS ? DDI_SUCCESS : DDI_FAILURE);
6906 } else if (!PM_GET_PM_INFO(dip))
6907 return (DDI_SUCCESS);
6908
6909 PMD(PMD_SET, ("%s: %s@%s(%s#%d), flags=%x\n", pmf, PM_DEVICE(dip),
6910 flags))
6911 *held = 0;
6912
6913 /*
6914 * If the dip is a leaf node, don't power it up.
6915 */
6916 if (!ddi_get_child(dip))
6917 return (DDI_SUCCESS);
6918
6919 /*
6920 * Do not power up the node if it is called due to auto-modunload.
6921 */
6922 if ((flags & NDI_AUTODETACH) && !pm_all_at_normal(dip))
6923 return (DDI_FAILURE);
6924
6925 pm_hold_power(dip);
6926 *held = 1;
6927 ret = pm_all_to_normal(dip, PM_CANBLOCK_BLOCK);
6928 if (ret != DDI_SUCCESS) {
6929 pm_rele_power(dip);
6930 *held = 0;
6931 }
6932 return (ret);
6933 }
6934
6935 /*
6936 * Notify ppm of attach action. Parent is already held at full power by
6937 * probe action.
6938 */
6939 void
pm_pre_attach(dev_info_t * dip,pm_ppm_cookie_t * cp,ddi_attach_cmd_t cmd)6940 pm_pre_attach(dev_info_t *dip, pm_ppm_cookie_t *cp, ddi_attach_cmd_t cmd)
6941 {
6942 static char *me = "pm_pre_attach";
6943 power_req_t power_req;
6944 int result;
6945
6946 /*
6947 * Initialize and fill in the PPM cookie
6948 */
6949 bzero(cp, sizeof (*cp));
6950 cp->ppc_cmd = (int)cmd;
6951 cp->ppc_ppm = PPM(dip);
6952 cp->ppc_dip = dip;
6953
6954 /*
6955 * DDI_ATTACH and DDI_RESUME cmds need to call platform specific
6956 * Power Management stuff. DDI_RESUME also has to purge it's
6957 * powerlevel information.
6958 */
6959 switch (cmd) {
6960 case DDI_ATTACH:
6961 if (cp->ppc_ppm) { /* if ppm driver claims the node */
6962 power_req.request_type = PMR_PPM_PRE_ATTACH;
6963 power_req.req.ppm_config_req.who = dip;
6964 ASSERT(PPM(dip));
6965 (void) pm_ctlops(cp->ppc_ppm, dip, DDI_CTLOPS_POWER,
6966 &power_req, &result);
6967 }
6968 #ifdef DEBUG
6969 else {
6970 power_req.request_type = PMR_PPM_PRE_ATTACH;
6971 power_req.req.ppm_config_req.who = dip;
6972 (void) pm_ctlops(NULL, dip,
6973 DDI_CTLOPS_POWER, &power_req, &result);
6974 }
6975 #endif
6976 break;
6977 case DDI_RESUME:
6978 pm_forget_power_level(dip);
6979
6980 if (cp->ppc_ppm) { /* if ppm driver claims the node */
6981 power_req.request_type = PMR_PPM_PRE_RESUME;
6982 power_req.req.resume_req.who = cp->ppc_dip;
6983 power_req.req.resume_req.cmd =
6984 (ddi_attach_cmd_t)cp->ppc_cmd;
6985 ASSERT(PPM(cp->ppc_dip) == cp->ppc_ppm);
6986 (void) pm_ctlops(cp->ppc_ppm, cp->ppc_dip,
6987 DDI_CTLOPS_POWER, &power_req, &result);
6988 }
6989 #ifdef DEBUG
6990 else {
6991 power_req.request_type = PMR_PPM_PRE_RESUME;
6992 power_req.req.resume_req.who = cp->ppc_dip;
6993 power_req.req.resume_req.cmd =
6994 (ddi_attach_cmd_t)cp->ppc_cmd;
6995 (void) pm_ctlops(NULL, cp->ppc_dip,
6996 DDI_CTLOPS_POWER, &power_req, &result);
6997 }
6998 #endif
6999 break;
7000
7001 case DDI_PM_RESUME:
7002 break;
7003
7004 default:
7005 panic(me);
7006 }
7007 }
7008
7009 /*
7010 * Nexus drivers call into pm framework to indicate which child driver is
7011 * being uninstalled. In some platforms, ppm may need to reconfigure the
7012 * hardware since the device driver is no longer installed.
7013 */
7014 int
pm_uninit_child(dev_info_t * dip)7015 pm_uninit_child(dev_info_t *dip)
7016 {
7017 power_req_t power_req;
7018
7019 ASSERT(ddi_binding_name(dip));
7020 ASSERT(ddi_get_name_addr(dip));
7021 pm_ppm_claim(dip);
7022 if (pm_ppm_claimed(dip)) { /* if ppm driver claims the node */
7023 power_req.request_type = PMR_PPM_UNINIT_CHILD;
7024 power_req.req.ppm_config_req.who = dip;
7025 ASSERT(PPM(dip));
7026 return (pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER, &power_req,
7027 NULL));
7028 } else {
7029 #ifdef DEBUG
7030 /* pass it to the default handler so we can debug things */
7031 power_req.request_type = PMR_PPM_UNINIT_CHILD;
7032 power_req.req.ppm_config_req.who = dip;
7033 (void) pm_ctlops(NULL, dip, DDI_CTLOPS_POWER, &power_req, NULL);
7034 #endif
7035 }
7036 return (DDI_SUCCESS);
7037 }
7038 /*
7039 * Decrement kidsupcnt so scan can turn the parent back off if it is idle
7040 * Also notify ppm of result of probe if there is a ppm that cares
7041 */
7042 void
pm_post_probe(pm_ppm_cookie_t * cp,int ret,int probe_failed)7043 pm_post_probe(pm_ppm_cookie_t *cp, int ret, int probe_failed)
7044 {
7045 _NOTE(ARGUNUSED(probe_failed))
7046 int result;
7047 power_req_t power_req;
7048
7049 if (cp->ppc_ppm) { /* if ppm driver claims the node */
7050 power_req.request_type = PMR_PPM_POST_PROBE;
7051 power_req.req.ppm_config_req.who = cp->ppc_dip;
7052 power_req.req.ppm_config_req.result = ret;
7053 ASSERT(PPM(cp->ppc_dip) == cp->ppc_ppm);
7054 (void) pm_ctlops(cp->ppc_ppm, cp->ppc_dip, DDI_CTLOPS_POWER,
7055 &power_req, &result);
7056 }
7057 #ifdef DEBUG
7058 else {
7059 power_req.request_type = PMR_PPM_POST_PROBE;
7060 power_req.req.ppm_config_req.who = cp->ppc_dip;
7061 power_req.req.ppm_config_req.result = ret;
7062 (void) pm_ctlops(NULL, cp->ppc_dip, DDI_CTLOPS_POWER,
7063 &power_req, &result);
7064 }
7065 #endif
7066 }
7067
7068 void
pm_post_config(dev_info_t * dip,char * devnm)7069 pm_post_config(dev_info_t *dip, char *devnm)
7070 {
7071 PMD_FUNC(pmf, "post_config")
7072
7073 if (MDI_VHCI(dip)) {
7074 PMD(PMD_SET, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
7075 (void) mdi_power(dip, MDI_PM_POST_CONFIG, NULL, devnm, 0);
7076 return;
7077 } else if (!PM_GET_PM_INFO(dip))
7078 return;
7079
7080 PMD(PMD_SET, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
7081 pm_rele_power(dip);
7082 }
7083
7084 void
pm_post_unconfig(dev_info_t * dip,int held,char * devnm)7085 pm_post_unconfig(dev_info_t *dip, int held, char *devnm)
7086 {
7087 PMD_FUNC(pmf, "post_unconfig")
7088
7089 if (MDI_VHCI(dip)) {
7090 PMD(PMD_SET, ("%s: %s@%s(%s#%d), held = %d\n", pmf,
7091 PM_DEVICE(dip), held))
7092 (void) mdi_power(dip, MDI_PM_POST_UNCONFIG, &held, devnm, 0);
7093 return;
7094 } else if (!PM_GET_PM_INFO(dip))
7095 return;
7096
7097 PMD(PMD_SET, ("%s: %s@%s(%s#%d), held = %d\n", pmf, PM_DEVICE(dip),
7098 held))
7099 if (!held)
7100 return;
7101 /*
7102 * We have held power in pre_unconfig, release it here.
7103 */
7104 pm_rele_power(dip);
7105 }
7106
7107 /*
7108 * Notify ppm of result of attach if there is a ppm that cares
7109 */
7110 void
pm_post_attach(pm_ppm_cookie_t * cp,int ret)7111 pm_post_attach(pm_ppm_cookie_t *cp, int ret)
7112 {
7113 int result;
7114 power_req_t power_req;
7115 dev_info_t *dip;
7116
7117 if (cp->ppc_cmd != DDI_ATTACH)
7118 return;
7119
7120 dip = cp->ppc_dip;
7121
7122 if (ret == DDI_SUCCESS) {
7123 /*
7124 * Attach succeeded, so proceed to doing post-attach pm tasks
7125 */
7126 if (PM_GET_PM_INFO(dip) == NULL)
7127 (void) pm_start(dip);
7128 } else {
7129 /*
7130 * Attach may have got pm started before failing
7131 */
7132 pm_stop(dip);
7133 }
7134
7135 if (cp->ppc_ppm) { /* if ppm driver claims the node */
7136 power_req.request_type = PMR_PPM_POST_ATTACH;
7137 power_req.req.ppm_config_req.who = cp->ppc_dip;
7138 power_req.req.ppm_config_req.result = ret;
7139 ASSERT(PPM(cp->ppc_dip) == cp->ppc_ppm);
7140 (void) pm_ctlops(cp->ppc_ppm, cp->ppc_dip,
7141 DDI_CTLOPS_POWER, &power_req, &result);
7142 }
7143 #ifdef DEBUG
7144 else {
7145 power_req.request_type = PMR_PPM_POST_ATTACH;
7146 power_req.req.ppm_config_req.who = cp->ppc_dip;
7147 power_req.req.ppm_config_req.result = ret;
7148 (void) pm_ctlops(NULL, cp->ppc_dip,
7149 DDI_CTLOPS_POWER, &power_req, &result);
7150 }
7151 #endif
7152 }
7153
7154 /*
7155 * Notify ppm of attach action. Parent is already held at full power by
7156 * probe action.
7157 */
7158 void
pm_pre_detach(dev_info_t * dip,ddi_detach_cmd_t cmd,pm_ppm_cookie_t * cp)7159 pm_pre_detach(dev_info_t *dip, ddi_detach_cmd_t cmd, pm_ppm_cookie_t *cp)
7160 {
7161 int result;
7162 power_req_t power_req;
7163
7164 bzero(cp, sizeof (*cp));
7165 cp->ppc_dip = dip;
7166 cp->ppc_cmd = (int)cmd;
7167
7168 switch (cmd) {
7169 case DDI_DETACH:
7170 pm_detaching(dip); /* suspend pm while detaching */
7171 if (pm_ppm_claimed(dip)) { /* if ppm driver claims node */
7172 power_req.request_type = PMR_PPM_PRE_DETACH;
7173 power_req.req.ppm_config_req.who = dip;
7174 ASSERT(PPM(dip));
7175 (void) pm_ctlops(PPM(dip), dip, DDI_CTLOPS_POWER,
7176 &power_req, &result);
7177 cp->ppc_ppm = PPM(dip);
7178 } else {
7179 #ifdef DEBUG
7180 /* pass to the default handler so we can debug things */
7181 power_req.request_type = PMR_PPM_PRE_DETACH;
7182 power_req.req.ppm_config_req.who = dip;
7183 (void) pm_ctlops(NULL, dip,
7184 DDI_CTLOPS_POWER, &power_req, &result);
7185 #endif
7186 cp->ppc_ppm = NULL;
7187 }
7188 break;
7189
7190 default:
7191 break;
7192 }
7193 }
7194
7195 /*
7196 * Dip is either a leaf node that exported "no-involuntary-power-cycles" prop.,
7197 * (if devi_pm_noinvol count is 0) or an ancestor of such a node. We need to
7198 * make an entry to record the details, which includes certain flag settings.
7199 */
7200 static void
pm_record_invol_path(char * path,int flags,int noinvolpm,int volpmd,int wasvolpmd,major_t major)7201 pm_record_invol_path(char *path, int flags, int noinvolpm, int volpmd,
7202 int wasvolpmd, major_t major)
7203 {
7204 PMD_FUNC(pmf, "record_invol_path")
7205 major_t pm_path_to_major(char *);
7206 size_t plen;
7207 pm_noinvol_t *ip, *np, *pp;
7208 pp = NULL;
7209
7210 plen = strlen(path) + 1;
7211 np = kmem_zalloc(sizeof (*np), KM_SLEEP);
7212 np->ni_size = plen;
7213 np->ni_path = kmem_alloc(plen, KM_SLEEP);
7214 np->ni_noinvolpm = noinvolpm;
7215 np->ni_volpmd = volpmd;
7216 np->ni_wasvolpmd = wasvolpmd;
7217 np->ni_flags = flags;
7218 (void) strcpy(np->ni_path, path);
7219 /*
7220 * If we haven't actually seen the node attached, it is hard to figure
7221 * out its major. If we could hold the node by path, we would be much
7222 * happier here.
7223 */
7224 if (major == DDI_MAJOR_T_NONE) {
7225 np->ni_major = pm_path_to_major(path);
7226 } else {
7227 np->ni_major = major;
7228 }
7229 rw_enter(&pm_noinvol_rwlock, RW_WRITER);
7230 for (ip = pm_noinvol_head; ip; pp = ip, ip = ip->ni_next) {
7231 int comp = strcmp(path, ip->ni_path);
7232 if (comp < 0) {
7233 PMD(PMD_NOINVOL, ("%s: %s insert before %s\n",
7234 pmf, path, ip->ni_path))
7235 /* insert before current entry */
7236 np->ni_next = ip;
7237 if (pp) {
7238 pp->ni_next = np;
7239 } else {
7240 pm_noinvol_head = np;
7241 }
7242 rw_exit(&pm_noinvol_rwlock);
7243 #ifdef DEBUG
7244 if (pm_debug & PMD_NOINVOL)
7245 pr_noinvol("record_invol_path exit0");
7246 #endif
7247 return;
7248 } else if (comp == 0) {
7249 panic("%s already in pm_noinvol list", path);
7250 }
7251 }
7252 /*
7253 * If we did not find an entry in the list that this should go before,
7254 * then it must go at the end
7255 */
7256 if (pp) {
7257 PMD(PMD_NOINVOL, ("%s: %s append after %s\n", pmf, path,
7258 pp->ni_path))
7259 ASSERT(pp->ni_next == 0);
7260 pp->ni_next = np;
7261 } else {
7262 PMD(PMD_NOINVOL, ("%s: %s added to end-of-list\n", pmf, path))
7263 ASSERT(!pm_noinvol_head);
7264 pm_noinvol_head = np;
7265 }
7266 rw_exit(&pm_noinvol_rwlock);
7267 #ifdef DEBUG
7268 if (pm_debug & PMD_NOINVOL)
7269 pr_noinvol("record_invol_path exit");
7270 #endif
7271 }
7272
7273 void
pm_record_invol(dev_info_t * dip)7274 pm_record_invol(dev_info_t *dip)
7275 {
7276 char *pathbuf;
7277 int pm_all_components_off(dev_info_t *);
7278 int volpmd = (PM_NUMCMPTS(dip) > 0) && pm_all_components_off(dip);
7279
7280 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
7281 (void) ddi_pathname(dip, pathbuf);
7282
7283 pm_record_invol_path(pathbuf, (DEVI(dip)->devi_pm_flags &
7284 (PMC_NO_INVOL | PMC_CONSOLE_FB)), DEVI(dip)->devi_pm_noinvolpm,
7285 DEVI(dip)->devi_pm_volpmd, volpmd, PM_MAJOR(dip));
7286
7287 /*
7288 * If this child's detach will be holding up its ancestors, then we
7289 * allow for an exception to that if all children of this type have
7290 * gone down voluntarily.
7291 * Now walk down the tree incrementing devi_pm_noinvolpm
7292 */
7293 (void) pm_noinvol_update(PM_BP_NOINVOL_DETACH, 0, volpmd, pathbuf,
7294 dip);
7295 kmem_free(pathbuf, MAXPATHLEN);
7296 }
7297
7298 void
pm_post_detach(pm_ppm_cookie_t * cp,int ret)7299 pm_post_detach(pm_ppm_cookie_t *cp, int ret)
7300 {
7301 dev_info_t *dip = cp->ppc_dip;
7302 int result;
7303 power_req_t power_req;
7304
7305 switch (cp->ppc_cmd) {
7306 case DDI_DETACH:
7307 if (cp->ppc_ppm) { /* if ppm driver claims the node */
7308 power_req.request_type = PMR_PPM_POST_DETACH;
7309 power_req.req.ppm_config_req.who = cp->ppc_dip;
7310 power_req.req.ppm_config_req.result = ret;
7311 ASSERT(PPM(cp->ppc_dip) == cp->ppc_ppm);
7312 (void) pm_ctlops(cp->ppc_ppm, cp->ppc_dip,
7313 DDI_CTLOPS_POWER, &power_req, &result);
7314 }
7315 #ifdef DEBUG
7316 else {
7317 power_req.request_type = PMR_PPM_POST_DETACH;
7318 power_req.req.ppm_config_req.who = cp->ppc_dip;
7319 power_req.req.ppm_config_req.result = ret;
7320 (void) pm_ctlops(NULL, cp->ppc_dip,
7321 DDI_CTLOPS_POWER, &power_req, &result);
7322 }
7323 #endif
7324 if (ret == DDI_SUCCESS) {
7325 /*
7326 * For hotplug detach we assume it is *really* gone
7327 */
7328 if (cp->ppc_cmd == DDI_DETACH &&
7329 ((DEVI(dip)->devi_pm_flags &
7330 (PMC_NO_INVOL | PMC_CONSOLE_FB)) ||
7331 DEVI(dip)->devi_pm_noinvolpm))
7332 pm_record_invol(dip);
7333 DEVI(dip)->devi_pm_flags &=
7334 ~(PMC_NO_INVOL | PMC_NOINVOL_DONE);
7335
7336 /*
7337 * If console fb is detaching, then we don't need to
7338 * worry any more about it going off (pm_detaching has
7339 * brought up all components)
7340 */
7341 if (PM_IS_CFB(dip)) {
7342 mutex_enter(&pm_cfb_lock);
7343 ASSERT(cfb_dip_detaching);
7344 ASSERT(cfb_dip == NULL);
7345 ASSERT(pm_cfb_comps_off == 0);
7346 cfb_dip_detaching = NULL;
7347 mutex_exit(&pm_cfb_lock);
7348 }
7349 pm_stop(dip); /* make it permanent */
7350 } else {
7351 if (PM_IS_CFB(dip)) {
7352 mutex_enter(&pm_cfb_lock);
7353 ASSERT(cfb_dip_detaching);
7354 ASSERT(cfb_dip == NULL);
7355 ASSERT(pm_cfb_comps_off == 0);
7356 cfb_dip = cfb_dip_detaching;
7357 cfb_dip_detaching = NULL;
7358 mutex_exit(&pm_cfb_lock);
7359 }
7360 pm_detach_failed(dip); /* resume power management */
7361 }
7362 break;
7363 case DDI_PM_SUSPEND:
7364 break;
7365 case DDI_SUSPEND:
7366 break; /* legal, but nothing to do */
7367 default:
7368 #ifdef DEBUG
7369 panic("pm_post_detach: unrecognized cmd %d for detach",
7370 cp->ppc_cmd);
7371 /*NOTREACHED*/
7372 #else
7373 break;
7374 #endif
7375 }
7376 }
7377
7378 /*
7379 * Called after vfs_mountroot has got the clock started to fix up timestamps
7380 * that were set when root bush drivers attached. hresttime was 0 then, so the
7381 * devices look busy but have a 0 busycnt
7382 */
7383 int
pm_adjust_timestamps(dev_info_t * dip,void * arg)7384 pm_adjust_timestamps(dev_info_t *dip, void *arg)
7385 {
7386 _NOTE(ARGUNUSED(arg))
7387
7388 pm_info_t *info = PM_GET_PM_INFO(dip);
7389 struct pm_component *cp;
7390 int i;
7391
7392 if (!info)
7393 return (DDI_WALK_CONTINUE);
7394 PM_LOCK_BUSY(dip);
7395 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
7396 cp = PM_CP(dip, i);
7397 if (cp->pmc_timestamp == 0 && cp->pmc_busycount == 0)
7398 cp->pmc_timestamp = gethrestime_sec();
7399 }
7400 PM_UNLOCK_BUSY(dip);
7401 return (DDI_WALK_CONTINUE);
7402 }
7403
7404 /*
7405 * Called at attach time to see if the device being attached has a record in
7406 * the no involuntary power cycles list. If so, we do some bookkeeping on the
7407 * parents and set a flag in the dip
7408 */
7409 void
pm_noinvol_specd(dev_info_t * dip)7410 pm_noinvol_specd(dev_info_t *dip)
7411 {
7412 PMD_FUNC(pmf, "noinvol_specd")
7413 char *pathbuf;
7414 pm_noinvol_t *ip, *pp = NULL;
7415 int wasvolpmd;
7416 int found = 0;
7417
7418 if (DEVI(dip)->devi_pm_flags & PMC_NOINVOL_DONE)
7419 return;
7420 DEVI(dip)->devi_pm_flags |= PMC_NOINVOL_DONE;
7421 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
7422 (void) ddi_pathname(dip, pathbuf);
7423
7424 PM_LOCK_DIP(dip);
7425 DEVI(dip)->devi_pm_volpmd = 0;
7426 DEVI(dip)->devi_pm_noinvolpm = 0;
7427 rw_enter(&pm_noinvol_rwlock, RW_READER);
7428 for (ip = pm_noinvol_head; ip; pp = ip, ip = ip->ni_next) {
7429 PMD(PMD_NOINVOL, ("%s: comparing '%s' to '%s'\n",
7430 pmf, pathbuf, ip->ni_path))
7431 if (strcmp(pathbuf, ip->ni_path) == 0) {
7432 found++;
7433 break;
7434 }
7435 }
7436 rw_exit(&pm_noinvol_rwlock);
7437 if (!found) {
7438 PM_UNLOCK_DIP(dip);
7439 kmem_free(pathbuf, MAXPATHLEN);
7440 return;
7441 }
7442 rw_enter(&pm_noinvol_rwlock, RW_WRITER);
7443 pp = NULL;
7444 for (ip = pm_noinvol_head; ip; pp = ip, ip = ip->ni_next) {
7445 PMD(PMD_NOINVOL, ("%s: comparing '%s' to '%s'\n",
7446 pmf, pathbuf, ip->ni_path))
7447 if (strcmp(pathbuf, ip->ni_path) == 0) {
7448 ip->ni_flags &= ~PMC_DRIVER_REMOVED;
7449 DEVI(dip)->devi_pm_flags |= ip->ni_flags;
7450 /*
7451 * Handle special case of console fb
7452 */
7453 if (PM_IS_CFB(dip)) {
7454 mutex_enter(&pm_cfb_lock);
7455 cfb_dip = dip;
7456 PMD(PMD_CFB, ("%s: %s@%s(%s#%d) setting "
7457 "cfb_dip\n", pmf, PM_DEVICE(dip)))
7458 mutex_exit(&pm_cfb_lock);
7459 }
7460 DEVI(dip)->devi_pm_noinvolpm = ip->ni_noinvolpm;
7461 ASSERT((DEVI(dip)->devi_pm_flags &
7462 (PMC_NO_INVOL | PMC_CONSOLE_FB)) ||
7463 DEVI(dip)->devi_pm_noinvolpm);
7464 DEVI(dip)->devi_pm_volpmd = ip->ni_volpmd;
7465 PMD(PMD_NOINVOL, ("%s: noinvol=%d, volpmd=%d, "
7466 "wasvolpmd=%d, flags=%x, path=%s\n", pmf,
7467 ip->ni_noinvolpm, ip->ni_volpmd,
7468 ip->ni_wasvolpmd, ip->ni_flags, ip->ni_path))
7469 /*
7470 * free the entry in hopes the list will now be empty
7471 * and we won't have to search it any more until the
7472 * device detaches
7473 */
7474 if (pp) {
7475 PMD(PMD_NOINVOL, ("%s: free %s, prev %s\n",
7476 pmf, ip->ni_path, pp->ni_path))
7477 pp->ni_next = ip->ni_next;
7478 } else {
7479 PMD(PMD_NOINVOL, ("%s: free %s head\n",
7480 pmf, ip->ni_path))
7481 ASSERT(pm_noinvol_head == ip);
7482 pm_noinvol_head = ip->ni_next;
7483 }
7484 PM_UNLOCK_DIP(dip);
7485 wasvolpmd = ip->ni_wasvolpmd;
7486 rw_exit(&pm_noinvol_rwlock);
7487 kmem_free(ip->ni_path, ip->ni_size);
7488 kmem_free(ip, sizeof (*ip));
7489 /*
7490 * Now walk up the tree decrementing devi_pm_noinvolpm
7491 * (and volpmd if appropriate)
7492 */
7493 (void) pm_noinvol_update(PM_BP_NOINVOL_ATTACH, 0,
7494 wasvolpmd, pathbuf, dip);
7495 #ifdef DEBUG
7496 if (pm_debug & PMD_NOINVOL)
7497 pr_noinvol("noinvol_specd exit");
7498 #endif
7499 kmem_free(pathbuf, MAXPATHLEN);
7500 return;
7501 }
7502 }
7503 kmem_free(pathbuf, MAXPATHLEN);
7504 rw_exit(&pm_noinvol_rwlock);
7505 PM_UNLOCK_DIP(dip);
7506 }
7507
7508 int
pm_all_components_off(dev_info_t * dip)7509 pm_all_components_off(dev_info_t *dip)
7510 {
7511 int i;
7512 pm_component_t *cp;
7513
7514 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
7515 cp = PM_CP(dip, i);
7516 if (cp->pmc_cur_pwr == PM_LEVEL_UNKNOWN ||
7517 cp->pmc_comp.pmc_lvals[cp->pmc_cur_pwr])
7518 return (0);
7519 }
7520 return (1); /* all off */
7521 }
7522
7523 /*
7524 * Make sure that all "no involuntary power cycles" devices are attached.
7525 * Called before doing a cpr suspend to make sure the driver has a say about
7526 * the power cycle
7527 */
7528 int
pm_reattach_noinvol(void)7529 pm_reattach_noinvol(void)
7530 {
7531 PMD_FUNC(pmf, "reattach_noinvol")
7532 pm_noinvol_t *ip;
7533 char *path;
7534 dev_info_t *dip;
7535
7536 /*
7537 * Prevent the modunload thread from unloading any modules until we
7538 * have completely stopped all kernel threads.
7539 */
7540 modunload_disable();
7541 for (ip = pm_noinvol_head; ip; ip = ip->ni_next) {
7542 /*
7543 * Forget we'v ever seen any entry
7544 */
7545 ip->ni_persistent = 0;
7546 }
7547 restart:
7548 rw_enter(&pm_noinvol_rwlock, RW_READER);
7549 for (ip = pm_noinvol_head; ip; ip = ip->ni_next) {
7550 #ifdef PMDDEBUG
7551 major_t maj;
7552 maj = ip->ni_major;
7553 #endif
7554 path = ip->ni_path;
7555 if (path != NULL && !(ip->ni_flags & PMC_DRIVER_REMOVED)) {
7556 if (ip->ni_persistent) {
7557 /*
7558 * If we weren't able to make this entry
7559 * go away, then we give up, as
7560 * holding/attaching the driver ought to have
7561 * resulted in this entry being deleted
7562 */
7563 PMD(PMD_NOINVOL, ("%s: can't reattach %s "
7564 "(%s|%d)\n", pmf, ip->ni_path,
7565 ddi_major_to_name(maj), (int)maj))
7566 cmn_err(CE_WARN, "cpr: unable to reattach %s ",
7567 ip->ni_path);
7568 modunload_enable();
7569 rw_exit(&pm_noinvol_rwlock);
7570 return (0);
7571 }
7572 ip->ni_persistent++;
7573 rw_exit(&pm_noinvol_rwlock);
7574 PMD(PMD_NOINVOL, ("%s: holding %s\n", pmf, path))
7575 dip = e_ddi_hold_devi_by_path(path, 0);
7576 if (dip == NULL) {
7577 PMD(PMD_NOINVOL, ("%s: can't hold (%s|%d)\n",
7578 pmf, path, (int)maj))
7579 cmn_err(CE_WARN, "cpr: unable to hold %s "
7580 "driver", path);
7581 modunload_enable();
7582 return (0);
7583 } else {
7584 PMD(PMD_DHR, ("%s: release %s\n", pmf, path))
7585 /*
7586 * Since the modunload thread is stopped, we
7587 * don't have to keep the driver held, which
7588 * saves a ton of bookkeeping
7589 */
7590 ddi_release_devi(dip);
7591 goto restart;
7592 }
7593 } else {
7594 PMD(PMD_NOINVOL, ("%s: skip %s; unknown major\n",
7595 pmf, ip->ni_path))
7596 continue;
7597 }
7598 }
7599 rw_exit(&pm_noinvol_rwlock);
7600 return (1);
7601 }
7602
7603 void
pm_reattach_noinvol_fini(void)7604 pm_reattach_noinvol_fini(void)
7605 {
7606 modunload_enable();
7607 }
7608
7609 /*
7610 * Display pm support code
7611 */
7612
7613
7614 /*
7615 * console frame-buffer power-mgmt gets enabled when debugging
7616 * services are not present or console fbpm override is set
7617 */
7618 void
pm_cfb_setup(const char * stdout_path)7619 pm_cfb_setup(const char *stdout_path)
7620 {
7621 PMD_FUNC(pmf, "cfb_setup")
7622 extern int obpdebug;
7623 char *devname;
7624 dev_info_t *dip;
7625 int devname_len;
7626 extern dev_info_t *fbdip;
7627
7628 /*
7629 * By virtue of this function being called (from consconfig),
7630 * we know stdout is a framebuffer.
7631 */
7632 stdout_is_framebuffer = 1;
7633
7634 if (obpdebug || (boothowto & RB_DEBUG)) {
7635 if (pm_cfb_override == 0) {
7636 /*
7637 * Console is frame buffer, but we want to suppress
7638 * pm on it because of debugging setup
7639 */
7640 pm_cfb_enabled = 0;
7641 cmn_err(CE_NOTE, "Kernel debugger present: disabling "
7642 "console power management.");
7643 /*
7644 * however, we still need to know which is the console
7645 * fb in order to suppress pm on it
7646 */
7647 } else {
7648 cmn_err(CE_WARN, "Kernel debugger present: see "
7649 "kmdb(1M) for interaction with power management.");
7650 }
7651 }
7652 #ifdef DEBUG
7653 /*
7654 * IF console is fb and is power managed, don't do prom_printfs from
7655 * pm debug macro
7656 */
7657 if (pm_cfb_enabled && !pm_debug_to_console) {
7658 if (pm_debug)
7659 prom_printf("pm debug output will be to log only\n");
7660 pm_divertdebug++;
7661 }
7662 #endif
7663 devname = i_ddi_strdup((char *)stdout_path, KM_SLEEP);
7664 devname_len = strlen(devname) + 1;
7665 PMD(PMD_CFB, ("%s: stripped %s\n", pmf, devname))
7666 /* if the driver is attached */
7667 if ((dip = fbdip) != NULL) {
7668 PMD(PMD_CFB, ("%s: attached: %s@%s(%s#%d)\n", pmf,
7669 PM_DEVICE(dip)))
7670 /*
7671 * We set up here as if the driver were power manageable in case
7672 * we get a later attach of a pm'able driver (which would result
7673 * in a panic later)
7674 */
7675 cfb_dip = dip;
7676 DEVI(dip)->devi_pm_flags |= (PMC_CONSOLE_FB | PMC_NO_INVOL);
7677 PMD(PMD_CFB, ("%s: cfb_dip -> %s@%s(%s#%d)\n", pmf,
7678 PM_DEVICE(dip)))
7679 #ifdef DEBUG
7680 if (!(PM_GET_PM_INFO(dip) != NULL && PM_NUMCMPTS(dip))) {
7681 PMD(PMD_CFB, ("%s: %s@%s(%s#%d) not power-managed\n",
7682 pmf, PM_DEVICE(dip)))
7683 }
7684 #endif
7685 } else {
7686 char *ep;
7687 PMD(PMD_CFB, ("%s: pntd %s failed\n", pmf, devname))
7688 pm_record_invol_path(devname,
7689 (PMC_CONSOLE_FB | PMC_NO_INVOL), 1, 0, 0,
7690 DDI_MAJOR_T_NONE);
7691 for (ep = strrchr(devname, '/'); ep != devname;
7692 ep = strrchr(devname, '/')) {
7693 PMD(PMD_CFB, ("%s: devname %s\n", pmf, devname))
7694 *ep = '\0';
7695 dip = pm_name_to_dip(devname, 0);
7696 if (dip != NULL) {
7697 /*
7698 * Walk up the tree incrementing
7699 * devi_pm_noinvolpm
7700 */
7701 (void) pm_noinvol_update(PM_BP_NOINVOL_CFB,
7702 0, 0, devname, dip);
7703 break;
7704 } else {
7705 pm_record_invol_path(devname,
7706 PMC_NO_INVOL, 1, 0, 0, DDI_MAJOR_T_NONE);
7707 }
7708 }
7709 }
7710 kmem_free(devname, devname_len);
7711 }
7712
7713 void
pm_cfb_rele(void)7714 pm_cfb_rele(void)
7715 {
7716 mutex_enter(&pm_cfb_lock);
7717 /*
7718 * this call isn't using the console any more, it is ok to take it
7719 * down if the count goes to 0
7720 */
7721 cfb_inuse--;
7722 mutex_exit(&pm_cfb_lock);
7723 }
7724
7725 /*
7726 * software interrupt handler for fbpm; this function exists because we can't
7727 * bring up the frame buffer power from above lock level. So if we need to,
7728 * we instead schedule a softint that runs this routine and takes us into
7729 * debug_enter (a bit delayed from the original request, but avoiding a panic).
7730 */
7731 static uint_t
pm_cfb_softint(caddr_t int_handler_arg)7732 pm_cfb_softint(caddr_t int_handler_arg)
7733 {
7734 _NOTE(ARGUNUSED(int_handler_arg))
7735 int rval = DDI_INTR_UNCLAIMED;
7736
7737 mutex_enter(&pm_cfb_lock);
7738 if (pm_soft_pending) {
7739 mutex_exit(&pm_cfb_lock);
7740 debug_enter((char *)NULL);
7741 /* acquired in debug_enter before calling pm_cfb_trigger */
7742 pm_cfb_rele();
7743 mutex_enter(&pm_cfb_lock);
7744 pm_soft_pending = B_FALSE;
7745 mutex_exit(&pm_cfb_lock);
7746 rval = DDI_INTR_CLAIMED;
7747 } else
7748 mutex_exit(&pm_cfb_lock);
7749
7750 return (rval);
7751 }
7752
7753 void
pm_cfb_setup_intr(void)7754 pm_cfb_setup_intr(void)
7755 {
7756 PMD_FUNC(pmf, "cfb_setup_intr")
7757 extern void prom_set_outfuncs(void (*)(void), void (*)(void));
7758 void pm_cfb_check_and_powerup(void);
7759
7760 mutex_init(&pm_cfb_lock, NULL, MUTEX_SPIN, (void *)ipltospl(SPL8));
7761 #ifdef PMDDEBUG
7762 mutex_init(&pm_debug_lock, NULL, MUTEX_SPIN, (void *)ipltospl(SPL8));
7763 #endif
7764
7765 if (!stdout_is_framebuffer) {
7766 PMD(PMD_CFB, ("%s: console not fb\n", pmf))
7767 return;
7768 }
7769
7770 /*
7771 * setup software interrupt handler
7772 */
7773 if (ddi_add_softintr(ddi_root_node(), DDI_SOFTINT_HIGH, &pm_soft_id,
7774 NULL, NULL, pm_cfb_softint, NULL) != DDI_SUCCESS)
7775 panic("pm: unable to register soft intr.");
7776
7777 prom_set_outfuncs(pm_cfb_check_and_powerup, pm_cfb_rele);
7778 }
7779
7780 /*
7781 * Checks to see if it is safe to write to the console wrt power management
7782 * (i.e. if the console is a framebuffer, then it must be at full power)
7783 * returns 1 when power is off (power-up is needed)
7784 * returns 0 when power is on (power-up not needed)
7785 */
7786 int
pm_cfb_check_and_hold(void)7787 pm_cfb_check_and_hold(void)
7788 {
7789 /*
7790 * cfb_dip is set iff console is a power manageable frame buffer
7791 * device
7792 */
7793 extern int modrootloaded;
7794
7795 mutex_enter(&pm_cfb_lock);
7796 cfb_inuse++;
7797 ASSERT(cfb_inuse); /* wrap? */
7798 if (modrootloaded && cfb_dip) {
7799 /*
7800 * don't power down the frame buffer, the prom is using it
7801 */
7802 if (pm_cfb_comps_off) {
7803 mutex_exit(&pm_cfb_lock);
7804 return (1);
7805 }
7806 }
7807 mutex_exit(&pm_cfb_lock);
7808 return (0);
7809 }
7810
7811 /*
7812 * turn on cfb power (which is known to be off).
7813 * Must be called below lock level!
7814 */
7815 void
pm_cfb_powerup(void)7816 pm_cfb_powerup(void)
7817 {
7818 pm_info_t *info;
7819 int norm;
7820 int ccount, ci;
7821 int unused;
7822 #ifdef DEBUG
7823 /*
7824 * Can't reenter prom_prekern, so suppress pm debug messages
7825 * (still go to circular buffer).
7826 */
7827 mutex_enter(&pm_debug_lock);
7828 pm_divertdebug++;
7829 mutex_exit(&pm_debug_lock);
7830 #endif
7831 info = PM_GET_PM_INFO(cfb_dip);
7832 ASSERT(info);
7833
7834 ccount = PM_NUMCMPTS(cfb_dip);
7835 for (ci = 0; ci < ccount; ci++) {
7836 norm = pm_get_normal_power(cfb_dip, ci);
7837 (void) pm_set_power(cfb_dip, ci, norm, PM_LEVEL_UPONLY,
7838 PM_CANBLOCK_BYPASS, 0, &unused);
7839 }
7840 #ifdef DEBUG
7841 mutex_enter(&pm_debug_lock);
7842 pm_divertdebug--;
7843 mutex_exit(&pm_debug_lock);
7844 #endif
7845 }
7846
7847 /*
7848 * Check if the console framebuffer is powered up. If not power it up.
7849 * Note: Calling pm_cfb_check_and_hold has put a hold on the power state which
7850 * must be released by calling pm_cfb_rele when the console fb operation
7851 * is completed.
7852 */
7853 void
pm_cfb_check_and_powerup(void)7854 pm_cfb_check_and_powerup(void)
7855 {
7856 if (pm_cfb_check_and_hold())
7857 pm_cfb_powerup();
7858 }
7859
7860 /*
7861 * Trigger a low level interrupt to power up console frame buffer.
7862 */
7863 void
pm_cfb_trigger(void)7864 pm_cfb_trigger(void)
7865 {
7866 if (cfb_dip == NULL)
7867 return;
7868
7869 mutex_enter(&pm_cfb_lock);
7870 /*
7871 * If the machine appears to be hung, pulling the keyboard connector of
7872 * the console will cause a high level interrupt and go to debug_enter.
7873 * But, if the fb is powered down, this routine will be called to bring
7874 * it up (by generating a softint to do the work). If a second attempt
7875 * at triggering this softint happens before the first one completes,
7876 * we panic as softints are most likely not being handled.
7877 */
7878 if (pm_soft_pending) {
7879 panicstr = "pm_cfb_trigger: failed to enter the debugger";
7880 panic(panicstr); /* does a power up at any intr level */
7881 /* NOTREACHED */
7882 }
7883 pm_soft_pending = B_TRUE;
7884 mutex_exit(&pm_cfb_lock);
7885 ddi_trigger_softintr(pm_soft_id);
7886 }
7887
7888 static major_t i_path_to_major(char *, char *);
7889
7890 major_t
pm_path_to_major(char * path)7891 pm_path_to_major(char *path)
7892 {
7893 PMD_FUNC(pmf, "path_to_major")
7894 char *np, *ap, *bp;
7895 major_t ret;
7896 size_t len;
7897
7898 PMD(PMD_NOINVOL, ("%s: %s\n", pmf, path))
7899
7900 np = strrchr(path, '/');
7901 if (np != NULL)
7902 np++;
7903 else
7904 np = path;
7905 len = strlen(np) + 1;
7906 bp = kmem_alloc(len, KM_SLEEP);
7907 (void) strcpy(bp, np);
7908 if ((ap = strchr(bp, '@')) != NULL) {
7909 *ap = '\0';
7910 }
7911 PMD(PMD_NOINVOL, ("%s: %d\n", pmf, ddi_name_to_major(np)))
7912 ret = i_path_to_major(path, np);
7913 kmem_free(bp, len);
7914 return (ret);
7915 }
7916
7917 #ifdef DEBUG
7918 #ifndef sparc
7919 clock_t pt_sleep = 1;
7920 #endif
7921
7922 char *pm_msgp;
7923 char *pm_bufend;
7924 char *pm_msgbuf = NULL;
7925 int pm_logpages = 0x100;
7926 #include <sys/sunldi.h>
7927 #include <sys/uio.h>
7928 clock_t pm_log_sleep = 1000;
7929 int pm_extra_cr = 1;
7930 volatile int pm_tty = 1;
7931
7932 #define PMLOGPGS pm_logpages
7933
7934 #if defined(__x86)
7935 void pm_printf(char *s);
7936 #endif
7937
7938 /*PRINTFLIKE1*/
7939 void
pm_log(const char * fmt,...)7940 pm_log(const char *fmt, ...)
7941 {
7942 va_list adx;
7943 size_t size;
7944
7945 mutex_enter(&pm_debug_lock);
7946 if (pm_msgbuf == NULL) {
7947 pm_msgbuf = kmem_zalloc(mmu_ptob(PMLOGPGS), KM_SLEEP);
7948 pm_bufend = pm_msgbuf + mmu_ptob(PMLOGPGS) - 1;
7949 pm_msgp = pm_msgbuf;
7950 }
7951 va_start(adx, fmt);
7952 size = vsnprintf(NULL, 0, fmt, adx) + 1;
7953 va_end(adx);
7954 va_start(adx, fmt);
7955 if (size > (pm_bufend - pm_msgp)) { /* wraps */
7956 bzero(pm_msgp, pm_bufend - pm_msgp);
7957 (void) vsnprintf(pm_msgbuf, size, fmt, adx);
7958 if (!pm_divertdebug)
7959 prom_printf("%s", pm_msgp);
7960 #if defined(__x86)
7961 if (pm_tty) {
7962 pm_printf(pm_msgp);
7963 if (pm_extra_cr)
7964 pm_printf("\r");
7965 }
7966 #endif
7967 pm_msgp = pm_msgbuf + size;
7968 } else {
7969 (void) vsnprintf(pm_msgp, size, fmt, adx);
7970 #if defined(__x86)
7971 if (pm_tty) {
7972 pm_printf(pm_msgp);
7973 if (pm_extra_cr)
7974 pm_printf("\r");
7975 }
7976 #endif
7977 if (!pm_divertdebug)
7978 prom_printf("%s", pm_msgp);
7979 pm_msgp += size;
7980 }
7981 va_end(adx);
7982 mutex_exit(&pm_debug_lock);
7983 drv_usecwait((clock_t)pm_log_sleep);
7984 }
7985 #endif /* DEBUG */
7986
7987 /*
7988 * We want to save the state of any directly pm'd devices over the suspend/
7989 * resume process so that we can put them back the way the controlling
7990 * process left them.
7991 */
7992 void
pm_save_direct_levels(void)7993 pm_save_direct_levels(void)
7994 {
7995 pm_processes_stopped = 1;
7996 ddi_walk_devs(ddi_root_node(), pm_save_direct_lvl_walk, 0);
7997 }
7998
7999 static int
pm_save_direct_lvl_walk(dev_info_t * dip,void * arg)8000 pm_save_direct_lvl_walk(dev_info_t *dip, void *arg)
8001 {
8002 _NOTE(ARGUNUSED(arg))
8003 int i;
8004 int *ip;
8005 pm_info_t *info = PM_GET_PM_INFO(dip);
8006
8007 if (!info)
8008 return (DDI_WALK_CONTINUE);
8009
8010 if (PM_ISDIRECT(dip) && !PM_ISBC(dip)) {
8011 if (PM_NUMCMPTS(dip) > 2) {
8012 info->pmi_lp = kmem_alloc(PM_NUMCMPTS(dip) *
8013 sizeof (int), KM_SLEEP);
8014 ip = info->pmi_lp;
8015 } else {
8016 ip = info->pmi_levels;
8017 }
8018 /* autopm and processes are stopped, ok not to lock power */
8019 for (i = 0; i < PM_NUMCMPTS(dip); i++)
8020 *ip++ = PM_CURPOWER(dip, i);
8021 /*
8022 * There is a small window between stopping the
8023 * processes and setting pm_processes_stopped where
8024 * a driver could get hung up in a pm_raise_power()
8025 * call. Free any such driver now.
8026 */
8027 pm_proceed(dip, PMP_RELEASE, -1, -1);
8028 }
8029
8030 return (DDI_WALK_CONTINUE);
8031 }
8032
8033 void
pm_restore_direct_levels(void)8034 pm_restore_direct_levels(void)
8035 {
8036 /*
8037 * If cpr didn't call pm_save_direct_levels, (because stopping user
8038 * threads failed) then we don't want to try to restore them
8039 */
8040 if (!pm_processes_stopped)
8041 return;
8042
8043 ddi_walk_devs(ddi_root_node(), pm_restore_direct_lvl_walk, 0);
8044 pm_processes_stopped = 0;
8045 }
8046
8047 static int
pm_restore_direct_lvl_walk(dev_info_t * dip,void * arg)8048 pm_restore_direct_lvl_walk(dev_info_t *dip, void *arg)
8049 {
8050 _NOTE(ARGUNUSED(arg))
8051 PMD_FUNC(pmf, "restore_direct_lvl_walk")
8052 int i, nc, result;
8053 int *ip;
8054
8055 pm_info_t *info = PM_GET_PM_INFO(dip);
8056 if (!info)
8057 return (DDI_WALK_CONTINUE);
8058
8059 if (PM_ISDIRECT(dip) && !PM_ISBC(dip)) {
8060 if ((nc = PM_NUMCMPTS(dip)) > 2) {
8061 ip = &info->pmi_lp[nc - 1];
8062 } else {
8063 ip = &info->pmi_levels[nc - 1];
8064 }
8065 /*
8066 * Because fb drivers fail attempts to turn off the
8067 * fb when the monitor is on, but treat a request to
8068 * turn on the monitor as a request to turn on the
8069 * fb too, we process components in descending order
8070 * Because autopm is disabled and processes aren't
8071 * running, it is ok to examine current power outside
8072 * of the power lock
8073 */
8074 for (i = nc - 1; i >= 0; i--, ip--) {
8075 if (PM_CURPOWER(dip, i) == *ip)
8076 continue;
8077 if (pm_set_power(dip, i, *ip, PM_LEVEL_EXACT,
8078 PM_CANBLOCK_BYPASS, 0, &result) != DDI_SUCCESS) {
8079 cmn_err(CE_WARN, "cpr: unable "
8080 "to restore power level of "
8081 "component %d of directly "
8082 "power manged device %s@%s"
8083 " to %d",
8084 i, PM_NAME(dip),
8085 PM_ADDR(dip), *ip);
8086 PMD(PMD_FAIL, ("%s: failed to restore "
8087 "%s@%s(%s#%d)[%d] exact(%d)->%d, "
8088 "errno %d\n", pmf, PM_DEVICE(dip), i,
8089 PM_CURPOWER(dip, i), *ip, result))
8090 }
8091 }
8092 if (nc > 2) {
8093 kmem_free(info->pmi_lp, nc * sizeof (int));
8094 info->pmi_lp = NULL;
8095 }
8096 }
8097 return (DDI_WALK_CONTINUE);
8098 }
8099
8100 /*
8101 * Stolen from the bootdev module
8102 * attempt to convert a path to a major number
8103 */
8104 static major_t
i_path_to_major(char * path,char * leaf_name)8105 i_path_to_major(char *path, char *leaf_name)
8106 {
8107 extern major_t path_to_major(char *pathname);
8108 major_t maj;
8109
8110 if ((maj = path_to_major(path)) == DDI_MAJOR_T_NONE) {
8111 maj = ddi_name_to_major(leaf_name);
8112 }
8113
8114 return (maj);
8115 }
8116
8117 static void i_pm_driver_removed(major_t major);
8118
8119 /*
8120 * When user calls rem_drv, we need to forget no-involuntary-power-cycles state
8121 * An entry in the list means that the device is detached, so we need to
8122 * adjust its ancestors as if they had just seen this attach, and any detached
8123 * ancestors need to have their list entries adjusted.
8124 */
8125 void
pm_driver_removed(major_t major)8126 pm_driver_removed(major_t major)
8127 {
8128
8129 /*
8130 * Serialize removal of drivers. This is to keep ancestors of
8131 * a node that is being deleted from getting deleted and added back
8132 * with different counters.
8133 */
8134 mutex_enter(&pm_remdrv_lock);
8135 i_pm_driver_removed(major);
8136 mutex_exit(&pm_remdrv_lock);
8137 }
8138
8139 static void adjust_ancestors(char *, int);
8140 static int pm_is_noinvol_ancestor(pm_noinvol_t *);
8141 static void pm_noinvol_process_ancestors(char *);
8142
8143 /*
8144 * This routine is called recursively by pm_noinvol_process_ancestors()
8145 */
8146 static void
i_pm_driver_removed(major_t major)8147 i_pm_driver_removed(major_t major)
8148 {
8149 PMD_FUNC(pmf, "driver_removed")
8150 pm_noinvol_t *ip, *pp = NULL;
8151 int wasvolpmd;
8152 ASSERT(major != DDI_MAJOR_T_NONE);
8153 PMD(PMD_NOINVOL, ("%s: %s\n", pmf, ddi_major_to_name(major)))
8154 again:
8155 rw_enter(&pm_noinvol_rwlock, RW_WRITER);
8156 for (ip = pm_noinvol_head; ip; pp = ip, ip = ip->ni_next) {
8157 if (major != ip->ni_major)
8158 continue;
8159 /*
8160 * If it is an ancestor of no-invol node, which is
8161 * not removed, skip it. This is to cover the case of
8162 * ancestor removed without removing its descendants.
8163 */
8164 if (pm_is_noinvol_ancestor(ip)) {
8165 ip->ni_flags |= PMC_DRIVER_REMOVED;
8166 continue;
8167 }
8168 wasvolpmd = ip->ni_wasvolpmd;
8169 /*
8170 * remove the entry from the list
8171 */
8172 if (pp) {
8173 PMD(PMD_NOINVOL, ("%s: freeing %s, prev is %s\n",
8174 pmf, ip->ni_path, pp->ni_path))
8175 pp->ni_next = ip->ni_next;
8176 } else {
8177 PMD(PMD_NOINVOL, ("%s: free %s head\n", pmf,
8178 ip->ni_path))
8179 ASSERT(pm_noinvol_head == ip);
8180 pm_noinvol_head = ip->ni_next;
8181 }
8182 rw_exit(&pm_noinvol_rwlock);
8183 adjust_ancestors(ip->ni_path, wasvolpmd);
8184 /*
8185 * Had an ancestor been removed before this node, it would have
8186 * been skipped. Adjust the no-invol counters for such skipped
8187 * ancestors.
8188 */
8189 pm_noinvol_process_ancestors(ip->ni_path);
8190 kmem_free(ip->ni_path, ip->ni_size);
8191 kmem_free(ip, sizeof (*ip));
8192 goto again;
8193 }
8194 rw_exit(&pm_noinvol_rwlock);
8195 }
8196
8197 /*
8198 * returns 1, if *aip is a ancestor of a no-invol node
8199 * 0, otherwise
8200 */
8201 static int
pm_is_noinvol_ancestor(pm_noinvol_t * aip)8202 pm_is_noinvol_ancestor(pm_noinvol_t *aip)
8203 {
8204 pm_noinvol_t *ip;
8205
8206 ASSERT(strlen(aip->ni_path) != 0);
8207 for (ip = pm_noinvol_head; ip; ip = ip->ni_next) {
8208 if (ip == aip)
8209 continue;
8210 /*
8211 * To be an ancestor, the path must be an initial substring of
8212 * the descendent, and end just before a '/' in the
8213 * descendent's path.
8214 */
8215 if ((strstr(ip->ni_path, aip->ni_path) == ip->ni_path) &&
8216 (ip->ni_path[strlen(aip->ni_path)] == '/'))
8217 return (1);
8218 }
8219 return (0);
8220 }
8221
8222 /*
8223 * scan through the pm_noinvolpm list adjusting ancestors of the current
8224 * node; Modifies string *path.
8225 */
8226 static void
adjust_ancestors(char * path,int wasvolpmd)8227 adjust_ancestors(char *path, int wasvolpmd)
8228 {
8229 PMD_FUNC(pmf, "adjust_ancestors")
8230 char *cp;
8231 pm_noinvol_t *lp;
8232 pm_noinvol_t *pp = NULL;
8233 major_t locked = DDI_MAJOR_T_NONE;
8234 dev_info_t *dip;
8235 char *pathbuf;
8236 size_t pathbuflen = strlen(path) + 1;
8237
8238 /*
8239 * First we look up the ancestor's dip. If we find it, then we
8240 * adjust counts up the tree
8241 */
8242 PMD(PMD_NOINVOL, ("%s: %s wasvolpmd %d\n", pmf, path, wasvolpmd))
8243 pathbuf = kmem_alloc(pathbuflen, KM_SLEEP);
8244 (void) strcpy(pathbuf, path);
8245 cp = strrchr(pathbuf, '/');
8246 if (cp == NULL) {
8247 /* if no ancestors, then nothing to do */
8248 kmem_free(pathbuf, pathbuflen);
8249 return;
8250 }
8251 *cp = '\0';
8252 dip = pm_name_to_dip(pathbuf, 1);
8253 if (dip != NULL) {
8254 locked = PM_MAJOR(dip);
8255
8256 (void) pm_noinvol_update(PM_BP_NOINVOL_REMDRV, 0, wasvolpmd,
8257 path, dip);
8258
8259 if (locked != DDI_MAJOR_T_NONE)
8260 ddi_release_devi(dip);
8261 } else {
8262 char *apath;
8263 size_t len = strlen(pathbuf) + 1;
8264 int lock_held = 1;
8265
8266 /*
8267 * Now check for ancestors that exist only in the list
8268 */
8269 apath = kmem_alloc(len, KM_SLEEP);
8270 (void) strcpy(apath, pathbuf);
8271 rw_enter(&pm_noinvol_rwlock, RW_WRITER);
8272 for (lp = pm_noinvol_head; lp; pp = lp, lp = lp->ni_next) {
8273 /*
8274 * This can only happen once. Since we have to drop
8275 * the lock, we need to extract the relevant info.
8276 */
8277 if (strcmp(pathbuf, lp->ni_path) == 0) {
8278 PMD(PMD_NOINVOL, ("%s: %s no %d -> %d\n", pmf,
8279 lp->ni_path, lp->ni_noinvolpm,
8280 lp->ni_noinvolpm - 1))
8281 lp->ni_noinvolpm--;
8282 if (wasvolpmd && lp->ni_volpmd) {
8283 PMD(PMD_NOINVOL, ("%s: %s vol %d -> "
8284 "%d\n", pmf, lp->ni_path,
8285 lp->ni_volpmd, lp->ni_volpmd - 1))
8286 lp->ni_volpmd--;
8287 }
8288 /*
8289 * remove the entry from the list, if there
8290 * are no more no-invol descendants and node
8291 * itself is not a no-invol node.
8292 */
8293 if (!(lp->ni_noinvolpm ||
8294 (lp->ni_flags & PMC_NO_INVOL))) {
8295 ASSERT(lp->ni_volpmd == 0);
8296 if (pp) {
8297 PMD(PMD_NOINVOL, ("%s: freeing "
8298 "%s, prev is %s\n", pmf,
8299 lp->ni_path, pp->ni_path))
8300 pp->ni_next = lp->ni_next;
8301 } else {
8302 PMD(PMD_NOINVOL, ("%s: free %s "
8303 "head\n", pmf, lp->ni_path))
8304 ASSERT(pm_noinvol_head == lp);
8305 pm_noinvol_head = lp->ni_next;
8306 }
8307 lock_held = 0;
8308 rw_exit(&pm_noinvol_rwlock);
8309 adjust_ancestors(apath, wasvolpmd);
8310 /* restore apath */
8311 (void) strcpy(apath, pathbuf);
8312 kmem_free(lp->ni_path, lp->ni_size);
8313 kmem_free(lp, sizeof (*lp));
8314 }
8315 break;
8316 }
8317 }
8318 if (lock_held)
8319 rw_exit(&pm_noinvol_rwlock);
8320 adjust_ancestors(apath, wasvolpmd);
8321 kmem_free(apath, len);
8322 }
8323 kmem_free(pathbuf, pathbuflen);
8324 }
8325
8326 /*
8327 * Do no-invol processing for any ancestors i.e. adjust counters of ancestors,
8328 * which were skipped even though their drivers were removed.
8329 */
8330 static void
pm_noinvol_process_ancestors(char * path)8331 pm_noinvol_process_ancestors(char *path)
8332 {
8333 pm_noinvol_t *lp;
8334
8335 rw_enter(&pm_noinvol_rwlock, RW_READER);
8336 for (lp = pm_noinvol_head; lp; lp = lp->ni_next) {
8337 if (strstr(path, lp->ni_path) &&
8338 (lp->ni_flags & PMC_DRIVER_REMOVED)) {
8339 rw_exit(&pm_noinvol_rwlock);
8340 i_pm_driver_removed(lp->ni_major);
8341 return;
8342 }
8343 }
8344 rw_exit(&pm_noinvol_rwlock);
8345 }
8346
8347 /*
8348 * Returns true if (detached) device needs to be kept up because it exported the
8349 * "no-involuntary-power-cycles" property or we're pretending it did (console
8350 * fb case) or it is an ancestor of such a device and has used up the "one
8351 * free cycle" allowed when all such leaf nodes have voluntarily powered down
8352 * upon detach. In any event, we need an exact hit on the path or we return
8353 * false.
8354 */
8355 int
pm_noinvol_detached(char * path)8356 pm_noinvol_detached(char *path)
8357 {
8358 PMD_FUNC(pmf, "noinvol_detached")
8359 pm_noinvol_t *ip;
8360 int ret = 0;
8361
8362 rw_enter(&pm_noinvol_rwlock, RW_READER);
8363 for (ip = pm_noinvol_head; ip; ip = ip->ni_next) {
8364 if (strcmp(path, ip->ni_path) == 0) {
8365 if (ip->ni_flags & PMC_CONSOLE_FB) {
8366 PMD(PMD_NOINVOL | PMD_CFB, ("%s: inhibits CFB "
8367 "%s\n", pmf, path))
8368 ret = 1;
8369 break;
8370 }
8371 #ifdef DEBUG
8372 if (ip->ni_noinvolpm != ip->ni_volpmd)
8373 PMD(PMD_NOINVOL, ("%s: (%d != %d) inhibits %s"
8374 "\n", pmf, ip->ni_noinvolpm, ip->ni_volpmd,
8375 path))
8376 #endif
8377 ret = (ip->ni_noinvolpm != ip->ni_volpmd);
8378 break;
8379 }
8380 }
8381 rw_exit(&pm_noinvol_rwlock);
8382 return (ret);
8383 }
8384
8385 int
pm_is_cfb(dev_info_t * dip)8386 pm_is_cfb(dev_info_t *dip)
8387 {
8388 return (dip == cfb_dip);
8389 }
8390
8391 #ifdef DEBUG
8392 /*
8393 * Return true if all components of the console frame buffer are at
8394 * "normal" power, i.e., fully on. For the case where the console is not
8395 * a framebuffer, we also return true
8396 */
8397 int
pm_cfb_is_up(void)8398 pm_cfb_is_up(void)
8399 {
8400 return (pm_cfb_comps_off == 0);
8401 }
8402 #endif
8403
8404 /*
8405 * Preventing scan from powering down the node by incrementing the
8406 * kidsupcnt.
8407 */
8408 void
pm_hold_power(dev_info_t * dip)8409 pm_hold_power(dev_info_t *dip)
8410 {
8411 e_pm_hold_rele_power(dip, 1);
8412 }
8413
8414 /*
8415 * Releasing the hold by decrementing the kidsupcnt allowing scan
8416 * to power down the node if all conditions are met.
8417 */
8418 void
pm_rele_power(dev_info_t * dip)8419 pm_rele_power(dev_info_t *dip)
8420 {
8421 e_pm_hold_rele_power(dip, -1);
8422 }
8423
8424 /*
8425 * A wrapper of pm_all_to_normal() to power up a dip
8426 * to its normal level
8427 */
8428 int
pm_powerup(dev_info_t * dip)8429 pm_powerup(dev_info_t *dip)
8430 {
8431 PMD_FUNC(pmf, "pm_powerup")
8432
8433 PMD(PMD_ALLNORM, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
8434 ASSERT(!(servicing_interrupt()));
8435
8436 /*
8437 * in case this node is not already participating pm
8438 */
8439 if (!PM_GET_PM_INFO(dip)) {
8440 if (!DEVI_IS_ATTACHING(dip))
8441 return (DDI_SUCCESS);
8442 if (pm_start(dip) != DDI_SUCCESS)
8443 return (DDI_FAILURE);
8444 if (!PM_GET_PM_INFO(dip))
8445 return (DDI_SUCCESS);
8446 }
8447
8448 return (pm_all_to_normal(dip, PM_CANBLOCK_BLOCK));
8449 }
8450
8451 int
pm_rescan_walk(dev_info_t * dip,void * arg)8452 pm_rescan_walk(dev_info_t *dip, void *arg)
8453 {
8454 _NOTE(ARGUNUSED(arg))
8455
8456 if (!PM_GET_PM_INFO(dip) || PM_ISBC(dip))
8457 return (DDI_WALK_CONTINUE);
8458
8459 /*
8460 * Currently pm_cpr_callb/resume code is the only caller
8461 * and it needs to make sure that stopped scan get
8462 * reactivated. Otherwise, rescan walk needn't reactive
8463 * stopped scan.
8464 */
8465 pm_scan_init(dip);
8466
8467 (void) pm_rescan(dip);
8468 return (DDI_WALK_CONTINUE);
8469 }
8470
8471 static dev_info_t *
pm_get_next_descendent(dev_info_t * dip,dev_info_t * tdip)8472 pm_get_next_descendent(dev_info_t *dip, dev_info_t *tdip)
8473 {
8474 dev_info_t *wdip, *pdip;
8475
8476 for (wdip = tdip; wdip != dip; wdip = pdip) {
8477 pdip = ddi_get_parent(wdip);
8478 if (pdip == dip)
8479 return (wdip);
8480 }
8481 return (NULL);
8482 }
8483
8484 int
pm_busop_bus_power(dev_info_t * dip,void * impl_arg,pm_bus_power_op_t op,void * arg,void * result)8485 pm_busop_bus_power(dev_info_t *dip, void *impl_arg, pm_bus_power_op_t op,
8486 void *arg, void *result)
8487 {
8488 PMD_FUNC(pmf, "bp_bus_power")
8489 dev_info_t *cdip;
8490 pm_info_t *cinfo;
8491 pm_bp_child_pwrchg_t *bpc;
8492 pm_sp_misc_t *pspm;
8493 pm_bp_nexus_pwrup_t *bpn;
8494 pm_bp_child_pwrchg_t new_bpc;
8495 pm_bp_noinvol_t *bpi;
8496 dev_info_t *tdip;
8497 char *pathbuf;
8498 int ret = DDI_SUCCESS;
8499 int errno = 0;
8500 pm_component_t *cp;
8501
8502 PMD(PMD_SET, ("%s: %s@%s(%s#%d) %s\n", pmf, PM_DEVICE(dip),
8503 pm_decode_op(op)))
8504 switch (op) {
8505 case BUS_POWER_CHILD_PWRCHG:
8506 bpc = (pm_bp_child_pwrchg_t *)arg;
8507 pspm = (pm_sp_misc_t *)bpc->bpc_private;
8508 tdip = bpc->bpc_dip;
8509 cdip = pm_get_next_descendent(dip, tdip);
8510 cinfo = PM_GET_PM_INFO(cdip);
8511 if (cdip != tdip) {
8512 /*
8513 * If the node is an involved parent, it needs to
8514 * power up the node as it is needed. There is nothing
8515 * else the framework can do here.
8516 */
8517 if (PM_WANTS_NOTIFICATION(cdip)) {
8518 PMD(PMD_SET, ("%s: call bus_power for "
8519 "%s@%s(%s#%d)\n", pmf, PM_DEVICE(cdip)))
8520 return ((*PM_BUS_POWER_FUNC(cdip))(cdip,
8521 impl_arg, op, arg, result));
8522 }
8523 ASSERT(pspm->pspm_direction == PM_LEVEL_UPONLY ||
8524 pspm->pspm_direction == PM_LEVEL_DOWNONLY ||
8525 pspm->pspm_direction == PM_LEVEL_EXACT);
8526 /*
8527 * we presume that the parent needs to be up in
8528 * order for the child to change state (either
8529 * because it must already be on if the child is on
8530 * (and the pm_all_to_normal_nexus() will be a nop)
8531 * or because it will need to be on for the child
8532 * to come on; so we make the call regardless
8533 */
8534 pm_hold_power(cdip);
8535 if (cinfo) {
8536 pm_canblock_t canblock = pspm->pspm_canblock;
8537 ret = pm_all_to_normal_nexus(cdip, canblock);
8538 if (ret != DDI_SUCCESS) {
8539 pm_rele_power(cdip);
8540 return (ret);
8541 }
8542 }
8543 PMD(PMD_SET, ("%s: walk down to %s@%s(%s#%d)\n", pmf,
8544 PM_DEVICE(cdip)))
8545 ret = pm_busop_bus_power(cdip, impl_arg, op, arg,
8546 result);
8547 pm_rele_power(cdip);
8548 } else {
8549 ret = pm_busop_set_power(cdip, impl_arg, op, arg,
8550 result);
8551 }
8552 return (ret);
8553
8554 case BUS_POWER_NEXUS_PWRUP:
8555 bpn = (pm_bp_nexus_pwrup_t *)arg;
8556 pspm = (pm_sp_misc_t *)bpn->bpn_private;
8557
8558 if (!e_pm_valid_info(dip, NULL) ||
8559 !e_pm_valid_comp(dip, bpn->bpn_comp, &cp) ||
8560 !e_pm_valid_power(dip, bpn->bpn_comp, bpn->bpn_level)) {
8561 PMD(PMD_SET, ("%s: %s@%s(%s#%d) has no pm info; EIO\n",
8562 pmf, PM_DEVICE(dip)))
8563 *pspm->pspm_errnop = EIO;
8564 *(int *)result = DDI_FAILURE;
8565 return (DDI_FAILURE);
8566 }
8567
8568 ASSERT(bpn->bpn_dip == dip);
8569 PMD(PMD_SET, ("%s: nexus powerup for %s@%s(%s#%d)\n", pmf,
8570 PM_DEVICE(dip)))
8571 new_bpc.bpc_dip = dip;
8572 pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
8573 new_bpc.bpc_path = ddi_pathname(dip, pathbuf);
8574 new_bpc.bpc_comp = bpn->bpn_comp;
8575 new_bpc.bpc_olevel = PM_CURPOWER(dip, bpn->bpn_comp);
8576 new_bpc.bpc_nlevel = bpn->bpn_level;
8577 new_bpc.bpc_private = bpn->bpn_private;
8578 ((pm_sp_misc_t *)(new_bpc.bpc_private))->pspm_direction =
8579 PM_LEVEL_UPONLY;
8580 ((pm_sp_misc_t *)(new_bpc.bpc_private))->pspm_errnop =
8581 &errno;
8582 ret = pm_busop_set_power(dip, impl_arg, BUS_POWER_CHILD_PWRCHG,
8583 (void *)&new_bpc, result);
8584 kmem_free(pathbuf, MAXPATHLEN);
8585 return (ret);
8586
8587 case BUS_POWER_NOINVOL:
8588 bpi = (pm_bp_noinvol_t *)arg;
8589 tdip = bpi->bpni_dip;
8590 cdip = pm_get_next_descendent(dip, tdip);
8591
8592 /* In case of rem_drv, the leaf node has been removed */
8593 if (cdip == NULL)
8594 return (DDI_SUCCESS);
8595
8596 cinfo = PM_GET_PM_INFO(cdip);
8597 if (cdip != tdip) {
8598 if (PM_WANTS_NOTIFICATION(cdip)) {
8599 PMD(PMD_NOINVOL,
8600 ("%s: call bus_power for %s@%s(%s#%d)\n",
8601 pmf, PM_DEVICE(cdip)))
8602 ret = (*PM_BUS_POWER_FUNC(cdip))
8603 (cdip, NULL, op, arg, result);
8604 if ((cinfo) && (ret == DDI_SUCCESS))
8605 (void) pm_noinvol_update_node(cdip,
8606 bpi);
8607 return (ret);
8608 } else {
8609 PMD(PMD_NOINVOL,
8610 ("%s: walk down to %s@%s(%s#%d)\n", pmf,
8611 PM_DEVICE(cdip)))
8612 ret = pm_busop_bus_power(cdip, NULL, op,
8613 arg, result);
8614 /*
8615 * Update the current node.
8616 */
8617 if ((cinfo) && (ret == DDI_SUCCESS))
8618 (void) pm_noinvol_update_node(cdip,
8619 bpi);
8620 return (ret);
8621 }
8622 } else {
8623 /*
8624 * For attach, detach, power up:
8625 * Do nothing for leaf node since its
8626 * counts are already updated.
8627 * For CFB and driver removal, since the
8628 * path and the target dip passed in is up to and incl.
8629 * the immediate ancestor, need to do the update.
8630 */
8631 PMD(PMD_NOINVOL, ("%s: target %s@%s(%s#%d) is "
8632 "reached\n", pmf, PM_DEVICE(cdip)))
8633 if (cinfo && ((bpi->bpni_cmd == PM_BP_NOINVOL_REMDRV) ||
8634 (bpi->bpni_cmd == PM_BP_NOINVOL_CFB)))
8635 (void) pm_noinvol_update_node(cdip, bpi);
8636 return (DDI_SUCCESS);
8637 }
8638
8639 default:
8640 PMD(PMD_SET, ("%s: operation %d is not supported!\n", pmf, op))
8641 return (DDI_FAILURE);
8642 }
8643 }
8644
8645 static int
pm_busop_set_power(dev_info_t * dip,void * impl_arg,pm_bus_power_op_t op,void * arg,void * resultp)8646 pm_busop_set_power(dev_info_t *dip, void *impl_arg, pm_bus_power_op_t op,
8647 void *arg, void *resultp)
8648 {
8649 _NOTE(ARGUNUSED(impl_arg))
8650 PMD_FUNC(pmf, "bp_set_power")
8651 pm_ppm_devlist_t *devl = NULL;
8652 int clevel, circ;
8653 #ifdef DEBUG
8654 int circ_db, ccirc_db;
8655 #endif
8656 int ret = DDI_SUCCESS;
8657 dev_info_t *cdip;
8658 pm_bp_child_pwrchg_t *bpc = (pm_bp_child_pwrchg_t *)arg;
8659 pm_sp_misc_t *pspm = (pm_sp_misc_t *)bpc->bpc_private;
8660 pm_canblock_t canblock = pspm->pspm_canblock;
8661 int scan = pspm->pspm_scan;
8662 int comp = bpc->bpc_comp;
8663 int olevel = bpc->bpc_olevel;
8664 int nlevel = bpc->bpc_nlevel;
8665 int comps_off_incr = 0;
8666 dev_info_t *pdip = ddi_get_parent(dip);
8667 int dodeps;
8668 int direction = pspm->pspm_direction;
8669 int *errnop = pspm->pspm_errnop;
8670 #ifdef PMDDEBUG
8671 char *dir = pm_decode_direction(direction);
8672 #endif
8673 int *iresp = (int *)resultp;
8674 time_t idletime, thresh;
8675 pm_component_t *cp = PM_CP(dip, comp);
8676 int work_type;
8677
8678 *iresp = DDI_SUCCESS;
8679 *errnop = 0;
8680 ASSERT(op == BUS_POWER_CHILD_PWRCHG);
8681 PMD(PMD_SET, ("%s: %s@%s(%s#%d) %s\n", pmf, PM_DEVICE(dip),
8682 pm_decode_op(op)))
8683
8684 /*
8685 * The following set of conditions indicate we are here to handle a
8686 * driver's pm_[raise|lower]_power request, but the device is being
8687 * power managed (PM_DIRECT_PM) by a user process. For that case
8688 * we want to pm_block and pass a status back to the caller based
8689 * on whether the controlling process's next activity on the device
8690 * matches the current request or not. This distinction tells
8691 * downstream functions to avoid calling into a driver or changing
8692 * the framework's power state. To actually block, we need:
8693 *
8694 * PM_ISDIRECT(dip)
8695 * no reason to block unless a process is directly controlling dev
8696 * direction != PM_LEVEL_EXACT
8697 * EXACT is used by controlling proc's PM_SET_CURRENT_POWER ioctl
8698 * !pm_processes_stopped
8699 * don't block if controlling proc already be stopped for cpr
8700 * canblock != PM_CANBLOCK_BYPASS
8701 * our caller must not have explicitly prevented blocking
8702 */
8703 if (direction != PM_LEVEL_EXACT && canblock != PM_CANBLOCK_BYPASS) {
8704 PM_LOCK_DIP(dip);
8705 while (PM_ISDIRECT(dip) && !pm_processes_stopped) {
8706 /* releases dip lock */
8707 ret = pm_busop_match_request(dip, bpc);
8708 if (ret == EAGAIN) {
8709 PM_LOCK_DIP(dip);
8710 continue;
8711 }
8712 return (*iresp = ret);
8713 }
8714 PM_UNLOCK_DIP(dip);
8715 }
8716 /* BC device is never scanned, so power will stick until we are done */
8717 if (PM_ISBC(dip) && comp != 0 && nlevel != 0 &&
8718 direction != PM_LEVEL_DOWNONLY) {
8719 int nrmpwr0 = pm_get_normal_power(dip, 0);
8720 if (pm_set_power(dip, 0, nrmpwr0, direction,
8721 canblock, 0, resultp) != DDI_SUCCESS) {
8722 /* *resultp set by pm_set_power */
8723 return (DDI_FAILURE);
8724 }
8725 }
8726 if (PM_WANTS_NOTIFICATION(pdip)) {
8727 PMD(PMD_SET, ("%s: pre_notify %s@%s(%s#%d) for child "
8728 "%s@%s(%s#%d)\n", pmf, PM_DEVICE(pdip), PM_DEVICE(dip)))
8729 ret = (*PM_BUS_POWER_FUNC(pdip))(pdip, NULL,
8730 BUS_POWER_PRE_NOTIFICATION, bpc, resultp);
8731 if (ret != DDI_SUCCESS) {
8732 PMD(PMD_SET, ("%s: failed to pre_notify %s@%s(%s#%d)\n",
8733 pmf, PM_DEVICE(pdip)))
8734 return (DDI_FAILURE);
8735 }
8736 } else {
8737 /*
8738 * Since we don't know what the actual power level is,
8739 * we place a power hold on the parent no matter what
8740 * component and level is changing.
8741 */
8742 pm_hold_power(pdip);
8743 }
8744 PM_LOCK_POWER(dip, &circ);
8745 clevel = PM_CURPOWER(dip, comp);
8746 /*
8747 * It's possible that a call was made to pm_update_maxpower()
8748 * on another thread before we took the lock above. So, we need to
8749 * make sure that this request isn't processed after the
8750 * change of power executed on behalf of pm_update_maxpower().
8751 */
8752 if (nlevel > pm_get_normal_power(dip, comp)) {
8753 PMD(PMD_SET, ("%s: requested level is higher than normal.\n",
8754 pmf))
8755 ret = DDI_FAILURE;
8756 *iresp = DDI_FAILURE;
8757 goto post_notify;
8758 }
8759 PMD(PMD_SET, ("%s: %s@%s(%s#%d), cmp=%d, olvl=%d, nlvl=%d, clvl=%d, "
8760 "dir=%s\n", pmf, PM_DEVICE(dip), comp, bpc->bpc_olevel, nlevel,
8761 clevel, dir))
8762 switch (direction) {
8763 case PM_LEVEL_UPONLY:
8764 /* Powering up */
8765 if (clevel >= nlevel) {
8766 PMD(PMD_SET, ("%s: current level is already "
8767 "at or above the requested level.\n", pmf))
8768 *iresp = DDI_SUCCESS;
8769 ret = DDI_SUCCESS;
8770 goto post_notify;
8771 }
8772 break;
8773 case PM_LEVEL_EXACT:
8774 /* specific level request */
8775 if (clevel == nlevel && !PM_ISBC(dip)) {
8776 PMD(PMD_SET, ("%s: current level is already "
8777 "at the requested level.\n", pmf))
8778 *iresp = DDI_SUCCESS;
8779 ret = DDI_SUCCESS;
8780 goto post_notify;
8781 } else if (PM_IS_CFB(dip) && (nlevel < clevel)) {
8782 PMD(PMD_CFB, ("%s: powerdown of console\n", pmf))
8783 if (!pm_cfb_enabled) {
8784 PMD(PMD_ERROR | PMD_CFB,
8785 ("%s: !pm_cfb_enabled, fails\n", pmf))
8786 *errnop = EINVAL;
8787 *iresp = DDI_FAILURE;
8788 ret = DDI_FAILURE;
8789 goto post_notify;
8790 }
8791 mutex_enter(&pm_cfb_lock);
8792 while (cfb_inuse) {
8793 mutex_exit(&pm_cfb_lock);
8794 if (delay_sig(1) == EINTR) {
8795 ret = DDI_FAILURE;
8796 *iresp = DDI_FAILURE;
8797 *errnop = EINTR;
8798 goto post_notify;
8799 }
8800 mutex_enter(&pm_cfb_lock);
8801 }
8802 mutex_exit(&pm_cfb_lock);
8803 }
8804 break;
8805 case PM_LEVEL_DOWNONLY:
8806 /* Powering down */
8807 thresh = cur_threshold(dip, comp);
8808 idletime = gethrestime_sec() - cp->pmc_timestamp;
8809 if (scan && ((PM_KUC(dip) != 0) ||
8810 (cp->pmc_busycount > 0) ||
8811 ((idletime < thresh) && !PM_IS_PID(dip)))) {
8812 #ifdef DEBUG
8813 if (DEVI(dip)->devi_pm_kidsupcnt != 0)
8814 PMD(PMD_SET, ("%s: scan failed: "
8815 "kidsupcnt != 0\n", pmf))
8816 if (cp->pmc_busycount > 0)
8817 PMD(PMD_SET, ("%s: scan failed: "
8818 "device become busy\n", pmf))
8819 if (idletime < thresh)
8820 PMD(PMD_SET, ("%s: scan failed: device "
8821 "hasn't been idle long enough\n", pmf))
8822 #endif
8823 *iresp = DDI_FAILURE;
8824 *errnop = EBUSY;
8825 ret = DDI_FAILURE;
8826 goto post_notify;
8827 } else if (clevel != PM_LEVEL_UNKNOWN && clevel <= nlevel) {
8828 PMD(PMD_SET, ("%s: current level is already at "
8829 "or below the requested level.\n", pmf))
8830 *iresp = DDI_SUCCESS;
8831 ret = DDI_SUCCESS;
8832 goto post_notify;
8833 }
8834 break;
8835 }
8836
8837 if (PM_IS_CFB(dip) && (comps_off_incr =
8838 calc_cfb_comps_incr(dip, comp, clevel, nlevel)) > 0) {
8839 /*
8840 * Pre-adjust pm_cfb_comps_off if lowering a console fb
8841 * component from full power. Remember that we tried to
8842 * lower power in case it fails and we need to back out
8843 * the adjustment.
8844 */
8845 update_comps_off(comps_off_incr, dip);
8846 PMD(PMD_CFB, ("%s: %s@%s(%s#%d)[%d] %d->%d cfb_comps_off->%d\n",
8847 pmf, PM_DEVICE(dip), comp, clevel, nlevel,
8848 pm_cfb_comps_off))
8849 }
8850
8851 if ((*iresp = power_dev(dip,
8852 comp, nlevel, clevel, canblock, &devl)) == DDI_SUCCESS) {
8853 #ifdef DEBUG
8854 /*
8855 * All descendents of this node should already be powered off.
8856 */
8857 if (PM_CURPOWER(dip, comp) == 0) {
8858 pm_desc_pwrchk_t pdpchk;
8859 pdpchk.pdpc_dip = dip;
8860 pdpchk.pdpc_par_involved = PM_WANTS_NOTIFICATION(dip);
8861 ndi_devi_enter(dip, &circ_db);
8862 for (cdip = ddi_get_child(dip); cdip != NULL;
8863 cdip = ddi_get_next_sibling(cdip)) {
8864 ndi_devi_enter(cdip, &ccirc_db);
8865 ddi_walk_devs(cdip, pm_desc_pwrchk_walk,
8866 (void *)&pdpchk);
8867 ndi_devi_exit(cdip, ccirc_db);
8868 }
8869 ndi_devi_exit(dip, circ_db);
8870 }
8871 #endif
8872 /*
8873 * Post-adjust pm_cfb_comps_off if we brought an fb component
8874 * back up to full power.
8875 */
8876 if (PM_IS_CFB(dip) && comps_off_incr < 0) {
8877 update_comps_off(comps_off_incr, dip);
8878 PMD(PMD_CFB, ("%s: %s@%s(%s#%d)[%d] %d->%d "
8879 "cfb_comps_off->%d\n", pmf, PM_DEVICE(dip),
8880 comp, clevel, nlevel, pm_cfb_comps_off))
8881 }
8882 dodeps = 0;
8883 if (POWERING_OFF(clevel, nlevel)) {
8884 if (PM_ISBC(dip)) {
8885 dodeps = (comp == 0);
8886 } else {
8887 int i;
8888 dodeps = 1;
8889 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
8890 /* if some component still on */
8891 if (PM_CURPOWER(dip, i)) {
8892 dodeps = 0;
8893 break;
8894 }
8895 }
8896 }
8897 if (dodeps)
8898 work_type = PM_DEP_WK_POWER_OFF;
8899 } else if (POWERING_ON(clevel, nlevel)) {
8900 if (PM_ISBC(dip)) {
8901 dodeps = (comp == 0);
8902 } else {
8903 int i;
8904 dodeps = 1;
8905 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
8906 if (i == comp)
8907 continue;
8908 if (PM_CURPOWER(dip, i) > 0) {
8909 dodeps = 0;
8910 break;
8911 }
8912 }
8913 }
8914 if (dodeps)
8915 work_type = PM_DEP_WK_POWER_ON;
8916 }
8917
8918 if (dodeps) {
8919 char *pathbuf = kmem_alloc(MAXPATHLEN, KM_SLEEP);
8920
8921 (void) ddi_pathname(dip, pathbuf);
8922 pm_dispatch_to_dep_thread(work_type, pathbuf, NULL,
8923 PM_DEP_NOWAIT, NULL, 0);
8924 kmem_free(pathbuf, MAXPATHLEN);
8925 }
8926 if ((PM_CURPOWER(dip, comp) == nlevel) && pm_watchers()) {
8927 int old;
8928
8929 /* If old power cached during deadlock, use it. */
8930 old = (cp->pmc_flags & PM_PHC_WHILE_SET_POWER ?
8931 cp->pmc_phc_pwr : olevel);
8932 mutex_enter(&pm_rsvp_lock);
8933 pm_enqueue_notify(PSC_HAS_CHANGED, dip, comp, nlevel,
8934 old, canblock);
8935 pm_enqueue_notify_others(&devl, canblock);
8936 mutex_exit(&pm_rsvp_lock);
8937 } else {
8938 pm_ppm_devlist_t *p;
8939 pm_ppm_devlist_t *next;
8940 for (p = devl; p != NULL; p = next) {
8941 next = p->ppd_next;
8942 kmem_free(p, sizeof (pm_ppm_devlist_t));
8943 }
8944 devl = NULL;
8945 }
8946
8947 /*
8948 * If we are coming from a scan, don't do it again,
8949 * else we can have infinite loops.
8950 */
8951 if (!scan)
8952 pm_rescan(dip);
8953 } else {
8954 /* if we incremented pm_comps_off_count, but failed */
8955 if (comps_off_incr > 0) {
8956 update_comps_off(-comps_off_incr, dip);
8957 PMD(PMD_CFB, ("%s: %s@%s(%s#%d)[%d] %d->%d "
8958 "cfb_comps_off->%d\n", pmf, PM_DEVICE(dip),
8959 comp, clevel, nlevel, pm_cfb_comps_off))
8960 }
8961 *errnop = EIO;
8962 }
8963
8964 post_notify:
8965 /*
8966 * This thread may have been in deadlock with pm_power_has_changed.
8967 * Before releasing power lock, clear the flag which marks this
8968 * condition.
8969 */
8970 cp->pmc_flags &= ~PM_PHC_WHILE_SET_POWER;
8971
8972 /*
8973 * Update the old power level in the bus power structure with the
8974 * actual power level before the transition was made to the new level.
8975 * Some involved parents depend on this information to keep track of
8976 * their children's power transition.
8977 */
8978 if (*iresp != DDI_FAILURE)
8979 bpc->bpc_olevel = clevel;
8980
8981 if (PM_WANTS_NOTIFICATION(pdip)) {
8982 ret = (*PM_BUS_POWER_FUNC(pdip))(pdip, NULL,
8983 BUS_POWER_POST_NOTIFICATION, bpc, resultp);
8984 PM_UNLOCK_POWER(dip, circ);
8985 PMD(PMD_SET, ("%s: post_notify %s@%s(%s#%d) for "
8986 "child %s@%s(%s#%d), ret=%d\n", pmf, PM_DEVICE(pdip),
8987 PM_DEVICE(dip), ret))
8988 } else {
8989 nlevel = cur_power(cp); /* in case phc deadlock updated pwr */
8990 PM_UNLOCK_POWER(dip, circ);
8991 /*
8992 * Now that we know what power transition has occurred
8993 * (if any), release the power hold. Leave the hold
8994 * in effect in the case of OFF->ON transition.
8995 */
8996 if (!(clevel == 0 && nlevel > 0 &&
8997 (!PM_ISBC(dip) || comp == 0)))
8998 pm_rele_power(pdip);
8999 /*
9000 * If the power transition was an ON->OFF transition,
9001 * remove the power hold from the parent.
9002 */
9003 if ((clevel > 0 || clevel == PM_LEVEL_UNKNOWN) &&
9004 nlevel == 0 && (!PM_ISBC(dip) || comp == 0))
9005 pm_rele_power(pdip);
9006 }
9007 if (*iresp != DDI_SUCCESS || ret != DDI_SUCCESS)
9008 return (DDI_FAILURE);
9009 else
9010 return (DDI_SUCCESS);
9011 }
9012
9013 /*
9014 * If an app (SunVTS or Xsun) has taken control, then block until it
9015 * gives it up or makes the requested power level change, unless
9016 * we have other instructions about blocking. Returns DDI_SUCCESS,
9017 * DDI_FAILURE or EAGAIN (owner released device from directpm).
9018 */
9019 static int
pm_busop_match_request(dev_info_t * dip,void * arg)9020 pm_busop_match_request(dev_info_t *dip, void *arg)
9021 {
9022 PMD_FUNC(pmf, "bp_match_request")
9023 pm_bp_child_pwrchg_t *bpc = (pm_bp_child_pwrchg_t *)arg;
9024 pm_sp_misc_t *pspm = (pm_sp_misc_t *)bpc->bpc_private;
9025 int comp = bpc->bpc_comp;
9026 int nlevel = bpc->bpc_nlevel;
9027 pm_canblock_t canblock = pspm->pspm_canblock;
9028 int direction = pspm->pspm_direction;
9029 int clevel, circ;
9030
9031 ASSERT(PM_IAM_LOCKING_DIP(dip));
9032 PM_LOCK_POWER(dip, &circ);
9033 clevel = PM_CURPOWER(dip, comp);
9034 PMD(PMD_SET, ("%s: %s@%s(%s#%d), cmp=%d, nlvl=%d, clvl=%d\n",
9035 pmf, PM_DEVICE(dip), comp, nlevel, clevel))
9036 if (direction == PM_LEVEL_UPONLY) {
9037 if (clevel >= nlevel) {
9038 PM_UNLOCK_POWER(dip, circ);
9039 PM_UNLOCK_DIP(dip);
9040 return (DDI_SUCCESS);
9041 }
9042 } else if (clevel == nlevel) {
9043 PM_UNLOCK_POWER(dip, circ);
9044 PM_UNLOCK_DIP(dip);
9045 return (DDI_SUCCESS);
9046 }
9047 if (canblock == PM_CANBLOCK_FAIL) {
9048 PM_UNLOCK_POWER(dip, circ);
9049 PM_UNLOCK_DIP(dip);
9050 return (DDI_FAILURE);
9051 }
9052 if (canblock == PM_CANBLOCK_BLOCK) {
9053 /*
9054 * To avoid a deadlock, we must not hold the
9055 * power lock when we pm_block.
9056 */
9057 PM_UNLOCK_POWER(dip, circ);
9058 PMD(PMD_SET, ("%s: blocking\n", pmf))
9059 /* pm_block releases dip lock */
9060 switch (pm_block(dip, comp, nlevel, clevel)) {
9061 case PMP_RELEASE:
9062 return (EAGAIN);
9063 case PMP_SUCCEED:
9064 return (DDI_SUCCESS);
9065 case PMP_FAIL:
9066 return (DDI_FAILURE);
9067 }
9068 } else {
9069 ASSERT(0);
9070 }
9071 _NOTE(NOTREACHED);
9072 return (DDI_FAILURE); /* keep gcc happy */
9073 }
9074
9075 static int
pm_all_to_normal_nexus(dev_info_t * dip,pm_canblock_t canblock)9076 pm_all_to_normal_nexus(dev_info_t *dip, pm_canblock_t canblock)
9077 {
9078 PMD_FUNC(pmf, "all_to_normal_nexus")
9079 int *normal;
9080 int i, ncomps;
9081 size_t size;
9082 int changefailed = 0;
9083 int ret, result = DDI_SUCCESS;
9084 pm_bp_nexus_pwrup_t bpn;
9085 pm_sp_misc_t pspm;
9086
9087 ASSERT(PM_GET_PM_INFO(dip));
9088 PMD(PMD_ALLNORM, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
9089 if (pm_get_norm_pwrs(dip, &normal, &size) != DDI_SUCCESS) {
9090 PMD(PMD_ALLNORM, ("%s: can't get norm pwrs\n", pmf))
9091 return (DDI_FAILURE);
9092 }
9093 ncomps = PM_NUMCMPTS(dip);
9094 for (i = 0; i < ncomps; i++) {
9095 bpn.bpn_dip = dip;
9096 bpn.bpn_comp = i;
9097 bpn.bpn_level = normal[i];
9098 pspm.pspm_canblock = canblock;
9099 pspm.pspm_scan = 0;
9100 bpn.bpn_private = &pspm;
9101 ret = pm_busop_bus_power(dip, NULL, BUS_POWER_NEXUS_PWRUP,
9102 (void *)&bpn, (void *)&result);
9103 if (ret != DDI_SUCCESS || result != DDI_SUCCESS) {
9104 PMD(PMD_FAIL | PMD_ALLNORM, ("%s: %s@%s(%s#%d)[%d] "
9105 "->%d failure result %d\n", pmf, PM_DEVICE(dip),
9106 i, normal[i], result))
9107 changefailed++;
9108 }
9109 }
9110 kmem_free(normal, size);
9111 if (changefailed) {
9112 PMD(PMD_FAIL, ("%s: failed to set %d comps %s@%s(%s#%d) "
9113 "full power\n", pmf, changefailed, PM_DEVICE(dip)))
9114 return (DDI_FAILURE);
9115 }
9116 return (DDI_SUCCESS);
9117 }
9118
9119 int
pm_noinvol_update(int subcmd,int volpmd,int wasvolpmd,char * path,dev_info_t * tdip)9120 pm_noinvol_update(int subcmd, int volpmd, int wasvolpmd, char *path,
9121 dev_info_t *tdip)
9122 {
9123 PMD_FUNC(pmf, "noinvol_update")
9124 pm_bp_noinvol_t args;
9125 int ret;
9126 int result = DDI_SUCCESS;
9127
9128 args.bpni_path = path;
9129 args.bpni_dip = tdip;
9130 args.bpni_cmd = subcmd;
9131 args.bpni_wasvolpmd = wasvolpmd;
9132 args.bpni_volpmd = volpmd;
9133 PMD(PMD_NOINVOL, ("%s: update for path %s tdip %p subcmd %d "
9134 "volpmd %d wasvolpmd %d\n", pmf,
9135 path, (void *)tdip, subcmd, wasvolpmd, volpmd))
9136 ret = pm_busop_bus_power(ddi_root_node(), NULL, BUS_POWER_NOINVOL,
9137 &args, &result);
9138 return (ret);
9139 }
9140
9141 void
pm_noinvol_update_node(dev_info_t * dip,pm_bp_noinvol_t * req)9142 pm_noinvol_update_node(dev_info_t *dip, pm_bp_noinvol_t *req)
9143 {
9144 PMD_FUNC(pmf, "noinvol_update_node")
9145
9146 PMD(PMD_NOINVOL, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
9147 switch (req->bpni_cmd) {
9148 case PM_BP_NOINVOL_ATTACH:
9149 PMD(PMD_NOINVOL, ("%s: PM_PB_NOINVOL_ATTACH %s@%s(%s#%d) "
9150 "noinvol %d->%d\n", pmf, PM_DEVICE(dip),
9151 DEVI(dip)->devi_pm_noinvolpm,
9152 DEVI(dip)->devi_pm_noinvolpm - 1))
9153 ASSERT(DEVI(dip)->devi_pm_noinvolpm);
9154 PM_LOCK_DIP(dip);
9155 DEVI(dip)->devi_pm_noinvolpm--;
9156 if (req->bpni_wasvolpmd) {
9157 PMD(PMD_NOINVOL, ("%s: PM_BP_NOINVOL_ATTACH "
9158 "%s@%s(%s#%d) volpmd %d->%d\n", pmf,
9159 PM_DEVICE(dip), DEVI(dip)->devi_pm_volpmd,
9160 DEVI(dip)->devi_pm_volpmd - 1))
9161 if (DEVI(dip)->devi_pm_volpmd)
9162 DEVI(dip)->devi_pm_volpmd--;
9163 }
9164 PM_UNLOCK_DIP(dip);
9165 break;
9166
9167 case PM_BP_NOINVOL_DETACH:
9168 PMD(PMD_NOINVOL, ("%s: PM_BP_NOINVOL_DETACH %s@%s(%s#%d) "
9169 "noinvolpm %d->%d\n", pmf, PM_DEVICE(dip),
9170 DEVI(dip)->devi_pm_noinvolpm,
9171 DEVI(dip)->devi_pm_noinvolpm + 1))
9172 PM_LOCK_DIP(dip);
9173 DEVI(dip)->devi_pm_noinvolpm++;
9174 if (req->bpni_wasvolpmd) {
9175 PMD(PMD_NOINVOL, ("%s: PM_BP_NOINVOL_DETACH "
9176 "%s@%s(%s#%d) volpmd %d->%d\n", pmf,
9177 PM_DEVICE(dip), DEVI(dip)->devi_pm_volpmd,
9178 DEVI(dip)->devi_pm_volpmd + 1))
9179 DEVI(dip)->devi_pm_volpmd++;
9180 }
9181 PM_UNLOCK_DIP(dip);
9182 break;
9183
9184 case PM_BP_NOINVOL_REMDRV:
9185 PMD(PMD_NOINVOL, ("%s: PM_BP_NOINVOL_REMDRV %s@%s(%s#%d) "
9186 "noinvol %d->%d\n", pmf, PM_DEVICE(dip),
9187 DEVI(dip)->devi_pm_noinvolpm,
9188 DEVI(dip)->devi_pm_noinvolpm - 1))
9189 ASSERT(DEVI(dip)->devi_pm_noinvolpm);
9190 PM_LOCK_DIP(dip);
9191 DEVI(dip)->devi_pm_noinvolpm--;
9192 if (req->bpni_wasvolpmd) {
9193 PMD(PMD_NOINVOL,
9194 ("%s: PM_BP_NOINVOL_REMDRV %s@%s(%s#%d) "
9195 "volpmd %d->%d\n", pmf, PM_DEVICE(dip),
9196 DEVI(dip)->devi_pm_volpmd,
9197 DEVI(dip)->devi_pm_volpmd - 1))
9198 /*
9199 * A power up could come in between and
9200 * clear the volpmd, if that's the case,
9201 * volpmd would be clear.
9202 */
9203 if (DEVI(dip)->devi_pm_volpmd)
9204 DEVI(dip)->devi_pm_volpmd--;
9205 }
9206 PM_UNLOCK_DIP(dip);
9207 break;
9208
9209 case PM_BP_NOINVOL_CFB:
9210 PMD(PMD_NOINVOL,
9211 ("%s: PM_BP_NOIVOL_CFB %s@%s(%s#%d) noinvol %d->%d\n",
9212 pmf, PM_DEVICE(dip), DEVI(dip)->devi_pm_noinvolpm,
9213 DEVI(dip)->devi_pm_noinvolpm + 1))
9214 PM_LOCK_DIP(dip);
9215 DEVI(dip)->devi_pm_noinvolpm++;
9216 PM_UNLOCK_DIP(dip);
9217 break;
9218
9219 case PM_BP_NOINVOL_POWER:
9220 PMD(PMD_NOINVOL,
9221 ("%s: PM_BP_NOIVOL_PWR %s@%s(%s#%d) volpmd %d->%d\n",
9222 pmf, PM_DEVICE(dip),
9223 DEVI(dip)->devi_pm_volpmd, DEVI(dip)->devi_pm_volpmd -
9224 req->bpni_volpmd))
9225 PM_LOCK_DIP(dip);
9226 DEVI(dip)->devi_pm_volpmd -= req->bpni_volpmd;
9227 PM_UNLOCK_DIP(dip);
9228 break;
9229
9230 default:
9231 break;
9232 }
9233
9234 }
9235
9236 #ifdef DEBUG
9237 static int
pm_desc_pwrchk_walk(dev_info_t * dip,void * arg)9238 pm_desc_pwrchk_walk(dev_info_t *dip, void *arg)
9239 {
9240 PMD_FUNC(pmf, "desc_pwrchk")
9241 pm_desc_pwrchk_t *pdpchk = (pm_desc_pwrchk_t *)arg;
9242 pm_info_t *info = PM_GET_PM_INFO(dip);
9243 int i;
9244 /* LINTED */
9245 int curpwr, ce_level;
9246
9247 if (!info)
9248 return (DDI_WALK_CONTINUE);
9249
9250 PMD(PMD_SET, ("%s: %s@%s(%s#%d)\n", pmf, PM_DEVICE(dip)))
9251 for (i = 0; i < PM_NUMCMPTS(dip); i++) {
9252 /* LINTED */
9253 if ((curpwr = PM_CURPOWER(dip, i)) == 0)
9254 continue;
9255 /* E_FUNC_SET_NOT_USED */
9256 ce_level = (pdpchk->pdpc_par_involved == 0) ? CE_PANIC :
9257 CE_WARN;
9258 PMD(PMD_SET, ("%s: %s@%s(%s#%d) is powered off while desc "
9259 "%s@%s(%s#%d)[%d] is at %d\n", pmf,
9260 PM_DEVICE(pdpchk->pdpc_dip), PM_DEVICE(dip), i, curpwr))
9261 cmn_err(ce_level, "!device %s@%s(%s#%d) is powered on, "
9262 "while its ancestor, %s@%s(%s#%d), is powering off!",
9263 PM_DEVICE(dip), PM_DEVICE(pdpchk->pdpc_dip));
9264 }
9265 return (DDI_WALK_CONTINUE);
9266 }
9267 #endif
9268
9269 /*
9270 * Record the fact that one thread is borrowing the lock on a device node.
9271 * Use is restricted to the case where the lending thread will block until
9272 * the borrowing thread (always curthread) completes.
9273 */
9274 void
pm_borrow_lock(kthread_t * lender)9275 pm_borrow_lock(kthread_t *lender)
9276 {
9277 lock_loan_t *prev = &lock_loan_head;
9278 lock_loan_t *cur = (lock_loan_t *)kmem_zalloc(sizeof (*cur), KM_SLEEP);
9279
9280 cur->pmlk_borrower = curthread;
9281 cur->pmlk_lender = lender;
9282 mutex_enter(&pm_loan_lock);
9283 cur->pmlk_next = prev->pmlk_next;
9284 prev->pmlk_next = cur;
9285 mutex_exit(&pm_loan_lock);
9286 }
9287
9288 /*
9289 * Return the borrowed lock. A thread can borrow only one.
9290 */
9291 void
pm_return_lock(void)9292 pm_return_lock(void)
9293 {
9294 lock_loan_t *cur;
9295 lock_loan_t *prev = &lock_loan_head;
9296
9297 mutex_enter(&pm_loan_lock);
9298 ASSERT(prev->pmlk_next != NULL);
9299 for (cur = prev->pmlk_next; cur; prev = cur, cur = cur->pmlk_next)
9300 if (cur->pmlk_borrower == curthread)
9301 break;
9302
9303 ASSERT(cur != NULL);
9304 prev->pmlk_next = cur->pmlk_next;
9305 mutex_exit(&pm_loan_lock);
9306 kmem_free(cur, sizeof (*cur));
9307 }
9308
9309 #if defined(__x86)
9310
9311 #define CPR_RXR 0x1
9312 #define CPR_TXR 0x20
9313 #define CPR_DATAREG 0x3f8
9314 #define CPR_LSTAT 0x3fd
9315 #define CPR_INTRCTL 0x3f9
9316
9317 char
pm_getchar(void)9318 pm_getchar(void)
9319 {
9320 while ((inb(CPR_LSTAT) & CPR_RXR) != CPR_RXR)
9321 drv_usecwait(10);
9322
9323 return (inb(CPR_DATAREG));
9324
9325 }
9326
9327 void
pm_putchar(char c)9328 pm_putchar(char c)
9329 {
9330 while ((inb(CPR_LSTAT) & CPR_TXR) == 0)
9331 drv_usecwait(10);
9332
9333 outb(CPR_DATAREG, c);
9334 }
9335
9336 void
pm_printf(char * s)9337 pm_printf(char *s)
9338 {
9339 while (*s) {
9340 pm_putchar(*s++);
9341 }
9342 }
9343
9344 #endif
9345
9346 int
pm_ppm_searchlist(pm_searchargs_t * sp)9347 pm_ppm_searchlist(pm_searchargs_t *sp)
9348 {
9349 power_req_t power_req;
9350 int result = 0;
9351 /* LINTED */
9352 int ret;
9353
9354 power_req.request_type = PMR_PPM_SEARCH_LIST;
9355 power_req.req.ppm_search_list_req.searchlist = sp;
9356 ASSERT(DEVI(ddi_root_node())->devi_pm_ppm);
9357 ret = pm_ctlops((dev_info_t *)DEVI(ddi_root_node())->devi_pm_ppm,
9358 ddi_root_node(), DDI_CTLOPS_POWER, &power_req, &result);
9359 PMD(PMD_SX, ("pm_ppm_searchlist returns %d, result %d\n",
9360 ret, result))
9361 return (result);
9362 }
9363