Re: [PATCH v2 2/3] hwmon: (asus_wmi_ec_sensors) Support B550 Asus WMI.

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Eugene,

As for me, use WMI methods will be more reliable and cover more
motherboards.

Best regards,
            Denis.

On Thu, 7 Oct 2021 20:11:33 +0200
Eugene Shalygin <eugene.shalygin@xxxxxxxxx> wrote:

> Denis and All,
> 
> regarding the asus-wmi-ec-sensors driver: it uses a WMI method to read
> EC registers, and this method is slow (requires almost a full second
> for a single call). Maybe I'm doing something wrong, but my impression
> is that the WMI calls themselves are that slow. I will try to
> reimplement this driver using direct EC operations and the global ACPI
> lock with a hope to make it read sensors quicker. If that works out,
> perhaps the nct6775 may go the same way, as it suffers too from the
> slow WMI calls. I know next to nothing about the ACPI system and learn
> from the beginning, so I'm not sure about the result. I know the naive
> reading from the ACPI EC registers leads to problems (fans get stuck,
> etc.), and if someone with knowledge can assure me that the idea with
> the ACPI global lock (as far as I understand it is even implemented in
> the ec kernel driver already) is correct, I would even request to stop
> accepting the EC WMI sensors driver, as it is so slow (albeit dead
> simple and small).
> 
> Best regards,
> Eugen
> 
> On Thu, 7 Oct 2021 at 19:55, Eugene Shalygin
> <eugene.shalygin@xxxxxxxxx> wrote:
> >
> > Hi Denis,
> >
> > yes, the GH repo contains the fix and a few code cleanups, which I
> > would like to propose for mainlining too. Also, please find below a
> > draft of the documentation:
> >
> > Kernel driver asus-wmi-ec-sensors
> > =================================
> >
> > Authors:
> >         <eugene.shalygin@xxxxxxxxx>
> >
> > Description:
> > ------------
> > ASUS mainboards publish hardware monitoring information via Super
> > I/O chip and the ACPI embedded controller (EC) registers. Some of
> > the sensors are only available via the EC.
> >
> > ASUS WMI interface provides a method (BREC) to read data from EC
> > registers, which is utilized by this driver to publish those sensor
> > readings to the HWMON system. The driver is aware of and reads the
> > following sensors:
> >
> > 1. Chipset (PCH) temperature
> > 2. CPU package temperature
> > 3. Motherboard temperature
> > 4. Readings from the T_Sensor header
> > 5. VRM temperature
> > 6. CPU_Opt fan RPM
> > 7. Chipset fan RPM
> > 8. Readings from the "Water flow meter" header (RPM)
> > 9. Readings from the "Water In" and "Water Out" temperature headers
> > 10. CPU current
> >
> > Best regards,
> > Eugene
> >
> > On Thu, 7 Oct 2021 at 17:46, Denis Pauk <pauk.denis@xxxxxxxxx>
> > wrote:  
> > >
> > > Hi Eugene,
> > >
> > > On Thu, 7 Oct 2021 01:32:14 +0200
> > > Eugene Shalygin <eugene.shalygin@xxxxxxxxx> wrote:
> > >  
> > > > On Thu, 7 Oct 2021 at 00:25, Denis Pauk <pauk.denis@xxxxxxxxx>
> > > > wrote:  
> > > > >  
> > > >  
> > > > > Supported motherboards:
> > > > > * ROG CROSSHAIR VIII HERO
> > > > > * ROG CROSSHAIR VIII DARK HERO
> > > > > * ROG CROSSHAIR VIII FORMULA
> > > > > * ROG STRIX X570-E GAMING
> > > > > * ROG STRIX B550-E GAMING  
> > > >
> > > > Pro WS X570-ACE is missing from this list.  
> > > Thanks, I will check.  
> > > >  
> > > > > + * EC provided:  
> > > > provides  
> > > Thanks, I will check.  
> > > >  
> > > > > + * Chipset temperature,
> > > > > + * CPU temperature,
> > > > > + * Motherboard temperature,
> > > > > + * T_Sensor temperature,
> > > > > + * VRM  temperature,
> > > > > + * Water In temperature,
> > > > > + * Water Out temperature,
> > > > > + * CPU Optional Fan,  
> > > > Hereinafter "CPU Optional Fan RPM"?
> > > >  
> > > Thanks, I will check.  
> > > > > +static const enum known_ec_sensor
> > > > > known_board_sensors[BOARD_MAX][SENSOR_MAX + 1] = {
> > > > > +       [BOARD_PW_X570_A] = {
> > > > > +               SENSOR_TEMP_CHIPSET, SENSOR_TEMP_CPU,
> > > > > SENSOR_TEMP_MB, SENSOR_TEMP_VRM,
> > > > > +               SENSOR_FAN_CHIPSET,  
> > > >
> > > > I missed SENSOR_CURR_CPU for a few boards, and unfortunately the
> > > > mistake made it here too. Sorry for that.
> > > >  
> > > Do you have such fix in your repository?  
> > > > > +/**
> > > > > + * struct asus_wmi_ec_info - sensor info.
> > > > > + * @sensors: list of sensors.
> > > > > + * @read_arg: UTF-16 string to pass to BRxx() WMI function.
> > > > > + * @read_buffer: WMI function output.  
> > > >
> > > > This seems to be a bit misleading to me in a sense that the
> > > > variable holds decoded output (array of numbers as opposed to
> > > > array of characters in the WMI output buffer.
> > > >  
> > > > > +struct asus_wmi_data {
> > > > > +       int ec_board;
> > > > > +};  
> > > >
> > > > A leftover?
> > > >  
> > > Its platform data and used to share board_id with probe.
> > >  
> > > > > +static void asus_wmi_ec_decode_reply_buffer(const u8 *inp,
> > > > > u8 *out) +{
> > > > > +       unsigned int len = ACPI_MIN(ASUS_WMI_MAX_BUF_LEN,
> > > > > inp[0] / 4);
> > > > > +       char buffer[ASUS_WMI_MAX_BUF_LEN * 2];
> > > > > +       const char *pos = buffer;
> > > > > +       const u8 *data = inp + 2;
> > > > > +       unsigned int i;
> > > > > +
> > > > > +       utf16s_to_utf8s((wchar_t *)data, len * 2,
> > > > > UTF16_LITTLE_ENDIAN, buffer, len * 2);  
> > > > Errr... Why is it here? You need the same loop afterwards, just
> > > > with a smaller stride.  
> > > I have tried to apply Andy's idea. And it looks it does not
> > > provide benefits. Andy, what do you think? Maybe I understand it
> > > in wrong way.  
> > > > > +
> > > > > +       for (i = 0; i < len; i++, pos += 2)
> > > > > +               out[i] = (hex_to_bin(pos[0]) << 4) +
> > > > > hex_to_bin(pos[1]); +}
> > > > > +
> > > > > +static void asus_wmi_ec_encode_registers(u16 *registers, u8
> > > > > len, char *out) +{
> > > > > +       char buffer[ASUS_WMI_MAX_BUF_LEN * 2];
> > > > > +       char *pos = buffer;
> > > > > +       unsigned int i;
> > > > > +       u8 byte;
> > > > > +
> > > > > +       *out++ = len * 8;
> > > > > +       *out++ = 0;
> > > > > +
> > > > > +       for (i = 0; i < len; i++) {
> > > > > +               byte = registers[i] >> 8;
> > > > > +               *pos = hex_asc_hi(byte);
> > > > > +               pos++;
> > > > > +               *pos = hex_asc_lo(byte);
> > > > > +               pos++;
> > > > > +               byte = registers[i];
> > > > > +               *pos = hex_asc_hi(byte);
> > > > > +               pos++;
> > > > > +               *pos = hex_asc_lo(byte);
> > > > > +               pos++;
> > > > > +       }
> > > > > +
> > > > > +       utf8s_to_utf16s(buffer, len * 4, UTF16_LITTLE_ENDIAN,
> > > > > (wchar_t *)out, len * 4);  
> > > > Same here. Just for the sake of calling utf8s_to_utf16s() you
> > > > need the same loop plus an additional buffer. I don't get it.
> > > >  
> > > I have tried to apply Andy's idea. And it looks it does not
> > > provide benefits. Andy, what do you think? Maybe I understand it
> > > in wrong way.  
> > > > > +}
> > > > > +
> > > > > +static void asus_wmi_ec_make_block_read_query(struct
> > > > > asus_wmi_ec_info *ec) +{
> > > > > +       u16 registers[ASUS_WMI_BLOCK_READ_REGISTERS_MAX];
> > > > > +       const struct ec_sensor_info *si;
> > > > > +       long i, j, register_idx = 0;  
> > > > long? maybe a simple unsigned or int?
> > > >  
> > > Looks as it was in original patch, I will look.  
> > > > > +
> > > > > +static int asus_wmi_ec_update_ec_sensors(struct
> > > > > asus_wmi_ec_info *ec) +{
> > > > > +       const struct ec_sensor_info *si;
> > > > > +       struct ec_sensor *s;
> > > > > +
> > > > > +       u32 value;  
> > > > This variable is now redundant.
> > > >  
> > > Thank you, I will look.
> > >  
> > > > > +               if (si->addr.size == 1)  
> > > > Maybe switch(si->addr.size)?
> > > >  
> > > Thank you, I will check.  
> > > > > +                       value = ec->read_buffer[read_reg_ct];
> > > > > +               else if (si->addr.size == 2)
> > > > > +                       value =
> > > > > get_unaligned_le16(&ec->read_buffer[read_reg_ct]);
> > > > > +               else if (si->addr.size == 4)
> > > > > +                       value =
> > > > > get_unaligned_le32(&ec->read_buffer[read_reg_ct]); +
> > > > > +               read_reg_ct += si->addr.size;
> > > > > +               s->cached_value = value;
> > > > > +       }
> > > > > +       return 0;
> > > > > +}  
> > > >
> > > >  
> > > > > +       mutex_lock(&sensor_data->lock);  
> > > > The mutex locking/unlocking should be moved inside the
> > > > update_ec_sensors(), I guess.
> > > >
> > > > I re-read your answer to my question as to why don't you add
> > > > module aliases to the driver, and I have to admit I don't
> > > > really understand it. Could you, please, elaborate?
> > > >  
> > > It looked complicated to support two kind of WMI interfaces with
> > > UUID. As we split big support module to two separate - I will
> > > look to such change also.
> > >  
> > > > Thank you,
> > > > Eugene  
> > >
> > > Best regards,
> > >      Denis.  




[Index of Archives]     [LM Sensors]     [Linux Sound]     [ALSA Users]     [ALSA Devel]     [Linux Audio Users]     [Linux Media]     [Kernel]     [Gimp]     [Yosemite News]     [Linux Media]

  Powered by Linux