* [PATCH v5 0/4] Fix SW_TABLET_MODE detection method
@ 2022-03-10 21:08 Jorge Lopez
2022-03-10 21:08 ` [PATCH v5 1/4] Fix hp_wmi_read_int() reporting error (0x05) Jorge Lopez
` (3 more replies)
0 siblings, 4 replies; 13+ messages in thread
From: Jorge Lopez @ 2022-03-10 21:08 UTC (permalink / raw)
To: platform-driver-x86
The intension for this patch was to address SW_TABLET_MODE detection
problem. It is during the initial investigation; two other issues were
identified and are related to the initial task.
First, several WMI queries were reporting error 0x05 including
HPWMI_HARDWARE_QUERY that is responsible for returning dock and table
modes values. See patch v5 part 2 and 3 comments for list of WMI queries
affected. The driver now reports the appropriate states and values
correctly.
Lastly, a limiting data size restriction was discovered.
struct bios_args data member size limits all possible WMI commands
to those requiring buffer size of 128 bytes or less. Several WMI
commands and queries require a buffer size larger than 128 bytes
hence limiting current and new feature supported by the driver.
hp_wmi_perform_query function changed to handle the memory
allocation and release of any required buffer size.
Description of changes between version 4 and version 5
------------------------------------------------------
v5 patch 1: Fix hp_wmi_read_int() reporting error (0x05)
-Moved hp_wmi_read_int() to a separate patch.
-Initially part of v4 patch 1
v5 patch 2: Fix SW_TABLET_MODE detection method
-Remaining part are changes included in v4 patch 1
-Replaced return values with -ENODEV errors
-Updated how the closing return value is calculated.
-Patch 2 is dependent of patch 1 in order for tablet
mode detection to work properly
v5 patch 3: Fix 0x05 error code reported by several WMI calls
-No new changes were introduced.
-Patch is identical to v4 patch 2
v5 patch 4: Changing bios_args.data to be dynamically allocated
-Replace sizeof() with struct_size() and flex_array_size() helpers
-Added ret variable value when the output buffer is zero
Jorge Lopez (4):
Fix hp_wmi_read_int() reporting error (0x05)
Fix SW_TABLET_MODE detection method
Fix 0x05 error code reported by several WMI calls
Changing bios_args.data to be dynamically allocated
drivers/platform/x86/hp-wmi.c | 159 ++++++++++++++++++++++------------
1 file changed, 106 insertions(+), 53 deletions(-)
--
2.25.1
^ permalink raw reply [flat|nested] 13+ messages in thread* [PATCH v5 1/4] Fix hp_wmi_read_int() reporting error (0x05) 2022-03-10 21:08 [PATCH v5 0/4] Fix SW_TABLET_MODE detection method Jorge Lopez @ 2022-03-10 21:08 ` Jorge Lopez 2022-03-14 10:41 ` Hans de Goede 2022-03-10 21:08 ` [PATCH v5 2/4] Fix SW_TABLET_MODE detection method Jorge Lopez ` (2 subsequent siblings) 3 siblings, 1 reply; 13+ messages in thread From: Jorge Lopez @ 2022-03-10 21:08 UTC (permalink / raw) To: platform-driver-x86 The purpose of this patch is to introduce a fix to hp_wmi_read_int() and eliminate failure error (0x05). Several WMI queries leverage hp_wmi_read_int() to read their data and were failing with error 0x05. HPWMI_DISPLAY_QUERY HPWMI_HDDTEMP_QUERY HPWMI_ALS_QUERY HPWMI_HARDWARE_QUERY HPWMI_WIRELESS_QUERY HPWMI_POSTCODEERROR_QUERY The failure occurs because hp_wmi_read_int() calls hp_wmi_perform_query() with input parameter of size greater than zero. Invoking those WMI commands with an input buffer size greater than zero causes the command to be rejected and error 0x05 be returned. All changes were validated on a HP ZBook Workstation notebook, HP EliteBook x360, and HP EliteBook 850 G8. Signed-off-by: Jorge Lopez <jorge.lopez2@hp.com> --- Based on the latest platform-drivers-x86.git/for-next --- drivers/platform/x86/hp-wmi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 48a46466f086..103f56399ed0 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -337,7 +337,7 @@ static int hp_wmi_read_int(int query) int val = 0, ret; ret = hp_wmi_perform_query(query, HPWMI_READ, &val, - sizeof(val), sizeof(val)); + 0, sizeof(val)); if (ret) return ret < 0 ? ret : -EINVAL; -- 2.25.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v5 1/4] Fix hp_wmi_read_int() reporting error (0x05) 2022-03-10 21:08 ` [PATCH v5 1/4] Fix hp_wmi_read_int() reporting error (0x05) Jorge Lopez @ 2022-03-14 10:41 ` Hans de Goede 0 siblings, 0 replies; 13+ messages in thread From: Hans de Goede @ 2022-03-14 10:41 UTC (permalink / raw) To: Jorge Lopez, platform-driver-x86 Hi, On 3/10/22 22:08, Jorge Lopez wrote: > The purpose of this patch is to introduce a fix to hp_wmi_read_int() > and eliminate failure error (0x05). Several WMI queries leverage > hp_wmi_read_int() to read their data and were failing with error 0x05. > > HPWMI_DISPLAY_QUERY > HPWMI_HDDTEMP_QUERY > HPWMI_ALS_QUERY > HPWMI_HARDWARE_QUERY > HPWMI_WIRELESS_QUERY > HPWMI_POSTCODEERROR_QUERY > > The failure occurs because hp_wmi_read_int() calls > hp_wmi_perform_query() with input parameter of size greater than zero. > Invoking those WMI commands with an input buffer size greater than > zero causes the command to be rejected and error 0x05 be returned. > > All changes were validated on a HP ZBook Workstation notebook, > HP EliteBook x360, and HP EliteBook 850 G8. > > Signed-off-by: Jorge Lopez <jorge.lopez2@hp.com> Thank you for your patch, I've applied this patch to my review-hans branch: https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans Note since your using a different email address then Signed-off-by to submit the patches, I've changed the From / Author of the patch to match the Signed-off-by while applying this patch (and the same for the other patches in the series). The patch will show up in my review-hans branch once I've pushed my local branch there, which might take a while. Once I've run some tests on this branch the patches there will be added to the platform-drivers-x86/for-next branch and eventually will be included in the pdx86 pull-request to Linus for the next merge-window. Regards, Hans > > --- > Based on the latest platform-drivers-x86.git/for-next > --- > drivers/platform/x86/hp-wmi.c | 2 +- > 1 file changed, 1 insertion(+), 1 deletion(-) > > diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c > index 48a46466f086..103f56399ed0 100644 > --- a/drivers/platform/x86/hp-wmi.c > +++ b/drivers/platform/x86/hp-wmi.c > @@ -337,7 +337,7 @@ static int hp_wmi_read_int(int query) > int val = 0, ret; > > ret = hp_wmi_perform_query(query, HPWMI_READ, &val, > - sizeof(val), sizeof(val)); > + 0, sizeof(val)); > > if (ret) > return ret < 0 ? ret : -EINVAL; ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v5 2/4] Fix SW_TABLET_MODE detection method 2022-03-10 21:08 [PATCH v5 0/4] Fix SW_TABLET_MODE detection method Jorge Lopez 2022-03-10 21:08 ` [PATCH v5 1/4] Fix hp_wmi_read_int() reporting error (0x05) Jorge Lopez @ 2022-03-10 21:08 ` Jorge Lopez 2022-03-14 10:44 ` Hans de Goede 2024-08-08 21:46 ` Stefan Sichler 2022-03-10 21:08 ` [PATCH v5 3/4] Fix 0x05 error code reported by several WMI calls Jorge Lopez 2022-03-10 21:08 ` [PATCH v5 4/4] Changing bios_args.data to be dynamically allocated Jorge Lopez 3 siblings, 2 replies; 13+ messages in thread From: Jorge Lopez @ 2022-03-10 21:08 UTC (permalink / raw) To: platform-driver-x86 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 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. The latest changes use SMBIOS Type 3 (chassis type) and WMI Command 0x40 (device_mode_status) information to determine if the device is in tablet mode or not. hp_wmi_hw_state function was split into two functions; hp_wmi_get_dock_state and hp_wmi_get_tablet_mode. The new functions separate how dock_state and tablet_mode is handled in a cleaner manner. All changes were validated on a HP ZBook Workstation notebook, HP EliteBook x360, and HP EliteBook 850 G8. Signed-off-by: Jorge Lopez <jorge.lopez2@hp.com> --- Based on the latest platform-drivers-x86.git/for-next This patch requires patch "Fix hp_wmi_read_int() reporting error (0x05)" in order to work correctly. --- drivers/platform/x86/hp-wmi.c | 71 +++++++++++++++++++++++++---------- 1 file changed, 52 insertions(+), 19 deletions(-) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 103f56399ed0..e9aa05c26a40 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -35,10 +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" #define HP_OMEN_EC_THERMAL_PROFILE_OFFSET 0x95 @@ -107,6 +103,7 @@ enum hp_wmi_commandtype { HPWMI_FEATURE2_QUERY = 0x0d, HPWMI_WIRELESS2_QUERY = 0x1b, HPWMI_POSTCODEERROR_QUERY = 0x2a, + HPWMI_SYSTEM_DEVICE_MODE = 0x40, HPWMI_THERMAL_PROFILE_QUERY = 0x4c, }; @@ -217,6 +214,18 @@ struct rfkill2_device { static int rfkill2_count; static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES]; +/* Chassis Types values were obtained from SMBIOS reference + * specification version 3.00. A complete list of system enclosures + * and chassis types is available on Table 17. + */ +static const char * const tablet_chassis_types[] = { + "30", /* Tablet*/ + "31", /* Convertible */ + "32" /* Detachable */ +}; + +#define DEVICE_MODE_TABLET 0x06 + /* map output size to the corresponding WMI method id */ static inline int encode_outsize_for_pvsz(int outsize) { @@ -345,14 +354,40 @@ static int hp_wmi_read_int(int query) return val; } -static int hp_wmi_hw_state(int mask) +static int hp_wmi_get_dock_state(void) { int state = hp_wmi_read_int(HPWMI_HARDWARE_QUERY); if (state < 0) return state; - return !!(state & mask); + return !!(state & HPWMI_DOCK_MASK); +} + +static int hp_wmi_get_tablet_mode(void) +{ + char system_device_mode[4] = { 0 }; + int ret; + bool tablet_found = false; + + const char *chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); + + if (!chassis_type) + return -ENODEV; + + tablet_found = match_string(tablet_chassis_types, + ARRAY_SIZE(tablet_chassis_types), + chassis_type) >= 0; + if (!tablet_found) + return -ENODEV; + + ret = hp_wmi_perform_query(HPWMI_SYSTEM_DEVICE_MODE, HPWMI_READ, + system_device_mode, 0, sizeof(system_device_mode)); + + if (ret < 0) + return ret; + + return system_device_mode[0] == DEVICE_MODE_TABLET; } static int omen_thermal_profile_set(int mode) @@ -568,7 +603,7 @@ static ssize_t als_show(struct device *dev, struct device_attribute *attr, static ssize_t dock_show(struct device *dev, struct device_attribute *attr, char *buf) { - int value = hp_wmi_hw_state(HPWMI_DOCK_MASK); + int value = hp_wmi_get_dock_state(); if (value < 0) return value; return sprintf(buf, "%d\n", value); @@ -577,7 +612,7 @@ static ssize_t dock_show(struct device *dev, struct device_attribute *attr, static ssize_t tablet_show(struct device *dev, struct device_attribute *attr, char *buf) { - int value = hp_wmi_hw_state(HPWMI_TABLET_MASK); + int value = hp_wmi_get_tablet_mode(); if (value < 0) return value; return sprintf(buf, "%d\n", value); @@ -699,10 +734,10 @@ static void hp_wmi_notify(u32 value, void *context) case HPWMI_DOCK_EVENT: if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit)) input_report_switch(hp_wmi_input_dev, SW_DOCK, - hp_wmi_hw_state(HPWMI_DOCK_MASK)); + hp_wmi_get_dock_state()); if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit)) input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, - hp_wmi_hw_state(HPWMI_TABLET_MASK)); + hp_wmi_get_tablet_mode()); input_sync(hp_wmi_input_dev); break; case HPWMI_PARK_HDD: @@ -780,19 +815,17 @@ static int __init hp_wmi_input_setup(void) __set_bit(EV_SW, hp_wmi_input_dev->evbit); /* Dock */ - val = hp_wmi_hw_state(HPWMI_DOCK_MASK); + val = hp_wmi_get_dock_state(); if (!(val < 0)) { __set_bit(SW_DOCK, hp_wmi_input_dev->swbit); input_report_switch(hp_wmi_input_dev, SW_DOCK, val); } /* 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); - input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val); - } + val = hp_wmi_get_tablet_mode(); + if (!(val < 0)) { + __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); + input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val); } err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL); @@ -1227,10 +1260,10 @@ static int hp_wmi_resume_handler(struct device *device) if (hp_wmi_input_dev) { if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit)) input_report_switch(hp_wmi_input_dev, SW_DOCK, - hp_wmi_hw_state(HPWMI_DOCK_MASK)); + hp_wmi_get_dock_state()); if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit)) input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, - hp_wmi_hw_state(HPWMI_TABLET_MASK)); + hp_wmi_get_tablet_mode()); input_sync(hp_wmi_input_dev); } -- 2.25.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v5 2/4] Fix SW_TABLET_MODE detection method 2022-03-10 21:08 ` [PATCH v5 2/4] Fix SW_TABLET_MODE detection method Jorge Lopez @ 2022-03-14 10:44 ` Hans de Goede 2024-08-08 21:46 ` Stefan Sichler 1 sibling, 0 replies; 13+ messages in thread From: Hans de Goede @ 2022-03-14 10:44 UTC (permalink / raw) To: Jorge Lopez, platform-driver-x86 Hi, On 3/10/22 22:08, 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 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. > > The latest changes use SMBIOS Type 3 (chassis type) and WMI Command > 0x40 (device_mode_status) information to determine if the device is > in tablet mode or not. > > hp_wmi_hw_state function was split into two functions; > hp_wmi_get_dock_state and hp_wmi_get_tablet_mode. The new functions > separate how dock_state and tablet_mode is handled in a cleaner > manner. > > All changes were validated on a HP ZBook Workstation notebook, > HP EliteBook x360, and HP EliteBook 850 G8. > > Signed-off-by: Jorge Lopez <jorge.lopez2@hp.com> > > --- > Based on the latest platform-drivers-x86.git/for-next > > This patch requires patch "Fix hp_wmi_read_int() reporting > error (0x05)" in order to work correctly. > --- > drivers/platform/x86/hp-wmi.c | 71 +++++++++++++++++++++++++---------- > 1 file changed, 52 insertions(+), 19 deletions(-) > > diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c > index 103f56399ed0..e9aa05c26a40 100644 > --- a/drivers/platform/x86/hp-wmi.c > +++ b/drivers/platform/x86/hp-wmi.c > @@ -35,10 +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" > #define HP_OMEN_EC_THERMAL_PROFILE_OFFSET 0x95 > @@ -107,6 +103,7 @@ enum hp_wmi_commandtype { > HPWMI_FEATURE2_QUERY = 0x0d, > HPWMI_WIRELESS2_QUERY = 0x1b, > HPWMI_POSTCODEERROR_QUERY = 0x2a, > + HPWMI_SYSTEM_DEVICE_MODE = 0x40, > HPWMI_THERMAL_PROFILE_QUERY = 0x4c, > }; > > @@ -217,6 +214,18 @@ struct rfkill2_device { > static int rfkill2_count; > static struct rfkill2_device rfkill2[HPWMI_MAX_RFKILL2_DEVICES]; > > +/* Chassis Types values were obtained from SMBIOS reference > + * specification version 3.00. A complete list of system enclosures > + * and chassis types is available on Table 17. > + */ > +static const char * const tablet_chassis_types[] = { > + "30", /* Tablet*/ > + "31", /* Convertible */ > + "32" /* Detachable */ > +}; > + > +#define DEVICE_MODE_TABLET 0x06 > + > /* map output size to the corresponding WMI method id */ > static inline int encode_outsize_for_pvsz(int outsize) > { > @@ -345,14 +354,40 @@ static int hp_wmi_read_int(int query) > return val; > } > > -static int hp_wmi_hw_state(int mask) > +static int hp_wmi_get_dock_state(void) > { > int state = hp_wmi_read_int(HPWMI_HARDWARE_QUERY); > > if (state < 0) > return state; > > - return !!(state & mask); > + return !!(state & HPWMI_DOCK_MASK); > +} > + > +static int hp_wmi_get_tablet_mode(void) > +{ > + char system_device_mode[4] = { 0 }; > + int ret; > + bool tablet_found = false; > + > + const char *chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); This new-line in the mids of the variable declaration block looks weird. Also we usually put variable declarations at the top of a function in reverse-christmas tree order (longest variable declarations first). I've fixed this up to look like this: char system_device_mode[4] = { 0 }; const char *chassis_type; bool tablet_found; int ret; chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); if (!chassis_type) return -ENODEV; (no functional changes). > + tablet_found = match_string(tablet_chassis_types, > + ARRAY_SIZE(tablet_chassis_types), > + chassis_type) >= 0; > + if (!tablet_found) > + return -ENODEV; > + > + ret = hp_wmi_perform_query(HPWMI_SYSTEM_DEVICE_MODE, HPWMI_READ, > + system_device_mode, 0, sizeof(system_device_mode)); > + The newline here between the call + check looks weird, I've dropped this while merging the patch: Thank you for your patch, I've applied this patch to my review-hans branch: https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans Note it will show up in my review-hans branch once I've pushed my local branch there, which might take a while. Once I've run some tests on this branch the patches there will be added to the platform-drivers-x86/for-next branch and eventually will be included in the pdx86 pull-request to Linus for the next merge-window. Regards, Hans > + if (ret < 0) > + return ret; > + > + return system_device_mode[0] == DEVICE_MODE_TABLET; > } > > static int omen_thermal_profile_set(int mode) > @@ -568,7 +603,7 @@ static ssize_t als_show(struct device *dev, struct device_attribute *attr, > static ssize_t dock_show(struct device *dev, struct device_attribute *attr, > char *buf) > { > - int value = hp_wmi_hw_state(HPWMI_DOCK_MASK); > + int value = hp_wmi_get_dock_state(); > if (value < 0) > return value; > return sprintf(buf, "%d\n", value); > @@ -577,7 +612,7 @@ static ssize_t dock_show(struct device *dev, struct device_attribute *attr, > static ssize_t tablet_show(struct device *dev, struct device_attribute *attr, > char *buf) > { > - int value = hp_wmi_hw_state(HPWMI_TABLET_MASK); > + int value = hp_wmi_get_tablet_mode(); > if (value < 0) > return value; > return sprintf(buf, "%d\n", value); > @@ -699,10 +734,10 @@ static void hp_wmi_notify(u32 value, void *context) > case HPWMI_DOCK_EVENT: > if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit)) > input_report_switch(hp_wmi_input_dev, SW_DOCK, > - hp_wmi_hw_state(HPWMI_DOCK_MASK)); > + hp_wmi_get_dock_state()); > if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit)) > input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, > - hp_wmi_hw_state(HPWMI_TABLET_MASK)); > + hp_wmi_get_tablet_mode()); > input_sync(hp_wmi_input_dev); > break; > case HPWMI_PARK_HDD: > @@ -780,19 +815,17 @@ static int __init hp_wmi_input_setup(void) > __set_bit(EV_SW, hp_wmi_input_dev->evbit); > > /* Dock */ > - val = hp_wmi_hw_state(HPWMI_DOCK_MASK); > + val = hp_wmi_get_dock_state(); > if (!(val < 0)) { > __set_bit(SW_DOCK, hp_wmi_input_dev->swbit); > input_report_switch(hp_wmi_input_dev, SW_DOCK, val); > } > > /* 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); > - input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val); > - } > + val = hp_wmi_get_tablet_mode(); > + if (!(val < 0)) { > + __set_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit); > + input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, val); > } > > err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL); > @@ -1227,10 +1260,10 @@ static int hp_wmi_resume_handler(struct device *device) > if (hp_wmi_input_dev) { > if (test_bit(SW_DOCK, hp_wmi_input_dev->swbit)) > input_report_switch(hp_wmi_input_dev, SW_DOCK, > - hp_wmi_hw_state(HPWMI_DOCK_MASK)); > + hp_wmi_get_dock_state()); > if (test_bit(SW_TABLET_MODE, hp_wmi_input_dev->swbit)) > input_report_switch(hp_wmi_input_dev, SW_TABLET_MODE, > - hp_wmi_hw_state(HPWMI_TABLET_MASK)); > + hp_wmi_get_tablet_mode()); > input_sync(hp_wmi_input_dev); > } > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 2/4] Fix SW_TABLET_MODE detection method 2022-03-10 21:08 ` [PATCH v5 2/4] Fix SW_TABLET_MODE detection method Jorge Lopez 2022-03-14 10:44 ` Hans de Goede @ 2024-08-08 21:46 ` Stefan Sichler 2024-08-13 14:34 ` Ilpo Järvinen 1 sibling, 1 reply; 13+ messages in thread From: Stefan Sichler @ 2024-08-08 21:46 UTC (permalink / raw) To: jorgealtxwork; +Cc: platform-driver-x86 Hi, this patch (which is now committed to the kernel as commit 520ee4ea1cc60251a6e3c911cf0336278aa52634 since v5.18-rc1) unfortunately introduced a regression on my HP EliteBook 2760p Convertible: Tablet mode is no longer detected. It worked flawlessly before (when enable_tablet_mode_sw module param was set to 1). Debugging showed that on this device, two problems prevent the table mode detection from working: - Chassis Type is reported as 0x10 (= Lunch Box) - the query of HPWMI_SYSTEM_DEVICE_MODE does not report tablet state at all Note that the chassis type of this device (switch to tablet mode by screen *rotation*) actually differs from the newer HP models (switch to tablet mode by screen *flipping*). I suggest fixing this by re-adding the removed module parameter "enable_tablet_mode_sw", but change its behavior to work in the following way: - when left at default -1 (auto): no change to current (new) implementation - when set to 0: unconditionally disable table mode reporting at all - when set to 1: ignore Chassis type and use old-skool hp_wmi_hw_state(HPWMI_TABLET_MASK) query method to determine tablet mode in addition to new hp_wmi_perform_query(HPWMI_SYSTEM_DEVICE_MODE...) method I prepared a patch based on commit 520ee4ea1cc60251a6e3c911cf0336278aa52634, and tested it successfully on my device. See below. Regards, Stefan --- hp-wmi.c.orig 2024-03-10 21:38:09.000000000 +0100 +++ hp-wmi.c 2024-08-08 09:23:29.509113900 +0200 @@ -35,6 +35,10 @@ 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" #define HP_OMEN_EC_THERMAL_PROFILE_OFFSET 0x95 @@ -428,6 +432,9 @@ bool tablet_found; int ret; + if (!enable_tablet_mode_sw) + return -ENODEV; + chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); if (!chassis_type) return -ENODEV; @@ -435,16 +442,24 @@ tablet_found = match_string(tablet_chassis_types, ARRAY_SIZE(tablet_chassis_types), chassis_type) >= 0; - if (!tablet_found) + if (!tablet_found && enable_tablet_mode_sw < 0 /*auto*/) return -ENODEV; ret = hp_wmi_perform_query(HPWMI_SYSTEM_DEVICE_MODE, HPWMI_READ, system_device_mode, zero_if_sup(system_device_mode), sizeof(system_device_mode)); - if (ret < 0) - return ret; + if (ret >= 0) + ret = (system_device_mode[0] == DEVICE_MODE_TABLET); + + /* workaround for older convertibles */ + if (ret <= 0 && enable_tablet_mode_sw > 0) + { + ret = hp_wmi_read_int(HPWMI_HARDWARE_QUERY); + if (!(ret < 0)) + ret = !!(ret & HPWMI_TABLET_MASK); + } - return system_device_mode[0] == DEVICE_MODE_TABLET; + return ret; } static int omen_thermal_profile_set(int mode) ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 2/4] Fix SW_TABLET_MODE detection method 2024-08-08 21:46 ` Stefan Sichler @ 2024-08-13 14:34 ` Ilpo Järvinen 2024-08-19 16:41 ` Stefan Sichler 0 siblings, 1 reply; 13+ messages in thread From: Ilpo Järvinen @ 2024-08-13 14:34 UTC (permalink / raw) To: Stefan Sichler; +Cc: jorgealtxwork, platform-driver-x86 On Thu, 8 Aug 2024, Stefan Sichler wrote: > this patch (which is now committed to the kernel as commit > 520ee4ea1cc60251a6e3c911cf0336278aa52634 since v5.18-rc1) unfortunately > introduced a regression on my HP EliteBook 2760p Convertible: > > Tablet mode is no longer detected. > > It worked flawlessly before (when enable_tablet_mode_sw module param was > set to 1). > > Debugging showed that on this device, two problems prevent the table > mode detection from working: > > - Chassis Type is reported as 0x10 (= Lunch Box) > > - the query of HPWMI_SYSTEM_DEVICE_MODE does not report tablet state > at all > > Note that the chassis type of this device (switch to tablet mode by > screen *rotation*) actually differs from the newer HP models (switch to > tablet mode by screen *flipping*). > > > I suggest fixing this by re-adding the removed module parameter > "enable_tablet_mode_sw", but change its behavior to work in the > following way: > > - when left at default -1 (auto): no change to current (new) > implementation > > - when set to 0: unconditionally disable table mode reporting at all > > - when set to 1: ignore Chassis type and use old-skool > hp_wmi_hw_state(HPWMI_TABLET_MASK) query method to determine tablet mode > in addition to new hp_wmi_perform_query(HPWMI_SYSTEM_DEVICE_MODE...) method > > > I prepared a patch based on commit > 520ee4ea1cc60251a6e3c911cf0336278aa52634, and tested it successfully on > my device. > See below. > > Regards, > Stefan > > --- hp-wmi.c.orig 2024-03-10 21:38:09.000000000 +0100 > +++ hp-wmi.c 2024-08-08 09:23:29.509113900 +0200 This submission does not follow the normal patch formatting guidelines, please see Documentation/process/submitting-patches.rst. > @@ -35,6 +35,10 @@ > 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" > #define HP_OMEN_EC_THERMAL_PROFILE_OFFSET 0x95 > @@ -428,6 +432,9 @@ > bool tablet_found; > int ret; > > + if (!enable_tablet_mode_sw) > + return -ENODEV; > + > chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); > if (!chassis_type) > return -ENODEV; > @@ -435,16 +442,24 @@ > tablet_found = match_string(tablet_chassis_types, > ARRAY_SIZE(tablet_chassis_types), > chassis_type) >= 0; > - if (!tablet_found) > + if (!tablet_found && enable_tablet_mode_sw < 0 /*auto*/) Having to add a comment like that is a very strong indication you'd want to have a named define instead, e.g., HPWMI_TABLET_MODE_AUTO. > return -ENODEV; > > ret = hp_wmi_perform_query(HPWMI_SYSTEM_DEVICE_MODE, HPWMI_READ, > system_device_mode, > zero_if_sup(system_device_mode), > sizeof(system_device_mode)); > - if (ret < 0) > - return ret; > + if (ret >= 0) > + ret = (system_device_mode[0] == DEVICE_MODE_TABLET); > + > + /* workaround for older convertibles */ > + if (ret <= 0 && enable_tablet_mode_sw > 0) > + { > + ret = hp_wmi_read_int(HPWMI_HARDWARE_QUERY); > + if (!(ret < 0)) > + ret = !!(ret & HPWMI_TABLET_MASK); > + } > > - return system_device_mode[0] == DEVICE_MODE_TABLET; > + return ret; The logic is quite hard to follow. It would be better to return early. if (ret < 0 && enable_tablet_mode_sw == HPWMI_TABLET_MODE_AUTO) return ret; if (ret >= 0 && system_device_mode[0] == DEVICE_MODE_TABLET) return 1; ret = hp_wmi_read_int(HPWMI_HARDWARE_QUERY); if (ret < 0) return ret; return !!(ret & HPWMI_TABLET_MASK); However, automatically detecting this condition over adding the module parameter would be the preferred solution. -- i. > } > > static int omen_thermal_profile_set(int mode) > > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 2/4] Fix SW_TABLET_MODE detection method 2024-08-13 14:34 ` Ilpo Järvinen @ 2024-08-19 16:41 ` Stefan Sichler 0 siblings, 0 replies; 13+ messages in thread From: Stefan Sichler @ 2024-08-19 16:41 UTC (permalink / raw) To: ilpo.jarvinen; +Cc: jorgealtxwork, platform-driver-x86 Hi Ilpo, thank you for your comments. I added some defines for the values of the module param and re-ordered the logic a bit. I think it is easier to follow now. I now also use another return variable "ret2" for the result of hp_wmi_read_int() to not overwrite the result of original hp_wmi_perform_query() when hp_wmi_read_int() fails. This was actually a bug in my first implementation. I still think that re-using the enable_tablet_mode_sw param for that is a reasonable compromise, because the comment of original commit 520ee4ea1cc60251a6e3c911cf0336278aa52634 suggests that there was some problem with hp_wmi_read_int(HPWMI_HARDWARE_QUERY) on newer Tablets. So, because I cannot test this, I'd prefer to not change current behavior when the enable_tablet_mode_sw parameter is not set. Best Regards Stefan >>>>>>>>>>>>>>> Actual patch starts here: From: Stefan Sichler <stsichler@web.de> Date: Mon, 19 Aug 2024 14:45:57 +0200 Subject: [PATCH] platform/x86: hp-wmi: repair Tablet Mode detection on old Convertibles This fixes a regression introduced by commit 520ee4ea1cc60251a6e3c911cf0336278aa52634 ("Fix SW_TABLET_MODE detection method"). Investigation showed that some older Convertibles like HP EliteBook 2760p do neither report Chassis Type correctly nor report tablet state by HPWMI_SYSTEM_DEVICE_MODE, so for those, it is still required to fallback to previous HPWMI_HARDWARE_QUERY method. Since on pre-5.18 kernels, it was required to set enable_tablet_mode_sw module param to enable this anyway, we re-add this removed parameter here and re-use it in the following way: - when left at default -1 (auto): no change to current implementation - when set to 0 (off): unconditionally disable tablet mode reporting - when set to 1 (force on): ignore Chassis type and use old hp_wmi_hw_state(HPWMI_TABLET_MASK) query method in addition to new hp_wmi_perform_query(HPWMI_SYSTEM_DEVICE_MODE...) method Signed-off-by: Stefan Sichler <stsichler@web.de> --- drivers/platform/x86/hp/hp-wmi.c | 32 ++++++++++++++++++++++++++++---- 1 file changed, 28 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/hp/hp-wmi.c b/drivers/platform/x86/hp/hp-wmi.c index 876e0a97c..cab01308d 100644 --- a/drivers/platform/x86/hp/hp-wmi.c +++ b/drivers/platform/x86/hp/hp-wmi.c @@ -38,6 +38,13 @@ 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_TABLET_MODE_SW_AUTO -1 +#define HPWMI_TABLET_MODE_SW_OFF 0 +#define HPWMI_TABLET_MODE_SW_FORCE_ON 1 + #define HPWMI_EVENT_GUID "95F24279-4D7B-4334-9387-ACCDC67EF61C" #define HPWMI_BIOS_GUID "5FB7F034-2C63-45E9-BE91-3D44E2C707E4" @@ -459,23 +466,40 @@ static int hp_wmi_get_tablet_mode(void) bool tablet_found; int ret; + if (enable_tablet_mode_sw == HPWMI_TABLET_MODE_SW_OFF) + return -ENODEV; + chassis_type = dmi_get_system_info(DMI_CHASSIS_TYPE); if (!chassis_type) return -ENODEV; - tablet_found = match_string(tablet_chassis_types, + tablet_found = + (enable_tablet_mode_sw == HPWMI_TABLET_MODE_SW_FORCE_ON) + || (match_string(tablet_chassis_types, ARRAY_SIZE(tablet_chassis_types), - chassis_type) >= 0; + chassis_type) >= 0); if (!tablet_found) return -ENODEV; ret = hp_wmi_perform_query(HPWMI_SYSTEM_DEVICE_MODE, HPWMI_READ, system_device_mode, zero_if_sup(system_device_mode), sizeof(system_device_mode)); - if (ret < 0) + if (ret < 0 && enable_tablet_mode_sw != HPWMI_TABLET_MODE_SW_FORCE_ON) return ret; - return system_device_mode[0] == DEVICE_MODE_TABLET; + if (ret >= 0) + ret = (system_device_mode[0] == DEVICE_MODE_TABLET); + + /* workaround for older convertibles. needs to be actively switched on + * and is only executed when HPWMI_SYSTEM_DEVICE_MODE query failed or + * did not report tablet state, i.e. (ret < 0) or (ret == 0) */ + if (ret <= 0 && enable_tablet_mode_sw == HPWMI_TABLET_MODE_SW_FORCE_ON) { + int ret2 = hp_wmi_read_int(HPWMI_HARDWARE_QUERY); + if (ret2 >= 0) + ret = !!(ret2 & HPWMI_TABLET_MASK); + } + + return ret; } static int omen_thermal_profile_set(int mode) -- 2.43.0 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* [PATCH v5 3/4] Fix 0x05 error code reported by several WMI calls 2022-03-10 21:08 [PATCH v5 0/4] Fix SW_TABLET_MODE detection method Jorge Lopez 2022-03-10 21:08 ` [PATCH v5 1/4] Fix hp_wmi_read_int() reporting error (0x05) Jorge Lopez 2022-03-10 21:08 ` [PATCH v5 2/4] Fix SW_TABLET_MODE detection method Jorge Lopez @ 2022-03-10 21:08 ` Jorge Lopez 2022-03-14 10:44 ` Hans de Goede 2022-03-10 21:08 ` [PATCH v5 4/4] Changing bios_args.data to be dynamically allocated Jorge Lopez 3 siblings, 1 reply; 13+ messages in thread From: Jorge Lopez @ 2022-03-10 21:08 UTC (permalink / raw) To: platform-driver-x86 Several WMI queries leverage hp_wmi_read_int function to read their data. hp_wmi_read_int function was corrected in a previous patch. Now, this function invokes hp_wmi_perform_query with input parameter of size zero and the output buffer of size 4. WMI commands calling hp_wmi_perform_query with input buffer size value of zero are listed below. HPWMI_DISPLAY_QUERY HPWMI_HDDTEMP_QUERY HPWMI_ALS_QUERY HPWMI_HARDWARE_QUERY HPWMI_WIRELESS_QUERY HPWMI_BIOS_QUERY HPWMI_FEATURE_QUERY HPWMI_HOTKEY_QUERY HPWMI_FEATURE2_QUERY HPWMI_WIRELESS2_QUERY HPWMI_POSTCODEERROR_QUERY HPWMI_THERMAL_PROFILE_QUERY HPWMI_FAN_SPEED_MAX_GET_QUERY Invoking those WMI commands with an input buffer size greater than zero will cause error 0x05 to be returned. All WMI commands executed by the driver were reviewed and changes were made to ensure the expected input and output buffer size match the WMI specification. Changes were validated on a HP ZBook Workstation notebook, HP EliteBook x360, and HP EliteBook 850 G8. Additional validation was included in the test process to ensure no other commands were incorrectly handled. Signed-off-by: Jorge Lopez <jorge.lopez2@hp.com> --- Based on the latest platform-drivers-x86.git/for-next --- drivers/platform/x86/hp-wmi.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index e9aa05c26a40..e76bd4bef6b5 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -329,7 +329,7 @@ static int hp_wmi_get_fan_speed(int fan) char fan_data[4] = { fan, 0, 0, 0 }; int ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_GET_QUERY, HPWMI_GM, - &fan_data, sizeof(fan_data), + &fan_data, sizeof(char), sizeof(fan_data)); if (ret != 0) @@ -399,7 +399,7 @@ static int omen_thermal_profile_set(int mode) return -EINVAL; ret = hp_wmi_perform_query(HPWMI_SET_PERFORMANCE_MODE, HPWMI_GM, - &buffer, sizeof(buffer), sizeof(buffer)); + &buffer, sizeof(buffer), 0); if (ret) return ret < 0 ? ret : -EINVAL; @@ -436,7 +436,7 @@ static int hp_wmi_fan_speed_max_set(int enabled) int ret; ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_MAX_SET_QUERY, HPWMI_GM, - &enabled, sizeof(enabled), sizeof(enabled)); + &enabled, sizeof(enabled), 0); if (ret) return ret < 0 ? ret : -EINVAL; @@ -449,7 +449,7 @@ static int hp_wmi_fan_speed_max_get(void) int val = 0, ret; ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_MAX_GET_QUERY, HPWMI_GM, - &val, sizeof(val), sizeof(val)); + &val, 0, sizeof(val)); if (ret) return ret < 0 ? ret : -EINVAL; @@ -461,7 +461,7 @@ static int __init hp_wmi_bios_2008_later(void) { int state = 0; int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, HPWMI_READ, &state, - sizeof(state), sizeof(state)); + 0, sizeof(state)); if (!ret) return 1; @@ -472,7 +472,7 @@ static int __init hp_wmi_bios_2009_later(void) { u8 state[128]; int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, HPWMI_READ, &state, - sizeof(state), sizeof(state)); + 0, sizeof(state)); if (!ret) return 1; @@ -550,7 +550,7 @@ static int hp_wmi_rfkill2_refresh(void) int err, i; err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state, - sizeof(state), sizeof(state)); + 0, sizeof(state)); if (err) return err; @@ -639,7 +639,7 @@ static ssize_t als_store(struct device *dev, struct device_attribute *attr, return ret; ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, HPWMI_WRITE, &tmp, - sizeof(tmp), sizeof(tmp)); + sizeof(tmp), 0); if (ret) return ret < 0 ? ret : -EINVAL; @@ -660,9 +660,9 @@ static ssize_t postcode_store(struct device *dev, struct device_attribute *attr, if (clear == false) return -EINVAL; - /* Clear the POST error code. It is kept until until cleared. */ + /* Clear the POST error code. It is kept until cleared. */ ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, HPWMI_WRITE, &tmp, - sizeof(tmp), sizeof(tmp)); + sizeof(tmp), 0); if (ret) return ret < 0 ? ret : -EINVAL; @@ -952,7 +952,7 @@ static int __init hp_wmi_rfkill2_setup(struct platform_device *device) int err, i; err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state, - sizeof(state), sizeof(state)); + 0, sizeof(state)); if (err) return err < 0 ? err : -EINVAL; -- 2.25.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v5 3/4] Fix 0x05 error code reported by several WMI calls 2022-03-10 21:08 ` [PATCH v5 3/4] Fix 0x05 error code reported by several WMI calls Jorge Lopez @ 2022-03-14 10:44 ` Hans de Goede 0 siblings, 0 replies; 13+ messages in thread From: Hans de Goede @ 2022-03-14 10:44 UTC (permalink / raw) To: Jorge Lopez, platform-driver-x86 Hi, On 3/10/22 22:08, Jorge Lopez wrote: > Several WMI queries leverage hp_wmi_read_int function to read their > data. hp_wmi_read_int function was corrected in a previous patch. > Now, this function invokes hp_wmi_perform_query with input parameter > of size zero and the output buffer of size 4. > > WMI commands calling hp_wmi_perform_query with input buffer size value > of zero are listed below. > > HPWMI_DISPLAY_QUERY > HPWMI_HDDTEMP_QUERY > HPWMI_ALS_QUERY > HPWMI_HARDWARE_QUERY > HPWMI_WIRELESS_QUERY > HPWMI_BIOS_QUERY > HPWMI_FEATURE_QUERY > HPWMI_HOTKEY_QUERY > HPWMI_FEATURE2_QUERY > HPWMI_WIRELESS2_QUERY > HPWMI_POSTCODEERROR_QUERY > HPWMI_THERMAL_PROFILE_QUERY > HPWMI_FAN_SPEED_MAX_GET_QUERY > > Invoking those WMI commands with an input buffer size greater > than zero will cause error 0x05 to be returned. > > All WMI commands executed by the driver were reviewed and changes > were made to ensure the expected input and output buffer size match > the WMI specification. > > Changes were validated on a HP ZBook Workstation notebook, > HP EliteBook x360, and HP EliteBook 850 G8. Additional > validation was included in the test process to ensure no other > commands were incorrectly handled. > > Signed-off-by: Jorge Lopez <jorge.lopez2@hp.com> Thank you for your patch, I've applied this patch to my review-hans branch: https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans Note it will show up in my review-hans branch once I've pushed my local branch there, which might take a while. Once I've run some tests on this branch the patches there will be added to the platform-drivers-x86/for-next branch and eventually will be included in the pdx86 pull-request to Linus for the next merge-window. Regards, Hans > > --- > Based on the latest platform-drivers-x86.git/for-next > --- > drivers/platform/x86/hp-wmi.c | 22 +++++++++++----------- > 1 file changed, 11 insertions(+), 11 deletions(-) > > diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c > index e9aa05c26a40..e76bd4bef6b5 100644 > --- a/drivers/platform/x86/hp-wmi.c > +++ b/drivers/platform/x86/hp-wmi.c > @@ -329,7 +329,7 @@ static int hp_wmi_get_fan_speed(int fan) > char fan_data[4] = { fan, 0, 0, 0 }; > > int ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_GET_QUERY, HPWMI_GM, > - &fan_data, sizeof(fan_data), > + &fan_data, sizeof(char), > sizeof(fan_data)); > > if (ret != 0) > @@ -399,7 +399,7 @@ static int omen_thermal_profile_set(int mode) > return -EINVAL; > > ret = hp_wmi_perform_query(HPWMI_SET_PERFORMANCE_MODE, HPWMI_GM, > - &buffer, sizeof(buffer), sizeof(buffer)); > + &buffer, sizeof(buffer), 0); > > if (ret) > return ret < 0 ? ret : -EINVAL; > @@ -436,7 +436,7 @@ static int hp_wmi_fan_speed_max_set(int enabled) > int ret; > > ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_MAX_SET_QUERY, HPWMI_GM, > - &enabled, sizeof(enabled), sizeof(enabled)); > + &enabled, sizeof(enabled), 0); > > if (ret) > return ret < 0 ? ret : -EINVAL; > @@ -449,7 +449,7 @@ static int hp_wmi_fan_speed_max_get(void) > int val = 0, ret; > > ret = hp_wmi_perform_query(HPWMI_FAN_SPEED_MAX_GET_QUERY, HPWMI_GM, > - &val, sizeof(val), sizeof(val)); > + &val, 0, sizeof(val)); > > if (ret) > return ret < 0 ? ret : -EINVAL; > @@ -461,7 +461,7 @@ static int __init hp_wmi_bios_2008_later(void) > { > int state = 0; > int ret = hp_wmi_perform_query(HPWMI_FEATURE_QUERY, HPWMI_READ, &state, > - sizeof(state), sizeof(state)); > + 0, sizeof(state)); > if (!ret) > return 1; > > @@ -472,7 +472,7 @@ static int __init hp_wmi_bios_2009_later(void) > { > u8 state[128]; > int ret = hp_wmi_perform_query(HPWMI_FEATURE2_QUERY, HPWMI_READ, &state, > - sizeof(state), sizeof(state)); > + 0, sizeof(state)); > if (!ret) > return 1; > > @@ -550,7 +550,7 @@ static int hp_wmi_rfkill2_refresh(void) > int err, i; > > err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state, > - sizeof(state), sizeof(state)); > + 0, sizeof(state)); > if (err) > return err; > > @@ -639,7 +639,7 @@ static ssize_t als_store(struct device *dev, struct device_attribute *attr, > return ret; > > ret = hp_wmi_perform_query(HPWMI_ALS_QUERY, HPWMI_WRITE, &tmp, > - sizeof(tmp), sizeof(tmp)); > + sizeof(tmp), 0); > if (ret) > return ret < 0 ? ret : -EINVAL; > > @@ -660,9 +660,9 @@ static ssize_t postcode_store(struct device *dev, struct device_attribute *attr, > if (clear == false) > return -EINVAL; > > - /* Clear the POST error code. It is kept until until cleared. */ > + /* Clear the POST error code. It is kept until cleared. */ > ret = hp_wmi_perform_query(HPWMI_POSTCODEERROR_QUERY, HPWMI_WRITE, &tmp, > - sizeof(tmp), sizeof(tmp)); > + sizeof(tmp), 0); > if (ret) > return ret < 0 ? ret : -EINVAL; > > @@ -952,7 +952,7 @@ static int __init hp_wmi_rfkill2_setup(struct platform_device *device) > int err, i; > > err = hp_wmi_perform_query(HPWMI_WIRELESS2_QUERY, HPWMI_READ, &state, > - sizeof(state), sizeof(state)); > + 0, sizeof(state)); > if (err) > return err < 0 ? err : -EINVAL; > ^ permalink raw reply [flat|nested] 13+ messages in thread
* [PATCH v5 4/4] Changing bios_args.data to be dynamically allocated 2022-03-10 21:08 [PATCH v5 0/4] Fix SW_TABLET_MODE detection method Jorge Lopez ` (2 preceding siblings ...) 2022-03-10 21:08 ` [PATCH v5 3/4] Fix 0x05 error code reported by several WMI calls Jorge Lopez @ 2022-03-10 21:08 ` Jorge Lopez 2022-03-14 10:51 ` Hans de Goede 3 siblings, 1 reply; 13+ messages in thread From: Jorge Lopez @ 2022-03-10 21:08 UTC (permalink / raw) To: platform-driver-x86 The purpose of this patch is to remove 128 bytes buffer limitation imposed in bios_args structure. A limiting factor discovered during this investigation was the struct bios_args.data size restriction. The data member size limits all possible WMI commands to those requiring buffer size of 128 bytes or less. Several WMI commands and queries require a buffer size larger than 128 bytes hence limiting current and feature supported by the driver. It is for this reason, struct bios_args.data changed and is dynamically allocated. hp_wmi_perform_query function changed to handle the memory allocation and release of any required buffer size. All changes were validated on a HP ZBook Workstation notebook, HP EliteBook x360, and HP EliteBook 850 G8. Additional validation was included in the test process to ensure no other commands were incorrectly handled. Signed-off-by: Jorge Lopez <jorge.lopez2@hp.com> --- Based on the latest platform-drivers-x86.git/for-next --- drivers/platform/x86/hp-wmi.c | 64 +++++++++++++++++++++++------------ 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index e76bd4bef6b5..cc5c4f637328 100644 --- a/drivers/platform/x86/hp-wmi.c +++ b/drivers/platform/x86/hp-wmi.c @@ -82,12 +82,17 @@ enum hp_wmi_event_ids { HPWMI_BATTERY_CHARGE_PERIOD = 0x10, }; +/** + * struct bios_args buffer is dynamically allocated. New WMI command types + * were introduced that exceeds 128-byte data size. Changes to handle + * the data size allocation scheme were kept in hp_wmi_perform_qurey function. + */ struct bios_args { u32 signature; u32 command; u32 commandtype; u32 datasize; - u8 data[128]; + u8 data[]; }; enum hp_wmi_commandtype { @@ -268,34 +273,40 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, int mid; struct bios_return *bios_return; int actual_outsize; - union acpi_object *obj; - struct bios_args args = { - .signature = 0x55434553, - .command = command, - .commandtype = query, - .datasize = insize, - .data = { 0 }, - }; - struct acpi_buffer input = { sizeof(struct bios_args), &args }; + union acpi_object *obj = NULL; + struct bios_args *args = NULL; + size_t bios_args_size = struct_size(args, data, insize); + + struct acpi_buffer input; struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; int ret = 0; - mid = encode_outsize_for_pvsz(outsize); - if (WARN_ON(mid < 0)) - return mid; + args = kmalloc(bios_args_size, GFP_KERNEL); + if (!args) + return -ENOMEM; - if (WARN_ON(insize > sizeof(args.data))) - return -EINVAL; - memcpy(&args.data[0], buffer, insize); + input.length = bios_args_size; + input.pointer = args; - wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); + mid = encode_outsize_for_pvsz(outsize); + if (WARN_ON(mid < 0)) { + ret = mid; + goto out_free; + } - obj = output.pointer; + memcpy(args->data, buffer, flex_array_size(args, data, insize)); - if (!obj) - return -EINVAL; + args->signature = 0x55434553; + args->command = command; + args->commandtype = query; + args->datasize = insize; - if (obj->type != ACPI_TYPE_BUFFER) { + ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); + if (ret) + goto out_free; + + obj = output.pointer; + if (!obj) { ret = -EINVAL; goto out_free; } @@ -310,9 +321,17 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, goto out_free; } + if (obj->type != ACPI_TYPE_BUFFER) { + pr_warn("query 0x%x returned an invalid object 0x%x\n", query, ret); + ret = -EINVAL; + goto out_free; + } + /* Ignore output data of zero size */ - if (!outsize) + if (!outsize) { + ret = 0; goto out_free; + } actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return))); memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize); @@ -320,6 +339,7 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, out_free: kfree(obj); + kfree(args); return ret; } -- 2.25.1 ^ permalink raw reply related [flat|nested] 13+ messages in thread
* Re: [PATCH v5 4/4] Changing bios_args.data to be dynamically allocated 2022-03-10 21:08 ` [PATCH v5 4/4] Changing bios_args.data to be dynamically allocated Jorge Lopez @ 2022-03-14 10:51 ` Hans de Goede 2022-03-14 11:33 ` Hans de Goede 0 siblings, 1 reply; 13+ messages in thread From: Hans de Goede @ 2022-03-14 10:51 UTC (permalink / raw) To: Jorge Lopez, platform-driver-x86 Hi, On 3/10/22 22:08, Jorge Lopez wrote: > The purpose of this patch is to remove 128 bytes buffer limitation > imposed in bios_args structure. > > A limiting factor discovered during this investigation was the struct > bios_args.data size restriction. The data member size limits all > possible WMI commands to those requiring buffer size of 128 bytes or > less. Several WMI commands and queries require a buffer size larger > than 128 bytes hence limiting current and feature supported by the > driver. It is for this reason, struct bios_args.data changed and is > dynamically allocated. hp_wmi_perform_query function changed to > handle the memory allocation and release of any required buffer size. > > All changes were validated on a HP ZBook Workstation notebook, > HP EliteBook x360, and HP EliteBook 850 G8. Additional > validation was included in the test process to ensure no other > commands were incorrectly handled. > > Signed-off-by: Jorge Lopez <jorge.lopez2@hp.com> > > --- > Based on the latest platform-drivers-x86.git/for-next > --- > drivers/platform/x86/hp-wmi.c | 64 +++++++++++++++++++++++------------ > 1 file changed, 42 insertions(+), 22 deletions(-) > > diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c > index e76bd4bef6b5..cc5c4f637328 100644 > --- a/drivers/platform/x86/hp-wmi.c > +++ b/drivers/platform/x86/hp-wmi.c > @@ -82,12 +82,17 @@ enum hp_wmi_event_ids { > HPWMI_BATTERY_CHARGE_PERIOD = 0x10, > }; > > +/** > + * struct bios_args buffer is dynamically allocated. New WMI command types > + * were introduced that exceeds 128-byte data size. Changes to handle > + * the data size allocation scheme were kept in hp_wmi_perform_qurey function. > + */ > struct bios_args { > u32 signature; > u32 command; > u32 commandtype; > u32 datasize; > - u8 data[128]; > + u8 data[]; > }; > > enum hp_wmi_commandtype { > @@ -268,34 +273,40 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, > int mid; > struct bios_return *bios_return; > int actual_outsize; > - union acpi_object *obj; > - struct bios_args args = { > - .signature = 0x55434553, > - .command = command, > - .commandtype = query, > - .datasize = insize, > - .data = { 0 }, > - }; > - struct acpi_buffer input = { sizeof(struct bios_args), &args }; > + union acpi_object *obj = NULL; > + struct bios_args *args = NULL; > + size_t bios_args_size = struct_size(args, data, insize); > + > + struct acpi_buffer input; > struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; > int ret = 0; > > - mid = encode_outsize_for_pvsz(outsize); > - if (WARN_ON(mid < 0)) > - return mid; > + args = kmalloc(bios_args_size, GFP_KERNEL); > + if (!args) > + return -ENOMEM; The variable declaration here again looks a bit messy, also there is no reason to move the block setting + checking mid, that just makes the diff unnecessarily large. I've cleaned this up while mergin (no functional changes). > > - if (WARN_ON(insize > sizeof(args.data))) > - return -EINVAL; > - memcpy(&args.data[0], buffer, insize); > + input.length = bios_args_size; > + input.pointer = args; > > - wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); > + mid = encode_outsize_for_pvsz(outsize); > + if (WARN_ON(mid < 0)) { > + ret = mid; > + goto out_free; > + } > > - obj = output.pointer; > + memcpy(args->data, buffer, flex_array_size(args, data, insize)); > > - if (!obj) > - return -EINVAL; > + args->signature = 0x55434553; > + args->command = command; > + args->commandtype = query; > + args->datasize = insize; > > - if (obj->type != ACPI_TYPE_BUFFER) { > + ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); > + if (ret) > + goto out_free; > + > + obj = output.pointer; > + if (!obj) { > ret = -EINVAL; > goto out_free; > } > @@ -310,9 +321,17 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, > goto out_free; > } > > + if (obj->type != ACPI_TYPE_BUFFER) { > + pr_warn("query 0x%x returned an invalid object 0x%x\n", query, ret); > + ret = -EINVAL; > + goto out_free; > + } > + You have now moved the obj->type != ACPI_TYPE_BUFFER check to after the: bios_return = (struct bios_return *)obj->buffer.pointer; Statement, which dereferences the buffer member of the obj union. That check MUST be done before looking at the buffer member, so I have moved it back to its old place, this also makes the diff/patch smaller. Note this one is a functional change to your patch. The changed initial block of the function now looks like this: static int hp_wmi_perform_query(int query, enum hp_wmi_command command, void *buffer, int insize, int outsize) { struct acpi_buffer input, output = { ACPI_ALLOCATE_BUFFER, NULL }; size_t bios_args_size = struct_size(args, data, insize); struct bios_return *bios_return; union acpi_object *obj = NULL; struct bios_args *args = NULL; int mid, actual_outsize, ret; mid = encode_outsize_for_pvsz(outsize); if (WARN_ON(mid < 0)) return mid; args = kmalloc(bios_args_size, GFP_KERNEL); if (!args) return -ENOMEM; input.length = bios_args_size; input.pointer = args; args->signature = 0x55434553; args->command = command; args->commandtype = query; args->datasize = insize; memcpy(args->data, buffer, flex_array_size(args, data, insize)); ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); if (ret) goto out_free; obj = output.pointer; if (!obj) { ret = -EINVAL; goto out_free; } if (obj->type != ACPI_TYPE_BUFFER) { pr_warn("query 0x%x returned an invalid object 0x%x\n", query, ret); ret = -EINVAL; goto out_free; } bios_return = (struct bios_return *)obj->buffer.pointer; And the new diff for this chunk of the patch now is: @@ -266,37 +271,42 @@ static inline int encode_outsize_for_pvsz(int outsize) static int hp_wmi_perform_query(int query, enum hp_wmi_command command, void *buffer, int insize, int outsize) { - int mid; + struct acpi_buffer input, output = { ACPI_ALLOCATE_BUFFER, NULL }; + size_t bios_args_size = struct_size(args, data, insize); struct bios_return *bios_return; - int actual_outsize; - union acpi_object *obj; - struct bios_args args = { - .signature = 0x55434553, - .command = command, - .commandtype = query, - .datasize = insize, - .data = { 0 }, - }; - struct acpi_buffer input = { sizeof(struct bios_args), &args }; - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; - int ret = 0; + union acpi_object *obj = NULL; + struct bios_args *args = NULL; + int mid, actual_outsize, ret; mid = encode_outsize_for_pvsz(outsize); if (WARN_ON(mid < 0)) return mid; - if (WARN_ON(insize > sizeof(args.data))) - return -EINVAL; - memcpy(&args.data[0], buffer, insize); + args = kmalloc(bios_args_size, GFP_KERNEL); + if (!args) + return -ENOMEM; - wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); + input.length = bios_args_size; + input.pointer = args; - obj = output.pointer; + args->signature = 0x55434553; + args->command = command; + args->commandtype = query; + args->datasize = insize; + memcpy(args->data, buffer, flex_array_size(args, data, insize)); - if (!obj) - return -EINVAL; + ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); + if (ret) + goto out_free; + + obj = output.pointer; + if (!obj) { + ret = -EINVAL; + goto out_free; + } if (obj->type != ACPI_TYPE_BUFFER) { + pr_warn("query 0x%x returned an invalid object 0x%x\n", query, ret); ret = -EINVAL; goto out_free; } @@ ... I've merged this patch with the above changes: Thank you for your patch, I've applied this patch to my review-hans branch: https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans Note it will show up in my review-hans branch once I've pushed my local branch there, which might take a while. Once I've run some tests on this branch the patches there will be added to the platform-drivers-x86/for-next branch and eventually will be included in the pdx86 pull-request to Linus for the next merge-window. Regards, Hans > /* Ignore output data of zero size */ > - if (!outsize) > + if (!outsize) { > + ret = 0; > goto out_free; > + } > > actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return))); > memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize); > @@ -320,6 +339,7 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, > > out_free: > kfree(obj); > + kfree(args); > return ret; > } > ^ permalink raw reply [flat|nested] 13+ messages in thread
* Re: [PATCH v5 4/4] Changing bios_args.data to be dynamically allocated 2022-03-14 10:51 ` Hans de Goede @ 2022-03-14 11:33 ` Hans de Goede 0 siblings, 0 replies; 13+ messages in thread From: Hans de Goede @ 2022-03-14 11:33 UTC (permalink / raw) To: Jorge Lopez, platform-driver-x86 Hi, On 3/14/22 11:51, Hans de Goede wrote: > Hi, > > On 3/10/22 22:08, Jorge Lopez wrote: >> The purpose of this patch is to remove 128 bytes buffer limitation >> imposed in bios_args structure. >> >> A limiting factor discovered during this investigation was the struct >> bios_args.data size restriction. The data member size limits all >> possible WMI commands to those requiring buffer size of 128 bytes or >> less. Several WMI commands and queries require a buffer size larger >> than 128 bytes hence limiting current and feature supported by the >> driver. It is for this reason, struct bios_args.data changed and is >> dynamically allocated. hp_wmi_perform_query function changed to >> handle the memory allocation and release of any required buffer size. >> >> All changes were validated on a HP ZBook Workstation notebook, >> HP EliteBook x360, and HP EliteBook 850 G8. Additional >> validation was included in the test process to ensure no other >> commands were incorrectly handled. >> >> Signed-off-by: Jorge Lopez <jorge.lopez2@hp.com> >> >> --- >> Based on the latest platform-drivers-x86.git/for-next >> --- >> drivers/platform/x86/hp-wmi.c | 64 +++++++++++++++++++++++------------ >> 1 file changed, 42 insertions(+), 22 deletions(-) >> >> diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c >> index e76bd4bef6b5..cc5c4f637328 100644 >> --- a/drivers/platform/x86/hp-wmi.c >> +++ b/drivers/platform/x86/hp-wmi.c >> @@ -82,12 +82,17 @@ enum hp_wmi_event_ids { >> HPWMI_BATTERY_CHARGE_PERIOD = 0x10, >> }; >> >> +/** >> + * struct bios_args buffer is dynamically allocated. New WMI command types >> + * were introduced that exceeds 128-byte data size. Changes to handle >> + * the data size allocation scheme were kept in hp_wmi_perform_qurey function. >> + */ >> struct bios_args { >> u32 signature; >> u32 command; >> u32 commandtype; >> u32 datasize; >> - u8 data[128]; >> + u8 data[]; >> }; >> >> enum hp_wmi_commandtype { >> @@ -268,34 +273,40 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, >> int mid; >> struct bios_return *bios_return; >> int actual_outsize; >> - union acpi_object *obj; >> - struct bios_args args = { >> - .signature = 0x55434553, >> - .command = command, >> - .commandtype = query, >> - .datasize = insize, >> - .data = { 0 }, >> - }; >> - struct acpi_buffer input = { sizeof(struct bios_args), &args }; >> + union acpi_object *obj = NULL; >> + struct bios_args *args = NULL; >> + size_t bios_args_size = struct_size(args, data, insize); >> + >> + struct acpi_buffer input; >> struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; >> int ret = 0; >> >> - mid = encode_outsize_for_pvsz(outsize); >> - if (WARN_ON(mid < 0)) >> - return mid; >> + args = kmalloc(bios_args_size, GFP_KERNEL); >> + if (!args) >> + return -ENOMEM; > > The variable declaration here again looks a bit messy, also > there is no reason to move the block setting + checking mid, > that just makes the diff unnecessarily large. > > I've cleaned this up while mergin (no functional changes). > > >> >> - if (WARN_ON(insize > sizeof(args.data))) >> - return -EINVAL; >> - memcpy(&args.data[0], buffer, insize); >> + input.length = bios_args_size; >> + input.pointer = args; >> >> - wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); >> + mid = encode_outsize_for_pvsz(outsize); >> + if (WARN_ON(mid < 0)) { >> + ret = mid; >> + goto out_free; >> + } >> >> - obj = output.pointer; >> + memcpy(args->data, buffer, flex_array_size(args, data, insize)); >> >> - if (!obj) >> - return -EINVAL; >> + args->signature = 0x55434553; >> + args->command = command; >> + args->commandtype = query; >> + args->datasize = insize; >> >> - if (obj->type != ACPI_TYPE_BUFFER) { >> + ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); >> + if (ret) >> + goto out_free; >> + >> + obj = output.pointer; >> + if (!obj) { >> ret = -EINVAL; >> goto out_free; >> } >> @@ -310,9 +321,17 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, >> goto out_free; >> } >> >> + if (obj->type != ACPI_TYPE_BUFFER) { >> + pr_warn("query 0x%x returned an invalid object 0x%x\n", query, ret); >> + ret = -EINVAL; >> + goto out_free; >> + } >> + > > You have now moved the obj->type != ACPI_TYPE_BUFFER check to after the: > > bios_return = (struct bios_return *)obj->buffer.pointer; > > Statement, which dereferences the buffer member of the obj union. That check > MUST be done before looking at the buffer member, so I have moved it back to > its old place, this also makes the diff/patch smaller. Note this one is > a functional change to your patch. > > The changed initial block of the function now looks like this: > > static int hp_wmi_perform_query(int query, enum hp_wmi_command command, > void *buffer, int insize, int outsize) > { > struct acpi_buffer input, output = { ACPI_ALLOCATE_BUFFER, NULL }; > size_t bios_args_size = struct_size(args, data, insize); Ahum, there is a compile error here because args is not declared yet, so the final version looks slightly different, see: https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/commit/?h=review-hans&id=9f7e383ebdee6712bee02e3a6c2027cf287950fc Regards, Hans > struct bios_return *bios_return; > union acpi_object *obj = NULL; > struct bios_args *args = NULL; > int mid, actual_outsize, ret; > > mid = encode_outsize_for_pvsz(outsize); > if (WARN_ON(mid < 0)) > return mid; > > args = kmalloc(bios_args_size, GFP_KERNEL); > if (!args) > return -ENOMEM; > > input.length = bios_args_size; > input.pointer = args; > > args->signature = 0x55434553; > args->command = command; > args->commandtype = query; > args->datasize = insize; > memcpy(args->data, buffer, flex_array_size(args, data, insize)); > > ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); > if (ret) > goto out_free; > > obj = output.pointer; > if (!obj) { > ret = -EINVAL; > goto out_free; > } > > if (obj->type != ACPI_TYPE_BUFFER) { > pr_warn("query 0x%x returned an invalid object 0x%x\n", query, ret); > ret = -EINVAL; > goto out_free; > } > > bios_return = (struct bios_return *)obj->buffer.pointer; > > > And the new diff for this chunk of the patch now is: > > @@ -266,37 +271,42 @@ static inline int encode_outsize_for_pvsz(int outsize) > static int hp_wmi_perform_query(int query, enum hp_wmi_command command, > void *buffer, int insize, int outsize) > { > - int mid; > + struct acpi_buffer input, output = { ACPI_ALLOCATE_BUFFER, NULL }; > + size_t bios_args_size = struct_size(args, data, insize); > struct bios_return *bios_return; > - int actual_outsize; > - union acpi_object *obj; > - struct bios_args args = { > - .signature = 0x55434553, > - .command = command, > - .commandtype = query, > - .datasize = insize, > - .data = { 0 }, > - }; > - struct acpi_buffer input = { sizeof(struct bios_args), &args }; > - struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; > - int ret = 0; > + union acpi_object *obj = NULL; > + struct bios_args *args = NULL; > + int mid, actual_outsize, ret; > > mid = encode_outsize_for_pvsz(outsize); > if (WARN_ON(mid < 0)) > return mid; > > - if (WARN_ON(insize > sizeof(args.data))) > - return -EINVAL; > - memcpy(&args.data[0], buffer, insize); > + args = kmalloc(bios_args_size, GFP_KERNEL); > + if (!args) > + return -ENOMEM; > > - wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); > + input.length = bios_args_size; > + input.pointer = args; > > - obj = output.pointer; > + args->signature = 0x55434553; > + args->command = command; > + args->commandtype = query; > + args->datasize = insize; > + memcpy(args->data, buffer, flex_array_size(args, data, insize)); > > - if (!obj) > - return -EINVAL; > + ret = wmi_evaluate_method(HPWMI_BIOS_GUID, 0, mid, &input, &output); > + if (ret) > + goto out_free; > + > + obj = output.pointer; > + if (!obj) { > + ret = -EINVAL; > + goto out_free; > + } > > if (obj->type != ACPI_TYPE_BUFFER) { > + pr_warn("query 0x%x returned an invalid object 0x%x\n", query, ret); > ret = -EINVAL; > goto out_free; > } > @@ ... > > I've merged this patch with the above changes: > > Thank you for your patch, I've applied this patch to my review-hans > branch: > https://git.kernel.org/pub/scm/linux/kernel/git/pdx86/platform-drivers-x86.git/log/?h=review-hans > > Note it will show up in my review-hans branch once I've pushed my > local branch there, which might take a while. > > Once I've run some tests on this branch the patches there will be > added to the platform-drivers-x86/for-next branch and eventually > will be included in the pdx86 pull-request to Linus for the next > merge-window. > > Regards, > > Hans > > > > > > > > >> /* Ignore output data of zero size */ >> - if (!outsize) >> + if (!outsize) { >> + ret = 0; >> goto out_free; >> + } >> >> actual_outsize = min(outsize, (int)(obj->buffer.length - sizeof(*bios_return))); >> memcpy(buffer, obj->buffer.pointer + sizeof(*bios_return), actual_outsize); >> @@ -320,6 +339,7 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, >> >> out_free: >> kfree(obj); >> + kfree(args); >> return ret; >> } >> > > ^ permalink raw reply [flat|nested] 13+ messages in thread
end of thread, other threads:[~2024-08-19 16:47 UTC | newest] Thread overview: 13+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2022-03-10 21:08 [PATCH v5 0/4] Fix SW_TABLET_MODE detection method Jorge Lopez 2022-03-10 21:08 ` [PATCH v5 1/4] Fix hp_wmi_read_int() reporting error (0x05) Jorge Lopez 2022-03-14 10:41 ` Hans de Goede 2022-03-10 21:08 ` [PATCH v5 2/4] Fix SW_TABLET_MODE detection method Jorge Lopez 2022-03-14 10:44 ` Hans de Goede 2024-08-08 21:46 ` Stefan Sichler 2024-08-13 14:34 ` Ilpo Järvinen 2024-08-19 16:41 ` Stefan Sichler 2022-03-10 21:08 ` [PATCH v5 3/4] Fix 0x05 error code reported by several WMI calls Jorge Lopez 2022-03-14 10:44 ` Hans de Goede 2022-03-10 21:08 ` [PATCH v5 4/4] Changing bios_args.data to be dynamically allocated Jorge Lopez 2022-03-14 10:51 ` Hans de Goede 2022-03-14 11:33 ` Hans de Goede
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox