Update v5.4 patches

Changes:
 - SAM:
   - Retry more SAM requests on communication failure to increase
     stability.
   - Fix bug in PCI platform power state initialization preventing the
     Intel LPSS driver from loading on 7th generation Surface devices.

Links:
 - SAM: bfab2be7d3
 - kernel: a1bd6046ac
This commit is contained in:
Maximilian Luz 2020-11-09 21:58:18 +01:00
parent 7f370a054c
commit 32986cf19a
No known key found for this signature in database
GPG key ID: 70EC0937F6C26F02
7 changed files with 153 additions and 159 deletions

View file

@ -1,4 +1,4 @@
From 920bb46ce522c4e28237071fb3a93ec17ab56e49 Mon Sep 17 00:00:00 2001
From dbf8ee1341ecd608385453313b0b8152f9693dfa Mon Sep 17 00:00:00 2001
From: qzed <qzed@users.noreply.github.com>
Date: Tue, 17 Sep 2019 17:17:56 +0200
Subject: [PATCH] platform/x86: Surface 3 battery platform operation region

View file

@ -1,4 +1,4 @@
From 407b720283ead9bd4a5e6c3a5aa3c8c5fdbf2787 Mon Sep 17 00:00:00 2001
From 4d815ded70ab8aae76493f3d09cf9deb66a9db89 Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Sun, 18 Oct 2020 16:42:44 +0900
Subject: [PATCH] (surface3-oemb) add DMI matches for Surface 3 with broken DMI

View file

@ -1,4 +1,4 @@
From 57064d3d4c35d097736f2cdf8ef6f1e7562da433 Mon Sep 17 00:00:00 2001
From 0b87680b0c33a0aaa76a37daf9497aa7aa1e0027 Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Thu, 24 Sep 2020 18:02:06 +0900
Subject: [PATCH] mwifiex: pcie: skip cancel_work_sync() on reset failure path
@ -156,7 +156,7 @@ index f7ce9b6db6b4..72d0c01ff359 100644
--
2.29.2
From 742fc7984e000b2d3c5d39235da39e5fe3bf18af Mon Sep 17 00:00:00 2001
From 536562e35c51306f47a238942347db48c0f4885e Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Mon, 28 Sep 2020 17:46:49 +0900
Subject: [PATCH] mwifiex: pcie: add DMI-based quirk impl for Surface devices
@ -364,7 +364,7 @@ index 000000000000..5326ae7e5671
--
2.29.2
From c8bf3ea2f7e6a382afadf7feda8998614619f652 Mon Sep 17 00:00:00 2001
From 4ceb625d1a47f305ed9a21ff46112efe0f9e7372 Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Tue, 29 Sep 2020 17:25:22 +0900
Subject: [PATCH] mwifiex: pcie: add reset_d3cold quirk for Surface gen4+
@ -565,7 +565,7 @@ index 5326ae7e5671..8b9dcb5070d8 100644
--
2.29.2
From 9083372666e4be1331463944fdc85f9caf077236 Mon Sep 17 00:00:00 2001
From 37bcc6710b54af86232f898e2ac1c9001f00138c Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Tue, 29 Sep 2020 17:32:22 +0900
Subject: [PATCH] mwifiex: pcie: add reset_wsid quirk for Surface 3
@ -744,7 +744,7 @@ index 8b9dcb5070d8..3ef7440418e3 100644
--
2.29.2
From b61057bb3c00b1a45e706ec25fedf92f585f2196 Mon Sep 17 00:00:00 2001
From b0e6eba5247ab5a40628e3f3680d52c91ecfb951 Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Wed, 30 Sep 2020 18:08:24 +0900
Subject: [PATCH] mwifiex: pcie: (OEMB) add quirk for Surface 3 with broken DMI
@ -806,7 +806,7 @@ index f0a6fa0a7ae5..34dcd84f02a6 100644
--
2.29.2
From fb2339ab3530a8007e8a0293fae1f50c41ee25b6 Mon Sep 17 00:00:00 2001
From 94041b7af83160ab418fa9657969537921435566 Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Thu, 24 Sep 2020 01:56:29 +0900
Subject: [PATCH] mwifiex: fix mwifiex_shutdown_sw() causing sw reset failure
@ -883,7 +883,7 @@ index d14e55e3c9da..5894566ec480 100644
--
2.29.2
From 3fc9d46d5b02f346a227e48546618c85c01f4635 Mon Sep 17 00:00:00 2001
From 90bd2981ca5273f2409210788b290440fa7b6106 Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Thu, 24 Sep 2020 01:56:34 +0900
Subject: [PATCH] mwifiex: pcie: use shutdown_sw()/reinit_sw() on
@ -1025,7 +1025,7 @@ index 263d918767bd..bd6791dc3a0f 100644
--
2.29.2
From b2c53074824e2f54b14ef972e0b947d5e94d1961 Mon Sep 17 00:00:00 2001
From 4628465f444ed13a728fd46d791892ac436b6541 Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Mon, 24 Aug 2020 17:11:35 +0900
Subject: [PATCH] mwifiex: pcie: add enable_device_dump module parameter
@ -1074,7 +1074,7 @@ index bd6791dc3a0f..d7ff898c1767 100644
--
2.29.2
From b7071b89e24c1cf97dd4190e1cb55e35cba74bbc Mon Sep 17 00:00:00 2001
From cd1ec33e59ff1202669c8f3624319dcedc345b95 Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Sun, 4 Oct 2020 00:11:49 +0900
Subject: [PATCH] mwifiex: pcie: disable bridge_d3 for Surface gen4+
@ -1229,7 +1229,7 @@ index 3ef7440418e3..a95ebac06e13 100644
--
2.29.2
From dfd218b1815eff411722992ebd18c1d7dd00c66e Mon Sep 17 00:00:00 2001
From da5ac4ee8acf649ab495c662e3b1e86415f576ce Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Sun, 4 Oct 2020 00:25:48 +0900
Subject: [PATCH] mwifiex: add allow_ps_mode module parameter
@ -1291,7 +1291,7 @@ index 9e6dc289ec3e..20f5ee3fe7e3 100644
--
2.29.2
From bb33cb017be76dff82f01e05ecb27581fdbdb2a8 Mon Sep 17 00:00:00 2001
From 02024fe7fa192bf5f5ba2e96d450067ea113c56e Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Sun, 4 Oct 2020 00:38:48 +0900
Subject: [PATCH] mwifiex: print message when changing ps_mode
@ -1326,7 +1326,7 @@ index 20f5ee3fe7e3..8020a2929069 100644
--
2.29.2
From 2971cc13ce677cb3512beb4ab96d39a4b2937443 Mon Sep 17 00:00:00 2001
From a41473e357bc9897c7b19faa5b1be5b8c839eb23 Mon Sep 17 00:00:00 2001
From: Tsuchiya Yuto <kitakar@gmail.com>
Date: Sun, 4 Oct 2020 00:59:37 +0900
Subject: [PATCH] mwifiex: disable ps_mode explicitly by default instead

