From patchwork Sat May 27 05:31:22 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Darren Hart X-Patchwork-Id: 9751567 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 264286032C for ; Sat, 27 May 2017 05:35:43 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 173A3283C5 for ; Sat, 27 May 2017 05:35:43 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 0B5532846A; Sat, 27 May 2017 05:35:43 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 63023283C5 for ; Sat, 27 May 2017 05:35:42 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752206AbdE0FcJ (ORCPT ); Sat, 27 May 2017 01:32:09 -0400 Received: from bombadil.infradead.org ([65.50.211.133]:57802 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752118AbdE0Fbu (ORCPT ); Sat, 27 May 2017 01:31:50 -0400 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=bombadil.20170209; h=Content-Transfer-Encoding: Content-Type:MIME-Version:References:In-Reply-To:Message-Id:Date:Subject:Cc: To:From:Sender:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=OJXT9PJlVUx3XUJ4eLbnQu5N4pRW3bmF1+MFys2LshQ=; b=FrvxbOb1vmnpYaT7uT3WPqAEu sHXQxXVlfF1uD7dgs9OgjMJhq8+rIJbVvTdjOQ5MzrumDBVJ6Qynqv17QpRpyViipkg5+WITQ1Jau WszLYtiSYTaAvF7qwD0oU+GWqPFBDJNnCTbK0hiF32AoPpw+PC8c3i7wLj26Ns3fOGZAcrx4QiMUz CdXA6oo+FyDipiRQBacpuJDSMtnzbTFaVtp+jVfTnNLVzOpApDE4tA7VzWvG2N+KpOwlw0ZfQCYxX 44sHCAWVWHWDs1NhwMKayYjqgB/cE1Lf3V+dMt2CKlIg5GX86Yp6NhDQjZsJw8Z4cfVpNy4auY/7v IdXX5ObwQ==; Received: from dvhart by bombadil.infradead.org with local (Exim 4.87 #1 (Red Hat Linux)) id 1dEUKM-0000gw-6A; Sat, 27 May 2017 05:31:50 +0000 From: Darren Hart To: platform-driver-x86@vger.kernel.org Cc: Andy Shevchenko , Andy Lutomirski , Andy Lutomirski , Mario Limonciello , =?UTF-8?q?Pali=20Roh=C3=A1r?= , Rafael Wysocki , linux-kernel@vger.kernel.org, linux-acpi@vger.kernel.org, Darren Hart Subject: [PATCH 08/16] platform/x86: wmi: Probe data objects for read and write capabilities Date: Fri, 26 May 2017 22:31:22 -0700 Message-Id: <3c3b31274e397c0267ac0d173b94904003f8b603.1495862272.git.dvhart@infradead.org> X-Mailer: git-send-email 2.9.4 In-Reply-To: References: In-Reply-To: References: MIME-Version: 1.0 Sender: linux-acpi-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-acpi@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Andy Lutomirski The Dell XPS 13 9350 has one RW data object, one RO data object, and one totally inaccessible data object. Check for the existence of the accessor methods and report in sysfs. The docs also permit WQxx getters for single-instance objects to take no parameters. Probe for that as well to avoid ACPICA warnings about mismatched signatures. Signed-off-by: Andy Lutomirski Cc: Andy Lutomirski Cc: Mario Limonciello Cc: Pali Rohár Cc: Rafael Wysocki Cc: linux-kernel@vger.kernel.org Cc: platform-driver-x86@vger.kernel.org Cc: linux-acpi@vger.kernel.org Signed-off-by: Darren Hart (VMware) --- drivers/platform/x86/wmi.c | 101 +++++++++++++++++++++++++++++++++++++++++++-- include/linux/wmi.h | 6 +++ 2 files changed, 103 insertions(+), 4 deletions(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 33a3609..651693a 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -67,6 +67,8 @@ struct wmi_block { struct acpi_device *acpi_device; wmi_notify_handler handler; void *handler_data; + + bool read_takes_no_args; /* only defined if readable */ }; @@ -138,6 +140,30 @@ static bool find_guid(const char *guid_string, struct wmi_block **out) return false; } +static int get_subobj_info(acpi_handle handle, const char *pathname, + struct acpi_device_info **info) +{ + struct acpi_device_info *dummy_info, **info_ptr; + acpi_handle subobj_handle; + acpi_status status; + + status = acpi_get_handle(handle, (char *)pathname, &subobj_handle); + if (status == AE_NOT_FOUND) + return -ENOENT; + else if (ACPI_FAILURE(status)) + return -EIO; + + info_ptr = info ? info : &dummy_info; + status = acpi_get_object_info(subobj_handle, info_ptr); + if (ACPI_FAILURE(status)) + return -EIO; + + if (!info) + kfree(dummy_info); + + return 0; +} + static acpi_status wmi_method_enable(struct wmi_block *wblock, int enable) { struct guid_block *block = NULL; @@ -261,6 +287,9 @@ struct acpi_buffer *out) wq_params[0].type = ACPI_TYPE_INTEGER; wq_params[0].integer.value = instance; + if (instance == 0 && wblock->read_takes_no_args) + input.count = 0; + /* * If ACPI_WMI_EXPENSIVE, call the relevant WCxx method first to * enable collection. @@ -628,11 +657,37 @@ static ssize_t object_id_show(struct device *dev, struct device_attribute *attr, } static DEVICE_ATTR_RO(object_id); -static struct attribute *wmi_data_or_method_attrs[] = { +static ssize_t readable_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct wmi_device *wdev = dev_to_wdev(dev); + + return sprintf(buf, "%d\n", (int)wdev->readable); +} +static DEVICE_ATTR_RO(readable); + +static ssize_t writeable_show(struct device *dev, struct device_attribute *attr, + char *buf) +{ + struct wmi_device *wdev = dev_to_wdev(dev); + + return sprintf(buf, "%d\n", (int)wdev->writeable); +} +static DEVICE_ATTR_RO(writeable); + +static struct attribute *wmi_data_attrs[] = { + &dev_attr_object_id.attr, + &dev_attr_readable.attr, + &dev_attr_writeable.attr, + NULL, +}; +ATTRIBUTE_GROUPS(wmi_data); + +static struct attribute *wmi_method_attrs[] = { &dev_attr_object_id.attr, NULL, }; -ATTRIBUTE_GROUPS(wmi_data_or_method); +ATTRIBUTE_GROUPS(wmi_method); static int wmi_dev_uevent(struct device *dev, struct kobj_uevent_env *env) { @@ -731,13 +786,13 @@ static struct device_type wmi_type_event = { static struct device_type wmi_type_method = { .name = "method", - .groups = wmi_data_or_method_groups, + .groups = wmi_method_groups, .release = wmi_dev_release, }; static struct device_type wmi_type_data = { .name = "data", - .groups = wmi_data_or_method_groups, + .groups = wmi_data_groups, .release = wmi_dev_release, }; @@ -756,7 +811,45 @@ static int wmi_create_device(struct device *wmi_bus_dev, } else if (gblock->flags & ACPI_WMI_METHOD) { wblock->dev.dev.type = &wmi_type_method; } else { + struct acpi_device_info *info; + char method[5]; + int result; + wblock->dev.dev.type = &wmi_type_data; + + strcpy(method, "WQ"); + strncat(method, wblock->gblock.object_id, 2); + result = get_subobj_info(device->handle, method, &info); + + if (result == 0) { + wblock->dev.readable = true; + + /* + * The Microsoft documentation specifically states: + * + * Data blocks registered with only a single instance + * can ignore the parameter. + * + * ACPICA will get mad at us if we call the method + * with the wrong number of arguments, so check what + * our method expects. (On some Dell laptops, WQxx + * may not be a method at all.) + */ + if (info->type != ACPI_TYPE_METHOD || + info->param_count == 0) + wblock->read_takes_no_args = true; + + kfree(info); + } + + strcpy(method, "WS"); + strncat(method, wblock->gblock.object_id, 2); + result = get_subobj_info(device->handle, method, NULL); + + if (result == 0) { + wblock->dev.writeable = true; + } + } return device_register(&wblock->dev.dev); diff --git a/include/linux/wmi.h b/include/linux/wmi.h index 29ed34b..5309500 100644 --- a/include/linux/wmi.h +++ b/include/linux/wmi.h @@ -21,6 +21,12 @@ struct wmi_device { struct device dev; + + /* + * These are true for data objects that support reads and writes, + * respectively. + */ + bool readable, writeable; }; struct wmi_device_id {