diff mbox

[v2] Add driver to force WMI Thunderbolt controller power status

Message ID 1504810042-4696-1-git-send-email-mario.limonciello@dell.com (mailing list archive)
State Changes Requested, archived
Delegated to: Darren Hart
Headers show

Commit Message

Limonciello, Mario Sept. 7, 2017, 6:47 p.m. UTC
Current implementations of Intel Thunderbolt controllers will go
into a low power mode when not in use.

Many machines containing these controllers also have a GPIO wired up
that can force the controller awake.  This is offered via a ACPI-WMI
interface intended to be manipulated by a userspace utility.

This mechanism is provided by Intel to OEMs to include in BIOS.
It uses an industry wide GUID that is populated in a separate _WDG
entry with no binary MOF.

This interface allows software such as fwupd to wake up thunderbolt
controllers to query the firmware version or flash new firmware.

Signed-off-by: Mario Limonciello <mario.limonciello@dell.com>
---
changes from v1 to v2:
 * Add ABI documentation
 * Update thunderbolt.rst
 * Remove unnecessary cast
 * Remove unneeded whitespace
 * Adjust references of "Intel Wmi thunderbolt" -> 
   "Intel WMI thunderbolt force power"

 .../testing/sysfs-platform-intel-wmi-thunderbolt   | 11 +++
 Documentation/admin-guide/thunderbolt.rst          | 15 ++++
 MAINTAINERS                                        |  5 ++
 drivers/platform/x86/Kconfig                       | 13 +++
 drivers/platform/x86/Makefile                      |  1 +
 drivers/platform/x86/intel-wmi-thunderbolt.c       | 96 ++++++++++++++++++++++
 6 files changed, 141 insertions(+)
 create mode 100644 Documentation/ABI/testing/sysfs-platform-intel-wmi-thunderbolt
 create mode 100644 drivers/platform/x86/intel-wmi-thunderbolt.c

Comments

Bernat, Yehezkel Sept. 7, 2017, 7:14 p.m. UTC | #1
> +Contact:       "Mario LimonciellO" <mario.limonciello@dell.com>

                                   ^
Looks like a typo
Limonciello, Mario Sept. 7, 2017, 8:09 p.m. UTC | #2
> -----Original Message-----

> From: Bernat, Yehezkel [mailto:yehezkel.bernat@intel.com]

> Sent: Thursday, September 7, 2017 2:15 PM

> To: dvhart@infradead.org; Limonciello, Mario <Mario_Limonciello@Dell.com>

> Cc: mika.westerberg@linux.intel.com; linux-kernel@vger.kernel.org; platform-

> driver-x86@vger.kernel.org; hughsient@gmail.com

> Subject: Re: [PATCH v2] Add driver to force WMI Thunderbolt controller power

> status

> 

> 

> > +Contact:       "Mario LimonciellO" <mario.limonciello@dell.com>

>                                    ^

> Looks like a typo


Yep - fat fingered shift while adding the second " :)

If that's all that's left, hopefully Daren can just fix it when committing.
Darren Hart Sept. 8, 2017, 12:06 a.m. UTC | #3
On Thu, Sep 07, 2017 at 08:09:28PM +0000, Mario.Limonciello@dell.com wrote:
> > -----Original Message-----
> > From: Bernat, Yehezkel [mailto:yehezkel.bernat@intel.com]
> > Sent: Thursday, September 7, 2017 2:15 PM
> > To: dvhart@infradead.org; Limonciello, Mario <Mario_Limonciello@Dell.com>
> > Cc: mika.westerberg@linux.intel.com; linux-kernel@vger.kernel.org; platform-
> > driver-x86@vger.kernel.org; hughsient@gmail.com
> > Subject: Re: [PATCH v2] Add driver to force WMI Thunderbolt controller power
> > status
> > 
> > 
> > > +Contact:       "Mario LimonciellO" <mario.limonciello@dell.com>
> >                                    ^
> > Looks like a typo
> 
> Yep - fat fingered shift while adding the second " :)
> 
> If that's all that's left, hopefully Daren can just fix it when committing.

Yup. I'd like an Reviewed-by from Mika. Bernat, you two if you're happy with it.
Appreciate all the reviews.
Mika Westerberg Sept. 8, 2017, 8:07 a.m. UTC | #4
On Thu, Sep 07, 2017 at 01:47:22PM -0500, Mario Limonciello wrote:

