Re: [PATCH v2 1/3] Fix SW_TABLET_MODE detection method

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

 



Hi Jorge,

On 2/18/22 17:09, Jorge Lopez wrote:
> The purpose of this patch is to introduce a fix and removal
> of the current hack when determining tablet mode status.
> 
> Determining the tablet mode status requires reading Byte 0 bit 2 and 3
> as reported by HPWMI_HARDWARE_QUERY.  The investigation identified the
> failure was rooted in two areas; HPWMI_HARDWARE_QUERY failure (0x05)
> and reading Byte 0, bit 2 only to determine the table mode status.
> HPWMI_HARDWARE_QUERY WMI failure also rendered the dock state value invalid.
> 
> All changes were validated on a ZBook Workstation notebook.
> 
> Signed-off-by: Jorge Lopez <jorge.lopez2@xxxxxx>
> 
> ---
> Based on the latest platform-drivers-x86.git/for-next
> ---
>  drivers/platform/x86/hp-wmi.c | 29 ++++++++++++++++-------------
>  1 file changed, 16 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c
> index 48a46466f086..544fce906ce7 100644
> --- a/drivers/platform/x86/hp-wmi.c
> +++ b/drivers/platform/x86/hp-wmi.c
> @@ -35,9 +35,6 @@ MODULE_LICENSE("GPL");
>  MODULE_ALIAS("wmi:95F24279-4D7B-4334-9387-ACCDC67EF61C");
>  MODULE_ALIAS("wmi:5FB7F034-2C63-45e9-BE91-3D44E2C707E4");
>  
> -static int enable_tablet_mode_sw = -1;
> -module_param(enable_tablet_mode_sw, int, 0444);
> -MODULE_PARM_DESC(enable_tablet_mode_sw, "Enable SW_TABLET_MODE reporting (-1=auto, 0=no, 1=yes)");
>  
>  #define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C"
>  #define HPWMI_BIOS_GUID "5FB7F034-2C63-45e9-BE91-3D44E2C707E4"
> @@ -127,6 +124,7 @@ enum hp_wmi_command {
>  enum hp_wmi_hardware_mask {
>  	HPWMI_DOCK_MASK		= 0x01,
>  	HPWMI_TABLET_MASK	= 0x04,
> +	HPWMI_DETACHABLE_MASK	= 0x08,
>  };
>  
>  struct bios_return {
> @@ -347,12 +345,19 @@ static int hp_wmi_read_int(int query)
>  
>  static int hp_wmi_hw_state(int mask)
>  {
> -	int state = hp_wmi_read_int(HPWMI_HARDWARE_QUERY);
> +	int state = 0, ret;
>  
> -	if (state < 0)
> -		return state;
> +	ret = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, HPWMI_READ, &state,
> +				   0, sizeof(state));
>  
> -	return !!(state & mask);
> +	if (ret)
> +		return ret < 0 ? ret : -EINVAL;
> +
> +	/* determine if Detachable mode is enabled */
> +	if (HPWMI_TABLET_MASK == mask)
> +		state = (state & HPWMI_DETACHABLE_MASK );

If you do: "state &= 0x08" as you do here
then after that "state & HPWMI_TABLET_MASK" aka
"state & 0x04" as done below will always be 0
since you have masked out the 0x04 bit when applying
the 0x08 mask.

I think you probably want something like this instead:

	if (HPWMI_TABLET_MASK == mask)
		if (!(state & HPWMI_DETACHABLE_MASK))
			return 0;

So when asked to check the HPWMI_TABLET_MASK then if
the device is not a detachable always return 0,
does that sound right ?

Note it is probable better to just makes this a generic
helper which no longer takes the mask and let the caller
handle all this. Or maybe just remove this function all
together since if you remove the masking I don't think
there will be much left of it.





> +
> +	return (state & mask);
>  }
>  
>  static int omen_thermal_profile_set(int mode)
> @@ -781,18 +786,16 @@ static int __init hp_wmi_input_setup(void)
>  
>  	/* Dock */
>  	val = hp_wmi_hw_state(HPWMI_DOCK_MASK);
> -	if (!(val < 0)) {
> +	if (val > 0) {
>  		__set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
>  		input_report_switch(hp_wmi_input_dev, SW_DOCK, val);
>  	}

I'm not sure why you made this change here, the original code here
actually is correct. This:

		__set_bit(SW_DOCK, hp_wmi_input_dev->swbit);

tells userspace that the input-device has a SW_DOCK switch,
where as this:

  		input_report_switch(hp_wmi_input_dev, SW_DOCK, val);

Set the initial value of the dock-switch.

After your change we will not only do this bit:

		__set_bit(SW_DOCK, hp_wmi_input_dev->swbit);

When the machine is docked at boot, which means that if it
gets docked later we will not report it since SW_DOCK is
never set in hp_wmi_input_dev->swbit in that case
(swbit must be initialized before registering the input-device).


>  
>  	/* Tablet mode */
> -	if (enable_tablet_mode_sw > 0) {
> -		val = hp_wmi_hw_state(HPWMI_TABLET_MASK);
> -		if (val >= 0) {
> -			__set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
> +	val = hp_wmi_hw_state(HPWMI_TABLET_MASK);
> +	if (val > 0) {
> +		__set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
>  			input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val);
> -		}
>  	}

Dropping the module option is fine, but otherwise this needs to be changed.

I think we want something like this here:

	err = hp_wmi_perform_query(HPWMI_HARDWARE_QUERY, HPWMI_READ, &val, 0, sizeof(val));

	if (!err) {
		__set_bit(SW_DOCK, hp_wmi_input_dev->swbit);
		input_report_switch(hp_wmi_input_dev, SW_DOCK, (val & HPWMI_DOCK_MASK));
	}

	if (!err && (val & HPWMI_DETACHABLE_MASK)) {
		__set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit);
		input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, (val & HPWMI_TABLET_MASK));
	}

This also avoids unnecessarily doing the HPWMI_HARDWARE_QUERY twice.

And we probably want something similar in hp_wmi_notify() case HPWMI_DOCK_EVENT:
to also avoid unnecessarily doing the HPWMI_HARDWARE_QUERY twice there.

Regards,

Hans


Reg




[Index of Archives]     [Linux Kernel Development]     [Linux USB Devel]     [Video for Linux]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux