From patchwork Tue Feb 15 23:30:07 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Lopez, Jorge A (Security)" X-Patchwork-Id: 12747709 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 49B18C433F5 for ; Tue, 15 Feb 2022 23:31:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243780AbiBOXba (ORCPT ); Tue, 15 Feb 2022 18:31:30 -0500 Received: from mxb-00190b01.gslb.pphosted.com ([23.128.96.19]:35548 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S241137AbiBOXb3 (ORCPT ); Tue, 15 Feb 2022 18:31:29 -0500 X-Greylist: delayed 64 seconds by postgrey-1.37 at lindbergh.monkeyblade.net; Tue, 15 Feb 2022 15:31:16 PST Received: from us-smtp-delivery-162.mimecast.com (us-smtp-delivery-162.mimecast.com [170.10.133.162]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id D1972F94EF for ; Tue, 15 Feb 2022 15:31:16 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=hp.com; s=mimecast20180716; t=1644967875; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=JH4DcdlXdKh0tEFIxGFe5z2Axy/b5pOoBhxo8CG4QtQ=; b=BLBg5dC4rHsPPXL20sNZvNkAnlnK0IYVzG0TaCSvWAn1BcTloRaKQpK/+im6i8FVdRO27/ ZlbTXj/TFeuM0gGZV9HkfWK9AoU810EasVLzFfdTdAWaFon1ITe44oA/p9YG0+zIZ92zaT 9qjzZXrQxqB//44u6trjhyhnS53wb/A= Received: from NAM11-BN8-obe.outbound.protection.outlook.com (mail-bn8nam11lp2176.outbound.protection.outlook.com [104.47.58.176]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-272-dzPpyQKIM7Cj5QsZTYL90Q-1; Tue, 15 Feb 2022 18:30:09 -0500 X-MC-Unique: dzPpyQKIM7Cj5QsZTYL90Q-1 Received: from PH0PR84MB1953.NAMPRD84.PROD.OUTLOOK.COM (2603:10b6:510:160::10) by MW5PR84MB1820.NAMPRD84.PROD.OUTLOOK.COM (2603:10b6:303:1c6::18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4951.18; Tue, 15 Feb 2022 23:30:08 +0000 Received: from PH0PR84MB1953.NAMPRD84.PROD.OUTLOOK.COM ([fe80::d4a1:2073:e2e4:f381]) by PH0PR84MB1953.NAMPRD84.PROD.OUTLOOK.COM ([fe80::d4a1:2073:e2e4:f381%5]) with mapi id 15.20.4975.019; Tue, 15 Feb 2022 23:30:08 +0000 From: "Lopez, Jorge A (Thin Clients)" To: "platform-driver-x86@vger.kernel.org" Subject: [PATCH] Fix SW_TABLET_MODE detection method Thread-Topic: [PATCH] Fix SW_TABLET_MODE detection method Thread-Index: Adgiw/Z47mhT1PhhR0+Ea9GWRYkByg== Date: Tue, 15 Feb 2022 23:30:07 +0000 Message-ID: Accept-Language: en-US X-MS-Has-Attach: X-MS-TNEF-Correlator: x-bromium-msgid: abc4664a-3d48-4301-90a7-4f22abbcb809 x-ms-publictraffictype: Email x-ms-office365-filtering-correlation-id: 42108b8d-6d10-4475-2d2e-08d9f0db1a66 x-ms-traffictypediagnostic: MW5PR84MB1820:EE_ x-microsoft-antispam-prvs: x-ms-oob-tlc-oobclassifiers: OLM:7691 x-ms-exchange-senderadcheck: 1 x-ms-exchange-antispam-relay: 0 x-microsoft-antispam: BCL:0 x-microsoft-antispam-message-info: WE0NQ9S8lRrqgnZe6WrdR0D0n1kWFS163QAfDAKejo8xEMgSu9rrWbFA8ooDgcOXIRrdTm+0SEnDI19DDUzSNg+kzW8ubAN4bWUiuQzDNGhWuDIssArJq9Z4qbEpht64t7biNDbJGx/28Ykbkl/v5GDTAVfySKmTa5OuhFKPui11ocTt+cTeQuUr5XbVhdQAZDbpbxqob7rF5E1TTfJaq0jPpQinxjnql4og44fEHhthgJRSGUBYPoCMdfiYb2lHwGLmKF3X/fvpnn8lVUc5X8NIevo9NLGVzakhCmnngn5tHUhv0FQIeuhHoaOT3Z2ULP9vDzj3G8Qvk1RGQySsNwp9CnOwVP5n19ECfGP/awfblTdQeSmQVB6vYXtcMQcSqbh6gSCiBgeJvJgefz2hx1KqymhH7mxep7HYvlvSxIxCGl5wgInvnU+tEu8JNLGi7jdKKpsR8lu+Rc8/hAKJNmi7bo1akk5EMnw6VOPhyc57LW7ilzMLo/8eBV/fOskiOcDxzj6ogd0caLkfsVOp8loMeyB4z+TTkIO/brvsmsupM2Zyl5pr3H8Tc8PvX40W0bNabwWMiXYHVDcPip9nhtoHQq+EasIua57XYMLXT2AImuxsNizslfDTMJp6ndmiD/7NEif9voYU2LwXJ6qMO2UcieaLH79JpJDHRaicvoNqxdbnZiQDUSCeSxLgGSN76YGuZyZ46zFYtUNIjPcz8w== x-forefront-antispam-report: CIP:255.255.255.255;CTRY:;LANG:en;SCL:1;SRV:;IPV:NLI;SFV:NSPM;H:PH0PR84MB1953.NAMPRD84.PROD.OUTLOOK.COM;PTR:;CAT:NONE;SFS:(13230001)(366004)(66946007)(33656002)(6506007)(508600001)(38070700005)(2906002)(76116006)(6916009)(38100700002)(316002)(7696005)(9686003)(122000001)(66446008)(52536014)(83380400001)(86362001)(186003)(82960400001)(26005)(66476007)(8936002)(66556008)(5660300002)(53546011)(71200400001)(8676002)(55016003)(64756008);DIR:OUT;SFP:1102 x-ms-exchange-antispam-messagedata-chunkcount: 1 x-ms-exchange-antispam-messagedata-0: Ne/AbCI4hXkIAnV9SeI6Zm+IcBHwmV/WBbJ0lHlqo2x3/TmnuF4LEGZEwVxZHTlvvKUacoeEV9Zy5f+Fy/31XtGOHF0+vxJCwmKYVDaRiVd+xEuEkrMH1/5W4Zi+QXkIhxBg8JVkfh4yY31SxF3aK1JCjt5SG5lQSTtEJQf7XMe9GUknS3WO+p7qaCx1pNthTcIZBJGGNn+uUfMty1meuYO7EHpG08/u0Fl1jI6mHBZnLlM0XvdV/bsyHypEXXLL2yyVbuiT+ojJ/i1FKiQh1AlKDFQe+5wJJuGC6KWnq2jPJBG6+f+gWCB8otxBkms4+ubNYeUoY9tn24rI6XAvvb3Xl6wDHDLYssdS2AILLnUj/CuHulsdpldueGCybhXUxeDRU79WeD/78QFZm9Hf/6JKf4RXOIOwBA6hojyOjCXSFY1J15eLV+SGYe/t7YoWo7z0X24Nn79SRBTWcTOzN8IuPYRvrcIgoWKORSGAQLyktQmA8geW9QEP8KUV4v3cqK91tKRtLHf+Fo1oUlqtsPubt40HYZhoI/sN13pDdI3i+7zZLLhO1uXQmNPqe4I0EBusn38tatWpN+UiVAfPELxzGx/Pk1H/54l8h8dYprgOF3AoCpA3pZeSJurknE/XwmRluprj54c3T7tgXBCYSlCUNAuQr0IN7NgXSArViJgT5JkI4jnTQXWMhi+Ha0y2sK9mowTYKK9q6lFDuLQUb1kvQEnn8neCb4d9AQ6sksFT3U7Q0vVsI7d69Og47QvXN9Vcwqibsp3xePWtF+6WJvd6nsLE7/SsmRdCS22Bo1N0oAkNdJKMmnudHMEeva8FkLmnotqo+vO6aB+i+kYnidRqErdntwu5ptOR0IAORzTu2gOKkRAlhoi3zSdpbRQuU/gxiJ9rsXGguGUccLUNy2/DNCNfqpveSOUBAT8BsChmLvq89U3Lym/JIyAa4+iDfSaguf3fP3hjHl9dkKqC/bfChIUAX8uQUh+LL+ddIssbcur4ucxcJaZLFkstkZhww2S8xSijTJo0+39rVQMsyW7IG9rI9pYfEE5++c7Afnw91/KZnKWn/Tlq9IuujI9Za2AaXjB+SzsxNBWR+Kdeme2rBc5YjxSa5P1lKmYoqV/BnLygFC6Hc54ObHEKlSGBfF3MTPuy3Zq/JTRuNzb0V7NaNHgvfL1sZUDrD71n70fskLLF/L0pQwb7M09NF0KKF8dft/jKp24Zcao8BQ4exAym2H+M0DRCytyT172FdsE6Hun4DZD6YNzsZHxVPFn4jT966oSxpXDTQAlLhQfZ5xIyuKtcBdFfsSbkRY1CT6RbKJsfhCPnoRgKwzH+jURmHXoUDn/A/EpDzcmlchrfhSxZMmBCgvPn7ecpr5aHX72aTDiwvkDypdgHxi+nHNyf0RKGTYhzSNcveoZhAOLsj3tYQkiggo+ebMEni+005cYNwGeDJavVzo3Hw2UPUE01iwfj6IUxPer7j28RR/Y6tiQN3foP1q3W2ETCXGEJIDT4yBAAU7DVtvzRwEQZXQB0yab3Uz55rg7PuoDi3GDkE/7uaDp8L1NoNMB3HkRqQ3mnCirO2suDbnWtJg9k0xqhdMYEUA3NJib+OjXU/Z9a2A== MIME-Version: 1.0 X-OriginatorOrg: hp.com X-MS-Exchange-CrossTenant-AuthAs: Internal X-MS-Exchange-CrossTenant-AuthSource: PH0PR84MB1953.NAMPRD84.PROD.OUTLOOK.COM X-MS-Exchange-CrossTenant-Network-Message-Id: 42108b8d-6d10-4475-2d2e-08d9f0db1a66 X-MS-Exchange-CrossTenant-originalarrivaltime: 15 Feb 2022 23:30:07.9636 (UTC) X-MS-Exchange-CrossTenant-fromentityheader: Hosted X-MS-Exchange-CrossTenant-id: ca7981a2-785a-463d-b82a-3db87dfc3ce6 X-MS-Exchange-CrossTenant-mailboxtype: HOSTED X-MS-Exchange-CrossTenant-userprincipalname: QML04ScHGvDktnOI0nhwxQ5qb4WL5bUL1rAkIWwcmUfYckK8zQh9AmzCgrL7TZmuyG9uu+yY3gvboWpTwCTbGA== X-MS-Exchange-Transport-CrossTenantHeadersStamped: MW5PR84MB1820 Authentication-Results: relay.mimecast.com; auth=pass smtp.auth=CUSA62A171 smtp.mailfrom=jorge.lopez2@hp.com X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: hp.com Content-Language: en-US Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org From ca8e079fe91263edd79044c9a114f22d9f251987 Mon Sep 17 00:00:00 2001 From: Jorge Lopez Date: Tue, 15 Feb 2022 16:10:27 -0600 Subject: [PATCH] Fix SW_TABLET_MODE detection method To: platform-driver-x86@vger.kernel.org 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. Several WMI queries leverage hp_wmi_read_int function to read their data. hp_wmi_read_int function returns the appropiate value if the WMI command requires an input and output buffer size values greater than zero. WMI queries such HPWMI_HARDWARE_QUERY, HPWMI_WIRELESS2_QUERY, and HPWMI_FEATURE2_QUERY requires calling hp_wmi_perform_query function with input buffer size value of zero. Any input buffer size greater than zero will cause error 0x05 to be returned. 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 it is dynamically allocated. hp_wmi_perform_query function changed to handle the memory allocation and release of any required buffer size. All identified problems were resolved and their correct operation validated on a ZBook Workstation notebook. Additional validation was included to ensure no other commands were failing or incorrectly handled. --- drivers/platform/x86/hp-wmi.c | 122 ++++++++++++++++++++++------------ 1 file changed, 79 insertions(+), 43 deletions(-) diff --git a/drivers/platform/x86/hp-wmi.c b/drivers/platform/x86/hp-wmi.c index 48a46466f086..5320c1eb5cfc 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" @@ -86,12 +83,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[0]; }; enum hp_wmi_commandtype { @@ -127,6 +129,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 { @@ -260,39 +263,47 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, 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 }; + size_t bios_args_size = sizeof(struct bios_args) + insize; + struct bios_args *args = NULL; + 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 in_free; + } - obj = output.pointer; + /* Avoid unnecessary copy to the data buffer if input buffer size is zero */ + if (insize > 0) + memcpy(args->data, buffer, 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); + + obj = output.pointer; + if (!obj) { + pr_warn("query 0x%x returned a null obj 0x%x\n", query, ret); ret = -EINVAL; - goto out_free; + goto in_free; } - bios_return = (struct bios_return *)obj->buffer.pointer; - ret = bios_return->return_code; + if (!ret && obj->type == ACPI_TYPE_BUFFER) { + bios_return = (struct bios_return *)obj->buffer.pointer; + ret = bios_return->return_code; + } if (ret) { if (ret != HPWMI_RET_UNKNOWN_COMMAND && @@ -301,6 +312,12 @@ 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) goto out_free; @@ -311,6 +328,8 @@ static int hp_wmi_perform_query(int query, enum hp_wmi_command command, out_free: kfree(obj); +in_free: + kfree(args); return ret; } @@ -347,12 +366,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)); + + if (ret) + return ret < 0 ? ret : -EINVAL; - return !!(state & mask); + /* determine if Detachable mode is enabled */ + if (HPWMI_TABLET_MASK == mask) + state = (state & HPWMI_DETACHABLE_MASK ); + + return (state & mask); } static int omen_thermal_profile_set(int mode) @@ -437,7 +463,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; @@ -472,25 +498,37 @@ static const struct rfkill_ops hp_wmi_rfkill_ops = { static bool hp_wmi_get_sw_state(enum hp_wmi_radio r) { int mask = 0x200 << (r * 8); + int ret= 0; + int wireless = 0; - int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY); + ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_READ, &wireless, + 0, sizeof(wireless)); + + if (ret < 0) + return -EINVAL; /* TBD: Pass error */ WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY"); - return !(wireless & mask); + return (wireless & mask); } static bool hp_wmi_get_hw_state(enum hp_wmi_radio r) { int mask = 0x800 << (r * 8); + int ret= 0; + int wireless = 0; + + ret = hp_wmi_perform_query(HPWMI_WIRELESS_QUERY, HPWMI_READ, &wireless, + 0, sizeof(wireless)); - int wireless = hp_wmi_read_int(HPWMI_WIRELESS_QUERY); + if (ret < 0) + return -EINVAL; /* TBD: Pass error */ WARN_ONCE(wireless < 0, "error executing HPWMI_WIRELESS_QUERY"); - return !(wireless & mask); + return (wireless & mask); } static int hp_wmi_rfkill2_set_block(void *data, bool blocked) @@ -515,7 +553,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; @@ -781,18 +819,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); } /* 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); - } } err = sparse_keymap_setup(hp_wmi_input_dev, hp_wmi_keymap, NULL); @@ -919,7 +955,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;