I have a small comment which you might want to consider.

> +static int intel_wmi_thunderbolt_probe(struct wmi_device *wdev)
> +{
> +	return sysfs_create_group(&wdev->dev.kobj, &tbt_attribute_group);
> +}
> +
> +static int intel_wmi_thunderbolt_remove(struct wmi_device *wdev)
> +{
> +	sysfs_remove_group(&wdev->dev.kobj, &tbt_attribute_group);
> +	return 0;
> +}

In order to notify userspace about this, what if you send KOBJ_CHANGE
for the wdev when you add/remove this attribute?
Limonciello, Mario Sept. 8, 2017, 3:15 p.m. UTC | #5
> -----Original Message-----
> From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> Sent: Friday, September 8, 2017 3:07 AM
> To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> Cc: dvhart@infradead.org; LKML <linux-kernel@vger.kernel.org>; platform-driver-
> x86@vger.kernel.org; Richard Hughes <hughsient@gmail.com>; Yehezkel Bernat
> <yehezkelshb@gmail.com>
> Subject: Re: [PATCH v2] Add driver to force WMI Thunderbolt controller power
> status
> 
> On Thu, Sep 07, 2017 at 01:47:22PM -0500, Mario Limonciello wrote:
> 
> I have a small comment which you might want to consider.
> 
> > +static int intel_wmi_thunderbolt_probe(struct wmi_device *wdev)
> > +{
> > +	return sysfs_create_group(&wdev->dev.kobj, &tbt_attribute_group);
> > +}
> > +
> > +static int intel_wmi_thunderbolt_remove(struct wmi_device *wdev)
> > +{
> > +	sysfs_remove_group(&wdev->dev.kobj, &tbt_attribute_group);
> > +	return 0;
> > +}
> 
> In order to notify userspace about this, what if you send KOBJ_CHANGE
> for the wdev when you add/remove this attribute?

Sure, makes sense to me.   I'll send a follow up patch.
Darren Hart Sept. 9, 2017, 4:14 a.m. UTC | #6
On Fri, Sep 08, 2017 at 03:15:10PM +0000, Mario.Limonciello@dell.com wrote:
> > -----Original Message-----
> > From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> > Sent: Friday, September 8, 2017 3:07 AM
> > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > Cc: dvhart@infradead.org; LKML <linux-kernel@vger.kernel.org>; platform-driver-
> > x86@vger.kernel.org; Richard Hughes <hughsient@gmail.com>; Yehezkel Bernat
> > <yehezkelshb@gmail.com>
> > Subject: Re: [PATCH v2] Add driver to force WMI Thunderbolt controller power
> > status
> > 
> > On Thu, Sep 07, 2017 at 01:47:22PM -0500, Mario Limonciello wrote:
> > 
> > I have a small comment which you might want to consider.
> > 
> > > +static int intel_wmi_thunderbolt_probe(struct wmi_device *wdev)
> > > +{
> > > +	return sysfs_create_group(&wdev->dev.kobj, &tbt_attribute_group);
> > > +}
> > > +
> > > +static int intel_wmi_thunderbolt_remove(struct wmi_device *wdev)
> > > +{
> > > +	sysfs_remove_group(&wdev->dev.kobj, &tbt_attribute_group);
> > > +	return 0;
> > > +}
> > 
> > In order to notify userspace about this, what if you send KOBJ_CHANGE
> > for the wdev when you add/remove this attribute?
> 
> Sure, makes sense to me.   I'll send a follow up patch.

Hrm, what am I missing.... the reason I recommended Mario add the attribute
group was so this would be automatically taken care of prior to the KOBJ_ADD
event, per the device documentation:

