├── COPYING ├── Makefile ├── README ├── README.bugzilla ├── README.dataserver ├── README.stressreport ├── README.stresstest ├── SECURITY.md ├── analyze_boot.py ├── analyze_suspend.py ├── autotest ├── install.sh ├── platform_AnalyzeBoot │ ├── analyze_boot.py │ ├── control │ └── platform_AnalyzeBoot.py ├── platform_AnalyzeFreeze │ ├── analyze_suspend.py │ ├── control │ └── platform_AnalyzeFreeze.py └── platform_AnalyzeSuspend │ ├── analyze_suspend.py │ ├── control │ └── platform_AnalyzeSuspend.py ├── bootgraph.8 ├── bootgraph.py ├── config ├── bisect-example.cfg ├── cgskip.txt ├── custom-timeline-functions.cfg ├── debug-serio-suspend.cfg ├── example.cfg ├── freeze-callgraph.cfg ├── freeze-dev.cfg ├── freeze.cfg ├── netfix-otcpl.cfg ├── netfix-tebrandt.cfg ├── netfix.cfg ├── standby-callgraph.cfg ├── standby-dev.cfg ├── standby.cfg ├── stresstest-intel-local.cfg ├── stresstest-intel.cfg ├── suspend-callgraph.cfg ├── suspend-dev.cfg ├── suspend-x2-proc.cfg └── suspend.cfg ├── debian ├── changelog ├── compat ├── control ├── copyright ├── docs ├── pm-graph.links ├── pm-graph.manpages ├── rules └── source │ ├── format │ └── options ├── dev ├── 0001-scsi-sr-use-block-layer-runtime-PM.patch ├── 0002-SCSI-pm-skip-resume-for-scsi-device-tree.patch ├── 0003-ata-skip-resume-for-ata-port.patch ├── aaron-scsi.patch ├── ata_deferred_resume.patch ├── ata_full_dev.patch ├── ata_resume_async.patch ├── ata_resume_async_dev.patch ├── hard-disk-resume │ ├── ata_port_resume_async.patch │ ├── mail0.txt │ ├── mail1.txt │ ├── mail2.txt │ └── sd_resume_async.patch ├── hard_disk_deferred_resume.patch ├── intel_pci_quirk_remove_d3_delay.patch ├── pm-deferred_resume.patch ├── pm_resume_async_non_blocking.patch └── usb-resume │ ├── skynet-usb-layout.txt │ ├── usb-trace.patch │ ├── usb-xhci-suspend-optimize.patch │ └── usb_address0.patch ├── devtest ├── devtest.sh ├── suspend-061314-131149 │ ├── run.sh │ ├── skynet_standby.html │ ├── skynet_standby_dmesg.txt │ └── skynet_standby_ftrace.txt ├── suspend-061314-131447 │ ├── run.sh │ ├── skynet_freeze.html │ ├── skynet_freeze_dmesg.txt │ └── skynet_freeze_ftrace.txt ├── suspend-061314-132459 │ ├── run.sh │ ├── skynet_mem.html │ ├── skynet_mem_dmesg.txt │ └── skynet_mem_ftrace.txt └── suspend-061314-132803 │ ├── run.sh │ ├── skynet_disk.html │ ├── skynet_disk_dmesg.txt │ └── skynet_disk_ftrace.txt ├── kernel ├── 3.10 │ ├── 1-enable_ftrace_in_suspendresume.patch │ ├── 2-enable_trace_events_suspend_resume.patch │ └── 3-enable_trace_events_device_pm_callback.patch ├── 3.14 │ └── suspend_resume_and_pm_callback_full.patch ├── extra-timeline-detail │ ├── 1-trace_suspend_resume_from_module.patch │ ├── 2-ata_port_resume_async.patch │ └── 3-i915-first-page-flip-after-resume.patch ├── pre-3.11-rc2 │ └── enable_ftrace_in_suspendresume.patch ├── pre-3.15 │ ├── enable_trace_events_device_pm_callback.patch │ └── enable_trace_events_suspend_resume.patch └── usb │ ├── 0000-cover-letter.patch │ ├── 0001-USB-add-switch-to-turn-off-padding-of-resume-time-de.patch │ └── 0002-USB-usb-timing-value-debug.patch ├── lib ├── __init__.py ├── argconfig.py ├── bugzilla.py ├── common.py ├── googleapi.py ├── kernel.py ├── parallel.py └── remotemachine.py ├── sleepgraph.8 ├── sleepgraph.py ├── stressreport.py ├── stresstest.py └── tools ├── android.sh ├── buggymon.py ├── config ├── dataserver.py ├── ftrace.py ├── googledrive.py ├── hwcheck.py ├── intel-multitest-handler.sh ├── intel-stresstest-friday.sh ├── intel-stresstest-local.sh ├── intel-stresstest-monday.sh ├── intel-stresstest-sunday.sh ├── intel-stresstest.sh ├── intel-updatecache.sh ├── kernelbuild.sh ├── lib ├── logfix.py ├── makedeb.sh ├── netfix.py ├── perftest.py ├── procmon.py ├── sanitycheck.sh ├── stresskernelbuild └── testall.sh /Makefile: -------------------------------------------------------------------------------- 1 | # SPDX-License-Identifier: GPL-2.0 2 | # 3 | # Copyright (c) 2013, Intel Corporation. 4 | # 5 | # This program is free software; you can redistribute it and/or modify it 6 | # under the terms and conditions of the GNU General Public License, 7 | # version 2, as published by the Free Software Foundation. 8 | # 9 | # This program is distributed in the hope it will be useful, but WITHOUT 10 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 | # more details. 13 | # 14 | # Authors: 15 | # Todd Brandt 16 | 17 | # Prefix to the directories we're installing to 18 | DESTDIR ?= 19 | 20 | # Directory definitions. These are default and most probably 21 | # do not need to be changed. Please note that DESTDIR is 22 | # added in front of any of them 23 | 24 | BINDIR ?= /usr/bin 25 | MANDIR ?= /usr/share/man 26 | SHRDIR ?= /usr/share/pm-graph 27 | LIBDIR ?= /usr/lib 28 | 29 | # Toolchain: what tools do we use, and what options do they need: 30 | INSTALL = /usr/bin/install 31 | INSTALL_DATA = ${INSTALL} -m 644 32 | 33 | all: 34 | @echo "Nothing to build" 35 | 36 | install : uninstall 37 | $(INSTALL) -d $(DESTDIR)$(LIBDIR)/pm-graph 38 | $(INSTALL) sleepgraph.py $(DESTDIR)$(LIBDIR)/pm-graph 39 | $(INSTALL) bootgraph.py $(DESTDIR)$(LIBDIR)/pm-graph 40 | $(INSTALL) tools/netfix.py $(DESTDIR)$(LIBDIR)/pm-graph 41 | $(INSTALL) lib/argconfig.py $(DESTDIR)$(LIBDIR)/pm-graph 42 | $(INSTALL) -d $(DESTDIR)$(LIBDIR)/pm-graph/config 43 | $(INSTALL_DATA) config/cgskip.txt $(DESTDIR)$(LIBDIR)/pm-graph/config 44 | $(INSTALL_DATA) config/freeze-callgraph.cfg $(DESTDIR)$(LIBDIR)/pm-graph/config 45 | $(INSTALL_DATA) config/freeze.cfg $(DESTDIR)$(LIBDIR)/pm-graph/config 46 | $(INSTALL_DATA) config/freeze-dev.cfg $(DESTDIR)$(LIBDIR)/pm-graph/config 47 | $(INSTALL_DATA) config/standby-callgraph.cfg $(DESTDIR)$(LIBDIR)/pm-graph/config 48 | $(INSTALL_DATA) config/standby.cfg $(DESTDIR)$(LIBDIR)/pm-graph/config 49 | $(INSTALL_DATA) config/standby-dev.cfg $(DESTDIR)$(LIBDIR)/pm-graph/config 50 | $(INSTALL_DATA) config/suspend-callgraph.cfg $(DESTDIR)$(LIBDIR)/pm-graph/config 51 | $(INSTALL_DATA) config/suspend.cfg $(DESTDIR)$(LIBDIR)/pm-graph/config 52 | $(INSTALL_DATA) config/suspend-dev.cfg $(DESTDIR)$(LIBDIR)/pm-graph/config 53 | $(INSTALL_DATA) config/suspend-x2-proc.cfg $(DESTDIR)$(LIBDIR)/pm-graph/config 54 | $(INSTALL) -d $(DESTDIR)$(SHRDIR) 55 | 56 | $(INSTALL) -d $(DESTDIR)$(BINDIR) 57 | ln -s ../lib/pm-graph/bootgraph.py $(DESTDIR)$(BINDIR)/bootgraph 58 | ln -s ../lib/pm-graph/sleepgraph.py $(DESTDIR)$(BINDIR)/sleepgraph 59 | ln -s ../lib/pm-graph/netfix.py $(DESTDIR)$(BINDIR)/netfix 60 | $(DESTDIR)$(BINDIR)/netfix defconfig > $(DESTDIR)$(SHRDIR)/netfix.cfg 61 | 62 | $(INSTALL) -d $(DESTDIR)$(MANDIR)/man8 63 | $(INSTALL) bootgraph.8 $(DESTDIR)$(MANDIR)/man8 64 | $(INSTALL) sleepgraph.8 $(DESTDIR)$(MANDIR)/man8 65 | 66 | uninstall : 67 | rm -f $(DESTDIR)$(MANDIR)/man8/bootgraph.8 68 | rm -f $(DESTDIR)$(MANDIR)/man8/sleepgraph.8 69 | 70 | rm -f $(DESTDIR)$(BINDIR)/bootgraph 71 | rm -f $(DESTDIR)$(BINDIR)/sleepgraph 72 | rm -f $(DESTDIR)$(BINDIR)/netfix 73 | 74 | rm -f $(DESTDIR)$(LIBDIR)/pm-graph/config/* 75 | if [ -d $(DESTDIR)$(LIBDIR)/pm-graph/config ] ; then \ 76 | rmdir $(DESTDIR)$(LIBDIR)/pm-graph/config; \ 77 | fi; 78 | rm -f $(DESTDIR)$(LIBDIR)/pm-graph/__pycache__/* 79 | if [ -d $(DESTDIR)$(LIBDIR)/pm-graph/__pycache__ ] ; then \ 80 | rmdir $(DESTDIR)$(LIBDIR)/pm-graph/__pycache__; \ 81 | fi; 82 | rm -f $(DESTDIR)$(LIBDIR)/pm-graph/* 83 | if [ -d $(DESTDIR)$(LIBDIR)/pm-graph ] ; then \ 84 | rmdir $(DESTDIR)$(LIBDIR)/pm-graph; \ 85 | fi; 86 | 87 | hwcheck-install : 88 | $(INSTALL) -d $(DESTDIR)$(LIBDIR)/pm-graph 89 | rm -f $(DESTDIR)$(BINDIR)/hwcheck 90 | rm -f $(DESTDIR)$(LIBDIR)/pm-graph/hwcheck.py 91 | $(INSTALL) tools/hwcheck.py $(DESTDIR)$(LIBDIR)/pm-graph 92 | $(INSTALL) -d $(DESTDIR)$(BINDIR) 93 | ln -s ../lib/pm-graph/hwcheck.py $(DESTDIR)$(BINDIR)/hwcheck 94 | $(DESTDIR)$(BINDIR)/hwcheck cronon 95 | 96 | hwcheck-uninstall : 97 | if [ -e $(DESTDIR)$(BINDIR)/hwcheck ] ; then \ 98 | $(DESTDIR)$(BINDIR)/hwcheck cronoff; \ 99 | fi; 100 | rm -f $(DESTDIR)$(BINDIR)/hwcheck 101 | rm -f $(DESTDIR)$(LIBDIR)/pm-graph/hwcheck.py 102 | 103 | help: 104 | @echo 'Building targets:' 105 | @echo ' all - Nothing to build' 106 | @echo ' install - Install the program and create necessary directories' 107 | @echo ' uninstall - Remove installed files and directories' 108 | @echo ' hwcheck-install - Install hwcheck utiltity and add a cronjob' 109 | @echo ' hwcheck-uninstall - Remove hwcheck utilityand disable cronjob' 110 | 111 | .PHONY: all install uninstall hwcheck-install hwcheck-uninstall help 112 | -------------------------------------------------------------------------------- /README.dataserver: -------------------------------------------------------------------------------- 1 | The dataserver tool is used to handle automatically uploading data to a server 2 | for sorting and processing by googlesheet. The information below is specific 3 | to the Intel implementation of the data server. 4 | 5 | [HOW IT WORKS] 6 | 7 | The otcpl-stress.ostc.intel.com server has a "sleepgraph" user account which 8 | has been configured to be able to run googlesheet with pre-installed 9 | credentials. It has a shell script called "multitest" which handles the entire 10 | process of analyzing and uploading data to google drive from a tarball. All you 11 | need to do is transport the data and call multitest. This is what dataserver 12 | does: generate a tar.gz file from a data folder, scp it to the server, and 13 | call multitest. 14 | 15 | usage: dataserver.py [-h] [-sshkeysetup] [-monitor] folder 16 | 17 | positional arguments: 18 | folder multitest folder, or "shell" to open an ssh shell 19 | 20 | optional arguments: 21 | -h, --help show this help message and exit 22 | -sshkeysetup setup password-less access by copying ssh keys 23 | -monitor Monitor server processing and wait for completion 24 | 25 | [SETUP] 26 | 27 | The best way to run the tool is with password-less access via ssh keys. If you 28 | don't mind typing the password three times for each upload you can skip this 29 | section. The following command is what you should run to configure ssh: 30 | 31 | $> ./tools/dataserver.py -sshkeysetup shell 32 | 33 | The "shell" command opens an ssh shell to the data serer via the sleepgraph 34 | account. The "-sshkeysetup" argument runs ssh-copy-id to add your id_rsa.pub 35 | to the server's authorized keys file. You must have an id_rsa/id_rsa.pub key 36 | pair in your ~/.ssh folder with a blank passphrase. You will have to login 37 | once in order to copy the keys, and the tool will tell you if it worked. After 38 | this you will not need to login again. 39 | 40 | [UPLOADING DATA] 41 | 42 | The data you want to upload should be contained in a single folder with one or 43 | more multitest outputs from the sleepgraph tool. multitest outputs look like 44 | this: 45 | 46 | # multitest for a specific kernel/host/mode 47 | suspend-x{count}-{date}-{time} 48 | # same kernel, host, mode for each individual test 49 | suspend-{date}-{time} 50 | host_mode.html 51 | host_mode_dmesg.txt(.gz) 52 | host_mode_ftrace.txt(.gz) 53 | suspend-{date}-{time} 54 | ... 55 | ... 56 | 57 | You can include as many multitests as you want, in any folder structure you 58 | want, and for any kernels/hosts/modes you want. The data server will sift 59 | through them and sort them by kernel, host, and mode, and add them to the 60 | web-hosted filesystem. The dataserver script will "tar cvzf" your folder 61 | into a /tmp/folder.tar.gz file, then scp it to dataserver:/tmp, and finally 62 | call "multitest /tmp/folder.tar.gz" on the server. 63 | 64 | The tool should immediately exit after this, leaving the multitest command 65 | running in the background on dataserver. However if you want to wait for the 66 | data to complete its processing you can use the -monitor argument to poll. 67 | 68 | ASYNCHRONOUS EXECUTION 69 | 70 | This command uploads the data and kicks of multitest asynchronously. It will 71 | tell you the log file to check and then disconnect. 72 | 73 | $> ./tools/dataserver.py folder 74 | Taring up folder for transport... 75 | Sending tarball to server... 76 | folder.tar.gz 100% 23MB 11.2MB/s 00:02 77 | Notifying server of new data... 78 | Logging at multitest-log-file.log 79 | Upload Complete 80 | 81 | You can then wait or monitor the log like this: 82 | 83 | $> ssh sleepgraph@otcpl-stress.ostc.intel.com "tail -f multitest-log-file.log" 84 | 85 | SYNCHRONOUS EXECUTION 86 | 87 | This command uploads the data and kicks of multitest synchronously. It will 88 | print the output of the processing and exit when it's complete. Ctrl-C will 89 | kill the process on the server. 90 | 91 | $> ./tools/dataserver.py -monitor folder 92 | Taring up folder for transport... 93 | Sending tarball to server... 94 | folder.tar.gz 100% 23MB 11.2MB/s 00:02 95 | Processing the data on the server... 96 | ... 97 | Upload Complete 98 | 99 | OUTPUT RESULTS 100 | 101 | The multitest folders you supplied will be organized by kernel, host, and mode 102 | and be available on the web server under the following folder structure: 103 | 104 | http://otcpl-stress.ostc.intel.com/pm-graph-test/ 105 | {kernel} 106 | {host} 107 | suspend-{mode}-{date}-{time}-multi 108 | summary-devices.html 109 | summary-issues.html 110 | summary.html 111 | suspend-{date}-{time} 112 | ... 113 | ... 114 | ... 115 | ... 116 | 117 | The googlesheet spreadsheets will be available on google drive with pointers 118 | to the timelines on the server. 119 | 120 | https://drive.google.com/open?id=1507yI_H_LBPAGRX9AMn86dfFAySC3u-t 121 | {kernel} 122 | {host} 123 | sleepgraph-{date}-{time}-{mode}-x{count} 124 | sleepgraph-{date}-{time}-{mode}-x{count} 125 | ... 126 | {host} 127 | sleepgraph-{date}-{time}-{mode}-x{count} 128 | sleepgraph-{date}-{time}-{mode}-x{count} 129 | ... 130 | ... 131 | ... 132 | 133 | NOTE: the tool only allows one googlesheet process at a time so you must wait 134 | til the system is free to use it. 135 | -------------------------------------------------------------------------------- /README.stressreport: -------------------------------------------------------------------------------- 1 | ------------------------------------------------------------------ 2 | | OVERVIEW | 3 | ------------------------------------------------------------------ 4 | 5 | The stressreport tool is used to Summarize sleepgraph multitests 6 | in the form of googlesheets. This tool searches a dir for sleepgraph 7 | multitest folders and generates google sheet summaries for them. 8 | It can also generate a high level summary of all the multtests found 9 | for quick viewing and analysis. 10 | 11 | ------------------------------------------------------------------ 12 | | SETUP | 13 | ------------------------------------------------------------------ 14 | 15 | This tool requires several python packages and libraries beyond what 16 | the base ubuntu build provides. The requirements are different for 17 | python2 vs python3, however both should be able to run the tool. 18 | 19 | [python2 debian package requirements] 20 | sudo apt-get install python-configparser python-requests python-psutil python-httplib2 python-pip 21 | sudo pip2 install --upgrade google-api-python-client oauth2client 22 | 23 | [python3 debian package requirements] 24 | sudo apt-get install python3-psutil python3-pip 25 | sudo pip3 install --upgrade google-api-python-client oauth2client 26 | 27 | Once the libraries are fully installed, the "stresstester.py -h" help 28 | text should be viewable. 29 | 30 | In order to get the tool to interface with google drive, you must 31 | create a "credentials.json" file with your encrypted login info. 32 | You do this by running "stresstester.py -setup". It will open a broswer 33 | window and ask you to login from the GUI. 34 | 35 | To run -setup without local browser use this command: 36 | ./stressreport.py -setup --noauth_local_webserver 37 | 38 | It will generate a link that you must click elsewhere in a browser 39 | to login and enable the tool. Once you've finished with the UI, it 40 | will give you a KEY which you must paste into the stresstester stdin. 41 | It will verify the key and download a credentials.json file for you. 42 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # Security Policy 2 | Intel is committed to rapidly addressing security vulnerabilities affecting our customers and providing clear guidance on the solution, impact, severity and mitigation. 3 | 4 | ## Reporting a Vulnerability 5 | Please report any security vulnerabilities in this project utilizing the guidelines [here](https://www.intel.com/content/www/us/en/security-center/vulnerability-handling-guidelines.html). 6 | -------------------------------------------------------------------------------- /analyze_boot.py: -------------------------------------------------------------------------------- 1 | bootgraph.py -------------------------------------------------------------------------------- /analyze_suspend.py: -------------------------------------------------------------------------------- 1 | sleepgraph.py -------------------------------------------------------------------------------- /autotest/install.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | TESTPATH='/usr/share/chromiumos/src/third_party/autotest/files/client/site_tests' 4 | 5 | for file in `ls -1` ; 6 | do 7 | if [ ! -d $file ]; then continue; fi 8 | cp -rfL $file $TESTPATH 9 | done 10 | -------------------------------------------------------------------------------- /autotest/platform_AnalyzeBoot/analyze_boot.py: -------------------------------------------------------------------------------- 1 | ../../analyze_boot.py -------------------------------------------------------------------------------- /autotest/platform_AnalyzeBoot/control: -------------------------------------------------------------------------------- 1 | # Copyright 2015 The Chromium OS Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | AUTHOR = 'Todd Brandt ' 6 | PURPOSE = 'Kernel Boot timeline' 7 | CRITERIA = 'This test is a performance test. Expected success, no crashes.' 8 | DOC = """ 9 | This test creates a timeline of kernel boot using the dmesg output 10 | """ 11 | NAME = 'platform_AnalyzeBoot' 12 | TIME = 'SHORT' 13 | TEST_CLASS = 'platform' 14 | TEST_CATEGORY = 'Performance' 15 | TEST_TYPE = 'client' 16 | REBOOT_REQUIRED = 'before' 17 | 18 | # Create a timeline from the dmesg log 19 | job.run_test('platform_AnalyzeBoot') 20 | -------------------------------------------------------------------------------- /autotest/platform_AnalyzeBoot/platform_AnalyzeBoot.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 The Chromium OS Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | import os, commands, logging 6 | from autotest_lib.client.bin import utils, test 7 | from autotest_lib.client.common_lib import error 8 | from autotest_lib.client.cros import rtc, sys_power 9 | import analyze_boot as ab 10 | 11 | class platform_AnalyzeBoot(test.test): 12 | version = 1 13 | myparams = [ 14 | 'initcall_debug', 15 | 'log_buf_len=' 16 | ] 17 | dmesgfile = '' 18 | def initialize(self): 19 | # pass in the dmesg instead of getting it from popen(dmesg) 20 | self.dmesgfile = os.path.join(self.resultsdir, 'dmesg.txt') 21 | if not self.checkKernelParameters(self.myparams): 22 | self.testFail('Missing Kernel Parameters: %s' % self.myparams) 23 | # setup the test with the right command line params 24 | ab.sysvals.hostname = 'chromium' 25 | ab.sysvals.htmlfile = os.path.join(self.resultsdir, 'bootgraph.html') 26 | ab.sysvals.dmesgfile = self.dmesgfile 27 | logging.info('dmesgfile : %s' % ab.sysvals.dmesgfile) 28 | logging.info('htmlfile : %s' % ab.sysvals.htmlfile) 29 | 30 | def checkKernelParameters(self, myparams): 31 | try: 32 | fp = open('/proc/cmdline') 33 | cmdline = fp.read().strip() 34 | fp.close() 35 | except: 36 | return False 37 | for param in myparams: 38 | if param not in cmdline: 39 | return False 40 | return True 41 | 42 | def run_once(self): 43 | logging.info('Retrieve dmesg log from sysinfo') 44 | # copy the dmesg.gz log from the sysinfo to results 45 | dmesg = os.path.join(self.resultsdir, '../../sysinfo/dmesg.gz') 46 | os.system('cp %s %s' % (dmesg, self.resultsdir)) 47 | # gunzup the file and create the input dmesg file 48 | dmesg = os.path.join(self.resultsdir, 'dmesg') 49 | os.system('gunzip %s.gz; mv %s %s' % (dmesg, dmesg, self.dmesgfile)) 50 | # run the test, load the kernel log 51 | logging.info('Load the dmesg log') 52 | data = ab.loadRawKernelLog() 53 | # verify the file has enough data to actually get a timeline 54 | logging.info('Extract basic test info from the log') 55 | ab.testResults(data, False) 56 | if not data.valid: 57 | self.testFail('Data is invalid: the dmesg log was incomplete') 58 | # parse the log and create a timeline object 59 | logging.info('Parse the dmesg log and create a timeline') 60 | ab.parseKernelBootLog(data) 61 | # convert the timeline object into an html timeline 62 | logging.info('Generate the html timeline output') 63 | ab.createBootGraph(data, False) 64 | 65 | def testFail(self, errtext): 66 | logging.error(errtext) 67 | raise error.TestFail(errtext) 68 | -------------------------------------------------------------------------------- /autotest/platform_AnalyzeFreeze/analyze_suspend.py: -------------------------------------------------------------------------------- 1 | ../../analyze_suspend.py -------------------------------------------------------------------------------- /autotest/platform_AnalyzeFreeze/control: -------------------------------------------------------------------------------- 1 | # Copyright 2015 The Chromium OS Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | AUTHOR = 'Todd Brandt ' 6 | PURPOSE = 'Kernel Freeze/Thaw timeline' 7 | CRITERIA = 'This test is a performance test. Expected success, no crashes.' 8 | DOC = """ 9 | This test puts the client host through a Freeze/Thaw cycle. 10 | """ 11 | NAME = 'platform_AnalyzeFreeze' 12 | TIME = 'SHORT' 13 | TEST_CLASS = 'platform' 14 | TEST_CATEGORY = 'Performance' 15 | TEST_TYPE = 'client' 16 | 17 | # Run a Freeze/Thaw cycle and collect a timeline 18 | job.run_test('platform_AnalyzeFreeze', devmode=False, waketime=10) 19 | -------------------------------------------------------------------------------- /autotest/platform_AnalyzeFreeze/platform_AnalyzeFreeze.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 The Chromium OS Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | import os, commands, logging 6 | from autotest_lib.client.bin import utils, test 7 | from autotest_lib.client.common_lib import error 8 | from autotest_lib.client.cros import rtc, sys_power 9 | import analyze_suspend as asusp 10 | 11 | class platform_AnalyzeFreeze(test.test): 12 | version = 1 13 | def initialize(self): 14 | asusp.sysvals.suspendmode = 'freeze' 15 | if not asusp.statusCheck(): 16 | logging.error('Status Check FAILED') 17 | raise error.TestFail('Status Check FAILED') 18 | asusp.sysvals.setPrecision(6) 19 | asusp.sysvals.mindevlen = 1 20 | asusp.sysvals.hostname = 'chromium' 21 | asusp.sysvals.initFtrace() 22 | asusp.sysvals.initTestOutput('.', self.resultsdir) 23 | logging.info('testdir : %s' % asusp.sysvals.testdir) 24 | logging.info('dmesgfile : %s' % asusp.sysvals.dmesgfile) 25 | logging.info('ftracefile : %s' % asusp.sysvals.ftracefile) 26 | logging.info('htmlfile : %s' % asusp.sysvals.htmlfile) 27 | 28 | def run_once(self, devmode=False, waketime=15): 29 | if devmode and asusp.sysvals.usekprobes: 30 | asusp.sysvals.usedevsrc = True 31 | asusp.sysvals.rtcwake = True 32 | asusp.sysvals.rtcwaketime = waketime 33 | asusp.executeSuspend() 34 | asusp.sysvals.cleanupFtrace() 35 | logging.info('PROCESSING DATA') 36 | if(asusp.sysvals.usetraceeventsonly): 37 | # data for kernels 3.15 or newer is entirely in ftrace 38 | testruns = asusp.parseTraceLog() 39 | else: 40 | # data for kernels older than 3.15 is primarily in dmesg 41 | testruns = asusp.loadKernelLog() 42 | for data in testruns: 43 | asusp.parseKernelLog(data) 44 | if(asusp.sysvals.usecallgraph or asusp.sysvals.usetraceevents): 45 | asusp.appendIncompleteTraceLog(testruns) 46 | asusp.createHTML(testruns) 47 | -------------------------------------------------------------------------------- /autotest/platform_AnalyzeSuspend/analyze_suspend.py: -------------------------------------------------------------------------------- 1 | ../../analyze_suspend.py -------------------------------------------------------------------------------- /autotest/platform_AnalyzeSuspend/control: -------------------------------------------------------------------------------- 1 | # Copyright 2015 The Chromium OS Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | AUTHOR = 'Todd Brandt ' 6 | PURPOSE = 'Kernel Suspend/Resume timeline' 7 | CRITERIA = 'This test is a performance test. Expected success, no crashes.' 8 | DOC = """ 9 | This test puts the client host through a suspend/resume cycle. 10 | """ 11 | NAME = 'platform_AnalyzeSuspend' 12 | TIME = 'SHORT' 13 | TEST_CLASS = 'platform' 14 | TEST_CATEGORY = 'Performance' 15 | TEST_TYPE = 'client' 16 | 17 | # Run a suspend/resume cycle and collect a timeline 18 | job.run_test('platform_AnalyzeSuspend', devmode=False, waketime=10, power_manager=True) 19 | -------------------------------------------------------------------------------- /autotest/platform_AnalyzeSuspend/platform_AnalyzeSuspend.py: -------------------------------------------------------------------------------- 1 | # Copyright 2015 The Chromium OS Authors. All rights reserved. 2 | # Use of this source code is governed by a BSD-style license that can be 3 | # found in the LICENSE file. 4 | 5 | import os, commands, logging 6 | from autotest_lib.client.bin import utils, test 7 | from autotest_lib.client.common_lib import error 8 | from autotest_lib.client.cros import rtc, sys_power 9 | import analyze_suspend as asusp 10 | 11 | class platform_AnalyzeSuspend(test.test): 12 | version = 1 13 | def initialize(self): 14 | asusp.sysvals.suspendmode = 'mem' 15 | if not asusp.statusCheck(): 16 | logging.error('Status Check FAILED') 17 | raise error.TestFail('Status Check FAILED') 18 | asusp.sysvals.setPrecision(6) 19 | asusp.sysvals.mindevlen = 1 20 | asusp.sysvals.hostname = 'chromium' 21 | asusp.sysvals.initFtrace() 22 | asusp.sysvals.initTestOutput('.', self.resultsdir) 23 | logging.info('testdir : %s' % asusp.sysvals.testdir) 24 | logging.info('dmesgfile : %s' % asusp.sysvals.dmesgfile) 25 | logging.info('ftracefile : %s' % asusp.sysvals.ftracefile) 26 | logging.info('htmlfile : %s' % asusp.sysvals.htmlfile) 27 | 28 | def executeSuspend(self, waketime): 29 | if(asusp.sysvals.usecallgraph or asusp.sysvals.usetraceevents): 30 | ftrace = True 31 | else: 32 | ftrace = False 33 | fwdata = [] 34 | asusp.sysvals.initdmesg() 35 | logging.info('START TRACING') 36 | if ftrace: 37 | asusp.sysvals.fsetVal('1', 'tracing_on') 38 | asusp.sysvals.fsetVal('SUSPEND START', 'trace_marker') 39 | # handle do_suspend manually here 40 | alarm, wakeup_count = sys_power.prepare_wakeup(waketime) 41 | sys_power.upstart.ensure_running('powerd') 42 | command = ('/usr/bin/powerd_dbus_suspend --delay=%d --timeout=30 ' 43 | '--wakeup_count=%d') % (0, wakeup_count) 44 | logging.info("Running '%s'", command) 45 | os.system(command) 46 | # check_waketime should not be fatal, just note it in the log 47 | now = sys_power.rtc.get_seconds() 48 | if now < alarm: 49 | logging.error('Woke up early at %d', now) 50 | logging.info('RESUME COMPLETE') 51 | if ftrace: 52 | asusp.sysvals.fsetVal('RESUME COMPLETE', 'trace_marker') 53 | asusp.sysvals.fsetVal('0', 'tracing_on') 54 | fwdata.append(asusp.getFPDT(False)) 55 | if ftrace: 56 | logging.info('CAPTURING TRACE') 57 | asusp.writeDatafileHeader(asusp.sysvals.ftracefile, fwdata) 58 | os.system('cat '+asusp.sysvals.tpath+'trace >> '+asusp.sysvals.ftracefile) 59 | asusp.sysvals.fsetVal('', 'trace') 60 | asusp.devProps() 61 | logging.info('CAPTURING DMESG') 62 | asusp.writeDatafileHeader(asusp.sysvals.dmesgfile, fwdata) 63 | asusp.sysvals.getdmesg() 64 | 65 | def run_once(self, devmode=False, waketime=15, power_manager=False): 66 | if devmode and asusp.sysvals.usekprobes: 67 | asusp.sysvals.usedevsrc = True 68 | if power_manager: 69 | self.executeSuspend(waketime) 70 | else: 71 | asusp.sysvals.rtcwake = True 72 | asusp.sysvals.rtcwaketime = waketime 73 | asusp.executeSuspend() 74 | asusp.sysvals.cleanupFtrace() 75 | logging.info('PROCESSING DATA') 76 | if(asusp.sysvals.usetraceeventsonly): 77 | # data for kernels 3.15 or newer is entirely in ftrace 78 | testruns = asusp.parseTraceLog() 79 | else: 80 | # data for kernels older than 3.15 is primarily in dmesg 81 | testruns = asusp.loadKernelLog() 82 | for data in testruns: 83 | asusp.parseKernelLog(data) 84 | if(asusp.sysvals.usecallgraph or asusp.sysvals.usetraceevents): 85 | asusp.appendIncompleteTraceLog(testruns) 86 | asusp.createHTML(testruns) 87 | -------------------------------------------------------------------------------- /bootgraph.8: -------------------------------------------------------------------------------- 1 | .TH BOOTGRAPH 8 2 | .SH NAME 3 | bootgraph \- Kernel boot timing analysis 4 | .SH SYNOPSIS 5 | .ft B 6 | .B bootgraph 7 | .RB [ OPTIONS ] 8 | .RB [ COMMAND ] 9 | .SH DESCRIPTION 10 | \fBbootgraph \fP reads the dmesg log from kernel boot and 11 | creates an html representation of the initcall timeline. It graphs 12 | every module init call found, through both kernel and user modes. The 13 | timeline is split into two phases: kernel mode & user mode. kernel mode 14 | represents a single process run on a single cpu with serial init calls. 15 | Once user mode begins, the init process is called, and the init calls 16 | start working in parallel. 17 | .PP 18 | If no specific command is given, the tool reads the current dmesg log and 19 | outputs a new timeline. 20 | .PP 21 | The tool can also augment the timeline with ftrace data on custom target 22 | functions as well as full trace callgraphs. 23 | .PP 24 | Generates output files in subdirectory: boot-yymmdd-HHMMSS 25 | html timeline : _boot.html 26 | raw dmesg file : _boot_dmesg.txt 27 | raw ftrace file : _boot_ftrace.txt 28 | .SH OPTIONS 29 | .TP 30 | \fB-h\fR 31 | Print this help text 32 | .TP 33 | \fB-v\fR 34 | Print the current tool version 35 | .TP 36 | \fB-addlogs\fR 37 | Add the dmesg log to the html output. It will be viewable by 38 | clicking a button in the timeline. 39 | .TP 40 | \fB-result \fIfile\fR 41 | Export a results table to a text file for parsing. 42 | .TP 43 | \fB-o \fIname\fR 44 | Overrides the output subdirectory name when running a new test. 45 | Use {date}, {time}, {hostname} for current values. 46 | .sp 47 | e.g. boot-{hostname}-{date}-{time} 48 | .SS "advanced" 49 | .TP 50 | \fB-f or -callgraph\fR 51 | Use ftrace to create initcall callgraphs (default: disabled). If -func 52 | is not used there will be one callgraph per initcall. This can produce 53 | very large outputs, i.e. 10MB - 100MB. 54 | .TP 55 | \fB-fstat\fR 56 | Use ftrace to add function detail (default: disabled) 57 | .TP 58 | \fB-maxdepth \fIlevel\fR 59 | limit the callgraph trace depth to \fIlevel\fR (default: 2). This is 60 | the best way to limit the output size when using -callgraph. 61 | .TP 62 | \fB-mincg \fIt\fR 63 | Discard all callgraphs shorter than \fIt\fR milliseconds (default: 0=all). 64 | This reduces the html file size as there can be many tiny callgraphs 65 | which are barely visible in the timeline. 66 | The value is a float: e.g. 0.001 represents 1 us. 67 | .TP 68 | \fB-cgfilter \fI"func1,func2,..."\fR 69 | Reduce callgraph output in the timeline by limiting it to a list of calls. The 70 | argument can be a single function name or a comma delimited list. 71 | (default: none) 72 | .TP 73 | \fB-cgskip \fIfile\fR 74 | Reduce callgraph output in the timeline by skipping over uninteresting 75 | functions in the trace, e.g. printk or console_unlock. The functions listed 76 | in this file will show up as empty leaves in the callgraph with only the start/end 77 | times displayed. 78 | (default: none) 79 | .TP 80 | \fB-timeprec \fIn\fR 81 | Number of significant digits in timestamps (0:S, 3:ms, [6:us]) 82 | .TP 83 | \fB-expandcg\fR 84 | pre-expand the callgraph data in the html output (default: disabled) 85 | .TP 86 | \fB-func \fI"func1,func2,..."\fR 87 | Instead of tracing each initcall, trace a custom list of functions (default: do_one_initcall) 88 | .TP 89 | \fB-reboot\fR 90 | Reboot the machine and generate a new timeline automatically. Works in 4 steps. 91 | 1. updates grub with the required kernel parameters 92 | 2. installs a cron job which re-runs the tool after reboot 93 | 3. reboots the system 94 | 4. after startup, extracts the data and generates the timeline 95 | .TP 96 | \fB-manual\fR 97 | Show the requirements to generate a new timeline manually. Requires 3 steps. 98 | 1. append the string to the kernel command line via your native boot manager. 99 | 2. reboot the system 100 | 3. after startup, re-run the tool with the same arguments and no command 101 | 102 | .SH COMMANDS 103 | .SS "rebuild" 104 | .TP 105 | \fB-dmesg \fIfile\fR 106 | Create HTML output from an existing dmesg file. 107 | .TP 108 | \fB-ftrace \fIfile\fR 109 | Create HTML output from an existing ftrace file (used with -dmesg). 110 | .SS "other" 111 | .TP 112 | \fB-flistall\fR 113 | Print all ftrace functions capable of being captured. These are all the 114 | possible values you can add to trace via the -func argument. 115 | .TP 116 | \fB-sysinfo\fR 117 | Print out system info extracted from BIOS. Reads /dev/mem directly instead of going through dmidecode. 118 | 119 | .SH EXAMPLES 120 | Create a timeline using the current dmesg log. 121 | .IP 122 | \f(CW$ bootgraph\fR 123 | .PP 124 | Create a timeline using the current dmesg and ftrace log. 125 | .IP 126 | \f(CW$ bootgraph -callgraph\fR 127 | .PP 128 | Create a timeline using the current dmesg, add the log to the html and change the folder. 129 | .IP 130 | \f(CW$ bootgraph -addlogs -o "myboot-{date}-{time}"\fR 131 | .PP 132 | Capture a new boot timeline by automatically rebooting the machine. 133 | .IP 134 | \f(CW$ sudo bootgraph -reboot -addlogs -o "latest-{hostname)"\fR 135 | .PP 136 | Capture a new boot timeline with function trace data. 137 | .IP 138 | \f(CW$ sudo bootgraph -reboot -f\fR 139 | .PP 140 | Capture a new boot timeline with trace & callgraph data. Skip callgraphs smaller than 5ms. 141 | .IP 142 | \f(CW$ sudo bootgraph -reboot -callgraph -mincg 5\fR 143 | .PP 144 | Capture a new boot timeline with callgraph data over custom functions. 145 | .IP 146 | \f(CW$ sudo bootgraph -reboot -callgraph -func "acpi_ps_parse_aml,msleep"\fR 147 | .PP 148 | Capture a brand new boot timeline with manual reboot. 149 | .IP 150 | \f(CW$ sudo bootgraph -callgraph -manual\fR 151 | .IP 152 | \f(CW$ vi /etc/default/grub # add the CMDLINE string to your kernel params\fR 153 | .IP 154 | \f(CW$ sudo reboot # reboot the machine\fR 155 | .IP 156 | \f(CW$ sudo bootgraph -callgraph # re-run the tool after restart\fR 157 | .PP 158 | .SS "rebuild timeline from logs" 159 | .PP 160 | Rebuild the html from a previous run's logs, using the same options. 161 | .IP 162 | \f(CW$ bootgraph -dmesg dmesg.txt -ftrace ftrace.txt -callgraph\fR 163 | .PP 164 | Rebuild the html with different options. 165 | .IP 166 | \f(CW$ bootgraph -dmesg dmesg.txt -ftrace ftrace.txt -addlogs\fR 167 | 168 | .SH "SEE ALSO" 169 | dmesg(1), update-grub(8), crontab(1), reboot(8) 170 | .PP 171 | .SH AUTHOR 172 | .nf 173 | Written by Todd Brandt 174 | -------------------------------------------------------------------------------- /config/bisect-example.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Sleepgraph stress testing 3 | # 4 | # This is the configuration file for stresstest.py. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. 7 | # 8 | # stresstest.py -config config/bisect.cfg bisect 9 | # 10 | 11 | [setup] 12 | 13 | # Kernel package format 14 | # Set kernel package format [deb/rpm] 15 | pkgfmt: deb 16 | 17 | # Kernel package output folder 18 | # Place build output files here (default: ksrc/..) 19 | pkgout: ~/workspace/bisecttest 20 | 21 | # Kernel source 22 | # Kernel source folder location (default: required to build) 23 | ksrc: ~/workspace/linux 24 | 25 | # Kernel config folder 26 | # Folder with config file and patches to apply to ksrc (default: no change) 27 | kcfg: ~/workspace/stressconfig 28 | 29 | # Good kernel commit/tag 30 | # Bisect assumes this is already tested, it won't run this kernel 31 | kgood = v6.1-rc2 32 | 33 | # Bad kernel commit/tag 34 | # Bisect assumes this is already tested, it won't run this kernel 35 | kbad = v6.1-rc3 36 | 37 | # Bisect test script 38 | # runs on the target system and returns "GOOD" or "BAD" 39 | ktest = tools/bisect-sleepgraph-test.py 40 | 41 | # Target machine hostname 42 | # stresstest checks the hostname to be sure it matches 43 | host = otcpl-adl-m-1 44 | 45 | # Target machine ip addr 46 | # The machine must be open to the network with ssh access 47 | addr = 10.54.39.10 48 | 49 | # Target machine username 50 | # The machine was have password-less ssh access enabled 51 | user = labuser 52 | 53 | # Wait for user input 54 | # Tool asks user to retry if something goes wrong 55 | userinput = True 56 | -------------------------------------------------------------------------------- /config/cgskip.txt: -------------------------------------------------------------------------------- 1 | # ----------------------------------------------- 2 | # CallGraph function skip list 3 | # 4 | # This file contains a list of functions which are 5 | # meant to be skipped in the callgraph trace. It reduces 6 | # the callgraph html file size by treating these functions 7 | # as leaves with no child calls. It can be editted by 8 | # adding or removing function symbol names. 9 | # 10 | # The sleepgraph tool automatically pulls this file in when 11 | # it is found in the config folder. It can be ignored if 12 | # the tool is called with "-cgskip off". 13 | # ----------------------------------------------- 14 | 15 | # low level scheduling and timing 16 | up 17 | down_timeout 18 | mutex_lock 19 | down_read 20 | complete_all 21 | schedule_timeout 22 | wake_up_process 23 | msleep 24 | __udelay 25 | ktime_get 26 | 27 | # console calls 28 | printk 29 | dev_printk 30 | __dev_printk 31 | console_unlock 32 | 33 | # memory handling 34 | __kmalloc 35 | __kmalloc_track_caller 36 | kmem_cache_alloc 37 | kmem_cache_alloc_trace 38 | kmem_cache_free 39 | kstrdup 40 | kstrdup_const 41 | kmalloc_slab 42 | new_slab 43 | __slab_alloc 44 | __slab_free 45 | raw_pci_read 46 | pci_read 47 | alloc_pages_current 48 | 49 | # debugfs and sysfs setup 50 | debugfs_remove_recursive 51 | debugfs_create_dir 52 | debugfs_create_files 53 | debugfs_create_dir 54 | debugfs_get_inode 55 | sysfs_add_file_mode_ns 56 | sysfs_add_file 57 | sysfs_create_dir_ns 58 | sysfs_create_link 59 | sysfs_create_group 60 | sysfs_create_groups 61 | sysfs_create_bin_file 62 | dpm_sysfs_add 63 | sysfs_create_file_ns 64 | sysfs_merge_group 65 | sysfs_add_link_to_group 66 | sysfs_create_link_sd 67 | -------------------------------------------------------------------------------- /config/custom-timeline-functions.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # This is the configuration file for sleepgraph. It contains 3 | # all the tool arguments so that they don't have to be given on the 4 | # command line. It also includes advanced settings for functions 5 | # and kprobes. It is run like this 6 | # 7 | # sudo ./sleepgraph.py -config thisfile.txt 8 | # 9 | 10 | [Settings] 11 | 12 | # Verbosity 13 | # print verbose messages (default: false) 14 | verbose: false 15 | 16 | # Suspend Mode 17 | # e.g. standby, mem, freeze, disk (default: mem) 18 | mode: mem 19 | 20 | # Automatic Wakeup 21 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) 22 | rtcwake: 15 23 | 24 | # Add Logs 25 | # add the dmesg and ftrace log to the html output (default: false) 26 | addlogs: false 27 | 28 | # Display function calls 29 | # graph source functions in the timeline (default: false) 30 | dev: true 31 | 32 | # Callgraph 33 | # gather detailed ftrace callgraph data on all timeline events (default: false) 34 | callgraph: false 35 | 36 | # Back to Back Suspend/Resume 37 | # Run two suspend/resumes back to back (default: false) 38 | x2: false 39 | 40 | # Back to Back Suspend Delay 41 | # Time delay between the two test runs in ms (default: 0 ms) 42 | x2delay: 0 43 | 44 | # Minimum Device Length 45 | # graph only devices longer than min in the timeline (default: 0.001 ms) 46 | mindev: 1 47 | 48 | # Minimum Callgraph Length 49 | # provide callgraph data for blocks longer than min (default: 0.001 ms) 50 | mincg: 1 51 | 52 | # Suspend/Resume Gap 53 | # insert a small visible gap between suspend and resume on the timeline (default: false) 54 | srgap: false 55 | 56 | # Output Directory Format 57 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values 58 | output-dir: suspend-{hostname}-{date}-{time}-custom 59 | 60 | # Override default timeline entries 61 | # Do not use the internal default functions for timeline entries (default: false) 62 | # Set this to true if you intend to only use the ones defined in this config 63 | override-timeline-functions: true 64 | 65 | # Override default dev timeline entries 66 | # Do not use the internal default functions for dev timeline entries (default: false) 67 | # Set this to true if you intend to only use the ones defined in this config 68 | override-dev-timeline-functions: true 69 | 70 | [timeline_functions_x86_64] 71 | # 72 | # Function calls to display in the timeline alongside device callbacks. 73 | # The tool has an internal set of these functions which should cover the 74 | # whole of kernel execution, but you can append or override here. 75 | # 76 | # This is a list of kprobes which use both symbol data and function arg data. 77 | # The function calls are displayed on the timeline alongside the device blocks. 78 | # The args are pulled directly from the stack using this architecture's registers 79 | # and stack formatting. Three pieces of info are required. The function name, 80 | # a format string, and an argument list 81 | # 82 | # Entry format: 83 | # 84 | # function: format{fn_arg1}_{fn_arg2} fn_arg1 fn_arg2 ... [color=purple] 85 | # 86 | # Required Arguments: 87 | # 88 | # function: The symbol name for the function you want probed, this is the 89 | # minimum required for an entry, it will show up as the function 90 | # name with no arguments. 91 | # 92 | # example: _cpu_up: 93 | # 94 | # Optional Arguments: 95 | # 96 | # format: The format to display the data on the timeline in. Use braces to 97 | # enclose the arg names. 98 | # 99 | # example: CPU_ON[{cpu}] 100 | # 101 | # color: The color of the entry block in the timeline. The default color is 102 | # transparent, so the entry shares the phase color. The color is an 103 | # html color string, either a word, or an RGB. 104 | # 105 | # example: [color=#CC00CC] 106 | # 107 | # arglist: A list of arguments from registers/stack addresses. See URL: 108 | # https://www.kernel.org/doc/Documentation/trace/kprobetrace.txt 109 | # 110 | # example: cpu=%di:s32 111 | # 112 | # Example: Display cpu resume in the timeline 113 | # 114 | # _cpu_up: CPU_ON[{cpu}] cpu=%di:s32 [color=orange] 115 | # 116 | _cpu_down: CPU_OFF[{cpu}] cpu=%di:s32 117 | _cpu_up: CPU_ON[{cpu}] cpu=%di:s32 118 | sys_sync: 119 | pm_prepare_console: 120 | pm_notifier_call_chain: 121 | freeze_processes: 122 | freeze_kernel_threads: 123 | pm_restrict_gfp_mask: 124 | acpi_suspend_begin: 125 | suspend_console: 126 | acpi_pm_prepare: 127 | syscore_suspend: 128 | arch_enable_nonboot_cpus_end: 129 | syscore_resume: 130 | acpi_pm_finish: 131 | resume_console: 132 | acpi_pm_end: 133 | pm_restore_gfp_mask: 134 | thaw_processes: 135 | pm_restore_console: 136 | 137 | [dev_timeline_functions_x86_64] 138 | # 139 | # Dev mode function calls to display inside timeline entries 140 | # 141 | # This is a list of kprobes which use both symbol data and function arg data. 142 | # The function calls are displayed on the timeline alongside the device blocks. 143 | # The args are pulled directly from the stack using this architecture's registers 144 | # and stack formatting. Three pieces of info are required. The function name, 145 | # a format string, and an argument list 146 | # 147 | # Entry format: 148 | # 149 | # function: format{fn_arg1}_{fn_arg2} fn_arg1 fn_arg2 ... [color=purple] 150 | # 151 | # Required Arguments: 152 | # 153 | # function: The symbol name for the function you want probed, this is the 154 | # minimum required for an entry, it will show up as the function 155 | # name with no arguments. 156 | # 157 | # example: ata_eh_recover: 158 | # 159 | # Optional Arguments: 160 | # 161 | # format: The format to display the data on the timeline in. Use braces to 162 | # enclose the arg names. 163 | # 164 | # example: ata{port}_port_reset 165 | # 166 | # color: The color of the entry block in the timeline. The default color is 167 | # transparent, so the entry shares the phase color. The color is an 168 | # html color string, either a word, or an RGB. 169 | # 170 | # example: [color=#CC00CC] 171 | # 172 | # arglist: A list of arguments from registers/stack addresses. See URL: 173 | # https://www.kernel.org/doc/Documentation/trace/kprobetrace.txt 174 | # 175 | # example: port=+36(%di):s32 176 | # 177 | # Example: Display ATA port reset as ataN_port_reset in the timeline 178 | # 179 | # ata_eh_recover: ata{port}_port_reset port=+36(%di):s32 180 | # 181 | msleep: msleep time=%di:s32 182 | schedule_timeout_uninterruptible: schedule_timeout_uninterruptible timeout=%di:s32 183 | schedule_timeout: schedule_timeout timeout=%di:s32 184 | usleep_range: usleep_range min=%di:s32 max=%si:s32 185 | __const_udelay: udelay loops=%di:s32 186 | __mutex_lock_slowpath: mutex_lock_slowpath 187 | ata_eh_recover: ata_eh_recover port=+36(%di):s32 188 | acpi_os_stall: 189 | acpi_resume_power_resources: 190 | acpi_ps_parse_aml: 191 | ext4_sync_fs: 192 | i915_gem_resume: 193 | i915_restore_state: 194 | intel_opregion_setup: 195 | g4x_pre_enable_dp: 196 | vlv_pre_enable_dp: 197 | chv_pre_enable_dp: 198 | g4x_enable_dp: 199 | vlv_enable_dp: 200 | intel_hpd_init: 201 | intel_opregion_register: 202 | intel_dp_detect: 203 | intel_hdmi_detect: 204 | intel_opregion_init: 205 | intel_fbdev_set_suspend: 206 | -------------------------------------------------------------------------------- /config/debug-serio-suspend.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # This is the configuration file for sleepgraph. It contains 3 | # all the tool arguments so that they don't have to be given on the 4 | # command line. It also includes advanced settings for functions 5 | # and kprobes. It is run like this 6 | # 7 | # sudo ./sleepgraph.py -config thisfile.txt 8 | # 9 | 10 | [Settings] 11 | 12 | # Verbosity 13 | # print verbose messages (default: false) 14 | verbose: false 15 | 16 | # Suspend Mode 17 | # e.g. standby, mem, freeze, disk (default: mem) 18 | mode: mem 19 | 20 | # Automatic Wakeup 21 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) 22 | rtcwake: 15 23 | 24 | # Add Logs 25 | # add the dmesg and ftrace log to the html output (default: false) 26 | addlogs: false 27 | 28 | # Display function calls 29 | # graph source functions in the timeline (default: false) 30 | dev: true 31 | 32 | # Callgraph 33 | # gather detailed ftrace callgraph data on all timeline events (default: false) 34 | callgraph: false 35 | 36 | # Back to Back Suspend/Resume 37 | # Run two suspend/resumes back to back (default: false) 38 | x2: false 39 | 40 | # Back to Back Suspend Delay 41 | # Time delay between the two test runs in ms (default: 0 ms) 42 | x2delay: 0 43 | 44 | # Minimum Device Length 45 | # graph only devices longer than min in the timeline (default: 0.001 ms) 46 | mindev: 0.001 47 | 48 | # Minimum Callgraph Length 49 | # provide callgraph data for blocks longer than min (default: 0.001 ms) 50 | mincg: 1 51 | 52 | # Suspend/Resume Gap 53 | # insert a small visible gap between suspend and resume on the timeline (default: false) 54 | srgap: false 55 | 56 | # Output Directory Format 57 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values 58 | output-dir: suspend-{hostname}-{date}-{time}-serio 59 | 60 | # Override default timeline entries 61 | # Do not use the internal default functions for timeline entries (default: false) 62 | # Set this to true if you intend to only use the ones defined in this config 63 | override-timeline-functions: false 64 | 65 | # Override default dev timeline entries 66 | # Do not use the internal default functions for dev timeline entries (default: false) 67 | # Set this to true if you intend to only use the ones defined in this config 68 | override-dev-timeline-functions: false 69 | 70 | [dev_timeline_functions_x86_64] 71 | # 72 | # Dev mode function calls to display inside timeline entries 73 | # 74 | # This is a list of kprobes which use both symbol data and function arg data. 75 | # The function calls are displayed on the timeline alongside the device blocks. 76 | # The args are pulled directly from the stack using this architecture's registers 77 | # and stack formatting. Three pieces of info are required. The function name, 78 | # a format string, and an argument list 79 | # 80 | # Entry format: 81 | # 82 | # function: format{fn_arg1}_{fn_arg2} fn_arg1 fn_arg2 ... [color=purple] 83 | # 84 | # Required Arguments: 85 | # 86 | # function: The symbol name for the function you want probed, this is the 87 | # minimum required for an entry, it will show up as the function 88 | # name with no arguments. 89 | # 90 | # example: ata_eh_recover: 91 | # 92 | # Optional Arguments: 93 | # 94 | # format: The format to display the data on the timeline in. Use braces to 95 | # enclose the arg names. 96 | # 97 | # example: ata{port}_port_reset 98 | # 99 | # color: The color of the entry block in the timeline. The default color is 100 | # transparent, so the entry shares the phase color. The color is an 101 | # html color string, either a word, or an RGB. 102 | # 103 | # example: [color=#CC00CC] 104 | # 105 | # arglist: A list of arguments from registers/stack addresses. See URL: 106 | # https://www.kernel.org/doc/Documentation/trace/kprobetrace.txt 107 | # 108 | # example: port=+36(%di):s32 109 | # 110 | # For x86_64: the 1st 6 function arguments go in registers 111 | # %di, %si, %dx, %cx, %8, %9 respectively, the remaining args are 112 | # pushed onto the stack. All addresses are 8 bytes (void, int, etc). 113 | # 114 | # 1st function arg is a struct address, 36 bytes in is a 32bit short, 115 | # get that number and set it to arg "port" 116 | # 117 | # int ata_eh_recover(struct ata_port *ap, ... 118 | # struct ata_port { 119 | # struct Scsi_Host *scsi_host; 120 | # struct ata_port_operations *ops; 121 | # spinlock_t *lock; 122 | # unsigned long flags; 123 | # unsigned int pflags; 124 | # unsigned int print_id; 125 | # unsigned int local_port_no; <---------- 126 | # ... 127 | # 128 | # Example: Display ATA port reset as ataN_port_reset in the timeline 129 | # 130 | # ata_eh_recover: ata{port}_port_reset port=+36(%di):s32 [color=red] 131 | # 132 | serio_reconnect_port: serio_reconnect_port({phys}/{name}) name=+8(%di):string phys=+40(%di):string 133 | serio_disconnect_port: serio_disconnect_port({phys}/{name}) name=+8(%di):string phys=+40(%di):string [color=ffc2c2] 134 | serio_find_driver: serio_find_driver({phys}/{name}) name=+8(%di):string phys=+40(%di):string [color=ffc2c2] 135 | #alps_rpt_cmd: alps_rpt_cmd({icmd}/{rcmd}) icmd=%si rcmd=%dx 136 | ps2_command: ps2_command_{name}({cmd}) cmd=%dx name=+8(+0(%di)):string [color=c2c2ff] 137 | serio_handle_event: 138 | serio_suspend: 139 | psmouse_connect: 140 | cortron_detect: 141 | intellimouse_detect: 142 | im_explorer_detect: 143 | genius_detect: 144 | thinking_detect: 145 | ps2bare_detect: 146 | synaptics_detect: 147 | focaltech_detect: 148 | alps_detect: 149 | elantech_detect: 150 | lifebook_detect: 151 | fsp_detect: 152 | trackpoint_detect: 153 | touchkit_ps2_detect: 154 | cypress_detect: 155 | -------------------------------------------------------------------------------- /config/example.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Generic S3 (Suspend to Mem) test 3 | # 4 | # This is the configuration file for sleepgraph. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. It also includes advanced settings for functions 7 | # and kprobes. It is run like this 8 | # 9 | # sudo ./sleepgraph.py -config config/example.cfg 10 | # 11 | 12 | [Settings] 13 | 14 | # ---- General Options ---- 15 | 16 | # Verbosity 17 | # print verbose messages (default: false) 18 | verbose: false 19 | 20 | # Suspend Mode 21 | # e.g. standby, mem, freeze, disk (default: mem) 22 | mode: mem 23 | 24 | # Output Directory Format 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values 26 | output-dir: suspend-{hostname}-{date}-{time} 27 | 28 | # Automatic Wakeup 29 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) 30 | rtcwake: 15 31 | 32 | # Add Logs 33 | # add the dmesg and ftrace log to the html output (default: false) 34 | addlogs: true 35 | 36 | # Suspend/Resume Gap 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) 38 | srgap: false 39 | 40 | # Skip HTML generation 41 | # Only capture the logs, don't generate the html timeline (default: false) 42 | skiphtml: false 43 | 44 | # Sync filesystem before suspend 45 | # run sync before the test, minimizes sys_sync call time (default: false) 46 | sync: true 47 | 48 | # Runtime suspend enable/disable 49 | # Enable/disable runtime suspend for all devices, restore all after test (default: no-action) 50 | # rs: disable 51 | 52 | # Turn display on/off for test 53 | # Switch the display on/off for the test using xset (default: no-action) 54 | # display: on 55 | 56 | # Print results to text file 57 | # Print the status of the test run in the given file (default: no-action) 58 | result: result.txt 59 | 60 | # Gzip the log files to save space 61 | # Gzip the generated log files, and read gzipped log files (default: false) 62 | gzip: true 63 | 64 | # ---- Advanced Options ---- 65 | 66 | # Command to execute in lieu of suspend (default: "") 67 | # command: echo mem > /sys/power/state 68 | 69 | # Display user processes 70 | # graph user processes and cpu usage in the timeline (default: false) 71 | proc: false 72 | 73 | # Display function calls 74 | # graph source functions in the timeline (default: false) 75 | dev: false 76 | 77 | # Multiple test runs 78 | # Run N tests D seconds apart, generates separate outputs with a summary (default: false) 79 | # multi: 3 5 80 | 81 | # Back to Back Suspend/Resume 82 | # Run two suspend/resumes back to back and display in the same timeline (default: false) 83 | x2: false 84 | 85 | # Back to Back Suspend Delay 86 | # Time delay between the two test runs in ms (default: 0 ms) 87 | x2delay: 0 88 | 89 | # Pre Suspend Delay 90 | # Include an N ms delay before (1st) suspend (default: 0 ms) 91 | predelay: 0 92 | 93 | # Post Resume Delay 94 | # Include an N ms delay after (last) resume (default: 0 ms) 95 | postdelay: 0 96 | 97 | # Minimum Device Length 98 | # graph only devices longer than min in the timeline (default: 0.001 ms) 99 | mindev: 0.001 100 | 101 | # Call Loop Max Gap (dev mode only) 102 | # merge loops of the same call if each is less than maxgap apart (def: 100us) 103 | callloop-maxgap: 0.0001 104 | 105 | # Call Loop Max Length (dev mode only) 106 | # merge loops of the same call if each is less than maxlen in length (def: 5ms) 107 | callloop-maxlen: 0.005 108 | 109 | # Override default timeline entries: 110 | # Do not use the internal default functions for timeline entries (def: false) 111 | # Set this to true if you intend to only use the ones defined in the config 112 | override-timeline-functions: true 113 | 114 | # Override default dev timeline entries: 115 | # Do not use the internal default functions for dev timeline entries (def: false) 116 | # Set this to true if you intend to only use the ones defined in the config 117 | override-dev-timeline-functions: true 118 | 119 | # ---- Debug Options ---- 120 | 121 | # Callgraph 122 | # gather detailed ftrace callgraph data on all timeline events (default: false) 123 | callgraph: false 124 | 125 | # Max graph depth 126 | # limit the callgraph trace to this depth (default: 0 = all) 127 | maxdepth: 2 128 | 129 | # Callgraph phase filter 130 | # Only enable callgraphs for one phase, i.e. resume_noirq (default: all) 131 | cgphase: suspend 132 | 133 | # Callgraph x2 test filter 134 | # Only enable callgraphs test 0 or 1 when using -x2 (default: 1) 135 | cgtest: 0 136 | 137 | # Expand Callgraph 138 | # pre-expand the callgraph data in the html output (default: disabled) 139 | expandcg: false 140 | 141 | # Minimum Callgraph Length 142 | # provide callgraph data for blocks longer than min (default: 0.001 ms) 143 | mincg: 1 144 | 145 | # Timestamp Precision 146 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) 147 | timeprec: 6 148 | 149 | # Device Filter 150 | # show only devices whose name/driver includes one of these strings 151 | # devicefilter: _cpu_up,_cpu_down,i915,usb 152 | 153 | # Add kprobe functions to the timeline 154 | # Add functions to the timeline from a text file (default: no-action) 155 | # fadd: file.txt 156 | 157 | # Ftrace buffer size 158 | # Set trace buffer size to N kilo-bytes (default: all of free memory up to 3GB) 159 | # bufsize: 1000 160 | -------------------------------------------------------------------------------- /config/freeze-callgraph.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Full Callgraph for S2 (Freeze) test 3 | # 4 | # This is the configuration file for sleepgraph. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. It also includes advanced settings for functions 7 | # and kprobes. It is run like this 8 | # 9 | # sudo ./sleepgraph.py -config config/freeze-callgraph.cfg 10 | # 11 | # NOTE: the output of this test is very large (> 30MB) 12 | 13 | [Settings] 14 | 15 | # ---- General Options ---- 16 | 17 | # Verbosity 18 | # print verbose messages (default: false) 19 | verbose: false 20 | 21 | # Suspend Mode 22 | # e.g. standby, mem, freeze, disk (default: mem) 23 | mode: freeze 24 | 25 | # Output Directory Format 26 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values 27 | output-dir: freeze-{hostname}-{date}-{time}-cg 28 | 29 | # Automatic Wakeup 30 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) 31 | rtcwake: 15 32 | 33 | # Add Logs 34 | # add the dmesg and ftrace log to the html output (default: false) 35 | addlogs: false 36 | 37 | # Suspend/Resume Gap 38 | # insert a small visible gap between suspend and resume on the timeline (default: false) 39 | srgap: false 40 | 41 | # ---- Advanced Options ---- 42 | 43 | # Command to execute in lieu of freeze (default: "") 44 | # command: echo freeze > /sys/power/state 45 | 46 | # Display user processes 47 | # graph user processes and cpu usage in the timeline (default: false) 48 | proc: false 49 | 50 | # Display function calls 51 | # graph source functions in the timeline (default: false) 52 | dev: false 53 | 54 | # Back to Back Suspend/Resume 55 | # Run two suspend/resumes back to back (default: false) 56 | x2: false 57 | 58 | # Back to Back Suspend Delay 59 | # Time delay between the two test runs in ms (default: 0 ms) 60 | x2delay: 0 61 | 62 | # Pre Suspend Delay 63 | # Include an N ms delay before (1st) suspend (default: 0 ms) 64 | predelay: 0 65 | 66 | # Post Resume Delay 67 | # Include an N ms delay after (last) resume (default: 0 ms) 68 | postdelay: 0 69 | 70 | # Minimum Device Length 71 | # graph only devices longer than min in the timeline (default: 0.001 ms) 72 | mindev: 1 73 | 74 | # ---- Debug Options ---- 75 | 76 | # Callgraph 77 | # gather detailed ftrace callgraph data on all timeline events (default: false) 78 | callgraph: true 79 | 80 | # Expand Callgraph 81 | # pre-expand the callgraph data in the html output (default: disabled) 82 | expandcg: false 83 | 84 | # Minimum Callgraph Length 85 | # provide callgraph data for blocks longer than min (default: 0.001 ms) 86 | mincg: 1 87 | 88 | # Timestamp Precision 89 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) 90 | timeprec: 6 91 | 92 | # Device Filter 93 | # show only devs whose name/driver includes one of these strings 94 | # devicefilter: _cpu_up,_cpu_down,i915,usb 95 | -------------------------------------------------------------------------------- /config/freeze-dev.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Dev S2 (Freeze) test - includes src calls / kernel threads 3 | # 4 | # This is the configuration file for sleepgraph. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. It also includes advanced settings for functions 7 | # and kprobes. It is run like this 8 | # 9 | # sudo ./sleepgraph.py -config config/freeze-dev.cfg 10 | # 11 | 12 | [Settings] 13 | 14 | # ---- General Options ---- 15 | 16 | # Verbosity 17 | # print verbose messages (default: false) 18 | verbose: false 19 | 20 | # Suspend Mode 21 | # e.g. standby, mem, freeze, disk (default: mem) 22 | mode: freeze 23 | 24 | # Output Directory Format 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values 26 | output-dir: freeze-{hostname}-{date}-{time}-dev 27 | 28 | # Automatic Wakeup 29 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) 30 | rtcwake: 15 31 | 32 | # Add Logs 33 | # add the dmesg and ftrace log to the html output (default: false) 34 | addlogs: false 35 | 36 | # Suspend/Resume Gap 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) 38 | srgap: false 39 | 40 | # ---- Advanced Options ---- 41 | 42 | # Command to execute in lieu of freeze (default: "") 43 | # command: echo freeze > /sys/power/state 44 | 45 | # Display user processes 46 | # graph user processes and cpu usage in the timeline (default: false) 47 | proc: false 48 | 49 | # Display function calls 50 | # graph source functions in the timeline (default: false) 51 | dev: true 52 | 53 | # Back to Back Suspend/Resume 54 | # Run two suspend/resumes back to back (default: false) 55 | x2: false 56 | 57 | # Back to Back Suspend Delay 58 | # Time delay between the two test runs in ms (default: 0 ms) 59 | x2delay: 0 60 | 61 | # Pre Suspend Delay 62 | # Include an N ms delay before (1st) suspend (default: 0 ms) 63 | predelay: 0 64 | 65 | # Post Resume Delay 66 | # Include an N ms delay after (last) resume (default: 0 ms) 67 | postdelay: 0 68 | 69 | # Minimum Device Length 70 | # graph only devices longer than min in the timeline (default: 0.001 ms) 71 | mindev: 1 72 | 73 | # ---- Debug Options ---- 74 | 75 | # Callgraph 76 | # gather detailed ftrace callgraph data on all timeline events (default: false) 77 | callgraph: false 78 | 79 | # Expand Callgraph 80 | # pre-expand the callgraph data in the html output (default: disabled) 81 | expandcg: false 82 | 83 | # Minimum Callgraph Length 84 | # provide callgraph data for blocks longer than min (default: 0.001 ms) 85 | mincg: 1 86 | 87 | # Timestamp Precision 88 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) 89 | timeprec: 3 90 | 91 | # Device Filter 92 | # show only devs whose name/driver includes one of these strings 93 | # devicefilter: _cpu_up,_cpu_down,i915,usb 94 | -------------------------------------------------------------------------------- /config/freeze.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Generic S2 (Freeze) test 3 | # 4 | # This is the configuration file for sleepgraph. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. It also includes advanced settings for functions 7 | # and kprobes. It is run like this 8 | # 9 | # sudo ./sleepgraph.py -config config/freeze.cfg 10 | # 11 | 12 | [Settings] 13 | 14 | # ---- General Options ---- 15 | 16 | # Verbosity 17 | # print verbose messages (default: false) 18 | verbose: false 19 | 20 | # Suspend Mode 21 | # e.g. standby, mem, freeze, disk (default: mem) 22 | mode: freeze 23 | 24 | # Output Directory Format 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values 26 | output-dir: freeze-{hostname}-{date}-{time} 27 | 28 | # Automatic Wakeup 29 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) 30 | rtcwake: 15 31 | 32 | # Add Logs 33 | # add the dmesg and ftrace log to the html output (default: false) 34 | addlogs: false 35 | 36 | # Suspend/Resume Gap 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) 38 | srgap: false 39 | 40 | # ---- Advanced Options ---- 41 | 42 | # Command to execute in lieu of freeze (default: "") 43 | # command: echo freeze > /sys/power/state 44 | 45 | # Display user processes 46 | # graph user processes and cpu usage in the timeline (default: false) 47 | proc: false 48 | 49 | # Display function calls 50 | # graph source functions in the timeline (default: false) 51 | dev: false 52 | 53 | # Back to Back Suspend/Resume 54 | # Run two suspend/resumes back to back (default: false) 55 | x2: false 56 | 57 | # Back to Back Suspend Delay 58 | # Time delay between the two test runs in ms (default: 0 ms) 59 | x2delay: 0 60 | 61 | # Pre Suspend Delay 62 | # Include an N ms delay before (1st) suspend (default: 0 ms) 63 | predelay: 0 64 | 65 | # Post Resume Delay 66 | # Include an N ms delay after (last) resume (default: 0 ms) 67 | postdelay: 0 68 | 69 | # Minimum Device Length 70 | # graph only devices longer than min in the timeline (default: 0.001 ms) 71 | mindev: 0.001 72 | 73 | # ---- Debug Options ---- 74 | 75 | # Callgraph 76 | # gather detailed ftrace callgraph data on all timeline events (default: false) 77 | callgraph: false 78 | 79 | # Expand Callgraph 80 | # pre-expand the callgraph data in the html output (default: disabled) 81 | expandcg: false 82 | 83 | # Minimum Callgraph Length 84 | # provide callgraph data for blocks longer than min (default: 0.001 ms) 85 | mincg: 1 86 | 87 | # Timestamp Precision 88 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) 89 | timeprec: 3 90 | 91 | # Device Filter 92 | # show only devs whose name/driver includes one of these strings 93 | # devicefilter: _cpu_up,_cpu_down,i915,usb 94 | -------------------------------------------------------------------------------- /config/netfix-otcpl.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Network Fixer Tool 3 | # 4 | # This is the configuration file for netfix.py. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. 7 | # 8 | # netfix.py -config config/netfix.cfg 9 | # 10 | 11 | [setup] 12 | 13 | # Wifi device name 14 | wifidev: wlp58s0 15 | 16 | # Kernel module for the wifi device 17 | wifidrv: iwlwifi 18 | 19 | # network name as defined by NetworkManager 20 | wifinet: LabWLAN 21 | -------------------------------------------------------------------------------- /config/netfix-tebrandt.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Network Fixer Tool 3 | # 4 | # This is the configuration file for netfix.py. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. 7 | # 8 | # netfix.py -config config/netfix.cfg 9 | # 10 | 11 | [setup] 12 | 13 | # Wifi device name 14 | wifidev: wlo1 15 | 16 | # Kernel module for the wifi device 17 | wifidrv: iwlwifi 18 | 19 | # network name as defined by NetworkManager 20 | wifinet: quaoar-max 21 | -------------------------------------------------------------------------------- /config/netfix.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Network Fixer Tool 3 | # 4 | # This is the configuration file for netfix.py. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. 7 | # 8 | # netfix.py -config config/netfix.cfg 9 | # 10 | 11 | [setup] 12 | 13 | # Wifi device name 14 | # wifidev: 15 | 16 | # Kernel module for the wifi device 17 | # wifidrv: 18 | 19 | # network name as defined by NetworkManager 20 | # wifinet: 21 | 22 | # Ethernet device name 23 | # ethdev: 24 | 25 | # USB Ethernet pci bus address (for dongles) 26 | # ethusb: 27 | 28 | # NetworkManager network name for ETH device 29 | # ethnet: 30 | 31 | # remote address to ping to check the connection 32 | # pingaddr: 33 | -------------------------------------------------------------------------------- /config/standby-callgraph.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Full Callgraph for S1 (Standby) test 3 | # 4 | # This is the configuration file for sleepgraph. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. It also includes advanced settings for functions 7 | # and kprobes. It is run like this 8 | # 9 | # sudo ./sleepgraph.py -config config/standby-callgraph.cfg 10 | # 11 | # NOTE: the output of this test is very large (> 30MB) 12 | 13 | [Settings] 14 | 15 | # ---- General Options ---- 16 | 17 | # Verbosity 18 | # print verbose messages (default: false) 19 | verbose: false 20 | 21 | # Suspend Mode 22 | # e.g. standby, mem, freeze, disk (default: mem) 23 | mode: standby 24 | 25 | # Output Directory Format 26 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values 27 | output-dir: standby-{hostname}-{date}-{time}-cg 28 | 29 | # Automatic Wakeup 30 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) 31 | rtcwake: 15 32 | 33 | # Add Logs 34 | # add the dmesg and ftrace log to the html output (default: false) 35 | addlogs: false 36 | 37 | # Suspend/Resume Gap 38 | # insert a small visible gap between suspend and resume on the timeline (default: false) 39 | srgap: false 40 | 41 | # ---- Advanced Options ---- 42 | 43 | # Command to execute in lieu of standby (default: "") 44 | # command: echo standby > /sys/power/state 45 | 46 | # Display user processes 47 | # graph user processes and cpu usage in the timeline (default: false) 48 | proc: false 49 | 50 | # Display function calls 51 | # graph source functions in the timeline (default: false) 52 | dev: false 53 | 54 | # Back to Back Suspend/Resume 55 | # Run two suspend/resumes back to back (default: false) 56 | x2: false 57 | 58 | # Back to Back Suspend Delay 59 | # Time delay between the two test runs in ms (default: 0 ms) 60 | x2delay: 0 61 | 62 | # Pre Suspend Delay 63 | # Include an N ms delay before (1st) suspend (default: 0 ms) 64 | predelay: 0 65 | 66 | # Post Resume Delay 67 | # Include an N ms delay after (last) resume (default: 0 ms) 68 | postdelay: 0 69 | 70 | # Minimum Device Length 71 | # graph only devices longer than min in the timeline (default: 0.001 ms) 72 | mindev: 1 73 | 74 | # ---- Debug Options ---- 75 | 76 | # Callgraph 77 | # gather detailed ftrace callgraph data on all timeline events (default: false) 78 | callgraph: true 79 | 80 | # Expand Callgraph 81 | # pre-expand the callgraph data in the html output (default: disabled) 82 | expandcg: false 83 | 84 | # Minimum Callgraph Length 85 | # provide callgraph data for blocks longer than min (default: 0.001 ms) 86 | mincg: 1 87 | 88 | # Timestamp Precision 89 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) 90 | timeprec: 6 91 | 92 | # Device Filter 93 | # show only devs whose name/driver includes one of these strings 94 | # devicefilter: _cpu_up,_cpu_down,i915,usb 95 | -------------------------------------------------------------------------------- /config/standby-dev.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Dev S1 (Standby) test - includes src calls / kernel threads 3 | # 4 | # This is the configuration file for sleepgraph. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. It also includes advanced settings for functions 7 | # and kprobes. It is run like this 8 | # 9 | # sudo ./sleepgraph.py -config config/standby-dev.cfg 10 | # 11 | 12 | [Settings] 13 | 14 | # ---- General Options ---- 15 | 16 | # Verbosity 17 | # print verbose messages (default: false) 18 | verbose: false 19 | 20 | # Suspend Mode 21 | # e.g. standby, mem, freeze, disk (default: mem) 22 | mode: standby 23 | 24 | # Output Directory Format 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values 26 | output-dir: standby-{hostname}-{date}-{time}-dev 27 | 28 | # Automatic Wakeup 29 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) 30 | rtcwake: 15 31 | 32 | # Add Logs 33 | # add the dmesg and ftrace log to the html output (default: false) 34 | addlogs: false 35 | 36 | # Suspend/Resume Gap 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) 38 | srgap: false 39 | 40 | # ---- Advanced Options ---- 41 | 42 | # Command to execute in lieu of standby (default: "") 43 | # command: echo standby > /sys/power/state 44 | 45 | # Display user processes 46 | # graph user processes and cpu usage in the timeline (default: false) 47 | proc: false 48 | 49 | # Display function calls 50 | # graph source functions in the timeline (default: false) 51 | dev: true 52 | 53 | # Back to Back Suspend/Resume 54 | # Run two suspend/resumes back to back (default: false) 55 | x2: false 56 | 57 | # Back to Back Suspend Delay 58 | # Time delay between the two test runs in ms (default: 0 ms) 59 | x2delay: 0 60 | 61 | # Pre Suspend Delay 62 | # Include an N ms delay before (1st) suspend (default: 0 ms) 63 | predelay: 0 64 | 65 | # Post Resume Delay 66 | # Include an N ms delay after (last) resume (default: 0 ms) 67 | postdelay: 0 68 | 69 | # Minimum Device Length 70 | # graph only devices longer than min in the timeline (default: 0.001 ms) 71 | mindev: 1 72 | 73 | # ---- Debug Options ---- 74 | 75 | # Callgraph 76 | # gather detailed ftrace callgraph data on all timeline events (default: false) 77 | callgraph: false 78 | 79 | # Expand Callgraph 80 | # pre-expand the callgraph data in the html output (default: disabled) 81 | expandcg: false 82 | 83 | # Minimum Callgraph Length 84 | # provide callgraph data for blocks longer than min (default: 0.001 ms) 85 | mincg: 1 86 | 87 | # Timestamp Precision 88 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) 89 | timeprec: 3 90 | 91 | # Device Filter 92 | # show only devs whose name/driver includes one of these strings 93 | # devicefilter: _cpu_up,_cpu_down,i915,usb 94 | -------------------------------------------------------------------------------- /config/standby.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Generic S1 (Standby) test 3 | # 4 | # This is the configuration file for sleepgraph. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. It also includes advanced settings for functions 7 | # and kprobes. It is run like this 8 | # 9 | # sudo ./sleepgraph.py -config config/standby.cfg 10 | # 11 | 12 | [Settings] 13 | 14 | # ---- General Options ---- 15 | 16 | # Verbosity 17 | # print verbose messages (default: false) 18 | verbose: false 19 | 20 | # Suspend Mode 21 | # e.g. standby, mem, freeze, disk (default: mem) 22 | mode: standby 23 | 24 | # Output Directory Format 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values 26 | output-dir: standby-{hostname}-{date}-{time} 27 | 28 | # Automatic Wakeup 29 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) 30 | rtcwake: 15 31 | 32 | # Add Logs 33 | # add the dmesg and ftrace log to the html output (default: false) 34 | addlogs: false 35 | 36 | # Suspend/Resume Gap 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) 38 | srgap: false 39 | 40 | # ---- Advanced Options ---- 41 | 42 | # Command to execute in lieu of standby (default: "") 43 | # command: echo standby > /sys/power/state 44 | 45 | # Display user processes 46 | # graph user processes and cpu usage in the timeline (default: false) 47 | proc: false 48 | 49 | # Display function calls 50 | # graph source functions in the timeline (default: false) 51 | dev: false 52 | 53 | # Back to Back Suspend/Resume 54 | # Run two suspend/resumes back to back (default: false) 55 | x2: false 56 | 57 | # Back to Back Suspend Delay 58 | # Time delay between the two test runs in ms (default: 0 ms) 59 | x2delay: 0 60 | 61 | # Pre Suspend Delay 62 | # Include an N ms delay before (1st) suspend (default: 0 ms) 63 | predelay: 0 64 | 65 | # Post Resume Delay 66 | # Include an N ms delay after (last) resume (default: 0 ms) 67 | postdelay: 0 68 | 69 | # Minimum Device Length 70 | # graph only devices longer than min in the timeline (default: 0.001 ms) 71 | mindev: 0.001 72 | 73 | # ---- Debug Options ---- 74 | 75 | # Callgraph 76 | # gather detailed ftrace callgraph data on all timeline events (default: false) 77 | callgraph: false 78 | 79 | # Expand Callgraph 80 | # pre-expand the callgraph data in the html output (default: disabled) 81 | expandcg: false 82 | 83 | # Minimum Callgraph Length 84 | # provide callgraph data for blocks longer than min (default: 0.001 ms) 85 | mincg: 1 86 | 87 | # Timestamp Precision 88 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) 89 | timeprec: 3 90 | 91 | # Device Filter 92 | # show only devs whose name/driver includes one of these strings 93 | # devicefilter: _cpu_up,_cpu_down,i915,usb 94 | -------------------------------------------------------------------------------- /config/stresstest-intel-local.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Sleepgraph stress testing 3 | # 4 | # This is the configuration file for stresssetup.py. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. 7 | # 8 | # stresssetup.py -config config/stresstest-intel.cfg 9 | # 10 | 11 | [setup] 12 | 13 | # Kernel package format 14 | # Set kernel package format [deb/rpm] (default: deb) 15 | pkgfmt: deb 16 | 17 | # Kernel package output folder 18 | # Place build output files here (default: ksrc/..) 19 | pkgout: ~/workspace/packages 20 | 21 | # Kernel source 22 | # Kernel source folder location (default: required to build) 23 | #ksrc: ~/workspace/linux 24 | 25 | # Kernel name 26 | # Set kernel name to - (default: blank) 27 | kname: 28 | 29 | # Kernel config folder 30 | # Folder with config file and patches to apply to ksrc (default: no change) 31 | kcfg: ~/workspace/stressconfig 32 | 33 | # Kernel git tag 34 | # If ksrc is a git repo, set to this tag (default: no change) 35 | # Used "latestrc" to select the newest release candidate 36 | ktag: latestrc 37 | 38 | # remove kernels 39 | # These are the kernels we want removed prior to install 40 | rmkernel: [1-9]\.[0-9]*\.[0-9]*-rc[0-9]*\-dirty 41 | 42 | # Machines file 43 | # Text file with list of machine/ip values for testing 44 | # Lines will be prepended with status as setup/test occurs 45 | machines: ~/workspace/stressconfig/machine.txt 46 | 47 | # Test output folder 48 | # Place test output files and logs here (required for run/status) 49 | testout: /media/zeus/pm-graph-test 50 | -------------------------------------------------------------------------------- /config/stresstest-intel.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Sleepgraph stress testing 3 | # 4 | # This is the configuration file for stresssetup.py. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. 7 | # 8 | # stresssetup.py -config config/stresstest-intel.cfg 9 | # 10 | 11 | [setup] 12 | 13 | # Kernel package format 14 | # Set kernel package format [deb/rpm] (default: deb) 15 | pkgfmt: deb 16 | 17 | # Kernel package output folder 18 | # Place build output files here (default: ksrc/..) 19 | pkgout: ~/workspace/packages 20 | 21 | # Kernel source 22 | # Kernel source folder location (default: required to build) 23 | ksrc: ~/workspace/linux 24 | 25 | # Kernel name 26 | # Set kernel name to - (default: blank) 27 | kname: 28 | 29 | # Kernel config folder 30 | # Folder with config file and patches to apply to ksrc (default: no change) 31 | kcfg: ~/workspace/stressconfig 32 | 33 | # Kernel git tag 34 | # If ksrc is a git repo, set to this tag (default: no change) 35 | # Used "latestrc" to select the newest release candidate 36 | ktag: latestrc 37 | 38 | # remove kernels 39 | # These are the kernels we want removed prior to install 40 | rmkernel: [1-9]\.[0-9]*\.[0-9]*-rc[0-9]*\-dirty 41 | 42 | # Machines file 43 | # Text file with list of machine/ip values for testing 44 | # Lines will be prepended with status as setup/test occurs 45 | machines: ~/workspace/stressconfig/machine.txt 46 | 47 | # Network Proxy 48 | # http_proxy to use when accessing the net on targets (default: none) 49 | proxy: http://proxy-dmz.intel.com:911/ 50 | 51 | # Reset Command 52 | # command to call to reset a machine given: host, user, addr. 53 | resetcmd: labmachine -m {host} restart -u sleepgraph 54 | 55 | # Power Down Command 56 | # command to power on a machine given: host, user, addr. 57 | offcmd: labmachine -m {host} off -u sleepgraph 58 | 59 | # Power On Command 60 | # command to call powr down a machine given: host, user, addr. 61 | oncmd: labmachine -m {host} on -u sleepgraph 62 | 63 | # Reserve Command 64 | # command to call to reserve a machine given: host, user, addr, minutes. 65 | reservecmd: labmachine -m {host} -u sleepgraph reserve:{minutes} 66 | 67 | # Release Command 68 | # command to call to release a machine given: host, user, addr. 69 | releasecmd: labmachine -m {host} -u sleepgraph release 70 | 71 | # Data collection start Command 72 | # command to start gathering data on a machine given: host, user, addr. 73 | dstartcmd: labmachine -m {host} -u sleepgraph serialon 74 | 75 | # Data collection stop and download Command 76 | # command to stop and download data on a machine given: host, user, addr. 77 | dstopcmd: labmachine -m {host} -u sleepgraph -f {file} serialoff 78 | 79 | # Test output folder 80 | # Place test output files and logs here (required for run/status) 81 | testout: /srv/pm-graph-test 82 | -------------------------------------------------------------------------------- /config/suspend-callgraph.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Full Callgraph for S3 (Suspend to Mem) test 3 | # 4 | # This is the configuration file for sleepgraph. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. It also includes advanced settings for functions 7 | # and kprobes. It is run like this 8 | # 9 | # sudo ./sleepgraph.py -config config/suspend.cfg 10 | # 11 | # NOTE: the output of this test is very large (> 30MB) 12 | 13 | [Settings] 14 | 15 | # ---- General Options ---- 16 | 17 | # Verbosity 18 | # print verbose messages (default: false) 19 | verbose: false 20 | 21 | # Suspend Mode 22 | # e.g. standby, mem, freeze, disk (default: mem) 23 | mode: mem 24 | 25 | # Output Directory Format 26 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values 27 | output-dir: suspend-{hostname}-{date}-{time}-cg 28 | 29 | # Automatic Wakeup 30 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) 31 | rtcwake: 15 32 | 33 | # Add Logs 34 | # add the dmesg and ftrace log to the html output (default: false) 35 | addlogs: false 36 | 37 | # Suspend/Resume Gap 38 | # insert a small visible gap between suspend and resume on the timeline (default: false) 39 | srgap: false 40 | 41 | # ---- Advanced Options ---- 42 | 43 | # Command to execute in lieu of suspend (default: "") 44 | # command: echo mem > /sys/power/state 45 | 46 | # Display user processes 47 | # graph user processes and cpu usage in the timeline (default: false) 48 | proc: false 49 | 50 | # Display function calls 51 | # graph source functions in the timeline (default: false) 52 | dev: false 53 | 54 | # Back to Back Suspend/Resume 55 | # Run two suspend/resumes back to back (default: false) 56 | x2: false 57 | 58 | # Back to Back Suspend Delay 59 | # Time delay between the two test runs in ms (default: 0 ms) 60 | x2delay: 0 61 | 62 | # Pre Suspend Delay 63 | # Include an N ms delay before (1st) suspend (default: 0 ms) 64 | predelay: 0 65 | 66 | # Post Resume Delay 67 | # Include an N ms delay after (last) resume (default: 0 ms) 68 | postdelay: 0 69 | 70 | # Minimum Device Length 71 | # graph only devices longer than min in the timeline (default: 0.001 ms) 72 | mindev: 0.001 73 | 74 | # ---- Debug Options ---- 75 | 76 | # Callgraph 77 | # gather detailed ftrace callgraph data on all timeline events (default: false) 78 | callgraph: true 79 | 80 | # Max graph depth 81 | # limit the callgraph trace to this depth (default: 0 = all) 82 | maxdepth: 5 83 | 84 | # Expand Callgraph 85 | # pre-expand the callgraph data in the html output (default: disabled) 86 | expandcg: false 87 | 88 | # Minimum Callgraph Length 89 | # provide callgraph data for blocks longer than min (default: 0.001 ms) 90 | mincg: 1 91 | 92 | # Timestamp Precision 93 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) 94 | timeprec: 6 95 | 96 | # Device Filter 97 | # show only devs whose name/driver includes one of these strings 98 | # devicefilter: _cpu_up,_cpu_down,i915,usb 99 | -------------------------------------------------------------------------------- /config/suspend-dev.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Dev S3 (Suspend to Mem) test - includes src calls / kernel threads 3 | # 4 | # This is the configuration file for sleepgraph. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. It also includes advanced settings for functions 7 | # and kprobes. It is run like this 8 | # 9 | # sudo ./sleepgraph.py -config config/suspend-dev.cfg 10 | # 11 | 12 | [Settings] 13 | 14 | # ---- General Options ---- 15 | 16 | # Verbosity 17 | # print verbose messages (default: false) 18 | verbose: false 19 | 20 | # Suspend Mode 21 | # e.g. standby, mem, freeze, disk (default: mem) 22 | mode: mem 23 | 24 | # Output Directory Format 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values 26 | output-dir: suspend-{hostname}-{date}-{time}-dev 27 | 28 | # Automatic Wakeup 29 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) 30 | rtcwake: 15 31 | 32 | # Add Logs 33 | # add the dmesg and ftrace log to the html output (default: false) 34 | addlogs: false 35 | 36 | # Suspend/Resume Gap 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) 38 | srgap: false 39 | 40 | # ---- Advanced Options ---- 41 | 42 | # Command to execute in lieu of suspend (default: "") 43 | # command: echo mem > /sys/power/state 44 | 45 | # Display user processes 46 | # graph user processes and cpu usage in the timeline (default: false) 47 | proc: false 48 | 49 | # Display function calls 50 | # graph source functions in the timeline (default: false) 51 | dev: true 52 | 53 | # Back to Back Suspend/Resume 54 | # Run two suspend/resumes back to back (default: false) 55 | x2: false 56 | 57 | # Back to Back Suspend Delay 58 | # Time delay between the two test runs in ms (default: 0 ms) 59 | x2delay: 0 60 | 61 | # Pre Suspend Delay 62 | # Include an N ms delay before (1st) suspend (default: 0 ms) 63 | predelay: 0 64 | 65 | # Post Resume Delay 66 | # Include an N ms delay after (last) resume (default: 0 ms) 67 | postdelay: 0 68 | 69 | # Minimum Device Length 70 | # graph only devices longer than min in the timeline (default: 0.001 ms) 71 | mindev: 1 72 | 73 | # ---- Debug Options ---- 74 | 75 | # Callgraph 76 | # gather detailed ftrace callgraph data on all timeline events (default: false) 77 | callgraph: false 78 | 79 | # Expand Callgraph 80 | # pre-expand the callgraph data in the html output (default: disabled) 81 | expandcg: false 82 | 83 | # Minimum Callgraph Length 84 | # provide callgraph data for blocks longer than min (default: 0.001 ms) 85 | mincg: 1 86 | 87 | # Timestamp Precision 88 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) 89 | timeprec: 3 90 | 91 | # Device Filter 92 | # show only devs whose name/driver includes one of these strings 93 | # devicefilter: _cpu_up,_cpu_down,i915,usb 94 | -------------------------------------------------------------------------------- /config/suspend-x2-proc.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Proc S3 (Suspend to Mem) x2 test - includes user processes 3 | # 4 | # This is the configuration file for sleepgraph. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. It also includes advanced settings for functions 7 | # and kprobes. It is run like this 8 | # 9 | # sudo ./sleepgraph.py -config config/suspend-proc.cfg 10 | # 11 | 12 | [Settings] 13 | 14 | # ---- General Options ---- 15 | 16 | # Verbosity 17 | # print verbose messages (default: false) 18 | verbose: false 19 | 20 | # Suspend Mode 21 | # e.g. standby, mem, freeze, disk (default: mem) 22 | mode: mem 23 | 24 | # Output Directory Format 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values 26 | output-dir: suspend-{hostname}-{date}-{time}-x2-proc 27 | 28 | # Automatic Wakeup 29 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) 30 | rtcwake: 15 31 | 32 | # Add Logs 33 | # add the dmesg and ftrace log to the html output (default: false) 34 | addlogs: false 35 | 36 | # Suspend/Resume Gap 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) 38 | srgap: false 39 | 40 | # ---- Advanced Options ---- 41 | 42 | # Command to execute in lieu of suspend (default: "") 43 | # command: echo mem > /sys/power/state 44 | 45 | # Display user processes 46 | # graph user processes and cpu usage in the timeline (default: false) 47 | proc: true 48 | 49 | # Display function calls 50 | # graph source functions in the timeline (default: false) 51 | dev: false 52 | 53 | # Back to Back Suspend/Resume 54 | # Run two suspend/resumes back to back (default: false) 55 | x2: true 56 | 57 | # Back to Back Suspend Delay 58 | # Time delay between the two test runs in ms (default: 0 ms) 59 | x2delay: 1000 60 | 61 | # Pre Suspend Delay 62 | # Include an N ms delay before (1st) suspend (default: 0 ms) 63 | predelay: 1000 64 | 65 | # Post Resume Delay 66 | # Include an N ms delay after (last) resume (default: 0 ms) 67 | postdelay: 1000 68 | 69 | # Minimum Device Length 70 | # graph only devices longer than min in the timeline (default: 0.001 ms) 71 | mindev: 1 72 | 73 | # ---- Debug Options ---- 74 | 75 | # Callgraph 76 | # gather detailed ftrace callgraph data on all timeline events (default: false) 77 | callgraph: false 78 | 79 | # Expand Callgraph 80 | # pre-expand the callgraph data in the html output (default: disabled) 81 | expandcg: false 82 | 83 | # Minimum Callgraph Length 84 | # provide callgraph data for blocks longer than min (default: 0.001 ms) 85 | mincg: 1 86 | 87 | # Timestamp Precision 88 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) 89 | timeprec: 3 90 | 91 | # Device Filter 92 | # show only devs whose name/driver includes one of these strings 93 | # devicefilter: _cpu_up,_cpu_down,i915,usb 94 | -------------------------------------------------------------------------------- /config/suspend.cfg: -------------------------------------------------------------------------------- 1 | # 2 | # Generic S3 (Suspend to Mem) test 3 | # 4 | # This is the configuration file for sleepgraph. It contains 5 | # all the tool arguments so that they don't have to be given on the 6 | # command line. It also includes advanced settings for functions 7 | # and kprobes. It is run like this 8 | # 9 | # sudo ./sleepgraph.py -config config/suspend.cfg 10 | # 11 | 12 | [Settings] 13 | 14 | # ---- General Options ---- 15 | 16 | # Verbosity 17 | # print verbose messages (default: false) 18 | verbose: false 19 | 20 | # Suspend Mode 21 | # e.g. standby, mem, freeze, disk (default: mem) 22 | mode: mem 23 | 24 | # Output Directory Format 25 | # output folder for html, ftrace, and dmesg. Use {date} and {time} for current values 26 | output-dir: suspend-{hostname}-{date}-{time} 27 | 28 | # Automatic Wakeup 29 | # Use rtcwake to autoresume after X seconds, or off to disable (default: 15) 30 | rtcwake: 15 31 | 32 | # Add Logs 33 | # add the dmesg and ftrace log to the html output (default: false) 34 | addlogs: false 35 | 36 | # Suspend/Resume Gap 37 | # insert a small visible gap between suspend and resume on the timeline (default: false) 38 | srgap: false 39 | 40 | # ---- Advanced Options ---- 41 | 42 | # Command to execute in lieu of suspend (default: "") 43 | # command: echo mem > /sys/power/state 44 | 45 | # Display user processes 46 | # graph user processes and cpu usage in the timeline (default: false) 47 | proc: false 48 | 49 | # Display function calls 50 | # graph source functions in the timeline (default: false) 51 | dev: false 52 | 53 | # Back to Back Suspend/Resume 54 | # Run two suspend/resumes back to back (default: false) 55 | x2: false 56 | 57 | # Back to Back Suspend Delay 58 | # Time delay between the two test runs in ms (default: 0 ms) 59 | x2delay: 0 60 | 61 | # Pre Suspend Delay 62 | # Include an N ms delay before (1st) suspend (default: 0 ms) 63 | predelay: 0 64 | 65 | # Post Resume Delay 66 | # Include an N ms delay after (last) resume (default: 0 ms) 67 | postdelay: 0 68 | 69 | # Minimum Device Length 70 | # graph only devices longer than min in the timeline (default: 0.001 ms) 71 | mindev: 0.001 72 | 73 | # ---- Debug Options ---- 74 | 75 | # Callgraph 76 | # gather detailed ftrace callgraph data on all timeline events (default: false) 77 | callgraph: false 78 | 79 | # Expand Callgraph 80 | # pre-expand the callgraph data in the html output (default: disabled) 81 | expandcg: false 82 | 83 | # Minimum Callgraph Length 84 | # provide callgraph data for blocks longer than min (default: 0.001 ms) 85 | mincg: 1 86 | 87 | # Timestamp Precision 88 | # Number of significant digits in timestamps (0:S, [3:ms], 6:us) 89 | timeprec: 3 90 | 91 | # Device Filter 92 | # show only devs whose name/driver includes one of these strings 93 | # devicefilter: _cpu_up,_cpu_down,i915,usb 94 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | pm-graph (5.8-1) bionic; urgency=medium 2 | 3 | * update to 5.8 4 | 5 | -- Todd Brandt Tue, Nov 10 2020 18:10:21 -0800 6 | 7 | pm-graph (5.7-1) bionic; urgency=medium 8 | 9 | * update to 5.7 10 | 11 | -- Todd Brandt Mon, Jul 20 2020 17:54:13 -0700 12 | 13 | pm-graph (5.6-1) artful; urgency=medium 14 | 15 | * update to 5.6 16 | 17 | -- Todd Brandt Tue, 22 Oct 2019 10:53:52 -0800 18 | 19 | pm-graph (4.8-1) artful; urgency=medium 20 | 21 | * update to 4.8 22 | 23 | -- Todd Brandt Wed, 22 Nov 2017 06:13:52 -0800 24 | 25 | pm-graph (4.7-1) zesty; urgency=medium 26 | 27 | * update to 4.7 28 | 29 | -- Todd Brandt Wed, 05 Jul 2017 14:43:48 -0700 30 | 31 | pm-graph (4.6-1) xenial; urgency=medium 32 | 33 | * Initial release. 34 | 35 | -- Todd Brandt Wed, 05 Apr 2017 11:32:41 -0700 36 | -------------------------------------------------------------------------------- /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: pm-graph 2 | Section: admin 3 | Priority: extra 4 | Maintainer: Todd Brandt 5 | Build-Depends: cdbs (>= 0.4.49), 6 | debhelper (>= 9), 7 | dh-python, 8 | python3-all:any 9 | Standards-Version: 3.9.6 10 | X-Python3-Version: >= 3.2 11 | Homepage: https://github.com/intel/pm-graph 12 | 13 | Package: pm-graph 14 | Architecture: i386 amd64 15 | Depends: ${misc:Depends}, 16 | ${python3:Depends}, 17 | python3-requests 18 | Description: Power Management performance analysis 19 | This package is designed to assist kernel and OS developers in optimizing 20 | their linux stack's boot and suspend/resume time. It includes two tools: 21 | bootgraph and sleepgraph, which use dmesg and ftrace data to create 22 | timelines of kernel boot and suspend/resume respectively. The timelines 23 | provide a detailed view of which devices/subsystems are taking the most 24 | time in boot and suspend/resume. 25 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | pm-graph - Tool for analyzing suspend/resume timing 2 | Debianized by Todd Brandt on 24 Mar 2017. 3 | 4 | Home Page: https://www.intel.com/content/www/us/en/developer/topic-technology/open/pm-graph/overview.html 5 | Source repo: https://github.com/intel/pm-graph 6 | 7 | Authors: 8 | Todd Brandt 9 | 10 | Copyright: 11 | Copyright (c) 2013, Intel Corporation. 12 | 13 | License: 14 | This program is free software; you can redistribute it and/or modify it 15 | under the terms and conditions of the GNU General Public License, 16 | version 2, as published by the Free Software Foundation. 17 | 18 | This program is distributed in the hope it will be useful, but WITHOUT 19 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 20 | FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 21 | more details. 22 | 23 | You should have received a copy of the GNU General Public License along with 24 | this program; if not, write to the Free Software Foundation, Inc., 25 | 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. 26 | 27 | On Debian systems, the complete text of the GNU General 28 | Public License can be found in `/usr/share/common-licenses/GPL-2'. 29 | -------------------------------------------------------------------------------- /debian/docs: -------------------------------------------------------------------------------- 1 | README 2 | -------------------------------------------------------------------------------- /debian/pm-graph.links: -------------------------------------------------------------------------------- 1 | /usr/lib/pm-graph/bootgraph.py /usr/bin/bootgraph 2 | /usr/lib/pm-graph/sleepgraph.py /usr/bin/sleepgraph 3 | -------------------------------------------------------------------------------- /debian/pm-graph.manpages: -------------------------------------------------------------------------------- 1 | bootgraph.8 2 | sleepgraph.8 3 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | include /usr/share/cdbs/1/rules/debhelper.mk 4 | 5 | install/pm-graph:: 6 | install -d -o root -g root -m 755 \ 7 | $(DEB_DESTDIR)/usr/lib/pm-graph 8 | install -D -o root -g root -m 755 sleepgraph.py \ 9 | $(DEB_DESTDIR)/usr/lib/pm-graph/sleepgraph.py 10 | install -D -o root -g root -m 755 bootgraph.py \ 11 | $(DEB_DESTDIR)/usr/lib/pm-graph/bootgraph.py 12 | install -d -o root -g root -m 755 \ 13 | $(DEB_DESTDIR)/usr/lib/pm-graph/config 14 | install -D -o root -g root -m 644 config/cgskip.txt \ 15 | $(DEB_DESTDIR)/usr/lib/pm-graph/config/cgskip.txt 16 | install -D -o root -g root -m 644 config/freeze-callgraph.cfg \ 17 | $(DEB_DESTDIR)/usr/lib/pm-graph/config/freeze-callgraph.cfg 18 | install -D -o root -g root -m 644 config/freeze.cfg \ 19 | $(DEB_DESTDIR)/usr/lib/pm-graph/config/freeze.cfg 20 | install -D -o root -g root -m 644 config/freeze-dev.cfg \ 21 | $(DEB_DESTDIR)/usr/lib/pm-graph/config/freeze-dev.cfg 22 | install -D -o root -g root -m 644 config/standby-callgraph.cfg \ 23 | $(DEB_DESTDIR)/usr/lib/pm-graph/config/standby-callgraph.cfg 24 | install -D -o root -g root -m 644 config/standby.cfg \ 25 | $(DEB_DESTDIR)/usr/lib/pm-graph/config/standby.cfg 26 | install -D -o root -g root -m 644 config/standby-dev.cfg \ 27 | $(DEB_DESTDIR)/usr/lib/pm-graph/config/standby-dev.cfg 28 | install -D -o root -g root -m 644 config/suspend-callgraph.cfg \ 29 | $(DEB_DESTDIR)/usr/lib/pm-graph/config/suspend-callgraph.cfg 30 | install -D -o root -g root -m 644 config/suspend.cfg \ 31 | $(DEB_DESTDIR)/usr/lib/pm-graph/config/suspend.cfg 32 | install -D -o root -g root -m 644 config/suspend-dev.cfg \ 33 | $(DEB_DESTDIR)/usr/lib/pm-graph/config/suspend-dev.cfg 34 | install -D -o root -g root -m 644 config/suspend-x2-proc.cfg \ 35 | $(DEB_DESTDIR)/usr/lib/pm-graph/config/suspend-x2-proc.cfg 36 | 37 | binary-install/pm-graph:: 38 | dh_python3 -p$(cdbs_curpkg) 39 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /debian/source/options: -------------------------------------------------------------------------------- 1 | diff-ignore = ".git|autotest|config|dev|devtest|kernel|tools" 2 | -------------------------------------------------------------------------------- /dev/0003-ata-skip-resume-for-ata-port.patch: -------------------------------------------------------------------------------- 1 | From 5ae666a4f6c4f4db9c78205c4308c94c0bb8b9a9 Mon Sep 17 00:00:00 2001 2 | From: Aaron Lu 3 | Date: Tue, 4 Jun 2013 15:03:36 +0800 4 | Subject: [PATCH 4/4] ata: skip resume for ata port 5 | 6 | To realize fast resume for hard disks, the ata port's device will also 7 | need to be set the newly introduced skip_resume flag. 8 | 9 | Signed-off-by: Aaron Lu 10 | --- 11 | drivers/ata/libata-transport.c | 1 + 12 | 1 file changed, 1 insertion(+) 13 | 14 | diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c 15 | index c04d393..ff62316 100644 16 | --- a/drivers/ata/libata-transport.c 17 | +++ b/drivers/ata/libata-transport.c 18 | @@ -295,6 +295,7 @@ int ata_tport_add(struct device *parent, 19 | pm_runtime_set_active(dev); 20 | pm_runtime_enable(dev); 21 | pm_runtime_forbid(dev); 22 | + device_pm_skip_resume(dev, true); 23 | 24 | transport_add_device(dev); 25 | transport_configure_device(dev); 26 | -- 27 | 1.8.3.3.gfada522 28 | 29 | -------------------------------------------------------------------------------- /dev/ata_resume_async.patch: -------------------------------------------------------------------------------- 1 | Signed-off-by: Todd Brandt 2 | 3 | diff --git a/block/genhd.c b/block/genhd.c 4 | index 7dcfdd8..3825d45 100644 5 | --- a/block/genhd.c 6 | +++ b/block/genhd.c 7 | @@ -525,6 +525,8 @@ static void register_disk(struct gendisk *disk) 8 | /* delay uevents, until we scanned partition table */ 9 | dev_set_uevent_suppress(ddev, 1); 10 | 11 | + device_enable_async_suspend(ddev); 12 | + 13 | if (device_add(ddev)) 14 | return; 15 | if (!sysfs_deprecated) { 16 | diff --git a/block/partition-generic.c b/block/partition-generic.c 17 | index 1cb4dec..7f136d1 100644 18 | --- a/block/partition-generic.c 19 | +++ b/block/partition-generic.c 20 | @@ -325,6 +325,7 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, 21 | pdev->class = &block_class; 22 | pdev->type = &part_type; 23 | pdev->parent = ddev; 24 | + pdev->power.async_suspend = true; 25 | 26 | err = blk_alloc_devt(p, &devt); 27 | if (err) 28 | diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c 29 | index c04d393..493f5ce 100644 30 | --- a/drivers/ata/libata-transport.c 31 | +++ b/drivers/ata/libata-transport.c 32 | @@ -285,13 +285,13 @@ int ata_tport_add(struct device *parent, 33 | dev->parent = get_device(parent); 34 | dev->release = ata_tport_release; 35 | dev_set_name(dev, "ata%d", ap->print_id); 36 | + device_enable_async_suspend(dev); 37 | transport_setup_device(dev); 38 | error = device_add(dev); 39 | if (error) { 40 | goto tport_err; 41 | } 42 | 43 | - device_enable_async_suspend(dev); 44 | pm_runtime_set_active(dev); 45 | pm_runtime_enable(dev); 46 | pm_runtime_forbid(dev); 47 | @@ -414,6 +414,7 @@ int ata_tlink_add(struct ata_link *link) 48 | else 49 | dev_set_name(dev, "link%d.%d", ap->print_id, link->pmp); 50 | 51 | + device_enable_async_suspend(dev); 52 | transport_setup_device(dev); 53 | 54 | error = device_add(dev); 55 | @@ -642,6 +643,7 @@ static int ata_tdev_add(struct ata_device *ata_dev) 56 | else 57 | dev_set_name(dev, "dev%d.%d.0", ap->print_id, link->pmp); 58 | 59 | + device_enable_async_suspend(dev); 60 | transport_setup_device(dev); 61 | error = device_add(dev); 62 | if (error) { 63 | diff --git a/drivers/base/attribute_container.c b/drivers/base/attribute_container.c 64 | index d78b204..7209b6e 100644 65 | --- a/drivers/base/attribute_container.c 66 | +++ b/drivers/base/attribute_container.c 67 | @@ -349,6 +349,7 @@ attribute_container_add_attrs(struct device *classdev) 68 | int 69 | attribute_container_add_class_device(struct device *classdev) 70 | { 71 | + classdev->power.async_suspend = true; 72 | int error = device_add(classdev); 73 | if (error) 74 | return error; 75 | diff --git a/drivers/base/core.c b/drivers/base/core.c 76 | index a235085..07fb818 100644 77 | --- a/drivers/base/core.c 78 | +++ b/drivers/base/core.c 79 | @@ -1020,7 +1020,8 @@ int device_add(struct device *dev) 80 | goto name_error; 81 | } 82 | 83 | - pr_debug("device: '%s': %s\n", dev_name(dev), __func__); 84 | + pr_debug("device: '%s': %s, %s suspend\n", dev_name(dev), __func__, 85 | + (dev->power.async_suspend) ? "async" : "sync"); 86 | 87 | parent = get_device(dev->parent); 88 | kobj = get_device_parent(dev, parent); 89 | @@ -1558,6 +1559,11 @@ struct device *device_create_vargs(struct class *class, struct device *parent, 90 | goto error; 91 | } 92 | 93 | + if (parent) 94 | + dev->power.async_suspend = parent->power.async_suspend; 95 | + else 96 | + dev->power.async_suspend = true; 97 | + 98 | dev->devt = devt; 99 | dev->class = class; 100 | dev->parent = parent; 101 | diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c 102 | index 931a7d9..22b5a5a 100644 103 | --- a/drivers/scsi/scsi_sysfs.c 104 | +++ b/drivers/scsi/scsi_sysfs.c 105 | @@ -838,6 +838,7 @@ static int scsi_target_add(struct scsi_target *starget) 106 | if (starget->state != STARGET_CREATED) 107 | return 0; 108 | 109 | + device_enable_async_suspend(&starget->dev); 110 | error = device_add(&starget->dev); 111 | if (error) { 112 | dev_err(&starget->dev, "target device_add failed, error %d\n", error); 113 | @@ -848,7 +849,6 @@ static int scsi_target_add(struct scsi_target *starget) 114 | 115 | pm_runtime_set_active(&starget->dev); 116 | pm_runtime_enable(&starget->dev); 117 | - device_enable_async_suspend(&starget->dev); 118 | 119 | return 0; 120 | } 121 | diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c 122 | index 7992635..3a412ea 100644 123 | --- a/drivers/scsi/sd.c 124 | +++ b/drivers/scsi/sd.c 125 | @@ -2924,6 +2924,9 @@ static int sd_probe(struct device *dev) 126 | sdkp->dev.class = &sd_disk_class; 127 | dev_set_name(&sdkp->dev, dev_name(dev)); 128 | 129 | + if (dev) 130 | + sdkp->dev.power.async_suspend = dev->power.async_suspend; 131 | + 132 | if (device_add(&sdkp->dev)) 133 | goto out_free_index; 134 | 135 | -------------------------------------------------------------------------------- /dev/hard-disk-resume/mail0.txt: -------------------------------------------------------------------------------- 1 | This patch reduces S3 resume time from 10+ seconds to less than a second 2 | on systems with SATA drives. It does this by making ata port and scsi disk 3 | resume non-blocking. 4 | 5 | This is v4, sent in response to Tejun Huo's comments and with some small 6 | fixes made after testing. 7 | 8 | OVERVIEW 9 | 10 | The essential issue behind hard disks' lengthy resume time is the ata port 11 | driver blocking until the ATA port hardware is finished coming online. So 12 | the kernel isn't really doing anything during all those seconds that the 13 | disks are resuming, it's just blocking until the hardware says it's ready 14 | to accept commands. Applying this patch set allows SATA disks to resume 15 | asynchronously without holding up system resume, thus allowing the UI to 16 | come online much more quickly. There may be a short period after resume 17 | where the disks are still spinning up in the background, but it will only 18 | momentarily affect applications using that disk. 19 | 20 | The patch set has two parts which apply to ata_port_resume and sd_resume 21 | respectively. Both are required to achieve any real performance benefit, 22 | but they will still function independantly without a performance hit. 23 | 24 | PERFORMANCE DATA 25 | 26 | [Computer One Test - 10.5X speedup on S3 resume] 27 | Platform: Ubuntu Raring Ringtail (13.04) kernel 3.11.0-rc7 28 | Cpu: Intel(R) Core(TM) i7-3960X CPU @ 3.30GHz 29 | Ahci: Intel C600/X79 series chipset 6-Port SATA AHCI (r5) 30 | Disk config (using all 6 ahci ports): 31 | 240 GB SSD, 3 TB HD, 500 GB HD, DVD-ROM (with cd inserted), 2 TB HD, 1 TB HD 32 | Resume time: [unpatched 11656ms] [patched 1110ms] 33 | 34 | [Computer Two Test - 12X speedup on S3 resume] 35 | Platform: Ubuntu Raring Ringtail (13.04) kernel 3.11.0-rc7 36 | Cpu: Intel(R) Core(TM) i7-3770 CPU @ 3.40GHz 37 | Ahci: Intel 7 Series/C210 Series Chipset Family 6-port SATA [AHCI mode] (r4) 38 | Disk config (using 1 ahci port): 320 GB Hard Disk 39 | Resume time: [unpatched 5416 ms] [patched 448 ms] 40 | 41 | [Computer Three Test - 7.8X speedup on S3 resume] 42 | Platform: Ubuntu Raring Ringtail (13.04) kernel 3.11.0-rc7 43 | Cpu: Intel(R) Core(TM) i7-4770S CPU @ 3.10GHz 44 | Ahci: Intel Lynx Point 6-port SATA Controller 1 [AHCI mode] (r2) 45 | Disk config (using 2 ahci ports): DVD-ROM (empty), 500 GB Hard Disk 46 | Resume time: [unpatched 5385ms] [patched 688ms] 47 | 48 | CHANGELOG 49 | 50 | v4: Jan 15, 2014 51 | [in response to Tejun Huo] 52 | - completely removed the pm_result member of the ata_port struct 53 | - result from ata_port_suspend/resume is now returned from the function 54 | instead of into a pointer location 55 | - ata_port_request_pm now only returns 0/-EAGAIN for pass/fail 56 | [fixes] 57 | - moved the scsi_disk_put call from sd_resume_complete into sd_resume 58 | since it needs to be called from the same context 59 | v3: Jan 14, 2014 60 | [in response to Tejun Huo] 61 | - respun the ata patch to merge the entire code path into async resume 62 | i.e. resume, restore, and thaw. 63 | - re-tested the changes in hibernate to verify there are no issues 64 | - respun the sd patch to apply clean over 3.13 rc8, no other changes 65 | v2: Oct 17, 2013 66 | [in response to Oliver Neukum] 67 | - Added scsi cmd error reporting through the scsi_sense_hdr 68 | [in response to James Bottomley] 69 | - unified the sd_resume code path by just making sd_resume async. Thus all 70 | three resume callbacks: resume, restore, and runtime-resume will use it, 71 | but there is a performance benefit for resume only. 72 | [in response to Bartlomiej Zolnierkiewicz] 73 | - unified the __ata_port_resume_common code path to include an async 74 | parameter. This way there's no need to re-implement ata_port_request_pm. 75 | v1: Sept 6, 2013 76 | -------------------------------------------------------------------------------- /dev/hard-disk-resume/mail2.txt: -------------------------------------------------------------------------------- 1 | On resume, the SD driver currently waits until the block driver finishes 2 | executing a disk start command with blk_execute_rq. This patch changes 3 | the sd_resume callback to use blk_execute_rq_nowait instead, which allows 4 | it to return immediately, thus allowing the next device in the pm queue 5 | to resume. The return value of blk_execute_rq_nowait is handled in the 6 | background by sd_resume_complete. Any commands issued to the scsi disk 7 | during the startup will be queued up and executed once the disk is online. 8 | Thus no information is lost. 9 | 10 | This patch applies to all three resume callbacks: resume, restore, and 11 | runtime-resume. There is only a performance benefit for resume, but for 12 | simplicity both restore and runtime-resume use the same code path. 13 | 14 | The execution flow has changed from a single, synchronous call, to two 15 | calls: one called to start sd_resume asynchronously, the other called on 16 | completion. Thus the dmesg log will now show two prints for each drive 17 | resume, on resume start and complete. The scsi sense data is managed 18 | the same, but is now analyzed and freed in sd_resume_complete. 19 | 20 | This code copies a portion of sd_start_stop_device, scsi_execute_req_flags, 21 | and scsi_execute directly into sd_resume: effectively circumventing 22 | sd_start_stop_device to start disks. This is to enable the START_STOP 23 | command to use blk_execute_rq_nowait instead of blk_execute_rq. So 24 | sd_start_stop_device is now only used to stop the device. The disk is 25 | started from within the sd_resume call itself. 26 | 27 | v4: Jan 15, 2014 28 | [fixes] 29 | - moved the scsi_disk_put call from sd_resume_complete into sd_resume 30 | since it needs to be called from the same context 31 | 32 | Signed-off-by: Todd Brandt 33 | Signed-off-by: Arjan van de Ven 34 | --- 35 | drivers/scsi/sd.c | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 36 | 1 file changed, 67 insertions(+), 3 deletions(-) 37 | 38 | diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c 39 | index 69725f7..7c02e46 100644 40 | --- a/drivers/scsi/sd.c 41 | +++ b/drivers/scsi/sd.c 42 | @@ -3172,18 +3172,82 @@ static int sd_suspend_runtime(struct device *dev) 43 | return sd_suspend_common(dev, false); 44 | } 45 | 46 | +static void sd_resume_complete(struct request *rq, int error) 47 | +{ 48 | + struct scsi_sense_hdr sshdr; 49 | + struct scsi_disk *sdkp = rq->end_io_data; 50 | + char *sense = rq->sense; 51 | + 52 | + if (error) { 53 | + sd_printk(KERN_WARNING, sdkp, "START FAILED\n"); 54 | + sd_print_result(sdkp, error); 55 | + if (sense && (driver_byte(error) & DRIVER_SENSE)) { 56 | + scsi_normalize_sense(sense, 57 | + SCSI_SENSE_BUFFERSIZE, &sshdr); 58 | + sd_print_sense_hdr(sdkp, &sshdr); 59 | + } 60 | + } else { 61 | + sd_printk(KERN_NOTICE, sdkp, "START SUCCESS\n"); 62 | + } 63 | + 64 | + kfree(sense); 65 | + rq->sense = NULL; 66 | + rq->end_io_data = NULL; 67 | + __blk_put_request(rq->q, rq); 68 | +} 69 | + 70 | static int sd_resume(struct device *dev) 71 | { 72 | + unsigned char cmd[6] = { START_STOP }; 73 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); 74 | + struct request *req; 75 | + char *sense = NULL; 76 | int ret = 0; 77 | 78 | if (!sdkp->device->manage_start_stop) 79 | - goto done; 80 | + goto error; 81 | 82 | sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); 83 | - ret = sd_start_stop_device(sdkp, 1); 84 | 85 | -done: 86 | + cmd[4] |= 1; 87 | + 88 | + if (sdkp->device->start_stop_pwr_cond) 89 | + cmd[4] |= 1 << 4; /* Active or Standby */ 90 | + 91 | + if (!scsi_device_online(sdkp->device)) { 92 | + ret = -ENODEV; 93 | + goto error; 94 | + } 95 | + 96 | + req = blk_get_request(sdkp->device->request_queue, 0, __GFP_WAIT); 97 | + if (!req) { 98 | + ret = -ENOMEM; 99 | + goto error; 100 | + } 101 | + 102 | + sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO); 103 | + if (!sense) { 104 | + ret = -ENOMEM; 105 | + goto error_sense; 106 | + } 107 | + 108 | + req->cmd_len = COMMAND_SIZE(cmd[0]); 109 | + memcpy(req->cmd, cmd, req->cmd_len); 110 | + req->sense = sense; 111 | + req->sense_len = 0; 112 | + req->retries = SD_MAX_RETRIES; 113 | + req->timeout = SD_TIMEOUT; 114 | + req->cmd_type = REQ_TYPE_BLOCK_PC; 115 | + req->cmd_flags |= REQ_PM | REQ_QUIET | REQ_PREEMPT; 116 | + 117 | + req->end_io_data = sdkp; 118 | + blk_execute_rq_nowait(req->q, NULL, req, 1, sd_resume_complete); 119 | + scsi_disk_put(sdkp); 120 | + return 0; 121 | + 122 | + error_sense: 123 | + __blk_put_request(req->q, req); 124 | + error: 125 | scsi_disk_put(sdkp); 126 | return ret; 127 | } 128 | 129 | -------------------------------------------------------------------------------- /dev/hard-disk-resume/sd_resume_async.patch: -------------------------------------------------------------------------------- 1 | Signed-off-by: Todd Brandt 2 | Signed-off-by: Arjan van de Ven 3 | 4 | diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c 5 | index 69725f7..7c02e46 100644 6 | --- a/drivers/scsi/sd.c 7 | +++ b/drivers/scsi/sd.c 8 | @@ -3172,18 +3172,82 @@ static int sd_suspend_runtime(struct device *dev) 9 | return sd_suspend_common(dev, false); 10 | } 11 | 12 | +static void sd_resume_complete(struct request *rq, int error) 13 | +{ 14 | + struct scsi_sense_hdr sshdr; 15 | + struct scsi_disk *sdkp = rq->end_io_data; 16 | + char *sense = rq->sense; 17 | + 18 | + if (error) { 19 | + sd_printk(KERN_WARNING, sdkp, "START FAILED\n"); 20 | + sd_print_result(sdkp, error); 21 | + if (sense && (driver_byte(error) & DRIVER_SENSE)) { 22 | + scsi_normalize_sense(sense, 23 | + SCSI_SENSE_BUFFERSIZE, &sshdr); 24 | + sd_print_sense_hdr(sdkp, &sshdr); 25 | + } 26 | + } else { 27 | + sd_printk(KERN_NOTICE, sdkp, "START SUCCESS\n"); 28 | + } 29 | + 30 | + kfree(sense); 31 | + rq->sense = NULL; 32 | + rq->end_io_data = NULL; 33 | + __blk_put_request(rq->q, rq); 34 | +} 35 | + 36 | static int sd_resume(struct device *dev) 37 | { 38 | + unsigned char cmd[6] = { START_STOP }; 39 | struct scsi_disk *sdkp = scsi_disk_get_from_dev(dev); 40 | + struct request *req; 41 | + char *sense = NULL; 42 | int ret = 0; 43 | 44 | if (!sdkp->device->manage_start_stop) 45 | - goto done; 46 | + goto error; 47 | 48 | sd_printk(KERN_NOTICE, sdkp, "Starting disk\n"); 49 | - ret = sd_start_stop_device(sdkp, 1); 50 | 51 | -done: 52 | + cmd[4] |= 1; 53 | + 54 | + if (sdkp->device->start_stop_pwr_cond) 55 | + cmd[4] |= 1 << 4; /* Active or Standby */ 56 | + 57 | + if (!scsi_device_online(sdkp->device)) { 58 | + ret = -ENODEV; 59 | + goto error; 60 | + } 61 | + 62 | + req = blk_get_request(sdkp->device->request_queue, 0, __GFP_WAIT); 63 | + if (!req) { 64 | + ret = -ENOMEM; 65 | + goto error; 66 | + } 67 | + 68 | + sense = kzalloc(SCSI_SENSE_BUFFERSIZE, GFP_NOIO); 69 | + if (!sense) { 70 | + ret = -ENOMEM; 71 | + goto error_sense; 72 | + } 73 | + 74 | + req->cmd_len = COMMAND_SIZE(cmd[0]); 75 | + memcpy(req->cmd, cmd, req->cmd_len); 76 | + req->sense = sense; 77 | + req->sense_len = 0; 78 | + req->retries = SD_MAX_RETRIES; 79 | + req->timeout = SD_TIMEOUT; 80 | + req->cmd_type = REQ_TYPE_BLOCK_PC; 81 | + req->cmd_flags |= REQ_PM | REQ_QUIET | REQ_PREEMPT; 82 | + 83 | + req->end_io_data = sdkp; 84 | + blk_execute_rq_nowait(req->q, NULL, req, 1, sd_resume_complete); 85 | + scsi_disk_put(sdkp); 86 | + return 0; 87 | + 88 | + error_sense: 89 | + __blk_put_request(req->q, req); 90 | + error: 91 | scsi_disk_put(sdkp); 92 | return ret; 93 | } 94 | -------------------------------------------------------------------------------- /dev/hard_disk_deferred_resume.patch: -------------------------------------------------------------------------------- 1 | diff --git a/block/genhd.c b/block/genhd.c 2 | index 20625ee..a3894d3 100644 3 | --- a/block/genhd.c 4 | +++ b/block/genhd.c 5 | @@ -517,6 +517,9 @@ static void register_disk(struct gendisk *disk) 6 | /* delay uevents, until we scanned partition table */ 7 | dev_set_uevent_suppress(ddev, 1); 8 | 9 | + device_enable_async_suspend(ddev); 10 | + device_pm_skip_resume(ddev, true); 11 | + 12 | if (device_add(ddev)) 13 | return; 14 | if (!sysfs_deprecated) { 15 | diff --git a/block/partition-generic.c b/block/partition-generic.c 16 | index 789cdea..a0e34ed 100644 17 | --- a/block/partition-generic.c 18 | +++ b/block/partition-generic.c 19 | @@ -325,6 +325,8 @@ struct hd_struct *add_partition(struct gendisk *disk, int partno, 20 | pdev->class = &block_class; 21 | pdev->type = &part_type; 22 | pdev->parent = ddev; 23 | + device_enable_async_suspend(pdev); 24 | + device_pm_skip_resume(pdev, true); 25 | 26 | err = blk_alloc_devt(p, &devt); 27 | if (err) 28 | diff --git a/drivers/ata/libata-transport.c b/drivers/ata/libata-transport.c 29 | index c04d393..1b801bc 100644 30 | --- a/drivers/ata/libata-transport.c 31 | +++ b/drivers/ata/libata-transport.c 32 | @@ -220,6 +220,14 @@ ata_port_simple_attr(stats.idle_irq, idle_irq, "%ld\n", unsigned long); 33 | static DECLARE_TRANSPORT_CLASS(ata_port_class, 34 | "ata_port", NULL, NULL, NULL); 35 | 36 | +static int 37 | +ata_set_async_suspend(struct device *dev, void *data) 38 | +{ 39 | + device_enable_async_suspend(dev); 40 | + device_pm_skip_resume(dev, true); 41 | + return 0; 42 | +} 43 | + 44 | static void ata_tport_release(struct device *dev) 45 | { 46 | put_device(dev->parent); 47 | @@ -292,12 +300,14 @@ int ata_tport_add(struct device *parent, 48 | } 49 | 50 | device_enable_async_suspend(dev); 51 | + device_pm_skip_resume(dev, true); 52 | pm_runtime_set_active(dev); 53 | pm_runtime_enable(dev); 54 | pm_runtime_forbid(dev); 55 | 56 | transport_add_device(dev); 57 | transport_configure_device(dev); 58 | + device_for_each_child(dev, NULL, ata_set_async_suspend); 59 | 60 | error = ata_tlink_add(&ap->link); 61 | if (error) { 62 | @@ -421,8 +431,11 @@ int ata_tlink_add(struct ata_link *link) 63 | goto tlink_err; 64 | } 65 | 66 | + device_enable_async_suspend(dev); 67 | + device_pm_skip_resume(dev, true); 68 | transport_add_device(dev); 69 | transport_configure_device(dev); 70 | + device_for_each_child(dev, NULL, ata_set_async_suspend); 71 | 72 | ata_for_each_dev(ata_dev, link, ALL) { 73 | error = ata_tdev_add(ata_dev); 74 | @@ -649,8 +662,11 @@ static int ata_tdev_add(struct ata_device *ata_dev) 75 | return error; 76 | } 77 | 78 | + device_enable_async_suspend(dev); 79 | + device_pm_skip_resume(dev, true); 80 | transport_add_device(dev); 81 | transport_configure_device(dev); 82 | + device_for_each_child(dev, NULL, ata_set_async_suspend); 83 | return 0; 84 | } 85 | 86 | diff --git a/drivers/scsi/scsi_sysfs.c b/drivers/scsi/scsi_sysfs.c 87 | index 931a7d9..a7ada55 100644 88 | --- a/drivers/scsi/scsi_sysfs.c 89 | +++ b/drivers/scsi/scsi_sysfs.c 90 | @@ -147,6 +147,14 @@ shost_rd_attr2(field, field, format_string) 91 | * Create the actual show/store functions and data structures. 92 | */ 93 | 94 | +static int 95 | +scsi_set_async_suspend(struct device *dev, void *data) 96 | +{ 97 | + device_enable_async_suspend(dev); 98 | + device_pm_skip_resume(dev, true); 99 | + return 0; 100 | +} 101 | + 102 | static ssize_t 103 | store_scan(struct device *dev, struct device_attribute *attr, 104 | const char *buf, size_t count) 105 | @@ -849,6 +857,7 @@ static int scsi_target_add(struct scsi_target *starget) 106 | pm_runtime_set_active(&starget->dev); 107 | pm_runtime_enable(&starget->dev); 108 | device_enable_async_suspend(&starget->dev); 109 | + device_pm_skip_resume(&starget->dev, true); 110 | 111 | return 0; 112 | } 113 | @@ -881,6 +890,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) 114 | transport_configure_device(&starget->dev); 115 | 116 | device_enable_async_suspend(&sdev->sdev_gendev); 117 | + device_pm_skip_resume(&sdev->sdev_gendev, true); 118 | scsi_autopm_get_target(starget); 119 | pm_runtime_set_active(&sdev->sdev_gendev); 120 | pm_runtime_forbid(&sdev->sdev_gendev); 121 | @@ -900,6 +910,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) 122 | return error; 123 | } 124 | device_enable_async_suspend(&sdev->sdev_dev); 125 | + device_pm_skip_resume(&sdev->sdev_dev, true); 126 | error = device_add(&sdev->sdev_dev); 127 | if (error) { 128 | sdev_printk(KERN_INFO, sdev, 129 | @@ -947,6 +958,7 @@ int scsi_sysfs_add_sdev(struct scsi_device *sdev) 130 | } 131 | } 132 | 133 | + device_for_each_child(&sdev->sdev_gendev, NULL, scsi_set_async_suspend); 134 | return error; 135 | } 136 | 137 | diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c 138 | index c1c5552..6ac3045 100644 139 | --- a/drivers/scsi/sd.c 140 | +++ b/drivers/scsi/sd.c 141 | @@ -2932,6 +2932,8 @@ static int sd_probe(struct device *dev) 142 | sdkp->dev.parent = dev; 143 | sdkp->dev.class = &sd_disk_class; 144 | dev_set_name(&sdkp->dev, dev_name(dev)); 145 | + device_enable_async_suspend(&sdkp->dev); 146 | + device_pm_skip_resume(&sdkp->dev, true); 147 | 148 | if (device_add(&sdkp->dev)) 149 | goto out_free_index; 150 | -------------------------------------------------------------------------------- /dev/intel_pci_quirk_remove_d3_delay.patch: -------------------------------------------------------------------------------- 1 | Signed-off-by: Todd Brandt 2 | 3 | diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c 4 | index e85d230..98ea960 100644 5 | --- a/drivers/pci/quirks.c 6 | +++ b/drivers/pci/quirks.c 7 | @@ -2955,6 +2955,29 @@ DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0102, disable_igfx_irq); 8 | DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x010a, disable_igfx_irq); 9 | 10 | /* 11 | + * PCI devices which are on Intel chips can skip the 10ms delay 12 | + * before entering D3 mode. 13 | + */ 14 | +static void quirk_remove_d3_delay(struct pci_dev *dev) 15 | +{ 16 | + dev->d3_delay = 0; 17 | +} 18 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0c00, quirk_remove_d3_delay); 19 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0412, quirk_remove_d3_delay); 20 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0c0c, quirk_remove_d3_delay); 21 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c31, quirk_remove_d3_delay); 22 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c3a, quirk_remove_d3_delay); 23 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c3d, quirk_remove_d3_delay); 24 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c2d, quirk_remove_d3_delay); 25 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c20, quirk_remove_d3_delay); 26 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c18, quirk_remove_d3_delay); 27 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c1c, quirk_remove_d3_delay); 28 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c26, quirk_remove_d3_delay); 29 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c4e, quirk_remove_d3_delay); 30 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c02, quirk_remove_d3_delay); 31 | +DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x8c22, quirk_remove_d3_delay); 32 | + 33 | +/* 34 | * Some devices may pass our check in pci_intx_mask_supported if 35 | * PCI_COMMAND_INTX_DISABLE works though they actually do not properly 36 | * support this feature. 37 | -------------------------------------------------------------------------------- /dev/pm-deferred_resume.patch: -------------------------------------------------------------------------------- 1 | diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c 2 | index 5a9b656..6e758ea 100644 3 | --- a/drivers/base/power/main.c 4 | +++ b/drivers/base/power/main.c 5 | @@ -384,6 +384,29 @@ static int dpm_run_callback(pm_callback_t cb, struct device *dev, 6 | return error; 7 | } 8 | 9 | +#ifdef CONFIG_PM_RUNTIME 10 | +void device_pm_skip_resume(struct device *dev, bool enable) 11 | +{ 12 | + device_pm_lock(); 13 | + 14 | + if (!dev->power.is_prepared) 15 | + dev->power.skip_resume = !!enable; 16 | + 17 | + device_pm_unlock(); 18 | +} 19 | + 20 | +static inline bool skip_device_resume(struct device *dev, pm_message_t state) 21 | +{ 22 | + return dev->power.skip_resume && (state.event == PM_EVENT_RESUME 23 | + || state.event == PM_EVENT_RESTORE); 24 | +} 25 | +#else 26 | +static inline bool skip_device_resume(struct device *dev, pm_message_t state) 27 | +{ 28 | + return false; 29 | +} 30 | +#endif /* CONFIG_PM_RUNTIME */ 31 | + 32 | /*------------------------- Resume routines -------------------------*/ 33 | 34 | /** 35 | @@ -446,21 +469,24 @@ static void dpm_resume_noirq(pm_message_t state) 36 | mutex_lock(&dpm_list_mtx); 37 | while (!list_empty(&dpm_noirq_list)) { 38 | struct device *dev = to_device(dpm_noirq_list.next); 39 | - int error; 40 | 41 | get_device(dev); 42 | list_move_tail(&dev->power.entry, &dpm_late_early_list); 43 | - mutex_unlock(&dpm_list_mtx); 44 | + if (!skip_device_resume(dev, state)) { 45 | + int error; 46 | 47 | - error = device_resume_noirq(dev, state); 48 | - if (error) { 49 | - suspend_stats.failed_resume_noirq++; 50 | - dpm_save_failed_step(SUSPEND_RESUME_NOIRQ); 51 | - dpm_save_failed_dev(dev_name(dev)); 52 | - pm_dev_err(dev, state, " noirq", error); 53 | - } 54 | + mutex_unlock(&dpm_list_mtx); 55 | 56 | - mutex_lock(&dpm_list_mtx); 57 | + error = device_resume_noirq(dev, state); 58 | + if (error) { 59 | + suspend_stats.failed_resume_noirq++; 60 | + dpm_save_failed_step(SUSPEND_RESUME_NOIRQ); 61 | + dpm_save_failed_dev(dev_name(dev)); 62 | + pm_dev_err(dev, state, " noirq", error); 63 | + } 64 | + 65 | + mutex_lock(&dpm_list_mtx); 66 | + } 67 | put_device(dev); 68 | } 69 | mutex_unlock(&dpm_list_mtx); 70 | @@ -527,21 +553,39 @@ static void dpm_resume_early(pm_message_t state) 71 | mutex_lock(&dpm_list_mtx); 72 | while (!list_empty(&dpm_late_early_list)) { 73 | struct device *dev = to_device(dpm_late_early_list.next); 74 | - int error; 75 | 76 | get_device(dev); 77 | list_move_tail(&dev->power.entry, &dpm_suspended_list); 78 | - mutex_unlock(&dpm_list_mtx); 79 | + if (skip_device_resume(dev, state)) { 80 | + pm_runtime_set_suspended(dev); 81 | + pm_runtime_enable(dev); 82 | + /* 83 | + * Balance the pm_runtime_get_noresume() in 84 | + * device_prepare(). 85 | + */ 86 | + pm_runtime_put_noidle(dev); 87 | + /* 88 | + * The device might have been powered up by the platform 89 | + * firmware already, so make it resume and then possibly 90 | + * suspend again to avoid leaving powered up devices as 91 | + * "suspended" for too long. 92 | + */ 93 | + pm_request_resume(dev); 94 | + } else { 95 | + int error; 96 | 97 | - error = device_resume_early(dev, state); 98 | - if (error) { 99 | - suspend_stats.failed_resume_early++; 100 | - dpm_save_failed_step(SUSPEND_RESUME_EARLY); 101 | - dpm_save_failed_dev(dev_name(dev)); 102 | - pm_dev_err(dev, state, " early", error); 103 | - } 104 | + mutex_unlock(&dpm_list_mtx); 105 | 106 | - mutex_lock(&dpm_list_mtx); 107 | + error = device_resume_early(dev, state); 108 | + if (error) { 109 | + suspend_stats.failed_resume_early++; 110 | + dpm_save_failed_step(SUSPEND_RESUME_EARLY); 111 | + dpm_save_failed_dev(dev_name(dev)); 112 | + pm_dev_err(dev, state, " early", error); 113 | + } 114 | + 115 | + mutex_lock(&dpm_list_mtx); 116 | + } 117 | put_device(dev); 118 | } 119 | mutex_unlock(&dpm_list_mtx); 120 | @@ -682,6 +726,10 @@ void dpm_resume(pm_message_t state) 121 | 122 | list_for_each_entry(dev, &dpm_suspended_list, power.entry) { 123 | INIT_COMPLETION(dev->power.completion); 124 | + if (skip_device_resume(dev, state)) { 125 | + complete(&dev->power.completion); 126 | + continue; 127 | + } 128 | if (is_async(dev)) { 129 | get_device(dev); 130 | async_schedule(async_resume, dev); 131 | @@ -691,7 +739,7 @@ void dpm_resume(pm_message_t state) 132 | while (!list_empty(&dpm_suspended_list)) { 133 | dev = to_device(dpm_suspended_list.next); 134 | get_device(dev); 135 | - if (!is_async(dev)) { 136 | + if (!is_async(dev) && !skip_device_resume(dev, state)) { 137 | int error; 138 | 139 | mutex_unlock(&dpm_list_mtx); 140 | @@ -780,11 +828,13 @@ void dpm_complete(pm_message_t state) 141 | get_device(dev); 142 | dev->power.is_prepared = false; 143 | list_move(&dev->power.entry, &list); 144 | - mutex_unlock(&dpm_list_mtx); 145 | + if (!skip_device_resume(dev, state)) { 146 | + mutex_unlock(&dpm_list_mtx); 147 | 148 | - device_complete(dev, state); 149 | + device_complete(dev, state); 150 | 151 | - mutex_lock(&dpm_list_mtx); 152 | + mutex_lock(&dpm_list_mtx); 153 | + } 154 | put_device(dev); 155 | } 156 | list_splice(&list, &dpm_list); 157 | diff --git a/include/linux/pm.h b/include/linux/pm.h 158 | index a224c7f..12b995a 100644 159 | --- a/include/linux/pm.h 160 | +++ b/include/linux/pm.h 161 | @@ -530,9 +530,12 @@ struct dev_pm_info { 162 | struct wakeup_source *wakeup; 163 | bool wakeup_path:1; 164 | bool syscore:1; 165 | +#ifdef CONFIG_PM_RUNTIME 166 | + bool skip_resume:1; 167 | +#endif 168 | #else 169 | unsigned int should_wakeup:1; 170 | -#endif 171 | +#endif /* CONFIG_PM_SLEEP */ 172 | #ifdef CONFIG_PM_RUNTIME 173 | struct timer_list suspend_timer; 174 | unsigned long timer_expires; 175 | @@ -559,7 +562,7 @@ struct dev_pm_info { 176 | unsigned long active_jiffies; 177 | unsigned long suspended_jiffies; 178 | unsigned long accounting_timestamp; 179 | -#endif 180 | +#endif /* CONFIG_PM_RUNTIME */ 181 | struct pm_subsys_data *subsys_data; /* Owned by the subsystem. */ 182 | struct dev_pm_qos *qos; 183 | }; 184 | @@ -714,4 +717,10 @@ enum dpm_order { 185 | DPM_ORDER_DEV_LAST, 186 | }; 187 | 188 | +#if defined(CONFIG_PM_RUNTIME) && defined(CONFIG_PM_SLEEP) 189 | +void device_pm_skip_resume(struct device *dev, bool enable); 190 | +#else 191 | +static inline void device_pm_skip_resume(struct device *dev, bool enable) {} 192 | +#endif /* CONFIG_PM_RUNTIME && CONFIG_PM_SLEEP */ 193 | + 194 | #endif /* _LINUX_PM_H */ 195 | -------------------------------------------------------------------------------- /dev/pm_resume_async_non_blocking.patch: -------------------------------------------------------------------------------- 1 | Signed-off-by: Todd Brandt 2 | 3 | diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c 4 | index 2b7f77d..1b16379 100644 5 | --- a/drivers/base/power/main.c 6 | +++ b/drivers/base/power/main.c 7 | @@ -713,7 +713,6 @@ void dpm_resume(pm_message_t state) 8 | put_device(dev); 9 | } 10 | mutex_unlock(&dpm_list_mtx); 11 | - async_synchronize_full(); 12 | dpm_show_time(starttime, state, NULL); 13 | } 14 | 15 | @@ -726,11 +725,14 @@ static void device_complete(struct device *dev, pm_message_t state) 16 | { 17 | void (*callback)(struct device *) = NULL; 18 | char *info = NULL; 19 | + bool hascb = false; 20 | 21 | if (dev->power.syscore) 22 | return; 23 | 24 | - device_lock(dev); 25 | + docomplete: 26 | + if (hascb) 27 | + device_lock(dev); 28 | 29 | if (dev->pm_domain) { 30 | info = "completing power domain "; 31 | @@ -751,13 +753,21 @@ static void device_complete(struct device *dev, pm_message_t state) 32 | callback = dev->driver->pm->complete; 33 | } 34 | 35 | + /* 36 | + * if a callback exists, lock the device and call it 37 | + * otherwise don't even lock/unlock the device 38 | + */ 39 | if (callback) { 40 | + if (!hascb) { 41 | + hascb = true; 42 | + goto docomplete; 43 | + } 44 | + 45 | pm_dev_dbg(dev, state, info); 46 | callback(dev); 47 | + device_unlock(dev); 48 | } 49 | 50 | - device_unlock(dev); 51 | - 52 | pm_runtime_put_sync(dev); 53 | } 54 | 55 | @@ -1180,6 +1190,8 @@ int dpm_suspend(pm_message_t state) 56 | might_sleep(); 57 | 58 | mutex_lock(&dpm_list_mtx); 59 | + /* wait for any processes still resuming */ 60 | + async_synchronize_full(); 61 | pm_transition = state; 62 | async_error = 0; 63 | while (!list_empty(&dpm_prepared_list)) { 64 | -------------------------------------------------------------------------------- /dev/usb-resume/skynet-usb-layout.txt: -------------------------------------------------------------------------------- 1 | ---------------------------------------------------------- 2 | Physical slot layout: 3 | 4 | USB 2.0 x2 on top (bus 001) 5 | USB 2.0 x2 on back, row 1 (bus 001) 6 | USB 2.0 x2 on back, row 2 (bus 002) 7 | USB 3.0 x2 on back (bus 004) 8 | 9 | ---------------------------------------------------------- 10 | Root hub (resume 0.3 ms) 11 | Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub 12 | 13 | Rate matching hub -- (resume 48 ms) 14 | Bus 001 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub 15 | 16 | Bluetooth (on the motherboard) -- (resume 3.5 ms) 17 | Bus 001 Device 004: ID 0cf3:e004 Atheros Communications, Inc. 18 | 19 | External USB hub (resume 4 ms) 20 | Bus 001 Device 007: ID 1a40:0201 Terminus Technology Inc. FE 2.1 7-port Hub 21 | 22 | Mouse (resume 1.8 ms) 23 | Bus 001 Device 017: ID 0461:4d64 Primax Electronics, Ltd 24 | 25 | Keyboard (resume 2.8 ms) 26 | Bus 001 Device 015: ID 04ca:0027 Lite-On Technology Corp. 27 | 28 | Webcam (Logitech) -- (resume 642 ms) 29 | Bus 001 Device 010: ID 046d:0804 Logitech, Inc. Webcam C250 30 | 31 | CellPhone (HTC G2) -- (resume 1.3 ms) 32 | Bus 001 Device 071: ID 0bb4:0c91 HTC (High Tech Computer Corp.) Vision 33 | 34 | ---------------------------------------------------------- 35 | Root hub (resume 32 ms) 36 | Bus 002 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub 37 | 38 | Rate matching hub -- (resume 1.5 ms) 39 | Bus 002 Device 002: ID 8087:0024 Intel Corp. Integrated Rate Matching Hub 40 | 41 | SD Card Slot (on the motherboard) -- (resume 0.5 ms) 42 | Bus 002 Device 003: ID 058f:6362 Alcor Micro Corp. Flash Card Reader/Writer 43 | 44 | Wifi (TP-Link 802.11n) -- (suspend 157 ms, resume 886 ms) 45 | Bus 002 Device 018: ID 0cf3:9271 Atheros Communications, Inc. AR9271 802.11n 46 | 47 | Webcam (Logitech HD) -- (resume 168 ms) 48 | Bus 002 Device 017: ID 046d:082d Logitech, Inc. 49 | 50 | ---------------------------------------------------------- 51 | Root hub (resume 0.5 ms) 52 | Bus 003 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub 53 | 54 | ---------------------------------------------------------- 55 | Root hub (resume 0.5 ms) 56 | Bus 004 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub 57 | 58 | 4 TB Harddrive (Seagate) -- (resume 70 ms) 59 | Bus 004 Device 002: ID 0bc2:a0a4 Seagate RSS LLC 60 | 61 | ---------------------------------------------------------- 62 | 63 | dpm_complete callback for webcam resulted in 450ms of waste: 64 | 65 | [ 2863.185239] PM: resume of devices complete after 1192.643 msecs 66 | [ 2863.452225] usb_audio: Warning! Unlikely big volume range (=6144), cval->res is probably wrong. 67 | [ 2863.631660] usb_audio: [5] FU [Mic Capture Volume] ch = 1, val = 1536/7680/1 68 | [ 2863.631660] PM: Finishing wakeup. 69 | [ 2863.631663] Restarting tasks ... done. 70 | 71 | 72 | ---------------------------------------------------------- 73 | 74 | Conclusions: 75 | 76 | Common delay: 77 | 78 | 1) Root / Rate matching hub -- (resume 32 ms / resume 48 ms) 79 | 80 | slowest devices: 81 | 82 | 1) USB TV tuner -- (resume 1.2 ms, complete 2000 ms) 83 | 2) Wifi (TP-Link 802.11n) -- (suspend 157 ms, resume 886 ms) 84 | 3) Webcam (Logitech) -- (resume 642 ms) 85 | 4) Webcam (Logitech HD) -- (resume 168 ms) + 450ms in dpm_complete 86 | 5) USB 3.0 Harddrive (4TB Seagate) -- (resume 70 ms) 87 | 88 | fastest devices: 89 | 90 | 1) External USB hub (resume 4 ms) 91 | 2) Bluetooth (on the motherboard) -- (resume 3.5 ms) 92 | 3) Keyboard (resume 2.8 ms) 93 | 4) Mouse (resume 1.8 ms) 94 | 5) GPS reciever -- (resume 1.5 ms) 95 | 6) CellPhone (HTC G2) -- (resume 1.3 ms) 96 | 7) USB Flash key -- (resume 1 ms) 97 | 8) USB 2.0 Harddrive (1TB Western Digital) -- (resume 0.7 ms) 98 | 9) SD Card Slot (on the motherboard) -- (resume 0.5 ms) 99 | 10) USB SD Card reader -- (resume 0.5 ms) 100 | 101 | need to test: 102 | 103 | touch panel 104 | -------------------------------------------------------------------------------- /dev/usb-resume/usb-trace.patch: -------------------------------------------------------------------------------- 1 | diff --git a/drivers/usb/core/driver.c b/drivers/usb/core/driver.c 2 | index 888881e..1958eb6 100644 3 | --- a/drivers/usb/core/driver.c 4 | +++ b/drivers/usb/core/driver.c 5 | @@ -1193,6 +1193,7 @@ static int usb_resume_device(struct usb_device *udev, pm_message_t msg) 6 | static int usb_suspend_interface(struct usb_device *udev, 7 | struct usb_interface *intf, pm_message_t msg) 8 | { 9 | + trace_suspend_resume("usb_suspend_interface", true); 10 | struct usb_driver *driver; 11 | int status = 0; 12 | 13 | @@ -1208,12 +1209,14 @@ static int usb_suspend_interface(struct usb_device *udev, 14 | 15 | done: 16 | dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status); 17 | + trace_suspend_resume("usb_suspend_interface", false); 18 | return status; 19 | } 20 | 21 | static int usb_resume_interface(struct usb_device *udev, 22 | struct usb_interface *intf, pm_message_t msg, int reset_resume) 23 | { 24 | + trace_suspend_resume("usb_resume_interface", true); 25 | struct usb_driver *driver; 26 | int status = 0; 27 | 28 | @@ -1262,6 +1265,7 @@ done: 29 | dev_vdbg(&intf->dev, "%s: status %d\n", __func__, status); 30 | 31 | /* Later we will unbind the driver and/or reprobe, if necessary */ 32 | + trace_suspend_resume("usb_resume_interface", false); 33 | return status; 34 | } 35 | 36 | diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c 37 | index 726fa07..be61224 100644 38 | --- a/drivers/usb/core/hub.c 39 | +++ b/drivers/usb/core/hub.c 40 | @@ -2969,6 +2969,7 @@ static unsigned wakeup_enabled_descendants(struct usb_device *udev) 41 | */ 42 | int usb_port_suspend(struct usb_device *udev, pm_message_t msg) 43 | { 44 | + trace_suspend_resume("usb_port_suspend", true); 45 | struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); 46 | struct usb_port *port_dev = hub->ports[udev->portnum - 1]; 47 | int port1 = udev->portnum; 48 | @@ -3070,6 +3071,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) 49 | } 50 | 51 | usb_mark_last_busy(hub->hdev); 52 | + trace_suspend_resume("usb_port_suspend", false); 53 | return status; 54 | } 55 | 56 | @@ -3086,6 +3088,7 @@ int usb_port_suspend(struct usb_device *udev, pm_message_t msg) 57 | */ 58 | static int finish_port_resume(struct usb_device *udev) 59 | { 60 | + trace_suspend_resume("finish_port_resume", true); 61 | int status = 0; 62 | u16 devstatus = 0; 63 | 64 | @@ -3164,6 +3167,7 @@ static int finish_port_resume(struct usb_device *udev) 65 | status); 66 | status = 0; 67 | } 68 | + trace_suspend_resume("finish_port_resume", false); 69 | return status; 70 | } 71 | 72 | @@ -3203,6 +3207,7 @@ static int finish_port_resume(struct usb_device *udev) 73 | */ 74 | int usb_port_resume(struct usb_device *udev, pm_message_t msg) 75 | { 76 | + trace_suspend_resume("usb_port_resume", true); 77 | struct usb_hub *hub = usb_hub_to_struct_hub(udev->parent); 78 | struct usb_port *port_dev = hub->ports[udev->portnum - 1]; 79 | int port1 = udev->portnum; 80 | @@ -3215,6 +3220,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) 81 | if (status < 0) { 82 | dev_dbg(&udev->dev, "can't resume usb port, status %d\n", 83 | status); 84 | + trace_suspend_resume("usb_port_resume", false); 85 | return status; 86 | } 87 | } 88 | @@ -3286,6 +3292,7 @@ int usb_port_resume(struct usb_device *udev, pm_message_t msg) 89 | usb_unlocked_enable_lpm(udev); 90 | } 91 | 92 | + trace_suspend_resume("usb_port_resume", false); 93 | return status; 94 | } 95 | 96 | @@ -4038,7 +4045,9 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, 97 | if (oldspeed == USB_SPEED_LOW) 98 | delay = HUB_LONG_RESET_TIME; 99 | 100 | + trace_suspend_resume("mutex_lock_usb_address0", true); 101 | mutex_lock(&hdev->bus->usb_address0_mutex); 102 | + trace_suspend_resume("mutex_lock_usb_address0", false); 103 | 104 | /* Reset the device; full speed may morph to high speed */ 105 | /* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */ 106 | @@ -4315,6 +4324,7 @@ fail: 107 | hub_port_disable(hub, port1, 0); 108 | update_devnum(udev, devnum); /* for disconnect processing */ 109 | } 110 | + trace_suspend_resume("mutex_unlock_usb_address0", true); 111 | mutex_unlock(&hdev->bus->usb_address0_mutex); 112 | return retval; 113 | } 114 | diff --git a/drivers/usb/core/usb.h b/drivers/usb/core/usb.h 115 | index 75bf649..3ba77fc 100644 116 | --- a/drivers/usb/core/usb.h 117 | +++ b/drivers/usb/core/usb.h 118 | @@ -1,5 +1,6 @@ 119 | #include 120 | #include 121 | +#include 122 | 123 | struct usb_hub_descriptor; 124 | struct usb_dev_state; 125 | -------------------------------------------------------------------------------- /dev/usb-resume/usb_address0.patch: -------------------------------------------------------------------------------- 1 | This patch creates a separate instance of the usb_address0 mutex for each USB 2 | bus, and attaches it to the usb_bus device struct. This allows devices on 3 | separate buses to be enumerated in parallel; saving time. 4 | 5 | In the current code, there is a single, global instance of the usb_address0 6 | mutex which is used for all devices on all buses. This isn't completely 7 | necessary, as this mutex is only needed to prevent address0 collisions for 8 | devices on the *same* bus (usb 2.0 spec, sec 4.6.1). This superfluous coverage 9 | can cause additional delay in system resume on systems with multiple hosts 10 | (up to several seconds depending on what devices are attached). 11 | 12 | Signed-off-by: Todd Brandt 13 | Acked-by: Alan Stern 14 | --- 15 | drivers/usb/core/hcd.c | 1 + 16 | drivers/usb/core/hub.c | 6 ++---- 17 | include/linux/usb.h | 2 ++ 18 | 3 files changed, 5 insertions(+), 4 deletions(-) 19 | 20 | v3: May 19, 2014 21 | - just format corrections to the patch submission 22 | v2: May 16, 2014 23 | [in response to Greg KH] 24 | - removed kmalloc failure debug prints 25 | [in response to Alan Stern] 26 | - moved the usb_address0_mutex to the usb_bus struct instead of usb_hcd 27 | - no longer mallocing the mutex, it's just statically defined now 28 | 29 | diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c 30 | index 9c4e292..87194e1 100644 31 | --- a/drivers/usb/core/hcd.c 32 | +++ b/drivers/usb/core/hcd.c 33 | @@ -918,6 +918,7 @@ static void usb_bus_init (struct usb_bus *bus) 34 | bus->bandwidth_allocated = 0; 35 | bus->bandwidth_int_reqs = 0; 36 | bus->bandwidth_isoc_reqs = 0; 37 | + mutex_init(&bus->usb_address0_mutex); 38 | 39 | INIT_LIST_HEAD (&bus->bus_list); 40 | } 41 | diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c 42 | index 090469e..726fa07 100644 43 | --- a/drivers/usb/core/hub.c 44 | +++ b/drivers/usb/core/hub.c 45 | @@ -4016,8 +4016,6 @@ static int 46 | hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, 47 | int retry_counter) 48 | { 49 | - static DEFINE_MUTEX(usb_address0_mutex); 50 | - 51 | struct usb_device *hdev = hub->hdev; 52 | struct usb_hcd *hcd = bus_to_hcd(hdev->bus); 53 | int i, j, retval; 54 | @@ -4040,7 +4038,7 @@ hub_port_init (struct usb_hub *hub, struct usb_device *udev, int port1, 55 | if (oldspeed == USB_SPEED_LOW) 56 | delay = HUB_LONG_RESET_TIME; 57 | 58 | - mutex_lock(&usb_address0_mutex); 59 | + mutex_lock(&hdev->bus->usb_address0_mutex); 60 | 61 | /* Reset the device; full speed may morph to high speed */ 62 | /* FIXME a USB 2.0 device may morph into SuperSpeed on reset. */ 63 | @@ -4317,7 +4315,7 @@ fail: 64 | hub_port_disable(hub, port1, 0); 65 | update_devnum(udev, devnum); /* for disconnect processing */ 66 | } 67 | - mutex_unlock(&usb_address0_mutex); 68 | + mutex_unlock(&hdev->bus->usb_address0_mutex); 69 | return retval; 70 | } 71 | 72 | diff --git a/include/linux/usb.h b/include/linux/usb.h 73 | index 6b7ec37..d2465bc 100644 74 | --- a/include/linux/usb.h 75 | +++ b/include/linux/usb.h 76 | @@ -352,6 +352,8 @@ struct usb_bus { 77 | struct usb_bus *hs_companion; /* Companion EHCI bus, if any */ 78 | struct list_head bus_list; /* list of busses */ 79 | 80 | + struct mutex usb_address0_mutex; /* unaddressed device mutex */ 81 | + 82 | int bandwidth_allocated; /* on this bus: how much of the time 83 | * reserved for periodic (intr/iso) 84 | * requests is used, on average? 85 | -------------------------------------------------------------------------------- /devtest/devtest.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # 4 | # Copyright 2014 Todd Brandt 5 | # 6 | # This program is free software; you may redistribute it and/or modify it 7 | # under the same terms as Perl itself. 8 | # trancearoundtheworld mp3 archive sync utility 9 | # Copyright (C) 2012 Todd Brandt 10 | # 11 | # This program is free software; you can redistribute it and/or modify 12 | # it under the terms of the GNU General Public License as published by 13 | # the Free Software Foundation; either version 2 of the License, or 14 | # (at your option) any later version. 15 | # 16 | # This program is distributed in the hope that it will be useful, 17 | # but WITHOUT ANY WARRANTY; without even the implied warranty of 18 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 19 | # GNU General Public License for more details. 20 | # 21 | # You should have received a copy of the GNU General Public License along 22 | # with this program; if not, write to the Free Software Foundation, Inc., 23 | # 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 24 | # 25 | 26 | listTests() { 27 | DIRS=`ls -1` 28 | for d in $DIRS; do 29 | if [ -e "$d/run.sh" ]; then 30 | echo "" 31 | echo "$d:" 32 | cat $d/run.sh | head -2 | sed "s/# //" 33 | fi 34 | done 35 | echo "" 36 | } 37 | 38 | diffTests() { 39 | TYPE=$1 40 | ROOT=$PWD 41 | DIRS=`ls -1` 42 | for d in $DIRS; do 43 | if [ ! -d $ROOT/$d ]; then continue; fi 44 | if [ ! -e "$ROOT/$d/run.sh" ]; then continue; fi 45 | cd $ROOT/$d 46 | PARAMS=`cat run.sh | grep "# params = " | tail -1 | sed "s/.*params.*= //"` 47 | OUT=`cat run.sh | grep "# output file = " | tail -1 | sed "s/.*output.*file.*= //"` 48 | if [ -z "$OUT" ]; then onError "invalid format for $d/run.sh"; fi 49 | echo "-----------------------------------------" 50 | echo "$d/$OUT ($PARAMS)" 51 | echo "" 52 | if [ ! -e "control.html" ]; then 53 | printBad "FAIL - missing control.html" 54 | continue 55 | fi 56 | if [ ! -e "$OUT" ]; then 57 | printBad "FAIL - missing $OUT" 58 | continue 59 | fi 60 | CHECK=`diff -q control.html $OUT` 61 | if [ -z "$CHECK" ]; then 62 | printGood "PASS" 63 | else 64 | printBad "WARNING - Files differ" 65 | if [ $TYPE = "full" ]; then 66 | DIFF=`diff control.html $OUT` 67 | printDiff "$DIFF" 68 | fi 69 | fi 70 | done 71 | echo "-----------------------------------------" 72 | cd $ROOT 73 | } 74 | 75 | runTests() { 76 | TYPE=$1 77 | ROOT=$PWD 78 | DIRS=`ls -1` 79 | for d in $DIRS; do 80 | if [ ! -d $ROOT/$d ]; then continue; fi 81 | if [ ! -e "$ROOT/$d/run.sh" ]; then continue; fi 82 | cd $ROOT/$d 83 | echo "-----------------------------------------" 84 | echo "$d:" 85 | cat run.sh | head -2 | sed "s/# //" 86 | OUT=`cat run.sh | grep "# output file = " | tail -1 | sed "s/.*output.*file.*= //"` 87 | if [ -z "$OUT" ]; then onError "invalid format for $d/run.sh"; fi 88 | case "$TYPE" in 89 | control) 90 | rm -f $OUT control.html output.txt 91 | echo -n "Creating control output... " 92 | run.sh > output.txt 93 | if [ ! -e $OUT ]; then onError "test failed, see $d/output.txt"; fi 94 | cp -f $OUT control.html 95 | echo "DONE" 96 | ;; 97 | *) 98 | rm -f $OUT output.txt 99 | echo -n "Running the test... " 100 | run.sh > output.txt 101 | if [ ! -e $OUT ]; then onError "test failed, see $d/output.txt"; fi 102 | CHECK=`diff -q control.html $OUT` 103 | if [ -z "$CHECK" ]; then 104 | printGood "PASS" 105 | else 106 | printBad "WARNING - Files differ" 107 | if [ $TYPE = "full" ]; then 108 | diff control.html $OUT 109 | fi 110 | fi 111 | ;; 112 | esac 113 | done 114 | cd $ROOT 115 | } 116 | 117 | printHelp() { 118 | echo "" 119 | echo "USAGE: devtest.sh command " 120 | echo " Commands:" 121 | echo " list" 122 | echo " desc : list all the tests currently available" 123 | echo " args : none" 124 | echo " run" 125 | echo " desc : execute the tests" 126 | echo " args : control, quick, full" 127 | echo " control - run all tests and make the outputs the new controls" 128 | echo " quick - run all tests and check for differences (default)" 129 | echo " full - run all tests and print any differences" 130 | echo " diff" 131 | echo " desc : compare all current outputs to the controls" 132 | echo " args : quick, full" 133 | echo " quick - run all tests and check for differences (default)" 134 | echo " full - run all tests and print any differences" 135 | echo "" 136 | } 137 | 138 | printDiff() { 139 | echo -e "\e[33m$1\e[39m" 140 | } 141 | 142 | printGood() { 143 | echo -e "\e[32m$1\e[39m" 144 | } 145 | 146 | printBad() { 147 | echo -e "\e[31m$1\e[39m" 148 | } 149 | 150 | onError() { 151 | if [ $2 ]; then 152 | printHelp 153 | else 154 | echo "" 155 | fi 156 | printBad "ERROR: $1" 157 | echo "" 158 | exit 159 | } 160 | 161 | # -- parse commands and arguments -- 162 | 163 | if [ $# -lt 1 ]; then printHelp; exit; fi 164 | 165 | COMMAND=$1 166 | shift 167 | case "$COMMAND" in 168 | list) 169 | listTests 170 | ;; 171 | diff) 172 | TYPE="quick" 173 | if [ $# -gt 0 ]; then 174 | TYPE="$1" 175 | fi 176 | case "$TYPE" in 177 | quick);; 178 | full);; 179 | *) 180 | onError "Invalid diff type ($TYPE)" true 181 | ;; 182 | esac 183 | diffTests $TYPE 184 | ;; 185 | run) 186 | TYPE="quick" 187 | if [ $# -gt 0 ]; then 188 | TYPE="$1" 189 | fi 190 | case "$TYPE" in 191 | control) 192 | echo "CREATING NEW CONTROLS" 193 | runTests $TYPE 194 | ;; 195 | quick) 196 | echo "QUICK TEST" 197 | runTests $TYPE 198 | ;; 199 | full) 200 | echo "FULL TEST" 201 | runTests $TYPE 202 | ;; 203 | *) 204 | onError "Invalid test type ($TYPE)" true 205 | ;; 206 | esac 207 | ;; 208 | *) 209 | onError "Invalid command ($COMMAND)" true 210 | ;; 211 | esac 212 | -------------------------------------------------------------------------------- /devtest/suspend-061314-131149/run.sh: -------------------------------------------------------------------------------- 1 | # params = standby: standard 2 | # output file = skynet_standby.html 3 | #!/bin/sh 4 | 5 | ../../sleepgraph.py -dmesg skynet_standby_dmesg.txt -ftrace skynet_standby_ftrace.txt -verbose 6 | -------------------------------------------------------------------------------- /devtest/suspend-061314-131447/run.sh: -------------------------------------------------------------------------------- 1 | # params = freeze: standard 2 | # output file = skynet_freeze.html 3 | #!/bin/sh 4 | 5 | ../../sleepgraph.py -dmesg skynet_freeze_dmesg.txt -ftrace skynet_freeze_ftrace.txt -verbose 6 | -------------------------------------------------------------------------------- /devtest/suspend-061314-132459/run.sh: -------------------------------------------------------------------------------- 1 | # params = mem: standard 2 | # output file = skynet_mem.html 3 | #!/bin/sh 4 | 5 | ../../sleepgraph.py -dmesg skynet_mem_dmesg.txt -ftrace skynet_mem_ftrace.txt -verbose 6 | -------------------------------------------------------------------------------- /devtest/suspend-061314-132803/run.sh: -------------------------------------------------------------------------------- 1 | # params = disk: standard 2 | # output file = skynet_disk.html 3 | #!/bin/sh 4 | 5 | ../../sleepgraph.py -dmesg skynet_disk_dmesg.txt -ftrace skynet_disk_ftrace.txt -verbose 6 | -------------------------------------------------------------------------------- /kernel/3.10/1-enable_ftrace_in_suspendresume.patch: -------------------------------------------------------------------------------- 1 | diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c 2 | index bef86d1..6c23af7 100644 3 | --- a/kernel/power/suspend.c 4 | +++ b/kernel/power/suspend.c 5 | @@ -210,6 +210,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) 6 | goto Platform_wake; 7 | } 8 | 9 | + ftrace_stop(); 10 | error = disable_nonboot_cpus(); 11 | if (error || suspend_test(TEST_CPUS)) 12 | goto Enable_cpus; 13 | @@ -232,6 +233,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) 14 | 15 | Enable_cpus: 16 | enable_nonboot_cpus(); 17 | + ftrace_start(); 18 | 19 | Platform_wake: 20 | if (need_suspend_ops(state) && suspend_ops->wake) 21 | @@ -265,7 +267,6 @@ int suspend_devices_and_enter(suspend_state_t state) 22 | goto Close; 23 | } 24 | suspend_console(); 25 | - ftrace_stop(); 26 | suspend_test_start(); 27 | error = dpm_suspend_start(PMSG_SUSPEND); 28 | if (error) { 29 | @@ -285,7 +286,6 @@ int suspend_devices_and_enter(suspend_state_t state) 30 | suspend_test_start(); 31 | dpm_resume_end(PMSG_RESUME); 32 | suspend_test_finish("resume devices"); 33 | - ftrace_start(); 34 | resume_console(); 35 | Close: 36 | if (need_suspend_ops(state) && suspend_ops->end) 37 | -------------------------------------------------------------------------------- /kernel/3.10/3-enable_trace_events_device_pm_callback.patch: -------------------------------------------------------------------------------- 1 | diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c 2 | index 0ba0019..b971811 100644 3 | --- a/drivers/base/power/main.c 4 | +++ b/drivers/base/power/main.c 5 | @@ -377,7 +377,9 @@ static int dpm_run_callback(pm_callback_t cb, struct device *dev, 6 | calltime = initcall_debug_start(dev); 7 | 8 | pm_dev_dbg(dev, state, info); 9 | + trace_device_pm_callback_start(dev, info, state.event); 10 | error = cb(dev); 11 | + trace_device_pm_callback_end(dev, error); 12 | suspend_report_result(cb, error); 13 | 14 | initcall_debug_report(dev, calltime, error); 15 | @@ -758,7 +760,9 @@ static void device_complete(struct device *dev, pm_message_t state) 16 | 17 | if (callback) { 18 | pm_dev_dbg(dev, state, info); 19 | + trace_device_pm_callback_start(dev, info, state.event); 20 | callback(dev); 21 | + trace_device_pm_callback_end(dev, 0); 22 | } 23 | 24 | device_unlock(dev); 25 | @@ -1039,14 +1043,17 @@ EXPORT_SYMBOL_GPL(dpm_suspend_end); 26 | * @cb: Suspend callback to execute. 27 | */ 28 | static int legacy_suspend(struct device *dev, pm_message_t state, 29 | - int (*cb)(struct device *dev, pm_message_t state)) 30 | + int (*cb)(struct device *dev, pm_message_t state), 31 | + char *info) 32 | { 33 | int error; 34 | ktime_t calltime; 35 | 36 | calltime = initcall_debug_start(dev); 37 | 38 | + trace_device_pm_callback_start(dev, info, state.event); 39 | error = cb(dev, state); 40 | + trace_device_pm_callback_end(dev, error); 41 | suspend_report_result(cb, error); 42 | 43 | initcall_debug_report(dev, calltime, error); 44 | @@ -1109,7 +1116,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) 45 | goto Run; 46 | } else if (dev->class->suspend) { 47 | pm_dev_dbg(dev, state, "legacy class "); 48 | - error = legacy_suspend(dev, state, dev->class->suspend); 49 | + error = legacy_suspend(dev, state, dev->class->suspend, 50 | + "legacy class "); 51 | goto End; 52 | } 53 | } 54 | @@ -1120,7 +1128,8 @@ static int __device_suspend(struct device *dev, pm_message_t state, bool async) 55 | callback = pm_op(dev->bus->pm, state); 56 | } else if (dev->bus->suspend) { 57 | pm_dev_dbg(dev, state, "legacy bus "); 58 | - error = legacy_suspend(dev, state, dev->bus->suspend); 59 | + error = legacy_suspend(dev, state, dev->bus->suspend, 60 | + "legacy bus "); 61 | goto End; 62 | } 63 | } 64 | @@ -1276,7 +1285,9 @@ static int device_prepare(struct device *dev, pm_message_t state) 65 | } 66 | 67 | if (callback) { 68 | + trace_device_pm_callback_start(dev, info, state.event); 69 | error = callback(dev); 70 | + trace_device_pm_callback_end(dev, error); 71 | suspend_report_result(callback, error); 72 | } 73 | 74 | diff --git a/include/trace/events/power.h b/include/trace/events/power.h 75 | index 55c022a..2157d70 100644 76 | --- a/include/trace/events/power.h 77 | +++ b/include/trace/events/power.h 78 | @@ -44,6 +44,17 @@ DEFINE_EVENT(cpu, cpu_idle, 79 | #define PWR_EVENT_EXIT -1 80 | #endif 81 | 82 | +#define pm_verb_symbolic(event) \ 83 | + __print_symbolic(event, \ 84 | + { PM_EVENT_SUSPEND, "suspend" }, \ 85 | + { PM_EVENT_RESUME, "resume" }, \ 86 | + { PM_EVENT_FREEZE, "freeze" }, \ 87 | + { PM_EVENT_QUIESCE, "quiesce" }, \ 88 | + { PM_EVENT_HIBERNATE, "hibernate" }, \ 89 | + { PM_EVENT_THAW, "thaw" }, \ 90 | + { PM_EVENT_RESTORE, "restore" }, \ 91 | + { PM_EVENT_RECOVER, "recover" }) 92 | + 93 | DEFINE_EVENT(cpu, cpu_frequency, 94 | 95 | TP_PROTO(unsigned int frequency, unsigned int cpu_id), 96 | @@ -51,6 +62,55 @@ DEFINE_EVENT(cpu, cpu_frequency, 97 | TP_ARGS(frequency, cpu_id) 98 | ); 99 | 100 | +TRACE_EVENT(device_pm_callback_start, 101 | + 102 | + TP_PROTO(struct device *dev, const char *pm_ops, int event_in), 103 | + 104 | + TP_ARGS(dev, pm_ops, event_in), 105 | + 106 | + TP_STRUCT__entry( 107 | + __string(device, dev_name(dev)) 108 | + __string(driver, dev_driver_string(dev)) 109 | + __string(parent, dev->parent ? dev_name(dev->parent) : "none") 110 | + __string(pm_ops, pm_ops ? pm_ops : "none ") 111 | + __field(int, event) 112 | + ), 113 | + 114 | + TP_fast_assign( 115 | + __assign_str(device, dev_name(dev)); 116 | + __assign_str(driver, dev_driver_string(dev)); 117 | + __assign_str(parent, dev->parent ? dev_name(dev->parent) : "none"); 118 | + __assign_str(pm_ops, pm_ops ? pm_ops : "none "); 119 | + __entry->event = event_in; 120 | + ), 121 | + 122 | + TP_printk("%s %s, parent: %s, %s[%s]", __get_str(driver), 123 | + __get_str(device), __get_str(parent), __get_str(pm_ops), 124 | + pm_verb_symbolic(__entry->event)) 125 | +); 126 | + 127 | +TRACE_EVENT(device_pm_callback_end, 128 | + 129 | + TP_PROTO(struct device *dev, int error_in), 130 | + 131 | + TP_ARGS(dev, error_in), 132 | + 133 | + TP_STRUCT__entry( 134 | + __string(device, dev_name(dev)) 135 | + __string(driver, dev_driver_string(dev)) 136 | + __field(int, error) 137 | + ), 138 | + 139 | + TP_fast_assign( 140 | + __assign_str(device, dev_name(dev)); 141 | + __assign_str(driver, dev_driver_string(dev)); 142 | + __entry->error = error_in; 143 | + ), 144 | + 145 | + TP_printk("%s %s, err=%d", 146 | + __get_str(driver), __get_str(device), __entry->error) 147 | +); 148 | + 149 | TRACE_EVENT(suspend_resume, 150 | 151 | TP_PROTO(const char *action, int val, bool start), 152 | -------------------------------------------------------------------------------- /kernel/extra-timeline-detail/1-trace_suspend_resume_from_module.patch: -------------------------------------------------------------------------------- 1 | diff --git a/kernel/trace/power-traces.c b/kernel/trace/power-traces.c 2 | index 1c71382..eb4220a 100644 3 | --- a/kernel/trace/power-traces.c 4 | +++ b/kernel/trace/power-traces.c 5 | @@ -13,5 +13,6 @@ 6 | #define CREATE_TRACE_POINTS 7 | #include 8 | 9 | +EXPORT_TRACEPOINT_SYMBOL_GPL(suspend_resume); 10 | EXPORT_TRACEPOINT_SYMBOL_GPL(cpu_idle); 11 | 12 | -------------------------------------------------------------------------------- /kernel/extra-timeline-detail/2-ata_port_resume_async.patch: -------------------------------------------------------------------------------- 1 | diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c 2 | index c5ba15a..5df566a 100644 3 | --- a/drivers/ata/libata-core.c 4 | +++ b/drivers/ata/libata-core.c 5 | @@ -69,6 +69,7 @@ 6 | #include 7 | #include 8 | #include 9 | +#include 10 | 11 | #include "libata.h" 12 | #include "libata-transport.h" 13 | @@ -3289,6 +3290,7 @@ static int ata_dev_set_mode(struct ata_device *dev) 14 | ata_mode_string(ata_xfer_mode2mask(dev->xfer_mode)), 15 | dev_err_whine); 16 | 17 | + trace_suspend_resume(TPS("ATA"), ap->print_id, false); 18 | return 0; 19 | 20 | fail: 21 | -------------------------------------------------------------------------------- /kernel/extra-timeline-detail/3-i915-first-page-flip-after-resume.patch: -------------------------------------------------------------------------------- 1 | diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c 2 | index 2318b4c..e6ce7b1c 100644 3 | --- a/drivers/gpu/drm/i915/i915_drv.c 4 | +++ b/drivers/gpu/drm/i915/i915_drv.c 5 | @@ -658,6 +658,8 @@ static int __i915_drm_thaw(struct drm_device *dev, bool restore_gtt_mappings) 6 | { 7 | struct drm_i915_private *dev_priv = dev->dev_private; 8 | 9 | + dev_priv->trace_page_flip = true; // we are resuming, trace first flip 10 | + 11 | if (drm_core_check_feature(dev, DRIVER_MODESET) && 12 | restore_gtt_mappings) { 13 | mutex_lock(&dev->struct_mutex); 14 | diff --git a/drivers/gpu/drm/i915/i915_drv.h b/drivers/gpu/drm/i915/i915_drv.h 15 | index 16a6f6d..2cd71ff 100644 16 | --- a/drivers/gpu/drm/i915/i915_drv.h 17 | +++ b/drivers/gpu/drm/i915/i915_drv.h 18 | @@ -1673,6 +1673,8 @@ struct drm_i915_private { 19 | /* Old ums support infrastructure, same warning applies. */ 20 | struct i915_ums_state ums; 21 | 22 | + bool trace_page_flip; // First page flip after S3 trace flag 23 | + 24 | /* Abstract the submission mechanism (legacy ringbuffer or execlists) away */ 25 | struct { 26 | int (*do_execbuf)(struct drm_device *dev, struct drm_file *file, 27 | diff --git a/drivers/gpu/drm/i915/intel_display.c b/drivers/gpu/drm/i915/intel_display.c 28 | index f0a1a56..3707aa5 100644 29 | --- a/drivers/gpu/drm/i915/intel_display.c 30 | +++ b/drivers/gpu/drm/i915/intel_display.c 31 | @@ -42,6 +42,7 @@ 32 | #include 33 | #include 34 | #include 35 | +#include 36 | 37 | /* Primary plane formats supported by all gen */ 38 | #define COMMON_PRIMARY_FORMATS \ 39 | @@ -10064,6 +10065,11 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc, 40 | 41 | trace_i915_flip_request(intel_crtc->plane, obj); 42 | 43 | + if (dev_priv->trace_page_flip) { 44 | + dev_priv->trace_page_flip = false; // reset to only track once 45 | + trace_suspend_resume(TPS("i915_page_flip"), 0, false); 46 | + } 47 | + 48 | return 0; 49 | 50 | cleanup_unpin: 51 | @@ -12132,6 +12138,8 @@ static void intel_crtc_init(struct drm_device *dev, int pipe) 52 | struct drm_plane *cursor = NULL; 53 | int i, ret; 54 | 55 | + dev_priv->trace_page_flip = false; // reset S3 page flip to no trace 56 | + 57 | intel_crtc = kzalloc(sizeof(*intel_crtc), GFP_KERNEL); 58 | if (intel_crtc == NULL) 59 | return; 60 | -------------------------------------------------------------------------------- /kernel/pre-3.11-rc2/enable_ftrace_in_suspendresume.patch: -------------------------------------------------------------------------------- 1 | diff --git a/kernel/power/suspend.c b/kernel/power/suspend.c 2 | index bef86d1..6c23af7 100644 3 | --- a/kernel/power/suspend.c 4 | +++ b/kernel/power/suspend.c 5 | @@ -210,6 +210,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) 6 | goto Platform_wake; 7 | } 8 | 9 | + ftrace_stop(); 10 | error = disable_nonboot_cpus(); 11 | if (error || suspend_test(TEST_CPUS)) 12 | goto Enable_cpus; 13 | @@ -232,6 +233,7 @@ static int suspend_enter(suspend_state_t state, bool *wakeup) 14 | 15 | Enable_cpus: 16 | enable_nonboot_cpus(); 17 | + ftrace_start(); 18 | 19 | Platform_wake: 20 | if (need_suspend_ops(state) && suspend_ops->wake) 21 | @@ -265,7 +267,6 @@ int suspend_devices_and_enter(suspend_state_t state) 22 | goto Close; 23 | } 24 | suspend_console(); 25 | - ftrace_stop(); 26 | suspend_test_start(); 27 | error = dpm_suspend_start(PMSG_SUSPEND); 28 | if (error) { 29 | @@ -285,7 +286,6 @@ int suspend_devices_and_enter(suspend_state_t state) 30 | suspend_test_start(); 31 | dpm_resume_end(PMSG_RESUME); 32 | suspend_test_finish("resume devices"); 33 | - ftrace_start(); 34 | resume_console(); 35 | Close: 36 | if (need_suspend_ops(state) && suspend_ops->end) 37 | -------------------------------------------------------------------------------- /kernel/pre-3.15/enable_trace_events_device_pm_callback.patch: -------------------------------------------------------------------------------- 1 | Adds two trace events which supply the same info that initcall_debug 2 | provides, but via ftrace instead of dmesg. The existing initcall_debug 3 | calls require the pm_print_times_enabled var to be set (either via 4 | sysfs or via the kernel cmd line). The new trace events provide all the 5 | same info as the initcall_debug prints but with less overhead, and also 6 | with coverage of device prepare and complete device callbacks. 7 | 8 | These events replace the device_pm_report_time event (which has been 9 | removed). device_pm_callback_start is called first and provides the device 10 | and callback info. device_pm_callback_end is called after with the 11 | device name and error info. The time and pid are gathered from the trace 12 | data headers. 13 | 14 | Signed-off-by: Todd Brandt 15 | ---- 16 | drivers/base/power/main.c | 14 ++++++++++---- 17 | include/trace/events/power.h | 60 ++++++++++++++++++++++++++++++++++++++++++------------------ 18 | 2 files changed, 52 insertions(+), 22 deletions(-) 19 | 20 | Raphael, I know we discussed this a while back as an alternative to 21 | the initcall_debug calls so as to reduce the dmesg traffic. Do you want 22 | to completely remove the pm_print_times_enabled option and initcall_debug 23 | calls? 24 | 25 | Also, I applied this patch to the bleeding-edge branch of your linux-pm 26 | tree. 27 | 28 | diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c 29 | index de3fe4f..bf41296 100644 30 | --- a/drivers/base/power/main.c 31 | +++ b/drivers/base/power/main.c 32 | @@ -214,9 +214,6 @@ static void initcall_debug_report(struct device *dev, ktime_t calltime, 33 | pr_info("call %s+ returned %d after %Ld usecs\n", dev_name(dev), 34 | error, (unsigned long long)nsecs >> 10); 35 | } 36 | - 37 | - trace_device_pm_report_time(dev, info, nsecs, pm_verb(state.event), 38 | - error); 39 | } 40 | 41 | /** 42 | @@ -387,7 +384,9 @@ static int dpm_run_callback(pm_callback_t cb, struct device *dev, 43 | calltime = initcall_debug_start(dev); 44 | 45 | pm_dev_dbg(dev, state, info); 46 | + trace_device_pm_callback_start(dev, info, state.event); 47 | error = cb(dev); 48 | + trace_device_pm_callback_end(dev, error); 49 | suspend_report_result(cb, error); 50 | 51 | initcall_debug_report(dev, calltime, error, state, info); 52 | @@ -919,7 +918,9 @@ static void device_complete(struct device *dev, pm_message_t state) 53 | 54 | if (callback) { 55 | pm_dev_dbg(dev, state, info); 56 | + trace_device_pm_callback_start(dev, info, state.event); 57 | callback(dev); 58 | + trace_device_pm_callback_end(dev, 0); 59 | } 60 | 61 | device_unlock(dev); 62 | @@ -1307,7 +1308,9 @@ static int legacy_suspend(struct device *dev, pm_message_t state, 63 | 64 | calltime = initcall_debug_start(dev); 65 | 66 | + trace_device_pm_callback_start(dev, info, state.event); 67 | error = cb(dev, state); 68 | + trace_device_pm_callback_end(dev, error); 69 | suspend_report_result(cb, error); 70 | 71 | initcall_debug_report(dev, calltime, error, state, info); 72 | @@ -1563,8 +1566,11 @@ static int device_prepare(struct device *dev, pm_message_t state) 73 | callback = dev->driver->pm->prepare; 74 | } 75 | 76 | - if (callback) 77 | + if (callback) { 78 | + trace_device_pm_callback_start(dev, info, state.event); 79 | ret = callback(dev); 80 | + trace_device_pm_callback_end(dev, ret); 81 | + } 82 | 83 | device_unlock(dev); 84 | 85 | diff --git a/include/trace/events/power.h b/include/trace/events/power.h 86 | index f88c857..d19840b 100644 87 | --- a/include/trace/events/power.h 88 | +++ b/include/trace/events/power.h 89 | @@ -93,6 +93,17 @@ TRACE_EVENT(pstate_sample, 90 | #define PWR_EVENT_EXIT -1 91 | #endif 92 | 93 | +#define pm_verb_symbolic(event) \ 94 | + __print_symbolic(event, \ 95 | + { PM_EVENT_SUSPEND, "suspend" }, \ 96 | + { PM_EVENT_RESUME, "resume" }, \ 97 | + { PM_EVENT_FREEZE, "freeze" }, \ 98 | + { PM_EVENT_QUIESCE, "quiesce" }, \ 99 | + { PM_EVENT_HIBERNATE, "hibernate" }, \ 100 | + { PM_EVENT_THAW, "thaw" }, \ 101 | + { PM_EVENT_RESTORE, "restore" }, \ 102 | + { PM_EVENT_RECOVER, "recover" }) 103 | + 104 | DEFINE_EVENT(cpu, cpu_frequency, 105 | 106 | TP_PROTO(unsigned int frequency, unsigned int cpu_id), 107 | @@ -100,41 +111,54 @@ DEFINE_EVENT(cpu, cpu_frequency, 108 | TP_ARGS(frequency, cpu_id) 109 | ); 110 | 111 | -TRACE_EVENT(device_pm_report_time, 112 | +TRACE_EVENT(device_pm_callback_start, 113 | 114 | - TP_PROTO(struct device *dev, const char *pm_ops, s64 ops_time, 115 | - char *pm_event_str, int error), 116 | + TP_PROTO(struct device *dev, const char *pm_ops, int event), 117 | 118 | - TP_ARGS(dev, pm_ops, ops_time, pm_event_str, error), 119 | + TP_ARGS(dev, pm_ops, event), 120 | 121 | TP_STRUCT__entry( 122 | __string(device, dev_name(dev)) 123 | __string(driver, dev_driver_string(dev)) 124 | __string(parent, dev->parent ? dev_name(dev->parent) : "none") 125 | __string(pm_ops, pm_ops ? pm_ops : "none ") 126 | - __string(pm_event_str, pm_event_str) 127 | - __field(s64, ops_time) 128 | - __field(int, error) 129 | + __field(int, event) 130 | ), 131 | 132 | TP_fast_assign( 133 | - const char *tmp = dev->parent ? dev_name(dev->parent) : "none"; 134 | - const char *tmp_i = pm_ops ? pm_ops : "none "; 135 | + __assign_str(device, dev_name(dev)); 136 | + __assign_str(driver, dev_driver_string(dev)); 137 | + __assign_str(parent, 138 | + dev->parent ? dev_name(dev->parent) : "none"); 139 | + __assign_str(pm_ops, pm_ops ? pm_ops : "none "); 140 | + __entry->event = event; 141 | + ), 142 | + 143 | + TP_printk("%s %s, parent: %s, %s[%s]", __get_str(driver), 144 | + __get_str(device), __get_str(parent), __get_str(pm_ops), 145 | + pm_verb_symbolic(__entry->event)) 146 | +); 147 | + 148 | +TRACE_EVENT(device_pm_callback_end, 149 | + 150 | + TP_PROTO(struct device *dev, int error), 151 | 152 | + TP_ARGS(dev, error), 153 | + 154 | + TP_STRUCT__entry( 155 | + __string(device, dev_name(dev)) 156 | + __string(driver, dev_driver_string(dev)) 157 | + __field(int, error) 158 | + ), 159 | + 160 | + TP_fast_assign( 161 | __assign_str(device, dev_name(dev)); 162 | __assign_str(driver, dev_driver_string(dev)); 163 | - __assign_str(parent, tmp); 164 | - __assign_str(pm_ops, tmp_i); 165 | - __assign_str(pm_event_str, pm_event_str); 166 | - __entry->ops_time = ops_time; 167 | __entry->error = error; 168 | ), 169 | 170 | - /* ops_str has an extra space at the end */ 171 | - TP_printk("%s %s parent=%s state=%s ops=%snsecs=%lld err=%d", 172 | - __get_str(driver), __get_str(device), __get_str(parent), 173 | - __get_str(pm_event_str), __get_str(pm_ops), 174 | - __entry->ops_time, __entry->error) 175 | + TP_printk("%s %s, err=%d", 176 | + __get_str(driver), __get_str(device), __entry->error) 177 | ); 178 | 179 | TRACE_EVENT(suspend_resume, 180 | -------------------------------------------------------------------------------- /kernel/usb/0000-cover-letter.patch: -------------------------------------------------------------------------------- 1 | From 6e4ebb4aa3c394ad9d4cef44cfd6ada5ee0a5c10 Mon Sep 17 00:00:00 2001 2 | Message-Id: 3 | From: Todd Brandt 4 | Date: Fri, 6 Jan 2017 14:18:24 -0800 5 | Subject: [PATCH v5 0/2] USB: resume time optimization by using spec minimums 6 | 7 | The USB resume code in the kernel currently uses a set of hard coded 8 | delay values that are defined in the USB 2.0 spec. These are the 9 | most important ones: 10 | 11 | - tdrsmdn: resume signal time (20ms - infinity) usb 2.0 spec 7.1.7.7 12 | - trsmrcy: resume recovery time (10ms) usb 2.0 spec 7.1.7.7 13 | - trstrcy: reset recovery time (0ms - infinity) usb 2.0 spec 7.1.7.5 14 | - tdrstr: root port reset time (50ms) usb2.0 spec 7.1.7.5 15 | 16 | Some of these values have been padded considerably in order to accomodate 17 | non-compliant devices. 18 | 19 | - tdrsmdn: resume signal time = 40ms 20 | - trstrcy: reset recovery time = 50ms 21 | 22 | I propose that we provide a kernel parameter that sets the USB timing 23 | values to their spec minimums. The following patches do this by creating 24 | a global struct which contains these values. By default the values remain 25 | as they are now, but if usbcore.timing_minimum=1 is added to the kernel cmd 26 | line they're set to their minimums. This struct can be expanded over time 27 | to include other hardcoded values that have padding we can remove. 28 | 29 | The patch is also useful in padding delay values even further for really 30 | temperamental devices. 31 | 32 | I've created a blog entry on 01.org with some analyze_suspend test 33 | cases illustrating the benefits: 34 | 35 | - https://01.org/suspendresume/blogs/tebrandt/2016/usb-resume-optimization-using-spec-minimum-delays 36 | 37 | Todd Brandt (2): 38 | USB: add switch to turn off padding of resume time delays 39 | USB: usb timing value debug 40 | 41 | Documentation/admin-guide/kernel-parameters.txt | 7 +++ 42 | drivers/usb/common/common.c | 8 +++ 43 | drivers/usb/core/hub.c | 12 ++--- 44 | drivers/usb/core/usb.c | 68 +++++++++++++++++++++++++ 45 | drivers/usb/dwc2/hcd.c | 2 +- 46 | drivers/usb/host/ehci-hcd.c | 4 +- 47 | drivers/usb/host/ehci-hub.c | 6 +-- 48 | drivers/usb/host/fotg210-hcd.c | 2 +- 49 | drivers/usb/host/isp116x-hcd.c | 2 +- 50 | drivers/usb/host/isp1362-hcd.c | 2 +- 51 | drivers/usb/host/ohci-hub.c | 2 +- 52 | drivers/usb/host/oxu210hp-hcd.c | 4 +- 53 | drivers/usb/host/r8a66597-hcd.c | 2 +- 54 | drivers/usb/host/sl811-hcd.c | 2 +- 55 | drivers/usb/host/uhci-hub.c | 6 +-- 56 | drivers/usb/host/xhci-hub.c | 6 +-- 57 | drivers/usb/host/xhci-ring.c | 2 +- 58 | drivers/usb/isp1760/isp1760-hcd.c | 2 +- 59 | drivers/usb/musb/musb_core.c | 6 +-- 60 | drivers/usb/musb/musb_virthub.c | 2 +- 61 | include/linux/usb.h | 26 +++++++++- 62 | 21 files changed, 140 insertions(+), 33 deletions(-) 63 | 64 | -- 65 | 2.1.4 66 | 67 | -------------------------------------------------------------------------------- /kernel/usb/0002-USB-usb-timing-value-debug.patch: -------------------------------------------------------------------------------- 1 | From 6e4ebb4aa3c394ad9d4cef44cfd6ada5ee0a5c10 Mon Sep 17 00:00:00 2001 2 | Message-Id: <6e4ebb4aa3c394ad9d4cef44cfd6ada5ee0a5c10.1483741104.git.todd.e.brandt@linux.intel.com> 3 | In-Reply-To: 4 | References: 5 | From: Todd Brandt 6 | Date: Fri, 6 Jan 2017 14:15:10 -0800 7 | Subject: [PATCH v5 2/2] USB: usb timing value debug 8 | 9 | add debugfs support for experimenting with USB timing delay 10 | values on the fly. Values are read/written from debugfs at 11 | /sys/kernel/debug/usb/timing. 12 | 13 | Signed-off-by: Todd Brandt 14 | --- 15 | drivers/usb/core/usb.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++ 16 | 1 file changed, 58 insertions(+) 17 | 18 | diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c 19 | index ac31263..bef73c2 100644 20 | --- a/drivers/usb/core/usb.c 21 | +++ b/drivers/usb/core/usb.c 22 | @@ -39,6 +39,8 @@ 23 | #include 24 | #include 25 | #include 26 | +#include 27 | +#include 28 | #include 29 | 30 | #include 31 | @@ -1036,6 +1038,52 @@ struct dentry *usb_debug_root; 32 | EXPORT_SYMBOL_GPL(usb_debug_root); 33 | 34 | static struct dentry *usb_debug_devices; 35 | +static struct dentry *usb_debug_timing; 36 | + 37 | +static int usb_timing_show(struct seq_file *s, void *unused) 38 | +{ 39 | + seq_printf(s, "tdrsmdn=%d\n", usb_timing.tdrsmdn); 40 | + seq_printf(s, "trsmrcy=%d\n", usb_timing.trsmrcy); 41 | + seq_printf(s, "trstrcy=%d\n", usb_timing.trstrcy); 42 | + seq_printf(s, "tdrstr=%d\n", usb_timing.tdrstr); 43 | + return 0; 44 | +} 45 | + 46 | +static int usb_timing_open(struct inode *inode, struct file *file) 47 | +{ 48 | + return single_open(file, usb_timing_show, inode->i_private); 49 | +} 50 | + 51 | +static ssize_t usb_timing_write(struct file *file, 52 | + const char __user *ubuf, size_t count, loff_t *ppos) 53 | +{ 54 | + int val; 55 | + char buf[32]; 56 | + 57 | + if (copy_from_user(&buf, ubuf, min_t(size_t, sizeof(buf) - 1, count))) 58 | + return -EFAULT; 59 | + 60 | + if (sscanf(buf, "tdrsmdn=%u", &val) == 1) 61 | + usb_timing.tdrsmdn = max(val, USB_TIMING_TDRSMDN_MIN); 62 | + else if (sscanf(buf, "trsmrcy=%u", &val) == 1) 63 | + usb_timing.trsmrcy = max(val, USB_TIMING_TRSMRCY_MIN); 64 | + else if (sscanf(buf, "trstrcy=%u", &val) == 1) 65 | + usb_timing.trstrcy = max(val, USB_TIMING_TRSTRCY_MIN); 66 | + else if (sscanf(buf, "tdrstr=%u", &val) == 1) 67 | + usb_timing.tdrstr = max(val, USB_TIMING_TDRSTR_MIN); 68 | + else 69 | + return -EINVAL; 70 | + 71 | + return count; 72 | +} 73 | + 74 | +static const struct file_operations usbfs_timing_fops = { 75 | + .open = usb_timing_open, 76 | + .write = usb_timing_write, 77 | + .read = seq_read, 78 | + .llseek = seq_lseek, 79 | + .release = single_release, 80 | +}; 81 | 82 | static int usb_debugfs_init(void) 83 | { 84 | @@ -1052,11 +1100,21 @@ static int usb_debugfs_init(void) 85 | return -ENOENT; 86 | } 87 | 88 | + usb_debug_timing = debugfs_create_file("timing", 0644, 89 | + usb_debug_root, NULL, 90 | + &usbfs_timing_fops); 91 | + if (!usb_debug_timing) { 92 | + debugfs_remove(usb_debug_root); 93 | + usb_debug_root = NULL; 94 | + return -ENOENT; 95 | + } 96 | + 97 | return 0; 98 | } 99 | 100 | static void usb_debugfs_cleanup(void) 101 | { 102 | + debugfs_remove(usb_debug_timing); 103 | debugfs_remove(usb_debug_devices); 104 | debugfs_remove(usb_debug_root); 105 | } 106 | -- 107 | 2.1.4 108 | 109 | -------------------------------------------------------------------------------- /lib/__init__.py: -------------------------------------------------------------------------------- 1 | from . import common 2 | from . import googleapi 3 | from . import bugzilla 4 | from . import parallel 5 | from . import remotemachine 6 | from . import argconfig 7 | from . import kernel 8 | -------------------------------------------------------------------------------- /lib/argconfig.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # SPDX-License-Identifier: GPL-2.0-only 3 | # 4 | # ArgConfig library 5 | # Copyright (c) 2020, Intel Corporation. 6 | # 7 | # This program is free software; you can redistribute it and/or modify it 8 | # under the terms and conditions of the GNU General Public License, 9 | # version 2, as published by the Free Software Foundation. 10 | # 11 | # This program is distributed in the hope it will be useful, but WITHOUT 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 | # more details. 15 | # 16 | # Authors: 17 | # Todd Brandt 18 | # 19 | # Description: 20 | # Allow argparse handling to be done with a config file instead 21 | # of on the command line. 22 | 23 | import os 24 | import os.path as op 25 | import argparse 26 | import configparser 27 | 28 | def arg_to_path(args, list): 29 | arglist = vars(args) 30 | for p in list: 31 | if p in arglist: 32 | arglist[p] = op.expanduser(arglist[p]) 33 | 34 | def args_from_config(parser, args, file, section): 35 | booltrue = ['enable', 'on', 'true', '1'] 36 | boolvalues = ['disable', 'off', 'false', '0'] + booltrue 37 | 38 | if not op.exists(file): 39 | return 'config file not found (%s)' % file 40 | Config, cfg = configparser.ConfigParser(), dict() 41 | Config.read(file) 42 | if section not in Config.sections(): 43 | return 'section "%s" not found in config' % section 44 | for opt in Config.options(section): 45 | cfg[opt] = Config.get(section, opt) 46 | 47 | arglist = vars(args) 48 | for key in arglist: 49 | val = arglist[key] 50 | if key not in cfg: 51 | continue 52 | if isinstance(val, bool): 53 | if cfg[key].lower() not in boolvalues: 54 | return '%s -> %s: "%s" is not bool' % (file, key, cfg[key]) 55 | if cfg[key].lower() in booltrue: 56 | arglist[key] = True 57 | else: 58 | arglist[key] = False 59 | elif isinstance(val, int) and not val: 60 | try: 61 | arglist[key] = int(cfg[key]) 62 | except: 63 | return '%s -> %s: "%s" is not int' % (file, key, cfg[key]) 64 | elif isinstance(val, float) and not val: 65 | try: 66 | arglist[key] = float(cfg[key]) 67 | except: 68 | return '%s -> %s: "%s" is not float' % (file, key, cfg[key]) 69 | elif isinstance(val, str): 70 | if not val: 71 | arglist[key] = cfg[key] 72 | elif val in ['blank', 'empty', 'null']: 73 | arglist[key] = '' 74 | 75 | return '' 76 | -------------------------------------------------------------------------------- /lib/common.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # SPDX-License-Identifier: GPL-2.0-only 3 | # 4 | # RemoteMachine library 5 | # Copyright (c) 2020, Intel Corporation. 6 | # 7 | # This program is free software; you can redistribute it and/or modify it 8 | # under the terms and conditions of the GNU General Public License, 9 | # version 2, as published by the Free Software Foundation. 10 | # 11 | # This program is distributed in the hope it will be useful, but WITHOUT 12 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 14 | # more details. 15 | # 16 | # Authors: 17 | # Todd Brandt 18 | # 19 | # Description: 20 | # common functions 21 | 22 | import os 23 | import sys 24 | import re 25 | import time 26 | from subprocess import call, Popen, PIPE 27 | 28 | mystarttime = time.time() 29 | def pprint(msg, withtime=True): 30 | if withtime: 31 | print('[%05d] %s' % (time.time()-mystarttime, msg)) 32 | else: 33 | print(msg) 34 | sys.stdout.flush() 35 | 36 | def printlines(out): 37 | if not out.strip(): 38 | return 39 | for line in out.split('\n'): 40 | if line.strip(): 41 | pprint(line.strip()) 42 | 43 | def ascii(text): 44 | return text.decode('ascii', 'ignore') 45 | 46 | def doError(msg): 47 | pprint('ERROR: %s\n' % msg) 48 | sys.exit(1) 49 | 50 | def runcmd(cmd, output=False, fatal=True): 51 | out = [] 52 | p = Popen(cmd.split(), stderr=PIPE, stdout=PIPE) 53 | for line in p.stdout: 54 | line = ascii(line).strip() 55 | if output: 56 | pprint(line) 57 | out.append(line) 58 | if fatal and p.poll(): 59 | doError(cmd) 60 | return out 61 | 62 | def userprompt(text, values): 63 | while True: 64 | res = input('\n'+text+' ') 65 | if res in values: 66 | return res 67 | print('Valid responese are %s' % values) 68 | return '' 69 | 70 | def userprompt_yesno(text): 71 | out = userprompt(text, ['yes', 'y', 'no', 'n']) 72 | if out[0] == 'y': 73 | return True 74 | return False 75 | 76 | def printRecursive(out, tab=''): 77 | if type(out) != type(dict()): 78 | print(out) 79 | return 80 | for i in sorted(out): 81 | if type(out[i]) == type(dict()): 82 | print('%s%s:' % (tab, i)) 83 | printRecursive(out[i], tab+' ') 84 | continue 85 | elif type(out[i]) == type([]): 86 | names = [] 87 | for j in out[i]: 88 | names.append(j[0][:20]) 89 | print('%s%s: %s' % (tab, i, ','.join(names))) 90 | else: 91 | print('%s%s: %s' % (tab, i, out[i])) 92 | -------------------------------------------------------------------------------- /lib/kernel.py: -------------------------------------------------------------------------------- 1 | 2 | #!/usr/bin/env python3 3 | # SPDX-License-Identifier: GPL-2.0-only 4 | # 5 | # RemoteMachine library 6 | # Copyright (c) 2020, Intel Corporation. 7 | # 8 | # This program is free software; you can redistribute it and/or modify it 9 | # under the terms and conditions of the GNU General Public License, 10 | # version 2, as published by the Free Software Foundation. 11 | # 12 | # This program is distributed in the hope it will be useful, but WITHOUT 13 | # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14 | # FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15 | # more details. 16 | # 17 | # Authors: 18 | # Todd Brandt 19 | # 20 | # Description: 21 | # functions for manipulating kernel source and git repos 22 | 23 | import os 24 | import os.path as op 25 | import sys 26 | import re 27 | import shutil 28 | import time 29 | from tempfile import mkdtemp 30 | from subprocess import call, Popen, PIPE 31 | from lib.common import mystarttime, pprint, printlines, ascii, runcmd 32 | 33 | def doError(msg): 34 | pprint('ERROR: %s\n' % msg) 35 | sys.exit(1) 36 | 37 | def isgit(src): 38 | return op.exists(op.join(src, '.git/config')) 39 | 40 | def clone(): 41 | repo = 'http://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git' 42 | src = mkdtemp(prefix='linux') 43 | pprint('Cloning new kernel source tree ...') 44 | call('git clone %s %s' % (repo, src), shell=True) 45 | return src 46 | 47 | def configure(src, cfg, isgit): 48 | kconfig = '' 49 | if not op.exists(cfg) or not op.isdir(cfg): 50 | doError('%s is not an existing folder' % cfg) 51 | patches = [] 52 | for file in sorted(os.listdir(cfg)): 53 | if file.endswith('.patch'): 54 | patches.append(op.join(cfg, file)) 55 | elif file.endswith('.config'): 56 | kconfig = op.join(cfg, file) 57 | if len(patches) > 0: 58 | if isgit: 59 | runcmd('git -C %s checkout .' % src, True) 60 | for patch in sorted(patches): 61 | runcmd('patch -N -d %s -i %s -p1' % (src, patch), True, False) 62 | if not kconfig: 63 | doError('Missing kernel config file') 64 | runcmd('cp %s %s' % (kconfig, op.join(src, '.config')), True) 65 | return kconfig 66 | 67 | def getconfig(cfg): 68 | if not op.exists(cfg) or not op.isdir(cfg): 69 | doError('%s is not an existing folder' % cfg) 70 | for file in sorted(os.listdir(cfg)): 71 | if file.endswith('.config'): 72 | return op.join(cfg, file) 73 | return '' 74 | 75 | def turbostatbuild(src, latest=False): 76 | if not op.exists(src) or not op.isdir(src): 77 | doError('%s is not an existing folder' % src) 78 | isgit = op.exists(op.join(src, '.git/config')) 79 | if isgit and latest: 80 | runcmd('git -C %s checkout .' % src, True) 81 | runcmd('git -C %s pull' % src, True) 82 | tdir = op.join(src, 'tools/power/x86/turbostat') 83 | if op.isdir(tdir): 84 | call('make -C %s clean' % tdir, shell=True) 85 | call('make -C %s turbostat' % tdir, shell=True) 86 | call('%s/turbostat -v' % tdir, shell=True) 87 | 88 | def clean(src, kconfig, latest=False): 89 | if latest and isgit(src): 90 | runcmd('git -C %s checkout .' % src, True) 91 | runcmd('git -C %s pull' % src, True) 92 | runcmd('make -C %s distclean' % src, True) 93 | runcmd('cp %s %s' % (kconfig, op.join(src, '.config')), True) 94 | 95 | def build(src, pkgfmt, name): 96 | try: 97 | numcpu = int(runcmd('getconf _NPROCESSORS_ONLN', False, False)[0]) 98 | except: 99 | numcpu = 2 100 | if pkgfmt == 'rpm' and not runcmd('which rpmbuild', False, False): 101 | doError('rpmbuild is required to build rpm packages') 102 | runcmd('make -C %s olddefconfig' % src, True) 103 | if name: 104 | kver = '%s-%s' % (runcmd('make -s -C %s kernelversion' % src)[0], name) 105 | out = runcmd('make -C %s -j %d bin%s-pkg LOCALVERSION=-%s' % \ 106 | (src, numcpu, pkgfmt, name), True) 107 | else: 108 | kver = runcmd('make -s -C %s kernelrelease' % src)[0] 109 | out = runcmd('make -C %s -j %d bin%s-pkg' % \ 110 | (src, numcpu, pkgfmt), True) 111 | outdir, packages = '', [] 112 | for line in out: 113 | if line.startswith('dpkg-deb: building package'): 114 | m = re.match('.* in \'(?P

