amd-debug-tools 0.2.8__py3-none-any.whl → 0.2.9__py3-none-any.whl

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.

amd_debug/__init__.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
 
4
3
 
amd_debug/acpi.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
 
4
3
  import os
amd_debug/battery.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
  from pyudev import Context
4
3
 
amd_debug/bios.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
  """s2idle analysis tool"""
4
3
  import argparse
amd_debug/common.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
 
4
3
  """
@@ -13,7 +12,6 @@ import platform
13
12
  import time
14
13
  import struct
15
14
  import subprocess
16
- import re
17
15
  import sys
18
16
  from ast import literal_eval
19
17
  from datetime import date, timedelta
amd_debug/database.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
 
4
3
  from datetime import datetime
@@ -99,8 +98,8 @@ class SleepDatabase:
99
98
 
100
99
  def start_cycle(self, timestamp):
101
100
  """Start a new sleep cycle"""
101
+ assert self.db
102
102
  self.last_suspend = timestamp
103
-
104
103
  # increment the counters so that systemd hooks work
105
104
  cur = self.db.cursor()
106
105
  cur.execute(
@@ -124,11 +123,13 @@ class SleepDatabase:
124
123
 
125
124
  def sync(self) -> None:
126
125
  """Sync the database to disk"""
126
+ assert self.db
127
127
  self.db.commit()
128
128
 
129
129
  def record_debug(self, message, level=6) -> None:
130
130
  """Helper function to record a message to debug database"""
131
131
  assert self.last_suspend
132
+ assert self.db
132
133
  cur = self.db.cursor()
133
134
  cur.execute(
134
135
  "INSERT into debug (t0, id, message, priority) VALUES (?, ?, ?, ?)",
@@ -151,6 +152,8 @@ class SleepDatabase:
151
152
 
152
153
  def record_battery_energy(self, name, energy, full, unit):
153
154
  """Helper function to record battery energy"""
155
+ assert self.db
156
+ assert self.last_suspend
154
157
  cur = self.db.cursor()
155
158
  cur.execute(
156
159
  "SELECT * FROM battery WHERE t0=?",
@@ -180,6 +183,7 @@ class SleepDatabase:
180
183
  def record_cycle_data(self, message, symbol) -> None:
181
184
  """Helper function to record a message to cycle_data database"""
182
185
  assert self.last_suspend
186
+ assert self.db
183
187
  cur = self.db.cursor()
184
188
  cur.execute(
185
189
  """
@@ -207,6 +211,7 @@ class SleepDatabase:
207
211
  ) -> None:
208
212
  """Helper function to record a sleep cycle into the cycle database"""
209
213
  assert self.last_suspend
214
+ assert self.db
210
215
  cur = self.db.cursor()
211
216
  cur.execute(
212
217
  """
@@ -227,6 +232,7 @@ class SleepDatabase:
227
232
  def record_prereq(self, message, symbol) -> None:
228
233
  """Helper function to record a message to prereq_data database"""
229
234
  assert self.last_suspend
235
+ assert self.db
230
236
  cur = self.db.cursor()
231
237
  cur.execute(
232
238
  """
@@ -246,6 +252,7 @@ class SleepDatabase:
246
252
 
247
253
  def report_prereq(self, t0) -> list:
248
254
  """Helper function to report the prereq_data database"""
255
+ assert self.db
249
256
  if t0 is None:
250
257
  return []
251
258
  cur = self.db.cursor()
@@ -255,10 +262,11 @@ class SleepDatabase:
255
262
  )
256
263
  return cur.fetchall()
257
264
 
258
- def report_debug(self, t0) -> str:
265
+ def report_debug(self, t0) -> list:
259
266
  """Helper function to report the debug database"""
267
+ assert self.db
260
268
  if t0 is None:
261
- return ""
269
+ return []
262
270
  cur = self.db.cursor()
