amd-debug-tools 0.2.5__tar.gz → 0.2.7__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of amd-debug-tools might be problematic. Click here for more details.

Files changed (52) hide show
  1. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/PKG-INFO +6 -3
  2. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/README.md +5 -2
  3. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/pyproject.toml +1 -0
  4. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/__init__.py +9 -1
  5. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/bios.py +5 -3
  6. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/common.py +39 -0
  7. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/installer.py +2 -2
  8. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/prerequisites.py +24 -2
  9. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/pstate.py +5 -3
  10. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/s2idle.py +5 -3
  11. amd_debug_tools-0.2.7/src/amd_debug/ttm.py +157 -0
  12. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/validator.py +20 -0
  13. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug_tools.egg-info/PKG-INFO +6 -3
  14. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug_tools.egg-info/SOURCES.txt +2 -0
  15. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug_tools.egg-info/entry_points.txt +1 -0
  16. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug_tools.egg-info/top_level.txt +1 -0
  17. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_bios.py +26 -8
  18. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_common.py +91 -0
  19. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_kernel.py +2 -1
  20. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_launcher.py +7 -0
  21. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_prerequisites.py +77 -1
  22. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_s2idle.py +6 -4
  23. amd_debug_tools-0.2.7/src/test_ttm.py +276 -0
  24. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_validator.py +63 -1
  25. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/LICENSE +0 -0
  26. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/setup.cfg +0 -0
  27. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/acpi.py +0 -0
  28. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/bash/amd-s2idle +0 -0
  29. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/battery.py +0 -0
  30. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/database.py +0 -0
  31. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/display.py +0 -0
  32. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/failures.py +0 -0
  33. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/kernel.py +0 -0
  34. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/s2idle-hook +0 -0
  35. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/sleep_report.py +0 -0
  36. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/templates/html +0 -0
  37. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/templates/md +0 -0
  38. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/templates/stdout +0 -0
  39. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/templates/txt +0 -0
  40. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug/wake.py +0 -0
  41. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug_tools.egg-info/dependency_links.txt +0 -0
  42. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/amd_debug_tools.egg-info/requires.txt +0 -0
  43. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/launcher.py +0 -0
  44. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_acpi.py +0 -0
  45. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_batteries.py +0 -0
  46. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_database.py +0 -0
  47. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_display.py +0 -0
  48. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_failures.py +0 -0
  49. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_installer.py +0 -0
  50. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_pstate.py +0 -0
  51. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_sleep_report.py +0 -0
  52. {amd_debug_tools-0.2.5 → amd_debug_tools-0.2.7}/src/test_wake.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amd-debug-tools
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: debug tools for AMD systems
5
5
  Author-email: Mario Limonciello <superm1@kernel.org>
6
6
  License-Expression: MIT
@@ -131,7 +131,7 @@ The following optional arguments are supported for this command:
131
131
  If the tool is launched with an environment that can call `xdg-open`, the report
132
132
  will be opened in a browser.
133
133
 
134
- ### `amd-s2idle version`
134
+ ### `amd-s2idle --version`
135
135
  This will print the version of the tool and exit.
136
136
 
137
137
  ### Debug output
@@ -164,7 +164,7 @@ The following optional arguments are supported for this command:
164
164
  --input INPUT Optional input file to parse
165
165
  --tool-debug Enable tool debug logging
166
166
 
167
- ### `amd-bios version`
167
+ ### `amd-bios --version`
168
168
  This will print the version of the tool and exit.
169
169
 
170
170
  ## amd-pstate
@@ -172,6 +172,9 @@ This will print the version of the tool and exit.
172
172
  It will capture some state from the system as well as from the machine specific registers that
173
173
  amd-pstate uses.
174
174
 
175
+ ## amd-ttm
176
+ `amd-ttm` is a tool used for managing the TTM memory settings on AMD systems.
177
+
175
178
  ## Compatibility scripts
176
179
 
177
180
  Compatibility scripts are provided for the previous names the tools went by:
@@ -107,7 +107,7 @@ The following optional arguments are supported for this command:
107
107
  If the tool is launched with an environment that can call `xdg-open`, the report