driver-model/device.txt
Mika Westerberg Sept. 9, 2017, 7:05 a.m. UTC | #7
On Fri, Sep 08, 2017 at 09:14:52PM -0700, Darren Hart wrote:
> On Fri, Sep 08, 2017 at 03:15:10PM +0000, Mario.Limonciello@dell.com wrote:
> > > -----Original Message-----
> > > From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> > > Sent: Friday, September 8, 2017 3:07 AM
> > > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > > Cc: dvhart@infradead.org; LKML <linux-kernel@vger.kernel.org>; platform-driver-
> > > x86@vger.kernel.org; Richard Hughes <hughsient@gmail.com>; Yehezkel Bernat
> > > <yehezkelshb@gmail.com>
> > > Subject: Re: [PATCH v2] Add driver to force WMI Thunderbolt controller power
> > > status
> > > 
> > > On Thu, Sep 07, 2017 at 01:47:22PM -0500, Mario Limonciello wrote:
> > > 
> > > I have a small comment which you might want to consider.
> > > 
> > > > +static int intel_wmi_thunderbolt_probe(struct wmi_device *wdev)
> > > > +{
> > > > +	return sysfs_create_group(&wdev->dev.kobj, &tbt_attribute_group);
> > > > +}
> > > > +
> > > > +static int intel_wmi_thunderbolt_remove(struct wmi_device *wdev)
> > > > +{
> > > > +	sysfs_remove_group(&wdev->dev.kobj, &tbt_attribute_group);
> > > > +	return 0;
> > > > +}
> > > 
> > > In order to notify userspace about this, what if you send KOBJ_CHANGE
> > > for the wdev when you add/remove this attribute?
> > 
> > Sure, makes sense to me.   I'll send a follow up patch.
> 
> Hrm, what am I missing.... the reason I recommended Mario add the attribute
> group was so this would be automatically taken care of prior to the KOBJ_ADD
> event, per the device documentation:
> 
> driver-model/device.txt

At this point the KOBJ_ADD event has already been send to the userspace
when the device was added to the system.
Darren Hart Sept. 11, 2017, 9:39 a.m. UTC | #8
On Sat, Sep 09, 2017 at 10:05:58AM +0300, Mika Westerberg wrote:
> On Fri, Sep 08, 2017 at 09:14:52PM -0700, Darren Hart wrote:
> > On Fri, Sep 08, 2017 at 03:15:10PM +0000, Mario.Limonciello@dell.com wrote:
> > > > -----Original Message-----
> > > > From: Mika Westerberg [mailto:mika.westerberg@linux.intel.com]
> > > > Sent: Friday, September 8, 2017 3:07 AM
> > > > To: Limonciello, Mario <Mario_Limonciello@Dell.com>
> > > > Cc: dvhart@infradead.org; LKML <linux-kernel@vger.kernel.org>; platform-driver-
> > > > x86@vger.kernel.org; Richard Hughes <hughsient@gmail.com>; Yehezkel Bernat
> > > > <yehezkelshb@gmail.com>
> > > > Subject: Re: [PATCH v2] Add driver to force WMI Thunderbolt controller power
> > > > status
> > > > 
> > > > On Thu, Sep 07, 2017 at 01:47:22PM -0500, Mario Limonciello wrote:
> > > > 
> > > > I have a small comment which you might want to consider.
> > > > 
> > > > > +static int intel_wmi_thunderbolt_probe(struct wmi_device *wdev)
> > > > > +{
> > > > > +	return sysfs_create_group(&wdev->dev.kobj, &tbt_attribute_group);
> > > > > +}
> > > > > +
> > > > > +static int intel_wmi_thunderbolt_remove(struct wmi_device *wdev)
> > > > > +{
> > > > > +	sysfs_remove_group(&wdev->dev.kobj, &tbt_attribute_group);
> > > > > +	return 0;
> > > > > +}
> > > > 
> > > > In order to notify userspace about this, what if you send KOBJ_CHANGE
> > > > for the wdev when you add/remove this attribute?
> > > 
> > > Sure, makes sense to me.   I'll send a follow up patch.
> > 
> > Hrm, what am I missing.... the reason I recommended Mario add the attribute
> > group was so this would be automatically taken care of prior to the KOBJ_ADD
> > event, per the device documentation:
> > 
> > driver-model/device.txt
> 
> At this point the KOBJ_ADD event has already been send to the userspace
> when the device was added to the system.

Which device are you referring to? This attribute is bound to the device
identified by the WMI GUID, and should be independent from the controller or any
thunderbolt connected physical device.
Mika Westerberg Sept. 11, 2017, 9:46 a.m. UTC | #9
On Mon, Sep 11, 2017 at 02:39:55AM -0700, Darren Hart wrote:
> Which device are you referring to? This attribute is bound to the device
> identified by the WMI GUID, and should be independent from the controller or any
> thunderbolt connected physical device.