263
271
  cur.execute(
264
272
  "SELECT message, priority FROM debug WHERE t0=?",
@@ -268,6 +276,7 @@ class SleepDatabase:
268
276
 
269
277
  def report_cycle(self, t0=None) -> list:
270
278
  """Helper function to report a cycle from database"""
279
+ assert self.db
271
280
  if t0 is None:
272
281
  assert self.last_suspend
273
282
  t0 = self.last_suspend
@@ -280,7 +289,9 @@ class SleepDatabase:
280
289
 
281
290
  def report_cycle_data(self, t0=None) -> str:
282
291
  """Helper function to report a table matching a timestamp from cycle_data database"""
292
+ assert self.db
283
293
  if t0 is None:
294
+ assert self.last_suspend
284
295
  t0 = self.last_suspend
285
296
  cur = self.db.cursor()
286
297
  cur.execute(
@@ -294,7 +305,9 @@ class SleepDatabase:
294
305
 
295
306
  def report_battery(self, t0=None) -> list:
296
307
  """Helper function to report a line from battery database"""
308
+ assert self.db
297
309
  if t0 is None:
310
+ assert self.last_suspend
298
311
  t0 = self.last_suspend
299
312
  cur = self.db.cursor()
300
313
  cur.execute(
@@ -305,19 +318,23 @@ class SleepDatabase:
305
318
 
306
319
  def get_last_prereq_ts(self) -> int:
307
320
  """Helper function to report the last line from prereq database"""
321
+ assert self.db
308
322
  cur = self.db.cursor()
309
323
  cur.execute("SELECT * FROM prereq_data ORDER BY t0 DESC LIMIT 1")
310
324
  result = cur.fetchone()
311
- return result[0] if result else None
325
+ return result[0] if result else 0
312
326
 
313
327
  def get_last_cycle(self) -> list:
314
328
  """Helper function to report the last line from battery database"""
329
+ assert self.db
315
330
  cur = self.db.cursor()
316
331
  cur.execute("SELECT t0 FROM cycle ORDER BY t0 DESC LIMIT 1")
317
332
  return cur.fetchone()
318
333
 
319
334
  def report_summary_dataframe(self, since, until) -> object:
320
335
  """Helper function to report a dataframe from the database"""
336
+ assert self.db
337
+
321
338
  import pandas as pd # pylint: disable=import-outside-toplevel
322
339
 
323
340
  pd.set_option("display.precision", 2)
amd_debug/display.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env python3
2
1
  # SPDX-License-Identifier: MIT
3
2
  """Display analysis"""
4
3
  import os
@@ -12,7 +11,7 @@ class Display:
12
11
 
13
12
  def __init__(self):
14
13
  self.pyudev = Context()
15
- self.edid = {}
14
+ self.edid = []
16
15
 
17
16
  for dev in self.pyudev.list_devices(subsystem="drm"):
18
17
  if not "card" in dev.device_path:
@@ -27,7 +26,7 @@ class Display:
27
26
  f = read_file(p)
28
27
  if f != "enabled":
29
28
  continue
30
- self.edid[dev.sys_name] = os.path.join(dev.sys_path, "edid")
29
+ self.edid.append(os.path.join(dev.sys_path, "edid"))
31
30
 
32
31
  def get_edid(self) -> list:
33
32
  """Get the path for EDID data for all connected displays"""
amd_debug/failures.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
 
4
3
  from datetime import timedelta
@@ -48,6 +47,19 @@ class RtcAlarmWrong(S0i3Failure):
48
47
  self.url = "https://github.com/systemd/systemd/issues/24279"
49
48
 
50
49
 
50
+ class MissingGpu(S0i3Failure):
51
+ """GPU device is missing"""
52
+
53
+ def __init__(self):
54
+ super().__init__()
55
+ self.description = "GPU device is missing"
56
+ self.explanation = (
57
+ "Running the s2idle sequence without an integrated GPU is likely "
58
+ "to cause problems. If you have a mux in BIOS, enable the integrated "
59
+ "GPU."
60
+ )
61
+
62
+
51
63
  class MissingAmdgpu(S0i3Failure):
52
64
  """AMDGPU driver is missing"""
53
65
 
@@ -467,7 +479,7 @@ class MissingIommuACPI(S0i3Failure):
467
479
  super().__init__()
468
480
  self.description = f"Device {device} missing from ACPI tables"
469
481
  self.explanation = (
470
- "The ACPI device {device} is required for suspend to work when the IOMMU is enabled. "
482
+ f"The ACPI device {device} is required for suspend to work when the IOMMU is enabled. "
471
483
  "Please check your BIOS settings and if configured correctly, report a bug to your system vendor."
472
484
  )
473
485
  self.url = "https://gitlab.freedesktop.org/drm/amd/-/issues/3738#note_2667140"
amd_debug/installer.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
 
4
3
  """
@@ -197,7 +196,7 @@ class DisplayInfoPackage(DistroPackage):
197
196
  def __init__(self):
198
197
  super().__init__(
199
198
  deb="libdisplay-info-bin",
200
- rpm="libdisplay-info",
199
+ rpm="libdisplay-info-tools",
201
200
  arch="libdisplay-info",
202
201
  message=Headers.MissingDiEdidDecode,
203
202
  )
amd_debug/kernel.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/env python3
2
1
  # SPDX-License-Identifier: MIT
3
2
  """Kernel log analysis"""
4
3
 
@@ -158,7 +157,7 @@ class KernelLogger:
158
157
  def seek_tail(self, tim=None):
159
158
  """Seek to the end of the log"""
160
159
 
161
- def process_callback(self, callback, priority):
160
+ def process_callback(self, callback, priority=None):
162
161
  """Process the log"""
163
162
 
164
163
  def match_line(self, _matches) -> str:
@@ -175,7 +174,7 @@ class InputFile(KernelLogger):
175
174
 
176
175
  def __init__(self, fname):
177
176
  self.since_support = False
178
- self.buffer = None
177
+ self.buffer = ""
179
178
  self.seeked = False
180
179
  self.buffer = read_file(fname)
181
180
 
@@ -190,7 +189,7 @@ class DmesgLogger(KernelLogger):
190
189
 
191
190
  def __init__(self):
192
191
  self.since_support = False
193
- self.buffer = None
192
+ self.buffer = ""
194
193
  self.seeked = False
195
194
 
196
195
  cmd = ["dmesg", "-h"]
@@ -204,7 +203,7 @@ class DmesgLogger(KernelLogger):
204
203
  self._refresh_head()
205
204
 
206
205
  def _refresh_head(self):
207
- self.buffer = []
206
+ self.buffer = ""
208
207
  self.seeked = False
209
208
  result = subprocess.run(self.command, check=True, capture_output=True)
210
209
  if result.returncode == 0:
@@ -262,7 +261,11 @@ class CySystemdLogger(KernelLogger):
262
261
  """Class for logging using systemd journal using cython"""
263
262
 
264
263
  def __init__(self):
265
- from cysystemd.reader import JournalReader, JournalOpenMode, Rule
264
+ from cysystemd.reader import (
265
+ JournalReader,
266
+ JournalOpenMode,
267
+ Rule,
268
+ ) # pylint: disable=import-outside-toplevel
266
269
 
267
270
  boot_reader = JournalReader()
268
271
  boot_reader.open(JournalOpenMode.SYSTEM)
@@ -384,6 +387,6 @@ def get_kernel_log(input_file=None) -> KernelLogger:
384
387
  kernel_log = DmesgLogger()
385
388
  except subprocess.CalledProcessError as e:
386
389
  fatal_error(f"{e}")
387
- kernel_log = None
390
+ kernel_log = KernelLogger()
388
391
  logging.debug("Kernel log provider: %s", kernel_log.__class__.__name__)
389
392
  return kernel_log
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
 
4
3
  """
@@ -58,6 +57,7 @@ from amd_debug.failures import (
58
57
  MissingAmdgpu,
59
58
  MissingAmdgpuFirmware,
60
59
  MissingAmdPmc,
60
+ MissingGpu,
61
61
  MissingDriver,
62
62
  MissingIommuACPI,
63
63
  MissingIommuPolicy,
@@ -156,7 +156,7 @@ class PrerequisiteValidator(AmdTool):
156
156
  if len(edids) == 0:
157
157
  self.db.record_debug("No EDID data found")
158
158
  return True
159
- for name, p in edids.items():
159
+ for p in edids:
160
160
  output = None
161
161
  for tool in ["di-edid-decode", "edid-decode"]:
162
162
  try:
@@ -167,16 +167,17 @@ class PrerequisiteValidator(AmdTool):
167
167
  break
168
168
  except FileNotFoundError:
169
169
  self.db.record_debug(f"{cmd} not installed")
170
- except subprocess.CalledProcessError as e:
170
+ except subprocess.CalledProcessError as _e:
171
171
  pass
172
172
  if not output:
173
173
  self.db.record_prereq("Failed to capture EDID table", "👀")
174
174
  else:
175
- self.db.record_debug(apply_prefix_wrapper(f"EDID for {name}:", output))
175
+ self.db.record_debug(apply_prefix_wrapper(f"EDID for {p}:", output))
176
176
  return True
177
177
 
178
178
  def check_amdgpu(self):
179
179
  """Check for the AMDGPU driver"""
180
+ count = 0
180
181
  for device in self.pyudev.list_devices(subsystem="pci"):
181
182
  klass = device.properties.get("PCI_CLASS")
182
183
  if klass not in ["30000", "38000"]:
@@ -184,6 +185,7 @@ class PrerequisiteValidator(AmdTool):
184
185
  pci_id = device.properties.get("PCI_ID")
185
186
  if not pci_id.startswith("1002"):
186
187
  continue
188
+ count += 1
187
189
  if device.properties.get("DRIVER") != "amdgpu":
188
190
  self.db.record_prereq("GPU driver `amdgpu` not loaded", "❌")
189
191
  self.failures += [MissingAmdgpu()]
@@ -191,6 +193,10 @@ class PrerequisiteValidator(AmdTool):
191
193
  slot = device.properties.get("PCI_SLOT_NAME")
192
194
 
193
195
  self.db.record_prereq(f"GPU driver `amdgpu` bound to {slot}", "✅")
196
+ if count == 0:
197
+ self.db.record_prereq("Integrated GPU not found", "❌")
198
+ self.failures += [MissingGpu()]
199
+ return False
194
200
  return True
195
201
 
196
202
  def check_amdgpu_parameters(self):
@@ -742,6 +748,9 @@ class PrerequisiteValidator(AmdTool):
742
748
  p = os.path.join("/", "sys", "kernel", "debug", "gpio")
743
749
  try:
744
750
  contents = read_file(p)
751
+ except FileNotFoundError:
752
+ self.db.record_prereq("GPIO debugfs not available", "👀")
753
+ contents = None
745
754
  except PermissionError:
746
755
  self.db.record_debug(f"Unable to capture {p}")
747
756
  contents = None
@@ -778,7 +787,7 @@ class PrerequisiteValidator(AmdTool):
778
787
  "utf-8"
779
788
  )
780
789
  except FileNotFoundError:
781
- self.db.record_prereq(f"ethtool is missing", "👀")
790
+ self.db.record_prereq("ethtool is missing", "👀")
782
791
  return True
783
792
  for line in output.split("\n"):
784
793
  if "Supports Wake-on" in line:
@@ -1179,7 +1188,6 @@ class PrerequisiteValidator(AmdTool):
1179
1188
  if self.cpu_family == 0x1A and self.cpu_model in affected_1a:
1180
1189
  found_iommu = False
1181
1190
  found_acpi = False
1182
- found_dmar = False
1183
1191
  for dev in self.pyudev.list_devices(subsystem="iommu"):
1184
1192
  found_iommu = True
1185
1193
  debug_str += f"Found IOMMU {dev.sys_path}\n"
@@ -1355,7 +1363,7 @@ class PrerequisiteValidator(AmdTool):
1355
1363
  logging.debug(line)
1356
1364
 
1357
1365
  if len(self.failures) == 0:
1358
- return True
1366
+ return
1359
1367
  print_color(Headers.ExplanationReport, "🗣️")
1360
1368
  for item in self.failures:
1361
1369
  item.get_failure()
amd_debug/pstate.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
  """CPPC triage script for AMD systems"""
4
3
 
amd_debug/s2idle.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
  """s2idle analysis tool"""
4
3
  import argparse
@@ -75,7 +74,7 @@ def display_report_file(fname, fmt) -> None:
75
74
  def get_report_file(report_file, extension) -> str:
76
75
  """Prompt user for report file"""
77
76
  if extension == "stdout":
78
- return None
77
+ return ""
79
78
  if not report_file:
80
79
  return f"amd-s2idle-report-{date.today()}.{extension}"
81
80
  return report_file
@@ -88,7 +87,7 @@ def get_report_format() -> str:
88
87
  return "html"
89
88
 
90
89
 
91
- def prompt_report_arguments(since, until, fname, fmt, report_debug) -> str:
90
+ def prompt_report_arguments(since, until, fname, fmt, report_debug) -> list:
92
91
  """Prompt user for report configuration"""
93
92
  if not since:
94
93
  default = Defaults.since
@@ -213,8 +212,10 @@ def run_test_cycle(
213
212
 
214
213
  try:
215
214
  duration, wait, count = prompt_test_arguments(duration, wait, count, rand)
215
+ total_seconds = (duration + wait) * count
216
+ until_time = datetime.now() + timedelta(seconds=total_seconds)
216
217
  since, until, fname, fmt, report_debug = prompt_report_arguments(
217
- datetime.now().isoformat(), Defaults.until.isoformat(), fname, fmt, True
218
+ datetime.now().isoformat(), until_time.isoformat(), fname, fmt, True
218
219
  )
219
220
  except KeyboardInterrupt:
220
221
  sys.exit("\nTest cancelled")
amd_debug/sleep_report.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
 
4
3
  import os
amd_debug/ttm.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
  """TTM configuration tool"""
4
3
 
amd_debug/validator.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
 
4
3
  import glob
@@ -435,7 +434,6 @@ class SleepValidator(AmdTool):
435
434
  continue
436
435
  self.db.record_debug(
437
436
  f"Woke up from input source {device} ({self.wakeup_count[device]}->{count})",
438
- "💤",
439
437
  )
440
438
  self.wakeup_count = wakeup_count
441
439
 
@@ -470,7 +468,7 @@ class SleepValidator(AmdTool):
470
468
  self.db.record_debug(f"HW sleep statistics file {p} is missing")
471
469
  if not self.hw_sleep_duration:
472
470
  self.db.record_cycle_data("Did not reach hardware sleep state", "❌")
473
- return self.hw_sleep_duration
471
+ return self.hw_sleep_duration > 0
474
472
 
475
473
  def capture_command_line(self):
476
474
  """Capture the kernel command line to debug"""
@@ -583,7 +581,6 @@ class SleepValidator(AmdTool):
583
581
  if bit_changed & BIT(bit):
584
582
  self.db.record_debug(
585
583
  f"Idle mask bit {bit} (0x{BIT(bit):x}) changed during suspend",
586
- "○",
587
584
  )
588
585
  if self.upep:
589
586
  if self.upep_microsoft:
@@ -661,10 +658,10 @@ class SleepValidator(AmdTool):
661
658
  check()
662
659
  self.db.record_cycle(
663
660
  self.requested_duration,
664
- self.active_gpios,
665
- self.wakeup_irqs,
666
- self.kernel_duration,
667
- self.hw_sleep_duration,
661
+ ",".join(str(gpio) for gpio in self.active_gpios),
662
+ ",".join(str(irq) for irq in self.wakeup_irqs),
663
+ int(self.kernel_duration),
664
+ int(self.hw_sleep_duration),
668
665
  )
669
666
 
670
667
  def prep(self):
amd_debug/wake.py CHANGED
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
 
4
3
  import os
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: amd-debug-tools
3
- Version: 0.2.8
3
+ Version: 0.2.9
4
4
  Summary: debug tools for AMD systems
5
5
  Author-email: Mario Limonciello <superm1@kernel.org>
6
6
  License-Expression: MIT
@@ -63,7 +63,7 @@ to set up the environment:
63
63
  This will add the `pipx` environment to your path.
64
64
 
65
65
  ## Running in-tree
66
- Documentation about running directly from a git checkout is available [here](https://github.com/superm1/amd-debug-tools/blob/master/docs/amd-s2idle.md).
66
+ Documentation about running directly from a git checkout is available [here](https://github.com/superm1/amd-debug-tools/blob/master/docs/in-tree.md).
67
67
 
68
68
  ## Tools
69
69
 
@@ -0,0 +1,47 @@
1
+ launcher.py,sha256=M8kT9DtyZoQgZaKWDbSBu4jsS6tZF1gWko3sovNVyag,947
2
+ test_acpi.py,sha256=wtS43Rz95h7YEEJBeFa6Mswaeo4syBZrw4hY8i0YbJY,3117
3
+ test_batteries.py,sha256=nN5pfP5El7Whypq3HHEpW8bufdf5EWSTVGbayfNQYP4,3360
4
+ test_bios.py,sha256=x_KLmQqGEbQhTugyWCHGXjGp2H1dCdhRz0kgw2Big8w,9276
5
+ test_common.py,sha256=qOCouXyO-dhY_x_L8kyNyuP_c0bhHhlqPoc084_F6Xg,20757
6
+ test_database.py,sha256=HAC4M4dyZBxskNFMfZn2kro6uT2-j0exjnto8-0OOnk,10042
7
+ test_display.py,sha256=awC1-OEPG1aV34BH-MzrOWtAHHPfhCmnKRetas4AGNE,5813
8
+ test_failures.py,sha256=H1UxXeVjhJs9-j9yas4vwAha676GX1Es7Kz8RN2B590,6845
9
+ test_installer.py,sha256=tZpGUOY4ACgXU-cs1Z5RHSPY5INa3HhLmmuB2H4QrOc,10222
10
+ test_kernel.py,sha256=2EXrLht5ZWdT4N5pb_F3zqZl9NEghjnDpcMGCMw3obI,7917
11
+ test_launcher.py,sha256=8g8CBTvLX64Us4RmHtRPSdpV5E2kQFaudBl7VIsxLhE,1733
12
+ test_prerequisites.py,sha256=SJk9y5zXdBmsNbtPMbBOHzkFsnuQF0j3BS6tdZ3ccTo,95944
13
+ test_pstate.py,sha256=a9oAJ9-LANX32XNQhplz6Y75VNYc__QqoSBKIrwvANg,6058
14
+ test_s2idle.py,sha256=FxsyujgX9Px3m56VzHNeA8yMTHmJiRLWxYt-fh1m5gw,33585
15
+ test_sleep_report.py,sha256=ANuxYi_C1oSKAi4xUU2wBu4SwJtcZA7VPpazBe3_WUQ,6922
16
+ test_ttm.py,sha256=QrCdRodQ_CD3nyDqKodb6yR158mgE0iIM5f1fV1Axu8,10515
17
+ test_validator.py,sha256=bfFFB2V3hrZtxTruwrvcUyZjoh-dcDa2TPt-l6pAfTA,36476
18
+ test_wake.py,sha256=6zi5GVFHQKU1sTWw3O5-aGriB9uu5713QLn4l2wjhpM,7152
19
+ amd_debug/__init__.py,sha256=0VsbaXBas5gcwZ6vBbJg20-8qHNDo_BKFYzdb1Agfq4,1252
20
+ amd_debug/acpi.py,sha256=_lnnAwTnAb4g8AW2BXwF45UY-WUmXIDpthhFLE5ENGo,3142
21
+ amd_debug/battery.py,sha256=qd6bo1ssAPnEfPY2HCmJfFcwgYADrfoJkxFQWQyxKlU,3103
22
+ amd_debug/bios.py,sha256=3dfE5yVoW0aZUN5osGKOtYF-RLOzUcH3ryA4yHZZoJA,4022
23
+ amd_debug/common.py,sha256=OR0rCFkWWoGlRIdsPdJ0hBr9iQ_vXcjIAL3poZ9BTj8,12606
24
+ amd_debug/database.py,sha256=kkl1iKIvekpVMc8M0xzo0iX3rc4yDaREyjCuLSnGuCk,11052
25
+ amd_debug/display.py,sha256=XATsKPh2QDoJAbm5mAE1YNFdVuFEq3yS3dffEasEq8c,922
26
+ amd_debug/failures.py,sha256=Sa2GEwhn8PImcIbZkHEPA2oCbuayTx9JheLaXBscz4I,23280
27
+ amd_debug/installer.py,sha256=JNlqGWNgF5pYxzy2VJiphmP4gXg99F0f4TBy2xk1Tpg,14275
28
+ amd_debug/kernel.py,sha256=w2y4syIMPd4OYXhPYrEmCDYnMBg9K16tK6iNwfzRVWU,11718
29
+ amd_debug/prerequisites.py,sha256=f55y-DUCMQHPWSQRjJcP-J8qvGaNKbXUIBbyhOzUB1U,52632
30
+ amd_debug/pstate.py,sha256=fGA-pKS1mzIrOa9fIqd_q3Y9DvMhuWmInq5GPAGc21k,9564
31
+ amd_debug/s2idle-hook,sha256=LLiaqPtGd0qetu9n6EYxKHZaIdHpVQDONdOuSc0pfFg,1695
32
+ amd_debug/s2idle.py,sha256=tj1_5g2adTScWfgaFAlH4NVjAse2jSCgOhpaOeWBYzk,13381
33
+ amd_debug/sleep_report.py,sha256=JQDtd_y-78gXQN5o7O7h-hKosEOWZeTmnZBSepdeCEE,17298
34
+ amd_debug/ttm.py,sha256=KoCY35jnU7Q2ZB0SO1nQmC_RsiCFwTWUzVmRbyUg0Lw,4660
35
+ amd_debug/validator.py,sha256=OEpaIAnkZg_GF_MeU48YNj8Wcj45vEgT7edqgflsChM,34151
36
+ amd_debug/wake.py,sha256=x33z60sOaukTlZTABKpvLJZVRk-kIe_o8XljtV3Q38Q,3917
37
+ amd_debug/bash/amd-s2idle,sha256=g_cle1ElCJpwE4wcLezL6y-BdasDKTnNMhrtzKLE9ks,1142
38
+ amd_debug/templates/html,sha256=JfGhpmHIB2C2GItdGI1kuC8uayqEVgrpQvAWAj35eZ4,14580
39
+ amd_debug/templates/md,sha256=r8X2aehnH2gzj0WHYTZ5K9wAqC5y39i_3nkDORSC0uM,787
40
+ amd_debug/templates/stdout,sha256=hyoOJ96K2dJfnWRWhyCuariLKbEHXvs9mstV_g5aMdI,469
41
+ amd_debug/templates/txt,sha256=nNdsvbPFOhGdL7VA-_4k5aN3nB-6ouGQt6AsWst7T3w,649
42
+ amd_debug_tools-0.2.9.dist-info/licenses/LICENSE,sha256=RBlZI6r3MRGzymI2VDX2iW__D2APDbMhu_Xg5t6BWeo,1066
43
+ amd_debug_tools-0.2.9.dist-info/METADATA,sha256=4rIp2I7Oipo1o3hCRtw4CoCf3IliJjyJcUV6SnYhkrE,2772
44
+ amd_debug_tools-0.2.9.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
+ amd_debug_tools-0.2.9.dist-info/entry_points.txt,sha256=hIskDz6k0_6q1qpqWCpVFsca_djxAqkLrUAwzAyEGuE,144
46
+ amd_debug_tools-0.2.9.dist-info/top_level.txt,sha256=VvGkkY5I7O3HoLNrc2VfgjCA-to3PUjnnKd7juONaFw,243
47
+ amd_debug_tools-0.2.9.dist-info/RECORD,,
test_database.py CHANGED
@@ -255,7 +255,7 @@ class TestSleepDatabase(unittest.TestCase):
255
255
  def test_get_last_prereq_ts_no_data(self):
256
256
  """Test getting the last prereq timestamp when no data exists"""
257
257
  result = self.db.get_last_prereq_ts()
258
- self.assertIsNone(result)
258
+ self.assertEqual(result, 0)
259
259
 
260
260
  def test_report_cycle_data(self):
261
261
  """Test reporting cycle data"""
test_display.py CHANGED
@@ -40,7 +40,7 @@ class TestDisplay(unittest.TestCase):
40
40
  display = Display()
41
41
 
42
42
  # Verify the EDID paths are correctly set
43
- expected_edid = {"card0": "/sys/devices/card0/edid"}
43
+ expected_edid = ["/sys/devices/card0/edid"]
44
44
  self.assertEqual(display.get_edid(), expected_edid)
45
45
  mock_context.assert_called_once()
46
46
 
@@ -54,7 +54,7 @@ class TestDisplay(unittest.TestCase):
54
54
  display = Display()
55
55
 
56
56
  # Verify the EDID dictionary is empty
57
- self.assertEqual(display.get_edid(), {})
57
+ self.assertEqual(display.get_edid(), [])
58
58
 
59
59
  @patch("amd_debug.display.Context")
60
60
  def test_device_without_card(self, mock_context):
@@ -70,7 +70,7 @@ class TestDisplay(unittest.TestCase):
70
70
  display = Display()
71
71
 
72
72
  # Verify the EDID dictionary is empty
73
- self.assertEqual(display.get_edid(), {})
73
+ self.assertEqual(display.get_edid(), [])
74
74
 
75
75
  @patch("amd_debug.display.Context")
76
76
  @patch("amd_debug.display.read_file")
@@ -94,7 +94,7 @@ class TestDisplay(unittest.TestCase):
94
94
  display = Display()
95
95
 
96
96
  # Verify the EDID dictionary is empty
97
- self.assertEqual(display.get_edid(), {})
97
+ self.assertEqual(display.get_edid(), [])
98
98
 
99
99
  @patch("amd_debug.display.Context")
100
100
  @patch("amd_debug.display.read_file")
@@ -116,7 +116,7 @@ class TestDisplay(unittest.TestCase):
116
116
  display = Display()
117
117
 
118
118
  # Verify the EDID dictionary is empty
119
- self.assertEqual(display.get_edid(), {})
119
+ self.assertEqual(display.get_edid(), [])
120
120
 
121
121
  @patch("amd_debug.display.Context")
122
122
  @patch("amd_debug.display.read_file")
@@ -140,4 +140,4 @@ class TestDisplay(unittest.TestCase):
140
140
  display = Display()
141
141
 
142
142
  # Verify the EDID dictionary is empty
143
- self.assertEqual(display.get_edid(), {})
143
+ self.assertEqual(display.get_edid(), [])
test_installer.py CHANGED
@@ -231,7 +231,7 @@ class TestInstaller(unittest.TestCase):
231
231
  self.installer.set_requirements("edid-decode")
232
232
  ret = self.installer.install_dependencies()
233
233
  _mock_check_call.assert_called_once_with(
234
- ["dnf", "install", "-y", "libdisplay-info"]
234
+ ["dnf", "install", "-y", "libdisplay-info-tools"]
235
235
  )
236
236
  self.assertTrue(ret)
237
237
 
test_prerequisites.py CHANGED
@@ -2108,3 +2108,107 @@ class TestPrerequisiteValidator(unittest.TestCase):
2108
2108
  ]
2109
2109
  self.validator.capture_cstates()
2110
2110
  self.mock_db.record_debug.assert_called_with("ACPI C-state information\n")
2111
+
2112
+ @patch("amd_debug.prerequisites.read_file")
2113
+ def test_check_pinctrl_amd_driver_loaded_with_missing_file_error(
2114
+ self, mock_read_file
2115
+ ):
2116
+ """Test check_pinctrl_amd when the driver is loaded but debug file is missing"""
2117
+ mock_read_file.side_effect = FileNotFoundError
2118
+ self.mock_pyudev.list_devices.return_value = [
2119
+ MagicMock(properties={"DRIVER": "amd_gpio"})
2120
+ ]
2121
+
2122
+ result = self.validator.check_pinctrl_amd()
2123
+ self.assertTrue(result)
2124
+ self.mock_db.record_prereq.assert_called_with(
2125
+ "GPIO debugfs not available", "👀"
2126
+ )
2127
+
2128
+ def test_check_amdgpu_no_devices(self):
2129
+ """Test check_amdgpu when no PCI devices are found"""
2130
+ self.mock_pyudev.list_devices.return_value = []
2131
+ result = self.validator.check_amdgpu()
2132
+ self.assertFalse(result)
2133
+ self.mock_db.record_prereq.assert_called_with("Integrated GPU not found", "❌")
2134
+ self.assertTrue(any(isinstance(f, MissingGpu) for f in self.validator.failures))
2135
+
2136
+ def test_check_amdgpu_non_amd_devices(self):
2137
+ """Test check_amdgpu when PCI devices are present but not AMD GPUs"""
2138
+ self.mock_pyudev.list_devices.return_value = [
2139
+ MagicMock(
2140
+ properties={
2141
+ "PCI_CLASS": "30000",
2142
+ "PCI_ID": "8086abcd",
2143
+ "DRIVER": "i915",
2144
+ }
2145
+ ),
2146
+ ]
2147
+ result = self.validator.check_amdgpu()
2148
+ self.assertFalse(result)
2149
+ self.mock_db.record_prereq.assert_called_with("Integrated GPU not found", "❌")
2150
+ self.assertTrue(any(isinstance(f, MissingGpu) for f in self.validator.failures))
2151
+
2152
+ def test_check_amdgpu_driver_not_loaded(self):
2153
+ """Test check_amdgpu when AMD GPU is present but driver is not loaded"""
2154
+ self.mock_pyudev.list_devices.return_value = [
2155
+ MagicMock(
2156
+ properties={"PCI_CLASS": "20000", "PCI_ID": "1111abcd", "DRIVER": None}
2157
+ ),
2158
+ MagicMock(
2159
+ properties={"PCI_CLASS": "30000", "PCI_ID": "1002abcd", "DRIVER": None}
2160
+ ),
2161
+ ]
2162
+ result = self.validator.check_amdgpu()
2163
+ self.assertFalse(result)
2164
+ self.mock_db.record_prereq.assert_called_with(
2165
+ "GPU driver `amdgpu` not loaded", "❌"
2166
+ )
2167
+ self.assertTrue(
2168
+ any(isinstance(f, MissingAmdgpu) for f in self.validator.failures)
2169
+ )
2170
+
2171
+ def test_check_amdgpu_driver_loaded(self):
2172
+ """Test check_amdgpu when AMD GPU is present and driver is loaded"""
2173
+ self.mock_pyudev.list_devices.return_value = [
2174
+ MagicMock(
2175
+ properties={
2176
+ "PCI_CLASS": "30000",
2177
+ "PCI_ID": "1002abcd",
2178
+ "DRIVER": "amdgpu",
2179
+ "PCI_SLOT_NAME": "0000:01:00.0",
2180
+ }
2181
+ ),
2182
+ ]
2183
+ result = self.validator.check_amdgpu()
2184
+ self.assertTrue(result)
2185
+ self.mock_db.record_prereq.assert_called_with(
2186
+ "GPU driver `amdgpu` bound to 0000:01:00.0", "✅"
2187
+ )
2188
+
2189
+ def test_check_amdgpu_multiple_devices_mixed(self):
2190
+ """Test check_amdgpu with multiple devices, one with driver loaded, one without"""
2191
+ self.mock_pyudev.list_devices.return_value = [
2192
+ MagicMock(
2193
+ properties={
2194
+ "PCI_CLASS": "30000",
2195
+ "PCI_ID": "1002abcd",
2196
+ "DRIVER": "amdgpu",
2197
+ "PCI_SLOT_NAME": "0000:01:00.0",
2198
+ }
2199
+ ),
2200
+ MagicMock(
2201
+ properties={"PCI_CLASS": "30000", "PCI_ID": "1002abcd", "DRIVER": None}
2202
+ ),
2203
+ ]
2204
+ result = self.validator.check_amdgpu()
2205
+ self.assertFalse(result)
2206
+ self.mock_db.record_prereq.assert_any_call(
2207
+ "GPU driver `amdgpu` bound to 0000:01:00.0", "✅"
2208
+ )
2209
+ self.mock_db.record_prereq.assert_any_call(
2210
+ "GPU driver `amdgpu` not loaded", "❌"
2211
+ )
2212
+ self.assertTrue(
2213
+ any(isinstance(f, MissingAmdgpu) for f in self.validator.failures)
2214
+ )
test_validator.py CHANGED
@@ -264,7 +264,7 @@ class TestValidator(unittest.TestCase):
264
264
 
265
265
  # Validate debug messages
266
266
  mock_record_debug.assert_called_once_with(
267
- "Woke up from input source /sys/devices/input0 (3->5)", "💤"
267
+ "Woke up from input source /sys/devices/input0 (3->5)"
268
268
  )
269
269
 
270
270
  # Stop patches
@@ -557,7 +557,7 @@ class TestValidator(unittest.TestCase):
557
557
  # Set attributes for record_cycle
558
558
  self.validator.requested_duration = 60
559
559
  self.validator.active_gpios = ["GPIO1"]
560
- self.validator.wakeup_irqs = [5]
560
+ self.validator.wakeup_irqs = ["5"]
561
561
  self.validator.kernel_duration = 1.5
562
562
  self.validator.hw_sleep_duration = 1.0
563
563
 
@@ -580,10 +580,10 @@ class TestValidator(unittest.TestCase):
580
580
  # Assert record_cycle was called with correct arguments
581
581
  mock_record_cycle.assert_called_once_with(
582
582
  self.validator.requested_duration,
583
- self.validator.active_gpios,
584
- self.validator.wakeup_irqs,
585
- self.validator.kernel_duration,
586
- self.validator.hw_sleep_duration,
583
+ ",".join(str(gpio) for gpio in self.validator.active_gpios),
584
+ ",".join(str(irq) for irq in self.validator.wakeup_irqs),
585
+ int(self.validator.kernel_duration),
586
+ int(self.validator.hw_sleep_duration),
587
587
  )
588
588
 
589
589
  def test_program_wakealarm(self):
@@ -1,47 +0,0 @@
1
- launcher.py,sha256=M8kT9DtyZoQgZaKWDbSBu4jsS6tZF1gWko3sovNVyag,947
2
- test_acpi.py,sha256=wtS43Rz95h7YEEJBeFa6Mswaeo4syBZrw4hY8i0YbJY,3117
3
- test_batteries.py,sha256=nN5pfP5El7Whypq3HHEpW8bufdf5EWSTVGbayfNQYP4,3360
4
- test_bios.py,sha256=x_KLmQqGEbQhTugyWCHGXjGp2H1dCdhRz0kgw2Big8w,9276
5
- test_common.py,sha256=qOCouXyO-dhY_x_L8kyNyuP_c0bhHhlqPoc084_F6Xg,20757
6
- test_database.py,sha256=q5ZjI5u20f7ki6iCY5o1iPi0YOvPz1_W0LTDraU8mN4,10040
7
- test_display.py,sha256=hHggv-zBthF1BlwWWSjzAm7BBw1DWcElwil5xAuz87g,5822
8
- test_failures.py,sha256=H1UxXeVjhJs9-j9yas4vwAha676GX1Es7Kz8RN2B590,6845
9
- test_installer.py,sha256=oDMCvaKqqAWjTggltacnasQ-s1gyUvXPDcNrCUGnux4,10216
10
- test_kernel.py,sha256=2EXrLht5ZWdT4N5pb_F3zqZl9NEghjnDpcMGCMw3obI,7917
11
- test_launcher.py,sha256=8g8CBTvLX64Us4RmHtRPSdpV5E2kQFaudBl7VIsxLhE,1733
12
- test_prerequisites.py,sha256=ig0ENpnR-wRMNlxLQ1FghivQsOu4yx5XP4HsJlptyQA,91791
13
- test_pstate.py,sha256=a9oAJ9-LANX32XNQhplz6Y75VNYc__QqoSBKIrwvANg,6058
14
- test_s2idle.py,sha256=FxsyujgX9Px3m56VzHNeA8yMTHmJiRLWxYt-fh1m5gw,33585
15
- test_sleep_report.py,sha256=ANuxYi_C1oSKAi4xUU2wBu4SwJtcZA7VPpazBe3_WUQ,6922
16
- test_ttm.py,sha256=QrCdRodQ_CD3nyDqKodb6yR158mgE0iIM5f1fV1Axu8,10515
17
- test_validator.py,sha256=RpjyzxDpExhLcSJfQ0UDuonr4sTFAfa7sTtY5g7tc_Q,36410
18
- test_wake.py,sha256=6zi5GVFHQKU1sTWw3O5-aGriB9uu5713QLn4l2wjhpM,7152
19
- amd_debug/__init__.py,sha256=66Ya61av8RCws6bEY_vdujGmjBIZ6_UqfuWHgMNNOJY,1271
20
- amd_debug/acpi.py,sha256=fkD3Sov8cRT5ryPlakRlT7Z9jiCLT9x_MPWxt3xU_tc,3161
21
- amd_debug/battery.py,sha256=WN-6ys9PHCZIwg7PdwyBOa62GjBp8WKG0v1YZt5_W5s,3122
22
- amd_debug/bios.py,sha256=y1iwDqX-mXCkoUtHSi-XO9pN-oLfaqbAMzANGI12zHs,4041
23
- amd_debug/common.py,sha256=JclB-X3xwz2Ovvm0nsejE3W9FirP-inTgvHYx7MPNZo,12635
24
- amd_debug/database.py,sha256=GkRg3cmaNceyQ2_hy0MBAlMbnTDPHo2co2o4ObWpnQg,10621
25
- amd_debug/display.py,sha256=5L9x9tI_UoulHpIvuxuVASRtdXta7UCW_JjTb5StEB0,953
26
- amd_debug/failures.py,sha256=z4O4Q-akv3xYGssSZFCqE0cDE4P9F_aw1hxil3McoD4,22910
27
- amd_debug/installer.py,sha256=6_Y0oHypW-oh_P8N9JW7fzbqidpsi5jphw9_8s5Qvso,14288
28
- amd_debug/kernel.py,sha256=HpX-QRh8tgkvqKnExfo2JrYqfcbMY8GNgDrC2VVV0Oc,11638
29
- amd_debug/prerequisites.py,sha256=-awyFaG2KCX3GSvVyzH1-o3UPhkMNm7Wf3F5AwYWH5U,52340
30
- amd_debug/pstate.py,sha256=AOKCvUb0ngwHU2C59uSKrFwdLzEyn8r1w2DgWhZAMKM,9583
31
- amd_debug/s2idle-hook,sha256=LLiaqPtGd0qetu9n6EYxKHZaIdHpVQDONdOuSc0pfFg,1695
32
- amd_debug/s2idle.py,sha256=4cxHNfmvq11BE-AtkEthIqR-xrWmxW2LTa6oVDtGztY,13284
33
- amd_debug/sleep_report.py,sha256=EzzvOHe0XxZcr8ZurxQXFjKs21gJPBj-qksj4a2WLuM,17317
34
- amd_debug/ttm.py,sha256=p9zV7OAOrcbI8apOkRMnsI8g1GDvOJfNEAklFuFGdRQ,4679
35
- amd_debug/validator.py,sha256=X-cNFVvHWKzFgT4aR0Td3I2kwQRBOK4vQUk6L276VCQ,34153
36
- amd_debug/wake.py,sha256=xT8WrFrN6voCmXWo5dsn4mQ7iR2QJxHrrYBd3EREG-Q,3936
37
- amd_debug/bash/amd-s2idle,sha256=g_cle1ElCJpwE4wcLezL6y-BdasDKTnNMhrtzKLE9ks,1142
38
- amd_debug/templates/html,sha256=JfGhpmHIB2C2GItdGI1kuC8uayqEVgrpQvAWAj35eZ4,14580
39
- amd_debug/templates/md,sha256=r8X2aehnH2gzj0WHYTZ5K9wAqC5y39i_3nkDORSC0uM,787
40
- amd_debug/templates/stdout,sha256=hyoOJ96K2dJfnWRWhyCuariLKbEHXvs9mstV_g5aMdI,469
41
- amd_debug/templates/txt,sha256=nNdsvbPFOhGdL7VA-_4k5aN3nB-6ouGQt6AsWst7T3w,649
42
- amd_debug_tools-0.2.8.dist-info/licenses/LICENSE,sha256=RBlZI6r3MRGzymI2VDX2iW__D2APDbMhu_Xg5t6BWeo,1066
43
- amd_debug_tools-0.2.8.dist-info/METADATA,sha256=rd1U-CfX7hGfsubYk0mvuR3Ec92dAZrquTKGKRdOFEk,2775
44
- amd_debug_tools-0.2.8.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
45
- amd_debug_tools-0.2.8.dist-info/entry_points.txt,sha256=hIskDz6k0_6q1qpqWCpVFsca_djxAqkLrUAwzAyEGuE,144
46
- amd_debug_tools-0.2.8.dist-info/top_level.txt,sha256=VvGkkY5I7O3HoLNrc2VfgjCA-to3PUjnnKd7juONaFw,243
47
- amd_debug_tools-0.2.8.dist-info/RECORD,,