Linux Hardware Monitor development
 help / color / mirror / Atom feed
From: Aureo Serrano de Souza <aureo.serrano@arctic.de>
To: linux-hwmon@vger.kernel.org
Cc: linux@roeck-us.net, linux@weissschuh.net, arctic.it.hk@arctic.de,
	corbet@lwn.net, skhan@linuxfoundation.org, rdunlap@infradead.org,
	linux-doc@vger.kernel.org, linux-kernel@vger.kernel.org,
	Aureo Serrano de Souza <aureo.serrano@arctic.de>
Subject: [PATCH 1/3] hwmon: arctic_fan_controller: default PWM cache to MCU 40%
Date: Thu, 10 Sep 2026 13:03:59 +0800	[thread overview]
Message-ID: <20260910050401.279868-2-aureo.serrano@arctic.de> (raw)
In-Reply-To: <20260910050401.279868-1-aureo.serrano@arctic.de>

The device has no GET_REPORT and every OUT report carries all 10
channels, so the cache has to start at some value. Starting at 0
means the first sysfs write to a single channel also sends 0% on
the other nine.

The MCU factory default is 40%. Initialize pwm_duty[] to 102 (40%
on the 0-255 sysfs scale) at probe and on reset-resume. Any initial
cache can be stale if the module is reloaded without a device
reset. 40% matches the hardware after power-on or power-loss
resume, and a first single-channel write leaves the fans running
at a safe speed.

PWM is still not taken from periodic IN reports: the device is
manual-only and the host cache stays authoritative after the first
successful write.

Signed-off-by: Aureo Serrano de Souza <aureo.serrano@arctic.de>
---
 Documentation/hwmon/arctic_fan_controller.rst | 26 +++++++++----------
 drivers/hwmon/arctic_fan_controller.c         | 18 ++++++++-----
 2 files changed, 23 insertions(+), 21 deletions(-)

diff --git a/Documentation/hwmon/arctic_fan_controller.rst b/Documentation/hwmon/arctic_fan_controller.rst
index b5be88ae464..200e51932a1 100644
--- a/Documentation/hwmon/arctic_fan_controller.rst
+++ b/Documentation/hwmon/arctic_fan_controller.rst
@@ -29,18 +29,16 @@ Usage notes
 Since it is a USB device, hotplug is supported. The device is autodetected.
 
 The device does not support GET_REPORT, so the driver cannot read back the
-current hardware PWM state at probe time. The cached PWM values (readable
-via pwm[1-10]) start at 0 and reflect only values that have been
-successfully written. Because each OUT report carries all 10 channel values,
-writing a single channel also sends the cached values for all other channels.
-Users should set all channels to the desired values before relying on the
-cached state.
-
-On system suspend, the device may lose power and reset its PWM channels to
-hardware defaults. The driver clears its cached duty values on resume so
-that reads reflect the unknown hardware state rather than stale pre-suspend
-values. Userspace is responsible for re-applying the desired duty cycles
-after resume.
+current hardware PWM state at probe time. Each OUT report carries all 10
+channels, so pwm[1-10] is a host cache. It starts at the MCU factory
+default of 40% (sysfs 102). After a successful write, the cache reflects
+that value. Users should set all channels to the desired values before
+relying on the cached state.
+
+On system suspend, the device may lose power and reset PWM to the factory
+default. The driver restores the cache to 40% on resume. If the device
+kept power across suspend, userspace should re-apply the desired duty
+cycles.
 
 Sysfs entries
 -------------
@@ -51,6 +49,6 @@ pwm[1-10]        PWM duty cycle (0-255). Write: sends an OUT report setting the
                  duty cycle (scaled from 0-255 to 0-100% for the device);
                  the cached value is updated only after the device ACKs the
                  command with a success status. Read: returns the last
-                 successfully written value; initialized to 0 at driver load
-                 and after resume (hardware state unknown).
+                 successfully written value; initialized to 102 (40%) at
+                 driver load and after resume (MCU factory default).
 ================ ==============================================================
