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
next prev parent 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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.