amd-debug-tools 0.2.5__py3-none-any.whl → 0.2.12__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.
@@ -1,4 +1,3 @@
1
- #!/usr/bin/python3
2
1
  # SPDX-License-Identifier: MIT
3
2
 
4
3
  """
@@ -21,7 +20,7 @@ import pyudev
21
20
 
22
21
  from amd_debug.wake import WakeIRQ
23
22
  from amd_debug.display import Display
24
- from amd_debug.kernel import get_kernel_log, SystemdLogger, DmesgLogger
23
+ from amd_debug.kernel import get_kernel_log, SystemdLogger, CySystemdLogger, DmesgLogger
25
24
  from amd_debug.common import (
26
25
  apply_prefix_wrapper,
27
26
  BIT,
@@ -55,12 +54,15 @@ from amd_debug.failures import (
55
54
  I2CHidBug,
56
55
  KernelRingBufferWrapped,
57
56
  LimitedCores,
57
+ MissingAmdCaptureModule,
58
58
  MissingAmdgpu,
59
59
  MissingAmdgpuFirmware,
60
60
  MissingAmdPmc,
61
+ MissingGpu,
61
62
  MissingDriver,
62
63
  MissingIommuACPI,
63
64
  MissingIommuPolicy,
65
+ MissingIsp4PlatformDriver,
64
66
  MissingThunderbolt,
65
67
  MissingXhciHcd,
66
68
  MSRFailure,
@@ -128,13 +130,35 @@ class PrerequisiteValidator(AmdTool):
128
130
  if not self.db.get_last_prereq_ts():
129
131
  self.run()
130
132
 
133
+ def capture_nvidia(self):
134
+ """Capture the NVIDIA GPU state"""
135
+ p = os.path.join("/", "proc", "driver", "nvidia", "version")
136
+ if not os.path.exists(p):
137
+ return True
138
+ try:
139
+ self.db.record_debug_file(p)
140
+ except PermissionError:
141
+ self.db.record_prereq("NVIDIA GPU version not readable", "👀")
142
+ return True
143
+ p = os.path.join("/", "proc", "driver", "nvidia", "gpus")
144
+ if not os.path.exists(p):
145
+ return True
146
+ for root, _dirs, files in os.walk(p, topdown=False):
147
+ for f in files:
148
+ try:
149
+ self.db.record_debug(f"NVIDIA {f}")
150
+ self.db.record_debug_file(os.path.join(root, f))
151
+ except PermissionError:
152
+ self.db.record_prereq("NVIDIA GPU {f} not readable", "👀")
153
+ return True
154
+
131
155
  def capture_edid(self):
132
156
  """Capture and decode the EDID data"""
133
157
  edids = self.display.get_edid()
134
158
  if len(edids) == 0:
135
159
  self.db.record_debug("No EDID data found")
136
160
  return True
137
- for name, p in edids.items():
161
+ for p in edids:
138
162
  output = None
139
163
  for tool in ["di-edid-decode", "edid-decode"]:
140
164
  try:
@@ -145,16 +169,17 @@ class PrerequisiteValidator(AmdTool):
145
169
  break
146
170
  except FileNotFoundError:
147
171
  self.db.record_debug(f"{cmd} not installed")
148
- except subprocess.CalledProcessError as e:
172
+ except subprocess.CalledProcessError as _e:
149
173
  pass
150
174
  if not output:
151
175
  self.db.record_prereq("Failed to capture EDID table", "👀")
152
176
  else:
153
- self.db.record_debug(apply_prefix_wrapper(f"EDID for {name}:", output))
177
+ self.db.record_debug(apply_prefix_wrapper(f"EDID for {p}:", output))
154
178
  return True
155
179
 
156
180
  def check_amdgpu(self):
157
181
  """Check for the AMDGPU driver"""
182
+ count = 0
158
183
  for device in self.pyudev.list_devices(subsystem="pci"):
159
184
  klass = device.properties.get("PCI_CLASS")
160
185
  if klass not in ["30000", "38000"]:
@@ -162,6 +187,7 @@ class PrerequisiteValidator(AmdTool):
162
187
  pci_id = device.properties.get("PCI_ID")
163
188
  if not pci_id.startswith("1002"):
164
189
  continue
190
+ count += 1
165
191
  if device.properties.get("DRIVER") != "amdgpu":
166
192
  self.db.record_prereq("GPU driver `amdgpu` not loaded", "❌")
167
193
  self.failures += [MissingAmdgpu()]
@@ -169,6 +195,10 @@ class PrerequisiteValidator(AmdTool):
169
195
  slot = device.properties.get("PCI_SLOT_NAME")
170
196
 
171
197
  self.db.record_prereq(f"GPU driver `amdgpu` bound to {slot}", "✅")
198
+ if count == 0:
199
+ self.db.record_prereq("Integrated GPU not found", "❌")
200
+ self.failures += [MissingGpu()]
201
+ return False
172
202
  return True
173
203
 
174
204
  def check_amdgpu_parameters(self):
@@ -650,7 +680,9 @@ class PrerequisiteValidator(AmdTool):
650
680
  """Check the source for kernel logs"""
651
681
  if isinstance(self.kernel_log, SystemdLogger):
652
682
  self.db.record_prereq("Logs are provided via systemd", "✅")
653
- if isinstance(self.kernel_log, DmesgLogger):
683
+ elif isinstance(self.kernel_log, CySystemdLogger):
684
+ self.db.record_prereq("Logs are provided via cysystemd", "✅")
685
+ elif isinstance(self.kernel_log, DmesgLogger):
654
686
  self.db.record_prereq(
655
687
  "Logs are provided via dmesg, timestamps may not be accurate over multiple cycles",
656
688
  "🚦",
@@ -718,6 +750,9 @@ class PrerequisiteValidator(AmdTool):
718
750
  p = os.path.join("/", "sys", "kernel", "debug", "gpio")
719
751
  try:
720
752
  contents = read_file(p)
753
+ except FileNotFoundError:
754
+ self.db.record_prereq("GPIO debugfs not available", "👀")
755
+ contents = None
721
756
  except PermissionError:
722
757
  self.db.record_debug(f"Unable to capture {p}")
723
758
  contents = None
@@ -754,7 +789,7 @@ class PrerequisiteValidator(AmdTool):
754
789
  "utf-8"
755
790
  )
756
791
  except FileNotFoundError:
757
- self.db.record_prereq(f"ethtool is missing", "👀")
792
+ self.db.record_prereq("ethtool is missing", "👀")
758
793
  return True
759
794
  for line in output.split("\n"):
760
795
  if "Supports Wake-on" in line:
@@ -946,6 +981,44 @@ class PrerequisiteValidator(AmdTool):
946
981
  if debug_str:
947
982
  self.db.record_debug(debug_str)
948
983
 
984
+ def check_isp4(self):
985
+ """Check if camera supported by ISP is present and set up properly"""
986
+ devices = []
987
+ for dev in self.pyudev.list_devices(subsystem="acpi"):
988
+ # look for ACPI device for camera (OMNI5C10:00 is seen today)
989
+ if not dev.sys_name.startswith("OMNI5C10"):
990
+ continue
991
+ p = os.path.join(dev.sys_path, "path")
992
+ if not os.path.exists(p):
993
+ continue
994
+ devices.append(dev)
995
+ for dev in devices:
996
+ p = os.path.join(dev.sys_path, "physical_node", "driver")
997
+ if os.path.exists(p):
998
+ driver = os.path.basename(os.readlink(p))
999
+ else:
1000
+ driver = None
1001
+ if driver != "amd-isp4":
1002
+ self.db.record_prereq(
1003
+ f"ISP4 platform camera driver 'amd-isp4' not bound to {dev.sys_name}",
1004
+ "❌",
1005
+ )
1006
+ self.failures += [MissingIsp4PlatformDriver()]
1007
+ return False
1008
+ self.db.record_prereq(
1009
+ f"ISP4 platform camera driver 'amd-isp4' bound to {dev.sys_name}", "✅"
1010
+ )
1011
+ # check if `amd_capture` module is loaded
1012
+ p = os.path.join("/", "sys", "module", "amd_capture")
1013
+ if not os.path.exists(p):
1014
+ self.db.record_prereq(
1015
+ "Camera driver module 'amd_capture' not loaded", "❌"
1016
+ )
1017
+ self.failures += [MissingAmdCaptureModule()]
1018
+ return False
1019
+ self.db.record_prereq("Camera driver module 'amd_capture' loaded", "✅")
1020
+ return True
1021
+
949
1022
  def map_acpi_path(self):
950
1023
  """Map of ACPI devices to ACPI paths"""
951
1024
  devices = []
@@ -1007,6 +1080,21 @@ class PrerequisiteValidator(AmdTool):
1007
1080
  shutil.rmtree(tmpd)
1008
1081
  return True
1009
1082
 
1083
+ def capture_cstates(self):
1084
+ """Capture ACPI C state information for the first CPU (assumes the same for all CPUs)"""
1085
+ base = os.path.join("/", "sys", "bus", "cpu", "devices", "cpu0", "cpuidle")
1086
+ paths = {}
1087
+ for root, _dirs, files in os.walk(base, topdown=False):
1088
+ for fname in files:
1089
+ target = os.path.join(root, fname)
1090
+ with open(target, "rb") as f:
1091
+ paths[target] = f.read()
1092
+ debug_str = "ACPI C-state information\n"
1093
+ for path, data in paths.items():
1094
+ prefix = "│ " if path != list(paths.keys())[-1] else "└─"
1095
+ debug_str += f"{prefix}{path}: {data.decode('utf-8', 'ignore')}"
1096
+ self.db.record_debug(debug_str)
1097
+
1010
1098
  def capture_battery(self):
1011
1099
  """Capture battery information"""
1012
1100
  obj = Batteries()
@@ -1065,11 +1153,22 @@ class PrerequisiteValidator(AmdTool):
1065
1153
  # check for artificially limited CPUs
1066
1154
  p = os.path.join("/", "sys", "devices", "system", "cpu", "kernel_max")
1067
1155
  max_cpus = int(read_file(p)) + 1 # 0 indexed
1068
- # https://www.amd.com/content/dam/amd/en/documents/processor-tech-docs/programmer-references/24594.pdf
1069
- # Extended Topology Enumeration (NumLogCores)
1070
- # CPUID 0x80000026 subleaf 1
1156
+ # https://docs.amd.com/v/u/en-US/40332-PUB_4.08
1157
+ # E.4.24 Function 8000_0026—Extended CPU Topology
1071
1158
  try:
1072
- _, cpu_count, _, _ = read_cpuid(0, 0x80000026, 1)
1159
+ # Need to discover the socket level to look at all CCDs in the socket
1160
+ for level in range(0, 5):
1161
+ _, _, ecx, _ = read_cpuid(0, 0x80000026, level)
1162
+ level_type = (ecx >> 8) & 0xFF
1163
+ if level_type == 0:
1164
+ self.db.record_prereq(
1165
+ "Unable to discover CPU topology, didn't find socket level",
1166
+ "🚦",
1167
+ )
1168
+ return True
1169
+ if level_type == 4:
1170
+ break
1171
+ _, cpu_count, _, _ = read_cpuid(0, 0x80000026, level)
1073
1172
  if cpu_count > max_cpus:
1074
1173
  self.db.record_prereq(
1075
1174
  f"The kernel has been limited to {max_cpus} CPU cores, "
@@ -1140,7 +1239,6 @@ class PrerequisiteValidator(AmdTool):
1140
1239
  if self.cpu_family == 0x1A and self.cpu_model in affected_1a:
1141
1240
  found_iommu = False
1142
1241
  found_acpi = False
1143
- found_dmar = False
1144
1242
  for dev in self.pyudev.list_devices(subsystem="iommu"):
1145
1243
  found_iommu = True
1146
1244
  debug_str += f"Found IOMMU {dev.sys_path}\n"
@@ -1227,9 +1325,8 @@ class PrerequisiteValidator(AmdTool):
1227
1325
  # ignore kernel warnings
1228
1326
  taint &= ~BIT(9)
1229
1327
  if taint != 0:
1230
- self.db.record_prereq(f"Kernel is tainted: {taint}", "")
1328
+ self.db.record_prereq(f"Kernel is tainted: {taint}", "🚦")
1231
1329
  self.failures += [TaintedKernel()]
1232
- return False
1233
1330
  return True
1234
1331
 
1235
1332
  def run(self):
@@ -1244,6 +1341,8 @@ class PrerequisiteValidator(AmdTool):
1244
1341
  self.capture_logind,
1245
1342
  self.capture_pci_acpi,
1246
1343
  self.capture_edid,
1344
+ self.capture_nvidia,
1345
+ self.capture_cstates,
1247
1346
  ]
1248
1347
  checks = []
1249
1348
 
@@ -1273,6 +1372,7 @@ class PrerequisiteValidator(AmdTool):
1273
1372
  self.check_iommu,
1274
1373
  self.check_asus_rog_ally,
1275
1374
  self.check_dpia_pg_dmcub,
1375
+ self.check_isp4,
1276
1376
  ]
1277
1377
 
1278
1378
  checks += [
@@ -1296,7 +1396,7 @@ class PrerequisiteValidator(AmdTool):
1296
1396
  if not check():
1297
1397
  result = False
1298
1398
  if not result:
1299
- self.db.record_prereq(Headers.BrokenPrerequisites, "💯")
1399
+ self.db.record_prereq(Headers.BrokenPrerequisites, "🚫")
1300
1400
  self.db.sync()
1301
1401
  clear_temporary_message(len(msg))
1302
1402
  return result
@@ -1315,7 +1415,7 @@ class PrerequisiteValidator(AmdTool):
1315
1415
  logging.debug(line)
1316
1416
 
1317
1417
  if len(self.failures) == 0:
1318
- return True
1418
+ return
1319
1419
  print_color(Headers.ExplanationReport, "🗣️")
1320
1420
  for item in self.failures:
1321
1421
  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
 
@@ -293,18 +292,20 @@ def parse_args():
293
292
  action="store_true",
294
293
  help="Enable tool debug logging",
295
294
  )
296
- subparsers.add_parser("version", help="Show version information")
295
+ parser.add_argument(
296
+ "--version", action="store_true", help="Show version information"
297
+ )
297
298
  if len(sys.argv) == 1:
298
299
  parser.print_help(sys.stderr)
299
300
  sys.exit(1)
300
301
  return parser.parse_args()
301
302
 
302
303
 
303
- def main() -> None|int:
304
+ def main() -> None | int:
304
305
  """Main function"""
305
306
  args = parse_args()
306
307
  ret = False
307
- if args.command == "version":
308
+ if args.version:
308
309
  print(version())
309
310
  return
310
311
  elif args.command == "triage":
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
@@ -11,6 +10,7 @@ from datetime import date, timedelta, datetime
11
10
  from amd_debug.common import (
12
11
  convert_string_to_bool,
13
12
  colorize_choices,
13
+ fatal_error,
14
14
  is_root,
15
15
  relaunch_sudo,
16
16
  show_log_info,
@@ -61,21 +61,22 @@ def display_report_file(fname, fmt) -> None:
61
61
  return
62
62
  user = os.environ.get("SUDO_USER")
63
63
  if user:
64
- # ensure that xdg tools will know how to display the file
65
- # (user may need to call tool with sudo -E)
66
- if os.environ.get("XDG_SESSION_TYPE"):
67
- subprocess.call(["sudo", "-E", "-u", user, "xdg-open", fname])
68
- else:
69
- print(
70
- "To display report automatically in browser launch tool "
71
- f"with '-E' argument (Example: sudo -E {sys.argv[0]})"
72
- )
64
+ cmd = [
65
+ "systemd-run",
66
+ "--user",
67
+ f"--machine={user}@.host",
68
+ "xdg-open",
69
+ os.path.abspath(fname),
70
+ ]
71
+ ret = subprocess.call(cmd)
72
+ if ret:
73
+ fatal_error(f"Failed to open report: {ret}")
73
74
 
74
75
 
75
76
  def get_report_file(report_file, extension) -> str:
76
77
  """Prompt user for report file"""
77
78
  if extension == "stdout":
78
- return None
79
+ return ""
79
80
  if not report_file:
80
81
  return f"amd-s2idle-report-{date.today()}.{extension}"
81
82
  return report_file
@@ -88,7 +89,7 @@ def get_report_format() -> str:
88
89
  return "html"
89
90
 
90
91
 
91
- def prompt_report_arguments(since, until, fname, fmt, report_debug) -> str:
92
+ def prompt_report_arguments(since, until, fname, fmt, report_debug) -> list:
92
93
  """Prompt user for report configuration"""
93
94
  if not since:
94
95
  default = Defaults.since
@@ -213,8 +214,10 @@ def run_test_cycle(
213
214
 
214
215
  try:
215
216
  duration, wait, count = prompt_test_arguments(duration, wait, count, rand)
217
+ total_seconds = (duration + wait) * count
218
+ until_time = datetime.now() + timedelta(seconds=total_seconds)
216
219
  since, until, fname, fmt, report_debug = prompt_report_arguments(
217
- datetime.now().isoformat(), Defaults.until.isoformat(), fname, fmt, True
220
+ datetime.now().isoformat(), until_time.isoformat(), fname, fmt, True
218
221
  )
219
222
  except KeyboardInterrupt:
220
223
  sys.exit("\nTest cancelled")
@@ -237,6 +240,7 @@ def run_test_cycle(
237
240
  rand=rand,
238
241
  logind=logind,
239
242
  )
243
+ until = datetime.now()
240
244
  else:
241
245
  since = None
242
246
  until = None
@@ -385,7 +389,9 @@ def parse_args():
385
389
  help="Enable tool debug logging",
386
390
  )
387
391
 
388
- subparsers.add_parser("version", help="Show version information")
392
+ parser.add_argument(
393
+ "--version", action="store_true", help="Show version information"
394
+ )
389
395
 
390
396
  if len(sys.argv) == 1:
391
397
  parser.print_help(sys.stderr)
@@ -394,7 +400,7 @@ def parse_args():
394
400
  return parser.parse_args()
395
401
 
396
402
 
397
- def main() -> None|int:
403
+ def main() -> None | int:
398
404
  """Main function"""
399
405
  args = parse_args()
400
406
  ret = False
@@ -427,7 +433,7 @@ def main() -> None|int:
427
433
  args.logind,
428
434
  args.bios_debug,
429
435
  )
430
- elif args.action == "version":
436
+ elif args.version:
431
437
  print(version())
432
438
  return
433
439
  else:
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
@@ -488,7 +487,7 @@ class SleepReport(AmdTool):
488
487
  text = line.strip()
489
488
  if not text:
490
489
  continue
491
- for group in ["🗣️", "❌", "🚦", "🦟", "💯", "○"]:
490
+ for group in ["🗣️", "❌", "🚦", "🦟", "🚫", "○"]:
492
491
  if line.startswith(group):
493
492
  text = line.split(group)[-1]
494
493
  color = get_group_color(group)
amd_debug/ttm.py ADDED
@@ -0,0 +1,157 @@
1
+ # SPDX-License-Identifier: MIT
2
+ """TTM configuration tool"""
3
+
4
+ import asyncio
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