From patchwork Sat May 27 05:31:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Darren Hart X-Patchwork-Id: 9751557 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 405546032C for ; Sat, 27 May 2017 05:35:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 3291A283C5 for ; Sat, 27 May 2017 05:35:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 275862846A; Sat, 27 May 2017 05:35:34 +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 A6540283C5 for ; Sat, 27 May 2017 05:35:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752220AbdE0FcL (ORCPT ); Sat, 27 May 2017 01:32:11 -0400 Received: from bombadil.infradead.org ([65.50.211.133]:46183 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752122AbdE0Fbx (ORCPT ); Sat, 27 May 2017 01:31:53 -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=4fsN/m/H3btyaN9wnO+M+v3Ry8DuMz/qyWWseFd9cgQ=; b=rPI56QOlHMJ8UOFQ1J9M2ffOt BNRKs7mAKlllTM6rygUyIwpKtwL/Eyr0Qi8sUPHkniwug0nIkpUioe/bfQBKzaioFixRj8QCbUSMp nf6za/tWV4VFzOTje8H8G+kWZlYoA9tGfe2EguuD555FzsUb3ghFlWsOonw6Pp/o5EGTuFNolkMdy fAfMT1ZhWvFPB5X+zykKAV6VodLX8feu6lYID2esfJuzbjWKNJQQOAPs45U69Nvp9TAsGrZC0r2Rt 6a4WgZ3J2mLwY8HWYD3hlWLZj6oVqdZbiP+iliaJC3qThX+OaniIB1CKDcVYGl+5FVKl6NcURIcOM j8JwmjCVA==; Received: from dvhart by bombadil.infradead.org with local (Exim 4.87 #1 (Red Hat Linux)) id 1dEUKO-0000iT-Tg; Sat, 27 May 2017 05:31:52 +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 10/16] platform/x86: wmi: Incorporate acpi_install_notify_handler Date: Fri, 26 May 2017 22:31:24 -0700 Message-Id: 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 As a platform driver, acpi_driver.notify will not be available, so use acpi_install_notify_handler as we will be converting to a platform driver. This gives event drivers a simple way to handle events. It also seems closer to what the Windows docs suggest that Windows does: it sounds like, in Windows, the mapper is responsible for called _WED before dispatching to the subdriver. Signed-off-by: Andy Lutomirski [dvhart: merge two development commits and update commit message] 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 | 89 +++++++++++++++++++++++++++++++++++++--------- include/linux/wmi.h | 1 + 2 files changed, 73 insertions(+), 17 deletions(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index bfc0a3f..208e187 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -93,7 +93,6 @@ MODULE_PARM_DESC(debug_dump_wdg, static int acpi_wmi_remove(struct acpi_device *device); static int acpi_wmi_add(struct acpi_device *device); -static void acpi_wmi_notify(struct acpi_device *device, u32 event); static const struct acpi_device_id wmi_device_ids[] = { {"PNP0C14", 0}, @@ -109,7 +108,6 @@ static struct acpi_driver acpi_wmi_driver = { .ops = { .add = acpi_wmi_add, .remove = acpi_wmi_remove, - .notify = acpi_wmi_notify, }, }; @@ -1023,36 +1021,80 @@ acpi_wmi_ec_space_handler(u32 function, acpi_physical_address address, } } -static void acpi_wmi_notify(struct acpi_device *device, u32 event) +static void acpi_wmi_notify_handler(acpi_handle handle, u32 event, + void *context) { struct guid_block *block; struct wmi_block *wblock; struct list_head *p; + bool found_it = false; list_for_each(p, &wmi_block_list) { wblock = list_entry(p, struct wmi_block, list); block = &wblock->gblock; - if (wblock->acpi_device == device && + if (wblock->acpi_device->handle == handle && (block->flags & ACPI_WMI_EVENT) && - (block->notify_id == event)) { - if (wblock->handler) - wblock->handler(event, wblock->handler_data); - if (debug_event) { - pr_info("DEBUG Event GUID: %pUL\n", - wblock->gblock.guid); - } - - acpi_bus_generate_netlink_event( - device->pnp.device_class, dev_name(&device->dev), - event, 0); + (block->notify_id == event)) + { + found_it = true; break; } } + + if (!found_it) + return; + + /* If a driver is bound, then notify the driver. */ + if (wblock->dev.dev.driver) { + struct wmi_driver *driver; + struct acpi_object_list input; + union acpi_object params[1]; + struct acpi_buffer evdata = { ACPI_ALLOCATE_BUFFER, NULL }; + acpi_status status; + + driver = container_of(wblock->dev.dev.driver, + struct wmi_driver, driver); + + input.count = 1; + input.pointer = params; + params[0].type = ACPI_TYPE_INTEGER; + params[0].integer.value = event; + + status = acpi_evaluate_object(wblock->acpi_device->handle, + "_WED", &input, &evdata); + if (ACPI_FAILURE(status)) { + dev_warn(&wblock->dev.dev, + "failed to get event data\n"); + return; + } + + if (driver->notify) + driver->notify(&wblock->dev, + (union acpi_object *)evdata.pointer); + + kfree(evdata.pointer); + } else if (wblock->handler) { + /* Legacy handler */ + wblock->handler(event, wblock->handler_data); + } + + if (debug_event) { + pr_info("DEBUG Event GUID: %pUL\n", + wblock->gblock.guid); + } + + acpi_bus_generate_netlink_event( + wblock->acpi_device->pnp.device_class, + dev_name(&wblock->dev.dev), + event, 0); + } static int acpi_wmi_remove(struct acpi_device *device) { + acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, + acpi_wmi_notify_handler); acpi_remove_address_space_handler(device->handle, ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler); wmi_free_devices(device); @@ -1077,11 +1119,20 @@ static int acpi_wmi_add(struct acpi_device *device) return -ENODEV; } + status = acpi_install_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, + acpi_wmi_notify_handler, + NULL); + if (ACPI_FAILURE(status)) { + dev_err(&device->dev, "Error installing notify handler\n"); + error = -ENODEV; + goto err_remove_ec_handler; + } + wmi_bus_dev = device_create(&wmi_bus_class, &device->dev, MKDEV(0, 0), NULL, "wmi_bus-%s", dev_name(&device->dev)); if (IS_ERR(wmi_bus_dev)) { error = PTR_ERR(wmi_bus_dev); - goto err_remove_handler; + goto err_remove_notify_handler; } device->driver_data = wmi_bus_dev; @@ -1096,7 +1147,11 @@ static int acpi_wmi_add(struct acpi_device *device) err_remove_busdev: device_unregister(wmi_bus_dev); -err_remove_handler: +err_remove_notify_handler: + acpi_remove_notify_handler(device->handle, ACPI_DEVICE_NOTIFY, + acpi_wmi_notify_handler); + +err_remove_ec_handler: acpi_remove_address_space_handler(device->handle, ACPI_ADR_SPACE_EC, &acpi_wmi_ec_space_handler); diff --git a/include/linux/wmi.h b/include/linux/wmi.h index 5309500..c6eedfd 100644 --- a/include/linux/wmi.h +++ b/include/linux/wmi.h @@ -39,6 +39,7 @@ struct wmi_driver { int (*probe)(struct wmi_device *wdev); int (*remove)(struct wmi_device *wdev); + void (*notify)(struct wmi_device *device, union acpi_object *data); }; extern int __must_check __wmi_driver_register(struct wmi_driver *driver,