I refer to "wdev->dev" whatever that is. That device has been created
long time before this driver is probed and thus userspace already got
the KOBJ_ADD uevent.
Darren Hart Sept. 11, 2017, 9:40 p.m. UTC | #10
On Mon, Sep 11, 2017 at 12:46:14PM +0300, Mika Westerberg wrote:
> On Mon, Sep 11, 2017 at 02:39:55AM -0700, Darren Hart wrote:
> > Which device are you referring to? This attribute is bound to the device
> > identified by the WMI GUID, and should be independent from the controller or any
> > thunderbolt connected physical device.
> 
> I refer to "wdev->dev" whatever that is. That device has been created
> long time before this driver is probed and thus userspace already got
> the KOBJ_ADD uevent.
> 

Ah yes, I see - at the time of device_register. Thanks Mika.
diff mbox

Patch

diff --git a/Documentation/ABI/testing/sysfs-platform-intel-wmi-thunderbolt b/Documentation/ABI/testing/sysfs-platform-intel-wmi-thunderbolt
new file mode 100644
index 0000000..7b8e61a
--- /dev/null
+++ b/Documentation/ABI/testing/sysfs-platform-intel-wmi-thunderbolt
@@ -0,0 +1,11 @@ 
+What:		/sys/devices/platform/<platform>/force_power
+Date:		September 2017
+KernelVersion:	4.14
+Contact:	"Mario LimonciellO" <mario.limonciello@dell.com>
+Description:
+		Modify the platform force power state, influencing
+		Thunderbolt controllers to turn on or off when no
+		devices are connected (write-only)
+		There are two available states:
+		    * 0 -> Force power disabled
+		    * 1 -> Force power enabled
diff --git a/Documentation/admin-guide/thunderbolt.rst b/Documentation/admin-guide/thunderbolt.rst
index 6a4cd1f..dadcd66 100644
--- a/Documentation/admin-guide/thunderbolt.rst
+++ b/Documentation/admin-guide/thunderbolt.rst
@@ -197,3 +197,18 @@  information is missing.
 
 To recover from this mode, one needs to flash a valid NVM image to the
 host host controller in the same way it is done in the previous chapter.
+
+Forcing power
+-------------
+Many OEMs include a method that can be used to force the power of a
+thunderbolt controller to an "On" state even if nothing is connected.
+If supported by your machine this will be exposed by the WMI bus with
+a sysfs attribute called "force_power".
+
+For example the intel-wmi-thunderbolt driver exposes this attribute in:
+  /sys/devices/platform/PNP0C14:00/wmi_bus/wmi_bus-PNP0C14:00/86CCFD48-205E-4A77-9C48-2021CBEDE341/force_power
+
+  To force the power to on, write 1 to this attribute file.
+  To disable force power, write 0 to this attribute file.
+
+Note: it's currently not possible to query the force power state of a platform.
diff --git a/MAINTAINERS b/MAINTAINERS
index 1c3feff..9a6b73e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3949,6 +3949,11 @@  M:	Pali Rohár <pali.rohar@gmail.com>
 S:	Maintained
 F:	drivers/platform/x86/dell-wmi.c
 
+INTEL WMI THUNDERBOLT FORCE POWER DRIVER
+M:	Mario Limonciello <mario.limonciello@dell.com>
+S:	Maintained
+F:	drivers/platform/x86/intel-wmi-thunderbolt.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 80b8795..f401ae4 100644
--- a/drivers/platform/x86/Kconfig
+++ b/drivers/platform/x86/Kconfig
@@ -658,6 +658,19 @@  config WMI_BMOF
 	  To compile this driver as a module, choose M here: the module will
 	  be called wmi-bmof.
 
+config INTEL_WMI_THUNDERBOLT
+	tristate "Intel WMI thunderbolt force power driver"
+	depends on ACPI_WMI
+	default ACPI_WMI
+	---help---
+	  Say Y here if you want to be able to use the WMI interface on select
+	  systems to force the power control of Intel Thunderbolt controllers.
+	  This is useful for updating the firmware when devices are not plugged
+	  into the controller.
+
+	  To compile this driver as a module, choose M here: the module will
+	  be called intel-wmi-thunderbolt.
+
 config MSI_WMI
 	tristate "MSI WMI extras"
 	depends on ACPI_WMI
