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