45540b9fab
Changes:
- Rebase onto v4.19.206
Links:
- kernel: 9c073cfc7c
441 lines
16 KiB
Diff
441 lines
16 KiB
Diff
From be8bb5f93d32d3ac7f918cdbfb04b412673ff80b Mon Sep 17 00:00:00 2001
|
||
From: Maximilian Luz <luzmaximilian@gmail.com>
|
||
Date: Sat, 27 Jul 2019 17:51:37 +0200
|
||
Subject: [PATCH] platform/x86: surfacepro3_button: Fix device check
|
||
|
||
Do not use the surfacepro3_button driver on newer Microsoft Surface
|
||
models, only use it on the Surface Pro 3 and 4. Newer models (5th, 6th
|
||
and possibly future generations) use the same device as the Surface Pro
|
||
4 to represent their volume and power buttons (MSHW0040), but their
|
||
actual implementation is significantly different. This patch ensures
|
||
that the surfacepro3_button driver is only used on the Pro 3 and 4
|
||
models, allowing a different driver to bind on other models.
|
||
|
||
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
|
||
Patchset: surface-buttons
|
||
---
|
||
drivers/platform/x86/surfacepro3_button.c | 47 +++++++++++++++++++++++
|
||
1 file changed, 47 insertions(+)
|
||
|
||
diff --git a/drivers/platform/x86/surfacepro3_button.c b/drivers/platform/x86/surfacepro3_button.c
|
||
index 1b491690ce07..96627627060e 100644
|
||
--- a/drivers/platform/x86/surfacepro3_button.c
|
||
+++ b/drivers/platform/x86/surfacepro3_button.c
|
||
@@ -24,6 +24,12 @@
|
||
#define SURFACE_BUTTON_OBJ_NAME "VGBI"
|
||
#define SURFACE_BUTTON_DEVICE_NAME "Surface Pro 3/4 Buttons"
|
||
|
||
+#define MSHW0040_DSM_REVISION 0x01
|
||
+#define MSHW0040_DSM_GET_OMPR 0x02 // get OEM Platform Revision
|
||
+static const guid_t MSHW0040_DSM_UUID =
|
||
+ GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, 0x95, 0xed, 0xab, 0x16, 0x65,
|
||
+ 0x49, 0x80, 0x35);
|
||
+
|
||
#define SURFACE_BUTTON_NOTIFY_TABLET_MODE 0xc8
|
||
|
||
#define SURFACE_BUTTON_NOTIFY_PRESS_POWER 0xc6
|
||
@@ -146,6 +152,44 @@ static int surface_button_resume(struct device *dev)
|
||
}
|
||
#endif
|
||
|
||
+/*
|
||
+ * Surface Pro 4 and Surface Book 2 / Surface Pro 2017 use the same device
|
||
+ * ID (MSHW0040) for the power/volume buttons. Make sure this is the right
|
||
+ * device by checking for the _DSM method and OEM Platform Revision.
|
||
+ *
|
||
+ * Returns true if the driver should bind to this device, i.e. the device is
|
||
+ * either MSWH0028 (Pro 3) or MSHW0040 on a Pro 4 or Book 1.
|
||
+ */
|
||
+static bool surface_button_check_MSHW0040(struct acpi_device *dev)
|
||
+{
|
||
+ acpi_handle handle = dev->handle;
|
||
+ union acpi_object *result;
|
||
+ u64 oem_platform_rev = 0; // valid revisions are nonzero
|
||
+
|
||
+ // get OEM platform revision
|
||
+ result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID,
|
||
+ MSHW0040_DSM_REVISION,
|
||
+ MSHW0040_DSM_GET_OMPR,
|
||
+ NULL, ACPI_TYPE_INTEGER);
|
||
+
|
||
+ /*
|
||
+ * If evaluating the _DSM fails, the method is not present. This means
|
||
+ * that we have either MSHW0028 or MSHW0040 on Pro 4 or Book 1, so we
|
||
+ * should use this driver. We use revision 0 indicating it is
|
||
+ * unavailable.
|
||
+ */
|
||
+
|
||
+ if (result) {
|
||
+ oem_platform_rev = result->integer.value;
|
||
+ ACPI_FREE(result);
|
||
+ }
|
||
+
|
||
+ dev_dbg(&dev->dev, "OEM Platform Revision %llu\n", oem_platform_rev);
|
||
+
|
||
+ return oem_platform_rev == 0;
|
||
+}
|
||
+
|
||
+
|
||
static int surface_button_add(struct acpi_device *device)
|
||
{
|
||
struct surface_button *button;
|
||
@@ -158,6 +202,9 @@ static int surface_button_add(struct acpi_device *device)
|
||
strlen(SURFACE_BUTTON_OBJ_NAME)))
|
||
return -ENODEV;
|
||
|
||
+ if (!surface_button_check_MSHW0040(device))
|
||
+ return -ENODEV;
|
||
+
|
||
button = kzalloc(sizeof(struct surface_button), GFP_KERNEL);
|
||
if (!button)
|
||
return -ENOMEM;
|
||
--
|
||
2.33.0
|
||
|
||
From dc6c755a5867401c03cb7ca17396f8d9b05df58d Mon Sep 17 00:00:00 2001
|
||
From: Maximilian Luz <luzmaximilian@gmail.com>
|
||
Date: Sat, 27 Jul 2019 17:52:01 +0200
|
||
Subject: [PATCH] Input: soc_button_array - Add support for newer surface
|
||
devices
|
||
|
||
Power and volume button support for 5th and 6th generation Microsoft
|
||
Surface devices via soc_button_array.
|
||
|
||
Note that these devices use the same MSHW0040 device as on the Surface
|
||
Pro 4, however the implementation is different (GPIOs vs. ACPI
|
||
notifications). Thus some checking is required to ensure we only load
|
||
this driver on the correct devices.
|
||
|
||
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
|
||
Patchset: surface-buttons
|
||
---
|
||
drivers/input/misc/Kconfig | 6 +-
|
||
drivers/input/misc/soc_button_array.c | 105 +++++++++++++++++++++++---
|
||
2 files changed, 96 insertions(+), 15 deletions(-)
|
||
|
||
diff --git a/drivers/input/misc/Kconfig b/drivers/input/misc/Kconfig
|
||
index ca59a2be9bc5..ea69610370e8 100644
|
||
--- a/drivers/input/misc/Kconfig
|
||
+++ b/drivers/input/misc/Kconfig
|
||
@@ -781,10 +781,10 @@ config INPUT_IDEAPAD_SLIDEBAR
|
||
|
||
config INPUT_SOC_BUTTON_ARRAY
|
||
tristate "Windows-compatible SoC Button Array"
|
||
- depends on KEYBOARD_GPIO
|
||
+ depends on KEYBOARD_GPIO && ACPI
|
||
help
|
||
- Say Y here if you have a SoC-based tablet that originally
|
||
- runs Windows 8.
|
||
+ Say Y here if you have a SoC-based tablet that originally runs
|
||
+ Windows 8 or a Microsoft Surface Book 2, Pro 5, Laptop 1 or later.
|
||
|
||
To compile this driver as a module, choose M here: the
|
||
module will be called soc_button_array.
|
||
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
|
||
index 55cd6e0b409c..8f21c062c85d 100644
|
||
--- a/drivers/input/misc/soc_button_array.c
|
||
+++ b/drivers/input/misc/soc_button_array.c
|
||
@@ -29,6 +29,11 @@ struct soc_button_info {
|
||
bool wakeup;
|
||
};
|
||
|
||
+struct soc_device_data {
|
||
+ const struct soc_button_info *button_info;
|
||
+ int (*check)(struct device *dev);
|
||
+};
|
||
+
|
||
/*
|
||
* Some of the buttons like volume up/down are auto repeat, while others
|
||
* are not. To support both, we register two platform devices, and put
|
||
@@ -91,8 +96,13 @@ soc_button_device_create(struct platform_device *pdev,
|
||
continue;
|
||
|
||
gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index);
|
||
- if (!gpio_is_valid(gpio))
|
||
+ if (gpio < 0 && gpio != -ENOENT) {
|
||
+ error = gpio;
|
||
+ goto err_free_mem;
|
||
+ } else if (!gpio_is_valid(gpio)) {
|
||
+ /* Skip GPIO if not present */
|
||
continue;
|
||
+ }
|
||
|
||
gpio_keys[n_buttons].type = info->event_type;
|
||
gpio_keys[n_buttons].code = info->event_code;
|
||
@@ -309,23 +319,26 @@ static int soc_button_remove(struct platform_device *pdev)
|
||
static int soc_button_probe(struct platform_device *pdev)
|
||
{
|
||
struct device *dev = &pdev->dev;
|
||
- const struct acpi_device_id *id;
|
||
- struct soc_button_info *button_info;
|
||
+ const struct soc_device_data *device_data;
|
||
+ const struct soc_button_info *button_info;
|
||
struct soc_button_data *priv;
|
||
struct platform_device *pd;
|
||
int i;
|
||
int error;
|
||
|
||
- id = acpi_match_device(dev->driver->acpi_match_table, dev);
|
||
- if (!id)
|
||
- return -ENODEV;
|
||
+ device_data = acpi_device_get_match_data(dev);
|
||
+ if (device_data && device_data->check) {
|
||
+ error = device_data->check(dev);
|
||
+ if (error)
|
||
+ return error;
|
||
+ }
|
||
|
||
- if (!id->driver_data) {
|
||
+ if (device_data && device_data->button_info) {
|
||
+ button_info = device_data->button_info;
|
||
+ } else {
|
||
button_info = soc_button_get_button_info(dev);
|
||
if (IS_ERR(button_info))
|
||
return PTR_ERR(button_info);
|
||
- } else {
|
||
- button_info = (struct soc_button_info *)id->driver_data;
|
||
}
|
||
|
||
error = gpiod_count(dev, NULL);
|
||
@@ -357,7 +370,7 @@ static int soc_button_probe(struct platform_device *pdev)
|
||
if (!priv->children[0] && !priv->children[1])
|
||
return -ENODEV;
|
||
|
||
- if (!id->driver_data)
|
||
+ if (!device_data || !device_data->button_info)
|
||
devm_kfree(dev, button_info);
|
||
|
||
return 0;
|
||
@@ -368,7 +381,7 @@ static int soc_button_probe(struct platform_device *pdev)
|
||
* is defined in section 2.8.7.2 of "Windows ACPI Design Guide for SoC
|
||
* Platforms"
|
||
*/
|
||
-static struct soc_button_info soc_button_PNP0C40[] = {
|
||
+static const struct soc_button_info soc_button_PNP0C40[] = {
|
||
{ "power", 0, EV_KEY, KEY_POWER, false, true },
|
||
{ "home", 1, EV_KEY, KEY_LEFTMETA, false, true },
|
||
{ "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false },
|
||
@@ -377,9 +390,77 @@ static struct soc_button_info soc_button_PNP0C40[] = {
|
||
{ }
|
||
};
|
||
|
||
+static const struct soc_device_data soc_device_PNP0C40 = {
|
||
+ .button_info = soc_button_PNP0C40,
|
||
+};
|
||
+
|
||
+/*
|
||
+ * Special device check for Surface Book 2 and Surface Pro (2017).
|
||
+ * Both, the Surface Pro 4 (surfacepro3_button.c) and the above mentioned
|
||
+ * devices use MSHW0040 for power and volume buttons, however the way they
|
||
+ * have to be addressed differs. Make sure that we only load this drivers
|
||
+ * for the correct devices by checking the OEM Platform Revision provided by
|
||
+ * the _DSM method.
|
||
+ */
|
||
+#define MSHW0040_DSM_REVISION 0x01
|
||
+#define MSHW0040_DSM_GET_OMPR 0x02 // get OEM Platform Revision
|
||
+static const guid_t MSHW0040_DSM_UUID =
|
||
+ GUID_INIT(0x6fd05c69, 0xcde3, 0x49f4, 0x95, 0xed, 0xab, 0x16, 0x65,
|
||
+ 0x49, 0x80, 0x35);
|
||
+
|
||
+static int soc_device_check_MSHW0040(struct device *dev)
|
||
+{
|
||
+ acpi_handle handle = ACPI_HANDLE(dev);
|
||
+ union acpi_object *result;
|
||
+ u64 oem_platform_rev = 0; // valid revisions are nonzero
|
||
+
|
||
+ // get OEM platform revision
|
||
+ result = acpi_evaluate_dsm_typed(handle, &MSHW0040_DSM_UUID,
|
||
+ MSHW0040_DSM_REVISION,
|
||
+ MSHW0040_DSM_GET_OMPR, NULL,
|
||
+ ACPI_TYPE_INTEGER);
|
||
+
|
||
+ if (result) {
|
||
+ oem_platform_rev = result->integer.value;
|
||
+ ACPI_FREE(result);
|
||
+ }
|
||
+
|
||
+ /*
|
||
+ * If the revision is zero here, the _DSM evaluation has failed. This
|
||
+ * indicates that we have a Pro 4 or Book 1 and this driver should not
|
||
+ * be used.
|
||
+ */
|
||
+ if (oem_platform_rev == 0)
|
||
+ return -ENODEV;
|
||
+
|
||
+ dev_dbg(dev, "OEM Platform Revision %llu\n", oem_platform_rev);
|
||
+
|
||
+ return 0;
|
||
+}
|
||
+
|
||
+/*
|
||
+ * Button infos for Microsoft Surface Book 2 and Surface Pro (2017).
|
||
+ * Obtained from DSDT/testing.
|
||
+ */
|
||
+static const struct soc_button_info soc_button_MSHW0040[] = {
|
||
+ { "power", 0, EV_KEY, KEY_POWER, false, true },
|
||
+ { "volume_up", 2, EV_KEY, KEY_VOLUMEUP, true, false },
|
||
+ { "volume_down", 4, EV_KEY, KEY_VOLUMEDOWN, true, false },
|
||
+ { }
|
||
+};
|
||
+
|
||
+static const struct soc_device_data soc_device_MSHW0040 = {
|
||
+ .button_info = soc_button_MSHW0040,
|
||
+ .check = soc_device_check_MSHW0040,
|
||
+};
|
||
+
|
||
static const struct acpi_device_id soc_button_acpi_match[] = {
|
||
- { "PNP0C40", (unsigned long)soc_button_PNP0C40 },
|
||
+ { "PNP0C40", (unsigned long)&soc_device_PNP0C40 },
|
||
{ "ACPI0011", 0 },
|
||
+
|
||
+ /* Microsoft Surface Devices (5th and 6th generation) */
|
||
+ { "MSHW0040", (unsigned long)&soc_device_MSHW0040 },
|
||
+
|
||
{ }
|
||
};
|
||
|
||
--
|
||
2.33.0
|
||
|
||
From 3495e149d8dc07d035fc87d0820b2e0938ed097b Mon Sep 17 00:00:00 2001
|
||
From: Hans de Goede <hdegoide@redhat.com>
|
||
Date: Sat, 5 Oct 2019 14:11:58 +0200
|
||
Subject: [PATCH] Input: soc_button_array - partial revert of support for newer
|
||
surface devices
|
||
|
||
Commit c394159310d0 ("Input: soc_button_array - add support for newer
|
||
surface devices") not only added support for the MSHW0040 ACPI HID,
|
||
but for some reason it also makes changes to the error handling of the
|
||
soc_button_lookup_gpio() call in soc_button_device_create(). Note ideally
|
||
this seamingly unrelated change would have been made in a separate commit,
|
||
with a message explaining the what and why of this change.
|
||
|
||
I guess this change may have been added to deal with -EPROBE_DEFER errors,
|
||
but in case of the existing support for PNP0C40 devices, treating
|
||
-EPROBE_DEFER as any other error is deliberate, see the comment this
|
||
commit adds for why.
|
||
|
||
The actual returning of -EPROBE_DEFER to the caller of soc_button_probe()
|
||
introduced by the new error checking causes a serious regression:
|
||
|
||
On devices with so called virtual GPIOs soc_button_lookup_gpio() will
|
||
always return -EPROBE_DEFER for these fake GPIOs, when this happens
|
||
during the second call of soc_button_device_create() we already have
|
||
successfully registered our first child. This causes the kernel to think
|
||
we are making progress with probing things even though we unregister the
|
||
child before again before we return the -EPROBE_DEFER. Since we are making
|
||
progress the kernel will retry deferred-probes again immediately ending
|
||
up stuck in a loop with the following showing in dmesg:
|
||
|
||
[ 124.022697] input: gpio-keys as /devices/platform/INTCFD9:00/gpio-keys.0.auto/input/input6537
|
||
[ 124.040764] input: gpio-keys as /devices/platform/INTCFD9:00/gpio-keys.0.auto/input/input6538
|
||
[ 124.056967] input: gpio-keys as /devices/platform/INTCFD9:00/gpio-keys.0.auto/input/input6539
|
||
[ 124.072143] input: gpio-keys as /devices/platform/INTCFD9:00/gpio-keys.0.auto/input/input6540
|
||
[ 124.092373] input: gpio-keys as /devices/platform/INTCFD9:00/gpio-keys.0.auto/input/input6541
|
||
[ 124.108065] input: gpio-keys as /devices/platform/INTCFD9:00/gpio-keys.0.auto/input/input6542
|
||
[ 124.128483] input: gpio-keys as /devices/platform/INTCFD9:00/gpio-keys.0.auto/input/input6543
|
||
[ 124.147141] input: gpio-keys as /devices/platform/INTCFD9:00/gpio-keys.0.auto/input/input6544
|
||
[ 124.165070] input: gpio-keys as /devices/platform/INTCFD9:00/gpio-keys.0.auto/input/input6545
|
||
[ 124.179775] input: gpio-keys as /devices/platform/INTCFD9:00/gpio-keys.0.auto/input/input6546
|
||
[ 124.202726] input: gpio-keys as /devices/platform/INTCFD9:00/gpio-keys.0.auto/input/input6547
|
||
<continues on and on and on>
|
||
|
||
And 1 CPU core being stuck at 100% and udev hanging since it is waiting
|
||
for the modprobe of soc_button_array to return.
|
||
|
||
This patch reverts the soc_button_lookup_gpio() error handling changes,
|
||
fixing this regression.
|
||
|
||
Fixes: c394159310d0 ("Input: soc_button_array - add support for newer surface devices")
|
||
BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=205031
|
||
Cc: Maximilian Luz <luzmaximilian@gmail.com>
|
||
Signed-off-by: Hans de Goede <hdegoede@redhat.com>
|
||
Patchset: surface-buttons
|
||
---
|
||
drivers/input/misc/soc_button_array.c | 17 ++++++++++++-----
|
||
1 file changed, 12 insertions(+), 5 deletions(-)
|
||
|
||
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
|
||
index 8f21c062c85d..5983733d78dd 100644
|
||
--- a/drivers/input/misc/soc_button_array.c
|
||
+++ b/drivers/input/misc/soc_button_array.c
|
||
@@ -96,11 +96,18 @@ soc_button_device_create(struct platform_device *pdev,
|
||
continue;
|
||
|
||
gpio = soc_button_lookup_gpio(&pdev->dev, info->acpi_index);
|
||
- if (gpio < 0 && gpio != -ENOENT) {
|
||
- error = gpio;
|
||
- goto err_free_mem;
|
||
- } else if (!gpio_is_valid(gpio)) {
|
||
- /* Skip GPIO if not present */
|
||
+ if (!gpio_is_valid(gpio)) {
|
||
+ /*
|
||
+ * Skip GPIO if not present. Note we deliberately
|
||
+ * ignore -EPROBE_DEFER errors here. On some devices
|
||
+ * Intel is using so called virtual GPIOs which are not
|
||
+ * GPIOs at all but some way for AML code to check some
|
||
+ * random status bits without need a custom opregion.
|
||
+ * In some cases the resources table we parse points to
|
||
+ * such a virtual GPIO, since these are not real GPIOs
|
||
+ * we do not have a driver for these so they will never
|
||
+ * show up, therefor we ignore -EPROBE_DEFER.
|
||
+ */
|
||
continue;
|
||
}
|
||
|
||
--
|
||
2.33.0
|
||
|
||
From 97852be9f07614c8f49c9aaa7308d550d952207d Mon Sep 17 00:00:00 2001
|
||
From: "Tsuchiya Yuto (kitakar5525)" <kitakar@gmail.com>
|
||
Date: Mon, 11 May 2020 17:40:21 +0900
|
||
Subject: [PATCH] Input: soc_button_array - fix Wdiscarded-qualifiers for
|
||
kernels below 4.20
|
||
MIME-Version: 1.0
|
||
Content-Type: text/plain; charset=UTF-8
|
||
Content-Transfer-Encoding: 8bit
|
||
|
||
There is a warning from compiler when building v4.19-surface kernel that
|
||
backported button patches from newer kernels.
|
||
|
||
drivers/input/misc/soc_button_array.c: In function ‘soc_button_probe’:
|
||
drivers/input/misc/soc_button_array.c:381:19: warning: passing argument 2 of ‘devm_kfree’ discards ‘const’ qualifier from pointer target type [-Wdiscarded-qualifiers]
|
||
381 | devm_kfree(dev, button_info);
|
||
| ^~~~~~~~~~~
|
||
In file included from ./include/linux/input.h:22,
|
||
from drivers/input/misc/soc_button_array.c:14:
|
||
./include/linux/device.h:695:50: note: expected ‘void *’ but argument is of type ‘const struct soc_button_info *’
|
||
695 | extern void devm_kfree(struct device *dev, void *p);
|
||
| ~~~~~~^
|
||
|
||
This warning happens bacause commit 0571967dfb5d25 ("devres: constify p
|
||
in devm_kfree()") has not been applied to v4.19 series (available after
|
||
v4.20-rc1).
|
||
|
||
This commit casts button_info to (void *) when calling devm_kfree() to
|
||
avoid compiler warning.
|
||
|
||
Fixes: b892fc124285ba ("Input: soc_button_array - Add support for newer surface devices")
|
||
Signed-off-by: Tsuchiya Yuto (kitakar5525) <kitakar@gmail.com>
|
||
Patchset: surface-buttons
|
||
---
|
||
drivers/input/misc/soc_button_array.c | 2 +-
|
||
1 file changed, 1 insertion(+), 1 deletion(-)
|
||
|
||
diff --git a/drivers/input/misc/soc_button_array.c b/drivers/input/misc/soc_button_array.c
|
||
index 5983733d78dd..c564ea99f47d 100644
|
||
--- a/drivers/input/misc/soc_button_array.c
|
||
+++ b/drivers/input/misc/soc_button_array.c
|
||
@@ -378,7 +378,7 @@ static int soc_button_probe(struct platform_device *pdev)
|
||
return -ENODEV;
|
||
|
||
if (!device_data || !device_data->button_info)
|
||
- devm_kfree(dev, button_info);
|
||
+ devm_kfree(dev, (void *)button_info);
|
||
|
||
return 0;
|
||
}
|
||
--
|
||
2.33.0
|
||
|