108
108
  will be opened in a browser.
109
109
 
110
- ### `amd-s2idle version`
110
+ ### `amd-s2idle --version`
111
111
  This will print the version of the tool and exit.
112
112
 
113
113
  ### Debug output
@@ -140,7 +140,7 @@ The following optional arguments are supported for this command:
140
140
  --input INPUT Optional input file to parse
141
141
  --tool-debug Enable tool debug logging
142
142
 
143
- ### `amd-bios version`
143
+ ### `amd-bios --version`
144
144
  This will print the version of the tool and exit.
145
145
 
146
146
  ## amd-pstate
@@ -148,6 +148,9 @@ This will print the version of the tool and exit.
148
148
  It will capture some state from the system as well as from the machine specific registers that
149
149
  amd-pstate uses.
150
150
 
151
+ ## amd-ttm
152
+ `amd-ttm` is a tool used for managing the TTM memory settings on AMD systems.
153
+
151
154
  ## Compatibility scripts
152
155
 
153
156
  Compatibility scripts are provided for the previous names the tools went by:
@@ -50,3 +50,4 @@ license = "MIT"
50
50
  amd-s2idle = "amd_debug:amd_s2idle"
51
51
  amd-bios = "amd_debug:amd_bios"
52
52
  amd-pstate = "amd_debug:amd_pstate"
53
+ amd-ttm = "amd_debug:amd_ttm"
@@ -23,8 +23,15 @@ def amd_pstate():
23
23
  return pstate.main()
24
24
 
25
25
 
26
+ def amd_ttm():
27
+ """Launch the amd-ttm tool."""
28
+ from . import ttm # pylint: disable=import-outside-toplevel
29
+
30
+ return ttm.main()
31
+
32
+
26
33
  def install_dep_superset():
27
- """Install all supserset dependencies."""
34
+ """Install all superset dependencies."""
28
35
  from . import installer # pylint: disable=import-outside-toplevel
29
36
 
30
37
  return installer.install_dep_superset()
@@ -36,6 +43,7 @@ def launch_tool(tool_name):
36
43
  "amd_s2idle.py": amd_s2idle,
37
44
  "amd_bios.py": amd_bios,
38
45
  "amd_pstate.py": amd_pstate,
46
+ "amd_ttm.py": amd_ttm,
39
47
  "install_deps.py": install_dep_superset,
40
48
  }
41
49
  if tool_name in tools:
@@ -105,7 +105,9 @@ def parse_args():
105
105
  action="store_true",
106
106
  help="Enable tool debug logging",
107
107
  )
108
- subparsers.add_parser("version", help="Show version information")
108
+ parser.add_argument(
109
+ "--version", action="store_true", help="Show version information"
110
+ )
109
111
 
110
112
  if len(sys.argv) == 1:
111
113
  parser.print_help(sys.stderr)
@@ -122,7 +124,7 @@ def parse_args():
122
124
  return args
123
125
 
124
126
 
125
- def main() -> None|int:
127
+ def main() -> None | int:
126
128
  """Main function"""
127
129
  args = parse_args()
128
130
  ret = False
@@ -132,7 +134,7 @@ def main() -> None|int:
132
134
  elif args.command == "parse":
133
135
  app = AmdBios(args.input, args.tool_debug)
134
136
  ret = app.run()
135
- elif args.command == "version":
137
+ elif args.version:
136
138
  print(version())
137
139
  show_log_info()
138
140
  if ret is False:
@@ -226,6 +226,45 @@ def get_pretty_distro() -> str:
226
226
  return distro
227
227
 
228
228
 
