From: Mario Limonciello <mario.limonciello@dell.com>
To: dvhart@infradead.org, Andy Shevchenko <andy.shevchenko@gmail.com>
Cc: LKML <linux-kernel@vger.kernel.org>,
platform-driver-x86@vger.kernel.org,
Andy Lutomirski <luto@kernel.org>,
quasisec@google.com, pali.rohar@gmail.com, rjw@rjwysocki.net,
mjg59@google.com, hch@lst.de, Greg KH <greg@kroah.com>,
Alan Cox <gnomes@lxorguk.ukuu.org.uk>,
Mario Limonciello <mario.limonciello@dell.com>
Subject: [PATCH v10 05/15] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver
Date: Thu, 19 Oct 2017 12:50:08 -0500 [thread overview]
Message-ID: <d68852a032398142e5277137f2a18ff6a5bee999.1508434513.git.mario.limonciello@dell.com> (raw)
In-Reply-To: <cover.1508434513.git.mario.limonciello@dell.com>
In-Reply-To: <cover.1508434513.git.mario.limonciello@dell.com>
All communication on individual GUIDs should occur in separate drivers.
Allowing a driver to communicate with the bus to another GUID is just
a hack that discourages drivers to adopt the bus model.
The information found from the WMI descriptor driver is now exported
for use by other drivers.
Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
Reviewed-by: Edward O'Callaghan <quasisec@google.com>
---
MAINTAINERS | 5 +
drivers/platform/x86/Kconfig | 5 +
drivers/platform/x86/Makefile | 1 +
drivers/platform/x86/dell-wmi-descriptor.c | 168 +++++++++++++++++++++++++++++
drivers/platform/x86/dell-wmi-descriptor.h | 21 ++++
drivers/platform/x86/dell-wmi.c | 80 ++------------
6 files changed, 206 insertions(+), 74 deletions(-)
create mode 100644 drivers/platform/x86/dell-wmi-descriptor.c
create mode 100644 drivers/platform/x86/dell-wmi-descriptor.h
diff --git a/MAINTAINERS b/MAINTAINERS
index 2347e36588dc..f4cf35950b08 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -4013,6 +4013,11 @@ M: Pali Rohár <pali.rohar@gmail.com>
S: Maintained
F: drivers/platform/x86/dell-wmi.c
+DELL WMI DESCRIPTOR DRIVER
+M: Mario Limonciello <mario.limonciello@dell.com>
+S: Maintained
+F: drivers/platform/x86/dell-wmi-descriptor.c
+
DELTA ST MEDIA DRIVER
M: Hugues Fruchet <hugues.fruchet@st.com>
L: linux-media@vger.kernel.org
diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig
index 1f7959ff055c..7722923c968c 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -121,6 +121,7 @@ config DELL_WMI
depends on DMI
depends on INPUT
depends on ACPI_VIDEO || ACPI_VIDEO = n
+ select DELL_WMI_DESCRIPTOR
select DELL_SMBIOS
select INPUT_SPARSEKMAP
---help---
@@ -129,6 +130,10 @@ config DELL_WMI
To compile this driver as a module, choose M here: the module will
be called dell-wmi.
+config DELL_WMI_DESCRIPTOR
+ tristate
+ depends on ACPI_WMI
+
config DELL_WMI_AIO
tristate "WMI Hotkeys for Dell All-In-One series"
depends on ACPI_WMI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 2b315d0df3b7..8636f5d3424f 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_COMPAL_LAPTOP) += compal-laptop.o
obj-$(CONFIG_DELL_SMBIOS) += dell-smbios.o
obj-$(CONFIG_DELL_LAPTOP) += dell-laptop.o
obj-$(CONFIG_DELL_WMI) += dell-wmi.o
+obj-$(CONFIG_DELL_WMI_DESCRIPTOR) += dell-wmi-descriptor.o
obj-$(CONFIG_DELL_WMI_AIO) += dell-wmi-aio.o
obj-$(CONFIG_DELL_WMI_LED) += dell-wmi-led.o
obj-$(CONFIG_DELL_SMO8800) += dell-smo8800.o
diff --git a/drivers/platform/x86/dell-wmi-descriptor.c b/drivers/platform/x86/dell-wmi-descriptor.c
new file mode 100644
index 000000000000..dcf4df39ad80
--- /dev/null
+++ b/drivers/platform/x86/dell-wmi-descriptor.c
@@ -0,0 +1,168 @@
+/*
+ * Dell WMI descriptor driver
+ *
+ * Copyright (C) 2017 Dell Inc. All Rights Reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 as published
+ * by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include <linux/acpi.h>
+#include <linux/list.h>
+#include <linux/module.h>
+#include <linux/wmi.h>
+#include "dell-wmi-descriptor.h"
+
+struct descriptor_priv {
+ struct list_head list;
+ u32 interface_version;
+ u32 size;
+};
+static LIST_HEAD(wmi_list);
+static DEFINE_MUTEX(list_mutex);
+
+bool dell_wmi_get_interface_version(u32 *version)
+{
+ struct descriptor_priv *priv;
+ bool ret = false;
+
+ mutex_lock(&list_mutex);
+ priv = list_first_entry_or_null(&wmi_list,
+ struct descriptor_priv,
+ list);
+ if (priv) {
+ *version = priv->interface_version;
+ ret = true;
+ }
+ mutex_unlock(&list_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dell_wmi_get_interface_version);
+
+bool dell_wmi_get_size(u32 *size)
+{
+ struct descriptor_priv *priv;
+ bool ret = false;
+
+ mutex_lock(&list_mutex);
+ priv = list_first_entry_or_null(&wmi_list,
+ struct descriptor_priv,
+ list);
+ if (priv) {
+ *size = priv->size;
+ ret = true;
+ }
+ mutex_unlock(&list_mutex);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(dell_wmi_get_size);
+
+/*
+ * Descriptor buffer is 128 byte long and contains:
+ *
+ * Name Offset Length Value
+ * Vendor Signature 0 4 "DELL"
+ * Object Signature 4 4 " WMI"
+ * WMI Interface Version 8 4 <version>
+ * WMI buffer length 12 4 <length>
+ */
+static int dell_wmi_descriptor_probe(struct wmi_device *wdev)
+{
+ union acpi_object *obj = NULL;
+ struct descriptor_priv *priv;
+ u32 *buffer;
+ int ret;
+
+ obj = wmidev_block_query(wdev, 0);
+ if (!obj) {
+ dev_err(&wdev->dev, "failed to read Dell WMI descriptor\n");
+ ret = -EIO;
+ goto out;
+ }
+
+ if (obj->type != ACPI_TYPE_BUFFER) {
+ dev_err(&wdev->dev, "Dell descriptor has wrong type\n");
+ ret = -EINVAL;
+ goto out;
+ }
+
+ /* Although it's not technically a failure, this would lead to
+ * unexpected behavior
+ */
+ if (obj->buffer.length != 128) {
+ dev_err(&wdev->dev,
+ "Dell descriptor buffer has unexpected length (%d)\n",
+ obj->buffer.length);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ buffer = (u32 *)obj->buffer.pointer;
+
+ if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0) {
+ dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature (%8ph)\n",
+ buffer);
+ ret = -EINVAL;
+ goto out;
+ }
+
+ if (buffer[2] != 0 && buffer[2] != 1)
+ dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%lu)\n",
+ (unsigned long) buffer[2]);
+
+ priv = devm_kzalloc(&wdev->dev, sizeof(struct descriptor_priv),
+ GFP_KERNEL);
+
+ priv->interface_version = buffer[2];
+ priv->size = buffer[3];
+ ret = 0;
+ dev_set_drvdata(&wdev->dev, priv);
+ list_add_tail(&priv->list, &wmi_list);
+
+ dev_dbg(&wdev->dev, "Detected Dell WMI interface version %lu and buffer size %lu\n",
+ (unsigned long) priv->interface_version,
+ (unsigned long) priv->size);
+
+out:
+ kfree(obj);
+ return ret;
+}
+
+static int dell_wmi_descriptor_remove(struct wmi_device *wdev)
+{
+ struct descriptor_priv *priv = dev_get_drvdata(&wdev->dev);
+
+ mutex_lock(&list_mutex);
+ list_del(&priv->list);
+ mutex_unlock(&list_mutex);
+ return 0;
+}
+
+static const struct wmi_device_id dell_wmi_descriptor_id_table[] = {
+ { .guid_string = DELL_WMI_DESCRIPTOR_GUID },
+ { },
+};
+
+static struct wmi_driver dell_wmi_descriptor_driver = {
+ .driver = {
+ .name = "dell-wmi-descriptor",
+ },
+ .probe = dell_wmi_descriptor_probe,
+ .remove = dell_wmi_descriptor_remove,
+ .id_table = dell_wmi_descriptor_id_table,
+};
+
+module_wmi_driver(dell_wmi_descriptor_driver);
+
+MODULE_ALIAS("wmi:" DELL_WMI_DESCRIPTOR_GUID);
+MODULE_AUTHOR("Mario Limonciello <mario.limonciello@dell.com>");
+MODULE_DESCRIPTION("Dell WMI descriptor driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/platform/x86/dell-wmi-descriptor.h b/drivers/platform/x86/dell-wmi-descriptor.h
new file mode 100644
index 000000000000..5f7b69c2c83a
--- /dev/null
+++ b/drivers/platform/x86/dell-wmi-descriptor.h
@@ -0,0 +1,21 @@
+/*
+ * Dell WMI descriptor driver
+ *
+ * Copyright (c) 2017 Dell Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef _DELL_WMI_DESCRIPTOR_H_
+#define _DELL_WMI_DESCRIPTOR_H_
+
+#include <linux/wmi.h>
+
+#define DELL_WMI_DESCRIPTOR_GUID "8D9DDCBC-A997-11DA-B012-B622A1EF5492"
+
+bool dell_wmi_get_interface_version(u32 *version);
+bool dell_wmi_get_size(u32 *size);
+
+#endif
diff --git a/drivers/platform/x86/dell-wmi.c b/drivers/platform/x86/dell-wmi.c
index da4f629d0831..6d657eb97672 100644
--- a/drivers/platform/x86/dell-wmi.c
+++ b/drivers/platform/x86/dell-wmi.c
@@ -39,6 +39,7 @@
#include <linux/wmi.h>
#include <acpi/video.h>
#include "dell-smbios.h"
+#include "dell-wmi-descriptor.h"
MODULE_AUTHOR("Matthew Garrett <mjg@redhat.com>");
MODULE_AUTHOR("Pali Rohár <pali.rohar@gmail.com>");
@@ -46,7 +47,6 @@ MODULE_DESCRIPTION("Dell laptop WMI hotkeys driver");
MODULE_LICENSE("GPL");
#define DELL_EVENT_GUID "9DBB5994-A997-11DA-B012-B622A1EF5492"
-#define DELL_DESCRIPTOR_GUID "8D9DDCBC-A997-11DA-B012-B622A1EF5492"
static bool wmi_requires_smbios_request;
@@ -617,75 +617,6 @@ static void dell_wmi_input_destroy(struct wmi_device *wdev)
input_unregister_device(priv->input_dev);
}
-/*
- * Descriptor buffer is 128 byte long and contains:
- *
- * Name Offset Length Value
- * Vendor Signature 0 4 "DELL"
- * Object Signature 4 4 " WMI"
- * WMI Interface Version 8 4 <version>
- * WMI buffer length 12 4 <length>
- */
-static int dell_wmi_check_descriptor_buffer(struct wmi_device *wdev)
-{
- struct dell_wmi_priv *priv = dev_get_drvdata(&wdev->dev);
- union acpi_object *obj = NULL;
- struct wmi_device *desc_dev;
- u32 *buffer;
- int ret;
-
- desc_dev = wmidev_get_other_guid(wdev, DELL_DESCRIPTOR_GUID);
- if (!desc_dev) {
- dev_err(&wdev->dev, "Dell WMI descriptor does not exist\n");
- return -ENODEV;
- }
-
- obj = wmidev_block_query(desc_dev, 0);
- if (!obj) {
- dev_err(&wdev->dev, "failed to read Dell WMI descriptor\n");
- ret = -EIO;
- goto out;
- }
-
- if (obj->type != ACPI_TYPE_BUFFER) {
- dev_err(&wdev->dev, "Dell descriptor has wrong type\n");
- ret = -EINVAL;
- goto out;
- }
-
- if (obj->buffer.length != 128) {
- dev_err(&wdev->dev,
- "Dell descriptor buffer has invalid length (%d)\n",
- obj->buffer.length);
- ret = -EINVAL;
- goto out;
- }
-
- buffer = (u32 *)obj->buffer.pointer;
-
- if (strncmp(obj->string.pointer, "DELL WMI", 8) != 0) {
- dev_err(&wdev->dev, "Dell descriptor buffer has invalid signature (%8ph)\n",
- buffer);
- ret = -EINVAL;
- goto out;
- }
-
- if (buffer[2] != 0 && buffer[2] != 1)
- dev_warn(&wdev->dev, "Dell descriptor buffer has unknown version (%lu)\n",
- (unsigned long) buffer[2]);
-
- priv->interface_version = buffer[2];
- ret = 0;
-
- dev_info(&wdev->dev, "Detected Dell WMI interface version %u\n",
- priv->interface_version);
-
-out:
- kfree(obj);
- put_device(&desc_dev->dev);
- return ret;
-}
-
/*
* According to Dell SMBIOS documentation:
*
@@ -721,7 +652,9 @@ static int dell_wmi_events_set_enabled(bool enable)
static int dell_wmi_probe(struct wmi_device *wdev)
{
struct dell_wmi_priv *priv;
- int err;
+
+ if (!wmi_has_guid(DELL_WMI_DESCRIPTOR_GUID))
+ return -ENODEV;
priv = devm_kzalloc(
&wdev->dev, sizeof(struct dell_wmi_priv), GFP_KERNEL);
@@ -729,9 +662,8 @@ static int dell_wmi_probe(struct wmi_device *wdev)
return -ENOMEM;
dev_set_drvdata(&wdev->dev, priv);
- err = dell_wmi_check_descriptor_buffer(wdev);
- if (err)
- return err;
+ if (!dell_wmi_get_interface_version(&priv->interface_version))
+ return -EPROBE_DEFER;
return dell_wmi_input_setup(wdev);
}
--
2.14.1
next prev parent reply other threads:[~2017-10-19 17:53 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2017-10-19 17:50 [PATCH v10 00/15] Introduce support for Dell SMBIOS over WMI Mario Limonciello
2017-10-19 17:50 ` [PATCH v10 01/15] platform/x86: wmi: Add new method wmidev_evaluate_method Mario Limonciello
2017-10-19 17:50 ` [PATCH v10 02/15] platform/x86: dell-wmi: increase severity of some failures Mario Limonciello
2017-10-19 17:50 ` [PATCH v10 03/15] platform/x86: dell-wmi: clean up wmi descriptor check Mario Limonciello
2017-10-19 17:55 ` Pali Rohár
2017-10-19 17:50 ` [PATCH v10 04/15] platform/x86: dell-wmi: don't check length returned Mario Limonciello
2017-10-19 17:56 ` Pali Rohár
2017-10-19 17:50 ` Mario Limonciello [this message]
2017-10-19 18:06 ` [PATCH v10 05/15] platform/x86: dell-wmi-descriptor: split WMI descriptor into it's own driver Pali Rohár
2017-10-19 17:50 ` [PATCH v10 06/15] platform/x86: wmi: Don't allow drivers to get each other's GUIDs Mario Limonciello
2017-10-19 17:50 ` [PATCH v10 07/15] platform/x86: dell-smbios: only run if proper oem string is detected Mario Limonciello
2017-10-19 17:50 ` [PATCH v10 08/15] platform/x86: dell-smbios: Add a sysfs interface for SMBIOS tokens Mario Limonciello
2017-10-19 17:50 ` [PATCH v10 09/15] platform/x86: dell-smbios: Introduce dispatcher for SMM calls Mario Limonciello
2017-10-19 17:50 ` [PATCH v10 10/15] platform/x86: dell-smbios-wmi: Add new WMI dispatcher driver Mario Limonciello
2017-10-19 17:50 ` [PATCH v10 11/15] platform/x86: dell-smbios-smm: test for WSMT Mario Limonciello
2017-10-19 18:09 ` Pali Rohár
2017-10-19 18:12 ` Mario.Limonciello
2017-10-19 22:46 ` Darren Hart
2017-10-19 17:50 ` [PATCH v10 12/15] platform/x86: dell-smbios: Add filtering support Mario Limonciello
2018-01-05 11:13 ` Pali Rohár
2018-01-05 14:32 ` Mario.Limonciello
2018-01-05 14:44 ` Pali Rohár
2018-01-05 14:48 ` Mario.Limonciello
2018-01-27 14:51 ` Pali Rohár
2018-01-29 16:22 ` Mario.Limonciello
2018-01-29 16:44 ` Pali Rohár
2018-01-05 14:44 ` Andy Shevchenko
2017-10-19 17:50 ` [PATCH v10 13/15] platform/x86: wmi: create userspace interface for drivers Mario Limonciello
2017-10-20 13:21 ` Greg KH
2017-10-20 13:54 ` Mario.Limonciello
2017-10-20 14:48 ` Christoph Hellwig
2017-10-20 15:07 ` Mario.Limonciello
2017-10-20 15:08 ` Christoph Hellwig
2017-10-20 15:31 ` Mario.Limonciello
2017-10-20 14:57 ` Greg KH
2017-10-20 13:22 ` Greg KH
2017-10-20 13:54 ` Mario.Limonciello
2017-10-20 13:23 ` Greg KH
2017-10-20 14:15 ` Mario.Limonciello
2017-10-19 17:50 ` [PATCH v10 14/15] platform/x86: dell-smbios-wmi: introduce userspace interface Mario Limonciello
2017-10-19 17:50 ` [PATCH v10 15/15] tools/wmi: add a sample for dell smbios communication over WMI Mario Limonciello
2017-11-09 9:52 ` [PATCH v10 00/15] Introduce support for Dell SMBIOS " Pavel Machek
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=d68852a032398142e5277137f2a18ff6a5bee999.1508434513.git.mario.limonciello@dell.com \
--to=mario.limonciello@dell.com \
--cc=andy.shevchenko@gmail.com \
--cc=dvhart@infradead.org \
--cc=gnomes@lxorguk.ukuu.org.uk \
--cc=greg@kroah.com \
--cc=hch@lst.de \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mjg59@google.com \
--cc=pali.rohar@gmail.com \
--cc=platform-driver-x86@vger.kernel.org \
--cc=quasisec@google.com \
--cc=rjw@rjwysocki.net \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).