From patchwork Tue Dec 1 01:06:00 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Andy Lutomirski X-Patchwork-Id: 7731571 Return-Path: X-Original-To: patchwork-platform-driver-x86@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.136]) by patchwork1.web.kernel.org (Postfix) with ESMTP id B6F1F9F54F for ; Tue, 1 Dec 2015 01:06:35 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id D107620641 for ; Tue, 1 Dec 2015 01:06:34 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id F3D7520648 for ; Tue, 1 Dec 2015 01:06:33 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754890AbbLABGY (ORCPT ); Mon, 30 Nov 2015 20:06:24 -0500 Received: from mail.kernel.org ([198.145.29.136]:46846 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1755348AbbLABGX (ORCPT ); Mon, 30 Nov 2015 20:06:23 -0500 Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 9368C2066F; Tue, 1 Dec 2015 01:06:22 +0000 (UTC) Received: from localhost (c-71-202-137-17.hsd1.ca.comcast.net [71.202.137.17]) (using TLSv1.2 with cipher AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id B6F4720674; Tue, 1 Dec 2015 01:06:21 +0000 (UTC) From: Andy Lutomirski To: Darren Hart Cc: Matthew Garrett , linux-acpi@vger.kernel.org, platform-driver-x86@vger.kernel.org, Mario Limonciello , =?UTF-8?q?Pali=20Roh=C3=A1r?= , Andy Lutomirski Subject: [PATCH 10/14] wmi: Add a driver .notify function Date: Mon, 30 Nov 2015 17:06:00 -0800 Message-Id: <7f1d3526155d12236b9d0126db391002294fe23b.1448931782.git.luto@kernel.org> X-Mailer: git-send-email 2.5.0 In-Reply-To: References: In-Reply-To: References: X-Spam-Status: No, score=-6.9 required=5.0 tests=BAYES_00, RCVD_IN_DNSWL_HI, T_RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Sender: platform-driver-x86-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: platform-driver-x86@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP This gives event drivers a very 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 --- drivers/platform/x86/wmi.c | 62 ++++++++++++++++++++++++++++++++++++++-------- include/linux/wmi.h | 1 + 2 files changed, 52 insertions(+), 11 deletions(-) diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c index 7d8a11a45bf9..24fabfef5e8e 100644 --- a/drivers/platform/x86/wmi.c +++ b/drivers/platform/x86/wmi.c @@ -1099,6 +1099,7 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event) 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); @@ -1106,20 +1107,59 @@ static void acpi_wmi_notify(struct acpi_device *device, u32 event) if (wblock->acpi_device == device && (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( + device->pnp.device_class, dev_name(&device->dev), + event, 0); + } static int acpi_wmi_remove(struct acpi_device *device) diff --git a/include/linux/wmi.h b/include/linux/wmi.h index 53095006821e..c6eedfd94e7d 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,