mcgillij / amdfan

Updated AMD Fan control utility forked from amdgpu-fan and updated.
https://mcgillij.dev/pages/amdfan.html
GNU General Public License v2.0
33 stars 7 forks source link

fan speed = 0, KeyError: 'pwm1_min' #9

Open ShashaankHari opened 3 years ago

ShashaankHari commented 3 years ago

Hi, I am using garuda Linux (arch based, zen kernel), on Lenovo Ideapad S340 (AMD Ryzen 5 3500U, Radeon vega 8 Picasso) my pc heats up so much on Linux even in conservative mode where charging is paused at 60%, i tried installing this aur but this is the status, below is the error..


╭─asa@asa in ~ took 5m31s
 ╰─λ sudo amdfan --monitor 
[sudo] password for asa:           
AMD Fan Control - ctrl-c to quit
                 amdgpu                 
┏━━━━━━━┳━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━┓
┃ Card  ┃ fan_speed (RPM) ┃ gpu_temp ℃ ┃
┡━━━━━━━╇━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━┩
│ card0 │ 0               │ 49.0       │
└───────┴─────────────────┴────────────┘

Aborted!

 ╭─asa@asa in ~ took 26s
[🔴] × sudo amdfan --daemon
[23:15:42] INFO     Starting amdfan                                                           amdfan.py:208
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /usr/bin/amdfan:33 in <module>                                                                   │
│                                                                                                  │
│   30                                                                                             │
│   31 if __name__ == '__main__':                                                                  │
│   32 │   sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])                       │
│ ❱ 33 │   sys.exit(load_entry_point('amdfan==0.1.11', 'console_scripts', 'amdfan')())             │
│   34                                                                                             │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/click/core.py:1137 in __call__                                  │
│                                                                                                  │
│   1134 │                                                                                         │
│   1135 │   def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any:                           │
│   1136 │   │   """Alias for :meth:`main`."""                                                     │
│ ❱ 1137 │   │   return self.main(*args, **kwargs)                                                 │
│   1138                                                                                           │
│   1139                                                                                           │
│   1140 class Command(BaseCommand):                                                               │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/click/core.py:1062 in main                                      │
│                                                                                                  │
│   1059 │   │   try:                                                                              │
│   1060 │   │   │   try:                                                                          │
│   1061 │   │   │   │   with self.make_context(prog_name, args, **extra) as ctx:                  │
│ ❱ 1062 │   │   │   │   │   rv = self.invoke(ctx)                                                 │
│   1063 │   │   │   │   │   if not standalone_mode:                                               │
│   1064 │   │   │   │   │   │   return rv                                                         │
│   1065 │   │   │   │   │   # it's not safe to `ctx.exit(rv)` here!                               │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/click/core.py:1404 in invoke                                    │
│                                                                                                  │
│   1401 │   │   │   echo(style(message, fg="red"), err=True)                                      │
│   1402 │   │                                                                                     │
│   1403 │   │   if self.callback is not None:                                                     │
│ ❱ 1404 │   │   │   return ctx.invoke(self.callback, **ctx.params)                                │
│   1405 │                                                                                         │
│   1406 │   def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]:  │
│   1407 │   │   """Return a list of completions for the incomplete value. Looks                   │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/click/core.py:763 in invoke                                     │
│                                                                                                  │
│    760 │   │                                                                                     │
│    761 │   │   with augment_usage_errors(__self):                                                │
│    762 │   │   │   with ctx:                                                                     │
│ ❱  763 │   │   │   │   return __callback(*args, **kwargs)                                        │
│    764 │                                                                                         │
│    765 │   def forward(                                                                          │
│    766 │   │   __self, __cmd: "Command", *args: t.Any, **kwargs: t.Any  # noqa: B902             │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/amdfan/amdfan.py:333 in cli                                     │
│                                                                                                  │
│   330 )                                                                                          │
│   331 def cli(daemon, monitor, manual, configuration, service):                                  │
│   332 │   if daemon:                                                                             │
│ ❱ 333 │   │   run_as_daemon()                                                                    │
│   334 │   elif monitor:                                                                          │
│   335 │   │   monitor_cards()                                                                    │
│   336 │   elif manual:                                                                           │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/amdfan/amdfan.py:361 in run_as_daemon                           │
│                                                                                                  │
│   358 │   │                                                                                      │
│   359 │   │   config = load_config(CONFIG_LOCATIONS[-1])                                         │
│   360 │                                                                                          │
│ ❱ 361 │   FanController(config).main()                                                           │
│   362                                                                                            │
│   363                                                                                            │
│   364 def show_table(cards):                                                                     │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/amdfan/amdfan.py:228 in main                                    │
│                                                                                                  │
│   225 │   │   │   │   │   self._last_temp,                                                       │
│   226 │   │   │   │   │   speed,                                                                 │
│   227 │   │   │   │   │   card.fan_speed,                                                        │
│ ❱ 228 │   │   │   │   │   card.fan_min,                                                          │
│   229 │   │   │   │   │   card.fan_max,                                                          │
│   230 │   │   │   │   )                                                                          │
│   231 │   │   │   │   if self._threshold and self._last_temp:                                    │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/amdfan/amdfan.py:142 in fan_min                                 │
│                                                                                                  │
│   139 │                                                                                          │
│   140 │   @property                                                                              │
│   141 │   def fan_min(self):                                                                     │
│ ❱ 142 │   │   return int(self.read_endpoint("pwm1_min"))                                         │
│   143 │                                                                                          │
│   144 │   def set_system_controlled_fan(self, state):                                            │
│   145                                                                                            │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/amdfan/amdfan.py:114 in read_endpoint                           │
│                                                                                                  │
│   111 │   │   return _endpoints                                                                  │
│   112 │                                                                                          │
│   113 │   def read_endpoint(self, endpoint):                                                     │
│ ❱ 114 │   │   with open(self._endpoints[endpoint], "r") as endpoint_file:                        │
│   115 │   │   │   return endpoint_file.read()                                                    │
│   116 │                                                                                          │
│   117 │   def write_endpoint(self, endpoint, data):                                              │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
KeyError: 'pwm1_min'

ON MANUAL MODE

╭─asa@asa in /home/asa took 8ms
╰─λ sudo amdfan --manual
Which card? [card0]: 
Please select one of the available options
Which card? [card0]: card0    
Fan speed, [1..100]% or 'auto' (auto): auto
[23:32:10] INFO     Setting fan speed to system controlled                                    amdfan.py:402
╭─────────────────────────────── Traceback (most recent call last) ────────────────────────────────╮
│ /usr/bin/amdfan:33 in <module>                                                                   │
│                                                                                                  │
│   30                                                                                             │
│   31 if __name__ == '__main__':                                                                  │
│   32 │   sys.argv[0] = re.sub(r'(-script\.pyw?|\.exe)?$', '', sys.argv[0])                       │
│ ❱ 33 │   sys.exit(load_entry_point('amdfan==0.1.11', 'console_scripts', 'amdfan')())             │
│   34                                                                                             │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/click/core.py:1137 in __call__                                  │
│                                                                                                  │
│   1134 │                                                                                         │
│   1135 │   def __call__(self, *args: t.Any, **kwargs: t.Any) -> t.Any:                           │
│   1136 │   │   """Alias for :meth:`main`."""                                                     │
│ ❱ 1137 │   │   return self.main(*args, **kwargs)                                                 │
│   1138                                                                                           │
│   1139                                                                                           │
│   1140 class Command(BaseCommand):                                                               │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/click/core.py:1062 in main                                      │
│                                                                                                  │
│   1059 │   │   try:                                                                              │
│   1060 │   │   │   try:                                                                          │
│   1061 │   │   │   │   with self.make_context(prog_name, args, **extra) as ctx:                  │
│ ❱ 1062 │   │   │   │   │   rv = self.invoke(ctx)                                                 │
│   1063 │   │   │   │   │   if not standalone_mode:                                               │
│   1064 │   │   │   │   │   │   return rv                                                         │
│   1065 │   │   │   │   │   # it's not safe to `ctx.exit(rv)` here!                               │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/click/core.py:1404 in invoke                                    │
│                                                                                                  │
│   1401 │   │   │   echo(style(message, fg="red"), err=True)                                      │
│   1402 │   │                                                                                     │
│   1403 │   │   if self.callback is not None:                                                     │
│ ❱ 1404 │   │   │   return ctx.invoke(self.callback, **ctx.params)                                │
│   1405 │                                                                                         │
│   1406 │   def shell_complete(self, ctx: Context, incomplete: str) -> t.List["CompletionItem"]:  │
│   1407 │   │   """Return a list of completions for the incomplete value. Looks                   │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/click/core.py:763 in invoke                                     │
│                                                                                                  │
│    760 │   │                                                                                     │
│    761 │   │   with augment_usage_errors(__self):                                                │
│    762 │   │   │   with ctx:                                                                     │
│ ❱  763 │   │   │   │   return __callback(*args, **kwargs)                                        │
│    764 │                                                                                         │
│    765 │   def forward(                                                                          │
│    766 │   │   __self, __cmd: "Command", *args: t.Any, **kwargs: t.Any  # noqa: B902             │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/amdfan/amdfan.py:337 in cli                                     │
│                                                                                                  │
│   334 │   elif monitor:                                                                          │
│   335 │   │   monitor_cards()                                                                    │
│   336 │   elif manual:                                                                           │
│ ❱ 337 │   │   set_fan_speed()                                                                    │
│   338 │   elif configuration:                                                                    │
│   339 │   │   print(DEFAULT_FAN_CONFIG)                                                          │
│   340 │   elif service:                                                                          │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/amdfan/amdfan.py:403 in set_fan_speed                           │
│                                                                                                  │
│   400 │   selected_card = scanner.cards.get(card_to_set)                                         │
│   401 │   if not input_fan_speed.isdigit() and input_fan_speed == "auto":                        │
│   402 │   │   LOGGER.info("Setting fan speed to system controlled")                              │
│ ❱ 403 │   │   selected_card.set_system_controlled_fan(True)                                      │
│   404 │   else:                                                                                  │
│   405 │   │   LOGGER.info("Setting fan speed to %d", int(input_fan_speed))                       │
│   406 │   │   c.print(selected_card.set_fan_speed(int(input_fan_speed)))                         │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/amdfan/amdfan.py:149 in set_system_controlled_fan               │
│                                                                                                  │
│   146 │   │   system_controlled_fan = 2                                                          │
│   147 │   │   manual_control = 1                                                                 │
│   148 │   │                                                                                      │
│ ❱ 149 │   │   self.write_endpoint(                                                               │
│   150 │   │   │   "pwm1_enable", system_controlled_fan if state else manual_control              │
│   151 │   │   )                                                                                  │
│   152                                                                                            │
│                                                                                                  │
│ /usr/lib/python3.9/site-packages/amdfan/amdfan.py:119 in write_endpoint                          │
│                                                                                                  │
│   116 │                                                                                          │
│   117 │   def write_endpoint(self, endpoint, data):                                              │
│   118 │   │   try:                                                                               │
│ ❱ 119 │   │   │   with open(self._endpoints[endpoint], "w") as endpoint_file:                    │
│   120 │   │   │   │   return endpoint_file.write(str(data))                                      │
│   121 │   │   except PermissionError:                                                            │
│   122 │   │   │   LOGGER.error("Failed writing to devfs file, are you running as root?")         │
╰──────────────────────────────────────────────────────────────────────────────────────────────────╯
KeyError: 'pwm1_enable'
mcgillij commented 3 years ago

Hey there, by the looks of it it can't find the right files to write the pwm state to. Are you using the amdgpu driver (it would create these files when the driver is loaded in /sys/class/drm/card0/device/hwmon/hwmon*)?

I've only tested this on standalone cards (Vega, 6800xt, 6900xt), since I don't have any laptops with AMD integrated gpus.

ShashaankHari commented 3 years ago

Hey there, by the looks of it it can't find the right files to write the pwm state to. Are you using the amdgpu driver (it would create these files when the driver is loaded in /sys/class/drm/card0/device/hwmon/hwmon*)?

I've only tested this on standalone cards (Vega, 6800xt, 6900xt), since I don't have any laptops with AMD integrated gpus.

the driver is loaded because i tested it using glmark2 and these are the files present in that directory

ls -a /sys/class/drm/card0/device/hwmon/hwmon3
drwxr-xr-x    - root 11 Aug 09:18  .
drwxr-xr-x    - root 11 Aug 08:59  ..
lrwxrwxrwx    0 root 11 Aug 09:19  device -> ../../../0000:04:00.0
drwxr-xr-x    - root 11 Aug 09:19  power
lrwxrwxrwx    0 root 11 Aug 08:59  subsystem -> ../../../../../../class/hwmon
.r--r--r-- 4.1k root 11 Aug 09:19  freq1_input
.r--r--r-- 4.1k root 11 Aug 09:19  freq1_label
.r--r--r-- 4.1k root 11 Aug 09:19  in0_input
.r--r--r-- 4.1k root 11 Aug 09:19  in0_label
.r--r--r-- 4.1k root 11 Aug 09:19  in1_input
.r--r--r-- 4.1k root 11 Aug 09:19  in1_label
.r--r--r-- 4.1k root 11 Aug 09:19  name
.r--r--r-- 4.1k root 11 Aug 09:19  temp1_input
.r--r--r-- 4.1k root 11 Aug 09:19  temp1_label
.rw-r--r-- 4.1k root 11 Aug 09:19  uevent
mcgillij commented 3 years ago

It doesn't look like you have any of the pwm files there which would usually allow controlling the fans.

Here's what it looks like on my system: image

Something like lsmod |grep amdgpu should let you see whats loaded in the kernel. I'm wondering if the integrated CPU/GPU's maybe use the CPU's PWM settings to control the fans.

You may just have to up your fan speeds on the CPU to get your cooling.

ShashaankHari commented 3 years ago

It doesn't look like you have any of the pwm files there which would usually allow controlling the fans.

Here's what it looks like on my system: image

Something like lsmod |grep amdgpu should let you see whats loaded in the kernel. I'm wondering if the integrated CPU/GPU's maybe use the CPU's PWM settings to control the fans.

You may just have to up your fan speeds on the CPU to get your cooling.

how do i control cpu fans?

mcgillij commented 3 years ago

You probably need to look into lm-sensors package / pwmconfig: https://wiki.archlinux.org/title/fan_speed_control

mcgillij commented 3 years ago

I'll add a note to the README that this is only intended to work on non-integrated gpus.

udev commented 2 years ago

I'm seeing the same error with a card that is not integrated.

steam@steam:~$ sudo systemctl status amdgpu-fan.service
● amdgpu-fan.service - Service for controling amdgpu fan.
     Loaded: loaded (/etc/systemd/system/amdgpu-fan.service; enabled; vendor preset: enabled)
     Active: active (running) since Mon 2022-01-24 16:47:15 CST; 215ms ago
   Main PID: 5545 (amdgpu-fan)
      Tasks: 4 (limit: 17832)
     Memory: 14.7M
        CPU: 422ms
     CGroup: /system.slice/amdgpu-fan.service
             └─5545 /usr/bin/python3 /usr/local/bin/amdgpu-fan

Jan 24 16:47:15 steam amdgpu-fan[5545]:     sys.exit(main())
Jan 24 16:47:15 steam amdgpu-fan[5545]:   File "/usr/local/lib/python3.9/dist-packages/amdgpu_fan/controller.py", line 78, in main
Jan 24 16:47:15 steam amdgpu-fan[5545]:     FanController(config).main()
Jan 24 16:47:15 steam amdgpu-fan[5545]:   File "/usr/local/lib/python3.9/dist-packages/amdgpu_fan/controller.py", line 35, in main
Jan 24 16:47:15 steam amdgpu-fan[5545]:     logger.debug(f'{name}: Temp {temp}, Setting fan speed to: {speed}, fan speed{card.fan_speed}, min:{card.fan_min}, max:{card.fan_max}')
Jan 24 16:47:15 steam amdgpu-fan[5545]:   File "/usr/local/lib/python3.9/dist-packages/amdgpu_fan/lib/amdgpu.py", line 64, in fan_min
Jan 24 16:47:15 steam amdgpu-fan[5545]:     return int(self.read_endpoint('pwm1_min'))
Jan 24 16:47:15 steam amdgpu-fan[5545]:   File "/usr/local/lib/python3.9/dist-packages/amdgpu_fan/lib/amdgpu.py", line 36, in read_endpoint
Jan 24 16:47:15 steam amdgpu-fan[5545]:     with open(self._endpoints[endpoint], 'r') as e:
Jan 24 16:47:15 steam amdgpu-fan[5545]: KeyError: 'pwm1_min'
steam@steam:~$ sudo systemctl status amdgpu-fan.service
● amdgpu-fan.service - Service for controling amdgpu fan.
     Loaded: loaded (/etc/systemd/system/amdgpu-fan.service; enabled; vendor preset: enabled)
     Active: activating (auto-restart) (Result: exit-code) since Mon 2022-01-24 16:47:15 CST; 374ms ago
    Process: 5545 ExecStart=/usr/local/bin/amdgpu-fan (code=exited, status=1/FAILURE)
   Main PID: 5545 (code=exited, status=1/FAILURE)
        CPU: 440ms

Additional info:

steam@steam:/sys/class/drm/card0/device/hwmon/hwmon0$ ls -lA
total 0
lrwxrwxrwx 1 root root    0 Jan 24 16:37 device -> ../../../0000:00:01.0
-r--r--r-- 1 root root 4096 Jan 24 16:52 freq1_input
-r--r--r-- 1 root root 4096 Jan 24 16:52 freq1_label
-r--r--r-- 1 root root 4096 Jan 24 16:37 in1_input
-r--r--r-- 1 root root 4096 Jan 24 16:37 in1_label
-r--r--r-- 1 root root 4096 Jan 24 16:37 name
drwxr-xr-x 2 root root    0 Jan 24 16:52 power
lrwxrwxrwx 1 root root    0 Jan 24 16:37 subsystem -> ../../../../../class/hwmon
-r--r--r-- 1 root root 4096 Jan 24 16:37 temp1_crit
-r--r--r-- 1 root root 4096 Jan 24 16:37 temp1_crit_hyst
-r--r--r-- 1 root root 4096 Jan 24 16:37 temp1_input
-r--r--r-- 1 root root 4096 Jan 24 16:37 temp1_label
-rw-r--r-- 1 root root 4096 Jan 24 16:37 uevent
steam@steam:/sys/class/drm/card0/device/hwmon/hwmon0$ cd power/
steam@steam:/sys/class/drm/card0/device/hwmon/hwmon0/power$ ls -lA
total 0
-rw-r--r-- 1 root root 4096 Jan 24 16:52 async
-rw-r--r-- 1 root root 4096 Jan 24 16:52 autosuspend_delay_ms
-rw-r--r-- 1 root root 4096 Jan 24 16:52 control
-r--r--r-- 1 root root 4096 Jan 24 16:52 runtime_active_kids
-r--r--r-- 1 root root 4096 Jan 24 16:52 runtime_active_time
-r--r--r-- 1 root root 4096 Jan 24 16:52 runtime_enabled
-r--r--r-- 1 root root 4096 Jan 24 16:52 runtime_status
-r--r--r-- 1 root root 4096 Jan 24 16:52 runtime_suspended_time
-r--r--r-- 1 root root 4096 Jan 24 16:52 runtime_usage
steam@steam:/sys/class/drm/card0/device/hwmon/hwmon0/power$ lsmod |grep amdgpu
amdgpu               7774208  15
gpu_sched              45056  1 amdgpu
i2c_algo_bit           16384  1 amdgpu
drm_ttm_helper         16384  1 amdgpu
ttm                    81920  2 amdgpu,drm_ttm_helper
drm_kms_helper        307200  1 amdgpu
drm                   634880  10 gpu_sched,drm_kms_helper,amdgpu,drm_ttm_helper,ttm
steam@steam:/sys/class/drm/card0/device/hwmon/hwmon0/power$ lspci -knn|grep Hawaii
01:00.0 VGA compatible controller [0300]: Advanced Micro Devices, Inc. [AMD/ATI] Hawaii XT / Grenada XT [Radeon R9 290X/390X] [1002:67b0]
    Subsystem: Advanced Micro Devices, Inc. [AMD/ATI] Hawaii XT / Grenada XT [Radeon R9 290X/390X] [1002:0b00]
01:00.1 Audio device [0403]: Advanced Micro Devices, Inc. [AMD/ATI] Hawaii HDMI Audio [Radeon R9 290/290X / 390/390X] [1002:aac8]
    Subsystem: Advanced Micro Devices, Inc. [AMD/ATI] Hawaii HDMI Audio [Radeon R9 290/290X / 390/390X] [1002:aac8]
steam@steam:/sys/class/drm/card0/device/hwmon/hwmon0/power$ 
mcgillij commented 2 years ago

KeyError: 'pwm1_min' This is the key part of the error, you don't have the right files present to be able to control the fans.

All this script does is send number values to the pwm controls, which you don't seem to have exposed in your /sysfs

udev commented 2 years ago

Ended up installing fancontrol. Thanks regardless.