View file

@ -1,4 +1,4 @@
From f46f184003cfb534077e48c4f56346af3d84a399 Mon Sep 17 00:00:00 2001
From eed20d079f4b88b004987ef649df7fa792532acf Mon Sep 17 00:00:00 2001
From: Dorian Stoll <dorian.stoll@tmsp.io>
Date: Mon, 27 Jan 2020 21:16:20 +0100
Subject: [PATCH] mei: Add IPTS device IDs
@ -53,7 +53,7 @@ index 75ab2ffbf235..78790904d77c 100644
--
2.29.2
From deb28840b7d00286d576e36e6493b1d3c209808c Mon Sep 17 00:00:00 2001
From 753755e1044d9e1a04b50df64ee65be4bfb5ea5c Mon Sep 17 00:00:00 2001
From: Dorian Stoll <dorian.stoll@tmsp.io>
Date: Fri, 20 Dec 2019 23:15:58 +0100
Subject: [PATCH] uapi: Add MEI bus ID
@ -79,7 +79,7 @@ index 9a61c28ed3ae..47fc20975245 100644
--
2.29.2
From 7c1cd0659188f679bc0e70271e513cbeb8cca983 Mon Sep 17 00:00:00 2001
From f7f03f4bb0e8f0adf2aaf23e1ab7a4da468a2b05 Mon Sep 17 00:00:00 2001
From: Dorian Stoll <dorian.stoll@tmsp.io>
Date: Mon, 27 Jan 2020 21:22:42 +0100
Subject: [PATCH] input: Add support for Intel Precise Touch & Stylus

View file

@ -1,4 +1,4 @@
From 2f8c97dac94f186ec0e48105d630679b4bd66d0d Mon Sep 17 00:00:00 2001
From c54eb171bdb93dfdd188cfee34c363ab27ab04d0 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sun, 16 Aug 2020 23:39:56 +0200
Subject: [PATCH] platform/x86: Add Driver to set up lid GPEs on MS Surface

View file

@ -1,4 +1,4 @@
From a5ebb9332254f494203c6d3a576df789e6074495 Mon Sep 17 00:00:00 2001
From 1fc81386c040856a80d56f2cfbc03d656eef6642 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 25 Jul 2020 17:19:53 +0200
Subject: [PATCH] i2c: acpi: Implement RawBytes read access
@ -109,7 +109,7 @@ index c70983780ae7..1c90651161a6 100644
--
2.29.2
From aee5409945fc3b0d30d8407e60aa3095e438dd37 Mon Sep 17 00:00:00 2001
From 3a3bd6bfb90b3e08b24c04baac718652d4d24b61 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sun, 6 Sep 2020 04:01:19 +0200
Subject: [PATCH] platform/x86: Add driver for Surface Book 1 dGPU switch

View file