diff --git a/drivers/hwmon/arctic_fan_controller.c b/drivers/hwmon/arctic_fan_controller.c
index dbe84cd93c0..9a609257273 100644
--- a/drivers/hwmon/arctic_fan_controller.c
+++ b/drivers/hwmon/arctic_fan_controller.c
@@ -35,6 +35,8 @@
  * Measured over 500 iterations: max ~563 ms. Keep 1 s as margin.
  */
 #define ARCTIC_ACK_TIMEOUT_MS		1000
+/* MCU factory default; 40% of 0-255 is 102. */
+#define ARCTIC_PWM_DEFAULT		102
 
 struct arctic_fan_data {
 	struct hid_device *hdev;
@@ -164,7 +166,7 @@ static int arctic_fan_write(struct device *dev, enum hwmon_sensor_types type,
 
 	/*
 	 * Build the buffer and arm write_pending under in_report_lock so that
-	 * reset_resume() cannot clear pwm_duty[] between the pwm_duty[] read
+	 * reset_resume() cannot replace pwm_duty[] between the pwm_duty[] read
 	 * and the buffer write, and raw_event() cannot deliver a stale ACK
 	 * from a previous write into this write's completion.
 	 *
@@ -256,14 +258,14 @@ static int arctic_fan_reset_resume(struct hid_device *hdev)
 	unsigned long flags;
 
 	/*
-	 * The device resets its PWM channels to hardware defaults on power
-	 * loss during suspend. Clear the cached duty values so they reflect
-	 * the unknown hardware state, consistent with probe-time behaviour
-	 * (the device has no GET_REPORT support). Hold in_report_lock so
-	 * this does not race with a concurrent pwm read or write callback.
+	 * The device resets its PWM channels to the MCU factory default
+	 * (40%) on power loss during suspend. Restore the cache to that
+	 * same default, consistent with probe-time behaviour (the device
+	 * has no GET_REPORT support). Hold in_report_lock so this does
+	 * not race with a concurrent pwm read or write callback.
 	 */
 	spin_lock_irqsave(&priv->in_report_lock, flags);
-	memset(priv->pwm_duty, 0, sizeof(priv->pwm_duty));
+	memset(priv->pwm_duty, ARCTIC_PWM_DEFAULT, sizeof(priv->pwm_duty));
 	spin_unlock_irqrestore(&priv->in_report_lock, flags);
 	return 0;
 }
@@ -288,6 +290,8 @@ static int arctic_fan_probe(struct hid_device *hdev,
 	priv->hdev = hdev;
 	spin_lock_init(&priv->in_report_lock);
 	init_completion(&priv->in_report_received);
+	/* Same MCU factory default as reset_resume(); see ARCTIC_PWM_DEFAULT above. */
+	memset(priv->pwm_duty, ARCTIC_PWM_DEFAULT, sizeof(priv->pwm_duty));
 	hid_set_drvdata(hdev, priv);
 
 	ret = hid_hw_start(hdev, HID_CONNECT_DRIVER);
-- 
2.43.0


  reply	other threads:[~2026-09-10  5:05 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-10  5:03 [PATCH 0/3] hwmon: arctic_fan_controller: PWM default, dual license, maintainer contact Aureo Serrano de Souza
2026-09-10  5:03 ` Aureo Serrano de Souza [this message]
2026-09-10  5:10   ` [PATCH 1/3] hwmon: arctic_fan_controller: default PWM cache to MCU 40% sashiko-bot
2026-09-11  0:55   ` Guenter Roeck
2026-09-10  5:04 ` [PATCH 2/3] hwmon: arctic_fan_controller: dual-license GPL-2.0-or-later OR BSD-2-Clause Aureo Serrano de Souza
2026-09-10  5:07   ` sashiko-bot
2026-09-11  0:56   ` Guenter Roeck
2026-09-10  5:04 ` [PATCH 3/3] hwmon: arctic_fan_controller: use shared maintainer address Aureo Serrano de Souza
2026-09-11  0:57   ` Guenter Roeck

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260910050401.279868-2-aureo.serrano@arctic.de \
    --to=aureo.serrano@arctic.de \
    --cc=arctic.it.hk@arctic.de \
    --cc=corbet@lwn.net \
    --cc=linux-doc@vger.kernel.org \
    --cc=linux-hwmon@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@roeck-us.net \
    --cc=linux@weissschuh.net \
    --cc=rdunlap@infradead.org \
    --cc=skhan@linuxfoundation.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox