From d92c9aef23fc789d50bfd03ae09a3abbf23a8429 Mon Sep 17 00:00:00 2001 From: Adeeb Shihadeh Date: Sat, 22 Jul 2023 17:15:58 -0700 Subject: [PATCH] tici: speedup power save setting (#29100) * speedup * update type --------- Co-authored-by: Comma Device --- Jenkinsfile | 3 +- common/gpio.py | 22 +++++++---- system/hardware/tici/hardware.py | 42 +++++++++++++-------- system/hardware/tici/tests/test_hardware.py | 31 +++++++++++++++ system/sensord/tests/test_sensord.py | 4 +- 5 files changed, 76 insertions(+), 26 deletions(-) create mode 100755 system/hardware/tici/tests/test_hardware.py diff --git a/Jenkinsfile b/Jenkinsfile index 4203c7f196..438149ef60 100644 --- a/Jenkinsfile +++ b/Jenkinsfile @@ -166,7 +166,8 @@ pipeline { ["test sensord", "cd system/sensord/tests && python -m unittest test_sensord.py"], ["test camerad", "python system/camerad/test/test_camerad.py"], ["test exposure", "python system/camerad/test/test_exposure.py"], - ["test amp", "python system/hardware/tici/tests/test_amplifier.py"], + ["test amp", "pytest system/hardware/tici/tests/test_amplifier.py"], + ["test hw", "pytest system/hardware/tici/tests/test_hardware.py"], ["test rawgpsd", "python system/sensord/rawgps/test_rawgps.py"], ]) } diff --git a/common/gpio.py b/common/gpio.py index 711fcff85d..f400ccc53a 100644 --- a/common/gpio.py +++ b/common/gpio.py @@ -1,4 +1,4 @@ -import glob +from functools import cache from typing import Optional, List def gpio_init(pin: int, output: bool) -> None: @@ -25,12 +25,20 @@ def gpio_read(pin: int) -> Optional[bool]: return val -def get_irq_for_action(action: str) -> List[int]: - ret = [] - for fn in glob.glob('/sys/kernel/irq/*/actions'): - with open(fn) as f: +@cache +def get_irq_action(irq: int) -> List[str]: + try: + with open(f"/sys/kernel/irq/{irq}/actions") as f: actions = f.read().strip().split(',') - if action in actions: - irq = int(fn.split('/')[-2]) + return actions + except FileNotFoundError: + return [] + +def get_irqs_for_action(action: str) -> List[str]: + ret = [] + with open("/proc/interrupts") as f: + for l in f.readlines(): + irq = l.split(':')[0].strip() + if irq.isdigit() and action in get_irq_action(irq): ret.append(irq) return ret diff --git a/system/hardware/tici/hardware.py b/system/hardware/tici/hardware.py index 780d870dcd..018bc30004 100644 --- a/system/hardware/tici/hardware.py +++ b/system/hardware/tici/hardware.py @@ -8,7 +8,7 @@ from functools import cached_property, lru_cache from pathlib import Path from cereal import log -from common.gpio import gpio_set, gpio_init, get_irq_for_action +from common.gpio import gpio_set, gpio_init, get_irqs_for_action from system.hardware.base import HardwareBase, ThermalConfig from system.hardware.tici import iwlist from system.hardware.tici.pins import GPIO @@ -61,17 +61,27 @@ MM_MODEM_ACCESS_TECHNOLOGY_LTE = 1 << 14 def sudo_write(val, path): - os.system(f"sudo su -c 'echo {val} > {path}'") + try: + with open(path, 'w') as f: + f.write(str(val)) + except PermissionError: + os.system(f"sudo chmod a+w {path}") + try: + with open(path, 'w') as f: + f.write(str(val)) + except PermissionError: + # fallback for debugfs files + os.system(f"sudo su -c 'echo {val} > {path}'") def affine_irq(val, action): - irq = get_irq_for_action(action) - if len(irq) == 0: + irqs = get_irqs_for_action(action) + if len(irqs) == 0: print(f"No IRQs found for '{action}'") return - for i in irq: - sudo_write(str(val), f"/proc/irq/{i}/smp_affinity_list") + for i in irqs: + sudo_write(str(val), f"/proc/irq/{i}/smp_affinity_list") class Tici(HardwareBase): @cached_property @@ -438,17 +448,17 @@ class Tici(HardwareBase): # *** IRQ config *** - # GPU - affine_irq(5, "kgsl-3d0") - # boardd core affine_irq(4, "spi_geni") # SPI affine_irq(4, "xhci-hcd:usb3") # aux panda USB (or potentially anything else on USB) if "tici" in self.get_device_type(): - affine_irq(4, "xhci-hcd:usb1") # internal panda USB + affine_irq(4, "xhci-hcd:usb1") # internal panda USB (also modem) + + # GPU + affine_irq(5, "kgsl-3d0") # camerad core - camera_irqs = ("cci", "cpas_camnoc", "cpas-cdm", "csid", "ife", "csid", "csid-lite", "ife-lite") + camera_irqs = ("cci", "cpas_camnoc", "cpas-cdm", "csid", "ife", "csid-lite", "ife-lite") for n in camera_irqs: affine_irq(5, n) @@ -472,14 +482,14 @@ class Tici(HardwareBase): # *** IRQ config *** - # move these off the default core - affine_irq(1, "msm_drm") - affine_irq(1, "msm_vidc") - affine_irq(1, "i2c_geni") - # mask off big cluster from default affinity sudo_write("f", "/proc/irq/default_smp_affinity") + # move these off the default core + affine_irq(1, "msm_drm") # display + affine_irq(1, "msm_vidc") # encoders + affine_irq(1, "i2c_geni") # sensors + # *** GPU config *** # https://github.com/commaai/agnos-kernel-sdm845/blob/master/arch/arm64/boot/dts/qcom/sdm845-gpu.dtsi#L216 sudo_write("1", "/sys/class/kgsl/kgsl-3d0/min_pwrlevel") diff --git a/system/hardware/tici/tests/test_hardware.py b/system/hardware/tici/tests/test_hardware.py new file mode 100755 index 0000000000..d910b13ec4 --- /dev/null +++ b/system/hardware/tici/tests/test_hardware.py @@ -0,0 +1,31 @@ +#!/usr/bin/env python3 +import time +import unittest +import numpy as np + +from system.hardware import TICI +from system.hardware.tici.hardware import Tici + +HARDWARE = Tici() + +class TestHardware(unittest.TestCase): + + @classmethod + def setUpClass(cls): + if not TICI: + raise unittest.SkipTest + + def test_power_save_time(self): + ts = [] + for _ in range(5): + for on in (True, False): + st = time.monotonic() + HARDWARE.set_power_save(on) + ts.append(time.monotonic() - st) + + assert 0.1 < np.mean(ts) < 0.2 + assert max(ts) < 0.3 + + +if __name__ == "__main__": + unittest.main() diff --git a/system/sensord/tests/test_sensord.py b/system/sensord/tests/test_sensord.py index b515ce16ab..eea527ed63 100755 --- a/system/sensord/tests/test_sensord.py +++ b/system/sensord/tests/test_sensord.py @@ -7,7 +7,7 @@ from collections import namedtuple, defaultdict import cereal.messaging as messaging from cereal import log -from common.gpio import get_irq_for_action +from common.gpio import get_irqs_for_action from system.hardware import TICI from selfdrive.manager.process_config import managed_processes @@ -113,7 +113,7 @@ class TestSensord(unittest.TestCase): cls.events = read_sensor_events(cls.sample_secs) # determine sensord's irq - cls.sensord_irq = get_irq_for_action("sensord")[0] + cls.sensord_irq = get_irqs_for_action("sensord")[0] finally: # teardown won't run if this doesn't succeed managed_processes["sensord"].stop()