229
+ def bytes_to_gb(bytes_value):
230
+ """Convert bytes to GB"""
231
+ return bytes_value * 4096 / (1024 * 1024 * 1024)
232
+
233
+
234
+ def gb_to_pages(gb_value):
235
+ """Convert GB into bytes"""
236
+ return int(gb_value * (1024 * 1024 * 1024) / 4096)
237
+
238
+
239
+ def reboot():
240
+ """Reboot the system"""
241
+ try:
242
+ import dbus # pylint: disable=import-outside-toplevel
243
+
244
+ bus = dbus.SystemBus()
245
+ obj = bus.get_object("org.freedesktop.login1", "/org/freedesktop/login1")
246
+ intf = dbus.Interface(obj, "org.freedesktop.login1.Manager")
247
+ intf.Reboot(True)
248
+ return True
249
+ except ImportError:
250
+ fatal_error("Missing dbus")
251
+ except dbus.exceptions.DBusException as e:
252
+ fatal_error({e})
253
+ return True
254
+
255
+
256
+ def get_system_mem():
257
+ """Get the total system memory in GB using /proc/meminfo"""
258
+ with open(os.path.join("/", "proc", "meminfo"), "r", encoding="utf-8") as f:
259
+ for line in f:
260
+ if line.startswith("MemTotal:"):
261
+ # MemTotal line format: "MemTotal: 16384516 kB"
262
+ # Extract the number and convert from kB to GB
263
+ mem_kb = int(line.split()[1])
264
+ return mem_kb / (1024 * 1024)
265
+ raise ValueError("Could not find MemTotal in /proc/meminfo")
266
+
267
+
229
268
  def is_root() -> bool:
230
269
  """Check if the user is root"""
231
270
  return os.geteuid() == 0
@@ -446,8 +446,8 @@ def parse_args():
446
446
  return parser.parse_args()
447
447
 
448
448
 
449
- def install_dep_superset() -> None|int:
450
- """Install all python supserset dependencies"""
449
+ def install_dep_superset() -> None | int:
450
+ """Install all python superset dependencies"""
451
451
  args = parse_args()
452
452
  tool = Installer(tool_debug=args.tool_debug)
453
453
  tool.set_requirements(
@@ -128,6 +128,28 @@ class PrerequisiteValidator(AmdTool):
128
128
  if not self.db.get_last_prereq_ts():
129
129
  self.run()
130
130
 
131
+ def capture_nvidia(self):
132
+ """Capture the NVIDIA GPU state"""
133
+ p = os.path.join("/", "proc", "driver", "nvidia", "version")
134
+ if not os.path.exists(p):
135
+ return True
136
+ try:
137
+ self.db.record_debug_file(p)
138
+ except PermissionError:
139
+ self.db.record_prereq("NVIDIA GPU version not readable", "👀")
140
+ return True
141
+ p = os.path.join("/", "proc", "driver", "nvidia", "gpus")
142
+ if not os.path.exists(p):
143
+ return True
144
+ for root, _dirs, files in os.walk(p, topdown=False):
145
+ for f in files:
146
+ try:
147
+ self.db.record_debug(f"NVIDIA {f}")
148
+ self.db.record_debug_file(os.path.join(root, f))
149
+ except PermissionError:
150
+ self.db.record_prereq("NVIDIA GPU {f} not readable", "👀")
151
+ return True
152
+
131
153
  def capture_edid(self):
132
154
  """Capture and decode the EDID data"""
133
155
  edids = self.display.get_edid()
@@ -1227,9 +1249,8 @@ class PrerequisiteValidator(AmdTool):
1227
1249
  # ignore kernel warnings
1228
1250
  taint &= ~BIT(9)
1229
1251
  if taint != 0:
1230
- self.db.record_prereq(f"Kernel is tainted: {taint}", "")
1252
+ self.db.record_prereq(f"Kernel is tainted: {taint}", "🚦")
1231
1253
  self.failures += [TaintedKernel()]
1232
- return False
1233
1254
  return True
1234
1255
 
1235
1256
  def run(self):
@@ -1244,6 +1265,7 @@ class PrerequisiteValidator(AmdTool):
1244
1265
  self.capture_logind,
1245
1266
  self.capture_pci_acpi,
1246
1267
  self.capture_edid,
1268
+ self.capture_nvidia,
1247
1269
  ]
1248
1270
  checks = []
1249
1271
 
@@ -293,18 +293,20 @@ def parse_args():
293
293
  action="store_true",
294
294
  help="Enable tool debug logging",
295
295
  )
296
- subparsers.add_parser("version", help="Show version information")
296
+ parser.add_argument(
297
+ "--version", action="store_true", help="Show version information"
298
+ )
297
299
  if len(sys.argv) == 1:
