ThinkCentre M75q-1 のファン爆音問題 の履歴(No.1)

更新


公開メモ

ThinkCentre M75q-1 (Debian) のファン爆音問題を ryzenadj で解決する

問題の概要

Lenovo ThinkCentre M75q-1 に Debian をインストールして運用していたところ、 特に高負荷な処理をしていないにもかかわらずファンが突然フル回転し、 うるさい風切り音が続くという問題が発生した。

調査の結果、以下の構造的な問題が判明した:

  • CPU(AMD Ryzen 5 PRO 3400GE)はアイドル時でも 55〜65°C になりやすい設計特性を持つらしい
  • ThinkCentre M75q-1 の EC(組み込みコントローラ)のファン制御は ON/OFF の二値制御に近く、
     約 62°C でフル回転、約 53.5°C で停止するという粗い動作をする
  • Windows 環境では Lenovo Vantage がバックグラウンドで TDP を適切に制御しているが、
     Linux にはそのドライバが存在しない
  • Linux からは EC のファン制御曲線を変更する手段がない(WMI・thinkpad_acpi ともに使用不可)

結果として、少しの負荷でも 62°C を超えてファンがフル回転し、冷えたら止まる というサイクルを繰り返す状態になっていた。

  • 吸入口のフィルタに掃除機を当てたら気持ち改善したが、これから夏本番であることを考えるとつらい
  • それでも年々悪化している気がするのはサーマルグリスが劣化しているせいかもしれないため、 塗りなおすのを試すのもいいかも

以下はこんなサーバー機をだましだまし使うための設定。

## 解決策の方針

EC のファン制御は変更できないため、**CPU 自身に温度上限を設けてクロックを自律的に制御させる** 方向で解決した。具体的には `ryzenadj` を使って CPU のサーマルスロットリング閾値(tctl-temp)を 62°C 未満に設定することで、ECがファンを回す前に CPU が自ら発熱を抑えるようにした。

## 環境

  • 機種: Lenovo ThinkCentre M75q-1
  • CPU: AMD Ryzen 5 PRO 3400GE(コードネーム: Picasso)
  • OS: Debian 12 (bookworm)
  • カーネル: 6.1.0-49-amd64

## 調査手順

### センサーの確認

```bash sudo apt install lm-sensors sudo sensors-detect sensors ```

ThinkCentre M75q-1 では `k10temp` のみが使用可能で、 ファンの PWM 制御端子(`fan*`, `pwm*`)は hwmon に存在しない。 EC がファンを完全に管理しており、Linux 側から制御できない。

```bash

# hwmon の内容を確認 for d in /sys/class/hwmon/hwmon*; do echo "==$d=="; ls $d; done ```

### 温度のリアルタイム監視

```bash

# 時刻付きで温度を継続表示(60秒間隔) while true; do

 echo "$(date +%T) $(sensors | grep Tctl)"
 sleep 60

done ```

### CPU クロックと温度の同時確認

```bash while true; do

 echo "$(date +%T) $(sensors | grep Tctl) $(cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq | awk '{printf "%d MHz", $1/1000}')"
 sleep 5

done ```

### ファンの ON/OFF 閾値の特定

上記の監視コマンドを使い、ファンが回り始める温度と止まる温度を記録した。 本環境では:

  • **ON 閾値**: 約 62°C
  • **OFF 閾値**: 約 53.5°C(ヒステリシス約 8.5°C)

### 負荷プロセスの調査

```bash

# プロセスごとの CPU 使用率合計 ps aux | awk 'NR>1 {sum += $3} END {print "Total CPU%:", sum}'

# pidstat で長期記録 sudo apt install sysstat pidstat -u 60 | tee /tmp/pidstat_log.txt

# 記録後に集計 awk ' /^[0-9]/ && $NF != "Command" {

   cpu[$NF] += $7
   count[$NF]++

} END {

   for (p in cpu)
       printf "%.2f\t%d samples\t%s\n", cpu[p]/count[p], count[p], p

} ' /tmp/pidstat_log.txt | sort -rn | head -20 ```

