Lines Matching refs:genpd

29 #define GENPD_DEV_CALLBACK(genpd, type, callback, dev)		\  argument
34 __routine = genpd->dev_ops.callback; \
45 void (*lock)(struct generic_pm_domain *genpd);
46 void (*lock_nested)(struct generic_pm_domain *genpd, int depth);
47 int (*lock_interruptible)(struct generic_pm_domain *genpd);
48 void (*unlock)(struct generic_pm_domain *genpd);
51 static void genpd_lock_mtx(struct generic_pm_domain *genpd) in genpd_lock_mtx() argument
53 mutex_lock(&genpd->mlock); in genpd_lock_mtx()
56 static void genpd_lock_nested_mtx(struct generic_pm_domain *genpd, in genpd_lock_nested_mtx() argument
59 mutex_lock_nested(&genpd->mlock, depth); in genpd_lock_nested_mtx()
62 static int genpd_lock_interruptible_mtx(struct generic_pm_domain *genpd) in genpd_lock_interruptible_mtx() argument
64 return mutex_lock_interruptible(&genpd->mlock); in genpd_lock_interruptible_mtx()
67 static void genpd_unlock_mtx(struct generic_pm_domain *genpd) in genpd_unlock_mtx() argument
69 return mutex_unlock(&genpd->mlock); in genpd_unlock_mtx()
79 static void genpd_lock_spin(struct generic_pm_domain *genpd) in genpd_lock_spin() argument
80 __acquires(&genpd->slock) in genpd_lock_spin()
84 spin_lock_irqsave(&genpd->slock, flags); in genpd_lock_spin()
85 genpd->lock_flags = flags; in genpd_lock_spin()
88 static void genpd_lock_nested_spin(struct generic_pm_domain *genpd, in genpd_lock_nested_spin() argument
90 __acquires(&genpd->slock) in genpd_lock_nested_spin()
94 spin_lock_irqsave_nested(&genpd->slock, flags, depth); in genpd_lock_nested_spin()
95 genpd->lock_flags = flags; in genpd_lock_nested_spin()
98 static int genpd_lock_interruptible_spin(struct generic_pm_domain *genpd) in genpd_lock_interruptible_spin() argument
99 __acquires(&genpd->slock) in genpd_lock_interruptible_spin()
103 spin_lock_irqsave(&genpd->slock, flags); in genpd_lock_interruptible_spin()
104 genpd->lock_flags = flags; in genpd_lock_interruptible_spin()
108 static void genpd_unlock_spin(struct generic_pm_domain *genpd) in genpd_unlock_spin() argument
109 __releases(&genpd->slock) in genpd_unlock_spin()
111 spin_unlock_irqrestore(&genpd->slock, genpd->lock_flags); in genpd_unlock_spin()
126 #define genpd_status_on(genpd) (genpd->status == GENPD_STATE_ON) argument
127 #define genpd_is_irq_safe(genpd) (genpd->flags & GENPD_FLAG_IRQ_SAFE) argument
128 #define genpd_is_always_on(genpd) (genpd->flags & GENPD_FLAG_ALWAYS_ON) argument
129 #define genpd_is_active_wakeup(genpd) (genpd->flags & GENPD_FLAG_ACTIVE_WAKEUP) argument
130 #define genpd_is_cpu_domain(genpd) (genpd->flags & GENPD_FLAG_CPU_DOMAIN) argument
131 #define genpd_is_rpm_always_on(genpd) (genpd->flags & GENPD_FLAG_RPM_ALWAYS_ON) argument
134 const struct generic_pm_domain *genpd) in irq_safe_dev_in_no_sleep_domain() argument
138 ret = pm_runtime_is_irq_safe(dev) && !genpd_is_irq_safe(genpd); in irq_safe_dev_in_no_sleep_domain()
145 if (ret && !genpd_is_always_on(genpd)) in irq_safe_dev_in_no_sleep_domain()
147 genpd->name); in irq_safe_dev_in_no_sleep_domain()
184 static int genpd_stop_dev(const struct generic_pm_domain *genpd, in genpd_stop_dev() argument
187 return GENPD_DEV_CALLBACK(genpd, int, stop, dev); in genpd_stop_dev()
190 static int genpd_start_dev(const struct generic_pm_domain *genpd, in genpd_start_dev() argument
193 return GENPD_DEV_CALLBACK(genpd, int, start, dev); in genpd_start_dev()
196 static bool genpd_sd_counter_dec(struct generic_pm_domain *genpd) in genpd_sd_counter_dec() argument
200 if (!WARN_ON(atomic_read(&genpd->sd_count) == 0)) in genpd_sd_counter_dec()
201 ret = !!atomic_dec_and_test(&genpd->sd_count); in genpd_sd_counter_dec()
206 static void genpd_sd_counter_inc(struct generic_pm_domain *genpd) in genpd_sd_counter_inc() argument
208 atomic_inc(&genpd->sd_count); in genpd_sd_counter_inc()
213 static void genpd_update_accounting(struct generic_pm_domain *genpd) in genpd_update_accounting() argument
218 delta = ktime_sub(now, genpd->accounting_time); in genpd_update_accounting()
225 if (genpd->status == GENPD_STATE_ON) { in genpd_update_accounting()
226 int state_idx = genpd->state_idx; in genpd_update_accounting()
228 genpd->states[state_idx].idle_time = in genpd_update_accounting()
229 ktime_add(genpd->states[state_idx].idle_time, delta); in genpd_update_accounting()
231 genpd->on_time = ktime_add(genpd->on_time, delta); in genpd_update_accounting()
234 genpd->accounting_time = now; in genpd_update_accounting()
237 static inline void genpd_update_accounting(struct generic_pm_domain *genpd) {} in genpd_update_accounting() argument
240 static int _genpd_reeval_performance_state(struct generic_pm_domain *genpd, in _genpd_reeval_performance_state() argument
248 if (state == genpd->performance_state) in _genpd_reeval_performance_state()
252 if (state > genpd->performance_state) in _genpd_reeval_performance_state()
256 list_for_each_entry(pdd, &genpd->dev_list, list_node) { in _genpd_reeval_performance_state()
277 list_for_each_entry(link, &genpd->parent_links, parent_node) { in _genpd_reeval_performance_state()
285 static int _genpd_set_performance_state(struct generic_pm_domain *genpd, in _genpd_set_performance_state() argument
292 if (state == genpd->performance_state) in _genpd_set_performance_state()
296 list_for_each_entry(link, &genpd->child_links, child_node) { in _genpd_set_performance_state()
303 ret = dev_pm_opp_xlate_performance_state(genpd->opp_table, in _genpd_set_performance_state()
327 ret = genpd->set_performance_state(genpd, state); in _genpd_set_performance_state()
331 genpd->performance_state = state; in _genpd_set_performance_state()
336 list_for_each_entry_continue_reverse(link, &genpd->child_links, in _genpd_set_performance_state()
378 struct generic_pm_domain *genpd; in dev_pm_genpd_set_performance_state() local
383 genpd = dev_to_genpd_safe(dev); in dev_pm_genpd_set_performance_state()
384 if (!genpd) in dev_pm_genpd_set_performance_state()
387 if (unlikely(!genpd->set_performance_state)) in dev_pm_genpd_set_performance_state()
394 genpd_lock(genpd); in dev_pm_genpd_set_performance_state()
400 state = _genpd_reeval_performance_state(genpd, state); in dev_pm_genpd_set_performance_state()
401 ret = _genpd_set_performance_state(genpd, state, 0); in dev_pm_genpd_set_performance_state()
405 genpd_unlock(genpd); in dev_pm_genpd_set_performance_state()
411 static int _genpd_power_on(struct generic_pm_domain *genpd, bool timed) in _genpd_power_on() argument
413 unsigned int state_idx = genpd->state_idx; in _genpd_power_on()
419 ret = raw_notifier_call_chain_robust(&genpd->power_notifiers, in _genpd_power_on()
426 if (!genpd->power_on) in _genpd_power_on()
430 ret = genpd->power_on(genpd); in _genpd_power_on()
438 ret = genpd->power_on(genpd); in _genpd_power_on()
443 if (elapsed_ns <= genpd->states[state_idx].power_on_latency_ns) in _genpd_power_on()
446 genpd->states[state_idx].power_on_latency_ns = elapsed_ns; in _genpd_power_on()
447 genpd->max_off_time_changed = true; in _genpd_power_on()
449 genpd->name, "on", elapsed_ns); in _genpd_power_on()
452 raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL); in _genpd_power_on()
455 raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF, in _genpd_power_on()
460 static int _genpd_power_off(struct generic_pm_domain *genpd, bool timed) in _genpd_power_off() argument
462 unsigned int state_idx = genpd->state_idx; in _genpd_power_off()
468 ret = raw_notifier_call_chain_robust(&genpd->power_notifiers, in _genpd_power_off()
475 if (!genpd->power_off) in _genpd_power_off()
479 ret = genpd->power_off(genpd); in _genpd_power_off()
487 ret = genpd->power_off(genpd); in _genpd_power_off()
492 if (elapsed_ns <= genpd->states[state_idx].power_off_latency_ns) in _genpd_power_off()
495 genpd->states[state_idx].power_off_latency_ns = elapsed_ns; in _genpd_power_off()
496 genpd->max_off_time_changed = true; in _genpd_power_off()
498 genpd->name, "off", elapsed_ns); in _genpd_power_off()
501 raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_OFF, in _genpd_power_off()
505 raw_notifier_call_chain(&genpd->power_notifiers, GENPD_NOTIFY_ON, NULL); in _genpd_power_off()
516 static void genpd_queue_power_off_work(struct generic_pm_domain *genpd) in genpd_queue_power_off_work() argument
518 queue_work(pm_wq, &genpd->power_off_work); in genpd_queue_power_off_work()
532 static int genpd_power_off(struct generic_pm_domain *genpd, bool one_dev_on, in genpd_power_off() argument
545 if (!genpd_status_on(genpd) || genpd->prepared_count > 0) in genpd_power_off()
553 if (genpd_is_always_on(genpd) || in genpd_power_off()
554 genpd_is_rpm_always_on(genpd) || in genpd_power_off()
555 atomic_read(&genpd->sd_count) > 0) in genpd_power_off()
558 list_for_each_entry(pdd, &genpd->dev_list, list_node) { in genpd_power_off()
570 irq_safe_dev_in_no_sleep_domain(pdd->dev, genpd)) in genpd_power_off()
577 if (genpd->gov && genpd->gov->power_down_ok) { in genpd_power_off()
578 if (!genpd->gov->power_down_ok(&genpd->domain)) in genpd_power_off()
583 if (!genpd->gov) in genpd_power_off()
584 genpd->state_idx = 0; in genpd_power_off()
587 if (atomic_read(&genpd->sd_count) > 0) in genpd_power_off()
590 ret = _genpd_power_off(genpd, true); in genpd_power_off()
592 genpd->states[genpd->state_idx].rejected++; in genpd_power_off()
596 genpd->status = GENPD_STATE_OFF; in genpd_power_off()
597 genpd_update_accounting(genpd); in genpd_power_off()
598 genpd->states[genpd->state_idx].usage++; in genpd_power_off()
600 list_for_each_entry(link, &genpd->child_links, child_node) { in genpd_power_off()
618 static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth) in genpd_power_on() argument
623 if (genpd_status_on(genpd)) in genpd_power_on()
631 list_for_each_entry(link, &genpd->child_links, child_node) { in genpd_power_on()
646 ret = _genpd_power_on(genpd, true); in genpd_power_on()
650 genpd->status = GENPD_STATE_ON; in genpd_power_on()
651 genpd_update_accounting(genpd); in genpd_power_on()
657 &genpd->child_links, in genpd_power_on()
670 struct generic_pm_domain *genpd = dev_to_genpd(dev); in genpd_dev_pm_start() local
672 return genpd_start_dev(genpd, dev); in genpd_dev_pm_start()
685 struct generic_pm_domain *genpd; in genpd_dev_pm_qos_notifier() local
694 genpd = dev_to_genpd(dev); in genpd_dev_pm_qos_notifier()
696 genpd = ERR_PTR(-ENODATA); in genpd_dev_pm_qos_notifier()
701 if (!IS_ERR(genpd)) { in genpd_dev_pm_qos_notifier()
702 genpd_lock(genpd); in genpd_dev_pm_qos_notifier()
703 genpd->max_off_time_changed = true; in genpd_dev_pm_qos_notifier()
704 genpd_unlock(genpd); in genpd_dev_pm_qos_notifier()
721 struct generic_pm_domain *genpd; in genpd_power_off_work_fn() local
723 genpd = container_of(work, struct generic_pm_domain, power_off_work); in genpd_power_off_work_fn()
725 genpd_lock(genpd); in genpd_power_off_work_fn()
726 genpd_power_off(genpd, false, 0); in genpd_power_off_work_fn()
727 genpd_unlock(genpd); in genpd_power_off_work_fn()
786 struct generic_pm_domain *genpd; in genpd_runtime_suspend() local
796 genpd = dev_to_genpd(dev); in genpd_runtime_suspend()
797 if (IS_ERR(genpd)) in genpd_runtime_suspend()
806 suspend_ok = genpd->gov ? genpd->gov->suspend_ok : NULL; in genpd_runtime_suspend()
819 ret = genpd_stop_dev(genpd, dev); in genpd_runtime_suspend()
832 genpd->max_off_time_changed = true; in genpd_runtime_suspend()
841 if (irq_safe_dev_in_no_sleep_domain(dev, genpd)) in genpd_runtime_suspend()
844 genpd_lock(genpd); in genpd_runtime_suspend()
845 genpd_power_off(genpd, true, 0); in genpd_runtime_suspend()
846 genpd_unlock(genpd); in genpd_runtime_suspend()
861 struct generic_pm_domain *genpd; in genpd_runtime_resume() local
871 genpd = dev_to_genpd(dev); in genpd_runtime_resume()
872 if (IS_ERR(genpd)) in genpd_runtime_resume()
879 if (irq_safe_dev_in_no_sleep_domain(dev, genpd)) { in genpd_runtime_resume()
884 genpd_lock(genpd); in genpd_runtime_resume()
885 ret = genpd_power_on(genpd, 0); in genpd_runtime_resume()
886 genpd_unlock(genpd); in genpd_runtime_resume()
897 ret = genpd_start_dev(genpd, dev); in genpd_runtime_resume()
912 genpd->max_off_time_changed = true; in genpd_runtime_resume()
920 genpd_stop_dev(genpd, dev); in genpd_runtime_resume()
923 (pm_runtime_is_irq_safe(dev) && genpd_is_irq_safe(genpd))) { in genpd_runtime_resume()
924 genpd_lock(genpd); in genpd_runtime_resume()
925 genpd_power_off(genpd, true, 0); in genpd_runtime_resume()
926 genpd_unlock(genpd); in genpd_runtime_resume()
945 struct generic_pm_domain *genpd; in genpd_power_off_unused() local
954 list_for_each_entry(genpd, &gpd_list, gpd_list_node) in genpd_power_off_unused()
955 genpd_queue_power_off_work(genpd); in genpd_power_off_unused()
978 static void genpd_sync_power_off(struct generic_pm_domain *genpd, bool use_lock, in genpd_sync_power_off() argument
983 if (!genpd_status_on(genpd) || genpd_is_always_on(genpd)) in genpd_sync_power_off()
986 if (genpd->suspended_count != genpd->device_count in genpd_sync_power_off()
987 || atomic_read(&genpd->sd_count) > 0) in genpd_sync_power_off()
991 genpd->state_idx = genpd->state_count - 1; in genpd_sync_power_off()
992 if (_genpd_power_off(genpd, false)) in genpd_sync_power_off()
995 genpd->status = GENPD_STATE_OFF; in genpd_sync_power_off()
997 list_for_each_entry(link, &genpd->child_links, child_node) { in genpd_sync_power_off()
1020 static void genpd_sync_power_on(struct generic_pm_domain *genpd, bool use_lock, in genpd_sync_power_on() argument
1025 if (genpd_status_on(genpd)) in genpd_sync_power_on()
1028 list_for_each_entry(link, &genpd->child_links, child_node) { in genpd_sync_power_on()
1040 _genpd_power_on(genpd, false); in genpd_sync_power_on()
1041 genpd->status = GENPD_STATE_ON; in genpd_sync_power_on()
1061 const struct generic_pm_domain *genpd) in resume_needed() argument
1068 active_wakeup = genpd_is_active_wakeup(genpd); in resume_needed()
1083 struct generic_pm_domain *genpd; in genpd_prepare() local
1088 genpd = dev_to_genpd(dev); in genpd_prepare()
1089 if (IS_ERR(genpd)) in genpd_prepare()
1097 if (resume_needed(dev, genpd)) in genpd_prepare()
1100 genpd_lock(genpd); in genpd_prepare()
1102 if (genpd->prepared_count++ == 0) in genpd_prepare()
1103 genpd->suspended_count = 0; in genpd_prepare()
1105 genpd_unlock(genpd); in genpd_prepare()
1109 genpd_lock(genpd); in genpd_prepare()
1111 genpd->prepared_count--; in genpd_prepare()
1113 genpd_unlock(genpd); in genpd_prepare()
1131 struct generic_pm_domain *genpd; in genpd_finish_suspend() local
1134 genpd = dev_to_genpd(dev); in genpd_finish_suspend()
1135 if (IS_ERR(genpd)) in genpd_finish_suspend()
1145 if (dev->power.wakeup_path && genpd_is_active_wakeup(genpd)) in genpd_finish_suspend()
1148 if (genpd->dev_ops.stop && genpd->dev_ops.start && in genpd_finish_suspend()
1150 ret = genpd_stop_dev(genpd, dev); in genpd_finish_suspend()
1160 genpd_lock(genpd); in genpd_finish_suspend()
1161 genpd->suspended_count++; in genpd_finish_suspend()
1162 genpd_sync_power_off(genpd, true, 0); in genpd_finish_suspend()
1163 genpd_unlock(genpd); in genpd_finish_suspend()
1190 struct generic_pm_domain *genpd; in genpd_resume_noirq() local
1195 genpd = dev_to_genpd(dev); in genpd_resume_noirq()
1196 if (IS_ERR(genpd)) in genpd_resume_noirq()
1199 if (dev->power.wakeup_path && genpd_is_active_wakeup(genpd)) in genpd_resume_noirq()
1202 genpd_lock(genpd); in genpd_resume_noirq()
1203 genpd_sync_power_on(genpd, true, 0); in genpd_resume_noirq()
1204 genpd->suspended_count--; in genpd_resume_noirq()
1205 genpd_unlock(genpd); in genpd_resume_noirq()
1207 if (genpd->dev_ops.stop && genpd->dev_ops.start && in genpd_resume_noirq()
1209 ret = genpd_start_dev(genpd, dev); in genpd_resume_noirq()
1228 const struct generic_pm_domain *genpd; in genpd_freeze_noirq() local
1233 genpd = dev_to_genpd(dev); in genpd_freeze_noirq()
1234 if (IS_ERR(genpd)) in genpd_freeze_noirq()
1241 if (genpd->dev_ops.stop && genpd->dev_ops.start && in genpd_freeze_noirq()
1243 ret = genpd_stop_dev(genpd, dev); in genpd_freeze_noirq()
1257 const struct generic_pm_domain *genpd; in genpd_thaw_noirq() local
1262 genpd = dev_to_genpd(dev); in genpd_thaw_noirq()
1263 if (IS_ERR(genpd)) in genpd_thaw_noirq()
1266 if (genpd->dev_ops.stop && genpd->dev_ops.start && in genpd_thaw_noirq()
1268 ret = genpd_start_dev(genpd, dev); in genpd_thaw_noirq()
1300 struct generic_pm_domain *genpd; in genpd_restore_noirq() local
1305 genpd = dev_to_genpd(dev); in genpd_restore_noirq()
1306 if (IS_ERR(genpd)) in genpd_restore_noirq()
1313 genpd_lock(genpd); in genpd_restore_noirq()
1314 if (genpd->suspended_count++ == 0) { in genpd_restore_noirq()
1320 genpd->status = GENPD_STATE_OFF; in genpd_restore_noirq()
1323 genpd_sync_power_on(genpd, true, 0); in genpd_restore_noirq()
1324 genpd_unlock(genpd); in genpd_restore_noirq()
1326 if (genpd->dev_ops.stop && genpd->dev_ops.start && in genpd_restore_noirq()
1328 ret = genpd_start_dev(genpd, dev); in genpd_restore_noirq()
1347 struct generic_pm_domain *genpd; in genpd_complete() local
1351 genpd = dev_to_genpd(dev); in genpd_complete()
1352 if (IS_ERR(genpd)) in genpd_complete()
1357 genpd_lock(genpd); in genpd_complete()
1359 genpd->prepared_count--; in genpd_complete()
1360 if (!genpd->prepared_count) in genpd_complete()
1361 genpd_queue_power_off_work(genpd); in genpd_complete()
1363 genpd_unlock(genpd); in genpd_complete()
1375 struct generic_pm_domain *genpd; in genpd_syscore_switch() local
1377 genpd = dev_to_genpd_safe(dev); in genpd_syscore_switch()
1378 if (!genpd) in genpd_syscore_switch()
1382 genpd->suspended_count++; in genpd_syscore_switch()
1383 genpd_sync_power_off(genpd, false, 0); in genpd_syscore_switch()
1385 genpd_sync_power_on(genpd, false, 0); in genpd_syscore_switch()
1386 genpd->suspended_count--; in genpd_syscore_switch()
1469 static void genpd_update_cpumask(struct generic_pm_domain *genpd, in genpd_update_cpumask() argument
1474 if (!genpd_is_cpu_domain(genpd)) in genpd_update_cpumask()
1477 list_for_each_entry(link, &genpd->child_links, child_node) { in genpd_update_cpumask()
1486 cpumask_set_cpu(cpu, genpd->cpus); in genpd_update_cpumask()
1488 cpumask_clear_cpu(cpu, genpd->cpus); in genpd_update_cpumask()
1491 static void genpd_set_cpumask(struct generic_pm_domain *genpd, int cpu) in genpd_set_cpumask() argument
1494 genpd_update_cpumask(genpd, cpu, true, 0); in genpd_set_cpumask()
1497 static void genpd_clear_cpumask(struct generic_pm_domain *genpd, int cpu) in genpd_clear_cpumask() argument
1500 genpd_update_cpumask(genpd, cpu, false, 0); in genpd_clear_cpumask()
1503 static int genpd_get_cpu(struct generic_pm_domain *genpd, struct device *dev) in genpd_get_cpu() argument
1507 if (!genpd_is_cpu_domain(genpd)) in genpd_get_cpu()
1518 static int genpd_add_device(struct generic_pm_domain *genpd, struct device *dev, in genpd_add_device() argument
1526 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(dev)) in genpd_add_device()
1533 gpd_data->cpu = genpd_get_cpu(genpd, base_dev); in genpd_add_device()
1535 ret = genpd->attach_dev ? genpd->attach_dev(genpd, dev) : 0; in genpd_add_device()
1539 genpd_lock(genpd); in genpd_add_device()
1541 genpd_set_cpumask(genpd, gpd_data->cpu); in genpd_add_device()
1542 dev_pm_domain_set(dev, &genpd->domain); in genpd_add_device()
1544 genpd->device_count++; in genpd_add_device()
1545 genpd->max_off_time_changed = true; in genpd_add_device()
1547 list_add_tail(&gpd_data->base.list_node, &genpd->dev_list); in genpd_add_device()
1549 genpd_unlock(genpd); in genpd_add_device()
1565 int pm_genpd_add_device(struct generic_pm_domain *genpd, struct device *dev) in pm_genpd_add_device() argument
1570 ret = genpd_add_device(genpd, dev, dev); in pm_genpd_add_device()
1577 static int genpd_remove_device(struct generic_pm_domain *genpd, in genpd_remove_device() argument
1591 genpd_lock(genpd); in genpd_remove_device()
1593 if (genpd->prepared_count > 0) { in genpd_remove_device()
1598 genpd->device_count--; in genpd_remove_device()
1599 genpd->max_off_time_changed = true; in genpd_remove_device()
1601 genpd_clear_cpumask(genpd, gpd_data->cpu); in genpd_remove_device()
1606 genpd_unlock(genpd); in genpd_remove_device()
1608 if (genpd->detach_dev) in genpd_remove_device()
1609 genpd->detach_dev(genpd, dev); in genpd_remove_device()
1616 genpd_unlock(genpd); in genpd_remove_device()
1628 struct generic_pm_domain *genpd = dev_to_genpd_safe(dev); in pm_genpd_remove_device() local
1630 if (!genpd) in pm_genpd_remove_device()
1633 return genpd_remove_device(genpd, dev); in pm_genpd_remove_device()
1654 struct generic_pm_domain *genpd; in dev_pm_genpd_add_notifier() local
1658 genpd = dev_to_genpd_safe(dev); in dev_pm_genpd_add_notifier()
1659 if (!genpd) in dev_pm_genpd_add_notifier()
1670 genpd_lock(genpd); in dev_pm_genpd_add_notifier()
1671 ret = raw_notifier_chain_register(&genpd->power_notifiers, nb); in dev_pm_genpd_add_notifier()
1672 genpd_unlock(genpd); in dev_pm_genpd_add_notifier()
1676 genpd->name); in dev_pm_genpd_add_notifier()
1700 struct generic_pm_domain *genpd; in dev_pm_genpd_remove_notifier() local
1704 genpd = dev_to_genpd_safe(dev); in dev_pm_genpd_remove_notifier()
1705 if (!genpd) in dev_pm_genpd_remove_notifier()
1716 genpd_lock(genpd); in dev_pm_genpd_remove_notifier()
1717 ret = raw_notifier_chain_unregister(&genpd->power_notifiers, in dev_pm_genpd_remove_notifier()
1719 genpd_unlock(genpd); in dev_pm_genpd_remove_notifier()
1723 genpd->name); in dev_pm_genpd_remove_notifier()
1732 static int genpd_add_subdomain(struct generic_pm_domain *genpd, in genpd_add_subdomain() argument
1738 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain) in genpd_add_subdomain()
1739 || genpd == subdomain) in genpd_add_subdomain()
1747 if (!genpd_is_irq_safe(genpd) && genpd_is_irq_safe(subdomain)) { in genpd_add_subdomain()
1749 genpd->name, subdomain->name); in genpd_add_subdomain()
1758 genpd_lock_nested(genpd, SINGLE_DEPTH_NESTING); in genpd_add_subdomain()
1760 if (!genpd_status_on(genpd) && genpd_status_on(subdomain)) { in genpd_add_subdomain()
1765 list_for_each_entry(itr, &genpd->parent_links, parent_node) { in genpd_add_subdomain()
1766 if (itr->child == subdomain && itr->parent == genpd) { in genpd_add_subdomain()
1772 link->parent = genpd; in genpd_add_subdomain()
1773 list_add_tail(&link->parent_node, &genpd->parent_links); in genpd_add_subdomain()
1777 genpd_sd_counter_inc(genpd); in genpd_add_subdomain()
1780 genpd_unlock(genpd); in genpd_add_subdomain()
1792 int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, in pm_genpd_add_subdomain() argument
1798 ret = genpd_add_subdomain(genpd, subdomain); in pm_genpd_add_subdomain()
1810 int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, in pm_genpd_remove_subdomain() argument
1816 if (IS_ERR_OR_NULL(genpd) || IS_ERR_OR_NULL(subdomain)) in pm_genpd_remove_subdomain()
1820 genpd_lock_nested(genpd, SINGLE_DEPTH_NESTING); in pm_genpd_remove_subdomain()
1824 genpd->name, subdomain->name); in pm_genpd_remove_subdomain()
1829 list_for_each_entry_safe(link, l, &genpd->parent_links, parent_node) { in pm_genpd_remove_subdomain()
1837 genpd_sd_counter_dec(genpd); in pm_genpd_remove_subdomain()
1844 genpd_unlock(genpd); in pm_genpd_remove_subdomain()
1857 static int genpd_set_default_power_state(struct generic_pm_domain *genpd) in genpd_set_default_power_state() argument
1865 genpd->states = state; in genpd_set_default_power_state()
1866 genpd->state_count = 1; in genpd_set_default_power_state()
1867 genpd->free_states = genpd_free_default_power_state; in genpd_set_default_power_state()
1872 static void genpd_lock_init(struct generic_pm_domain *genpd) in genpd_lock_init() argument
1874 if (genpd->flags & GENPD_FLAG_IRQ_SAFE) { in genpd_lock_init()
1875 spin_lock_init(&genpd->slock); in genpd_lock_init()
1876 genpd->lock_ops = &genpd_spin_ops; in genpd_lock_init()
1878 mutex_init(&genpd->mlock); in genpd_lock_init()
1879 genpd->lock_ops = &genpd_mtx_ops; in genpd_lock_init()
1891 int pm_genpd_init(struct generic_pm_domain *genpd, in pm_genpd_init() argument
1896 if (IS_ERR_OR_NULL(genpd)) in pm_genpd_init()
1899 INIT_LIST_HEAD(&genpd->parent_links); in pm_genpd_init()
1900 INIT_LIST_HEAD(&genpd->child_links); in pm_genpd_init()
1901 INIT_LIST_HEAD(&genpd->dev_list); in pm_genpd_init()
1902 RAW_INIT_NOTIFIER_HEAD(&genpd->power_notifiers); in pm_genpd_init()
1903 genpd_lock_init(genpd); in pm_genpd_init()
1904 genpd->gov = gov; in pm_genpd_init()
1905 INIT_WORK(&genpd->power_off_work, genpd_power_off_work_fn); in pm_genpd_init()
1906 atomic_set(&genpd->sd_count, 0); in pm_genpd_init()
1907 genpd->status = is_off ? GENPD_STATE_OFF : GENPD_STATE_ON; in pm_genpd_init()
1908 genpd->device_count = 0; in pm_genpd_init()
1909 genpd->max_off_time_ns = -1; in pm_genpd_init()
1910 genpd->max_off_time_changed = true; in pm_genpd_init()
1911 genpd->provider = NULL; in pm_genpd_init()
1912 genpd->has_provider = false; in pm_genpd_init()
1913 genpd->accounting_time = ktime_get(); in pm_genpd_init()
1914 genpd->domain.ops.runtime_suspend = genpd_runtime_suspend; in pm_genpd_init()
1915 genpd->domain.ops.runtime_resume = genpd_runtime_resume; in pm_genpd_init()
1916 genpd->domain.ops.prepare = genpd_prepare; in pm_genpd_init()
1917 genpd->domain.ops.suspend_noirq = genpd_suspend_noirq; in pm_genpd_init()
1918 genpd->domain.ops.resume_noirq = genpd_resume_noirq; in pm_genpd_init()
1919 genpd->domain.ops.freeze_noirq = genpd_freeze_noirq; in pm_genpd_init()
1920 genpd->domain.ops.thaw_noirq = genpd_thaw_noirq; in pm_genpd_init()
1921 genpd->domain.ops.poweroff_noirq = genpd_poweroff_noirq; in pm_genpd_init()
1922 genpd->domain.ops.restore_noirq = genpd_restore_noirq; in pm_genpd_init()
1923 genpd->domain.ops.complete = genpd_complete; in pm_genpd_init()
1924 genpd->domain.start = genpd_dev_pm_start; in pm_genpd_init()
1926 if (genpd->flags & GENPD_FLAG_PM_CLK) { in pm_genpd_init()
1927 genpd->dev_ops.stop = pm_clk_suspend; in pm_genpd_init()
1928 genpd->dev_ops.start = pm_clk_resume; in pm_genpd_init()
1932 if ((genpd_is_always_on(genpd) || genpd_is_rpm_always_on(genpd)) && in pm_genpd_init()
1933 !genpd_status_on(genpd)) in pm_genpd_init()
1936 if (genpd_is_cpu_domain(genpd) && in pm_genpd_init()
1937 !zalloc_cpumask_var(&genpd->cpus, GFP_KERNEL)) in pm_genpd_init()
1941 if (genpd->state_count == 0) { in pm_genpd_init()
1942 ret = genpd_set_default_power_state(genpd); in pm_genpd_init()
1944 if (genpd_is_cpu_domain(genpd)) in pm_genpd_init()
1945 free_cpumask_var(genpd->cpus); in pm_genpd_init()
1948 } else if (!gov && genpd->state_count > 1) { in pm_genpd_init()
1949 pr_warn("%s: no governor for states\n", genpd->name); in pm_genpd_init()
1952 device_initialize(&genpd->dev); in pm_genpd_init()
1953 dev_set_name(&genpd->dev, "%s", genpd->name); in pm_genpd_init()
1956 list_add(&genpd->gpd_list_node, &gpd_list); in pm_genpd_init()
1963 static int genpd_remove(struct generic_pm_domain *genpd) in genpd_remove() argument
1967 if (IS_ERR_OR_NULL(genpd)) in genpd_remove()
1970 genpd_lock(genpd); in genpd_remove()
1972 if (genpd->has_provider) { in genpd_remove()
1973 genpd_unlock(genpd); in genpd_remove()
1974 pr_err("Provider present, unable to remove %s\n", genpd->name); in genpd_remove()
1978 if (!list_empty(&genpd->parent_links) || genpd->device_count) { in genpd_remove()
1979 genpd_unlock(genpd); in genpd_remove()
1980 pr_err("%s: unable to remove %s\n", __func__, genpd->name); in genpd_remove()
1984 list_for_each_entry_safe(link, l, &genpd->child_links, child_node) { in genpd_remove()
1990 list_del(&genpd->gpd_list_node); in genpd_remove()
1991 genpd_unlock(genpd); in genpd_remove()
1992 cancel_work_sync(&genpd->power_off_work); in genpd_remove()
1993 if (genpd_is_cpu_domain(genpd)) in genpd_remove()
1994 free_cpumask_var(genpd->cpus); in genpd_remove()
1995 if (genpd->free_states) in genpd_remove()
1996 genpd->free_states(genpd->states, genpd->state_count); in genpd_remove()
1998 pr_debug("%s: removed %s\n", __func__, genpd->name); in genpd_remove()
2016 int pm_genpd_remove(struct generic_pm_domain *genpd) in pm_genpd_remove() argument
2021 ret = genpd_remove(genpd); in pm_genpd_remove()
2140 static bool genpd_present(const struct generic_pm_domain *genpd) in genpd_present() argument
2145 if (gpd == genpd) in genpd_present()
2156 struct generic_pm_domain *genpd) in of_genpd_add_provider_simple() argument
2160 if (!np || !genpd) in of_genpd_add_provider_simple()
2165 if (!genpd_present(genpd)) in of_genpd_add_provider_simple()
2168 genpd->dev.of_node = np; in of_genpd_add_provider_simple()
2171 if (genpd->set_performance_state) { in of_genpd_add_provider_simple()
2172 ret = dev_pm_opp_of_add_table(&genpd->dev); in of_genpd_add_provider_simple()
2175 dev_err(&genpd->dev, "Failed to add OPP table: %d\n", in of_genpd_add_provider_simple()
2184 genpd->opp_table = dev_pm_opp_get_opp_table(&genpd->dev); in of_genpd_add_provider_simple()
2185 WARN_ON(IS_ERR(genpd->opp_table)); in of_genpd_add_provider_simple()
2188 ret = genpd_add_provider(np, genpd_xlate_simple, genpd); in of_genpd_add_provider_simple()
2190 if (genpd->set_performance_state) { in of_genpd_add_provider_simple()
2191 dev_pm_opp_put_opp_table(genpd->opp_table); in of_genpd_add_provider_simple()
2192 dev_pm_opp_of_remove_table(&genpd->dev); in of_genpd_add_provider_simple()
2198 genpd->provider = &np->fwnode; in of_genpd_add_provider_simple()
2199 genpd->has_provider = true; in of_genpd_add_provider_simple()
2216 struct generic_pm_domain *genpd; in of_genpd_add_provider_onecell() local
2229 genpd = data->domains[i]; in of_genpd_add_provider_onecell()
2231 if (!genpd) in of_genpd_add_provider_onecell()
2233 if (!genpd_present(genpd)) in of_genpd_add_provider_onecell()
2236 genpd->dev.of_node = np; in of_genpd_add_provider_onecell()
2239 if (genpd->set_performance_state) { in of_genpd_add_provider_onecell()
2240 ret = dev_pm_opp_of_add_table_indexed(&genpd->dev, i); in of_genpd_add_provider_onecell()
2243 dev_err(&genpd->dev, "Failed to add OPP table for index %d: %d\n", in of_genpd_add_provider_onecell()
2252 genpd->opp_table = dev_pm_opp_get_opp_table_indexed(&genpd->dev, i); in of_genpd_add_provider_onecell()
2253 WARN_ON(IS_ERR(genpd->opp_table)); in of_genpd_add_provider_onecell()
2256 genpd->provider = &np->fwnode; in of_genpd_add_provider_onecell()
2257 genpd->has_provider = true; in of_genpd_add_provider_onecell()
2270 genpd = data->domains[i]; in of_genpd_add_provider_onecell()
2272 if (!genpd) in of_genpd_add_provider_onecell()
2275 genpd->provider = NULL; in of_genpd_add_provider_onecell()
2276 genpd->has_provider = false; in of_genpd_add_provider_onecell()
2278 if (genpd->set_performance_state) { in of_genpd_add_provider_onecell()
2279 dev_pm_opp_put_opp_table(genpd->opp_table); in of_genpd_add_provider_onecell()
2280 dev_pm_opp_of_remove_table(&genpd->dev); in of_genpd_add_provider_onecell()
2345 struct generic_pm_domain *genpd = ERR_PTR(-ENOENT); in genpd_get_from_provider() local
2356 genpd = provider->xlate(genpdspec, provider->data); in genpd_get_from_provider()
2357 if (!IS_ERR(genpd)) in genpd_get_from_provider()
2363 return genpd; in genpd_get_from_provider()
2376 struct generic_pm_domain *genpd; in of_genpd_add_device() local
2381 genpd = genpd_get_from_provider(genpdspec); in of_genpd_add_device()
2382 if (IS_ERR(genpd)) { in of_genpd_add_device()
2383 ret = PTR_ERR(genpd); in of_genpd_add_device()
2387 ret = genpd_add_device(genpd, dev, dev); in of_genpd_add_device()
2487 struct generic_pm_domain *gpd, *tmp, *genpd = ERR_PTR(-ENOENT); in of_genpd_remove_last() local
2497 genpd = ret ? ERR_PTR(ret) : gpd; in of_genpd_remove_last()
2503 return genpd; in of_genpd_remove_last()
2868 struct generic_pm_domain *genpd = NULL; in pm_genpd_opp_to_performance_state() local
2871 genpd = container_of(genpd_dev, struct generic_pm_domain, dev); in pm_genpd_opp_to_performance_state()
2873 if (unlikely(!genpd->opp_to_performance_state)) in pm_genpd_opp_to_performance_state()
2876 genpd_lock(genpd); in pm_genpd_opp_to_performance_state()
2877 state = genpd->opp_to_performance_state(genpd, opp); in pm_genpd_opp_to_performance_state()
2878 genpd_unlock(genpd); in pm_genpd_opp_to_performance_state()
2931 struct generic_pm_domain *genpd) in genpd_summary_one() argument
2943 ret = genpd_lock_interruptible(genpd); in genpd_summary_one()
2947 if (WARN_ON(genpd->status >= ARRAY_SIZE(status_lookup))) in genpd_summary_one()
2949 if (!genpd_status_on(genpd)) in genpd_summary_one()
2951 status_lookup[genpd->status], genpd->state_idx); in genpd_summary_one()
2954 status_lookup[genpd->status]); in genpd_summary_one()
2955 seq_printf(s, "%-30s %-15s ", genpd->name, state); in genpd_summary_one()
2962 list_for_each_entry(link, &genpd->parent_links, parent_node) { in genpd_summary_one()
2964 if (!list_is_last(&link->parent_node, &genpd->parent_links)) in genpd_summary_one()
2968 list_for_each_entry(pm_data, &genpd->dev_list, list_node) { in genpd_summary_one()
2970 genpd_is_irq_safe(genpd) ? in genpd_summary_one()
2982 genpd_unlock(genpd); in genpd_summary_one()
2989 struct generic_pm_domain *genpd; in summary_show() local
3000 list_for_each_entry(genpd, &gpd_list, gpd_list_node) { in summary_show()
3001 ret = genpd_summary_one(s, genpd); in summary_show()
3017 struct generic_pm_domain *genpd = s->private; in status_show() local
3020 ret = genpd_lock_interruptible(genpd); in status_show()
3024 if (WARN_ON_ONCE(genpd->status >= ARRAY_SIZE(status_lookup))) in status_show()
3027 if (genpd->status == GENPD_STATE_OFF) in status_show()
3028 seq_printf(s, "%s-%u\n", status_lookup[genpd->status], in status_show()
3029 genpd->state_idx); in status_show()
3031 seq_printf(s, "%s\n", status_lookup[genpd->status]); in status_show()
3033 genpd_unlock(genpd); in status_show()
3039 struct generic_pm_domain *genpd = s->private; in sub_domains_show() local
3043 ret = genpd_lock_interruptible(genpd); in sub_domains_show()
3047 list_for_each_entry(link, &genpd->parent_links, parent_node) in sub_domains_show()
3050 genpd_unlock(genpd); in sub_domains_show()
3056 struct generic_pm_domain *genpd = s->private; in idle_states_show() local
3060 ret = genpd_lock_interruptible(genpd); in idle_states_show()
3066 for (i = 0; i < genpd->state_count; i++) { in idle_states_show()
3070 if ((genpd->status == GENPD_STATE_OFF) && in idle_states_show()
3071 (genpd->state_idx == i)) in idle_states_show()
3072 delta = ktime_sub(ktime_get(), genpd->accounting_time); in idle_states_show()
3075 ktime_add(genpd->states[i].idle_time, delta)); in idle_states_show()
3077 genpd->states[i].usage, genpd->states[i].rejected); in idle_states_show()
3080 genpd_unlock(genpd); in idle_states_show()
3086 struct generic_pm_domain *genpd = s->private; in active_time_show() local
3090 ret = genpd_lock_interruptible(genpd); in active_time_show()
3094 if (genpd->status == GENPD_STATE_ON) in active_time_show()
3095 delta = ktime_sub(ktime_get(), genpd->accounting_time); in active_time_show()
3098 ktime_add(genpd->on_time, delta))); in active_time_show()
3100 genpd_unlock(genpd); in active_time_show()
3106 struct generic_pm_domain *genpd = s->private; in total_idle_time_show() local
3111 ret = genpd_lock_interruptible(genpd); in total_idle_time_show()
3115 for (i = 0; i < genpd->state_count; i++) { in total_idle_time_show()
3117 if ((genpd->status == GENPD_STATE_OFF) && in total_idle_time_show()
3118 (genpd->state_idx == i)) in total_idle_time_show()
3119 delta = ktime_sub(ktime_get(), genpd->accounting_time); in total_idle_time_show()
3121 total = ktime_add(total, genpd->states[i].idle_time); in total_idle_time_show()
3127 genpd_unlock(genpd); in total_idle_time_show()
3134 struct generic_pm_domain *genpd = s->private; in devices_show() local
3139 ret = genpd_lock_interruptible(genpd); in devices_show()
3143 list_for_each_entry(pm_data, &genpd->dev_list, list_node) { in devices_show()
3145 genpd_is_irq_safe(genpd) ? in devices_show()
3154 genpd_unlock(genpd); in devices_show()
3160 struct generic_pm_domain *genpd = s->private; in perf_state_show() local
3162 if (genpd_lock_interruptible(genpd)) in perf_state_show()
3165 seq_printf(s, "%u\n", genpd->performance_state); in perf_state_show()
3167 genpd_unlock(genpd); in perf_state_show()
3183 struct generic_pm_domain *genpd; in genpd_debug_init() local
3190 list_for_each_entry(genpd, &gpd_list, gpd_list_node) { in genpd_debug_init()
3191 d = debugfs_create_dir(genpd->name, genpd_debugfs_dir); in genpd_debug_init()
3194 d, genpd, &status_fops); in genpd_debug_init()
3196 d, genpd, &sub_domains_fops); in genpd_debug_init()
3198 d, genpd, &idle_states_fops); in genpd_debug_init()
3200 d, genpd, &active_time_fops); in genpd_debug_init()
3202 d, genpd, &total_idle_time_fops); in genpd_debug_init()
3204 d, genpd, &devices_fops); in genpd_debug_init()
3205 if (genpd->set_performance_state) in genpd_debug_init()
3207 d, genpd, &perf_state_fops); in genpd_debug_init()