298
300
  parser.print_help(sys.stderr)
299
301
  sys.exit(1)
300
302
  return parser.parse_args()
301
303
 
302
304
 
303
- def main() -> None|int:
305
+ def main() -> None | int:
304
306
  """Main function"""
305
307
  args = parse_args()
306
308
  ret = False
307
- if args.command == "version":
309
+ if args.version:
308
310
  print(version())
309
311
  return
310
312
  elif args.command == "triage":
@@ -385,7 +385,9 @@ def parse_args():
385
385
  help="Enable tool debug logging",
386
386
  )
387
387
 
388
- subparsers.add_parser("version", help="Show version information")
388
+ parser.add_argument(
389
+ "--version", action="store_true", help="Show version information"
390
+ )
389
391
 
390
392
  if len(sys.argv) == 1:
391
393
  parser.print_help(sys.stderr)
@@ -394,7 +396,7 @@ def parse_args():
394
396
  return parser.parse_args()
395
397
 
396
398
 
397
- def main() -> None|int:
399
+ def main() -> None | int:
398
400
  """Main function"""
399
401
  args = parse_args()
400
402
  ret = False
@@ -427,7 +429,7 @@ def main() -> None|int:
427
429
  args.logind,
428
430
  args.bios_debug,
429
431
  )
430
- elif args.action == "version":
432
+ elif args.version:
431
433
  print(version())
432
434
  return
433
435
  else:
