Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge branches 'pm-sleep', 'pm-domains', 'powercap' and 'pm-tools'

* pm-sleep:
PM: sleep: spread "const char *" correctness
PM: hibernate: fix white space in a few places
freezer: Add unsafe version of freezable_schedule_timeout_interruptible() for NFS
PM: sleep: core: Emit changed uevent on wakeup_sysfs_add/remove

* pm-domains:
PM: domains: Restore comment indentation for generic_pm_domain.child_links
PM: domains: Fix up terminology with parent/child

* powercap:
powercap: Add Power Limit4 support
powercap: idle_inject: Replace play_idle() with play_idle_precise() in comments
powercap: intel_rapl: add support for Sapphire Rapids

* pm-tools:
pm-graph v5.7 - important s2idle fixes
cpupower: Replace HTTP links with HTTPS ones
cpupower: Fix NULL but dereferenced coccicheck errors
cpupower: Fix comparing pointer to 0 coccicheck warns

+411 -249
+10 -5
Documentation/power/powercap/powercap.rst
··· 167 167 package-0 168 168 --------- 169 169 170 - The Intel RAPL technology allows two constraints, short term and long term, 171 - with two different time windows to be applied to each power zone. Thus for 172 - each zone there are 2 attributes representing the constraint names, 2 power 173 - limits and 2 attributes representing the sizes of the time windows. Such that, 174 - constraint_j_* attributes correspond to the jth constraint (j = 0,1). 170 + Depending on different power zones, the Intel RAPL technology allows 171 + one or multiple constraints like short term, long term and peak power, 172 + with different time windows to be applied to each power zone. 173 + All the zones contain attributes representing the constraint names, 174 + power limits and the sizes of the time windows. Note that time window 175 + is not applicable to peak power. Here, constraint_j_* attributes 176 + correspond to the jth constraint (j = 0,1,2). 175 177 176 178 For example:: 177 179 ··· 183 181 constraint_1_name 184 182 constraint_1_power_limit_uw 185 183 constraint_1_time_window_us 184 + constraint_2_name 185 + constraint_2_power_limit_uw 186 + constraint_2_time_window_us 186 187 187 188 Power Zone Attributes 188 189 =====================
+97 -97
drivers/base/power/domain.c
··· 263 263 /* 264 264 * Traverse all sub-domains within the domain. This can be 265 265 * done without any additional locking as the link->performance_state 266 - * field is protected by the master genpd->lock, which is already taken. 266 + * field is protected by the parent genpd->lock, which is already taken. 267 267 * 268 268 * Also note that link->performance_state (subdomain's performance state 269 - * requirement to master domain) is different from 270 - * link->slave->performance_state (current performance state requirement 269 + * requirement to parent domain) is different from 270 + * link->child->performance_state (current performance state requirement 271 271 * of the devices/sub-domains of the subdomain) and so can have a 272 272 * different value. 273 273 * 274 274 * Note that we also take vote from powered-off sub-domains into account 275 275 * as the same is done for devices right now. 276 276 */ 277 - list_for_each_entry(link, &genpd->master_links, master_node) { 277 + list_for_each_entry(link, &genpd->parent_links, parent_node) { 278 278 if (link->performance_state > state) 279 279 state = link->performance_state; 280 280 } ··· 285 285 static int _genpd_set_performance_state(struct generic_pm_domain *genpd, 286 286 unsigned int state, int depth) 287 287 { 288 - struct generic_pm_domain *master; 288 + struct generic_pm_domain *parent; 289 289 struct gpd_link *link; 290 - int master_state, ret; 290 + int parent_state, ret; 291 291 292 292 if (state == genpd->performance_state) 293 293 return 0; 294 294 295 - /* Propagate to masters of genpd */ 296 - list_for_each_entry(link, &genpd->slave_links, slave_node) { 297 - master = link->master; 295 + /* Propagate to parents of genpd */ 296 + list_for_each_entry(link, &genpd->child_links, child_node) { 297 + parent = link->parent; 298 298 299 - if (!master->set_performance_state) 299 + if (!parent->set_performance_state) 300 300 continue; 301 301 302 - /* Find master's performance state */ 302 + /* Find parent's performance state */ 303 303 ret = dev_pm_opp_xlate_performance_state(genpd->opp_table, 304 - master->opp_table, 304 + parent->opp_table, 305 305 state); 306 306 if (unlikely(ret < 0)) 307 307 goto err; 308 308 309 - master_state = ret; 309 + parent_state = ret; 310 310 311 - genpd_lock_nested(master, depth + 1); 311 + genpd_lock_nested(parent, depth + 1); 312 312 313 313 link->prev_performance_state = link->performance_state; 314 - link->performance_state = master_state; 315 - master_state = _genpd_reeval_performance_state(master, 316 - master_state); 317 - ret = _genpd_set_performance_state(master, master_state, depth + 1); 314 + link->performance_state = parent_state; 315 + parent_state = _genpd_reeval_performance_state(parent, 316 + parent_state); 317 + ret = _genpd_set_performance_state(parent, parent_state, depth + 1); 318 318 if (ret) 319 319 link->performance_state = link->prev_performance_state; 320 320 321 - genpd_unlock(master); 321 + genpd_unlock(parent); 322 322 323 323 if (ret) 324 324 goto err; ··· 333 333 334 334 err: 335 335 /* Encountered an error, lets rollback */ 336 - list_for_each_entry_continue_reverse(link, &genpd->slave_links, 337 - slave_node) { 338 - master = link->master; 336 + list_for_each_entry_continue_reverse(link, &genpd->child_links, 337 + child_node) { 338 + parent = link->parent; 339 339 340 - if (!master->set_performance_state) 340 + if (!parent->set_performance_state) 341 341 continue; 342 342 343 - genpd_lock_nested(master, depth + 1); 343 + genpd_lock_nested(parent, depth + 1); 344 344 345 - master_state = link->prev_performance_state; 346 - link->performance_state = master_state; 345 + parent_state = link->prev_performance_state; 346 + link->performance_state = parent_state; 347 347 348 - master_state = _genpd_reeval_performance_state(master, 349 - master_state); 350 - if (_genpd_set_performance_state(master, master_state, depth + 1)) { 348 + parent_state = _genpd_reeval_performance_state(parent, 349 + parent_state); 350 + if (_genpd_set_performance_state(parent, parent_state, depth + 1)) { 351 351 pr_err("%s: Failed to roll back to %d performance state\n", 352 - master->name, master_state); 352 + parent->name, parent_state); 353 353 } 354 354 355 - genpd_unlock(master); 355 + genpd_unlock(parent); 356 356 } 357 357 358 358 return ret; ··· 552 552 553 553 /* 554 554 * If sd_count > 0 at this point, one of the subdomains hasn't 555 - * managed to call genpd_power_on() for the master yet after 555 + * managed to call genpd_power_on() for the parent yet after 556 556 * incrementing it. In that case genpd_power_on() will wait 557 557 * for us to drop the lock, so we can call .power_off() and let 558 558 * the genpd_power_on() restore power for us (this shouldn't ··· 566 566 genpd->status = GPD_STATE_POWER_OFF; 567 567 genpd_update_accounting(genpd); 568 568 569 - list_for_each_entry(link, &genpd->slave_links, slave_node) { 570 - genpd_sd_counter_dec(link->master); 571 - genpd_lock_nested(link->master, depth + 1); 572 - genpd_power_off(link->master, false, depth + 1); 573 - genpd_unlock(link->master); 569 + list_for_each_entry(link, &genpd->child_links, child_node) { 570 + genpd_sd_counter_dec(link->parent); 571 + genpd_lock_nested(link->parent, depth + 1); 572 + genpd_power_off(link->parent, false, depth + 1); 573 + genpd_unlock(link->parent); 574 574 } 575 575 576 576 return 0; 577 577 } 578 578 579 579 /** 580 - * genpd_power_on - Restore power to a given PM domain and its masters. 580 + * genpd_power_on - Restore power to a given PM domain and its parents. 581 581 * @genpd: PM domain to power up. 582 582 * @depth: nesting count for lockdep. 583 583 * 584 - * Restore power to @genpd and all of its masters so that it is possible to 584 + * Restore power to @genpd and all of its parents so that it is possible to 585 585 * resume a device belonging to it. 586 586 */ 587 587 static int genpd_power_on(struct generic_pm_domain *genpd, unsigned int depth) ··· 594 594 595 595 /* 596 596 * The list is guaranteed not to change while the loop below is being 597 - * executed, unless one of the masters' .power_on() callbacks fiddles 597 + * executed, unless one of the parents' .power_on() callbacks fiddles 598 598 * with it. 599 599 */ 600 - list_for_each_entry(link, &genpd->slave_links, slave_node) { 601 - struct generic_pm_domain *master = link->master; 600 + list_for_each_entry(link, &genpd->child_links, child_node) { 601 + struct generic_pm_domain *parent = link->parent; 602 602 603 - genpd_sd_counter_inc(master); 603 + genpd_sd_counter_inc(parent); 604 604 605 - genpd_lock_nested(master, depth + 1); 606 - ret = genpd_power_on(master, depth + 1); 607 - genpd_unlock(master); 605 + genpd_lock_nested(parent, depth + 1); 606 + ret = genpd_power_on(parent, depth + 1); 607 + genpd_unlock(parent); 608 608 609 609 if (ret) { 610 - genpd_sd_counter_dec(master); 610 + genpd_sd_counter_dec(parent); 611 611 goto err; 612 612 } 613 613 } ··· 623 623 624 624 err: 625 625 list_for_each_entry_continue_reverse(link, 626 - &genpd->slave_links, 627 - slave_node) { 628 - genpd_sd_counter_dec(link->master); 629 - genpd_lock_nested(link->master, depth + 1); 630 - genpd_power_off(link->master, false, depth + 1); 631 - genpd_unlock(link->master); 626 + &genpd->child_links, 627 + child_node) { 628 + genpd_sd_counter_dec(link->parent); 629 + genpd_lock_nested(link->parent, depth + 1); 630 + genpd_power_off(link->parent, false, depth + 1); 631 + genpd_unlock(link->parent); 632 632 } 633 633 634 634 return ret; ··· 932 932 #ifdef CONFIG_PM_SLEEP 933 933 934 934 /** 935 - * genpd_sync_power_off - Synchronously power off a PM domain and its masters. 935 + * genpd_sync_power_off - Synchronously power off a PM domain and its parents. 936 936 * @genpd: PM domain to power off, if possible. 937 937 * @use_lock: use the lock. 938 938 * @depth: nesting count for lockdep. 939 939 * 940 940 * Check if the given PM domain can be powered off (during system suspend or 941 - * hibernation) and do that if so. Also, in that case propagate to its masters. 941 + * hibernation) and do that if so. Also, in that case propagate to its parents. 942 942 * 943 943 * This function is only called in "noirq" and "syscore" stages of system power 944 944 * transitions. The "noirq" callbacks may be executed asynchronously, thus in ··· 963 963 964 964 genpd->status = GPD_STATE_POWER_OFF; 965 965 966 - list_for_each_entry(link, &genpd->slave_links, slave_node) { 967 - genpd_sd_counter_dec(link->master); 966 + list_for_each_entry(link, &genpd->child_links, child_node) { 967 + genpd_sd_counter_dec(link->parent); 968 968 969 969 if (use_lock) 970 - genpd_lock_nested(link->master, depth + 1); 970 + genpd_lock_nested(link->parent, depth + 1); 971 971 972 - genpd_sync_power_off(link->master, use_lock, depth + 1); 972 + genpd_sync_power_off(link->parent, use_lock, depth + 1); 973 973 974 974 if (use_lock) 975 - genpd_unlock(link->master); 975 + genpd_unlock(link->parent); 976 976 } 977 977 } 978 978 979 979 /** 980 - * genpd_sync_power_on - Synchronously power on a PM domain and its masters. 980 + * genpd_sync_power_on - Synchronously power on a PM domain and its parents. 981 981 * @genpd: PM domain to power on. 982 982 * @use_lock: use the lock. 983 983 * @depth: nesting count for lockdep. ··· 994 994 if (genpd_status_on(genpd)) 995 995 return; 996 996 997 - list_for_each_entry(link, &genpd->slave_links, slave_node) { 998 - genpd_sd_counter_inc(link->master); 997 + list_for_each_entry(link, &genpd->child_links, child_node) { 998 + genpd_sd_counter_inc(link->parent); 999 999 1000 1000 if (use_lock) 1001 - genpd_lock_nested(link->master, depth + 1); 1001 + genpd_lock_nested(link->parent, depth + 1); 1002 1002 1003 - genpd_sync_power_on(link->master, use_lock, depth + 1); 1003 + genpd_sync_power_on(link->parent, use_lock, depth + 1); 1004 1004 1005 1005 if (use_lock) 1006 - genpd_unlock(link->master); 1006 + genpd_unlock(link->parent); 1007 1007 } 1008 1008 1009 1009 _genpd_power_on(genpd, false); ··· 1443 1443 if (!genpd_is_cpu_domain(genpd)) 1444 1444 return; 1445 1445 1446 - list_for_each_entry(link, &genpd->slave_links, slave_node) { 1447 - struct generic_pm_domain *master = link->master; 1446 + list_for_each_entry(link, &genpd->child_links, child_node) { 1447 + struct generic_pm_domain *parent = link->parent; 1448 1448 1449 - genpd_lock_nested(master, depth + 1); 1450 - genpd_update_cpumask(master, cpu, set, depth + 1); 1451 - genpd_unlock(master); 1449 + genpd_lock_nested(parent, depth + 1); 1450 + genpd_update_cpumask(parent, cpu, set, depth + 1); 1451 + genpd_unlock(parent); 1452 1452 } 1453 1453 1454 1454 if (set) ··· 1636 1636 goto out; 1637 1637 } 1638 1638 1639 - list_for_each_entry(itr, &genpd->master_links, master_node) { 1640 - if (itr->slave == subdomain && itr->master == genpd) { 1639 + list_for_each_entry(itr, &genpd->parent_links, parent_node) { 1640 + if (itr->child == subdomain && itr->parent == genpd) { 1641 1641 ret = -EINVAL; 1642 1642 goto out; 1643 1643 } 1644 1644 } 1645 1645 1646 - link->master = genpd; 1647 - list_add_tail(&link->master_node, &genpd->master_links); 1648 - link->slave = subdomain; 1649 - list_add_tail(&link->slave_node, &subdomain->slave_links); 1646 + link->parent = genpd; 1647 + list_add_tail(&link->parent_node, &genpd->parent_links); 1648 + link->child = subdomain; 1649 + list_add_tail(&link->child_node, &subdomain->child_links); 1650 1650 if (genpd_status_on(subdomain)) 1651 1651 genpd_sd_counter_inc(genpd); 1652 1652 ··· 1660 1660 1661 1661 /** 1662 1662 * pm_genpd_add_subdomain - Add a subdomain to an I/O PM domain. 1663 - * @genpd: Master PM domain to add the subdomain to. 1663 + * @genpd: Leader PM domain to add the subdomain to. 1664 1664 * @subdomain: Subdomain to be added. 1665 1665 */ 1666 1666 int pm_genpd_add_subdomain(struct generic_pm_domain *genpd, ··· 1678 1678 1679 1679 /** 1680 1680 * pm_genpd_remove_subdomain - Remove a subdomain from an I/O PM domain. 1681 - * @genpd: Master PM domain to remove the subdomain from. 1681 + * @genpd: Leader PM domain to remove the subdomain from. 1682 1682 * @subdomain: Subdomain to be removed. 1683 1683 */ 1684 1684 int pm_genpd_remove_subdomain(struct generic_pm_domain *genpd, ··· 1693 1693 genpd_lock(subdomain); 1694 1694 genpd_lock_nested(genpd, SINGLE_DEPTH_NESTING); 1695 1695 1696 - if (!list_empty(&subdomain->master_links) || subdomain->device_count) { 1696 + if (!list_empty(&subdomain->parent_links) || subdomain->device_count) { 1697 1697 pr_warn("%s: unable to remove subdomain %s\n", 1698 1698 genpd->name, subdomain->name); 1699 1699 ret = -EBUSY; 1700 1700 goto out; 1701 1701 } 1702 1702 1703 - list_for_each_entry_safe(link, l, &genpd->master_links, master_node) { 1704 - if (link->slave != subdomain) 1703 + list_for_each_entry_safe(link, l, &genpd->parent_links, parent_node) { 1704 + if (link->child != subdomain) 1705 1705 continue; 1706 1706 1707 - list_del(&link->master_node); 1708 - list_del(&link->slave_node); 1707 + list_del(&link->parent_node); 1708 + list_del(&link->child_node); 1709 1709 kfree(link); 1710 1710 if (genpd_status_on(subdomain)) 1711 1711 genpd_sd_counter_dec(genpd); ··· 1770 1770 if (IS_ERR_OR_NULL(genpd)) 1771 1771 return -EINVAL; 1772 1772 1773 - INIT_LIST_HEAD(&genpd->master_links); 1774 - INIT_LIST_HEAD(&genpd->slave_links); 1773 + INIT_LIST_HEAD(&genpd->parent_links); 1774 + INIT_LIST_HEAD(&genpd->child_links); 1775 1775 INIT_LIST_HEAD(&genpd->dev_list); 1776 1776 genpd_lock_init(genpd); 1777 1777 genpd->gov = gov; ··· 1848 1848 return -EBUSY; 1849 1849 } 1850 1850 1851 - if (!list_empty(&genpd->master_links) || genpd->device_count) { 1851 + if (!list_empty(&genpd->parent_links) || genpd->device_count) { 1852 1852 genpd_unlock(genpd); 1853 1853 pr_err("%s: unable to remove %s\n", __func__, genpd->name); 1854 1854 return -EBUSY; 1855 1855 } 1856 1856 1857 - list_for_each_entry_safe(link, l, &genpd->slave_links, slave_node) { 1858 - list_del(&link->master_node); 1859 - list_del(&link->slave_node); 1857 + list_for_each_entry_safe(link, l, &genpd->child_links, child_node) { 1858 + list_del(&link->parent_node); 1859 + list_del(&link->child_node); 1860 1860 kfree(link); 1861 1861 } 1862 1862 ··· 2827 2827 2828 2828 /* 2829 2829 * Modifications on the list require holding locks on both 2830 - * master and slave, so we are safe. 2830 + * parent and child, so we are safe. 2831 2831 * Also genpd->name is immutable. 2832 2832 */ 2833 - list_for_each_entry(link, &genpd->master_links, master_node) { 2834 - seq_printf(s, "%s", link->slave->name); 2835 - if (!list_is_last(&link->master_node, &genpd->master_links)) 2833 + list_for_each_entry(link, &genpd->parent_links, parent_node) { 2834 + seq_printf(s, "%s", link->child->name); 2835 + if (!list_is_last(&link->parent_node, &genpd->parent_links)) 2836 2836 seq_puts(s, ", "); 2837 2837 } 2838 2838 ··· 2860 2860 struct generic_pm_domain *genpd; 2861 2861 int ret = 0; 2862 2862 2863 - seq_puts(s, "domain status slaves\n"); 2863 + seq_puts(s, "domain status children\n"); 2864 2864 seq_puts(s, " /device runtime status\n"); 2865 2865 seq_puts(s, "----------------------------------------------------------------------\n"); 2866 2866 ··· 2915 2915 if (ret) 2916 2916 return -ERESTARTSYS; 2917 2917 2918 - list_for_each_entry(link, &genpd->master_links, master_node) 2919 - seq_printf(s, "%s\n", link->slave->name); 2918 + list_for_each_entry(link, &genpd->parent_links, parent_node) 2919 + seq_printf(s, "%s\n", link->child->name); 2920 2920 2921 2921 genpd_unlock(genpd); 2922 2922 return ret;
+6 -6
drivers/base/power/domain_governor.c
··· 135 135 * 136 136 * All subdomains have been powered off already at this point. 137 137 */ 138 - list_for_each_entry(link, &genpd->master_links, master_node) { 139 - struct generic_pm_domain *sd = link->slave; 138 + list_for_each_entry(link, &genpd->parent_links, parent_node) { 139 + struct generic_pm_domain *sd = link->child; 140 140 s64 sd_max_off_ns = sd->max_off_time_ns; 141 141 142 142 if (sd_max_off_ns < 0) ··· 217 217 } 218 218 219 219 /* 220 - * We have to invalidate the cached results for the masters, so 220 + * We have to invalidate the cached results for the parents, so 221 221 * use the observation that default_power_down_ok() is not 222 - * going to be called for any master until this instance 222 + * going to be called for any parent until this instance 223 223 * returns. 224 224 */ 225 - list_for_each_entry(link, &genpd->slave_links, slave_node) 226 - link->master->max_off_time_changed = true; 225 + list_for_each_entry(link, &genpd->child_links, child_node) 226 + link->parent->max_off_time_changed = true; 227 227 228 228 genpd->max_off_time_ns = -1; 229 229 genpd->max_off_time_changed = false;
+8 -1
drivers/base/power/sysfs.c
··· 1 1 // SPDX-License-Identifier: GPL-2.0 2 2 /* sysfs entries for device PM */ 3 3 #include <linux/device.h> 4 + #include <linux/kobject.h> 4 5 #include <linux/string.h> 5 6 #include <linux/export.h> 6 7 #include <linux/pm_qos.h> ··· 740 739 741 740 int wakeup_sysfs_add(struct device *dev) 742 741 { 743 - return sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group); 742 + int ret = sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group); 743 + 744 + if (!ret) 745 + kobject_uevent(&dev->kobj, KOBJ_CHANGE); 746 + 747 + return ret; 744 748 } 745 749 746 750 void wakeup_sysfs_remove(struct device *dev) 747 751 { 748 752 sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group); 753 + kobject_uevent(&dev->kobj, KOBJ_CHANGE); 749 754 } 750 755 751 756 int pm_qos_sysfs_add_resume_latency(struct device *dev)
+5 -5
drivers/powercap/idle_inject.c
··· 19 19 * The idle + run duration is specified via separate helpers and that allows 20 20 * idle injection to be started. 21 21 * 22 - * The idle injection kthreads will call play_idle() with the idle duration 23 - * specified as per the above. 22 + * The idle injection kthreads will call play_idle_precise() with the idle 23 + * duration and max allowed latency specified as per the above. 24 24 * 25 25 * After all of them have been woken up, a timer is set to start the next idle 26 26 * injection cycle. ··· 100 100 * 101 101 * This function is called when the idle injection timer expires. It wakes up 102 102 * idle injection tasks associated with the timer and they, in turn, invoke 103 - * play_idle() to inject a specified amount of CPU idle time. 103 + * play_idle_precise() to inject a specified amount of CPU idle time. 104 104 * 105 105 * Return: HRTIMER_RESTART. 106 106 */ ··· 124 124 * idle_inject_fn - idle injection work function 125 125 * @cpu: the CPU owning the task 126 126 * 127 - * This function calls play_idle() to inject a specified amount of CPU idle 128 - * time. 127 + * This function calls play_idle_precise() to inject a specified amount of CPU 128 + * idle time. 129 129 */ 130 130 static void idle_inject_fn(unsigned int cpu) 131 131 {
+74 -3
drivers/powercap/intel_rapl_common.c
··· 39 39 #define POWER_HIGH_LOCK BIT_ULL(63) 40 40 #define POWER_LOW_LOCK BIT(31) 41 41 42 + #define POWER_LIMIT4_MASK 0x1FFF 43 + 42 44 #define TIME_WINDOW1_MASK (0x7FULL<<17) 43 45 #define TIME_WINDOW2_MASK (0x7FULL<<49) 44 46 ··· 84 82 85 83 static const char pl1_name[] = "long_term"; 86 84 static const char pl2_name[] = "short_term"; 85 + static const char pl4_name[] = "peak_power"; 87 86 88 87 #define power_zone_to_rapl_domain(_zone) \ 89 88 container_of(_zone, struct rapl_domain, power_zone) ··· 96 93 u64 (*compute_time_window)(struct rapl_package *rp, u64 val, 97 94 bool to_raw); 98 95 unsigned int dram_domain_energy_unit; 96 + unsigned int psys_domain_energy_unit; 99 97 }; 100 98 static struct rapl_defaults *rapl_defaults; 101 99 ··· 341 337 case PL2_ENABLE: 342 338 rapl_write_data_raw(rd, POWER_LIMIT2, power_limit); 343 339 break; 340 + case PL4_ENABLE: 341 + rapl_write_data_raw(rd, POWER_LIMIT4, power_limit); 342 + break; 344 343 default: 345 344 ret = -EINVAL; 346 345 } ··· 377 370 break; 378 371 case PL2_ENABLE: 379 372 prim = POWER_LIMIT2; 373 + break; 374 + case PL4_ENABLE: 375 + prim = POWER_LIMIT4; 380 376 break; 381 377 default: 382 378 put_online_cpus(); ··· 450 440 case PL2_ENABLE: 451 441 ret = rapl_read_data_raw(rd, TIME_WINDOW2, true, &val); 452 442 break; 443 + case PL4_ENABLE: 444 + /* 445 + * Time window parameter is not applicable for PL4 entry 446 + * so assigining '0' as default value. 447 + */ 448 + val = 0; 449 + break; 453 450 default: 454 451 put_online_cpus(); 455 452 return -EINVAL; ··· 500 483 case PL2_ENABLE: 501 484 prim = MAX_POWER; 502 485 break; 486 + case PL4_ENABLE: 487 + prim = MAX_POWER; 488 + break; 503 489 default: 504 490 put_online_cpus(); 505 491 return -EINVAL; ··· 511 491 ret = -EIO; 512 492 else 513 493 *data = val; 494 + 495 + /* As a generalization rule, PL4 would be around two times PL2. */ 496 + if (rd->rpl[id].prim_id == PL4_ENABLE) 497 + *data = *data * 2; 514 498 515 499 put_online_cpus(); 516 500 ··· 548 524 rd->id = i; 549 525 rd->rpl[0].prim_id = PL1_ENABLE; 550 526 rd->rpl[0].name = pl1_name; 551 - /* some domain may support two power limits */ 552 - if (rp->priv->limits[i] == 2) { 527 + 528 + /* 529 + * The PL2 power domain is applicable for limits two 530 + * and limits three 531 + */ 532 + if (rp->priv->limits[i] >= 2) { 553 533 rd->rpl[1].prim_id = PL2_ENABLE; 554 534 rd->rpl[1].name = pl2_name; 535 + } 536 + 537 + /* Enable PL4 domain if the total power limits are three */ 538 + if (rp->priv->limits[i] == 3) { 539 + rd->rpl[2].prim_id = PL4_ENABLE; 540 + rd->rpl[2].name = pl4_name; 555 541 } 556 542 557 543 for (j = 0; j < RAPL_DOMAIN_REG_MAX; j++) 558 544 rd->regs[j] = rp->priv->regs[i][j]; 559 545 560 - if (i == RAPL_DOMAIN_DRAM) { 546 + switch (i) { 547 + case RAPL_DOMAIN_DRAM: 561 548 rd->domain_energy_unit = 562 549 rapl_defaults->dram_domain_energy_unit; 563 550 if (rd->domain_energy_unit) 564 551 pr_info("DRAM domain energy unit %dpj\n", 565 552 rd->domain_energy_unit); 553 + break; 554 + case RAPL_DOMAIN_PLATFORM: 555 + rd->domain_energy_unit = 556 + rapl_defaults->psys_domain_energy_unit; 557 + if (rd->domain_energy_unit) 558 + pr_info("Platform domain energy unit %dpj\n", 559 + rd->domain_energy_unit); 560 + break; 561 + default: 562 + break; 566 563 } 567 564 rd++; 568 565 } ··· 632 587 RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0), 633 588 PRIMITIVE_INFO_INIT(POWER_LIMIT2, POWER_LIMIT2_MASK, 32, 634 589 RAPL_DOMAIN_REG_LIMIT, POWER_UNIT, 0), 590 + PRIMITIVE_INFO_INIT(POWER_LIMIT4, POWER_LIMIT4_MASK, 0, 591 + RAPL_DOMAIN_REG_PL4, POWER_UNIT, 0), 635 592 PRIMITIVE_INFO_INIT(FW_LOCK, POWER_LOW_LOCK, 31, 636 593 RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0), 637 594 PRIMITIVE_INFO_INIT(PL1_ENABLE, POWER_LIMIT1_ENABLE, 15, ··· 644 597 RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0), 645 598 PRIMITIVE_INFO_INIT(PL2_CLAMP, POWER_LIMIT2_CLAMP, 48, 646 599 RAPL_DOMAIN_REG_LIMIT, ARBITRARY_UNIT, 0), 600 + PRIMITIVE_INFO_INIT(PL4_ENABLE, POWER_LIMIT4_MASK, 0, 601 + RAPL_DOMAIN_REG_PL4, ARBITRARY_UNIT, 0), 647 602 PRIMITIVE_INFO_INIT(TIME_WINDOW1, TIME_WINDOW1_MASK, 17, 648 603 RAPL_DOMAIN_REG_LIMIT, TIME_UNIT, 0), 649 604 PRIMITIVE_INFO_INIT(TIME_WINDOW2, TIME_WINDOW2_MASK, 49, ··· 968 919 .dram_domain_energy_unit = 15300, 969 920 }; 970 921 922 + static const struct rapl_defaults rapl_defaults_spr_server = { 923 + .check_unit = rapl_check_unit_core, 924 + .set_floor_freq = set_floor_freq_default, 925 + .compute_time_window = rapl_compute_time_window_core, 926 + .dram_domain_energy_unit = 15300, 927 + .psys_domain_energy_unit = 1000000000, 928 + }; 929 + 971 930 static const struct rapl_defaults rapl_defaults_byt = { 972 931 .floor_freq_reg_addr = IOSF_CPU_POWER_BUDGET_CTL_BYT, 973 932 .check_unit = rapl_check_unit_atom, ··· 1035 978 X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE_L, &rapl_defaults_core), 1036 979 X86_MATCH_INTEL_FAM6_MODEL(COMETLAKE, &rapl_defaults_core), 1037 980 X86_MATCH_INTEL_FAM6_MODEL(TIGERLAKE_L, &rapl_defaults_core), 981 + X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, &rapl_defaults_spr_server), 1038 982 1039 983 X86_MATCH_INTEL_FAM6_MODEL(ATOM_SILVERMONT, &rapl_defaults_byt), 1040 984 X86_MATCH_INTEL_FAM6_MODEL(ATOM_AIRMONT, &rapl_defaults_cht), ··· 1310 1252 if (find_nr_power_limit(rd) > 1) { 1311 1253 rapl_write_data_raw(rd, PL2_ENABLE, 0); 1312 1254 rapl_write_data_raw(rd, PL2_CLAMP, 0); 1255 + rapl_write_data_raw(rd, PL4_ENABLE, 0); 1313 1256 } 1314 1257 if (rd->id == RAPL_DOMAIN_PACKAGE) { 1315 1258 rd_package = rd; ··· 1419 1360 if (ret) 1420 1361 rd->rpl[i].last_power_limit = 0; 1421 1362 break; 1363 + case PL4_ENABLE: 1364 + ret = rapl_read_data_raw(rd, 1365 + POWER_LIMIT4, true, 1366 + &rd->rpl[i].last_power_limit); 1367 + if (ret) 1368 + rd->rpl[i].last_power_limit = 0; 1369 + break; 1422 1370 } 1423 1371 } 1424 1372 } ··· 1454 1388 case PL2_ENABLE: 1455 1389 if (rd->rpl[i].last_power_limit) 1456 1390 rapl_write_data_raw(rd, POWER_LIMIT2, 1391 + rd->rpl[i].last_power_limit); 1392 + break; 1393 + case PL4_ENABLE: 1394 + if (rd->rpl[i].last_power_limit) 1395 + rapl_write_data_raw(rd, POWER_LIMIT4, 1457 1396 rd->rpl[i].last_power_limit); 1458 1397 break; 1459 1398 }
+15
drivers/powercap/intel_rapl_msr.c
··· 28 28 29 29 /* Local defines */ 30 30 #define MSR_PLATFORM_POWER_LIMIT 0x0000065C 31 + #define MSR_VR_CURRENT_CONFIG 0x00000601 31 32 32 33 /* private data for RAPL MSR Interface */ 33 34 static struct rapl_if_priv rapl_msr_priv = { ··· 124 123 return ra->err; 125 124 } 126 125 126 + /* List of verified CPUs. */ 127 + static const struct x86_cpu_id pl4_support_ids[] = { 128 + { X86_VENDOR_INTEL, 6, INTEL_FAM6_TIGERLAKE_L, X86_FEATURE_ANY }, 129 + {} 130 + }; 131 + 127 132 static int rapl_msr_probe(struct platform_device *pdev) 128 133 { 134 + const struct x86_cpu_id *id = x86_match_cpu(pl4_support_ids); 129 135 int ret; 130 136 131 137 rapl_msr_priv.read_raw = rapl_msr_read_raw; 132 138 rapl_msr_priv.write_raw = rapl_msr_write_raw; 139 + 140 + if (id) { 141 + rapl_msr_priv.limits[RAPL_DOMAIN_PACKAGE] = 3; 142 + rapl_msr_priv.regs[RAPL_DOMAIN_PACKAGE][RAPL_DOMAIN_REG_PL4] = 143 + MSR_VR_CURRENT_CONFIG; 144 + pr_info("PL4 support detected.\n"); 145 + } 133 146 134 147 rapl_msr_priv.control_type = powercap_register_control_type(NULL, "intel-rapl", NULL); 135 148 if (IS_ERR(rapl_msr_priv.control_type)) {
+1 -1
fs/nfs/nfs4proc.c
··· 414 414 { 415 415 might_sleep(); 416 416 417 - freezable_schedule_timeout_interruptible(nfs4_update_delay(timeout)); 417 + freezable_schedule_timeout_interruptible_unsafe(nfs4_update_delay(timeout)); 418 418 if (!signal_pending(current)) 419 419 return 0; 420 420 return __fatal_signal_pending(current) ? -EINTR :-ERESTARTSYS;
+14
include/linux/freezer.h
··· 207 207 return __retval; 208 208 } 209 209 210 + /* DO NOT ADD ANY NEW CALLERS OF THIS FUNCTION */ 211 + static inline long freezable_schedule_timeout_interruptible_unsafe(long timeout) 212 + { 213 + long __retval; 214 + 215 + freezer_do_not_count(); 216 + __retval = schedule_timeout_interruptible(timeout); 217 + freezer_count_unsafe(); 218 + return __retval; 219 + } 220 + 210 221 /* Like schedule_timeout_killable(), but should not block the freezer. */ 211 222 static inline long freezable_schedule_timeout_killable(long timeout) 212 223 { ··· 294 283 #define freezable_schedule_timeout(timeout) schedule_timeout(timeout) 295 284 296 285 #define freezable_schedule_timeout_interruptible(timeout) \ 286 + schedule_timeout_interruptible(timeout) 287 + 288 + #define freezable_schedule_timeout_interruptible_unsafe(timeout) \ 297 289 schedule_timeout_interruptible(timeout) 298 290 299 291 #define freezable_schedule_timeout_killable(timeout) \
+4 -1
include/linux/intel_rapl.h
··· 29 29 RAPL_DOMAIN_REG_PERF, 30 30 RAPL_DOMAIN_REG_POLICY, 31 31 RAPL_DOMAIN_REG_INFO, 32 + RAPL_DOMAIN_REG_PL4, 32 33 RAPL_DOMAIN_REG_MAX, 33 34 }; 34 35 ··· 39 38 ENERGY_COUNTER, 40 39 POWER_LIMIT1, 41 40 POWER_LIMIT2, 41 + POWER_LIMIT4, 42 42 FW_LOCK, 43 43 44 44 PL1_ENABLE, /* power limit 1, aka long term */ 45 45 PL1_CLAMP, /* allow frequency to go below OS request */ 46 46 PL2_ENABLE, /* power limit 2, aka short term, instantaneous */ 47 47 PL2_CLAMP, 48 + PL4_ENABLE, /* power limit 4, aka max peak power */ 48 49 49 50 TIME_WINDOW1, /* long term */ 50 51 TIME_WINDOW2, /* short term */ ··· 68 65 unsigned long timestamp; 69 66 }; 70 67 71 - #define NR_POWER_LIMITS (2) 68 + #define NR_POWER_LIMITS (3) 72 69 struct rapl_power_limit { 73 70 struct powercap_zone_constraint *constraint; 74 71 int prim_id; /* primitive ID used to enable */
+6 -6
include/linux/pm_domain.h
··· 95 95 struct device dev; 96 96 struct dev_pm_domain domain; /* PM domain operations */ 97 97 struct list_head gpd_list_node; /* Node in the global PM domains list */ 98 - struct list_head master_links; /* Links with PM domain as a master */ 99 - struct list_head slave_links; /* Links with PM domain as a slave */ 98 + struct list_head parent_links; /* Links with PM domain as a parent */ 99 + struct list_head child_links; /* Links with PM domain as a child */ 100 100 struct list_head dev_list; /* List of devices */ 101 101 struct dev_power_governor *gov; 102 102 struct work_struct power_off_work; ··· 151 151 } 152 152 153 153 struct gpd_link { 154 - struct generic_pm_domain *master; 155 - struct list_head master_node; 156 - struct generic_pm_domain *slave; 157 - struct list_head slave_node; 154 + struct generic_pm_domain *parent; 155 + struct list_head parent_node; 156 + struct generic_pm_domain *child; 157 + struct list_head child_node; 158 158 159 159 /* Sub-domain's per-master domain performance state */ 160 160 unsigned int performance_state;
+3 -3
kernel/power/hibernate.c
··· 1062 1062 static ssize_t resume_show(struct kobject *kobj, struct kobj_attribute *attr, 1063 1063 char *buf) 1064 1064 { 1065 - return sprintf(buf,"%d:%d\n", MAJOR(swsusp_resume_device), 1065 + return sprintf(buf, "%d:%d\n", MAJOR(swsusp_resume_device), 1066 1066 MINOR(swsusp_resume_device)); 1067 1067 } 1068 1068 ··· 1162 1162 1163 1163 power_attr(reserved_size); 1164 1164 1165 - static struct attribute * g[] = { 1165 + static struct attribute *g[] = { 1166 1166 &disk_attr.attr, 1167 1167 &resume_offset_attr.attr, 1168 1168 &resume_attr.attr, ··· 1190 1190 if (noresume) 1191 1191 return 1; 1192 1192 1193 - strncpy( resume_file, str, 255 ); 1193 + strncpy(resume_file, str, 255); 1194 1194 return 1; 1195 1195 } 1196 1196
+1 -1
kernel/power/power.h
··· 32 32 return arch_hibernation_header_save(info, MAX_ARCH_HEADER_SIZE); 33 33 } 34 34 35 - static inline char *check_image_kernel(struct swsusp_info *info) 35 + static inline const char *check_image_kernel(struct swsusp_info *info) 36 36 { 37 37 return arch_hibernation_header_restore(info) ? 38 38 "architecture specific data" : NULL;
+2 -2
kernel/power/snapshot.c
··· 2023 2023 return 0; 2024 2024 } 2025 2025 2026 - static char *check_image_kernel(struct swsusp_info *info) 2026 + static const char *check_image_kernel(struct swsusp_info *info) 2027 2027 { 2028 2028 if (info->version_code != LINUX_VERSION_CODE) 2029 2029 return "kernel version"; ··· 2176 2176 2177 2177 static int check_header(struct swsusp_info *info) 2178 2178 { 2179 - char *reason; 2179 + const char *reason; 2180 2180 2181 2181 reason = check_image_kernel(info); 2182 2182 if (!reason && info->num_physpages != get_num_physpages())
+6 -6
scripts/gdb/linux/genpd.py
··· 49 49 else: 50 50 status_string = 'off-{}'.format(genpd['state_idx']) 51 51 52 - slave_names = [] 52 + child_names = [] 53 53 for link in list_for_each_entry( 54 - genpd['master_links'], 54 + genpd['parent_links'], 55 55 device_link_type.get_type().pointer(), 56 - 'master_node'): 57 - slave_names.apend(link['slave']['name']) 56 + 'parent_node'): 57 + child_names.append(link['child']['name']) 58 58 59 59 gdb.write('%-30s %-15s %s\n' % ( 60 60 genpd['name'].string(), 61 61 status_string, 62 - ', '.join(slave_names))) 62 + ', '.join(child_names))) 63 63 64 64 # Print devices in domain 65 65 for pm_data in list_for_each_entry(genpd['dev_list'], ··· 70 70 gdb.write(' %-50s %s\n' % (kobj_path, rtpm_status_str(dev))) 71 71 72 72 def invoke(self, arg, from_tty): 73 - gdb.write('domain status slaves\n'); 73 + gdb.write('domain status children\n'); 74 74 gdb.write(' /device runtime status\n'); 75 75 gdb.write('----------------------------------------------------------------------\n'); 76 76 for genpd in list_for_each_entry(
+5 -5
tools/power/cpupower/lib/cpufreq.c
··· 285 285 } else { 286 286 first = malloc(sizeof(*first)); 287 287 if (!first) 288 - goto error_out; 288 + return NULL; 289 289 current = first; 290 290 } 291 291 current->first = first; ··· 362 362 } else { 363 363 first = malloc(sizeof(*first)); 364 364 if (!first) 365 - goto error_out; 365 + return NULL; 366 366 current = first; 367 367 } 368 368 current->first = first; ··· 418 418 } else { 419 419 first = malloc(sizeof(*first)); 420 420 if (!first) 421 - goto error_out; 421 + return NULL; 422 422 current = first; 423 423 } 424 424 current->first = first; ··· 493 493 } else { 494 494 first = malloc(sizeof(*first)); 495 495 if (!first) 496 - goto error_out; 496 + return NULL; 497 497 current = first; 498 498 } 499 499 current->first = first; ··· 726 726 } else { 727 727 first = malloc(sizeof(*first)); 728 728 if (!first) 729 - goto error_out; 729 + return NULL; 730 730 current = first; 731 731 } 732 732 current->first = first;
+2 -2
tools/power/cpupower/man/cpupower-monitor.1
··· 170 170 171 171 .SH REFERENCES 172 172 "BIOS and Kernel Developer’s Guide (BKDG) for AMD Family 14h Processors" 173 - http://support.amd.com/us/Processor_TechDocs/43170.pdf 173 + https://support.amd.com/us/Processor_TechDocs/43170.pdf 174 174 175 175 "Intel® Turbo Boost Technology 176 176 in Intel® Core™ Microarchitecture (Nehalem) Based Processors" ··· 178 178 179 179 "Intel® 64 and IA-32 Architectures Software Developer's Manual 180 180 Volume 3B: System Programming Guide" 181 - http://www.intel.com/products/processor/manuals 181 + https://www.intel.com/products/processor/manuals 182 182 183 183 .SH FILES 184 184 .ta
+3 -3
tools/power/cpupower/utils/helpers/bitmask.c
··· 26 26 struct bitmask *bmp; 27 27 28 28 bmp = malloc(sizeof(*bmp)); 29 - if (bmp == 0) 29 + if (!bmp) 30 30 return 0; 31 31 bmp->size = n; 32 32 bmp->maskp = calloc(longsperbits(n), sizeof(unsigned long)); 33 - if (bmp->maskp == 0) { 33 + if (!bmp->maskp) { 34 34 free(bmp); 35 35 return 0; 36 36 } ··· 40 40 /* Free `struct bitmask` */ 41 41 void bitmask_free(struct bitmask *bmp) 42 42 { 43 - if (bmp == 0) 43 + if (!bmp) 44 44 return; 45 45 free(bmp->maskp); 46 46 bmp->maskp = (unsigned long *)0xdeadcdef; /* double free tripwire */
+1 -1
tools/power/pm-graph/README
··· 6 6 |_| |___/ |_| 7 7 8 8 pm-graph: suspend/resume/boot timing analysis tools 9 - Version: 5.6 9 + Version: 5.7 10 10 Author: Todd Brandt <todd.e.brandt@intel.com> 11 11 Home Page: https://01.org/pm-graph 12 12
+148 -101
tools/power/pm-graph/sleepgraph.py
··· 81 81 # store system values and test parameters 82 82 class SystemValues: 83 83 title = 'SleepGraph' 84 - version = '5.6' 84 + version = '5.7' 85 85 ansi = False 86 86 rs = 0 87 87 display = '' ··· 198 198 'suspend_console': {}, 199 199 'acpi_pm_prepare': {}, 200 200 'syscore_suspend': {}, 201 - 'arch_thaw_secondary_cpus_end': {}, 201 + 'arch_enable_nonboot_cpus_end': {}, 202 202 'syscore_resume': {}, 203 203 'acpi_pm_finish': {}, 204 204 'resume_console': {}, ··· 924 924 tp = TestProps() 925 925 tf = self.openlog(self.ftracefile, 'r') 926 926 for line in tf: 927 - # determine the trace data type (required for further parsing) 928 - m = re.match(tp.tracertypefmt, line) 929 - if(m): 930 - tp.setTracerType(m.group('t')) 927 + if tp.stampInfo(line, self): 931 928 continue 932 929 # parse only valid lines, if this is not one move on 933 930 m = re.match(tp.ftrace_line_fmt, line) ··· 1241 1244 if self.xtraclass: 1242 1245 return ' '+self.xtraclass 1243 1246 if self.isasync: 1244 - return ' async_device' 1245 - return ' sync_device' 1247 + return ' (async)' 1248 + return ' (sync)' 1246 1249 1247 1250 # Class: DeviceNode 1248 1251 # Description: ··· 1298 1301 'FAIL' : r'(?i).*\bFAILED\b.*', 1299 1302 'INVALID' : r'(?i).*\bINVALID\b.*', 1300 1303 'CRASH' : r'(?i).*\bCRASHED\b.*', 1304 + 'TIMEOUT' : r'(?i).*\bTIMEOUT\b.*', 1301 1305 'IRQ' : r'.*\bgenirq: .*', 1302 1306 'TASKFAIL': r'.*Freezing of tasks *.*', 1303 1307 'ACPI' : r'.*\bACPI *(?P<b>[A-Za-z]*) *Error[: ].*', ··· 1356 1358 if self.dmesg[p]['order'] == order: 1357 1359 return p 1358 1360 return '' 1359 - def lastPhase(self): 1361 + def lastPhase(self, depth=1): 1360 1362 plist = self.sortedPhases() 1361 - if len(plist) < 1: 1363 + if len(plist) < depth: 1362 1364 return '' 1363 - return plist[-1] 1365 + return plist[-1*depth] 1364 1366 def turbostatInfo(self): 1365 1367 tp = TestProps() 1366 1368 out = {'syslpi':'N/A','pkgpc10':'N/A'} ··· 1380 1382 if len(self.dmesgtext) < 1 and sysvals.dmesgfile: 1381 1383 lf = sysvals.openlog(sysvals.dmesgfile, 'r') 1382 1384 i = 0 1385 + tp = TestProps() 1383 1386 list = [] 1384 1387 for line in lf: 1385 1388 i += 1 1389 + if tp.stampInfo(line, sysvals): 1390 + continue 1386 1391 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 1387 1392 if not m: 1388 1393 continue ··· 1401 1400 list.append((msg, err, dir, t, i, i)) 1402 1401 self.kerror = True 1403 1402 break 1404 - msglist = [] 1403 + tp.msglist = [] 1405 1404 for msg, type, dir, t, idx1, idx2 in list: 1406 - msglist.append(msg) 1405 + tp.msglist.append(msg) 1407 1406 self.errorinfo[dir].append((type, t, idx1, idx2)) 1408 1407 if self.kerror: 1409 1408 sysvals.dmesglog = True 1410 1409 if len(self.dmesgtext) < 1 and sysvals.dmesgfile: 1411 1410 lf.close() 1412 - return msglist 1411 + return tp 1413 1412 def setStart(self, time, msg=''): 1414 1413 self.start = time 1415 1414 if msg: ··· 1624 1623 if('src' in d): 1625 1624 for e in d['src']: 1626 1625 e.time = self.trimTimeVal(e.time, t0, dT, left) 1626 + e.end = self.trimTimeVal(e.end, t0, dT, left) 1627 + e.length = e.end - e.time 1627 1628 for dir in ['suspend', 'resume']: 1628 1629 list = [] 1629 1630 for e in self.errorinfo[dir]: ··· 1643 1640 if tL > 0: 1644 1641 left = True if tR > tZero else False 1645 1642 self.trimTime(tS, tL, left) 1646 - self.tLow.append('%.0f'%(tL*1000)) 1643 + if 'trying' in self.dmesg[lp] and self.dmesg[lp]['trying'] >= 0.001: 1644 + tTry = round(self.dmesg[lp]['trying'] * 1000) 1645 + text = '%.0f (-%.0f waking)' % (tL * 1000, tTry) 1646 + else: 1647 + text = '%.0f' % (tL * 1000) 1648 + self.tLow.append(text) 1647 1649 lp = phase 1648 1650 def getMemTime(self): 1649 1651 if not self.hwstart or not self.hwend: ··· 1784 1776 length = -1.0 1785 1777 if(start >= 0 and end >= 0): 1786 1778 length = end - start 1787 - if pid == -2: 1779 + if pid == -2 or name not in sysvals.tracefuncs.keys(): 1788 1780 i = 2 1789 1781 origname = name 1790 1782 while(name in list): ··· 1797 1789 if color: 1798 1790 list[name]['color'] = color 1799 1791 return name 1792 + def findDevice(self, phase, name): 1793 + list = self.dmesg[phase]['list'] 1794 + mydev = '' 1795 + for devname in sorted(list): 1796 + if name == devname or re.match('^%s\[(?P<num>[0-9]*)\]$' % name, devname): 1797 + mydev = devname 1798 + if mydev: 1799 + return list[mydev] 1800 + return False 1800 1801 def deviceChildren(self, devname, phase): 1801 1802 devlist = [] 1802 1803 list = self.dmesg[phase]['list'] ··· 2796 2779 testerrfmt = '^# enter_sleep_error (?P<e>.*)' 2797 2780 sysinfofmt = '^# sysinfo .*' 2798 2781 cmdlinefmt = '^# command \| (?P<cmd>.*)' 2782 + kparamsfmt = '^# kparams \| (?P<kp>.*)' 2799 2783 devpropfmt = '# Device Properties: .*' 2800 2784 pinfofmt = '# platform-(?P<val>[a-z,A-Z,0-9]*): (?P<info>.*)' 2801 2785 tracertypefmt = '# tracer: (?P<t>.*)' ··· 2808 2790 '[ +!#\*@$]*(?P<dur>[0-9\.]*) .*\| (?P<msg>.*)' 2809 2791 ftrace_line_fmt_nop = \ 2810 2792 ' *(?P<proc>.*)-(?P<pid>[0-9]*) *\[(?P<cpu>[0-9]*)\] *'+\ 2811 - '(?P<flags>.{4}) *(?P<time>[0-9\.]*): *'+\ 2793 + '(?P<flags>\S*) *(?P<time>[0-9\.]*): *'+\ 2812 2794 '(?P<msg>.*)' 2795 + machinesuspend = 'machine_suspend\[.*' 2813 2796 def __init__(self): 2814 2797 self.stamp = '' 2815 2798 self.sysinfo = '' ··· 2831 2812 self.ftrace_line_fmt = self.ftrace_line_fmt_nop 2832 2813 else: 2833 2814 doError('Invalid tracer format: [%s]' % tracer) 2834 - def stampInfo(self, line): 2815 + def stampInfo(self, line, sv): 2835 2816 if re.match(self.stampfmt, line): 2836 2817 self.stamp = line 2837 2818 return True 2838 2819 elif re.match(self.sysinfofmt, line): 2839 2820 self.sysinfo = line 2840 - return True 2841 - elif re.match(self.cmdlinefmt, line): 2842 - self.cmdline = line 2843 2821 return True 2844 2822 elif re.match(self.tstatfmt, line): 2845 2823 self.turbostat.append(line) ··· 2849 2833 return True 2850 2834 elif re.match(self.firmwarefmt, line): 2851 2835 self.fwdata.append(line) 2836 + return True 2837 + elif(re.match(self.devpropfmt, line)): 2838 + self.parseDevprops(line, sv) 2839 + return True 2840 + elif(re.match(self.pinfofmt, line)): 2841 + self.parsePlatformInfo(line, sv) 2842 + return True 2843 + m = re.match(self.cmdlinefmt, line) 2844 + if m: 2845 + self.cmdline = m.group('cmd') 2846 + return True 2847 + m = re.match(self.tracertypefmt, line) 2848 + if(m): 2849 + self.setTracerType(m.group('t')) 2852 2850 return True 2853 2851 return False 2854 2852 def parseStamp(self, data, sv): ··· 2888 2858 data.stamp[key] = val 2889 2859 sv.hostname = data.stamp['host'] 2890 2860 sv.suspendmode = data.stamp['mode'] 2861 + if sv.suspendmode == 'freeze': 2862 + self.machinesuspend = 'timekeeping_freeze\[.*' 2863 + else: 2864 + self.machinesuspend = 'machine_suspend\[.*' 2891 2865 if sv.suspendmode == 'command' and sv.ftracefile != '': 2892 2866 modes = ['on', 'freeze', 'standby', 'mem', 'disk'] 2893 - fp = sysvals.openlog(sv.ftracefile, 'r') 2867 + fp = sv.openlog(sv.ftracefile, 'r') 2894 2868 for line in fp: 2895 2869 m = re.match('.* machine_suspend\[(?P<mode>.*)\]', line) 2896 2870 if m and m.group('mode') in ['1', '2', '3', '4']: ··· 2902 2868 data.stamp['mode'] = sv.suspendmode 2903 2869 break 2904 2870 fp.close() 2905 - m = re.match(self.cmdlinefmt, self.cmdline) 2906 - if m: 2907 - sv.cmdline = m.group('cmd') 2871 + sv.cmdline = self.cmdline 2908 2872 if not sv.stamp: 2909 2873 sv.stamp = data.stamp 2910 2874 # firmware data ··· 3084 3052 for line in tf: 3085 3053 # remove any latent carriage returns 3086 3054 line = line.replace('\r\n', '') 3087 - if tp.stampInfo(line): 3088 - continue 3089 - # determine the trace data type (required for further parsing) 3090 - m = re.match(tp.tracertypefmt, line) 3091 - if(m): 3092 - tp.setTracerType(m.group('t')) 3093 - continue 3094 - # device properties line 3095 - if(re.match(tp.devpropfmt, line)): 3096 - tp.parseDevprops(line, sysvals) 3097 - continue 3098 - # platform info line 3099 - if(re.match(tp.pinfofmt, line)): 3100 - tp.parsePlatformInfo(line, sysvals) 3055 + if tp.stampInfo(line, sysvals): 3101 3056 continue 3102 3057 # parse only valid lines, if this is not one move on 3103 3058 m = re.match(tp.ftrace_line_fmt, line) ··· 3185 3166 if sysvals.usekprobes: 3186 3167 tracewatch += ['sync_filesystems', 'freeze_processes', 'syscore_suspend', 3187 3168 'syscore_resume', 'resume_console', 'thaw_processes', 'CPU_ON', 3188 - 'CPU_OFF', 'timekeeping_freeze', 'acpi_suspend'] 3169 + 'CPU_OFF', 'acpi_suspend'] 3189 3170 3190 3171 # extract the callgraph and traceevent data 3172 + s2idle_enter = hwsus = False 3191 3173 tp = TestProps() 3192 - testruns = [] 3193 - testdata = [] 3194 - testrun = 0 3195 - data, limbo = 0, True 3174 + testruns, testdata = [], [] 3175 + testrun, data, limbo = 0, 0, True 3196 3176 tf = sysvals.openlog(sysvals.ftracefile, 'r') 3197 3177 phase = 'suspend_prepare' 3198 3178 for line in tf: 3199 3179 # remove any latent carriage returns 3200 3180 line = line.replace('\r\n', '') 3201 - if tp.stampInfo(line): 3202 - continue 3203 - # tracer type line: determine the trace data type 3204 - m = re.match(tp.tracertypefmt, line) 3205 - if(m): 3206 - tp.setTracerType(m.group('t')) 3207 - continue 3208 - # device properties line 3209 - if(re.match(tp.devpropfmt, line)): 3210 - tp.parseDevprops(line, sysvals) 3211 - continue 3212 - # platform info line 3213 - if(re.match(tp.pinfofmt, line)): 3214 - tp.parsePlatformInfo(line, sysvals) 3181 + if tp.stampInfo(line, sysvals): 3215 3182 continue 3216 3183 # ignore all other commented lines 3217 3184 if line[0] == '#': ··· 3308 3303 phase = data.setPhase('suspend_noirq', t.time, isbegin) 3309 3304 continue 3310 3305 # suspend_machine/resume_machine 3311 - elif(re.match('machine_suspend\[.*', t.name)): 3306 + elif(re.match(tp.machinesuspend, t.name)): 3307 + lp = data.lastPhase() 3312 3308 if(isbegin): 3313 - lp = data.lastPhase() 3309 + hwsus = True 3314 3310 if lp.startswith('resume_machine'): 3315 - data.dmesg[lp]['end'] = t.time 3311 + # trim out s2idle loops, track time trying to freeze 3312 + llp = data.lastPhase(2) 3313 + if llp.startswith('suspend_machine'): 3314 + if 'trying' not in data.dmesg[llp]: 3315 + data.dmesg[llp]['trying'] = 0 3316 + data.dmesg[llp]['trying'] += \ 3317 + t.time - data.dmesg[lp]['start'] 3318 + data.currphase = '' 3319 + del data.dmesg[lp] 3320 + continue 3316 3321 phase = data.setPhase('suspend_machine', data.dmesg[lp]['end'], True) 3317 3322 data.setPhase(phase, t.time, False) 3318 3323 if data.tSuspended == 0: 3319 3324 data.tSuspended = t.time 3320 3325 else: 3326 + if lp.startswith('resume_machine'): 3327 + data.dmesg[lp]['end'] = t.time 3328 + continue 3321 3329 phase = data.setPhase('resume_machine', t.time, True) 3322 3330 if(sysvals.suspendmode in ['mem', 'disk']): 3323 3331 susp = phase.replace('resume', 'suspend') ··· 3361 3343 # global events (outside device calls) are graphed 3362 3344 if(name not in testrun.ttemp): 3363 3345 testrun.ttemp[name] = [] 3346 + # special handling for s2idle_enter 3347 + if name == 'machine_suspend': 3348 + if hwsus: 3349 + s2idle_enter = hwsus = False 3350 + elif s2idle_enter and not isbegin: 3351 + if(len(testrun.ttemp[name]) > 0): 3352 + testrun.ttemp[name][-1]['end'] = t.time 3353 + testrun.ttemp[name][-1]['loop'] += 1 3354 + elif not s2idle_enter and isbegin: 3355 + s2idle_enter = True 3356 + testrun.ttemp[name].append({'begin': t.time, 3357 + 'end': t.time, 'pid': pid, 'loop': 0}) 3358 + continue 3364 3359 if(isbegin): 3365 3360 # create a new list entry 3366 3361 testrun.ttemp[name].append(\ ··· 3405 3374 if(not m): 3406 3375 continue 3407 3376 n = m.group('d') 3408 - list = data.dmesg[phase]['list'] 3409 - if(n in list): 3410 - dev = list[n] 3377 + dev = data.findDevice(phase, n) 3378 + if dev: 3411 3379 dev['length'] = t.time - dev['start'] 3412 3380 dev['end'] = t.time 3413 3381 # kprobe event processing ··· 3509 3479 # add actual trace funcs 3510 3480 for name in sorted(test.ttemp): 3511 3481 for event in test.ttemp[name]: 3512 - data.newActionGlobal(name, event['begin'], event['end'], event['pid']) 3482 + if event['end'] - event['begin'] <= 0: 3483 + continue 3484 + title = name 3485 + if name == 'machine_suspend' and 'loop' in event: 3486 + title = 's2idle_enter_%dx' % event['loop'] 3487 + data.newActionGlobal(title, event['begin'], event['end'], event['pid']) 3513 3488 # add the kprobe based virtual tracefuncs as actual devices 3514 3489 for key in sorted(tp.ktemp): 3515 3490 name, pid = key ··· 3583 3548 for p in sorted(phasedef, key=lambda k:phasedef[k]['order']): 3584 3549 if p not in data.dmesg: 3585 3550 if not terr: 3586 - pprint('TEST%s FAILED: %s failed in %s phase' % (tn, sysvals.suspendmode, lp)) 3587 - terr = '%s%s failed in %s phase' % (sysvals.suspendmode, tn, lp) 3551 + ph = p if 'machine' in p else lp 3552 + terr = '%s%s failed in %s phase' % (sysvals.suspendmode, tn, ph) 3553 + pprint('TEST%s FAILED: %s' % (tn, terr)) 3588 3554 error.append(terr) 3589 3555 if data.tSuspended == 0: 3590 3556 data.tSuspended = data.dmesg[lp]['end'] ··· 3647 3611 idx = line.find('[') 3648 3612 if idx > 1: 3649 3613 line = line[idx:] 3650 - if tp.stampInfo(line): 3614 + if tp.stampInfo(line, sysvals): 3651 3615 continue 3652 3616 m = re.match('[ \t]*(\[ *)(?P<ktime>[0-9\.]*)(\]) (?P<msg>.*)', line) 3653 3617 if(not m): ··· 3995 3959 if sv.cgphase and p != sv.cgphase: 3996 3960 continue 3997 3961 list = data.dmesg[p]['list'] 3998 - for devname in data.sortedDevices(p): 3999 - if len(sv.cgfilter) > 0 and devname not in sv.cgfilter: 3962 + for d in data.sortedDevices(p): 3963 + if len(sv.cgfilter) > 0 and d not in sv.cgfilter: 4000 3964 continue 4001 - dev = list[devname] 3965 + dev = list[d] 4002 3966 color = 'white' 4003 3967 if 'color' in data.dmesg[p]: 4004 3968 color = data.dmesg[p]['color'] 4005 3969 if 'color' in dev: 4006 3970 color = dev['color'] 4007 - name = devname 4008 - if(devname in sv.devprops): 4009 - name = sv.devprops[devname].altName(devname) 3971 + name = d if '[' not in d else d.split('[')[0] 3972 + if(d in sv.devprops): 3973 + name = sv.devprops[d].altName(d) 3974 + if 'drv' in dev and dev['drv']: 3975 + name += ' {%s}' % dev['drv'] 4010 3976 if sv.suspendmode in suspendmodename: 4011 3977 name += ' '+p 4012 3978 if('ftrace' in dev): ··· 4555 4517 # draw the devices for this phase 4556 4518 phaselist = data.dmesg[b]['list'] 4557 4519 for d in sorted(data.tdevlist[b]): 4558 - name = d 4559 - drv = '' 4560 - dev = phaselist[d] 4561 - xtraclass = '' 4562 - xtrainfo = '' 4563 - xtrastyle = '' 4520 + dname = d if '[' not in d else d.split('[')[0] 4521 + name, dev = dname, phaselist[d] 4522 + drv = xtraclass = xtrainfo = xtrastyle = '' 4564 4523 if 'htmlclass' in dev: 4565 4524 xtraclass = dev['htmlclass'] 4566 4525 if 'color' in dev: ··· 4588 4553 title += b 4589 4554 devtl.html += devtl.html_device.format(dev['id'], \ 4590 4555 title, left, top, '%.3f'%rowheight, width, \ 4591 - d+drv, xtraclass, xtrastyle) 4556 + dname+drv, xtraclass, xtrastyle) 4592 4557 if('cpuexec' in dev): 4593 4558 for t in sorted(dev['cpuexec']): 4594 4559 start, end = t ··· 4606 4571 continue 4607 4572 # draw any trace events for this device 4608 4573 for e in dev['src']: 4574 + if e.length == 0: 4575 + continue 4609 4576 height = '%.3f' % devtl.rowH 4610 4577 top = '%.3f' % (rowtop + devtl.scaleH + (e.row*devtl.rowH)) 4611 4578 left = '%f' % (((e.time-m0)*100)/mTotal) ··· 5913 5876 5914 5877 def processData(live=False, quiet=False): 5915 5878 if not quiet: 5916 - pprint('PROCESSING DATA') 5879 + pprint('PROCESSING: %s' % sysvals.htmlfile) 5917 5880 sysvals.vprint('usetraceevents=%s, usetracemarkers=%s, usekprobes=%s' % \ 5918 5881 (sysvals.usetraceevents, sysvals.usetracemarkers, sysvals.usekprobes)) 5919 5882 error = '' ··· 5965 5928 sysvals.vprint('Creating the html timeline (%s)...' % sysvals.htmlfile) 5966 5929 createHTML(testruns, error) 5967 5930 if not quiet: 5968 - pprint('DONE') 5931 + pprint('DONE: %s' % sysvals.htmlfile) 5969 5932 data = testruns[0] 5970 5933 stamp = data.stamp 5971 5934 stamp['suspend'], stamp['resume'] = data.getTimeValues() ··· 6021 5984 return 0 6022 5985 6023 5986 def find_in_html(html, start, end, firstonly=True): 6024 - n, cnt, out = 0, len(html), [] 6025 - while n < cnt: 6026 - e = cnt if (n + 10000 > cnt or n == 0) else n + 10000 6027 - m = re.search(start, html[n:e]) 5987 + cnt, out, list = len(html), [], [] 5988 + if firstonly: 5989 + m = re.search(start, html) 5990 + if m: 5991 + list.append(m) 5992 + else: 5993 + list = re.finditer(start, html) 5994 + for match in list: 5995 + s = match.end() 5996 + e = cnt if (len(out) < 1 or s + 10000 > cnt) else s + 10000 5997 + m = re.search(end, html[s:e]) 6028 5998 if not m: 6029 5999 break 6030 - i = m.end() 6031 - m = re.search(end, html[n+i:e]) 6032 - if not m: 6033 - break 6034 - j = m.start() 6035 - str = html[n+i:n+i+j] 6000 + e = s + m.start() 6001 + str = html[s:e] 6036 6002 if end == 'ms': 6037 6003 num = re.search(r'[-+]?\d*\.\d+|\d+', str) 6038 6004 str = num.group() if num else 'NaN' 6039 6005 if firstonly: 6040 6006 return str 6041 6007 out.append(str) 6042 - n += i+j 6043 6008 if firstonly: 6044 6009 return '' 6045 6010 return out ··· 6073 6034 else: 6074 6035 result = 'pass' 6075 6036 # extract error info 6076 - ilist = [] 6037 + tp, ilist = False, [] 6077 6038 extra = dict() 6078 6039 log = find_in_html(html, '<div id="dmesglog" style="display:none;">', 6079 6040 '</div>').strip() ··· 6081 6042 d = Data(0) 6082 6043 d.end = 999999999 6083 6044 d.dmesgtext = log.split('\n') 6084 - msglist = d.extractErrorInfo() 6085 - for msg in msglist: 6045 + tp = d.extractErrorInfo() 6046 + for msg in tp.msglist: 6086 6047 sysvals.errorSummary(issues, msg) 6087 6048 if stmp[2] == 'freeze': 6088 6049 extra = d.turbostatInfo() ··· 6098 6059 if wifi: 6099 6060 extra['wifi'] = wifi 6100 6061 low = find_in_html(html, 'freeze time: <b>', ' ms</b>') 6101 - if low and '|' in low: 6102 - issue = 'FREEZEx%d' % len(low.split('|')) 6062 + if low and 'waking' in low: 6063 + issue = 'FREEZEWAKE' 6103 6064 match = [i for i in issues if i['match'] == issue] 6104 6065 if len(match) > 0: 6105 6066 match[0]['count'] += 1 ··· 6165 6126 data[key] = extra[key] 6166 6127 if fulldetail: 6167 6128 data['funclist'] = find_in_html(html, '<div title="', '" class="traceevent"', False) 6129 + if tp: 6130 + for arg in ['-multi ', '-info ']: 6131 + if arg in tp.cmdline: 6132 + data['target'] = tp.cmdline[tp.cmdline.find(arg):].split()[1] 6133 + break 6168 6134 return data 6169 6135 6170 6136 def genHtml(subdir, force=False): ··· 6199 6155 pprint('Generating a summary of folder:\n %s' % inpath) 6200 6156 if genhtml: 6201 6157 genHtml(subdir) 6202 - issues = [] 6203 - testruns = [] 6158 + target, issues, testruns = '', [], [] 6204 6159 desc = {'host':[],'mode':[],'kernel':[]} 6205 6160 for dirname, dirnames, filenames in os.walk(subdir): 6206 6161 for filename in filenames: ··· 6208 6165 data = data_from_html(os.path.join(dirname, filename), outpath, issues) 6209 6166 if(not data): 6210 6167 continue 6168 + if 'target' in data: 6169 + target = data['target'] 6211 6170 testruns.append(data) 6212 6171 for key in desc: 6213 6172 if data[key] not in desc[key]: ··· 6217 6172 pprint('Summary files:') 6218 6173 if len(desc['host']) == len(desc['mode']) == len(desc['kernel']) == 1: 6219 6174 title = '%s %s %s' % (desc['host'][0], desc['kernel'][0], desc['mode'][0]) 6175 + if target: 6176 + title += ' %s' % target 6220 6177 else: 6221 6178 title = inpath 6222 6179 createHTMLSummarySimple(testruns, os.path.join(outpath, 'summary.html'), title)