diff --git a/drivers/platform/x86/Makefile b/drivers/platform/x86/Makefile
index 91cec17..2b315d0 100644
--- a/drivers/platform/x86/Makefile
+++ b/drivers/platform/x86/Makefile
@@ -39,6 +39,7 @@  obj-$(CONFIG_PEAQ_WMI)		+= peaq-wmi.o
 obj-$(CONFIG_SURFACE3_WMI)	+= surface3-wmi.o
 obj-$(CONFIG_TOPSTAR_LAPTOP)	+= topstar-laptop.o
 obj-$(CONFIG_WMI_BMOF)		+= wmi-bmof.o
+obj-$(CONFIG_INTEL_WMI_THUNDERBOLT)	+= intel-wmi-thunderbolt.o
 
 # toshiba_acpi must link after wmi to ensure that wmi devices are found
 # before toshiba_acpi initializes
diff --git a/drivers/platform/x86/intel-wmi-thunderbolt.c b/drivers/platform/x86/intel-wmi-thunderbolt.c
new file mode 100644
index 0000000..e8c98dc
--- /dev/null
+++ b/drivers/platform/x86/intel-wmi-thunderbolt.c
@@ -0,0 +1,96 @@ 
+/*
+ * WMI Thunderbolt 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/device.h>
+#include <linux/fs.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/string.h>
+#include <linux/sysfs.h>
+#include <linux/types.h>
+#include <linux/wmi.h>
+
+#define INTEL_WMI_THUNDERBOLT_GUID "86CCFD48-205E-4A77-9C48-2021CBEDE341"
+
+static ssize_t force_power_store(struct device *dev,
+				 struct device_attribute *attr,
+				 const char *buf, size_t count)
+{
+	struct acpi_buffer input;
+	acpi_status status;
+	u8 mode;
+
+	input.length = sizeof(u8);
+	input.pointer = &mode;
+	mode = hex_to_bin(buf[0]);
+	if (mode == 0 || mode == 1) {
+		status = wmi_evaluate_method(INTEL_WMI_THUNDERBOLT_GUID, 0, 1,
+					     &input, NULL);
+		if (ACPI_FAILURE(status)) {
+			pr_err("intel-wmi-thunderbolt: failed setting %s\n",
+			       buf);
+			return -ENODEV;
+		}
+	} else {
+		pr_err("intel-wmi-thunderbolt: unsupported mode: %d", mode);
+	}
+	return count;
+}
+
+static DEVICE_ATTR_WO(force_power);
+
+static struct attribute *tbt_attrs[] = {
+	&dev_attr_force_power.attr,
+	NULL
+};
+
+static const struct attribute_group tbt_attribute_group = {
+	.attrs = tbt_attrs,
+};
+
+static int intel_wmi_thunderbolt_probe(struct wmi_device *wdev)
+{
+	return sysfs_create_group(&wdev->dev.kobj, &tbt_attribute_group);
+}
+
+static int intel_wmi_thunderbolt_remove(struct wmi_device *wdev)
+{
+	sysfs_remove_group(&wdev->dev.kobj, &tbt_attribute_group);
+	return 0;
+}
+
+static const struct wmi_device_id intel_wmi_thunderbolt_id_table[] = {
+	{ .guid_string = INTEL_WMI_THUNDERBOLT_GUID },
+	{ },
+};
+
+static struct wmi_driver intel_wmi_thunderbolt_driver = {
+	.driver = {
+		.name = "intel-wmi-thunderbolt",
+	},
+	.probe = intel_wmi_thunderbolt_probe,
+	.remove = intel_wmi_thunderbolt_remove,
+	.id_table = intel_wmi_thunderbolt_id_table,
+};
+
+module_wmi_driver(intel_wmi_thunderbolt_driver);
+
+MODULE_ALIAS("wmi:" INTEL_WMI_THUNDERBOLT_GUID);
+MODULE_AUTHOR("Mario Limonciello <mario.limonciello@dell.com>");
+MODULE_DESCRIPTION("Intel WMI Thunderbolt force power driver");
+MODULE_LICENSE("GPL");