Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ASUS laptop] Charging end threshold not properly set after hibernate #589

Closed
waechtjn opened this issue Oct 11, 2021 · 13 comments
Closed

Comments

@waechtjn
Copy link

Hi,
I am using tlp 1.4.0 on Arch Linux/Manjaro and an ASUS ExperBook (B9450FA). I have set STOP_CHARGE_THRESH_BAT0=80 in /etc/tlp.conf. Normally this works fine and the battery is not charged to more than 80%. However, after waking up from hibernate (suspend to disk), this setting is not respected and the battery charges to 100%. cat /sys/class/power_supply/BAT0/charge_control_end_threshold still reports a threshold of 80%, though.

I suspect that the problem is that asus_wmi (kernel version: 5.14.10-1-MANJARO) has the value for sysfs cached somewhere and does not restore it to the firmware when booting from hibernate. I am not sure whether to report this as a kernel module bug or as a tlp bug.

I can check whether setting /sys/class/power_supply/BAT0/charge_control_end_threshold to 100 and then back to 80 (or even setting it again only to 80) after waking from hibernate resolves the issue. Would you be willing to implement this as a work around?

Thanks!

@waechtjn
Copy link
Author

I can now confirm that writing the same value to /sys/class/power_supply/BAT0/charge_control_end_threshold after resuming from hibernate works and the charging threshold is correctly applied.

This also seems to agree with the source code of charge_control_end_threshold_store in asus_wmi.c. In fact, there is even a comment that the actual currently used value cannot be read from the firmware. Thus, a cached valued is used to read the value back, which does not coincide with the actual value in the firmware after a resume from hibernate.

I tried to fix this by creating a systemd service file to call tlp init restart when resuming from hibernate. However, the way writing the charging thresholds is implemented in tlp in bat.d/15-asus prevents this from working: it first reads the (cached) value from sysfs and does not write it back if the new value agrees with the (wrongly read) old one.

I propose to drop this check (since the actual value from the firmware cannot be read anyway as stated in the kernel driver).

@linrunner
Copy link
Owner

Hi,

thanks for your report. I already knew that with ASUS you have to rewrite the threshold after resume and have already implemented that -> https://github.com/linrunner/TLP/blob/main/tlp.in#L434 .

I will remove the comparison and always write the threshold twice.

@linrunner
Copy link
Owner

I can now confirm that writing the same value to /sys/class/power_supply/BAT0/charge_control_end_threshold after resuming from hibernate works and the charging threshold is correctly applied.

When I read this I am no longer quite sure: is writing once sufficient?

@waechtjn
Copy link
Author

I think you only have to write the value again after resume from hibernate/suspend to disk (not from sleep/suspend to RAM). If you like, I can verify this again.

Writing ONCE is enough for the change to take effect. Thus, the value should be written (at least) ONCE after a normal boot and ONCE after resuming from hibernate (which is a normal boot from the persepective of the firmware, I suppose).

I hope this clears things up. Let me know if you need more information and thank you!

@linrunner
Copy link
Owner

linrunner commented Oct 14, 2021

Well. I guess I have all the information for implementing the change. I'll commence with writing once. TLP doesn't differentiate between resume from S3 and S4, but I suppose it doesn't hurt writing after S3 too.

I won't be able to do it before next week, though, because I'm in the process of moving.

@linrunner linrunner added this to the 1.5 Release milestone Nov 8, 2021
linrunner added a commit that referenced this issue Nov 10, 2021
Rationale: asus_wmi.c states that the actual currently used value for the
threshold cannot be read from the firmware. Thus, a cached valued is used
to read the value back, which does not coincide with the actual value
in the firmware after a resume from hibernate.

Solution: remove the read-and-compare code, always write the thresholds.
As a precaution, this is implemented for all threshold write operations,
i.e. boot, resume from suspend/hibernate and command line.

References:
* #589
* https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/platform/x86/asus-wmi.c#n640
@linrunner
Copy link
Owner

Done. Please test with the main branch (you may use tlp-git from the AUR).

@waechtjn
Copy link
Author

I have switched to tlp-git from AUR and it seems to work now!

(There is still a short phase where the computer is charging at boot but I think that this is when the kernel has booted but tlphas not been called yet by systemd; so I suppose this cannot be avoided.)

Thank you very much for your work and I hope your move went well!

@linrunner
Copy link
Owner

There is still a short phase where the computer is charging at boot

Looks like either the threshold is not saved at all in the EC or is reset each time when turning on power. Strange.

Thanks for testing.

@waechtjn
Copy link
Author

It is saved (because the machine does not charge to 100% while powered off) but the firmware must rest it on every boot. I have tested it and the same happens with Windows: when at 80%, the computer is not charging while powered off and during the first boot phases but then gets charged for a couple of seconds until Windows has booted (I suppose until the appropriate Asus system service has started). So I think that this is "normal" behavior and that not much can be done.

@linrunner
Copy link
Owner

TLP 1.5 Beta 1 is out -> #609

@linrunner
Copy link
Owner

Beta test is completed and TLP 1.5.0 is out. Have fun!

@LuccoJ
Copy link

LuccoJ commented Oct 31, 2022

Apologies, I had a "zombie" remnant of asusctl/asusd that was responsible for restoring a wrong threshold, I'm an idiot. I had removed the package, but given I hadn't rebooted, asusd was still running despite not even existing as a file anymore.

@linrunner
Copy link
Owner

@LuccoJ : thanks for your feedback anyway.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants