On Mon, Mar 22 2021, Klemens Nanni <k...@openbsd.org> wrote:
> Better diff at the end thanks to jca's eyeballing, see comments inline.
>
> kettenis:  I see room for improvement in our subsystems and their
> interactions, but I don't think the current situation is bad enough to
> leave those bits out for now.
>
> Feedback? OK?
>

[...]

>> > @@ -202,6 +217,12 @@ cwfg_attach(struct device *parent, struc
>> >  
>> >    sensor_task_register(sc, cwfg_update_sensors, 5);
>> >  
>> > +#if NAPM > 0
>> > +  /* make sure we have the apm state initialized before apm attaches */
>> > +  cwfg_update_sensors(sc);
>> > +  apm_setinfohook(cwfg_apminfo);
>> > +#endif
>> > +
>> >    printf("\n");
>> >  }
>> >  
>> > @@ -324,6 +345,7 @@ cwfg_update_sensors(void *arg)
>> >    uint32_t vcell, rtt, tmp;
>> >    uint8_t val;
>> >    int error, n;
>> > +  u_char bat_percent;
>> >  
>> >    if ((error = cwfg_lock(sc)) != 0)
>> >            return;
>> > @@ -348,6 +370,7 @@ cwfg_update_sensors(void *arg)
>> >    if ((error = cwfg_read(sc, SOC_HI_REG, &val)) != 0)
>> >            goto done;
>> >    if (val != 0xff) {
>> > +          bat_percent = val;
>> >            sc->sc_sensor[CWFG_SENSOR_SOC].value = val * 1000;
>> >            sc->sc_sensor[CWFG_SENSOR_SOC].flags &= ~SENSOR_FINVALID;
>> >    }
>> 
>> If val == 0xff bat_percent is unitialized.  Note that in this error
>> condition the sensors code leaves sc->sc_sensor[CWFG_SENSOR_SOC].value
>> alone.
> Oops.  Both `val' and `rtt' can be "useless" and we could end up with
> a partially updated `cwfg_power'.

With the current code, rtt is always meaningful.  I was really talking
only about bat_percent being possibly uninitialized.

> If we always reset all values up front and then update whatever is
> possible, we can avoid the intermediate variable completely and end up
> with `cwfg_power' providing consistent readings.

Except if reading one register fails and we take the goto done shortcut.
In that case sensors and apm get out of sync, which is bad IMHO.

[...]

>> So to keep apm and sensors in sync I think it would be better to reuse
>> the cached sc->sc_sensor[CWFG_SENSOR_SOC].value.
> I did `sc->sc_sensor[CWFG_SENSOR_SOC].value / 1000' first but ended up
> with bogus values, hence the `bat_percent' buffer to avoid arithmetics.
>
>
>> I don't know whether the error condition mentioned above happens
>> frequently with this driver.  Reporting APM_BATT_ABSENT (and similar for
>> sensors) would be useful, and could be done in a subsequent step.
> But that isn't the case?  From apm(4):
>
>              APM_BATTERY_ABSENT
>                                   No battery installed.
>
> The driver just can't tell us enough, but the battery is still there
> (we get good percentage/liftime readings), so
>
>              APM_BATT_UNKNOWN
>                                   Cannot read the current battery state.
>
> is only appropiate here imho.
>
>
>> What's the underlying hardware, does it involve a pluggable battery?
> Nope, Pinebook Pro with one internal battery and AC.

Since the battery can't be removed in your pinebook, then obviously
APM_BATTERY_ABSENT isn't very meaningful.  But maybe the CellWise
hardware supports pluggable batteries.  Anyway...

The diff below is mostly your diff, except:
- statically initialize cwfg_power with proper values.  That way there's
  a reason less for initializing it early by forcefully calling
  cwfg_update_sensors().
- only update cwfg_power when we already fetched new values for sensors.

I hope that this approach will make changing the cwfg_update_sensors()
code easier.

If it works for you and you agree with this tweaked proposal, ok jca@


Index: cwfg.c
===================================================================
RCS file: /d/cvs/src/sys/dev/fdt/cwfg.c,v
retrieving revision 1.2
diff -u -p -p -u -r1.2 cwfg.c
--- cwfg.c      22 Mar 2021 18:37:26 -0000      1.2
+++ cwfg.c      23 Mar 2021 23:49:22 -0000
@@ -32,12 +32,15 @@
 #include <sys/malloc.h>
 #include <sys/sensors.h>
 
+#include <machine/apmvar.h>
 #include <machine/fdt.h>
 
 #include <dev/ofw/openfirm.h>
 
 #include <dev/i2c/i2cvar.h>
 
+#include "apm.h"
+
 #define        VERSION_REG             0x00
 #define        VCELL_HI_REG            0x02
 #define         VCELL_HI_MASK                  0x3f
@@ -119,6 +122,22 @@ struct cfdriver cwfg_cd = {
        NULL, "cwfg", DV_DULL
 };
 
+#if NAPM > 0
+struct apm_power_info cwfg_power = {
+       .battery_state = APM_BATT_UNKNOWN,
+       .ac_state = APM_AC_UNKNOWN,
+       .battery_life = 0,
+       .minutes_left = -1,
+};
+
+int
+cwfg_apminfo(struct apm_power_info *info)
+{
+       memcpy(info, &cwfg_power, sizeof(*info));
+       return 0;
+}
+#endif
+
 int
 cwfg_match(struct device *parent, void *match, void *aux)
 {
@@ -202,6 +221,10 @@ cwfg_attach(struct device *parent, struc
 
        sensor_task_register(sc, cwfg_update_sensors, 5);
 
+#if NAPM > 0
+       apm_setinfohook(cwfg_apminfo);
+#endif
+
        printf("\n");
 }
 
@@ -350,6 +373,11 @@ cwfg_update_sensors(void *arg)
        if (val != 0xff) {
                sc->sc_sensor[CWFG_SENSOR_SOC].value = val * 1000;
                sc->sc_sensor[CWFG_SENSOR_SOC].flags &= ~SENSOR_FINVALID;
+#if NAPM > 0
+               cwfg_power.battery_state = val > sc->sc_alert_level ?
+                   APM_BATT_HIGH : APM_BATT_LOW;
+               cwfg_power.battery_life = val;
+#endif
        }
 
        /* RTT */
@@ -362,6 +390,9 @@ cwfg_update_sensors(void *arg)
        if (rtt != 0x1fff) {
                sc->sc_sensor[CWFG_SENSOR_RTT].value = rtt;
                sc->sc_sensor[CWFG_SENSOR_RTT].flags &= ~SENSOR_FINVALID;
+#if NAPM > 0
+               cwfg_power.minutes_left = rtt;
+#endif
        }
 
 done:

-- 
jca | PGP : 0x1524E7EE / 5135 92C1 AD36 5293 2BDF  DDCC 0DFA 74AE 1524 E7EE

Reply via email to