@@ -0,0 +1,157 @@
1
+ #!/usr/bin/python3
2
+ # SPDX-License-Identifier: MIT
3
+ """TTM configuration tool"""
4
+
5
+ import os
6
+ import argparse
7
+ from amd_debug.common import (
8
+ AmdTool,
9
+ bytes_to_gb,
10
+ gb_to_pages,
11
+ get_system_mem,
12
+ relaunch_sudo,
13
+ print_color,
14
+ reboot,
15
+ version,
16
+ )
17
+
18
+ TTM_PARAM_PATH = "/sys/module/ttm/parameters/pages_limit"
19
+ MODPROBE_CONF_PATH = "/etc/modprobe.d/ttm.conf"
20
+ # Maximum percentage of total system memory to allow for TTM
21
+ MAX_MEMORY_PERCENTAGE = 90
22
+
23
+
24
+ def maybe_reboot() -> bool:
25
+ """Prompt to reboot system"""
26
+ response = input("Would you like to reboot the system now? (y/n): ").strip().lower()
27
+ if response in ("y", "yes"):
28
+ return reboot()
29
+ return True
30
+
31
+
32
+ class AmdTtmTool(AmdTool):
33
+ """Class for handling TTM page configuration"""
34
+
35
+ def __init__(self, logging):
36
+ log_prefix = "ttm" if logging else None
37
+ super().__init__(log_prefix)
38
+
39
+ def get(self) -> bool:
40
+ """Read current page limit"""
41
+ try:
42
+ with open(TTM_PARAM_PATH, "r", encoding="utf-8") as f:
43
+ pages = int(f.read().strip())
44
+ gb_value = bytes_to_gb(pages)
45
+ print_color(
46
+ f"Current TTM pages limit: {pages} pages ({gb_value:.2f} GB)", "💻"
47
+ )
48
+ except FileNotFoundError:
49
+ print_color(f"Error: Could not find {TTM_PARAM_PATH}", "❌")
50
+ return False
51
+
52
+ total = get_system_mem()
53
+ if total > 0:
54
+ print_color(f"Total system memory: {total:.2f} GB", "💻")
55
+
56
+ return True
57
+
58
+ def set(self, gb_value) -> bool:
59
+ """Set a new page limit"""
60
+ relaunch_sudo()
61
+
62
+ # Check against system memory
63
+ total = get_system_mem()
64
+ if total > 0:
65
+ max_recommended_gb = total * MAX_MEMORY_PERCENTAGE / 100
66
+
67
+ if gb_value > total:
68
+ print_color(
69
+ f"{gb_value:.2f} GB is greater than total system memory ({total:.2f} GB)",
70
+ "❌",
71
+ )
72
+ return False
73
+
74
+ if gb_value > max_recommended_gb:
75
+ print_color(
76
+ f"Warning: The requested value ({gb_value:.2f} GB) exceeds {MAX_MEMORY_PERCENTAGE}% of your system memory ({max_recommended_gb:.2f} GB).",
77
+ "🚦",
78
+ )
79
+ response = (
80
+ input(
81
+ "This could cause system instability. Continue anyway? (y/n): "
82
+ )
83
+ .strip()
84
+ .lower()
85
+ )
86
+ if response not in ("y", "yes"):
87
+ print_color("Operation cancelled.", "🚦")
88
+ return False
89
+
90
+ pages = gb_to_pages(gb_value)
91
+
92
+ with open(MODPROBE_CONF_PATH, "w", encoding="utf-8") as f:
93
+ f.write(f"options ttm pages_limit={pages}\n")
94
+ print_color(
95
+ f"Successfully set TTM pages limit to {pages} pages ({gb_value:.2f} GB)",
96
+ "🐧",
97
+ )
98
+ print_color(f"Configuration written to {MODPROBE_CONF_PATH}", "🐧")
99
+ print_color("NOTE: You need to reboot for changes to take effect.", "○")
100
+
101
+ return maybe_reboot()
102
+
103
+ def clear(self) -> bool:
104
+ """Clears the page limit"""
105
+ if not os.path.exists(MODPROBE_CONF_PATH):
106
+ print_color(f"{MODPROBE_CONF_PATH} doesn't exist", "❌")
107
+ return False
108
+
109
+ relaunch_sudo()
110
+
111
+ os.remove(MODPROBE_CONF_PATH)
112
+ print_color(f"Configuration {MODPROBE_CONF_PATH} removed", "🐧")
113
+
114
+ return maybe_reboot()
115
+
116
+
117
+ def parse_args():
118
+ """Parse command line arguments."""
119
+ parser = argparse.ArgumentParser(description="Manage TTM pages limit")
120
+ parser.add_argument("--set", type=float, help="Set pages limit in GB")
121
+ parser.add_argument(
122
+ "--clear", action="store_true", help="Clear a previously set page limit"
123
+ )
124
+ parser.add_argument(
125
+ "--version", action="store_true", help="Show version information"
126
+ )
127
+ parser.add_argument(
128
+ "--tool-debug",
129
+ action="store_true",
130
+ help="Enable tool debug logging",
131
+ )
132
+
133
+ return parser.parse_args()
134
+
135
+
136
+ def main() -> None | int:
137
+ """Main function"""
138
+
139
+ args = parse_args()
140
+ tool = AmdTtmTool(args.tool_debug)
141
+ ret = False
142
+
143
+ if args.version:
144
+ print(version())
145
+ return
146
+ elif args.set is not None:
147
+ if args.set <= 0:
148
+ print("Error: GB value must be greater than 0")
149
+ return 1
150
+ ret = tool.set(args.set)
151
+ elif args.clear:
152
+ ret = tool.clear()
153
+ else:
154
+ ret = tool.get()
155
+ if ret is False:
156
+ return 1
157
+ return
@@ -703,6 +703,22 @@ class SleepValidator(AmdTool):
703
703
  else:
704
704
  print_color("No RTC device found, please manually wake system", "🚦")
705
705
 
706
+ def toggle_nvidia(self, value):
707
+ """Write to the NVIDIA suspend interface"""
708
+ p = os.path.join("/", "proc", "driver", "nvidia", "suspend")
709
+ if not os.path.exists(p):
710
+ return True
711
+ fd = os.open(p, os.O_WRONLY | os.O_SYNC)
712
+ try:
713
+ os.write(fd, value)
714
+ except OSError as e:
715
+ self.db.record_cycle_data(f"Failed to set {value} in NVIDIA {e}", "❌")
716
+ return False
717
+ finally:
718
+ os.close(fd)
719
+ self.db.record_debug(f"Wrote {value} to NVIDIA driver")
720
+ return True
721
+
706
722
  @pm_debugging
707
723
  def suspend_system(self):
