frederik-h / acer-wmi-battery

A linux kernel driver for the Acer WMI battery health control interface
GNU General Public License v2.0
113 stars 15 forks source link

acer_wmi_battery: Unknown buffer length 4 on Aspire A315-53G #23

Closed NexAdn closed 1 year ago

NexAdn commented 1 year ago

Acer Aspire A315-53G with Gentoo Linux here. The module compiles just fine, but shows errors on dmesg after insmod. Complete dmesg output after insmod:

[271855.458537] acer_wmi_battery: Unknown buffer length 4
[271855.458545] acer_wmi_battery: available modes: health mode, calibration mode

Trying to go into calibration mode with echo 1 | sudo tee /sys/bus/wmi/drivers/acer-wmi-battery/calibration_mode yields the same error:

[271913.736903] acer_wmi_battery: Unknown buffer length 4

The output from sysfs afterwards indicates that neither the calibration mode nor the health mode have turned on:

$ cat /sys/bus/wmi/drivers/acer-wmi-battery/calibration_mode
0
$ cat /sys/bus/wmi/drivers/acer-wmi-battery/health_mode
0

(this happens when trying to enable calibration mode as well as health mode).

I found two places where such an error message is emitted. Both validate that the response from wmi_evaluate_method. The first one asserts a response length of 8 while the second one asserts a response length of 4. Hence, this part of the code is probably relevant here:

https://github.com/frederik-h/acer-wmi-battery/blob/2e57c4a77f0b1d85d8d55d30f1c3832b14c59088/acer-wmi-battery.c#L93-L111

NexAdn commented 1 year ago

One thing I forgot to mention: I already had to replace the battery once. The replacement battery is Acer AC14B18J.

frederik-h commented 1 year ago

Acer Aspire A315-53G with Gentoo Linux here. The module compiles just fine, but shows errors on dmesg after insmod. Complete dmesg output after insmod:

[271855.458537] acer_wmi_battery: Unknown buffer length 4
[271855.458545] acer_wmi_battery: available modes: health mode, calibration mode

Trying to go into calibration mode with echo 1 | sudo tee /sys/bus/wmi/drivers/acer-wmi-battery/calibration_mode yields the same error:

[271913.736903] acer_wmi_battery: Unknown buffer length 4

The output from sysfs afterwards indicates that neither the calibration mode nor the health mode have turned on:

$ cat /sys/bus/wmi/drivers/acer-wmi-battery/calibration_mode
0
$ cat /sys/bus/wmi/drivers/acer-wmi-battery/health_mode
0

(this happens when trying to enable calibration mode as well as health mode).

I found two places where such an error message is emitted. Both validate that the response from wmi_evaluate_method. The first one asserts a response length of 8 while the second one asserts a response length of 4. Hence, this part of the code is probably relevant here:

https://github.com/frederik-h/acer-wmi-battery/blob/2e57c4a77f0b1d85d8d55d30f1c3832b14c59088/acer-wmi-battery.c#L93-L111

You could try to see what happens if you simply ignore the difference in the buffer length. I have quickly added the necessary code change in a branch for you, see https://github.com/frederik-h/acer-wmi-battery/tree/buffer-length.

The last 5 bytes are the "FunctionStatus". The module uses only the first two of this. The first one is the "health mode", the second one the "callibration mode". Perhaps your laptop does not support calibration mode? If you try it, ignore the reported status for the calibration mode.

NexAdn commented 1 year ago

Thanks! Unfortunately, it doesn't work. The driver loads successfully with the following dmesg output:

[332904.234263] acer_wmi_battery: loading out-of-tree module taints kernel.
[332904.239485] acer_wmi_battery: unexpected status function return buffer length 4
[332904.239491] acer_wmi_battery: available modes: 

Trying to enter calibration mode hangs with this command:

/sys/bus/wmi/drivers/acer-wmi-battery # echo 1 > calibration_mode

I've inserted a few trace outputs in the code showing function calls, entry and the return of calibration_mode_store. Seems like WMI calls the store functions over and over again:

[334504.212245] acer_wmi_battery: enter: calibration_mode_store
[334504.212247] acer_wmi_battery: ret:   calibration_mode(0) [calibration_mode < 0]
[334504.212251] acer_wmi_battery: enter: calibration_mode_store
[334504.212253] acer_wmi_battery: ret:   calibration_mode(0) [calibration_mode < 0]
[... heavily truncated output, the above lines repeat constantly ...]

A quick debug output of the health_mode and calibration_mode values of battery_status in init_state():

[335141.615288] acer_wmi_battery: status: hm: -1 cm: -1

From the debug output I assume:

frederik-h commented 1 year ago

Thanks! Unfortunately, it doesn't work. The driver loads successfully with the following dmesg output:

[332904.234263] acer_wmi_battery: loading out-of-tree module taints kernel.
[332904.239485] acer_wmi_battery: unexpected status function return buffer length 4
[332904.239491] acer_wmi_battery: available modes: 

Trying to enter calibration mode hangs with this command:

/sys/bus/wmi/drivers/acer-wmi-battery # echo 1 > calibration_mode

I've inserted a few trace outputs in the code showing function calls, entry and the return of calibration_mode_store. Seems like WMI calls the store functions over and over again:

[334504.212245] acer_wmi_battery: enter: calibration_mode_store
[334504.212247] acer_wmi_battery: ret:   calibration_mode(0) [calibration_mode < 0]
[334504.212251] acer_wmi_battery: enter: calibration_mode_store
[334504.212253] acer_wmi_battery: ret:   calibration_mode(0) [calibration_mode < 0]
[... heavily truncated output, the above lines repeat constantly ...]

A quick debug output of the health_mode and calibration_mode values of battery_status in init_state():

[335141.615288] acer_wmi_battery: status: hm: -1 cm: -1

From the debug output I assume:

* WMI doesn't like it when the function returns 0. Maybe WMI thinks that the write was incomplete, trying to repeat the write until it succeeds.

* The battery might not support health mode (just an interpretation of the aforementioned `-1`)

Thanks for the information. I was already expecting the calibration mode not to work. The health mode did not work for you either, right? That is, you are not able to enable the health mode even if you do not attempt to use calibration mode before. In this case, I think I should keep the error if the buffer size is too short. The health mode and calibration mode should be correctly reported as being unsupported. I think this is not happening because the error is not handled in init_state.

NexAdn commented 1 year ago

The health mode did not work for you either, right?

Yes, I just confirmed health mode enters an infinite write loop as well.

It's a bit unfortunate that my battery is not supported, but at least you have more information about what your driver supports...