\S*)\'\.', line) 115 | if m: 116 | file = op.abspath(os.path.join(src, m.group('p'))) 117 | outdir = op.dirname(file) 118 | packages.append(op.basename(file)) 119 | else: 120 | doError('build log format error, unable to find deb package names') 121 | elif line.startswith('Wrote:'): 122 | m = re.match('Wrote: (?P

\S*)', line) 123 | if m: 124 | file = op.abspath(m.group('p')) 125 | outdir = op.dirname(file) 126 | packages.append(op.basename(file)) 127 | else: 128 | doError('build log format error, unable to find rpm package names') 129 | turbostatbuild(src) 130 | return (outdir, kver, packages) 131 | 132 | def move_packages(src, dst, packages): 133 | if not op.exists(dst): 134 | os.makedirs(dst) 135 | if src == os.path.realpath(dst): 136 | return 137 | for file in packages: 138 | tgt = os.path.join(dst, file) 139 | if op.exists(tgt): 140 | pprint('Overwriting %s' % file) 141 | os.remove(tgt) 142 | shutil.move(os.path.join(src, file), dst) 143 | 144 | def kvermatch(kmatch, os, pkgname): 145 | if os in ['ubuntu']: 146 | if pkgname.startswith('linux-headers-'): 147 | kver = pkgname[14:] 148 | elif pkgname.startswith('linux-image-'): 149 | if pkgname.endswith('-dbg'): 150 | kver = pkgname[12:-4] 151 | else: 152 | kver = pkgname[12:] 153 | else: 154 | return False 155 | if kmatch == pkgname or kmatch == kver or re.match(kmatch, kver): 156 | return True 157 | elif os in ['fedora', 'centos']: 158 | m = re.match('^kernel-(?P\S*)-[0-9]\.', pkgname) 159 | if not m: 160 | return False 161 | kver = m.group('v').replace('_', '-') 162 | if kmatch == pkgname or kmatch == kver or re.match(kmatch, kver): 163 | return True 164 | return False 165 | 166 | def get_packages_deb(pkgout, version): 167 | packages = [] 168 | for file in sorted(os.listdir(pkgout)): 169 | if not file.startswith('linux-') or not file.endswith('.deb'): 170 | continue 171 | libcver = version.replace('dirty', '1') 172 | if version in file or libcver in file: 173 | packages.append(file) 174 | elif version.endswith('-intel-next+'): 175 | kver = version[:-12].replace('-', '~') 176 | if 'intel-next' in file and kver in file: 177 | packages.append(file) 178 | return packages 179 | 180 | def get_packages_rpm(pkgout, version): 181 | prefix = 'kernel-%s' % version.replace('-', '_') 182 | for file in sorted(os.listdir(pkgout)): 183 | if file.startswith(prefix) and file.endswith('.rpm'): 184 | return [file] 185 | return [] 186 | 187 | def bisect_step_info(out): 188 | for line in out: 189 | m = re.match('\[(?P[a-z,0-9]*)\] .*', line) 190 | if m: 191 | commit = m.group('commit') 192 | return(commit, False) 193 | m = re.match('(?P[a-z,0-9]*) is the first bad commit', line) 194 | if m: 195 | commit = m.group('commit') 196 | return(commit, True) 197 | return ('', True) 198 | 199 | def bisect_start(src, kgood, kbad): 200 | runcmd('git -C %s bisect reset' % src, False) 201 | runcmd('git -C %s bisect start' % src, True) 202 | runcmd('git -C %s bisect good %s' % (src, kgood), True) 203 | out = runcmd('git -C %s bisect bad %s' % (src, kbad), True) 204 | return bisect_step_info(out) 205 | 206 | def bisect_step(src, state): 207 | if state not in ['good', 'bad', 'skip']: 208 | doError('invalid bisect state, need good, bad, or skip: %s' % state) 209 | out = runcmd('git -C %s bisect %s' % (src, state), True) 210 | return bisect_step_info(out) 211 | -------------------------------------------------------------------------------- /tools/buggymon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import sys 4 | import time 5 | import os 6 | import string 7 | import re 8 | from datetime import datetime 9 | import base64 10 | import json 11 | import requests 12 | try: 13 | from urllib import urlencode 14 | except ImportError: 15 | from urllib.parse import urlencode 16 | 17 | def webrequest(url): 18 | try: 19 | res = requests.get(url) 20 | except Exception as e: 21 | print('URL: %s\nException: %s' % (url, str(e))) 22 | return dict() 23 | if res == 0: 24 | print('ERROR: res == 0') 25 | return dict() 26 | res.raise_for_status() 27 | return res.json() 28 | 29 | def bugs(urlprefix): 30 | params = { 31 | 'bug_status' : ['NEW','ASSIGNED','REOPENED','RESOLVED','VERIFIED','DEFERRED','NEEDINFO','CLOSED'], 32 | 'op_sys' : 'Linux', 33 | # 'cf_tree' : 'Mainline', 34 | 'rep_platform' : ['Intel','IA-32','IA-64'], 35 | 'order' : 'bugs.creation_ts desc', 36 | # 'order' : 'bugs.delta_ts desc', 37 | # 'limit' : '800', 38 | } 39 | url = '%s/bug?%s' % (urlprefix, urlencode(params, True)) 40 | res = webrequest(url) 41 | if 'bugs' not in res: 42 | return [] 43 | return res['bugs'] 44 | 45 | def attachments(urlprefix, id): 46 | url = '%s/bug/%s/attachment' % (urlprefix, id) 47 | res = webrequest(url) 48 | if 'bugs' not in res or id not in res['bugs']: 49 | return [] 50 | return res['bugs'][id] 51 | 52 | def parseMachineInfo(atts): 53 | out = [] 54 | for att in atts: 55 | if 'data' not in att: 56 | continue 57 | data = base64.b64decode(att['data']).decode('ascii', 'ignore') 58 | dmi = '' 59 | for line in data.split('\n'): 60 | m = re.match('.*\] DMI: (?P.*)', line) 61 | if m: 62 | dmi = m.group('info').split(', BIOS')[0] 63 | if dmi and dmi not in out: 64 | out.append(dmi) 65 | return out 66 | 67 | if __name__ == '__main__': 68 | 69 | machines = dict() 70 | urlprefix = 'http://bugzilla.kernel.org/rest.cgi' 71 | bugshow = ' - http://bugzilla.kernel.org/show_bug.cgi?id={0} {1}' 72 | 73 | bugs = bugs(urlprefix) 74 | print('%d BUGS FOUND' % len(bugs)) 75 | i = 0 76 | for bug in bugs: 77 | ctime = bug['creation_time'] 78 | bugid = '%d' % bug['id'] 79 | info = bugshow.format(bugid, ctime[:10]) 80 | atts = attachments(urlprefix, bugid) 81 | print('%4d BUG: %sx%d %s' % (i, bugid, len(atts), ctime[:10])) 82 | for m in parseMachineInfo(atts): 83 | if m not in machines: 84 | machines[m] = {'count':1,'bugs':[info]} 85 | else: 86 | machines[m]['count'] += 1 87 | machines[m]['bugs'].append(info) 88 | print('MACHINE: %s, COUNT: %d' % (m, machines[m]['count'])) 89 | i += 1 90 | 91 | print('\nTOTAL MACHINES: %d' % len(machines.keys())) 92 | for m in sorted(machines, key=lambda k:machines[k]['count'], reverse=True): 93 | print('MACHINE: %s, BUGS: %d' % (m, machines[m]['count'])) 94 | for info in machines[m]['bugs']: 95 | print(info) 96 | -------------------------------------------------------------------------------- /tools/config: -------------------------------------------------------------------------------- 1 | ../config -------------------------------------------------------------------------------- /tools/dataserver.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import sys 5 | from tempfile import mktemp 6 | from datetime import datetime 7 | from subprocess import call, Popen, PIPE 8 | from lib.parallel import AsyncProcess 9 | 10 | class DataServer: 11 | def __init__(self, user, host): 12 | self.host = host 13 | self.user = user 14 | def sshcopyid(self): 15 | res = call('ssh-copy-id %s@%s' % (self.user, self.host), shell=True) 16 | return res == 0 17 | def sshkeyworks(self): 18 | cmd = 'ssh -q -o BatchMode=yes -o ConnectTimeout=5 %s@%s echo -n' % \ 19 | (self.user, self.host) 20 | res = call(cmd, shell=True) 21 | return res == 0 22 | def setup(self): 23 | print('Enabling password-less access on %s.\n'\ 24 | 'I will try to add your id_rsa/id_rsa.pub using ssh-copy-id...' %\ 25 | (self.host)) 26 | if not self.sshcopyid(): 27 | return False 28 | if not self.sshkeyworks(): 29 | print('ERROR: failed to setup ssh key access.') 30 | return False 31 | print('SUCCESS: you now have password-less access.\n') 32 | return True 33 | def setupordie(self): 34 | if not self.setup(): 35 | sys.exit(1) 36 | def sshproc(self, cmd, timeout=60): 37 | return AsyncProcess(('ssh %s@%s "{0}"' % (self.user, self.host)).format(cmd), timeout, self.host) 38 | def sshcmd(self, cmd, timeout=60): 39 | ap = self.sshproc(cmd, timeout) 40 | out = ap.runcmd() 41 | if ap.terminated: 42 | print('SSH TIMEOUT: %s' % cmd) 43 | self.die() 44 | return out 45 | def scpfile(self, file, dir): 46 | res = call('scp %s %s@%s:%s/' % (file, self.user, self.host, dir), shell=True) 47 | return res == 0 48 | def tarfolder(self, folder): 49 | pdir, tdir = os.path.dirname(folder), os.path.basename(folder) 50 | pdir = pdir if pdir else '.' 51 | tarball = mktemp(prefix='multitest-data-', suffix='.tar.gz') 52 | print('Taring up %s for transport...' % folder) 53 | res = call('cd %s; tar cvzf %s %s > /dev/null' % (pdir, tarball, tdir), shell=True) 54 | if res != 0: 55 | print('ERROR: failed to create the tarball') 56 | self.die() 57 | return tarball 58 | def uploadfolder(self, folder, monitor): 59 | if not os.path.exists(folder): 60 | print('ERROR: %s does not exist' % folder) 61 | self.die() 62 | tarball = self.tarfolder(folder) if os.path.isdir(folder) else folder 63 | print('Sending tarball to server...') 64 | if not self.scpfile(tarball, '/tmp'): 65 | print('ERROR: could not upload the tarball') 66 | self.die() 67 | rtarball = '/tmp/' + os.path.basename(tarball) 68 | if monitor: 69 | print('Processing the data on the server...') 70 | res = call('ssh %s@%s "multitest %s"' % \ 71 | (self.user, self.host, rtarball), shell=True) 72 | else: 73 | print('Notifying server of new data...') 74 | logfile = self.logfile() 75 | res = call('ssh -n -f %s@%s "multitest %s > %s 2>&1 &"' % \ 76 | (self.user, self.host, rtarball, logfile), shell=True) 77 | print('Logging at %s' % logfile) 78 | print('ssh %s@%s "tail -f %s"' % (self.user, self.host, logfile)) 79 | if res != 0: 80 | print('ERROR: server processing failed') 81 | self.die() 82 | if os.path.isdir(folder): 83 | os.remove(tarball) 84 | print('Upload Complete') 85 | def openshell(self): 86 | call('ssh -X %s@%s' % (self.user, self.host), shell=True) 87 | def hasbandwidth(self): 88 | out = self.sshcmd('ps aux') 89 | count = 0 90 | for line in out.split('\n'): 91 | if 'stresstester' in line and '-webdir' in line: 92 | count += 1 93 | if count > 2: 94 | return False 95 | return True 96 | def istarball(self, file): 97 | print('Verifying integrity %s ...' % file) 98 | res = call('tar -tzf %s > /dev/null 2>&1' % file, shell=True) 99 | return res == 0 100 | def logfile(self): 101 | logfile = 'multitest-%s' % (datetime.now().strftime('%y%m%d-%H%M%S')) 102 | if 'SUDO_USER' in os.environ and os.environ['SUDO_USER']: 103 | logfile += '-' + os.environ['SUDO_USER'] 104 | elif 'USER' in os.environ and os.environ['USER']: 105 | logfile += '-' + os.environ['USER'] 106 | return logfile + '.log' 107 | def die(self): 108 | sys.exit(1) 109 | 110 | # ----------------- MAIN -------------------- 111 | # exec start (skipped if script is loaded as library) 112 | if __name__ == '__main__': 113 | import argparse 114 | 115 | parser = argparse.ArgumentParser() 116 | parser.add_argument('-sshkeysetup', action='store_true', 117 | help='setup password-less access by copying ssh keys') 118 | parser.add_argument('-monitor', action='store_true', 119 | help='Monitor server processing and wait for completion') 120 | parser.add_argument('folder', nargs='?', 121 | help='multitest folder, or "shell" to open an ssh shell') 122 | args = parser.parse_args() 123 | usetarball = False 124 | 125 | if args.folder and args.folder != 'shell' and \ 126 | not os.path.exists(args.folder): 127 | print('ERROR: %s is not a valid file or folder' % args.folder) 128 | sys.exit(1) 129 | 130 | ds = DataServer('sleepgraph', 'otcpl-stress.ostc.intel.com') 131 | 132 | if args.sshkeysetup: 133 | ds.setupordie() 134 | if not args.folder: 135 | sys.exit(0); 136 | 137 | if args.folder == 'shell': 138 | ds.openshell() 139 | sys.exit() 140 | elif not args.folder: 141 | print('ERROR: no folder supplied') 142 | sys.exit(1) 143 | 144 | if not os.path.isdir(args.folder) and not ds.istarball(args.folder): 145 | print('ERROR: %s is not a valid tarball (tar.gz)' % args.folder) 146 | sys.exit(1) 147 | 148 | if not ds.hasbandwidth(): 149 | print('Server is currently processing other data, please try again later.') 150 | print('Exitting...') 151 | sys.exit(1) 152 | 153 | ds.uploadfolder(args.folder, args.monitor) 154 | -------------------------------------------------------------------------------- /tools/googledrive.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | # 3 | # Google Sheet Creator 4 | # 5 | # The following additional packages are required beyond the base install: 6 | # 7 | # python2 package requirements: 8 | # sudo apt-get install python-configparser python-requests python-psutil python-httplib2 python-pip 9 | # sudo pip2 install --upgrade google-api-python-client oauth2client 10 | # 11 | # python3 package requirements: 12 | # sudo apt-get install python3-psutil python3-pip 13 | # sudo pip3 install --upgrade google-api-python-client oauth2client 14 | # 15 | # To run -setup without local browser use this command: 16 | # ./stresstester.py -setup --noauth_local_webserver 17 | # 18 | 19 | import os 20 | import sys 21 | import re 22 | import shutil 23 | import time 24 | import fcntl 25 | from subprocess import call, Popen, PIPE 26 | from datetime import datetime 27 | import argparse 28 | import os.path as op 29 | from lib.googleapi import setupGoogleAPIs, initGoogleAPIs,\ 30 | gdrive_command_simple, gdrive_upload, gdrive_sheet 31 | 32 | if __name__ == '__main__': 33 | 34 | parser = argparse.ArgumentParser(description='Google Sheet Utility') 35 | parser.add_argument('-setup', action='store_true', 36 | help='Setup access to google drive apis via your account') 37 | parser.add_argument('--noauth_local_webserver', action='store_true', 38 | help='Run setup without a local web browser (copy a link, paste a verification string)') 39 | parser.add_argument('-link', metavar='gpath', 40 | help='Get the URL for a given google drive file/folder') 41 | parser.add_argument('-list', metavar='gpath', 42 | help='List the contents of a given google drive folder') 43 | parser.add_argument('-blist', metavar='gpath', 44 | help='List all backup spreadsheets recursively in the given gpath') 45 | parser.add_argument('-bclear', metavar='gpath', 46 | help='Delete all unused backup spreadsheets recursively in the given gpath') 47 | parser.add_argument('-upload', nargs=2, metavar=('local', 'remote'), 48 | help='Upload local file to remote gdrive path') 49 | parser.add_argument('-sheet', nargs=2, metavar=('local', 'remote'), 50 | help='Upload local csv file to remote googlesheet path') 51 | args = parser.parse_args() 52 | if len(sys.argv) < 2: 53 | parser.print_help() 54 | sys.exit(1) 55 | 56 | if args.setup: 57 | sys.exit(setupGoogleAPIs()) 58 | 59 | initGoogleAPIs() 60 | if args.link: 61 | sys.exit(0 if gdrive_command_simple('link', args.link) else 1) 62 | elif args.list: 63 | sys.exit(0 if gdrive_command_simple('list', args.list) else 1) 64 | elif args.blist: 65 | sys.exit(0 if gdrive_command_simple('blist', args.blist) else 1) 66 | elif args.bclear: 67 | sys.exit(0 if gdrive_command_simple('bclear', args.bclear) else 1) 68 | elif args.upload: 69 | sys.exit(0 if gdrive_upload(args.upload[0], args.upload[1]) else 1) 70 | elif args.sheet: 71 | sys.exit(0 if gdrive_sheet(args.sheet[0], args.sheet[1]) else 1) 72 | -------------------------------------------------------------------------------- /tools/intel-multitest-handler.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | validTarball() { 4 | ext=`echo $1 | sed "s/.tar.gz$//"` 5 | if [ $1 != "$ext" ]; then 6 | return 7 | fi 8 | ext=`echo $1 | sed "s/.tgz$//"` 9 | if [ $1 != "$ext" ]; then 10 | return 11 | fi 12 | if [ ! -e $1 ]; then 13 | echo "ERROR: $1 does not exist" 14 | exit 15 | elif [ -d $1 ]; then 16 | echo "ERROR: $1 is a directory, not a tarball" 17 | exit 18 | fi 19 | } 20 | 21 | if [ $# -lt 1 ]; then 22 | echo "stressreport multisheet processer" 23 | echo "USAGE: multitest " 24 | exit 25 | fi 26 | 27 | INSIZE=0 28 | INFILES="" 29 | while [ "$1" ] ; do 30 | validTarball "$1" 31 | SZ=`stat -c %s $1` 32 | INSIZE=$(($SZ + $INSIZE)) 33 | if [ -z "$INFILES" ]; then 34 | INFILES="$1" 35 | else 36 | INFILES="$INFILES $1" 37 | fi 38 | shift 39 | done 40 | 41 | export https_proxy="http://proxy-dmz.intel.com:912/" 42 | export http_proxy="http://proxy-dmz.intel.com:911/" 43 | export no_proxy="intel.com,.intel.com,localhost,127.0.0.1" 44 | export socks_proxy="socks://proxy-dmz.intel.com:1080/" 45 | export ftp_proxy="ftp://proxy-dmz.intel.com:911/" 46 | 47 | GS="python3 $HOME/pm-graph/stressreport.py" 48 | URL="http://otcpl-stress.ostc.intel.com/pm-graph-test" 49 | WEBDIR="$HOME/pm-graph-test" 50 | SORTDIR="$HOME/pm-graph-sort" 51 | DATADIR="/srv/pm-graph-test" 52 | MS="$HOME/.machswap" 53 | 54 | XARGS="" 55 | if [ $INSIZE -gt 30000000000 ]; then 56 | XARGS="-tempdisk /srv/tmp" 57 | fi 58 | 59 | if [ -e "/tmp/bugzilla.bin" ]; then 60 | $GS $XARGS -webdir "$WEBDIR" -datadir "$DATADIR" -sortdir "$SORTDIR" -urlprefix "$URL" -machswap "$MS" -stype sheet -create both -bugfile /tmp/bugzilla.bin -maxproc 4 -parallel 16 -genhtml -cache -rmtar "$INFILES" 61 | else 62 | $GS $XARGS -webdir "$WEBDIR" -datadir "$DATADIR" -sortdir "$SORTDIR" -urlprefix "$URL" -machswap "$MS" -stype sheet -create both -bugzilla -maxproc 4 -parallel 16 -genhtml -cache -rmtar "$INFILES" 63 | fi 64 | -------------------------------------------------------------------------------- /tools/intel-stresstest-friday.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | CHECK=`ps aux | grep -v grep | grep run | grep /home/sleepgraph/pm-graph/stresstest.py` 4 | 5 | if [ -n "$CHECK" ]; then 6 | echo "stress testing appears to be running already" 7 | exit 8 | fi 9 | 10 | LOG=`date "+/home/sleepgraph/stresslogs/%y%m%d-%H%M%S-stresstest.txt"` 11 | 12 | labmachine killjobs > $LOG 2>&1 13 | intel-stresstest resetwired >> $LOG 2>&1 14 | intel-stresstest turbostat >> $LOG 2>&1 15 | intel-stresstest online restart >> $LOG 2>&1 16 | intel-stresstest install >> $LOG 2>&1 17 | sleep 180 18 | intel-stresstest reset >> $LOG 2>&1 19 | intel-stresstest online restart >> $LOG 2>&1 20 | intel-stresstest ready >> $LOG 2>&1 21 | intel-stresstest runlast >> $LOG 2>&1 22 | -------------------------------------------------------------------------------- /tools/intel-stresstest-monday.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | KFILELAST="/home/sleepgraph/workspace/stressconfig/kernel-last.txt" 4 | KFILE="/home/sleepgraph/workspace/stressconfig/kernel.txt" 5 | 6 | LOG=`date "+/home/sleepgraph/stresslogs/%y%m%d-%H%M%S-stressreport.txt"` 7 | intel-stresstest report > $LOG 2>&1 8 | CHECK=`diff -q $KFILELAST $KFILE` 9 | if [ -n "$CHECK" ]; then 10 | LOG=`date "+/home/sleepgraph/stresslogs/%y%m%d-%H%M%S-stressreport.txt"` 11 | intel-stresstest reportlast > $LOG 2>&1 12 | fi 13 | stressreportmail.sh latest 14 | -------------------------------------------------------------------------------- /tools/intel-stresstest-sunday.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | CHECK=`ps aux | grep -v grep | grep run | grep /home/sleepgraph/pm-graph/stresstest.py` 4 | 5 | if [ -n "$CHECK" ]; then 6 | echo "stress testing appears to be running already" 7 | exit 8 | fi 9 | 10 | LOG=`date "+/home/sleepgraph/stresslogs/%y%m%d-%H%M%S-stresstest.txt"` 11 | 12 | intel-stresstest resetwired >> $LOG 2>&1 13 | intel-stresstest turbostat >> $LOG 2>&1 14 | intel-stresstest online restart >> $LOG 2>&1 15 | intel-stresstest install >> $LOG 2>&1 16 | sleep 180 17 | intel-stresstest reset >> $LOG 2>&1 18 | intel-stresstest online restart >> $LOG 2>&1 19 | intel-stresstest ready >> $LOG 2>&1 20 | intel-stresstest runfirst >> $LOG 2>&1 21 | -------------------------------------------------------------------------------- /tools/intel-updatecache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | echo "Updating the multitest and multitestdata cache files" 4 | URL="http://otcpl-stress.ostc.intel.com/pm-graph-test" 5 | WEBDIR="$HOME/pm-graph-test" 6 | SORTDIR="$HOME/pm-graph-sort" 7 | MS="$HOME/.machswap" 8 | GS="python3 $HOME/workspace/pm-graph/stressreport.py" 9 | CACHE="$HOME/.multitests" 10 | DATACACHE="$HOME/.multitestdata" 11 | 12 | printUsage() { 13 | echo "USAGE: intel-updatecache command" 14 | echo "COMMANDS:" 15 | echo " showmissing - show the multitests that have no data" 16 | echo " all - update both the multitest and multitestdata caches" 17 | echo " data - update only the multitestdata cache" 18 | exit 0 19 | } 20 | 21 | if [ $# -gt 2 -o $# -lt 1 ]; then printUsage; fi 22 | 23 | if [ $1 = "help" ]; then 24 | printUsage 25 | elif [ $1 = "showmissing" ]; then 26 | cat $DATACACHE | sed "s/|.*//g" | sort > /tmp/check2.txt 27 | cat $CACHE | sort > /tmp/check1.txt 28 | diff /tmp/check1.txt /tmp/check2.txt | grep / | sed -e "s/< //g" > /tmp/check3.txt 29 | for p in `cat /tmp/check3.txt` 30 | do 31 | if [ -e knownbad ]; then 32 | CHECK=`cat knownbad | grep $p` 33 | if [ -n "$CHECK" ]; then 34 | continue 35 | fi 36 | fi 37 | if [ ! -e $p ]; then 38 | echo "BAD: $p" 39 | continue; 40 | fi 41 | SZ=`ls -ald $p/suspend-??????-?????? | wc -l` 42 | if [ $SZ -gt 8 ]; then 43 | echo $p 44 | echo $SZ 45 | fi 46 | done 47 | rm /tmp/check1.txt /tmp/check2.txt /tmp/check3.txt 48 | elif [ $1 = "all" ]; then 49 | cd $WEBDIR 50 | $GS -webdir $WEBDIR -sortdir $SORTDIR -machswap $MS -urlprefix $URL -sort test . 51 | elif [ $1 = "data" ]; then 52 | cd $WEBDIR 53 | $GS -cache -webdir $WEBDIR -sortdir $SORTDIR -machswap $MS -urlprefix $URL -sort test . 54 | fi 55 | -------------------------------------------------------------------------------- /tools/kernelbuild.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # args 4 | OUTPATH="$HOME/workspace" 5 | SRCPATH="$HOME/workspace/linux" 6 | REBOOT="no" 7 | NAME="" 8 | 9 | # build info 10 | ARCH="amd64" 11 | KVER="" 12 | BVER="" 13 | PKGS="" 14 | KREL="" 15 | PKG="deb" 16 | 17 | printUsage() { 18 | echo "USAGE: kernelbuild.sh command " 19 | echo "COMMANDS:" 20 | echo " build - build a new kernel and optionally install it" 21 | echo " args: name " 22 | echo " install - install packages from current build" 23 | echo " args: machine " 24 | echo " info - print out what's currently built" 25 | exit 26 | } 27 | 28 | getArch() { 29 | DEFCON=`grep -s "^CONFIG_ARCH_DEFCONFIG=\"arch/x86/configs/" $SRCPATH/.config` 30 | if [ -n "$DEFCON" ]; then 31 | KARCH=`echo $DEFCON | sed "s/.*configs\///;s/_defconfig.*//"` 32 | if [ "$KARCH" = "x86_64" ]; then 33 | ARCH="amd64" 34 | elif [ "$KARCH" = "i386" ]; then 35 | ARCH="i386" 36 | fi 37 | fi 38 | } 39 | 40 | getCurrentPackages() { 41 | getArch 42 | KVER=`cd $SRCPATH; make kernelrelease 2>/dev/null` 43 | BVER=`cat $SRCPATH/.version 2>/dev/null` 44 | KREL=`cat $SRCPATH/include/config/kernel.release 2>/dev/null` 45 | if [ -z "$NAME" ]; then 46 | PKGS="linux-headers-${KVER}_${KVER}-${BVER}_${ARCH}.$PKG \ 47 | linux-image-${KVER}_${KVER}-${BVER}_${ARCH}.$PKG \ 48 | linux-libc-dev_${KVER}-${BVER}_${ARCH}.$PKG" 49 | else 50 | PKGS="linux-headers-${KVER}-${NAME}_${KVER}-${NAME}-${BVER}_${ARCH}.$PKG \ 51 | linux-image-${KVER}-${NAME}_${KVER}-${NAME}-${BVER}_${ARCH}.$PKG \ 52 | linux-libc-dev_${KVER}-${NAME}-${BVER}_${ARCH}.$PKG" 53 | fi 54 | } 55 | 56 | getExpectedPackages() { 57 | getArch 58 | KVER=`cd $SRCPATH; make kernelrelease 2>/dev/null` 59 | BVER=`cat $SRCPATH/.version 2>/dev/null` 60 | if [ -z "$NAME" ]; then 61 | PKGS="linux-headers-${KVER}_${KVER}-${BVER}_${ARCH}.$PKG \ 62 | linux-image-${KVER}_${KVER}-${BVER}_${ARCH}.$PKG \ 63 | linux-libc-dev_${KVER}-${BVER}_${ARCH}.$PKG" 64 | else 65 | PKGS="linux-headers-${KVER}-${NAME}_${KVER}-${NAME}-${BVER}_${ARCH}.$PKG \ 66 | linux-image-${KVER}-${NAME}_${KVER}-${NAME}-${BVER}_${ARCH}.$PKG \ 67 | linux-libc-dev_${KVER}-${NAME}-${BVER}_${ARCH}.$PKG" 68 | fi 69 | } 70 | 71 | checkReboot() { 72 | REBOOT="no" 73 | if [ $1 = "reboot" ]; then 74 | REBOOT="yes" 75 | else 76 | printUsage 77 | fi 78 | } 79 | 80 | printVersion() { 81 | getCurrentPackages 82 | echo "\nKernel Info:" 83 | echo " Version: $KVER" 84 | echo " Release: $KREL" 85 | echo " Build: $BVER" 86 | echo " Arch: $ARCH" 87 | echo "Built Packages:" 88 | cd $OUTPATH 89 | for file in $PKGS 90 | do 91 | if [ -e $file ]; then 92 | echo " FOUND: $file" 93 | else 94 | echo " MISSING: $file" 95 | fi 96 | done 97 | echo "" 98 | exit 99 | } 100 | 101 | testServer() { 102 | if [ "$SERVER" != "local" ]; then 103 | CHECK=`ping -q -w 10 $SERVER | grep ", 0% packet loss,"` 104 | if [ -z "$CHECK" ]; then 105 | echo "Host $SERVER is unreachable" 106 | exit 107 | fi 108 | echo "$SERVER found" 109 | fi 110 | } 111 | 112 | buildKernel() { 113 | getExpectedPackages 114 | if [ -z "$ARCH" ]; then 115 | echo "ERROR: The .config file is either missing or set to a non-x86 architecture" 116 | exit 117 | fi 118 | echo "Bulding kernel ${KVER}-${NAME} for ${ARCH}" 119 | cd $SRCPATH 120 | make oldconfig 121 | if [ -z "$NAME" ]; then 122 | make -j `getconf _NPROCESSORS_ONLN` bin$PKG-pkg 123 | else 124 | make -j `getconf _NPROCESSORS_ONLN` bin$PKG-pkg LOCALVERSION=-$NAME 125 | fi 126 | getExpectedPackages 127 | cd $OUTPATH 128 | for file in $PKGS 129 | do 130 | if [ ! -e $file ]; then 131 | echo "ERROR: $file doesn't exist" 132 | exit 133 | fi 134 | done 135 | PKGS=`ls -1 $PKGS | tr '\n' ' '` 136 | echo $PKGS 137 | echo "BUILD COMPLETE" 138 | for file in $PKGS 139 | do 140 | ls -1 $OUTPATH/$file 141 | done 142 | } 143 | 144 | installKernel() { 145 | if [ -n "$SERVER" ]; then 146 | cd $OUTPATH 147 | if [ $SERVER = "local" ]; then 148 | echo "INSTALLING LOCALLY" 149 | sudo dpkg -i $PKGS 150 | if [ "$REBOOT" = "yes" ]; then 151 | sleep 4 152 | echo "REBOOTING $HOSTNAME" 153 | sudo reboot 154 | fi 155 | else 156 | echo "INSTALLING ON $SERVER" 157 | scp $PKGS ${SERVER}:/tmp/ 158 | ssh -X root@$SERVER "cd /tmp; dpkg -i $PKGS" 159 | if [ "$REBOOT" = "yes" ]; then 160 | sleep 4 161 | echo "REBOOTING $SERVER" 162 | ssh -X root@$SERVER "reboot" 163 | fi 164 | fi 165 | fi 166 | } 167 | 168 | if [ $# -gt 5 -o $# -lt 1 ]; then 169 | printUsage 170 | else 171 | if [ $1 = "info" ]; then 172 | printVersion 173 | exit 174 | elif [ $1 = "install" ]; then 175 | if [ $# -gt 3 -o $# -lt 2 ]; then 176 | printUsage 177 | fi 178 | SERVER=$2 179 | if [ $# -eq 3 ]; then 180 | checkReboot $3 181 | fi 182 | testServer 183 | getCurrentPackages 184 | installKernel 185 | exit 186 | elif [ $1 = "build" ]; then 187 | if [ $# -gt 5 -o $# -lt 1 ]; then 188 | printUsage 189 | fi 190 | if [ $# -ge 2 ]; then 191 | if [ $2 = "none" -o $2 = "NONE" ]; then 192 | NAME="" 193 | else 194 | NAME=$2 195 | fi 196 | fi 197 | if [ $# -ge 3 ]; then 198 | if [ $3 != "deb" -a $3 != "rpm" ]; then 199 | echo "\nUUNKNOW package type: $3 [use deb or rpm]\n" 200 | fi 201 | PKG="$3" 202 | fi 203 | if [ $# -ge 4 ]; then 204 | if [ $# -ge 5 ]; then 205 | checkReboot $5 206 | fi 207 | SERVER=$4 208 | testServer 209 | fi 210 | buildKernel 211 | if [ $# -ge 4 ]; then 212 | installKernel 213 | fi 214 | else 215 | echo "\nUNKNOWN COMMAND: $1\n" 216 | printUsage 217 | fi 218 | fi 219 | -------------------------------------------------------------------------------- /tools/lib: -------------------------------------------------------------------------------- 1 | ../lib -------------------------------------------------------------------------------- /tools/logfix.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | 3 | import os 4 | import os.path as op 5 | import sys 6 | import re 7 | import time 8 | import tempfile 9 | import shutil 10 | from datetime import datetime 11 | from subprocess import call, Popen, PIPE 12 | 13 | def sysinfoline(args, line): 14 | v = dict() 15 | for f in line.strip().split('|'): 16 | if '#' in f: 17 | continue 18 | tmp = f.strip().split(':', 1) 19 | key, val = tmp[0], tmp[1] 20 | v[key] = val 21 | if args.man: 22 | v['man'] = args.man 23 | if args.plat: 24 | v['plat'] = args.plat 25 | if args.cpu: 26 | v['cpu'] = args.cpu 27 | if args.bios: 28 | v['bios'] = args.bios 29 | if args.biosdate: 30 | v['biosdate'] = args.biosdate 31 | out = '# sysinfo | man:%s | plat:%s | cpu:%s | bios:%s | biosdate:%s | numcpu:%s | memsz:%s | memfr:%s\n' % \ 32 | (v['man'], v['plat'], v['cpu'], v['bios'], v['biosdate'], 33 | v['numcpu'], v['memsz'], v['memfr']) 34 | return out 35 | 36 | def logfix(args, file): 37 | fd, tmpfile = tempfile.mkstemp(prefix='sleepgraph-', text=True) 38 | fp, op = open(file, 'r'), open(tmpfile, 'w') 39 | for line in fp: 40 | if line.startswith('# sysinfo |'): 41 | line = sysinfoline(args, line) 42 | op.write(line) 43 | fp.close(), op.close() 44 | shutil.copyfile(tmpfile, file) 45 | os.remove(tmpfile) 46 | 47 | def logfixall(args): 48 | for dirname, dirnames, filenames in os.walk(args.folder): 49 | for file in filenames: 50 | if not (file.endswith('_dmesg.txt') or 51 | file.endswith('_ftrace.txt') or 52 | file.endswith('_dmesg.txt.gz') or 53 | file.endswith('_ftrace.txt.gz')): 54 | continue 55 | filepath = op.join(dirname, file) 56 | print(filepath) 57 | gzip = True if file.endswith('.gz') else False 58 | if gzip: 59 | call('gunzip %s' % filepath, shell=True) 60 | filepath = filepath[:-3] 61 | logfix(args, filepath) 62 | if gzip: 63 | call('gzip %s' % filepath, shell=True) 64 | 65 | def doError(msg): 66 | print('ERROR: %s\n' % msg) 67 | sys.exit(1) 68 | 69 | if __name__ == '__main__': 70 | import argparse 71 | 72 | parser = argparse.ArgumentParser() 73 | parser.add_argument('-man', metavar='value', default='', 74 | help='Manufacturer Name') 75 | parser.add_argument('-plat', metavar='value', default='', 76 | help='Platform/Model Name') 77 | parser.add_argument('-cpu', metavar='value', default='', 78 | help='CPU Name/Version') 79 | parser.add_argument('-bios', metavar='value', default='', 80 | help='BIOS Version') 81 | parser.add_argument('-biosdate', metavar='value', default='', 82 | help='BIOS Date') 83 | parser.add_argument('folder') 84 | args = parser.parse_args() 85 | 86 | if args.folder == 'help': 87 | parser.print_help() 88 | sys.exit(0) 89 | 90 | if not op.exists(args.folder) or not op.isdir(args.folder): 91 | doError('%s is not a valid folder' % args.folder) 92 | 93 | logfixall(args) 94 | -------------------------------------------------------------------------------- /tools/makedeb.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # sudo apt-get install devscripts cdbs debhelper 4 | cd /tmp 5 | if [ -d pm-graph ]; then 6 | rm -rf pm-graph 7 | fi 8 | git clone -b master https://github.com/intel/pm-graph.git 9 | cd pm-graph 10 | debuild -i -us -uc -b 11 | if [ $? -eq 0 ];then 12 | echo "SUCCESS: the package files are here" 13 | ls -al /tmp/pm-graph_*.* 14 | fi 15 | -------------------------------------------------------------------------------- /tools/perftest.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | import time 4 | import string 5 | import os 6 | import argparse 7 | from subprocess import call, Popen, PIPE 8 | 9 | DATACACHE="~/.multitestdata" 10 | TESTCACHE="~/.multitests" 11 | ansi = False 12 | 13 | def sanityCheck(): 14 | global DATACACHE, TESTCACHE, ansi 15 | 16 | if 'HOME' in os.environ: 17 | DATACACHE = DATACACHE.replace('~', os.environ['HOME']) 18 | TESTCACHE = TESTCACHE.replace('~', os.environ['HOME']) 19 | 20 | if not os.path.exists(DATACACHE): 21 | print('ERROR: %s does not exist' % DATACACHE) 22 | sys.exit(1) 23 | 24 | if not os.path.exists(TESTCACHE): 25 | print('ERROR: %s does not exist' % TESTCACHE) 26 | sys.exit(1) 27 | 28 | if (hasattr(sys.stdout, 'isatty') and sys.stdout.isatty()): 29 | ansi = True 30 | 31 | def colorText(str, color=31): 32 | global ansi 33 | if not ansi: 34 | return str 35 | return '\x1B[1;%dm%s\x1B[m' % (color, str) 36 | 37 | if __name__ == '__main__': 38 | 39 | parser = argparse.ArgumentParser() 40 | parser.add_argument('kernel1') 41 | parser.add_argument('kernel2') 42 | args = parser.parse_args() 43 | 44 | sanityCheck() 45 | 46 | print('Compare performance between [%s] and [%s]' %\ 47 | (args.kernel1, args.kernel2)) 48 | data = dict() 49 | fp = open(DATACACHE, 'r') 50 | for line in fp: 51 | vals = line.strip().split('|') 52 | kernel = vals[3] 53 | if kernel != args.kernel1 and kernel != args.kernel2: 54 | continue 55 | try: 56 | smed = float(vals[12]) 57 | rmed = float(vals[15]) 58 | except: 59 | continue 60 | mode = vals[4] 61 | host = vals[5] 62 | if host not in data: 63 | data[host] = dict() 64 | if mode not in data[host]: 65 | data[host][mode] = {'smed': -1, 'rmed': -1} 66 | if kernel not in data[host][mode]: 67 | data[host][mode][kernel] = {'smed': -1, 'rmed': -1} 68 | data[host][mode][kernel]['smed'] = smed 69 | data[host][mode][kernel]['rmed'] = rmed 70 | 71 | fullout = '' 72 | for host in sorted(data): 73 | hostgood = False 74 | out = '%s\n' % host 75 | for mode in sorted(data[host]): 76 | if args.kernel1 not in data[host][mode]: 77 | continue 78 | if args.kernel2 not in data[host][mode]: 79 | continue 80 | smed1 = data[host][mode][args.kernel1]['smed'] 81 | rmed1 = data[host][mode][args.kernel1]['rmed'] 82 | smed2 = data[host][mode][args.kernel2]['smed'] 83 | rmed2 = data[host][mode][args.kernel2]['rmed'] 84 | sdiff = smed2 - smed1 85 | rdiff = rmed2 - rmed1 86 | modeout = '%-6s: ' % mode 87 | list = [] 88 | if abs(sdiff) > 40: 89 | c = 32 if sdiff < 0 else 31 90 | list.append(colorText('suspend %+.0f ms' % sdiff, c)) 91 | if abs(rdiff) > 40: 92 | c = 32 if rdiff < 0 else 31 93 | list.append(colorText('resume %+.0f ms' % rdiff, c)) 94 | if len(list) < 1: 95 | continue 96 | out += modeout + ', '.join(list) + '\n' 97 | hostgood = True 98 | if hostgood: 99 | fullout += out 100 | print(fullout) 101 | -------------------------------------------------------------------------------- /tools/procmon.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python3 2 | import sys 3 | import time 4 | import string 5 | from subprocess import call, Popen, PIPE 6 | 7 | if __name__ == '__main__': 8 | if(len(sys.argv) != 2): 9 | print('Procmon - monitor a process cpu and mem usage') 10 | print('USAGE: procmon.py "command to run"') 11 | sys.exit() 12 | p = Popen(sys.argv[1].split()) 13 | maxvmem = maxpmem = 0 14 | lastjiff = 0 15 | while p.poll() == None: 16 | with open('/proc/%d/stat' % p.pid, 'r') as fp: 17 | data = fp.read().split() 18 | jiff = int(data[13]) 19 | vmem = float(data[22])/(1024*1024) 20 | pmem = float(data[23])*4096/(1024*1024) 21 | maxvmem = max(vmem, maxvmem) 22 | maxpmem = max(pmem, maxpmem) 23 | print('CPU=%3d%%, VMEM=%.3f MB, PMEM=%.3f MB, MAX=[%.3f MB %.3f MB]' % (jiff - lastjiff, vmem, pmem, maxvmem, maxpmem)) 24 | lastjiff = jiff 25 | time.sleep(1) 26 | -------------------------------------------------------------------------------- /tools/sanitycheck.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ $# -ne 2 ]; then 4 | echo "Simple tester for comparaing outputs from two versions of" 5 | echo "sleepgraph. Runs on all timeline folders in the current path.\n" 6 | echo " USAGE: sanitycheck.sh " 7 | exit 8 | fi 9 | 10 | SG1=$1 11 | if [ ! -e $SG1 ]; then 12 | echo "NOT FOUND: $SG1" 13 | exit 14 | fi 15 | SG2=$2 16 | if [ ! -e $SG2 ]; then 17 | echo "NOT FOUND: $SG2" 18 | exit 19 | fi 20 | 21 | for dir in `ls -1d suspend-*` 22 | do 23 | echo "[$dir]" 24 | DMESG=`ls $dir/*_dmesg.txt 2>/dev/null` 25 | if [ -z "$DMESG" ]; then 26 | DMESG=`ls $dir/*_dmesg.txt.gz 2>/dev/null` 27 | if [ -z "$DMESG" ]; then 28 | echo "SKIPPING - dmesg not found" 29 | continue 30 | fi 31 | fi 32 | FTRACE=`ls $dir/*_ftrace.txt 2>/dev/null` 33 | if [ -z "$FTRACE" ]; then 34 | FTRACE=`ls $dir/*_ftrace.txt.gz 2>/dev/null` 35 | if [ -z "$FTRACE" ]; then 36 | echo "SKIPPING - ftrace not found" 37 | continue 38 | else 39 | CG=`gzip -cd $FTRACE | grep function_graph` 40 | fi 41 | else 42 | CG=`cat $FTRACE | grep function_graph` 43 | fi 44 | if [ -n "$CG" ]; then 45 | $SG1 -dmesg $DMESG -ftrace $FTRACE -f -cgskip off -o output.html > /dev/null 46 | else 47 | $SG1 -dmesg $DMESG -ftrace $FTRACE -dev -proc -o output.html > /dev/null 48 | fi 49 | if [ -e output.html ]; then 50 | SMSG1="--------------------------------------------------------" 51 | mv output.html $dir/output1.html 52 | else 53 | SMSG1="-----------------------MISSING--------------------------" 54 | fi 55 | if [ -n "$CG" ]; then 56 | $SG2 -dmesg $DMESG -ftrace $FTRACE -f -cgskip off -o output.html > /dev/null 57 | else 58 | $SG2 -dmesg $DMESG -ftrace $FTRACE -dev -proc -o output.html > /dev/null 59 | fi 60 | if [ -e output.html ]; then 61 | SMSG2="--------------------------------------------------------" 62 | mv output.html $dir/output2.html 63 | else 64 | SMSG2="-----------------------MISSING--------------------------" 65 | fi 66 | echo $SMSG1 67 | CHECK="" 68 | if [ -e $dir/output1.html -a -e $dir/output2.html ]; then 69 | CHECK=`diff $dir/output1.html $dir/output2.html` 70 | fi 71 | if [ -n "$CHECK" ]; then 72 | echo "$CHECK" 73 | echo "TIMELINES DIFFER!" 74 | fi 75 | echo $SMSG2 76 | done 77 | -------------------------------------------------------------------------------- /tools/stresskernelbuild: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | if [ -z "$USER" ]; then 4 | USER=otcpladmin 5 | fi 6 | 7 | PKG="deb" 8 | if [ $# -gt 0 ]; then 9 | PKG=$1 10 | fi 11 | 12 | if [ "$PKG" != "deb" -a "$PKG" != "rpm" ]; then 13 | echo "ERROR: the package format is either deb or rpm" 14 | exit 15 | fi 16 | 17 | CMD=/home/$USER/workspace/pm-graph/stresstest.py 18 | CFG=/home/$USER/workspace/pm-graph/config/stresstest-intel.cfg 19 | LOG=/home/$USER/build.txt 20 | 21 | http_proxy=http://proxy-dmz.intel.com:911 $CMD -config $CFG -pkgfmt $PKG build > $LOG 2>&1 22 | 23 | if [ ! -e $LOG ]; then 24 | exit 25 | fi 26 | 27 | KVER=`cat $LOG | grep "Kernel is " | awk '{print $NF}'` 28 | OUTDIR=`cat $LOG | grep "Packages in " | awk '{print $NF}'` 29 | FILES=`cat $LOG | grep -v "\[" | grep "\.$PKG"` 30 | 31 | if [ -z "$KVER" -o -z "$OUTDIR" -o -z "$FILES" ]; then 32 | exit 33 | fi 34 | 35 | SRV=sleepgraph@otcpl-stress.ostc.intel.com 36 | ssh -X $SRV "mv -f ~/workspace/stressconfig/kernel.txt ~/workspace/stressconfig/kernel-last.txt" 37 | ssh -X $SRV "echo $KVER > ~/workspace/stressconfig/kernel.txt" 38 | for f in $FILES; do 39 | scp $OUTDIR/$f $SRV:workspace/packages/ 40 | done 41 | mv $LOG /home/$USER/build-$KVER.txt 42 | -------------------------------------------------------------------------------- /tools/testall.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | CMD="../sleepgraph.py" 4 | HOST=`hostname` 5 | MODES="" 6 | BATCH=0 7 | CLEANUP=1 8 | FREEZE=0 9 | MEM=0 10 | OUTDIR="" 11 | 12 | printhelp() { 13 | echo "USAGE: testall.sh [-h/-s/-f/-m/-b/-o outdir]" 14 | echo "OPTIONS" 15 | echo " -h: print help" 16 | echo " -s: save output files after test" 17 | echo " -f: test the freeze functionality" 18 | echo " -m: test the mem functionality" 19 | echo " -b: use minimal & easily parsable outputs for batch testing" 20 | echo " -o outdir: put output in an existing directory (implies -s)" 21 | } 22 | 23 | while [ "$1" ] ; do 24 | case "$1" in 25 | -h) 26 | shift 27 | printhelp 28 | exit 29 | ;; 30 | -s) 31 | shift 32 | CLEANUP=0 33 | ;; 34 | -b) 35 | shift 36 | BATCH=1 37 | ;; 38 | -f) 39 | shift 40 | MODES="$MODES freeze" 41 | ;; 42 | -m) 43 | shift 44 | MODES="$MODES mem" 45 | ;; 46 | -o) 47 | shift 48 | if [ -z "$1" ]; then 49 | echo "ERROR: missing output folder argument to -o" 50 | exit 51 | fi 52 | if [ ! -d "$1" ]; then 53 | echo "ERROR: $1 is not an existing folder" 54 | exit 55 | fi 56 | OUTDIR=$1 57 | shift 58 | ;; 59 | *) 60 | echo "Unknown option: $1" 61 | printhelp 62 | exit 63 | ;; 64 | esac 65 | done 66 | 67 | if [ -z "$OUTDIR" ]; then 68 | OUTDIR=`mktemp -d` 69 | else 70 | CLEANUP=0 71 | fi 72 | 73 | finished() { 74 | if [ $CLEANUP -eq 0 ]; then 75 | printf "%-20s: %s\n" "OUTPUT" $OUTDIR 76 | else 77 | rm -r $OUTDIR 78 | fi 79 | exit 80 | } 81 | 82 | check() { 83 | OUTVAL=$? 84 | if [ $OUTVAL -ne 0 -a $OUTVAL -ne 2 ]; then 85 | if [ $BATCH -eq 0 ]; then 86 | printf "%-20s: NON-ZERO EXIT %d\n" $1 $OUTVAL 87 | cat $2 88 | else 89 | INFO=`base64 -w 0 $2` 90 | printf "%-20s: FAIL\n" "RESULT" 91 | printf "%-20s: %s\n" "TEST" $1 92 | printf "%-20s: NON-ZERO EXIT %d\n" "ERROR" $OUTVAL 93 | printf "%-20s: %s\n" "LOG" $INFO 94 | fi 95 | finished 96 | fi 97 | TITLE=$1 98 | shift 99 | if [ -z "$1" ]; then 100 | if [ $BATCH -eq 0 ]; then 101 | printf "%-20s: PASS\n" $TITLE 102 | fi 103 | else 104 | FAIL=0 105 | while [ "$1" ] ; do 106 | if [ ! -e "$1" -o ! -s "$1" ]; then 107 | FAIL=1 108 | break 109 | fi 110 | shift 111 | done 112 | if [ $FAIL -eq 0 ]; then 113 | if [ $BATCH -eq 0 ]; then 114 | printf "%-20s: PASS\n" $TITLE 115 | fi 116 | else 117 | FILE=`basename $1` 118 | if [ $BATCH -eq 0 ]; then 119 | printf "%-20s: MISSING -> %s\n" $TITLE $FILE 120 | else 121 | printf "%-20s: FAIL\n" "RESULT" 122 | printf "%-20s: %s\n" "TEST" $TITLE 123 | printf "%-20s: MISSING FILE %s\n" "ERROR" $FILE 124 | fi 125 | finished 126 | fi 127 | fi 128 | } 129 | 130 | # one-off commands that require no suspend 131 | 132 | $CMD -h > $OUTDIR/help.txt 2>&1 133 | check "HELP" $OUTDIR/help.txt 134 | 135 | $CMD -v > $OUTDIR/version.txt 2>&1 136 | check "VERSION" $OUTDIR/version.txt 137 | 138 | $CMD -modes > $OUTDIR/modes.txt 2>&1 139 | check "MODES" $OUTDIR/modes.txt 140 | 141 | $CMD -status > $OUTDIR/status.txt 2>&1 142 | check "STATUS" $OUTDIR/status.txt 143 | 144 | sudo $CMD -sysinfo > $OUTDIR/sysinfo.txt 2>&1 145 | check "SYSINFO" $OUTDIR/sysinfo.txt 146 | 147 | $CMD -devinfo > $OUTDIR/devinfo.txt 2>&1 148 | check "DEVINFO" $OUTDIR/devinfo.txt 149 | 150 | $CMD -cmdinfo > $OUTDIR/cmdinfo.txt 2>&1 151 | check "CMDINFO" $OUTDIR/cmdinfo.txt 152 | 153 | $CMD -wificheck > $OUTDIR/wifi.txt 2>&1 154 | check "WIFICHECK" $OUTDIR/wifi.txt 155 | 156 | sudo $CMD -flist > $OUTDIR/flist.txt 2>&1 157 | check "FLIST" $OUTDIR/flist.txt 158 | 159 | sudo $CMD -flistall > $OUTDIR/flistall.txt 2>&1 160 | check "FLISTALL" $OUTDIR/flistall.txt 161 | 162 | $CMD -xstat > $OUTDIR/display.txt 2>&1 163 | check "DISPLAY" $OUTDIR/display.txt 164 | 165 | # suspend dependent commands 166 | 167 | AVAIL=`$CMD -modes | sed -e "s/[\',\[]//g" -e "s/\]//g"` 168 | for m in $AVAIL; do 169 | if [ $m = "freeze" ]; then 170 | FREEZE=1 171 | elif [ $m = "mem" ]; then 172 | MEM=1 173 | fi 174 | done 175 | 176 | for m in $MODES; do 177 | if [ $m = "freeze" ]; then 178 | if [ $FREEZE -eq 0 ]; then continue; fi 179 | name="freeze" 180 | elif [ $m = "mem" ]; then 181 | if [ $MEM -eq 0 ]; then continue; fi 182 | name="mem " 183 | else 184 | continue 185 | fi 186 | 187 | sudo sh -c "echo platform > /sys/power/pm_test" 188 | ARGS="-m $m -gzip -rtcwake 10 -verbose -addlogs -srgap -wifi -sync -rs off -display off -mindev 1" 189 | DMESG=${HOST}_${m}_dmesg.txt.gz 190 | FTRACE=${HOST}_${m}_ftrace.txt.gz 191 | HTML=${HOST}_${m}.html 192 | RESULT=result.txt 193 | 194 | OUT=$OUTDIR/suspend-${m}-simple 195 | sudo $CMD $ARGS -result $OUT/$RESULT -o $OUT > $OUT.txt 2>&1 196 | check "SIMPLE_$name" $OUT.txt $OUT/$DMESG $OUT/$FTRACE $OUT/$HTML $OUT/$RESULT 197 | 198 | OUT=$OUTDIR/suspend-${m}-dev 199 | sudo $CMD $ARGS -dev -result $OUT/$RESULT -o $OUT > $OUT.txt 2>&1 200 | check "DEV_$name" $OUT.txt $OUT/$DMESG $OUT/$FTRACE $OUT/$HTML $OUT/$RESULT 201 | 202 | OUT=$OUTDIR/suspend-${m}-proc 203 | sudo $CMD $ARGS -proc -result $OUT/$RESULT -o $OUT > $OUT.txt 2>&1 204 | check "PROC_$name" $OUT.txt $OUT/$DMESG $OUT/$FTRACE $OUT/$HTML $OUT/$RESULT 205 | 206 | OUT=$OUTDIR/suspend-${m}-devproc 207 | sudo $CMD $ARGS -dev -proc -result $OUT/$RESULT -o $OUT > $OUT.txt 2>&1 208 | check "DEVPROC_$name" $OUT.txt $OUT/$DMESG $OUT/$FTRACE $OUT/$HTML $OUT/$RESULT 209 | 210 | OUT=$OUTDIR/suspend-${m}-x2 211 | sudo $CMD $ARGS -x2 -x2delay 100 -predelay 100 -postdelay 100 -result $OUT/$RESULT -o $OUT > $OUT.txt 2>&1 212 | check "X2_$name" $OUT.txt $OUT/$DMESG $OUT/$FTRACE $OUT/$HTML $OUT/$RESULT 213 | 214 | OUT=$OUTDIR/suspend-${m}-cg 215 | sudo $CMD $ARGS -f -maxdepth 10 -result $OUT/$RESULT -o $OUT > $OUT.txt 2>&1 216 | check "CALLGRAPH_$name" $OUT.txt $OUT/$DMESG $OUT/$FTRACE $OUT/$HTML $OUT/$RESULT 217 | 218 | OUT=$OUTDIR/suspend-${m}-cgtop 219 | sudo $CMD $ARGS -ftop -maxdepth 10 -result $OUT/$RESULT -o $OUT > $OUT.txt 2>&1 220 | check "CALLGRAPHTOP_$name" $OUT.txt $OUT/$DMESG $OUT/$FTRACE $OUT/$HTML $OUT/$RESULT 221 | 222 | OUT=$OUTDIR/suspend-${m}-x3 223 | sudo $CMD $ARGS -multi 3 0 -maxfail 1 -result $OUT/$RESULT -o $OUT > $OUT.txt 2>&1 224 | check "MULTI_$name" $OUT.txt $OUT/$RESULT $OUT/summary.html $OUT/summary-devices.html $OUT/summary-issues.html 225 | sudo sh -c "echo none > /sys/power/pm_test" 226 | done 227 | 228 | printf "%-20s: PASS\n" "RESULT" 229 | finished 230 | --------------------------------------------------------------------------------