708
724
  """Suspend the system using the dbus or sysfs interface"""
@@ -744,6 +760,8 @@ class SleepValidator(AmdTool):
744
760
  self.db.record_cycle_data("Missing dbus", "❌")
745
761
  return False
746
762
  else:
763
+ if not self.toggle_nvidia(b"suspend"):
764
+ return False
747
765
  old = get_wakeup_count()
748
766
  p = os.path.join("/", "sys", "power", "state")
749
767
  fd = os.open(p, os.O_WRONLY | os.O_SYNC)
@@ -757,6 +775,8 @@ class SleepValidator(AmdTool):
757
775
  return False
758
776
  finally:
759
777
  os.close(fd)
778
+ if not self.toggle_nvidia(b"resume"):
779
+ return False
760
780
  return True
761
781
 
762
782
  def unlock_session(self):
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amd-debug-tools
3
- Version: 0.2.5
3
+ Version: 0.2.7
4
4
  Summary: debug tools for AMD systems
5
5
  Author-email: Mario Limonciello <superm1@kernel.org>
6
6
  License-Expression: MIT
@@ -131,7 +131,7 @@ The following optional arguments are supported for this command:
131
131
  If the tool is launched with an environment that can call `xdg-open`, the report
132
132
  will be opened in a browser.
133
133
 
134
- ### `amd-s2idle version`
134
+ ### `amd-s2idle --version`
135
135
  This will print the version of the tool and exit.
136
136
 
137
137
  ### Debug output
@@ -164,7 +164,7 @@ The following optional arguments are supported for this command:
164
164
  --input INPUT Optional input file to parse
165
165
  --tool-debug Enable tool debug logging
166
166
 
167
- ### `amd-bios version`
167
+ ### `amd-bios --version`
168
168
  This will print the version of the tool and exit.
169
169
 
170
170
  ## amd-pstate
@@ -172,6 +172,9 @@ This will print the version of the tool and exit.
172
172
  It will capture some state from the system as well as from the machine specific registers that
173
173
  amd-pstate uses.
174
174
 
175
+ ## amd-ttm
176
+ `amd-ttm` is a tool used for managing the TTM memory settings on AMD systems.
177
+
175
178
  ## Compatibility scripts
176
179
 
177
180
  Compatibility scripts are provided for the previous names the tools went by:
@@ -16,6 +16,7 @@ src/test_prerequisites.py
16
16
  src/test_pstate.py
17
17
  src/test_s2idle.py
18
18
  src/test_sleep_report.py
19
+ src/test_ttm.py
19
20
  src/test_validator.py
20
21
  src/test_wake.py
21
22
  src/amd_debug/__init__.py
@@ -33,6 +34,7 @@ src/amd_debug/pstate.py
33
34
  src/amd_debug/s2idle-hook
34
35
  src/amd_debug/s2idle.py
35
36
  src/amd_debug/sleep_report.py
37
+ src/amd_debug/ttm.py
36
38
  src/amd_debug/validator.py
37
39
  src/amd_debug/wake.py
38
40
  src/amd_debug/bash/amd-s2idle
@@ -2,3 +2,4 @@
2
2
  amd-bios = amd_debug:amd_bios
3
3
  amd-pstate = amd_debug:amd_pstate
4
4
  amd-s2idle = amd_debug:amd_s2idle
5
+ amd-ttm = amd_debug:amd_ttm
@@ -14,5 +14,6 @@ test_prerequisites
14
14
  test_pstate
15
15
  test_s2idle
16
16
  test_sleep_report
17
+ test_ttm
17
18
  test_validator
18
19
  test_wake
@@ -33,8 +33,14 @@ class TestAmdBios(unittest.TestCase):
33
33
  @patch("amd_debug.bios.minimum_kernel")
34
34
  @patch("amd_debug.bios.AcpicaTracer")
35
35
  @patch("amd_debug.bios.print_color")
36
+ @patch("subprocess.run")
36
37
  def test_set_tracing_enable(
37
- self, _mock_print, mock_acpica_tracer, mock_minimum_kernel, mock_relaunch_sudo
38
+ self,
39
+ _mock_run,
40
+ _mock_print,
41
+ mock_acpica_tracer,
42
+ mock_minimum_kernel,
43
+ mock_relaunch_sudo,
38
44
  ):