本環境では特定の重いプロセスは見当たらず、複数の軽いプロセスが常時動いている状態だった。

## ryzenadj のインストールと設定

### 必要なパッケージのインストール

```bash sudo apt install cmake libpci-dev build-essential dkms linux-headers-$(uname -r) ```

### ryzen_smu カーネルモジュールのビルドとインストール

`ryzenadj` は `ryzen_smu` カーネルモジュールと連携して動作する。 オリジナルの `leogx9r/ryzen_smu` は古くメンテされていないため、 アクティブにメンテされている `amkillam/ryzen_smu`(バージョン 0.1.7)を使用する。

```bash git clone https://github.com/amkillam/ryzen_smu.git cd ryzen_smu

# バージョン確認(0.1.7 であることを確認) grep "^VERSION" Makefile

# DKMS でインストール(カーネル更新時に自動再ビルドされる) sudo make dkms-install

# モジュールのロードと確認 sudo modprobe ryzen_smu sudo dmesg | grep ryzen_smu | tail -5 sudo cat /sys/kernel/ryzen_smu_drv/drv_version ```

`/sys/kernel/ryzen_smu_drv/` 以下にファイルが展開されていれば正常。

### ryzenadj のビルド

```bash cd
git clone https://github.com/FlyGoat/RyzenAdj.git cd RyzenAdj mkdir build && cd build cmake .. make sudo cp ryzenadj /usr/local/bin/ ```

### 現在の設定確認

```bash sudo ryzenadj --info ```

`THM LIMIT CORE`(tctl-temp)がデフォルト 95°C になっていることを確認できる。

### tctl-temp の設定

ファン ON 閾値(62°C)より少し低い値に設定する。 本環境では 60°C に設定したところ、CPU が 58°C 台で安定しファンが回らなくなった。 スロットリングは閾値の手前から徐々に効き始めるため、設定温度より数度低い温度で安定する。

```bash sudo ryzenadj --tctl-temp=60

# 確認 sudo ryzenadj --info 2>&1 | grep "THM LIMIT" ```

## 永続化(起動時の自動適用)

### systemd サービスの作成

```bash sudo nano /etc/systemd/system/ryzenadj.service ```

```ini [Unit] Description=RyzenAdj power settings After=multi-user.target

[Service] Type=oneshot ExecStart=/usr/local/bin/ryzenadj --tctl-temp=60 RemainAfterExit=yes

[Install] WantedBy=multi-user.target ```

`ryzenadj` は SMU に値を書き込んで即終了するコマンドであり、常駐しない。 `Type=oneshot` は「起動時に一度だけ実行して終了するサービス」を表す systemd の設定で、このような用途に適している。 `RemainAfterExit=yes` を指定することで、コマンド終了後もサービスが「active」状態として扱われ、`systemctl status` で確認しやすくなる。

```bash sudo systemctl daemon-reload sudo systemctl enable ryzenadj.service sudo systemctl start ryzenadj.service sudo systemctl status ryzenadj.service ```

### 再起動後の確認

```bash sudo ryzenadj --info 2>&1 | grep "THM LIMIT"

# THM LIMIT CORE | 60.000 と表示されれば成功 ```

## 結果

設定前後の比較:

設定前設定後
---------
アイドル温度60〜62°C58°C 台で安定
ファン挙動62°C でフル回転→冷却→繰り返しほぼ停止
クロック最大 1500MHz 制限1300〜1400MHz 付近で自律制御

## 注意事項

  • `tctl-temp` を低く設定するほど CPU クロックが抑制され処理性能が低下する。
     用途に応じて値を調整すること。
  • この設定はサーマルスロットリングを意図的に早めるものであり、
     CPU 保護の観点からは問題ないが、高負荷処理(動画エンコード等)では
     パフォーマンス低下が顕著になる場合がある。
  • `ryzen_smu` はカーネルの taint(汚染)フラグを立てる out-of-tree モジュールである。
  • DKMS によりカーネル更新時に自動再ビルドされるが、
     大幅なカーネルバージョン変更時には動作確認を推奨する。

Counter: 69 (from 2010/06/03), today: 1, yesterday: 3