@ -1,4 +1,4 @@
From ac17033208f929d076dd302839c9473648d2958d Mon Sep 17 00:00:00 2001
From 4d748f3baa99a037bcf82e0eeadb37f9f414725f Mon Sep 17 00:00:00 2001
From: qzed <qzed@users.noreply.github.com>
Date: Mon, 26 Aug 2019 01:11:08 +0200
Subject: [PATCH] ACPI: Fix buffer/integer type mismatch
@ -60,7 +60,7 @@ index d3d2dbfba680..0b7f617a6e9b 100644
--
2.29.2
From a757e866a23d47d85adda8e734fd9f4183d12fac Mon Sep 17 00:00:00 2001
From d92ec71cdcfd601d5ca8b2b8606d45ee47b8f2e3 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Tue, 24 Sep 2019 17:38:12 +0200
Subject: [PATCH] serdev: Add ACPI devices by ResourceSource field
@ -248,7 +248,7 @@ index a9719858c950..ce5309d00280 100644
--
2.29.2
From 09933f9205430ef74c98c492d40a3423feed3165 Mon Sep 17 00:00:00 2001
From 6d87a01f7841f9c287607adec3604cbf16292453 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Thu, 29 Oct 2020 22:04:38 +0100
Subject: [PATCH] PCI: Allow D3cold for hot-plug ports on Surface Books
@ -333,90 +333,69 @@ index b1b2c8ddbc92..15566ec8f75d 100644
--
2.29.2
From 0e455871fcc6d9ea928be2846e137c4f5c48dd15 Mon Sep 17 00:00:00 2001
From da5f35bad772a6854c80df04f6710a2842b3d040 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 31 Oct 2020 19:48:06 +0100
Subject: [PATCH] PCI: Update platform power state when updating PCI state
Date: Mon, 9 Nov 2020 14:23:00 +0100
Subject: [PATCH] PCI: Run platform power transition on initial D0 entry
On some devices and platforms, the initial platform power state is not
in sync with the power state of the PCI device.
Specifically, on the Surface Book 2 and 3, some ACPI power regions that
should be "on" for the D0 state (and others) are initialized as "off" in
ACPI, whereas the PCI device is in D0. As the state is updated in
pci_enable_device_flags() without ensuring that the platform state is
also updated, the power resource will never be properly turned on.
Instead, it lives in a sort of on-but-marked-as-off zombie-state, which
confuses things down the line when attempting to transition the device
into D3cold: As the resource is already marked as off, it won't be
turned off and the device does not fully enter D3cold, causing increased
power consumption during (runtime-)suspend.
pci_enable_device_flags() updates the state of a PCI device by reading
from the the PCI_PM_CTRL register. This may change the stored power
state of the device without running the appropriate platform power
transition.
Ensuring that the platform power state is in sync with the PCI power
state when updating the latter guarantees that all required ACPI power
regions are powered on/off in accordance with the requirements
(specified in the ACPI _PRn fields) for the current PCI power state.
Due to the stored power-state being changed, the later call to
pci_set_power_state(..., PCI_D0) in do_pci_enable_device() can evaluate
to a no-op if the stored state has been changed to D0 via that. This
will then prevent the appropriate platform power transition to be run,
which can on some devices and platforms lead to platform and PCI power
state being entirely different, i.e. out-of-sync. On ACPI platforms,
this can lead to power resources not being turned on, even though they
are marked as required for D0.
Specifically, on the Microsoft Surface Book 2 and 3, some ACPI power
regions that should be "on" for the D0 state (and others) are
initialized as "off" in ACPI, whereas the PCI device is in D0. As the
state is updated in pci_enable_device_flags() without ensuring that the
platform state is also updated, the power resource will never be
properly turned on. Instead, it lives in a sort of on-but-marked-as-off
zombie-state, which confuses things down the line when attempting to
transition the device into D3cold: As the resource is already marked as
off, it won't be turned off and the device does not fully enter D3cold,
causing increased power consumption during (runtime-)suspend.
By replacing pci_set_power_state() in do_pci_enable_device() with
pci_power_up(), we can force pci_platform_power_transition() to be
called, which will then check if the platform power state needs updating
and appropriate actions need to be taken.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Patchset: surface-sam
---
drivers/pci/pci.c | 30 ++++++++++++++++++++++++++++--
1 file changed, 28 insertions(+), 2 deletions(-)
drivers/pci/pci.c | 4 +---
1 file changed, 1 insertion(+), 3 deletions(-)
diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c
index 15566ec8f75d..6839053db5a5 100644
index 15566ec8f75d..9b0a591fc60b 100644
--- a/drivers/pci/pci.c
+++ b/drivers/pci/pci.c
@@ -1663,7 +1663,7 @@ static void pci_enable_bridge(struct pci_dev *dev)
static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)
{
struct pci_dev *bridge;
- int err;
+ int err = 0;
int i, bars = 0;
@@ -1596,9 +1596,7 @@ static int do_pci_enable_device(struct pci_dev *dev, int bars)
u16 cmd;
u8 pin;
/*
@@ -1673,9 +1673,35 @@ static int pci_enable_device_flags(struct pci_dev *dev, unsigned long flags)
* (e.g. if the device really is in D0 at enable time).
*/
if (dev->pm_cap) {
+ pci_power_t current_state;
u16 pmcsr;
+
pci_read_config_word(dev, dev->pm_cap + PCI_PM_CTRL, &pmcsr);
- dev->current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
+ current_state = (pmcsr & PCI_PM_CTRL_STATE_MASK);
+
+ /*
+ * On some platforms, the initial power state may not be in
+ * sync with the PCI power state. Specifically, on ACPI based
+ * platforms, power-resources for the current state may not
+ * have been properly enabled (or power-resources not required
+ * for the current state disabled) yet. Thus, ensure that the
+ * platform power state reflects the PCI state.
+ *
+ * Update platform state before actually setting current state
+ * so that it can still be accessed in platform code, if
+ * necessary.
+ */
+ if (platform_pci_power_manageable(dev))
+ err = platform_pci_set_power_state(dev, current_state);
+
+ // always update current state
+ dev->current_state = current_state;
+
+ if (err) {
+ pci_err(dev, "failed to update platform power state: %d\n",
+ err);
+ return err;
+ }
}
- err = pci_set_power_state(dev, PCI_D0);
- if (err < 0 && err != -EIO)
- return err;
+ pci_power_up(dev);
if (atomic_inc_return(&dev->enable_cnt) > 1)
bridge = pci_upstream_bridge(dev);
if (bridge)
--
2.29.2
From fd5cd1327bf1d3ad4afae59883c72377e1c4afd3 Mon Sep 17 00:00:00 2001
From f8142da29f19db03995420b7f8e798c38ae03200 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 31 Oct 2020 20:46:33 +0100
Subject: [PATCH] PCI: Add sysfs attribute for PCI device power state
@ -489,7 +468,7 @@ index e401f040f157..418927872ae6 100644
--
2.29.2
From b0dc7bcd746fd167d16f35f298c099797be5f7a3 Mon Sep 17 00:00:00 2001
From 9f6c88bb06a99de23bf214f8d5b5bea49c164d09 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Mon, 17 Aug 2020 01:23:20 +0200
Subject: [PATCH] misc: surface_sam: Add file2alias support for Surface SAM
@ -591,7 +570,7 @@ index c91eba751804..bc06f7631200 100644
--
2.29.2
From 21fd6098eee8750891488d2e1e99d36bea9f17ac Mon Sep 17 00:00:00 2001
From 9f94a0785a1171b88ccf73cffd472dd2fd973dae Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Mon, 17 Aug 2020 01:44:30 +0200
Subject: [PATCH] misc: Add support for Surface System Aggregator Module
@ -631,12 +610,12 @@ Patchset: surface-sam
.../clients/surface_acpi_notify.c | 884 ++++++
.../clients/surface_aggregator_cdev.c | 299 ++
.../clients/surface_aggregator_registry.c | 609 ++++
.../clients/surface_battery.c | 1195 ++++++++
.../surface_aggregator/clients/surface_dtx.c | 1277 ++++++++
.../surface_aggregator/clients/surface_hid.c | 925 ++++++
.../clients/surface_battery.c | 1192 ++++++++
.../surface_aggregator/clients/surface_dtx.c | 1279 +++++++++
.../surface_aggregator/clients/surface_hid.c | 922 ++++++
.../clients/surface_hotplug.c | 269 ++
.../clients/surface_perfmode.c | 122 +
drivers/misc/surface_aggregator/controller.c | 2555 +++++++++++++++++
drivers/misc/surface_aggregator/controller.c | 2557 +++++++++++++++++
drivers/misc/surface_aggregator/controller.h | 288 ++
drivers/misc/surface_aggregator/core.c | 842 ++++++
drivers/misc/surface_aggregator/ssh_msgb.h | 201 ++
@ -649,14 +628,14 @@ Patchset: surface-sam
drivers/misc/surface_aggregator/trace.h | 625 ++++
include/linux/mod_devicetable.h | 5 +-
include/linux/surface_acpi_notify.h | 39 +
include/linux/surface_aggregator/controller.h | 815 ++++++
include/linux/surface_aggregator/controller.h | 832 ++++++
include/linux/surface_aggregator/device.h | 430 +++
include/linux/surface_aggregator/serial_hub.h | 659 +++++
include/uapi/linux/surface_aggregator/cdev.h | 58 +
include/uapi/linux/surface_aggregator/dtx.h | 150 +
scripts/mod/devicetable-offsets.c | 3 +-
scripts/mod/file2alias.c | 10 +-
48 files changed, 18772 insertions(+), 7 deletions(-)
48 files changed, 18787 insertions(+), 7 deletions(-)
create mode 100644 Documentation/driver-api/surface_aggregator/client-api.rst
create mode 100644 Documentation/driver-api/surface_aggregator/client.rst
create mode 100644 Documentation/driver-api/surface_aggregator/clients/cdev.rst
@ -3385,7 +3364,7 @@ index 000000000000..7320922ba755
+obj-$(CONFIG_SURFACE_PERFMODE) += surface_perfmode.o
diff --git a/drivers/misc/surface_aggregator/clients/surface_acpi_notify.c b/drivers/misc/surface_aggregator/clients/surface_acpi_notify.c
new file mode 100644
index 000000000000..9010f3aafd28
index 000000000000..7a5b8f280036
--- /dev/null
+++ b/drivers/misc/surface_aggregator/clients/surface_acpi_notify.c
@@ -0,0 +1,884 @@
@ -3977,8 +3956,8 @@ index 000000000000..9010f3aafd28
+ return san_rqst_fixup_suspended(d, &rqst, buffer);
+ }
+
+ status = ssam_retry(ssam_request_sync_onstack, SAN_REQUEST_NUM_TRIES,
+ d->ctrl, &rqst, &rsp, SAN_GSB_MAX_RQSX_PAYLOAD);
+ status = __ssam_retry(ssam_request_sync_onstack, SAN_REQUEST_NUM_TRIES,
+ d->ctrl, &rqst, &rsp, SAN_GSB_MAX_RQSX_PAYLOAD);
+
+ if (!status) {
+ gsb_rqsx_response_success(buffer, rsp.pointer, rsp.length);
@ -4580,7 +4559,7 @@ index 000000000000..f5e81cd67357
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/surface_aggregator/clients/surface_aggregator_registry.c b/drivers/misc/surface_aggregator/clients/surface_aggregator_registry.c
new file mode 100644
index 000000000000..282f4409535b
index 000000000000..215308c79666
--- /dev/null
+++ b/drivers/misc/surface_aggregator/clients/surface_aggregator_registry.c
@@ -0,0 +1,609 @@
@ -4868,7 +4847,7 @@ index 000000000000..282f4409535b
+ u8 opmode;
+ int status;
+
+ status = ssam_bas_query_opmode(sdev->ctrl, &opmode);
+ status = ssam_retry(ssam_bas_query_opmode, sdev->ctrl, &opmode);
+ if (status < 0) {
+ dev_err(&sdev->dev, "failed to query base state: %d\n", status);
+ return status;
@ -5195,10 +5174,10 @@ index 000000000000..282f4409535b
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/surface_aggregator/clients/surface_battery.c b/drivers/misc/surface_aggregator/clients/surface_battery.c
new file mode 100644
index 000000000000..e1e0804eeb54
index 000000000000..7ed9ba3f98d7
--- /dev/null
+++ b/drivers/misc/surface_aggregator/clients/surface_battery.c
@@ -0,0 +1,1195 @@
@@ -0,0 +1,1192 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Surface battery and AC device driver.
@ -5220,9 +5199,6 @@ index 000000000000..e1e0804eeb54
+
+#include <linux/surface_aggregator/device.h>
+
+#define SPWR_RETRY 3
+#define spwr_retry(fn, args...) ssam_retry(fn, SPWR_RETRY, args)
+
+#define SPWR_AC_BAT_UPDATE_DELAY msecs_to_jiffies(5000)
+
+
@ -5451,7 +5427,7 @@ index 000000000000..e1e0804eeb54
+
+static int spwr_battery_load_sta(struct spwr_battery_device *bat)
+{
+ return spwr_retry(ssam_bat_get_sta, bat->sdev, &bat->sta);
+ return ssam_retry(ssam_bat_get_sta, bat->sdev, &bat->sta);
+}
+
+static int spwr_battery_load_bix(struct spwr_battery_device *bat)
@ -5461,7 +5437,7 @@ index 000000000000..e1e0804eeb54
+ if (!spwr_battery_present(bat))
+ return 0;
+
+ status = spwr_retry(ssam_bat_get_bix, bat->sdev, &bat->bix);
+ status = ssam_retry(ssam_bat_get_bix, bat->sdev, &bat->bix);
+
+ // enforce NULL terminated strings in case anything goes wrong...
+ bat->bix.model[ARRAY_SIZE(bat->bix.model) - 1] = 0;
@ -5477,7 +5453,7 @@ index 000000000000..e1e0804eeb54
+ if (!spwr_battery_present(bat))
+ return 0;
+
+ return spwr_retry(ssam_bat_get_bst, bat->sdev, &bat->bst);
+ return ssam_retry(ssam_bat_get_bst, bat->sdev, &bat->bst);
+}
+
+static int spwr_battery_set_alarm_unlocked(struct spwr_battery_device *bat,
@ -5486,7 +5462,7 @@ index 000000000000..e1e0804eeb54
+ __le32 value_le = cpu_to_le32(value);
+
+ bat->alarm = value;
+ return spwr_retry(ssam_bat_set_btp, bat->sdev, &value_le);
+ return ssam_retry(ssam_bat_set_btp, bat->sdev, &value_le);
+}
+
+static int spwr_battery_set_alarm(struct spwr_battery_device *bat, u32 value)
@ -5563,7 +5539,7 @@ index 000000000000..e1e0804eeb54
+ int status;
+ u32 old = ac->state;
+
+ status = spwr_retry(ssam_bat_get_psrc, ac->sdev, &ac->state);
+ status = ssam_retry(ssam_bat_get_psrc, ac->sdev, &ac->state);
+ if (status < 0)
+ return status;
+
@ -6091,7 +6067,7 @@ index 000000000000..e1e0804eeb54
+ int status;
+
+ // make sure the device is there and functioning properly
+ status = spwr_retry(ssam_bat_get_sta, ac->sdev, &sta);
+ status = ssam_retry(ssam_bat_get_sta, ac->sdev, &sta);
+ if (status)
+ return status;
+
@ -6154,7 +6130,7 @@ index 000000000000..e1e0804eeb54
+ int status;
+
+ // make sure the device is there and functioning properly
+ status = spwr_retry(ssam_bat_get_sta, bat->sdev, &sta);
+ status = ssam_retry(ssam_bat_get_sta, bat->sdev, &sta);
+ if (status)
+ return status;
+
@ -6396,10 +6372,10 @@ index 000000000000..e1e0804eeb54
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/surface_aggregator/clients/surface_dtx.c b/drivers/misc/surface_aggregator/clients/surface_dtx.c
new file mode 100644
index 000000000000..588931ddcb48
index 000000000000..346b54848b8f
--- /dev/null
+++ b/drivers/misc/surface_aggregator/clients/surface_dtx.c
@@ -0,0 +1,1277 @@
@@ -0,0 +1,1279 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Surface Book (gen. 2 and later) detachment system (DTX) driver.
@ -6688,7 +6664,7 @@ index 000000000000..588931ddcb48
+ struct sdtx_base_info info;
+ int status;
+
+ status = ssam_bas_get_base(ddev->ctrl, &raw);
+ status = ssam_retry(ssam_bas_get_base, ddev->ctrl, &raw);
+ if (status < 0)
+ return status;
+
@ -6706,7 +6682,7 @@ index 000000000000..588931ddcb48
+ u8 mode;
+ int status;
+
+ status = ssam_bas_get_device_mode(ddev->ctrl, &mode);
+ status = ssam_retry(ssam_bas_get_device_mode, ddev->ctrl, &mode);
+ if (status < 0)
+ return status;
+
@ -6718,7 +6694,7 @@ index 000000000000..588931ddcb48
+ u8 latch;
+ int status;
+
+ status = ssam_bas_get_latch_status(ddev->ctrl, &latch);
+ status = ssam_retry(ssam_bas_get_latch_status, ddev->ctrl, &latch);
+ if (status < 0)
+ return status;
+
@ -6740,22 +6716,22 @@ index 000000000000..588931ddcb48
+ return 0;
+
+ case SDTX_IOCTL_LATCH_LOCK:
+ return ssam_bas_latch_lock(ddev->ctrl);
+ return ssam_retry(ssam_bas_latch_lock, ddev->ctrl);
+
+ case SDTX_IOCTL_LATCH_UNLOCK:
+ return ssam_bas_latch_unlock(ddev->ctrl);
+ return ssam_retry(ssam_bas_latch_unlock, ddev->ctrl);
+
+ case SDTX_IOCTL_LATCH_REQUEST:
+ return ssam_bas_latch_request(ddev->ctrl);
+ return ssam_retry(ssam_bas_latch_request, ddev->ctrl);
+
+ case SDTX_IOCTL_LATCH_CONFIRM:
+ return ssam_bas_latch_confirm(ddev->ctrl);
+ return ssam_retry(ssam_bas_latch_confirm, ddev->ctrl);
+
+ case SDTX_IOCTL_LATCH_HEARTBEAT:
+ return ssam_bas_latch_heartbeat(ddev->ctrl);
+ return ssam_retry(ssam_bas_latch_heartbeat, ddev->ctrl);
+
+ case SDTX_IOCTL_LATCH_CANCEL:
+ return ssam_bas_latch_cancel(ddev->ctrl);
+ return ssam_retry(ssam_bas_latch_cancel, ddev->ctrl);
+
+ case SDTX_IOCTL_GET_BASE_INFO:
+ return sdtx_ioctl_get_base_info(ddev,
@ -7136,14 +7112,14 @@ index 000000000000..588931ddcb48
+ ddev = container_of(work, struct sdtx_device, mode_work.work);
+
+ // get operation mode
+ status = ssam_bas_get_device_mode(ddev->ctrl, &mode);
+ status = ssam_retry(ssam_bas_get_device_mode, ddev->ctrl, &mode);
+ if (status) {
+ dev_err(ddev->dev, "failed to get device mode: %d\n", status);
+ return;
+ }
+
+ // get base info
+ status = ssam_bas_get_base(ddev->ctrl, &base);
+ status = ssam_retry(ssam_bas_get_base, ddev->ctrl, &base);
+ if (status) {
+ dev_err(ddev->dev, "failed to get base info: %d\n", status);
+ return;
@ -7287,19 +7263,19 @@ index 000000000000..588931ddcb48
+ */
+ smp_mb__after_atomic();
+
+ status = ssam_bas_get_base(ddev->ctrl, &base);
+ status = ssam_retry(ssam_bas_get_base, ddev->ctrl, &base);
+ if (status) {
+ dev_err(ddev->dev, "failed to get base state: %d\n", status);
+ return;
+ }
+
+ status = ssam_bas_get_device_mode(ddev->ctrl, &mode);
+ status = ssam_retry(ssam_bas_get_device_mode, ddev->ctrl, &mode);
+ if (status) {
+ dev_err(ddev->dev, "failed to get device mode: %d\n", status);
+ return;
+ }
+
+ status = ssam_bas_get_latch_status(ddev->ctrl, &latch);
+ status = ssam_retry(ssam_bas_get_latch_status, ddev->ctrl, &latch);
+ if (status) {
+ dev_err(ddev->dev, "failed to get latch status: %d\n", status);
+ return;
@ -7377,15 +7353,17 @@ index 000000000000..588931ddcb48
+ * Note that we also need to do this before registring the event
+ * notifier, as that may access the state values.
+ */
+ status = ssam_bas_get_base(ddev->ctrl, &ddev->state.base);
+ status = ssam_retry(ssam_bas_get_base, ddev->ctrl, &ddev->state.base);
+ if (status)
+ return status;
+
+ status = ssam_bas_get_device_mode(ddev->ctrl, &ddev->state.device_mode);
+ status = ssam_retry(ssam_bas_get_device_mode, ddev->ctrl,
+ &ddev->state.device_mode);
+ if (status)
+ return status;
+
+ status = ssam_bas_get_latch_status(ddev->ctrl, &ddev->state.latch_status);
+ status = ssam_retry(ssam_bas_get_latch_status, ddev->ctrl,
+ &ddev->state.latch_status);
+ if (status)
+ return status;
+
@ -7679,10 +7657,10 @@ index 000000000000..588931ddcb48
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/surface_aggregator/clients/surface_hid.c b/drivers/misc/surface_aggregator/clients/surface_hid.c
new file mode 100644
index 000000000000..60691800e7e5
index 000000000000..033abc9aa95e
--- /dev/null
+++ b/drivers/misc/surface_aggregator/clients/surface_hid.c
@@ -0,0 +1,925 @@
@@ -0,0 +1,922 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Surface System Aggregator Module (SSAM) HID device driver.
@ -7707,9 +7685,6 @@ index 000000000000..60691800e7e5
+#include <linux/surface_aggregator/controller.h>
+#include <linux/surface_aggregator/device.h>
+
+#define SHID_RETRY 3
+#define shid_retry(fn, args...) ssam_retry(fn, SHID_RETRY, args)
+
+
+enum surface_hid_descriptor_entry {
+ SURFACE_HID_DESC_HID = 0,
@ -7831,7 +7806,7 @@ index 000000000000..60691800e7e5
+
+ rsp.length = 0;
+
+ status = shid_retry(ssam_request_sync_onstack, shid->ctrl,
+ status = ssam_retry(ssam_request_sync_onstack, shid->ctrl,
+ &rqst, &rsp, sizeof(*slice));
+ if (status)
+ return status;
@ -7883,7 +7858,7 @@ index 000000000000..60691800e7e5
+
+ buf[0] = report_id;
+
+ return shid_retry(ssam_request_sync, shid->ctrl, &rqst, NULL);
+ return ssam_retry(ssam_request_sync, shid->ctrl, &rqst, NULL);
+}
+
+static int ssam_hid_get_raw_report(struct surface_hid_device *shid,
@ -7904,7 +7879,7 @@ index 000000000000..60691800e7e5
+ rsp.length = 0;
+ rsp.pointer = buf;
+
+ return shid_retry(ssam_request_sync_onstack, shid->ctrl, &rqst, &rsp,
+ return ssam_retry(ssam_request_sync_onstack, shid->ctrl, &rqst, &rsp,
+ sizeof(report_id));
+}
+
@ -7989,7 +7964,7 @@ index 000000000000..60691800e7e5
+ rsp.length = 0;
+ rsp.pointer = buf;
+
+ status = shid_retry(ssam_request_sync_onstack, shid->ctrl, &rqst, &rsp,
+ status = ssam_retry(ssam_request_sync_onstack, shid->ctrl, &rqst, &rsp,
+ sizeof(entry));
+ if (status)
+ return status;
@ -8016,7 +7991,7 @@ index 000000000000..60691800e7e5
+ rqst.length = sizeof(value_u8);
+ rqst.payload = &value_u8;
+
+ return shid_retry(ssam_request_sync_onstack, shid->ctrl, &rqst, NULL,
+ return ssam_retry(ssam_request_sync_onstack, shid->ctrl, &rqst, NULL,
+ sizeof(value_u8));
+}
+
@ -8040,7 +8015,7 @@ index 000000000000..60691800e7e5
+ rsp.length = 0;
+ rsp.pointer = buf;
+
+ status = shid_retry(ssam_request_sync_onstack, shid->ctrl, &rqst, &rsp,
+ status = ssam_retry(ssam_request_sync_onstack, shid->ctrl, &rqst, &rsp,
+ sizeof(payload));
+ if (status)
+ return status;
@ -8885,7 +8860,7 @@ index 000000000000..9afddfc6a358
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/surface_aggregator/clients/surface_perfmode.c b/drivers/misc/surface_aggregator/clients/surface_perfmode.c
new file mode 100644
index 000000000000..006601b3bea6
index 000000000000..e13f4995b28b
--- /dev/null
+++ b/drivers/misc/surface_aggregator/clients/surface_perfmode.c
@@ -0,0 +1,122 @@
@ -8941,7 +8916,7 @@ index 000000000000..006601b3bea6
+ if (mode < __SAM_PERF_MODE__MIN || mode > __SAM_PERF_MODE__MAX)
+ return -EINVAL;
+
+ return __ssam_tmp_perf_mode_set(sdev, &mode_le);
+ return ssam_retry(__ssam_tmp_perf_mode_set, sdev, &mode_le);
+}
+
+static ssize_t perf_mode_show(struct device *dev, struct device_attribute *attr,
@ -8951,7 +8926,7 @@ index 000000000000..006601b3bea6
+ struct ssam_perf_info info;
+ int status;
+
+ status = ssam_tmp_perf_mode_get(sdev, &info);
+ status = ssam_retry(ssam_tmp_perf_mode_get, sdev, &info);
+ if (status) {
+ dev_err(dev, "failed to get current performance mode: %d\n",
+ status);
@ -9013,10 +8988,10 @@ index 000000000000..006601b3bea6
+MODULE_LICENSE("GPL");
diff --git a/drivers/misc/surface_aggregator/controller.c b/drivers/misc/surface_aggregator/controller.c
new file mode 100644
index 000000000000..c5d19feb4d38
index 000000000000..feee7c7c5945
--- /dev/null
+++ b/drivers/misc/surface_aggregator/controller.c
@@ -0,0 +1,2555 @@
@@ -0,0 +1,2557 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Main SSAM/SSH controller structure and functionality.
@ -10836,7 +10811,8 @@ index 000000000000..c5d19feb4d38
+ result.length = 0;
+ result.pointer = buf;
+
+ status = ssam_request_sync_onstack(ctrl, &rqst, &result, sizeof(params));
+ status = ssam_retry(ssam_request_sync_onstack, ctrl, &rqst, &result,
+ sizeof(params));
+ if (status) {
+ ssam_err(ctrl, "failed to enable event source (tc: 0x%02x, "
+ "iid: 0x%02x, reg: 0x%02x)\n", id.target_category,
@ -10904,7 +10880,8 @@ index 000000000000..c5d19feb4d38
+ result.length = 0;
+ result.pointer = buf;
+
+ status = ssam_request_sync_onstack(ctrl, &rqst, &result, sizeof(params));
+ status = ssam_retry(ssam_request_sync_onstack, ctrl, &rqst, &result,
+ sizeof(params));
+ if (status) {
+ ssam_err(ctrl, "failed to disable event source (tc: 0x%02x, "
+ "iid: 0x%02x, reg: 0x%02x)\n", id.target_category,
@ -10938,7 +10915,7 @@ index 000000000000..c5d19feb4d38
+ __le32 __version;
+ int status;
+
+ status = ssam_ssh_get_firmware_version(ctrl, &__version);
+ status = ssam_retry(ssam_ssh_get_firmware_version, ctrl, &__version);
+ if (status)
+ return status;
+
@ -10980,7 +10957,7 @@ index 000000000000..c5d19feb4d38
+
+ ssam_dbg(ctrl, "pm: notifying display off\n");
+
+ status = ssam_ssh_notif_display_off(ctrl, &response);
+ status = ssam_retry(ssam_ssh_notif_display_off, ctrl, &response);
+ if (status)
+ return status;
+
@ -11019,7 +10996,7 @@ index 000000000000..c5d19feb4d38
+
+ ssam_dbg(ctrl, "pm: notifying display on\n");
+
+ status = ssam_ssh_notif_display_on(ctrl, &response);
+ status = ssam_retry(ssam_ssh_notif_display_on, ctrl, &response);
+ if (status)
+ return status;
+
@ -11061,7 +11038,7 @@ index 000000000000..c5d19feb4d38
+
+ ssam_dbg(ctrl, "pm: notifying D0 exit\n");
+
+ status = ssam_ssh_notif_d0_exit(ctrl, &response);
+ status = ssam_retry(ssam_ssh_notif_d0_exit, ctrl, &response);
+ if (status)
+ return status;
+
@ -11103,7 +11080,7 @@ index 000000000000..c5d19feb4d38
+
+ ssam_dbg(ctrl, "pm: notifying D0 entry\n");
+
+ status = ssam_ssh_notif_d0_entry(ctrl, &response);
+ status = ssam_retry(ssam_ssh_notif_d0_entry, ctrl, &response);
+ if (status)
+ return status;
+
@ -17624,10 +17601,10 @@ index 000000000000..8e3e86c7d78c
+#endif /* _LINUX_SURFACE_ACPI_NOTIFY_H */
diff --git a/include/linux/surface_aggregator/controller.h b/include/linux/surface_aggregator/controller.h
new file mode 100644
index 000000000000..447cda590409
index 000000000000..d128c68c04e0
--- /dev/null
+++ b/include/linux/surface_aggregator/controller.h
@@ -0,0 +1,815 @@
@@ -0,0 +1,832 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Surface System Aggregator Module (SSAM) controller interface.
@ -17876,7 +17853,7 @@ index 000000000000..447cda590409
+ })
+
+/**
+ * ssam_retry - Retry request in case of I/O errors or timeouts.
+ * __ssam_retry - Retry request in case of I/O errors or timeouts.
+ * @request: The request function to execute. Must return an integer.
+ * @n: Number of tries.
+ * @args: Arguments for the request function.
@ -17888,7 +17865,7 @@ index 000000000000..447cda590409
+ *
+ * Return: Returns the return value of the last execution of @request.
+ */
+#define ssam_retry(request, n, args...) \
+#define __ssam_retry(request, n, args...) \
+ ({ \
+ int __i, __s = 0; \
+ \
@ -17900,6 +17877,23 @@ index 000000000000..447cda590409
+ __s; \
+ })
+
+/**
+ * ssam_retry - Retry request in case of I/O errors or timeouts up to three
+ * times in total.
+ * @request: The request function to execute. Must return an integer.
+ * @args: Arguments for the request function.
+ *
+ * Executes the given request function, i.e. calls @request. In case the
+ * request returns %-EREMOTEIO (indicates I/O error) or -%ETIMEDOUT (request
+ * or underlying packet timed out), @request will be re-executed again, up to
+ * three times in total.
+ *
+ * See __ssam_retry() for a more generic macro for this purpose.
+ *
+ * Return: Returns the return value of the last execution of @request.
+ */
+#define ssam_retry(request, args...) \
+ __ssam_retry(request, 3, args)
+
+/**
+ * struct ssam_request_spec - Blue-print specification of SAM request.