39
45
  """Test enabling tracing"""
40
46
  mock_minimum_kernel.return_value = True
@@ -53,8 +59,14 @@ class TestAmdBios(unittest.TestCase):
53
59
  @patch("amd_debug.bios.minimum_kernel")
54
60
  @patch("amd_debug.bios.AcpicaTracer")
55
61
  @patch("amd_debug.bios.print_color")
62
+ @patch("subprocess.run")
56
63
  def test_set_tracing_disable(
57
- self, _mock_print, mock_acpica_tracer, mock_minimum_kernel, mock_relaunch_sudo
64
+ self,
65
+ _mock_run,
66
+ _mock_print,
67
+ mock_acpica_tracer,
68
+ mock_minimum_kernel,
69
+ mock_relaunch_sudo,
58
70
  ):
59
71
  """Test disabling tracing"""
60
72
  mock_minimum_kernel.return_value = True
@@ -71,7 +83,10 @@ class TestAmdBios(unittest.TestCase):
71
83
 
72
84
  @patch("amd_debug.bios.sscanf_bios_args")
73
85
  @patch("amd_debug.bios.print_color")
74
- def test_analyze_kernel_log_line(self, mock_print_color, mock_sscanf_bios_args):
86
+ @patch("subprocess.run")
87
+ def test_analyze_kernel_log_line(
88
+ self, _mock_run, mock_print_color, mock_sscanf_bios_args
89
+ ):
75
90
  """Test analyzing kernel log line"""
76
91
  mock_sscanf_bios_args.return_value = "BIOS argument found"
77
92
 
@@ -85,8 +100,9 @@ class TestAmdBios(unittest.TestCase):
85
100
 
86
101
  @patch("amd_debug.bios.sscanf_bios_args")
87
102
  @patch("amd_debug.bios.print_color")
103
+ @patch("subprocess.run")
88
104
  def test_analyze_kernel_log_line_no_bios_args(
89
- self, mock_print_color, mock_sscanf_bios_args
105
+ self, _mock_run, mock_print_color, mock_sscanf_bios_args
90
106
  ):
91
107
  """Test analyzing kernel log line with no BIOS arguments"""
92
108
  mock_sscanf_bios_args.return_value = None
@@ -140,12 +156,12 @@ class TestAmdBios(unittest.TestCase):
140
156
  self.assertFalse(args.enable)
141
157
  self.assertTrue(args.disable)
142
158
 
143
- @patch("sys.argv", ["bios.py", "version"])
159
+ @patch("sys.argv", ["bios.py", "--version"])
144
160
  def test_parse_args_version_command(self):
145
161
  """Test parse_args with version command"""
146
162
 
147
163
  args = parse_args()
148
- self.assertEqual(args.command, "version")
164
+ self.assertTrue(args.version)
149
165
 
150
166
  @patch("sys.argv", ["bios.py"])
151
167
  @patch("argparse.ArgumentParser.print_help")
@@ -227,7 +243,7 @@ class TestAmdBios(unittest.TestCase):
227
243
  self, _mock_print, mock_show_log_info, mock_version, mock_parse_args
228
244
  ):
229
245
  """Test main function with version command"""
230
- mock_parse_args.return_value = argparse.Namespace(command="version")
246
+ mock_parse_args.return_value = argparse.Namespace(version=True, command=None)
231
247
  mock_version.return_value = "1.0.0"
232
248
 
233
249
  result = main()
@@ -241,7 +257,9 @@ class TestAmdBios(unittest.TestCase):
241
257
  @patch("amd_debug.bios.show_log_info")
242
258
  def test_main_invalid_command(self, mock_show_log_info, mock_parse_args):
243
259
  """Test main function with an invalid command"""
244
- mock_parse_args.return_value = argparse.Namespace(command="invalid")
260
+ mock_parse_args.return_value = argparse.Namespace(
261
+ version=False, command="invalid"
262
+ )
245
263
 
246
264
  result = main()
247
265