aboutsummaryrefslogtreecommitdiff
path: root/SOURCES
diff options
context:
space:
mode:
Diffstat (limited to 'SOURCES')
-rw-r--r--SOURCES/Patchlist.changelog3
-rw-r--r--SOURCES/kernel-aarch64-debug-fedora.config5
-rw-r--r--SOURCES/kernel-aarch64-debug-rhel.config5
-rw-r--r--SOURCES/kernel-aarch64-fedora.config5
-rw-r--r--SOURCES/kernel-aarch64-rhel.config5
-rw-r--r--SOURCES/kernel-armv7hl-debug-fedora.config5
-rw-r--r--SOURCES/kernel-armv7hl-fedora.config5
-rw-r--r--SOURCES/kernel-armv7hl-lpae-debug-fedora.config5
-rw-r--r--SOURCES/kernel-armv7hl-lpae-fedora.config5
-rw-r--r--SOURCES/kernel-ppc64le-debug-fedora.config5
-rw-r--r--SOURCES/kernel-ppc64le-debug-rhel.config5
-rw-r--r--SOURCES/kernel-ppc64le-fedora.config5
-rw-r--r--SOURCES/kernel-ppc64le-rhel.config5
-rw-r--r--SOURCES/kernel-s390x-debug-fedora.config5
-rw-r--r--SOURCES/kernel-s390x-debug-rhel.config5
-rw-r--r--SOURCES/kernel-s390x-fedora.config5
-rw-r--r--SOURCES/kernel-s390x-rhel.config5
-rw-r--r--SOURCES/kernel-s390x-zfcpdump-rhel.config5
-rw-r--r--SOURCES/kernel-x86_64-debug-fedora.config5
-rw-r--r--SOURCES/kernel-x86_64-debug-rhel.config5
-rw-r--r--SOURCES/kernel-x86_64-fedora.config5
-rw-r--r--SOURCES/kernel-x86_64-rhel.config5
-rw-r--r--SOURCES/linux-surface.patch4113
-rw-r--r--SOURCES/patch-5.17-redhat.patch61
-rw-r--r--SOURCES/simpledrm-nvidia.patch87
25 files changed, 3786 insertions, 583 deletions
diff --git a/SOURCES/Patchlist.changelog b/SOURCES/Patchlist.changelog
index 174e803..2d1781f 100644
--- a/SOURCES/Patchlist.changelog
+++ b/SOURCES/Patchlist.changelog
@@ -1,3 +1,6 @@
+"https://gitlab.com/cki-project/kernel-ark/-/commit"/205bec68a0ea67b6bff6fea9603b7b8aeacc9d46
+ 205bec68a0ea67b6bff6fea9603b7b8aeacc9d46 drivers/firmware: skip simpledrm if nvidia-drm.modeset=1 is set
+
"https://gitlab.com/cki-project/kernel-ark/-/commit"/8a35d9b408eeb4798a147fb76eb3f10368133de8
8a35d9b408eeb4798a147fb76eb3f10368133de8 efi: x86: Set the NX-compatibility flag in the PE header
diff --git a/SOURCES/kernel-aarch64-debug-fedora.config b/SOURCES/kernel-aarch64-debug-fedora.config
index 2c7833c..1606cf7 100644
--- a/SOURCES/kernel-aarch64-debug-fedora.config
+++ b/SOURCES/kernel-aarch64-debug-fedora.config
@@ -8690,7 +8690,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-aarch64-debug-rhel.config b/SOURCES/kernel-aarch64-debug-rhel.config
index 15f15ac..50fa689 100644
--- a/SOURCES/kernel-aarch64-debug-rhel.config
+++ b/SOURCES/kernel-aarch64-debug-rhel.config
@@ -6882,7 +6882,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-aarch64-fedora.config b/SOURCES/kernel-aarch64-fedora.config
index 5f17da1..29630dc 100644
--- a/SOURCES/kernel-aarch64-fedora.config
+++ b/SOURCES/kernel-aarch64-fedora.config
@@ -8663,7 +8663,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-aarch64-rhel.config b/SOURCES/kernel-aarch64-rhel.config
index 065f98d..f4b65bf 100644
--- a/SOURCES/kernel-aarch64-rhel.config
+++ b/SOURCES/kernel-aarch64-rhel.config
@@ -6857,7 +6857,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-armv7hl-debug-fedora.config b/SOURCES/kernel-armv7hl-debug-fedora.config
index 672f0be..52825d4 100644
--- a/SOURCES/kernel-armv7hl-debug-fedora.config
+++ b/SOURCES/kernel-armv7hl-debug-fedora.config
@@ -8910,7 +8910,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-armv7hl-fedora.config b/SOURCES/kernel-armv7hl-fedora.config
index 92a6a8b..dbbac99 100644
--- a/SOURCES/kernel-armv7hl-fedora.config
+++ b/SOURCES/kernel-armv7hl-fedora.config
@@ -8884,7 +8884,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-armv7hl-lpae-debug-fedora.config b/SOURCES/kernel-armv7hl-lpae-debug-fedora.config
index 9165701..f960594 100644
--- a/SOURCES/kernel-armv7hl-lpae-debug-fedora.config
+++ b/SOURCES/kernel-armv7hl-lpae-debug-fedora.config
@@ -8652,7 +8652,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-armv7hl-lpae-fedora.config b/SOURCES/kernel-armv7hl-lpae-fedora.config
index dbb9949..800935b 100644
--- a/SOURCES/kernel-armv7hl-lpae-fedora.config
+++ b/SOURCES/kernel-armv7hl-lpae-fedora.config
@@ -8626,7 +8626,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-ppc64le-debug-fedora.config b/SOURCES/kernel-ppc64le-debug-fedora.config
index 492f79e..d033a76 100644
--- a/SOURCES/kernel-ppc64le-debug-fedora.config
+++ b/SOURCES/kernel-ppc64le-debug-fedora.config
@@ -7447,7 +7447,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-ppc64le-debug-rhel.config b/SOURCES/kernel-ppc64le-debug-rhel.config
index d8bdbb0..6d84f26 100644
--- a/SOURCES/kernel-ppc64le-debug-rhel.config
+++ b/SOURCES/kernel-ppc64le-debug-rhel.config
@@ -6645,7 +6645,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-ppc64le-fedora.config b/SOURCES/kernel-ppc64le-fedora.config
index 8d6969d..7b6c577 100644
--- a/SOURCES/kernel-ppc64le-fedora.config
+++ b/SOURCES/kernel-ppc64le-fedora.config
@@ -7420,7 +7420,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-ppc64le-rhel.config b/SOURCES/kernel-ppc64le-rhel.config
index ddefaa0..bd3aa18 100644
--- a/SOURCES/kernel-ppc64le-rhel.config
+++ b/SOURCES/kernel-ppc64le-rhel.config
@@ -6624,7 +6624,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-s390x-debug-fedora.config b/SOURCES/kernel-s390x-debug-fedora.config
index 1ce9216..8fb3926 100644
--- a/SOURCES/kernel-s390x-debug-fedora.config
+++ b/SOURCES/kernel-s390x-debug-fedora.config
@@ -7403,7 +7403,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-s390x-debug-rhel.config b/SOURCES/kernel-s390x-debug-rhel.config
index c98deed..bd0d5ee 100644
--- a/SOURCES/kernel-s390x-debug-rhel.config
+++ b/SOURCES/kernel-s390x-debug-rhel.config
@@ -6602,7 +6602,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-s390x-fedora.config b/SOURCES/kernel-s390x-fedora.config
index 8014372..a8346e6 100644
--- a/SOURCES/kernel-s390x-fedora.config
+++ b/SOURCES/kernel-s390x-fedora.config
@@ -7376,7 +7376,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-s390x-rhel.config b/SOURCES/kernel-s390x-rhel.config
index 606f9db..872d3bf 100644
--- a/SOURCES/kernel-s390x-rhel.config
+++ b/SOURCES/kernel-s390x-rhel.config
@@ -6581,7 +6581,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-s390x-zfcpdump-rhel.config b/SOURCES/kernel-s390x-zfcpdump-rhel.config
index 158f57f..a8eba5a 100644
--- a/SOURCES/kernel-s390x-zfcpdump-rhel.config
+++ b/SOURCES/kernel-s390x-zfcpdump-rhel.config
@@ -6609,7 +6609,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-x86_64-debug-fedora.config b/SOURCES/kernel-x86_64-debug-fedora.config
index 54034f0..80ca310 100644
--- a/SOURCES/kernel-x86_64-debug-fedora.config
+++ b/SOURCES/kernel-x86_64-debug-fedora.config
@@ -7940,7 +7940,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-x86_64-debug-rhel.config b/SOURCES/kernel-x86_64-debug-rhel.config
index dd3c843..d38e73e 100644
--- a/SOURCES/kernel-x86_64-debug-rhel.config
+++ b/SOURCES/kernel-x86_64-debug-rhel.config
@@ -6912,7 +6912,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-x86_64-fedora.config b/SOURCES/kernel-x86_64-fedora.config
index d1aeed8..7733147 100644
--- a/SOURCES/kernel-x86_64-fedora.config
+++ b/SOURCES/kernel-x86_64-fedora.config
@@ -7914,7 +7914,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/kernel-x86_64-rhel.config b/SOURCES/kernel-x86_64-rhel.config
index 446bf4e..7e4ecde 100644
--- a/SOURCES/kernel-x86_64-rhel.config
+++ b/SOURCES/kernel-x86_64-rhel.config
@@ -6888,7 +6888,12 @@ CONFIG_I2C_NCT6775=m
CONFIG_ZENIFY=y
# device specific config
+# Steam Deck
CONFIG_STEAMDECK=y
+# Microsoft Surface
CONFIG_MISC_IPTS=m
CONFIG_SURFACE_KIP_TABLET_SWITCH=m
+CONFIG_SURFACE_AGGREGATOR_HUB=m
CONFIG_SURFACE_BOOK1_DGPU_SWITCH=y
+CONFIG_VIDEO_DW9719=m
+
diff --git a/SOURCES/linux-surface.patch b/SOURCES/linux-surface.patch
index 4b97e90..f36ed75 100644
--- a/SOURCES/linux-surface.patch
+++ b/SOURCES/linux-surface.patch
@@ -1,4 +1,4 @@
-From ec6fa26f04034a252e606d4cdc8097282c59ab18 Mon Sep 17 00:00:00 2001
+From 646a8f056267c0c6efe791753f05c202d5f991c1 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
@@ -97,9 +97,9 @@ index c60a5e8e7bc9..e947133a2c36 100644
};
--
-2.36.0
+2.36.1
-From 1395350fc7351ab5a75541dd444b9321ab51642a Mon Sep 17 00:00:00 2001
+From 8d5bbcb596dc777e691b738c90fdde519d5ff70b 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
@@ -282,9 +282,9 @@ index 8ec4176d698f..25370c5a4f59 100644
int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
+int mwifiex_pcie_reset_wsid_quirk(struct pci_dev *pdev);
--
-2.36.0
+2.36.1
-From 312dfdce8be446cbe3fc1fb49754057218e2c7bd Mon Sep 17 00:00:00 2001
+From aa1d32ead69fc367cfe67296dda751a5e40b342f 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
@@ -344,9 +344,9 @@ index 563dd0d5ac79..32e2f000e57b 100644
};
--
-2.36.0
+2.36.1
-From 91a301f7fd782acf695910c618edcb98c062ed99 Mon Sep 17 00:00:00 2001
+From 4ac41e0c2d8fe11f20a5f79a0bfe0f56db7a5f2e 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+
@@ -499,9 +499,9 @@ index 25370c5a4f59..a1de111ad1db 100644
void mwifiex_initialize_quirks(struct pcie_service_card *card);
int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
--
-2.36.0
+2.36.1
-From 1febd99bd24be85092ba5ddbf04cac8d9deab2c0 Mon Sep 17 00:00:00 2001
+From bfcc84af31034dbdd24013dc9a26abe285b40f6c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Tue, 3 Nov 2020 13:28:04 +0100
Subject: [PATCH] mwifiex: Add quirk resetting the PCI bridge on MS Surface
@@ -666,9 +666,9 @@ index a1de111ad1db..0e429779bb04 100644
void mwifiex_initialize_quirks(struct pcie_service_card *card);
int mwifiex_pcie_reset_d3cold_quirk(struct pci_dev *pdev);
--
-2.36.0
+2.36.1
-From 8c6862539a41224f764f06e5f0c7284770edc3f4 Mon Sep 17 00:00:00 2001
+From 58c6afc494c4e3b99d616ecbcaaae4fc2a2793f3 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Thu, 25 Mar 2021 11:33:02 +0100
Subject: [PATCH] Bluetooth: btusb: Lower passive lescan interval on Marvell
@@ -744,9 +744,9 @@ index 42234d5f602d..72202a744564 100644
(id->driver_info & BTUSB_MEDIATEK)) {
hdev->setup = btusb_mtk_setup;
--
-2.36.0
+2.36.1
-From 921b3bdd8d6d963f5ea108a699ef6f70a3709acd Mon Sep 17 00:00:00 2001
+From 2fca431e32e851a81ec218ef3dc87563d7cd0e68 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Tue, 10 Nov 2020 12:49:56 +0100
Subject: [PATCH] mwifiex: Use non-posted PCI register writes
@@ -801,9 +801,9 @@ index 24bcd22a2618..b4ad0113a035 100644
}
--
-2.36.0
+2.36.1
-From 1e8468a42b52eb369a70003f99dde7b16846c5e2 Mon Sep 17 00:00:00 2001
+From d4c4b533922f980a4cf0ad48db72506b3cba3a01 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 27 Feb 2021 00:45:52 +0100
Subject: [PATCH] ath10k: Add module parameters to override board files
@@ -922,9 +922,9 @@ index 8f5b8eb368fa..80c1bac732bc 100644
ret = firmware_request_nowarn(&fw, filename, ar->dev);
ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot fw request '%s': %d\n",
--
-2.36.0
+2.36.1
-From 5f96f9f986f4177c1072baa7f3ab5f134cf20415 Mon Sep 17 00:00:00 2001
+From e2a9cc1c420b8f9584c85914b6b8c8cb38b2fecc Mon Sep 17 00:00:00 2001
From: Dorian Stoll <dorian.stoll@tmsp.io>
Date: Thu, 30 Jul 2020 13:21:53 +0200
Subject: [PATCH] misc: mei: Add missing IPTS device IDs
@@ -960,9 +960,9 @@ index a738253dbd05..4e1c3fe09e53 100644
{MEI_PCI_DEVICE(MEI_DEV_ID_TGP_LP, MEI_ME_PCH15_CFG)},
--
-2.36.0
+2.36.1
-From fce727fc65f22335a65f82446d045da06cae42c6 Mon Sep 17 00:00:00 2001
+From c7d40fe3f9a803b17f8529caa7bc4b58c0a2e66a Mon Sep 17 00:00:00 2001
From: Dorian Stoll <dorian.stoll@tmsp.io>
Date: Thu, 6 Aug 2020 11:20:41 +0200
Subject: [PATCH] misc: Add support for Intel Precise Touch & Stylus
@@ -2425,118 +2425,9 @@ index 000000000000..53fb86a88f97
+
+#endif /* _IPTS_UAPI_H_ */
--
-2.36.0
+2.36.1
-From db68833d47e0d5ee2bc2003b9e410a4f672aa43a Mon Sep 17 00:00:00 2001
-From: zouxiaoh <xiaohong.zou@intel.com>
-Date: Fri, 25 Jun 2021 08:52:59 +0800
-Subject: [PATCH] iommu: intel-ipu: use IOMMU passthrough mode for Intel IPUs
-
-Intel IPU(Image Processing Unit) has its own (IO)MMU hardware,
-The IPU driver allocates its own page table that is not mapped
-via the DMA, and thus the Intel IOMMU driver blocks access giving
-this error: DMAR: DRHD: handling fault status reg 3 DMAR:
-[DMA Read] Request device [00:05.0] PASID ffffffff
-fault addr 76406000 [fault reason 06] PTE Read access is not set
-As IPU is not an external facing device which is not risky, so use
-IOMMU passthrough mode for Intel IPUs.
-
-Change-Id: I6dcccdadac308cf42e20a18e1b593381391e3e6b
-Depends-On: Iacd67578e8c6a9b9ac73285f52b4081b72fb68a6
-Tracked-On: #JIITL8-411
-Signed-off-by: Bingbu Cao <bingbu.cao@intel.com>
-Signed-off-by: zouxiaoh <xiaohong.zou@intel.com>
-Signed-off-by: Xu Chongyang <chongyang.xu@intel.com>
-Patchset: ipts
----
- drivers/iommu/intel/iommu.c | 29 +++++++++++++++++++++++++++++
- 1 file changed, 29 insertions(+)
-
-diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
-index 5b196cfe9ed2..a5fc95dbb06d 100644
---- a/drivers/iommu/intel/iommu.c
-+++ b/drivers/iommu/intel/iommu.c
-@@ -57,6 +57,12 @@
- #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
- #define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
- #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
-+#define IS_INTEL_IPU(pdev) ((pdev)->vendor == PCI_VENDOR_ID_INTEL && \
-+ ((pdev)->device == 0x9a19 || \
-+ (pdev)->device == 0x9a39 || \
-+ (pdev)->device == 0x4e19 || \
-+ (pdev)->device == 0x465d || \
-+ (pdev)->device == 0x1919))
- #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
-
- #define IOAPIC_RANGE_START (0xfee00000)
-@@ -332,12 +338,14 @@ int intel_iommu_enabled = 0;
- EXPORT_SYMBOL_GPL(intel_iommu_enabled);
-
- static int dmar_map_gfx = 1;
-+static int dmar_map_ipu = 1;
- static int intel_iommu_superpage = 1;
- static int iommu_identity_mapping;
- static int iommu_skip_te_disable;
-
- #define IDENTMAP_GFX 2
- #define IDENTMAP_AZALIA 4
-+#define IDENTMAP_IPU 8
-
- int intel_iommu_gfx_mapped;
- EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
-@@ -2966,6 +2974,9 @@ static int device_def_domain_type(struct device *dev)
-
- if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
- return IOMMU_DOMAIN_IDENTITY;
-+
-+ if ((iommu_identity_mapping & IDENTMAP_IPU) && IS_INTEL_IPU(pdev))
-+ return IOMMU_DOMAIN_IDENTITY;
- }
-
- return 0;
-@@ -3402,6 +3413,9 @@ static int __init init_dmars(void)
- if (!dmar_map_gfx)
- iommu_identity_mapping |= IDENTMAP_GFX;
-
-+ if (!dmar_map_ipu)
-+ iommu_identity_mapping |= IDENTMAP_IPU;
-+
- check_tylersburg_isoch();
-
- ret = si_domain_init(hw_pass_through);
-@@ -5643,6 +5657,18 @@ static void quirk_iommu_igfx(struct pci_dev *dev)
- dmar_map_gfx = 0;
- }
-
-+static void quirk_iommu_ipu(struct pci_dev *dev)
-+{
-+ if (!IS_INTEL_IPU(dev))
-+ return;
-+
-+ if (risky_device(dev))
-+ return;
-+
-+ pci_info(dev, "Passthrough IOMMU for integrated Intel IPU\n");
-+ dmar_map_ipu = 0;
-+}
-+
- /* G4x/GM45 integrated gfx dmar support is totally busted. */
- DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_igfx);
- DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_igfx);
-@@ -5678,6 +5704,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1632, quirk_iommu_igfx);
- DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163A, quirk_iommu_igfx);
- DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163D, quirk_iommu_igfx);
-
-+/* disable IPU dmar support */
-+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_iommu_ipu);
-+
- static void quirk_iommu_rwbf(struct pci_dev *dev)
- {
- if (risky_device(dev))
---
-2.36.0
-
-From b3fbdb5c4552d9d98715e19ca13302615e7aca80 Mon Sep 17 00:00:00 2001
+From af203d5ea529b8d75dfcb53b993bd7c060d258a2 Mon Sep 17 00:00:00 2001
From: Liban Hannan <liban.p@gmail.com>
Date: Tue, 12 Apr 2022 23:31:12 +0100
Subject: [PATCH] iommu: ipts: use IOMMU passthrough mode for IPTS
@@ -2558,37 +2449,36 @@ Patchset: ipts
1 file changed, 24 insertions(+)
diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
-index a5fc95dbb06d..b3f6213048fd 100644
+index ab2273300346..a91eed82bb39 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
-@@ -63,6 +63,8 @@
- (pdev)->device == 0x4e19 || \
- (pdev)->device == 0x465d || \
- (pdev)->device == 0x1919))
+@@ -57,6 +57,8 @@
+ #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
+ #define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
+ #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
+#define IS_IPTS(pdev) ((pdev)->vendor == PCI_VENDOR_ID_INTEL && \
+ ((pdev)->device == 0x9d3e))
#define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
#define IOAPIC_RANGE_START (0xfee00000)
-@@ -339,6 +341,7 @@ EXPORT_SYMBOL_GPL(intel_iommu_enabled);
+@@ -332,12 +334,14 @@ int intel_iommu_enabled = 0;
+ EXPORT_SYMBOL_GPL(intel_iommu_enabled);
static int dmar_map_gfx = 1;
- static int dmar_map_ipu = 1;
+static int dmar_map_ipts = 1;
static int intel_iommu_superpage = 1;
static int iommu_identity_mapping;
static int iommu_skip_te_disable;
-@@ -346,6 +349,7 @@ static int iommu_skip_te_disable;
+
#define IDENTMAP_GFX 2
#define IDENTMAP_AZALIA 4
- #define IDENTMAP_IPU 8
+#define IDENTMAP_IPTS 16
int intel_iommu_gfx_mapped;
EXPORT_SYMBOL_GPL(intel_iommu_gfx_mapped);
-@@ -2977,6 +2981,9 @@ static int device_def_domain_type(struct device *dev)
+@@ -2987,6 +2991,9 @@ static int device_def_domain_type(struct device *dev)
- if ((iommu_identity_mapping & IDENTMAP_IPU) && IS_INTEL_IPU(pdev))
+ if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
return IOMMU_DOMAIN_IDENTITY;
+
+ if ((iommu_identity_mapping & IDENTMAP_IPTS) && IS_IPTS(pdev))
@@ -2596,9 +2486,9 @@ index a5fc95dbb06d..b3f6213048fd 100644
}
return 0;
-@@ -3416,6 +3423,9 @@ static int __init init_dmars(void)
- if (!dmar_map_ipu)
- iommu_identity_mapping |= IDENTMAP_IPU;
+@@ -3423,6 +3430,9 @@ static int __init init_dmars(void)
+ if (!dmar_map_gfx)
+ iommu_identity_mapping |= IDENTMAP_GFX;
+ if (!dmar_map_ipts)
+ iommu_identity_mapping |= IDENTMAP_IPTS;
@@ -2606,8 +2496,8 @@ index a5fc95dbb06d..b3f6213048fd 100644
check_tylersburg_isoch();
ret = si_domain_init(hw_pass_through);
-@@ -5669,6 +5679,17 @@ static void quirk_iommu_ipu(struct pci_dev *dev)
- dmar_map_ipu = 0;
+@@ -5664,6 +5674,17 @@ static void quirk_iommu_igfx(struct pci_dev *dev)
+ dmar_map_gfx = 0;
}
+static void quirk_iommu_ipts(struct pci_dev *dev)
@@ -2624,9 +2514,9 @@ index a5fc95dbb06d..b3f6213048fd 100644
/* G4x/GM45 integrated gfx dmar support is totally busted. */
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_igfx);
DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_igfx);
-@@ -5707,6 +5728,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163D, quirk_iommu_igfx);
- /* disable IPU dmar support */
- DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_iommu_ipu);
+@@ -5699,6 +5720,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1632, quirk_iommu_igfx);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163A, quirk_iommu_igfx);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163D, quirk_iommu_igfx);
+/* disable IPTS dmar support */
+DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9D3E, quirk_iommu_ipts);
@@ -2635,9 +2525,9 @@ index a5fc95dbb06d..b3f6213048fd 100644
{
if (risky_device(dev))
--
-2.36.0
+2.36.1
-From 2bb8c3daadfa4daa1f2d0f35b7753f850d0f0b62 Mon Sep 17 00:00:00 2001
+From a992351b539f71c2d037d717d09052d2a7c454fc Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Tue, 8 Jun 2021 00:24:47 +0200
Subject: [PATCH] platform/surface: aggregator: Allow devices to be marked as
@@ -2663,24 +2553,9 @@ attempts should be avoided.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Patchset: surface-sam
---
- drivers/platform/surface/aggregator/bus.c | 3 ++
include/linux/surface_aggregator/device.h | 48 +++++++++++++++++++++--
- 2 files changed, 48 insertions(+), 3 deletions(-)
+ 1 file changed, 45 insertions(+), 3 deletions(-)
-diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c
-index abbbb5b08b07..2b003dcbfc4b 100644
---- a/drivers/platform/surface/aggregator/bus.c
-+++ b/drivers/platform/surface/aggregator/bus.c
-@@ -388,6 +388,9 @@ void ssam_remove_clients(struct device *dev)
- }
- EXPORT_SYMBOL_GPL(ssam_remove_clients);
-
-+
-+/* -- Bus registration. ----------------------------------------------------- */
-+
- /**
- * ssam_bus_register() - Register and set-up the SSAM client device bus.
- */
diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
index cc257097eb05..491aa7e9f4bc 100644
--- a/include/linux/surface_aggregator/device.h
@@ -2756,9 +2631,9 @@ index cc257097eb05..491aa7e9f4bc 100644
* ssam_device_get() - Increment reference count of SSAM client device.
* @sdev: The device to increment the reference count of.
--
-2.36.0
+2.36.1
-From e1da5a5135346e7091651f7fe2aa8c43b9d03f7d Mon Sep 17 00:00:00 2001
+From 8c9b27fdeb07fd4c83bb0d9d79776f21640d39d6 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Tue, 8 Jun 2021 00:48:22 +0200
Subject: [PATCH] platform/surface: aggregator: Allow notifiers to avoid
@@ -2769,7 +2644,7 @@ communication attempts with those devices may fail and time out. This
can even extend to event notifiers, due to which timeouts may occur
during device removal, slowing down that process.
-Add a flag to the notifier unregister function that allows skipping
+Add a parameter to the notifier unregister function that allows skipping
communication with the EC to prevent this. Furthermore, add wrappers for
registering and unregistering notifiers belonging to SSAM client devices
that automatically check if the device has been marked as hot-removed
@@ -2783,10 +2658,10 @@ Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Patchset: surface-sam
---
.../driver-api/surface_aggregator/client.rst | 6 +-
- .../platform/surface/aggregator/controller.c | 53 ++++++++++------
- include/linux/surface_aggregator/controller.h | 24 +++++++-
- include/linux/surface_aggregator/device.h | 60 +++++++++++++++++++
- 4 files changed, 122 insertions(+), 21 deletions(-)
+ .../platform/surface/aggregator/controller.c | 53 ++++++++++-----
+ include/linux/surface_aggregator/controller.h | 24 ++++++-
+ include/linux/surface_aggregator/device.h | 66 +++++++++++++++++++
+ 4 files changed, 128 insertions(+), 21 deletions(-)
diff --git a/Documentation/driver-api/surface_aggregator/client.rst b/Documentation/driver-api/surface_aggregator/client.rst
index e519d374c378..27f95abdbe99 100644
@@ -2974,10 +2849,10 @@ index 74bfdffaf7b0..50a2b4926c06 100644
int ssam_controller_event_enable(struct ssam_controller *ctrl,
struct ssam_event_registry reg,
diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
-index 491aa7e9f4bc..16816c34da3e 100644
+index 491aa7e9f4bc..ad245c6b00d0 100644
--- a/include/linux/surface_aggregator/device.h
+++ b/include/linux/surface_aggregator/device.h
-@@ -472,4 +472,64 @@ static inline void ssam_remove_clients(struct device *dev) {}
+@@ -472,4 +472,70 @@ static inline void ssam_remove_clients(struct device *dev) {}
sdev->uid.instance, ret); \
}
@@ -3010,6 +2885,12 @@ index 491aa7e9f4bc..16816c34da3e 100644
+static inline int ssam_device_notifier_register(struct ssam_device *sdev,
+ struct ssam_event_notifier *n)
+{
++ /*
++ * Note that this check does not provide any guarantees whatsoever as
++ * hot-removal could happen at any point and we can't protect against
++ * it. Nevertheless, if we can detect hot-removal, bail early to avoid
++ * communication timeouts.
++ */
+ if (ssam_device_is_hot_removed(sdev))
+ return -ENODEV;
+
@@ -3043,9 +2924,9 @@ index 491aa7e9f4bc..16816c34da3e 100644
+
#endif /* _LINUX_SURFACE_AGGREGATOR_DEVICE_H */
--
-2.36.0
+2.36.1
-From bf9269161d0e15076508e0ca776a31d860eacb7f Mon Sep 17 00:00:00 2001
+From 9c5a46d6a755d4c9546f44a4e13ef5a92bc98b2d Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Tue, 8 Jun 2021 01:20:49 +0200
Subject: [PATCH] platform/surface: aggregator_registry: Use client device
@@ -3092,9 +2973,9 @@ index ce2bd88feeaa..9f630e890ff7 100644
ssam_remove_clients(&sdev->dev);
}
--
-2.36.0
+2.36.1
-From 7dffc0d5aa0b675201815f0db11d4207ed1bcf47 Mon Sep 17 00:00:00 2001
+From 86e1009150f92b4e756f6be81e80d45a42a9d497 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Thu, 28 Oct 2021 03:37:06 +0200
Subject: [PATCH] power/supply: surface_charger: Use client device wrappers for
@@ -3132,9 +3013,9 @@ index a060c36c7766..59182d55742d 100644
static const struct spwr_psy_properties spwr_psy_props_adp1 = {
--
-2.36.0
+2.36.1
-From bf04f91eb86cd24faed47f078d4c7cba0d3afb0a Mon Sep 17 00:00:00 2001
+From 033434def6261f801001c8d76b4a525b33b77372 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Thu, 28 Oct 2021 03:38:09 +0200
Subject: [PATCH] power/supply: surface_battery: Use client device wrappers for
@@ -3172,9 +3053,9 @@ index 5ec2e6bb2465..540707882bb0 100644
}
--
-2.36.0
+2.36.1
-From ec5de9e26ab336abeb4510101843ca9215f306ac Mon Sep 17 00:00:00 2001
+From 2971cc213e3adb104ac7de5a0feff4237a255166 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Tue, 8 Jun 2021 01:33:02 +0200
Subject: [PATCH] HID: surface-hid: Add support for hot-removal
@@ -3186,8 +3067,8 @@ be avoided as it may fail and time out. While the device will be removed
as soon as we detect hot-removal, communication may still occur during
teardown, especially when unregistering notifiers.
-While hot-removal is a surprise event that can happen any time, try to
-avoid communication as much as possible once it has been detected to
+While hot-removal is a surprise event that can happen at any time, try
+to avoid communication as much as possible once it has been detected to
prevent timeouts that can slow down device removal and cause issues,
e.g. when quickly re-attaching the device.
@@ -3283,9 +3164,9 @@ index e46330b2e561..87637f813de2 100644
return shid->ops.output_report(shid, reportnum, buf, len);
--
-2.36.0
+2.36.1
-From 4bdf54b718375e303f8fe6745ffa90c4b153e20c Mon Sep 17 00:00:00 2001
+From f579f070fff7d5245cc08e08f888e2522ac62024 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sun, 31 Oct 2021 12:34:08 +0100
Subject: [PATCH] platform/surface: aggregator: Add comment for KIP subsystem
@@ -3308,7 +3189,7 @@ Patchset: surface-sam
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/linux/surface_aggregator/serial_hub.h b/include/linux/surface_aggregator/serial_hub.h
-index c3de43edcffa..d1efac85caf1 100644
+index c3de43edcffa..26b95ec12733 100644
--- a/include/linux/surface_aggregator/serial_hub.h
+++ b/include/linux/surface_aggregator/serial_hub.h
@@ -306,7 +306,7 @@ enum ssam_ssh_tc {
@@ -3316,16 +3197,403 @@ index c3de43edcffa..d1efac85caf1 100644
SSAM_SSH_TC_TCL = 0x0c,
SSAM_SSH_TC_SFL = 0x0d,
- SSAM_SSH_TC_KIP = 0x0e,
-+ SSAM_SSH_TC_KIP = 0x0e, /* Manages detachable peripherals (Pro X/8 keyboard cover) */
++ SSAM_SSH_TC_KIP = 0x0e, /* Manages detachable peripherals (Pro X/8 keyboard cover) */
SSAM_SSH_TC_EXT = 0x0f,
SSAM_SSH_TC_BLD = 0x10,
SSAM_SSH_TC_BAS = 0x11, /* Detachment system (Surface Book 2/3). */
--
-2.36.0
+2.36.1
-From b05a57a23fb0dce8c1be11eda511116493d1e114 Mon Sep 17 00:00:00 2001
+From 8102d2904cbbddf212983a946dcbd3612dde060a Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
-Date: Sun, 10 Oct 2021 23:56:23 +0200
+Date: Fri, 29 Apr 2022 22:42:32 +0200
+Subject: [PATCH] platform/surface: aggregator_registry: Generify subsystem hub
+ functionality
+
+The Surface System Aggregator Module (SSAM) has multiple subsystems that
+can manage detachable devices. At the moment, we only support the "base"
+(BAS/0x11) subsystem, which is used on the Surface Book 3 to manage
+devices (including keyboard, touchpad, and secondary battery) connected
+to the base of the device.
+
+The Surface Pro 8 has a new type-cover with keyboard and touchpad, which
+is managed via the KIP/0x0e subsystem. The general procedure is the
+same, but with slightly different events and setup. To make
+implementation of the KIP hub easier and prevent duplication, generify
+the parts of the base hub that we can use for the KIP hub (or any
+potential future subsystem hubs).
+
+This also switches over to use the newly introduced "hot-remove"
+functionality, which should prevent communication issues when devices
+have been detached.
+
+Lastly, also drop the undocumented and unused sysfs "state" attribute of
+the base hub. It has at best been useful for debugging.
+
+Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
+Patchset: surface-sam
+---
+ .../surface/surface_aggregator_registry.c | 269 ++++++++++--------
+ 1 file changed, 153 insertions(+), 116 deletions(-)
+
+diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
+index 9f630e890ff7..09cbeee2428b 100644
+--- a/drivers/platform/surface/surface_aggregator_registry.c
++++ b/drivers/platform/surface/surface_aggregator_registry.c
+@@ -308,30 +308,159 @@ static int ssam_hub_register_clients(struct device *parent, struct ssam_controll
+ }
+
+
+-/* -- SSAM base-hub driver. ------------------------------------------------- */
++/* -- SSAM generic subsystem hub driver framework. -------------------------- */
+
+-/*
+- * Some devices (especially battery) may need a bit of time to be fully usable
+- * after being (re-)connected. This delay has been determined via
+- * experimentation.
+- */
+-#define SSAM_BASE_UPDATE_CONNECT_DELAY msecs_to_jiffies(2500)
++enum ssam_hub_state {
++ SSAM_HUB_UNINITIALIZED, /* Only set during initialization. */
++ SSAM_HUB_CONNECTED,
++ SSAM_HUB_DISCONNECTED,
++};
+
+-enum ssam_base_hub_state {
+- SSAM_BASE_HUB_UNINITIALIZED,
+- SSAM_BASE_HUB_CONNECTED,
+- SSAM_BASE_HUB_DISCONNECTED,
++enum ssam_hub_flags {
++ SSAM_HUB_HOT_REMOVED,
+ };
+
+-struct ssam_base_hub {
++struct ssam_hub {
+ struct ssam_device *sdev;
+
+- enum ssam_base_hub_state state;
++ enum ssam_hub_state state;
++ unsigned long flags;
++
+ struct delayed_work update_work;
++ unsigned long connect_delay;
+
+ struct ssam_event_notifier notif;
++
++ int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
+ };
+
++static void ssam_hub_update_workfn(struct work_struct *work)
++{
++ struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
++ struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
++ enum ssam_hub_state state;
++ int status = 0;
++
++ status = hub->get_state(hub, &state);
++ if (status)
++ return;
++
++ /*
++ * There is a small possibility that hub devices were hot-removed and
++ * re-added before we were able to remove them here. In that case, both
++ * the state returned by get_state() and the state of the hub will
++ * equal SSAM_HUB_CONNECTED and we would bail early below, which would
++ * leave child devices without proper (re-)initialization and the
++ * hot-remove flag set.
++ *
++ * Therefore, we check whether devices have been hot-removed via an
++ * additional flag on the hub and, in this case, override the returned
++ * hub state. In case of a missed disconnect (i.e. get_state returned
++ * "connected"), we further need to re-schedule this work (with the
++ * appropriate delay) as the actual connect work submission might have
++ * been merged with this one.
++ *
++ * This then leads to one of two cases: Either we submit an unnecessary
++ * work item (which will get ignored via either the queue or the state
++ * checks) or, in the unlikely case that the work is actually required,
++ * double the normal connect delay.
++ */
++ if (test_and_clear_bit(SSAM_HUB_HOT_REMOVED, &hub->flags)) {
++ if (state == SSAM_HUB_CONNECTED)
++ schedule_delayed_work(&hub->update_work, hub->connect_delay);
++
++ state = SSAM_HUB_DISCONNECTED;
++ }
++
++ if (hub->state == state)
++ return;
++ hub->state = state;
++
++ if (hub->state == SSAM_HUB_CONNECTED)
++ status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
++ else
++ ssam_remove_clients(&hub->sdev->dev);
++
++ if (status)
++ dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status);
++}
++
++static int ssam_hub_mark_hot_removed(struct device *dev, void *_data)
++{
++ struct ssam_device *sdev = to_ssam_device(dev);
++
++ if (is_ssam_device(dev))
++ ssam_device_mark_hot_removed(sdev);
++
++ return 0;
++}
++
++static void ssam_hub_update(struct ssam_hub *hub, bool connected)
++{
++ unsigned long delay;
++
++ /* Mark devices as hot-removed before we remove any. */
++ if (!connected) {
++ set_bit(SSAM_HUB_HOT_REMOVED, &hub->flags);
++ device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed);
++ }
++
++ /*
++ * Delay update when the base/keyboard cover is being connected to give
++ * devices/EC some time to set up.
++ */
++ delay = connected ? hub->connect_delay : 0;
++
++ schedule_delayed_work(&hub->update_work, delay);
++}
++
++static int __maybe_unused ssam_hub_resume(struct device *dev)
++{
++ struct ssam_hub *hub = dev_get_drvdata(dev);
++
++ schedule_delayed_work(&hub->update_work, 0);
++ return 0;
++}
++static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume);
++
++static int ssam_hub_setup(struct ssam_device *sdev, struct ssam_hub *hub)
++{
++ int status;
++
++ hub->sdev = sdev;
++ hub->state = SSAM_HUB_UNINITIALIZED;
++
++ INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn);
++
++ ssam_device_set_drvdata(sdev, hub);
++
++ status = ssam_device_notifier_register(sdev, &hub->notif);
++ if (status)
++ return status;
++
++ schedule_delayed_work(&hub->update_work, 0);
++ return 0;
++}
++
++static void ssam_hub_remove(struct ssam_device *sdev)
++{
++ struct ssam_hub *hub = ssam_device_get_drvdata(sdev);
++
++ ssam_device_notifier_unregister(sdev, &hub->notif);
++ cancel_delayed_work_sync(&hub->update_work);
++ ssam_remove_clients(&sdev->dev);
++}
++
++
++/* -- SSAM base-hub driver. ------------------------------------------------- */
++
++/*
++ * Some devices (especially battery) may need a bit of time to be fully usable
++ * after being (re-)connected. This delay has been determined via
++ * experimentation.
++ */
++#define SSAM_BASE_UPDATE_CONNECT_DELAY msecs_to_jiffies(2500)
++
+ SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
+ .target_category = SSAM_SSH_TC_BAS,
+ .target_id = 0x01,
+@@ -342,7 +471,7 @@ SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
+ #define SSAM_BAS_OPMODE_TABLET 0x00
+ #define SSAM_EVENT_BAS_CID_CONNECTION 0x0c
+
+-static int ssam_base_hub_query_state(struct ssam_base_hub *hub, enum ssam_base_hub_state *state)
++static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
+ {
+ u8 opmode;
+ int status;
+@@ -354,62 +483,16 @@ static int ssam_base_hub_query_state(struct ssam_base_hub *hub, enum ssam_base_h
+ }
+
+ if (opmode != SSAM_BAS_OPMODE_TABLET)
+- *state = SSAM_BASE_HUB_CONNECTED;
++ *state = SSAM_HUB_CONNECTED;
+ else
+- *state = SSAM_BASE_HUB_DISCONNECTED;
++ *state = SSAM_HUB_DISCONNECTED;
+
+ return 0;
+ }
+
+-static ssize_t ssam_base_hub_state_show(struct device *dev, struct device_attribute *attr,
+- char *buf)
+-{
+- struct ssam_base_hub *hub = dev_get_drvdata(dev);
+- bool connected = hub->state == SSAM_BASE_HUB_CONNECTED;
+-
+- return sysfs_emit(buf, "%d\n", connected);
+-}
+-
+-static struct device_attribute ssam_base_hub_attr_state =
+- __ATTR(state, 0444, ssam_base_hub_state_show, NULL);
+-
+-static struct attribute *ssam_base_hub_attrs[] = {
+- &ssam_base_hub_attr_state.attr,
+- NULL,
+-};
+-
+-static const struct attribute_group ssam_base_hub_group = {
+- .attrs = ssam_base_hub_attrs,
+-};
+-
+-static void ssam_base_hub_update_workfn(struct work_struct *work)
+-{
+- struct ssam_base_hub *hub = container_of(work, struct ssam_base_hub, update_work.work);
+- struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
+- enum ssam_base_hub_state state;
+- int status = 0;
+-
+- status = ssam_base_hub_query_state(hub, &state);
+- if (status)
+- return;
+-
+- if (hub->state == state)
+- return;
+- hub->state = state;
+-
+- if (hub->state == SSAM_BASE_HUB_CONNECTED)
+- status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
+- else
+- ssam_remove_clients(&hub->sdev->dev);
+-
+- if (status)
+- dev_err(&hub->sdev->dev, "failed to update base-hub devices: %d\n", status);
+-}
+-
+ static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
+ {
+- struct ssam_base_hub *hub = container_of(nf, struct ssam_base_hub, notif);
+- unsigned long delay;
++ struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
+
+ if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION)
+ return 0;
+@@ -419,13 +502,7 @@ static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam
+ return 0;
+ }
+
+- /*
+- * Delay update when the base is being connected to give devices/EC
+- * some time to set up.
+- */
+- delay = event->data[0] ? SSAM_BASE_UPDATE_CONNECT_DELAY : 0;
+-
+- schedule_delayed_work(&hub->update_work, delay);
++ ssam_hub_update(hub, event->data[0]);
+
+ /*
+ * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and
+@@ -435,27 +512,14 @@ static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam
+ return 0;
+ }
+
+-static int __maybe_unused ssam_base_hub_resume(struct device *dev)
+-{
+- struct ssam_base_hub *hub = dev_get_drvdata(dev);
+-
+- schedule_delayed_work(&hub->update_work, 0);
+- return 0;
+-}
+-static SIMPLE_DEV_PM_OPS(ssam_base_hub_pm_ops, NULL, ssam_base_hub_resume);
+-
+ static int ssam_base_hub_probe(struct ssam_device *sdev)
+ {
+- struct ssam_base_hub *hub;
+- int status;
++ struct ssam_hub *hub;
+
+ hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
+ if (!hub)
+ return -ENOMEM;
+
+- hub->sdev = sdev;
+- hub->state = SSAM_BASE_HUB_UNINITIALIZED;
+-
+ hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
+ hub->notif.base.fn = ssam_base_hub_notif;
+ hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
+@@ -464,37 +528,10 @@ static int ssam_base_hub_probe(struct ssam_device *sdev)
+ hub->notif.event.mask = SSAM_EVENT_MASK_NONE;
+ hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
+
+- INIT_DELAYED_WORK(&hub->update_work, ssam_base_hub_update_workfn);
+-
+- ssam_device_set_drvdata(sdev, hub);
+-
+- status = ssam_device_notifier_register(sdev, &hub->notif);
+- if (status)
+- return status;
+-
+- status = sysfs_create_group(&sdev->dev.kobj, &ssam_base_hub_group);
+- if (status)
+- goto err;
+-
+- schedule_delayed_work(&hub->update_work, 0);
+- return 0;
++ hub->connect_delay = SSAM_BASE_UPDATE_CONNECT_DELAY;
++ hub->get_state = ssam_base_hub_query_state;
+
+-err:
+- ssam_device_notifier_unregister(sdev, &hub->notif);
+- cancel_delayed_work_sync(&hub->update_work);
+- ssam_remove_clients(&sdev->dev);
+- return status;
+-}
+-
+-static void ssam_base_hub_remove(struct ssam_device *sdev)
+-{
+- struct ssam_base_hub *hub = ssam_device_get_drvdata(sdev);
+-
+- sysfs_remove_group(&sdev->dev.kobj, &ssam_base_hub_group);
+-
+- ssam_device_notifier_unregister(sdev, &hub->notif);
+- cancel_delayed_work_sync(&hub->update_work);
+- ssam_remove_clients(&sdev->dev);
++ return ssam_hub_setup(sdev, hub);
+ }
+
+ static const struct ssam_device_id ssam_base_hub_match[] = {
+@@ -504,12 +541,12 @@ static const struct ssam_device_id ssam_base_hub_match[] = {
+
+ static struct ssam_device_driver ssam_base_hub_driver = {
+ .probe = ssam_base_hub_probe,
+- .remove = ssam_base_hub_remove,
++ .remove = ssam_hub_remove,
+ .match_table = ssam_base_hub_match,
+ .driver = {
+ .name = "surface_aggregator_base_hub",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+- .pm = &ssam_base_hub_pm_ops,
++ .pm = &ssam_hub_pm_ops,
+ },
+ };
+
+--
+2.36.1
+
+From 54a66b25ae897b15bb5bb5d5f4d930f3332f7c3f Mon Sep 17 00:00:00 2001
+From: Maximilian Luz <luzmaximilian@gmail.com>
+Date: Fri, 29 Apr 2022 23:02:06 +0200
Subject: [PATCH] platform/surface: aggregator_registry: Add KIP device hub
Add a Surface System Aggregator Module (SSAM) client device hub for
@@ -3337,33 +3605,25 @@ SSAM client devices. Specifically, it manages HID input devices
contained in the detachable keyboard cover of the Surface Pro 8 and
Surface Pro X.
-To properly handle detachable devices, we need to remove their kernel
-representation when the physical device has been detached and (re-)add
-and (re-)initialize said representation when the physical device has
-been (re-)attached. Note that we need to hot-remove those devices, as
-communication (especially during event notifier unregistration) may time
-out when the physical device is no longer present, which would lead to
-an unnecessary delay. This delay might become problematic when devices
-are detached and re-attached quickly.
-
The KIP subsystem handles a single group of devices (e.g. all devices
contained in the keyboard cover) and cannot handle devices individually.
-Thus we model it as a client device hub, which removes all devices
+Thus we model it as a client device hub, which (hot-)removes all devices
contained under it once removal of the hub (e.g. keyboard cover) has
been detected and (re-)adds all devices once the physical hub device has
-been (re-)attached.
+been (re-)attached. To do this, use the previously generified SSAM
+subsystem hub framework.
Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
Patchset: surface-sam
---
- .../surface/surface_aggregator_registry.c | 247 +++++++++++++++++-
- 1 file changed, 245 insertions(+), 2 deletions(-)
+ .../surface/surface_aggregator_registry.c | 103 +++++++++++++++++-
+ 1 file changed, 101 insertions(+), 2 deletions(-)
diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
-index 9f630e890ff7..4838ce6519a6 100644
+index 09cbeee2428b..1e60435c7cce 100644
--- a/drivers/platform/surface/surface_aggregator_registry.c
+++ b/drivers/platform/surface/surface_aggregator_registry.c
-@@ -514,6 +514,237 @@ static struct ssam_device_driver ssam_base_hub_driver = {
+@@ -551,6 +551,93 @@ static struct ssam_device_driver ssam_base_hub_driver = {
};
@@ -3377,21 +3637,6 @@ index 9f630e890ff7..4838ce6519a6 100644
+
+#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c
+
-+enum ssam_kip_hub_state {
-+ SSAM_KIP_HUB_UNINITIALIZED,
-+ SSAM_KIP_HUB_CONNECTED,
-+ SSAM_KIP_HUB_DISCONNECTED,
-+};
-+
-+struct ssam_kip_hub {
-+ struct ssam_device *sdev;
-+
-+ enum ssam_kip_hub_state state;
-+ struct delayed_work update_work;
-+
-+ struct ssam_event_notifier notif;
-+};
-+
+SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_connection_state, u8, {
+ .target_category = SSAM_SSH_TC_KIP,
+ .target_id = 0x01,
@@ -3399,7 +3644,7 @@ index 9f630e890ff7..4838ce6519a6 100644
+ .instance_id = 0x00,
+});
+
-+static int ssam_kip_get_connection_state(struct ssam_kip_hub *hub, enum ssam_kip_hub_state *state)
++static int ssam_kip_get_connection_state(struct ssam_hub *hub, enum ssam_hub_state *state)
+{
+ int status;
+ u8 connected;
@@ -3410,92 +3655,13 @@ index 9f630e890ff7..4838ce6519a6 100644
+ return status;
+ }
+
-+ *state = connected ? SSAM_KIP_HUB_CONNECTED : SSAM_KIP_HUB_DISCONNECTED;
-+ return 0;
-+}
-+
-+static ssize_t ssam_kip_hub_state_show(struct device *dev, struct device_attribute *attr, char *buf)
-+{
-+ struct ssam_kip_hub *hub = dev_get_drvdata(dev);
-+ const char *state;
-+
-+ switch (hub->state) {
-+ case SSAM_KIP_HUB_UNINITIALIZED:
-+ state = "uninitialized";
-+ break;
-+
-+ case SSAM_KIP_HUB_CONNECTED:
-+ state = "connected";
-+ break;
-+
-+ case SSAM_KIP_HUB_DISCONNECTED:
-+ state = "disconnected";
-+ break;
-+
-+ default:
-+ /*
-+ * Any value not handled in the above cases is invalid and
-+ * should never have been set. Thus this case should be
-+ * impossible to reach.
-+ */
-+ WARN(1, "invalid KIP hub state: %d\n", hub->state);
-+ state = "<invalid>";
-+ break;
-+ }
-+
-+ return sysfs_emit(buf, "%s\n", state);
-+}
-+
-+static struct device_attribute ssam_kip_hub_attr_state =
-+ __ATTR(state, 0444, ssam_kip_hub_state_show, NULL);
-+
-+static struct attribute *ssam_kip_hub_attrs[] = {
-+ &ssam_kip_hub_attr_state.attr,
-+ NULL,
-+};
-+
-+static const struct attribute_group ssam_kip_hub_group = {
-+ .attrs = ssam_kip_hub_attrs,
-+};
-+
-+static int ssam_kip_hub_mark_hot_removed(struct device *dev, void *_data)
-+{
-+ struct ssam_device *sdev = to_ssam_device(dev);
-+
-+ if (is_ssam_device(dev))
-+ ssam_device_mark_hot_removed(sdev);
-+
++ *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED;
+ return 0;
+}
+
-+static void ssam_kip_hub_update_workfn(struct work_struct *work)
-+{
-+ struct ssam_kip_hub *hub = container_of(work, struct ssam_kip_hub, update_work.work);
-+ struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
-+ enum ssam_kip_hub_state state;
-+ int status = 0;
-+
-+ status = ssam_kip_get_connection_state(hub, &state);
-+ if (status)
-+ return;
-+
-+ if (hub->state == state)
-+ return;
-+ hub->state = state;
-+
-+ if (hub->state == SSAM_KIP_HUB_CONNECTED)
-+ status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
-+ else
-+ ssam_remove_clients(&hub->sdev->dev);
-+
-+ if (status)
-+ dev_err(&hub->sdev->dev, "failed to update KIP-hub devices: %d\n", status);
-+}
-+
+static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
+{
-+ struct ssam_kip_hub *hub = container_of(nf, struct ssam_kip_hub, notif);
-+ unsigned long delay;
++ struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
+
+ if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION)
+ return 0; /* Return "unhandled". */
@@ -3505,41 +3671,18 @@ index 9f630e890ff7..4838ce6519a6 100644
+ return 0;
+ }
+
-+ /* Mark devices as hot-removed before we remove any */
-+ if (!event->data[0])
-+ device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_kip_hub_mark_hot_removed);
-+
-+ /*
-+ * Delay update when KIP devices are being connected to give devices/EC
-+ * some time to set up.
-+ */
-+ delay = event->data[0] ? SSAM_KIP_UPDATE_CONNECT_DELAY : 0;
-+
-+ schedule_delayed_work(&hub->update_work, delay);
++ ssam_hub_update(hub, event->data[0]);
+ return SSAM_NOTIF_HANDLED;
+}
+
-+static int __maybe_unused ssam_kip_hub_resume(struct device *dev)
-+{
-+ struct ssam_kip_hub *hub = dev_get_drvdata(dev);
-+
-+ schedule_delayed_work(&hub->update_work, 0);
-+ return 0;
-+}
-+static SIMPLE_DEV_PM_OPS(ssam_kip_hub_pm_ops, NULL, ssam_kip_hub_resume);
-+
+static int ssam_kip_hub_probe(struct ssam_device *sdev)
+{
-+ struct ssam_kip_hub *hub;
-+ int status;
++ struct ssam_hub *hub;
+
+ hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
+ if (!hub)
+ return -ENOMEM;
+
-+ hub->sdev = sdev;
-+ hub->state = SSAM_KIP_HUB_UNINITIALIZED;
-+
+ hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
+ hub->notif.base.fn = ssam_kip_hub_notif;
+ hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
@@ -3548,37 +3691,10 @@ index 9f630e890ff7..4838ce6519a6 100644
+ hub->notif.event.mask = SSAM_EVENT_MASK_TARGET;
+ hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
+
-+ INIT_DELAYED_WORK(&hub->update_work, ssam_kip_hub_update_workfn);
-+
-+ ssam_device_set_drvdata(sdev, hub);
-+
-+ status = ssam_device_notifier_register(sdev, &hub->notif);
-+ if (status)
-+ return status;
-+
-+ status = sysfs_create_group(&sdev->dev.kobj, &ssam_kip_hub_group);
-+ if (status)
-+ goto err;
-+
-+ schedule_delayed_work(&hub->update_work, 0);
-+ return 0;
++ hub->connect_delay = SSAM_KIP_UPDATE_CONNECT_DELAY;
++ hub->get_state = ssam_kip_get_connection_state;
+
-+err:
-+ ssam_device_notifier_unregister(sdev, &hub->notif);
-+ cancel_delayed_work_sync(&hub->update_work);
-+ ssam_remove_clients(&sdev->dev);
-+ return status;
-+}
-+
-+static void ssam_kip_hub_remove(struct ssam_device *sdev)
-+{
-+ struct ssam_kip_hub *hub = ssam_device_get_drvdata(sdev);
-+
-+ sysfs_remove_group(&sdev->dev.kobj, &ssam_kip_hub_group);
-+
-+ ssam_device_notifier_unregister(sdev, &hub->notif);
-+ cancel_delayed_work_sync(&hub->update_work);
-+ ssam_remove_clients(&sdev->dev);
++ return ssam_hub_setup(sdev, hub);
+}
+
+static const struct ssam_device_id ssam_kip_hub_match[] = {
@@ -3588,12 +3704,12 @@ index 9f630e890ff7..4838ce6519a6 100644
+
+static struct ssam_device_driver ssam_kip_hub_driver = {
+ .probe = ssam_kip_hub_probe,
-+ .remove = ssam_kip_hub_remove,
++ .remove = ssam_hub_remove,
+ .match_table = ssam_kip_hub_match,
+ .driver = {
+ .name = "surface_kip_hub",
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
-+ .pm = &ssam_kip_hub_pm_ops,
++ .pm = &ssam_hub_pm_ops,
+ },
+};
+
@@ -3601,7 +3717,7 @@ index 9f630e890ff7..4838ce6519a6 100644
/* -- SSAM platform/meta-hub driver. ---------------------------------------- */
static const struct acpi_device_id ssam_platform_hub_match[] = {
-@@ -636,18 +867,30 @@ static int __init ssam_device_hub_init(void)
+@@ -673,18 +760,30 @@ static int __init ssam_device_hub_init(void)
status = platform_driver_register(&ssam_platform_hub_driver);
if (status)
@@ -3635,9 +3751,9 @@ index 9f630e890ff7..4838ce6519a6 100644
platform_driver_unregister(&ssam_platform_hub_driver);
}
--
-2.36.0
+2.36.1
-From 0e443bc77964f90eed651cb32af45398060ba42e Mon Sep 17 00:00:00 2001
+From 6a2326ef63c3ac8b8dc45c6efee6933f649a1618 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Wed, 27 Oct 2021 22:33:03 +0200
Subject: [PATCH] platform/surface: aggregator_registry: Add support for
@@ -3668,7 +3784,7 @@ Patchset: surface-sam
1 file changed, 36 insertions(+), 1 deletion(-)
diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
-index 4838ce6519a6..c0e29c0514df 100644
+index 1e60435c7cce..ab69669316bd 100644
--- a/drivers/platform/surface/surface_aggregator_registry.c
+++ b/drivers/platform/surface/surface_aggregator_registry.c
@@ -47,6 +47,12 @@ static const struct software_node ssam_node_hub_base = {
@@ -3733,9 +3849,9 @@ index 4838ce6519a6..c0e29c0514df 100644
};
--
-2.36.0
+2.36.1
-From f3ff67b118c39ab15a3443f953f93fa933c1d957 Mon Sep 17 00:00:00 2001
+From 97b2239771769f3d843c72d143e7d683a7472700 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Tue, 8 Jun 2021 03:19:20 +0200
Subject: [PATCH] platform/surface: Add KIP tablet-mode switch
@@ -3827,7 +3943,7 @@ index 32889482de55..6d9291c993c4 100644
obj-$(CONFIG_SURFACE_PRO3_BUTTON) += surfacepro3_button.o
diff --git a/drivers/platform/surface/surface_kip_tablet_switch.c b/drivers/platform/surface/surface_kip_tablet_switch.c
new file mode 100644
-index 000000000000..458470067579
+index 000000000000..27371da71ef2
--- /dev/null
+++ b/drivers/platform/surface/surface_kip_tablet_switch.c
@@ -0,0 +1,245 @@
@@ -3836,7 +3952,7 @@ index 000000000000..458470067579
+ * Surface System Aggregator Module (SSAM) tablet mode switch via KIP
+ * subsystem.
+ *
-+ * Copyright (C) 2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+#include <linux/input.h>
@@ -4077,9 +4193,9 @@ index 000000000000..458470067579
+MODULE_DESCRIPTION("Tablet mode switch driver for Surface devices using KIP subsystem");
+MODULE_LICENSE("GPL");
--
-2.36.0
+2.36.1
-From 228072592809b63575ea69a4d2bb9192beb74b02 Mon Sep 17 00:00:00 2001
+From 58cb6fbb1b2613b195cdc7adfb7261888028e3c9 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Wed, 27 Oct 2021 22:33:03 +0200
Subject: [PATCH] platform/surface: aggregator_registry: Add support for tablet
@@ -4097,7 +4213,7 @@ Patchset: surface-sam
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
-index c0e29c0514df..eaf0054627a5 100644
+index ab69669316bd..c666392d4a9a 100644
--- a/drivers/platform/surface/surface_aggregator_registry.c
+++ b/drivers/platform/surface/surface_aggregator_registry.c
@@ -77,6 +77,12 @@ static const struct software_node ssam_node_tmp_pprof = {
@@ -4127,9 +4243,1640 @@ index c0e29c0514df..eaf0054627a5 100644
};
--
-2.36.0
+2.36.1
+
+From a330b47584598d3b8c4e80993787d7e5f1a1784e Mon Sep 17 00:00:00 2001
+From: Maximilian Luz <luzmaximilian@gmail.com>
+Date: Sat, 21 May 2022 00:30:46 +0200
+Subject: [PATCH] platform/surface: aggregator: Move device registry helper
+ function to core module
+
+Move helper functions for client device registration to the core module.
+This simplifies addition of future DT/OF support and also allows us to
+split out the device hub drivers into their own module.
+
+At the same time, also improve device node validation a bit by not
+silently skipping devices with invalid device UID specifiers.
+
+Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
+Patchset: surface-sam
+---
+ drivers/platform/surface/aggregator/bus.c | 176 ++++++++++++++++--
+ .../surface/surface_aggregator_registry.c | 75 +-------
+ include/linux/surface_aggregator/device.h | 37 ++++
+ 3 files changed, 199 insertions(+), 89 deletions(-)
+
+diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c
+index abbbb5b08b07..4bba60884bb5 100644
+--- a/drivers/platform/surface/aggregator/bus.c
++++ b/drivers/platform/surface/aggregator/bus.c
+@@ -6,6 +6,7 @@
+ */
+
+ #include <linux/device.h>
++#include <linux/property.h>
+ #include <linux/slab.h>
+
+ #include <linux/surface_aggregator/controller.h>
+@@ -14,6 +15,9 @@
+ #include "bus.h"
+ #include "controller.h"
+
++
++/* -- Device and bus functions. --------------------------------------------- */
++
+ static ssize_t modalias_show(struct device *dev, struct device_attribute *attr,
+ char *buf)
+ {
+@@ -363,6 +367,162 @@ void ssam_device_driver_unregister(struct ssam_device_driver *sdrv)
+ }
+ EXPORT_SYMBOL_GPL(ssam_device_driver_unregister);
+
++
++/* -- Bus registration. ----------------------------------------------------- */
++
++/**
++ * ssam_bus_register() - Register and set-up the SSAM client device bus.
++ */
++int ssam_bus_register(void)
++{
++ return bus_register(&ssam_bus_type);
++}
++
++/**
++ * ssam_bus_unregister() - Unregister the SSAM client device bus.
++ */
++void ssam_bus_unregister(void)
++{
++ return bus_unregister(&ssam_bus_type);
++}
++
++
++/* -- Helpers for controller and hub devices. ------------------------------- */
++
++static int ssam_device_uid_from_string(const char *str, struct ssam_device_uid *uid)
++{
++ u8 d, tc, tid, iid, fn;
++ int n;
++
++ n = sscanf(str, "%hhx:%hhx:%hhx:%hhx:%hhx", &d, &tc, &tid, &iid, &fn);
++ if (n != 5)
++ return -EINVAL;
++
++ uid->domain = d;
++ uid->category = tc;
++ uid->target = tid;
++ uid->instance = iid;
++ uid->function = fn;
++
++ return 0;
++}
++
++static int ssam_get_uid_for_node(struct fwnode_handle *node, struct ssam_device_uid *uid)
++{
++ const char* str = fwnode_get_name(node);
++
++ /*
++ * To simplify definitions of firmware nodes, we set the device name
++ * based on the UID of the device, prefixed with "ssam:".
++ */
++ if (strncmp(str, "ssam:", strlen("ssam:")) != 0)
++ return -ENODEV;
++
++ str += strlen("ssam:");
++ return ssam_device_uid_from_string(str, uid);
++}
++
++static int ssam_add_client_device(struct device *parent, struct ssam_controller *ctrl,
++ struct fwnode_handle *node)
++{
++ struct ssam_device_uid uid;
++ struct ssam_device *sdev;
++ int status;
++
++ status = ssam_get_uid_for_node(node, &uid);
++ if (status)
++ return status;
++
++ sdev = ssam_device_alloc(ctrl, uid);
++ if (!sdev)
++ return -ENOMEM;
++
++ sdev->dev.parent = parent;
++ sdev->dev.fwnode = node;
++
++ status = ssam_device_add(sdev);
++ if (status)
++ ssam_device_put(sdev);
++
++ return status;
++}
++
++/**
++ * __ssam_register_clients() - Register client devices defined under the
++ * given firmware node as children of the given device.
++ * @parent: The parent device under which clients should be registered.
++ * @ctrl: The controller with which client should be registered.
++ * @node: The firmware node holding definitions of the devices to be added.
++ *
++ * Register all clients that have been defined as children of the given root
++ * firmware node as children of the given parent device. The respective child
++ * firmware nodes will be associated with the correspondingly created child
++ * devices.
++ *
++ * The given controller will be used to instantiate the new devices. See
++ * ssam_device_add() for details.
++ *
++ * Note that, generally, the use of either ssam_device_register_clients() or
++ * ssam_register_clients() should be preferred as they directly use the
++ * firmware node and/or controller associated with the given device. This
++ * function is only intended for use when different device specifications (e.g.
++ * ACPI and firmware nodes) need to be combined (as is done in the platform hub
++ * of the device registry).
++ *
++ * Return: Returns zero on success, nonzero on failure.
++ */
++int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
++ struct fwnode_handle *node)
++{
++ struct fwnode_handle *child;
++ int status;
++
++ fwnode_for_each_child_node(node, child) {
++ /*
++ * Try to add the device specified in the firmware node. If
++ * this fails with -ENODEV, the node does not specify any SSAM
++ * device, so ignore it and continue with the next one.
++ */
++ status = ssam_add_client_device(parent, ctrl, child);
++ if (status && status != -ENODEV)
++ goto err;
++ }
++
++ return 0;
++err:
++ ssam_remove_clients(parent);
++ return status;
++}
++EXPORT_SYMBOL_GPL(__ssam_register_clients);
++
++/**
++ * ssam_register_clients() - Register all client devices defined under the
++ * given parent device.
++ * @dev: The parent device under which clients should be registered.
++ * @ctrl: The controller with which client should be registered.
++ *
++ * Register all clients that have via firmware nodes been defined as children
++ * of the given (parent) device. The respective child firmware nodes will be
++ * associated with the correspondingly created child devices.
++ *
++ * The given controller will be used to instantiate the new devices. See
++ * ssam_device_add() for details.
++ *
++ * Return: Returns zero on success, nonzero on failure.
++ */
++int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl)
++{
++ struct fwnode_handle *node;
++ int status;
++
++ node = fwnode_handle_get(dev_fwnode(dev));
++ status = __ssam_register_clients(dev, ctrl, node);
++ fwnode_handle_put(node);
++
++ return status;
++}
++EXPORT_SYMBOL_GPL(ssam_register_clients);
++
+ static int ssam_remove_device(struct device *dev, void *_data)
+ {
+ struct ssam_device *sdev = to_ssam_device(dev);
+@@ -387,19 +547,3 @@ void ssam_remove_clients(struct device *dev)
+ device_for_each_child_reverse(dev, NULL, ssam_remove_device);
+ }
+ EXPORT_SYMBOL_GPL(ssam_remove_clients);
+-
+-/**
+- * ssam_bus_register() - Register and set-up the SSAM client device bus.
+- */
+-int ssam_bus_register(void)
+-{
+- return bus_register(&ssam_bus_type);
+-}
+-
+-/**
+- * ssam_bus_unregister() - Unregister the SSAM client device bus.
+- */
+-void ssam_bus_unregister(void)
+-{
+- return bus_unregister(&ssam_bus_type);
+-}
+diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
+index c666392d4a9a..3261c8141841 100644
+--- a/drivers/platform/surface/surface_aggregator_registry.c
++++ b/drivers/platform/surface/surface_aggregator_registry.c
+@@ -279,76 +279,6 @@ static const struct software_node *ssam_node_group_sp8[] = {
+ };
+
+
+-/* -- Device registry helper functions. ------------------------------------- */
+-
+-static int ssam_uid_from_string(const char *str, struct ssam_device_uid *uid)
+-{
+- u8 d, tc, tid, iid, fn;
+- int n;
+-
+- n = sscanf(str, "ssam:%hhx:%hhx:%hhx:%hhx:%hhx", &d, &tc, &tid, &iid, &fn);
+- if (n != 5)
+- return -EINVAL;
+-
+- uid->domain = d;
+- uid->category = tc;
+- uid->target = tid;
+- uid->instance = iid;
+- uid->function = fn;
+-
+- return 0;
+-}
+-
+-static int ssam_hub_add_device(struct device *parent, struct ssam_controller *ctrl,
+- struct fwnode_handle *node)
+-{
+- struct ssam_device_uid uid;
+- struct ssam_device *sdev;
+- int status;
+-
+- status = ssam_uid_from_string(fwnode_get_name(node), &uid);
+- if (status)
+- return status;
+-
+- sdev = ssam_device_alloc(ctrl, uid);
+- if (!sdev)
+- return -ENOMEM;
+-
+- sdev->dev.parent = parent;
+- sdev->dev.fwnode = node;
+-
+- status = ssam_device_add(sdev);
+- if (status)
+- ssam_device_put(sdev);
+-
+- return status;
+-}
+-
+-static int ssam_hub_register_clients(struct device *parent, struct ssam_controller *ctrl,
+- struct fwnode_handle *node)
+-{
+- struct fwnode_handle *child;
+- int status;
+-
+- fwnode_for_each_child_node(node, child) {
+- /*
+- * Try to add the device specified in the firmware node. If
+- * this fails with -EINVAL, the node does not specify any SSAM
+- * device, so ignore it and continue with the next one.
+- */
+-
+- status = ssam_hub_add_device(parent, ctrl, child);
+- if (status && status != -EINVAL)
+- goto err;
+- }
+-
+- return 0;
+-err:
+- ssam_remove_clients(parent);
+- return status;
+-}
+-
+-
+ /* -- SSAM generic subsystem hub driver framework. -------------------------- */
+
+ enum ssam_hub_state {
+@@ -378,7 +308,6 @@ struct ssam_hub {
+ static void ssam_hub_update_workfn(struct work_struct *work)
+ {
+ struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
+- struct fwnode_handle *node = dev_fwnode(&hub->sdev->dev);
+ enum ssam_hub_state state;
+ int status = 0;
+
+@@ -418,7 +347,7 @@ static void ssam_hub_update_workfn(struct work_struct *work)
+ hub->state = state;
+
+ if (hub->state == SSAM_HUB_CONNECTED)
+- status = ssam_hub_register_clients(&hub->sdev->dev, hub->sdev->ctrl, node);
++ status = ssam_device_register_clients(hub->sdev);
+ else
+ ssam_remove_clients(&hub->sdev->dev);
+
+@@ -762,7 +691,7 @@ static int ssam_platform_hub_probe(struct platform_device *pdev)
+
+ set_secondary_fwnode(&pdev->dev, root);
+
+- status = ssam_hub_register_clients(&pdev->dev, ctrl, root);
++ status = __ssam_register_clients(&pdev->dev, ctrl, root);
+ if (status) {
+ set_secondary_fwnode(&pdev->dev, NULL);
+ software_node_unregister_node_group(nodes);
+diff --git a/include/linux/surface_aggregator/device.h b/include/linux/surface_aggregator/device.h
+index ad245c6b00d0..6ae110e830b4 100644
+--- a/include/linux/surface_aggregator/device.h
++++ b/include/linux/surface_aggregator/device.h
+@@ -364,11 +364,48 @@ void ssam_device_driver_unregister(struct ssam_device_driver *d);
+ /* -- Helpers for controller and hub devices. ------------------------------- */
+
+ #ifdef CONFIG_SURFACE_AGGREGATOR_BUS
++
++int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
++ struct fwnode_handle *node);
++int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl);
+ void ssam_remove_clients(struct device *dev);
++
+ #else /* CONFIG_SURFACE_AGGREGATOR_BUS */
++
++static inline int __ssam_register_clients(struct device *parent, struct ssam_controller *ctrl,
++ struct fwnode_handle *node)
++{
++ return 0;
++}
++
++static inline int ssam_register_clients(struct device *dev, struct ssam_controller *ctrl)
++{
++ return 0;
++}
++
+ static inline void ssam_remove_clients(struct device *dev) {}
++
+ #endif /* CONFIG_SURFACE_AGGREGATOR_BUS */
+
++/**
++ * ssam_device_register_clients() - Register all client devices defined under
++ * the given SSAM parent device.
++ * @sdev: The parent device under which clients should be registered.
++ *
++ * Register all clients that have via firmware nodes been defined as children
++ * of the given (parent) device. The respective child firmware nodes will be
++ * associated with the correspondingly created child devices.
++ *
++ * The controller used by the parent device will be used to instantiate the new
++ * devices. See ssam_device_add() for details.
++ *
++ * Return: Returns zero on success, nonzero on failure.
++ */
++static inline int ssam_device_register_clients(struct ssam_device *sdev)
++{
++ return ssam_register_clients(&sdev->dev, sdev->ctrl);
++}
++
+
+ /* -- Helpers for client-device requests. ----------------------------------- */
+
+--
+2.36.1
+
+From cefc65cdcead1c23ab8a793d8a3779fed1e6f86d Mon Sep 17 00:00:00 2001
+From: Maximilian Luz <luzmaximilian@gmail.com>
+Date: Sat, 21 May 2022 00:39:56 +0200
+Subject: [PATCH] platform/surface: aggregator: Move subsystem hub drivers to
+ their own module
+
+Split out subsystem device hub drivers into their own module. This
+allows us to load the hub drivers separately from the registry, which
+will help future DT/OF support.
+
+While doing so, also remove a small bit of code duplication.
+
+Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
+Patchset: surface-sam
+---
+ drivers/platform/surface/Kconfig | 35 +-
+ drivers/platform/surface/Makefile | 1 +
+ .../platform/surface/surface_aggregator_hub.c | 363 +++++++++++++++++
+ .../surface/surface_aggregator_registry.c | 371 +-----------------
+ 4 files changed, 396 insertions(+), 374 deletions(-)
+ create mode 100644 drivers/platform/surface/surface_aggregator_hub.c
+
+diff --git a/drivers/platform/surface/Kconfig b/drivers/platform/surface/Kconfig
+index 9c228090c35b..c685ec440535 100644
+--- a/drivers/platform/surface/Kconfig
++++ b/drivers/platform/surface/Kconfig
+@@ -79,18 +79,45 @@ config SURFACE_AGGREGATOR_CDEV
+ The provided interface is intended for debugging and development only,
+ and should not be used otherwise.
+
++config SURFACE_AGGREGATOR_HUB
++ tristate "Surface System Aggregator Module Subsystem Device Hubs"
++ depends on SURFACE_AGGREGATOR
++ depends on SURFACE_AGGREGATOR_BUS
++ help
++ Device-hub drivers for Surface System Aggregator Module (SSAM) subsystem
++ devices.
++
++ Provides subsystem hub drivers which manage client devices on various
++ SSAM subsystems. In some subsystems, notably the BAS subsystem managing
++ devices contained in the base of the Surface Book 3 and the KIP subsystem
++ managing type-cover devices in the Surface Pro 8 and Surface Pro X,
++ devices can be (hot-)removed. Hub devices and drivers are required to
++ manage these subdevices.
++
++ Devices managed via these hubs are:
++ - Battery/AC devices (Surface Book 3).
++ - HID input devices (7th-generation and later models with detachable
++ input devices).
++
++ Select M (recommended) or Y here if you want support for the above
++ mentioned devices on the corresponding Surface models. Without this
++ module, the respective devices mentioned above will not be instantiated
++ and thus any functionality provided by them will be missing, even when
++ drivers for these devices are present. This module only provides the
++ respective subsystem hubs. Both drivers and device specification (e.g.
++ via the Surface Aggregator Registry) for these devices still need to be
++ selected via other options.
++
+ config SURFACE_AGGREGATOR_REGISTRY
+ tristate "Surface System Aggregator Module Device Registry"
+ depends on SURFACE_AGGREGATOR
+ depends on SURFACE_AGGREGATOR_BUS
+ help
+- Device-registry and device-hubs for Surface System Aggregator Module
+- (SSAM) devices.
++ Device-registry for Surface System Aggregator Module (SSAM) devices.
+
+ Provides a module and driver which act as a device-registry for SSAM
+ client devices that cannot be detected automatically, e.g. via ACPI.
+- Such devices are instead provided via this registry and attached via
+- device hubs, also provided in this module.
++ Such devices are instead provided and managed via this registry.
+
+ Devices provided via this registry are:
+ - Platform profile (performance-/cooling-mode) device (5th- and later
+diff --git a/drivers/platform/surface/Makefile b/drivers/platform/surface/Makefile
+index 6d9291c993c4..fccd33e6780d 100644
+--- a/drivers/platform/surface/Makefile
++++ b/drivers/platform/surface/Makefile
+@@ -10,6 +10,7 @@ obj-$(CONFIG_SURFACE_3_POWER_OPREGION) += surface3_power.o
+ obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o
+ obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/
+ obj-$(CONFIG_SURFACE_AGGREGATOR_CDEV) += surface_aggregator_cdev.o
++obj-$(CONFIG_SURFACE_AGGREGATOR_HUB) += surface_aggregator_hub.o
+ obj-$(CONFIG_SURFACE_AGGREGATOR_REGISTRY) += surface_aggregator_registry.o
+ obj-$(CONFIG_SURFACE_DTX) += surface_dtx.o
+ obj-$(CONFIG_SURFACE_GPE) += surface_gpe.o
+diff --git a/drivers/platform/surface/surface_aggregator_hub.c b/drivers/platform/surface/surface_aggregator_hub.c
+new file mode 100644
+index 000000000000..20b1c38debfe
+--- /dev/null
++++ b/drivers/platform/surface/surface_aggregator_hub.c
+@@ -0,0 +1,363 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Driver for Surface System Aggregator Module (SSAM) subsystem device hubs.
++ *
++ * Provides a driver for SSAM subsystems device hubs. This driver performs
++ * instantiation of the devices managed by said hubs and takes care of
++ * (hot-)removal.
++ *
++ * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
++ */
++
++#include <linux/kernel.h>
++#include <linux/limits.h>
++#include <linux/module.h>
++#include <linux/types.h>
++#include <linux/workqueue.h>
++
++#include <linux/surface_aggregator/device.h>
++
++
++/* -- SSAM generic subsystem hub driver framework. -------------------------- */
++
++enum ssam_hub_state {
++ SSAM_HUB_UNINITIALIZED, /* Only set during initialization. */
++ SSAM_HUB_CONNECTED,
++ SSAM_HUB_DISCONNECTED,
++};
++
++enum ssam_hub_flags {
++ SSAM_HUB_HOT_REMOVED,
++};
++
++struct ssam_hub {
++ struct ssam_device *sdev;
++
++ enum ssam_hub_state state;
++ unsigned long flags;
++
++ struct delayed_work update_work;
++ unsigned long connect_delay;
++
++ struct ssam_event_notifier notif;
++
++ int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
++};
++
++struct ssam_hub_info {
++ struct {
++ struct ssam_event_registry reg;
++ struct ssam_event_id id;
++ enum ssam_event_mask mask;
++ u8 flags;
++ } event;
++
++ u32 (*notify)(struct ssam_event_notifier *nf, const struct ssam_event *event);
++ int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
++
++ unsigned long connect_delay_ms;
++};
++
++static void ssam_hub_update_workfn(struct work_struct *work)
++{
++ struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
++ enum ssam_hub_state state;
++ int status = 0;
++
++ status = hub->get_state(hub, &state);
++ if (status)
++ return;
++
++ /*
++ * There is a small possibility that hub devices were hot-removed and
++ * re-added before we were able to remove them here. In that case, both
++ * the state returned by get_state() and the state of the hub will
++ * equal SSAM_HUB_CONNECTED and we would bail early below, which would
++ * leave child devices without proper (re-)initialization and the
++ * hot-remove flag set.
++ *
++ * Therefore, we check whether devices have been hot-removed via an
++ * additional flag on the hub and, in this case, override the returned
++ * hub state. In case of a missed disconnect (i.e. get_state returned
++ * "connected"), we further need to re-schedule this work (with the
++ * appropriate delay) as the actual connect work submission might have
++ * been merged with this one.
++ *
++ * This then leads to one of two cases: Either we submit an unnecessary
++ * work item (which will get ignored via either the queue or the state
++ * checks) or, in the unlikely case that the work is actually required,
++ * double the normal connect delay.
++ */
++ if (test_and_clear_bit(SSAM_HUB_HOT_REMOVED, &hub->flags)) {
++ if (state == SSAM_HUB_CONNECTED)
++ schedule_delayed_work(&hub->update_work, hub->connect_delay);
++
++ state = SSAM_HUB_DISCONNECTED;
++ }
++
++ if (hub->state == state)
++ return;
++ hub->state = state;
++
++ if (hub->state == SSAM_HUB_CONNECTED)
++ status = ssam_device_register_clients(hub->sdev);
++ else
++ ssam_remove_clients(&hub->sdev->dev);
++
++ if (status)
++ dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status);
++}
++
++static int ssam_hub_mark_hot_removed(struct device *dev, void *_data)
++{
++ struct ssam_device *sdev = to_ssam_device(dev);
++
++ if (is_ssam_device(dev))
++ ssam_device_mark_hot_removed(sdev);
++
++ return 0;
++}
++
++static void ssam_hub_update(struct ssam_hub *hub, bool connected)
++{
++ unsigned long delay;
++
++ /* Mark devices as hot-removed before we remove any. */
++ if (!connected) {
++ set_bit(SSAM_HUB_HOT_REMOVED, &hub->flags);
++ device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed);
++ }
++
++ /*
++ * Delay update when the base/keyboard cover is being connected to give
++ * devices/EC some time to set up.
++ */
++ delay = connected ? hub->connect_delay : 0;
++
++ schedule_delayed_work(&hub->update_work, delay);
++}
++
++static int __maybe_unused ssam_hub_resume(struct device *dev)
++{
++ struct ssam_hub *hub = dev_get_drvdata(dev);
++
++ schedule_delayed_work(&hub->update_work, 0);
++ return 0;
++}
++static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume);
++
++static int ssam_hub_probe(struct ssam_device *sdev)
++{
++ const struct ssam_hub_info *info;
++ struct ssam_hub *hub;
++ int status;
++
++ info = ssam_device_get_match_data(sdev);
++ if (!info) {
++ WARN(1, "no driver match data specified");
++ return -EINVAL;
++ }
++
++ hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
++ if (!hub)
++ return -ENOMEM;
++
++ hub->sdev = sdev;
++ hub->state = SSAM_HUB_UNINITIALIZED;
++
++ hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
++ hub->notif.base.fn = info->notify;
++ hub->notif.event.reg = info->event.reg;
++ hub->notif.event.id = info->event.id;
++ hub->notif.event.mask = info->event.mask;
++ hub->notif.event.flags = info->event.flags;
++
++ hub->connect_delay = msecs_to_jiffies(info->connect_delay_ms);
++ hub->get_state = info->get_state;
++
++ INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn);
++
++ ssam_device_set_drvdata(sdev, hub);
++
++ status = ssam_device_notifier_register(sdev, &hub->notif);
++ if (status)
++ return status;
++
++ schedule_delayed_work(&hub->update_work, 0);
++ return 0;
++}
++
++static void ssam_hub_remove(struct ssam_device *sdev)
++{
++ struct ssam_hub *hub = ssam_device_get_drvdata(sdev);
++
++ ssam_device_notifier_unregister(sdev, &hub->notif);
++ cancel_delayed_work_sync(&hub->update_work);
++ ssam_remove_clients(&sdev->dev);
++}
++
++
++/* -- SSAM base-subsystem hub driver. --------------------------------------- */
++
++/*
++ * Some devices (especially battery) may need a bit of time to be fully usable
++ * after being (re-)connected. This delay has been determined via
++ * experimentation.
++ */
++#define SSAM_BASE_UPDATE_CONNECT_DELAY 2500
++
++SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
++ .target_category = SSAM_SSH_TC_BAS,
++ .target_id = 0x01,
++ .command_id = 0x0d,
++ .instance_id = 0x00,
++});
++
++#define SSAM_BAS_OPMODE_TABLET 0x00
++#define SSAM_EVENT_BAS_CID_CONNECTION 0x0c
++
++static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
++{
++ u8 opmode;
++ int status;
++
++ status = ssam_retry(ssam_bas_query_opmode, hub->sdev->ctrl, &opmode);
++ if (status < 0) {
++ dev_err(&hub->sdev->dev, "failed to query base state: %d\n", status);
++ return status;
++ }
++
++ if (opmode != SSAM_BAS_OPMODE_TABLET)
++ *state = SSAM_HUB_CONNECTED;
++ else
++ *state = SSAM_HUB_DISCONNECTED;
++
++ return 0;
++}
++
++static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
++{
++ struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
++
++ if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION)
++ return 0;
++
++ if (event->length < 1) {
++ dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
++ return 0;
++ }
++
++ ssam_hub_update(hub, event->data[0]);
++
++ /*
++ * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and
++ * consumed by the detachment system driver. We're just a (more or less)
++ * silent observer.
++ */
++ return 0;
++}
++
++static const struct ssam_hub_info base_hub = {
++ .event = {
++ .reg = SSAM_EVENT_REGISTRY_SAM,
++ .id = {
++ .target_category = SSAM_SSH_TC_BAS,
++ .instance = 0,
++ },
++ .mask = SSAM_EVENT_MASK_NONE,
++ .flags = SSAM_EVENT_SEQUENCED,
++ },
++ .notify = ssam_base_hub_notif,
++ .get_state = ssam_base_hub_query_state,
++ .connect_delay_ms = SSAM_BASE_UPDATE_CONNECT_DELAY,
++};
++
++
++/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */
++
++/*
++ * Some devices may need a bit of time to be fully usable after being
++ * (re-)connected. This delay has been determined via experimentation.
++ */
++#define SSAM_KIP_UPDATE_CONNECT_DELAY 250
++
++#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c
++
++SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_query_state, u8, {
++ .target_category = SSAM_SSH_TC_KIP,
++ .target_id = 0x01,
++ .command_id = 0x2c,
++ .instance_id = 0x00,
++});
++
++static int ssam_kip_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
++{
++ int status;
++ u8 connected;
++
++ status = ssam_retry(__ssam_kip_query_state, hub->sdev->ctrl, &connected);
++ if (status < 0) {
++ dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status);
++ return status;
++ }
++
++ *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED;
++ return 0;
++}
++
++static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
++{
++ struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
++
++ if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION)
++ return 0; /* Return "unhandled". */
++
++ if (event->length < 1) {
++ dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
++ return 0;
++ }
++
++ ssam_hub_update(hub, event->data[0]);
++ return SSAM_NOTIF_HANDLED;
++}
++
++static const struct ssam_hub_info kip_hub = {
++ .event = {
++ .reg = SSAM_EVENT_REGISTRY_SAM,
++ .id = {
++ .target_category = SSAM_SSH_TC_KIP,
++ .instance = 0,
++ },
++ .mask = SSAM_EVENT_MASK_TARGET,
++ .flags = SSAM_EVENT_SEQUENCED,
++ },
++ .notify = ssam_kip_hub_notif,
++ .get_state = ssam_kip_hub_query_state,
++ .connect_delay_ms = SSAM_KIP_UPDATE_CONNECT_DELAY,
++};
++
++
++/* -- Driver registration. -------------------------------------------------- */
++
++static const struct ssam_device_id ssam_hub_match[] = {
++ { SSAM_VDEV(HUB, 0x02, SSAM_ANY_IID, 0x00), (unsigned long)&base_hub },
++ { SSAM_SDEV(KIP, 0x01, 0x00, 0x00), (unsigned long)&kip_hub },
++ { }
++};
++MODULE_DEVICE_TABLE(ssam, ssam_hub_match);
++
++static struct ssam_device_driver ssam_subsystem_hub_driver = {
++ .probe = ssam_hub_probe,
++ .remove = ssam_hub_remove,
++ .match_table = ssam_hub_match,
++ .driver = {
++ .name = "surface_aggregator_subsystem_hub",
++ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
++ .pm = &ssam_hub_pm_ops,
++ },
++};
++module_ssam_device_driver(ssam_subsystem_hub_driver);
++
++MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
++MODULE_DESCRIPTION("Subsystem device hub driver for Surface System Aggregator Module");
++MODULE_LICENSE("GPL");
+diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
+index 3261c8141841..11b51aa9ea73 100644
+--- a/drivers/platform/surface/surface_aggregator_registry.c
++++ b/drivers/platform/surface/surface_aggregator_registry.c
+@@ -11,14 +11,11 @@
+
+ #include <linux/acpi.h>
+ #include <linux/kernel.h>
+-#include <linux/limits.h>
+ #include <linux/module.h>
+ #include <linux/platform_device.h>
+ #include <linux/property.h>
+ #include <linux/types.h>
+-#include <linux/workqueue.h>
+
+-#include <linux/surface_aggregator/controller.h>
+ #include <linux/surface_aggregator/device.h>
+
+
+@@ -279,335 +276,6 @@ static const struct software_node *ssam_node_group_sp8[] = {
+ };
+
+
+-/* -- SSAM generic subsystem hub driver framework. -------------------------- */
+-
+-enum ssam_hub_state {
+- SSAM_HUB_UNINITIALIZED, /* Only set during initialization. */
+- SSAM_HUB_CONNECTED,
+- SSAM_HUB_DISCONNECTED,
+-};
+-
+-enum ssam_hub_flags {
+- SSAM_HUB_HOT_REMOVED,
+-};
+-
+-struct ssam_hub {
+- struct ssam_device *sdev;
+-
+- enum ssam_hub_state state;
+- unsigned long flags;
+-
+- struct delayed_work update_work;
+- unsigned long connect_delay;
+-
+- struct ssam_event_notifier notif;
+-
+- int (*get_state)(struct ssam_hub *hub, enum ssam_hub_state *state);
+-};
+-
+-static void ssam_hub_update_workfn(struct work_struct *work)
+-{
+- struct ssam_hub *hub = container_of(work, struct ssam_hub, update_work.work);
+- enum ssam_hub_state state;
+- int status = 0;
+-
+- status = hub->get_state(hub, &state);
+- if (status)
+- return;
+-
+- /*
+- * There is a small possibility that hub devices were hot-removed and
+- * re-added before we were able to remove them here. In that case, both
+- * the state returned by get_state() and the state of the hub will
+- * equal SSAM_HUB_CONNECTED and we would bail early below, which would
+- * leave child devices without proper (re-)initialization and the
+- * hot-remove flag set.
+- *
+- * Therefore, we check whether devices have been hot-removed via an
+- * additional flag on the hub and, in this case, override the returned
+- * hub state. In case of a missed disconnect (i.e. get_state returned
+- * "connected"), we further need to re-schedule this work (with the
+- * appropriate delay) as the actual connect work submission might have
+- * been merged with this one.
+- *
+- * This then leads to one of two cases: Either we submit an unnecessary
+- * work item (which will get ignored via either the queue or the state
+- * checks) or, in the unlikely case that the work is actually required,
+- * double the normal connect delay.
+- */
+- if (test_and_clear_bit(SSAM_HUB_HOT_REMOVED, &hub->flags)) {
+- if (state == SSAM_HUB_CONNECTED)
+- schedule_delayed_work(&hub->update_work, hub->connect_delay);
+-
+- state = SSAM_HUB_DISCONNECTED;
+- }
+-
+- if (hub->state == state)
+- return;
+- hub->state = state;
+-
+- if (hub->state == SSAM_HUB_CONNECTED)
+- status = ssam_device_register_clients(hub->sdev);
+- else
+- ssam_remove_clients(&hub->sdev->dev);
+-
+- if (status)
+- dev_err(&hub->sdev->dev, "failed to update hub child devices: %d\n", status);
+-}
+-
+-static int ssam_hub_mark_hot_removed(struct device *dev, void *_data)
+-{
+- struct ssam_device *sdev = to_ssam_device(dev);
+-
+- if (is_ssam_device(dev))
+- ssam_device_mark_hot_removed(sdev);
+-
+- return 0;
+-}
+-
+-static void ssam_hub_update(struct ssam_hub *hub, bool connected)
+-{
+- unsigned long delay;
+-
+- /* Mark devices as hot-removed before we remove any. */
+- if (!connected) {
+- set_bit(SSAM_HUB_HOT_REMOVED, &hub->flags);
+- device_for_each_child_reverse(&hub->sdev->dev, NULL, ssam_hub_mark_hot_removed);
+- }
+-
+- /*
+- * Delay update when the base/keyboard cover is being connected to give
+- * devices/EC some time to set up.
+- */
+- delay = connected ? hub->connect_delay : 0;
+-
+- schedule_delayed_work(&hub->update_work, delay);
+-}
+-
+-static int __maybe_unused ssam_hub_resume(struct device *dev)
+-{
+- struct ssam_hub *hub = dev_get_drvdata(dev);
+-
+- schedule_delayed_work(&hub->update_work, 0);
+- return 0;
+-}
+-static SIMPLE_DEV_PM_OPS(ssam_hub_pm_ops, NULL, ssam_hub_resume);
+-
+-static int ssam_hub_setup(struct ssam_device *sdev, struct ssam_hub *hub)
+-{
+- int status;
+-
+- hub->sdev = sdev;
+- hub->state = SSAM_HUB_UNINITIALIZED;
+-
+- INIT_DELAYED_WORK(&hub->update_work, ssam_hub_update_workfn);
+-
+- ssam_device_set_drvdata(sdev, hub);
+-
+- status = ssam_device_notifier_register(sdev, &hub->notif);
+- if (status)
+- return status;
+-
+- schedule_delayed_work(&hub->update_work, 0);
+- return 0;
+-}
+-
+-static void ssam_hub_remove(struct ssam_device *sdev)
+-{
+- struct ssam_hub *hub = ssam_device_get_drvdata(sdev);
+-
+- ssam_device_notifier_unregister(sdev, &hub->notif);
+- cancel_delayed_work_sync(&hub->update_work);
+- ssam_remove_clients(&sdev->dev);
+-}
+-
+-
+-/* -- SSAM base-hub driver. ------------------------------------------------- */
+-
+-/*
+- * Some devices (especially battery) may need a bit of time to be fully usable
+- * after being (re-)connected. This delay has been determined via
+- * experimentation.
+- */
+-#define SSAM_BASE_UPDATE_CONNECT_DELAY msecs_to_jiffies(2500)
+-
+-SSAM_DEFINE_SYNC_REQUEST_R(ssam_bas_query_opmode, u8, {
+- .target_category = SSAM_SSH_TC_BAS,
+- .target_id = 0x01,
+- .command_id = 0x0d,
+- .instance_id = 0x00,
+-});
+-
+-#define SSAM_BAS_OPMODE_TABLET 0x00
+-#define SSAM_EVENT_BAS_CID_CONNECTION 0x0c
+-
+-static int ssam_base_hub_query_state(struct ssam_hub *hub, enum ssam_hub_state *state)
+-{
+- u8 opmode;
+- int status;
+-
+- status = ssam_retry(ssam_bas_query_opmode, hub->sdev->ctrl, &opmode);
+- if (status < 0) {
+- dev_err(&hub->sdev->dev, "failed to query base state: %d\n", status);
+- return status;
+- }
+-
+- if (opmode != SSAM_BAS_OPMODE_TABLET)
+- *state = SSAM_HUB_CONNECTED;
+- else
+- *state = SSAM_HUB_DISCONNECTED;
+-
+- return 0;
+-}
+-
+-static u32 ssam_base_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
+-{
+- struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
+-
+- if (event->command_id != SSAM_EVENT_BAS_CID_CONNECTION)
+- return 0;
+-
+- if (event->length < 1) {
+- dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
+- return 0;
+- }
+-
+- ssam_hub_update(hub, event->data[0]);
+-
+- /*
+- * Do not return SSAM_NOTIF_HANDLED: The event should be picked up and
+- * consumed by the detachment system driver. We're just a (more or less)
+- * silent observer.
+- */
+- return 0;
+-}
+-
+-static int ssam_base_hub_probe(struct ssam_device *sdev)
+-{
+- struct ssam_hub *hub;
+-
+- hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
+- if (!hub)
+- return -ENOMEM;
+-
+- hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
+- hub->notif.base.fn = ssam_base_hub_notif;
+- hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
+- hub->notif.event.id.target_category = SSAM_SSH_TC_BAS,
+- hub->notif.event.id.instance = 0,
+- hub->notif.event.mask = SSAM_EVENT_MASK_NONE;
+- hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
+-
+- hub->connect_delay = SSAM_BASE_UPDATE_CONNECT_DELAY;
+- hub->get_state = ssam_base_hub_query_state;
+-
+- return ssam_hub_setup(sdev, hub);
+-}
+-
+-static const struct ssam_device_id ssam_base_hub_match[] = {
+- { SSAM_VDEV(HUB, 0x02, SSAM_ANY_IID, 0x00) },
+- { },
+-};
+-
+-static struct ssam_device_driver ssam_base_hub_driver = {
+- .probe = ssam_base_hub_probe,
+- .remove = ssam_hub_remove,
+- .match_table = ssam_base_hub_match,
+- .driver = {
+- .name = "surface_aggregator_base_hub",
+- .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+- .pm = &ssam_hub_pm_ops,
+- },
+-};
+-
+-
+-/* -- SSAM KIP-subsystem hub driver. ---------------------------------------- */
+-
+-/*
+- * Some devices may need a bit of time to be fully usable after being
+- * (re-)connected. This delay has been determined via experimentation.
+- */
+-#define SSAM_KIP_UPDATE_CONNECT_DELAY msecs_to_jiffies(250)
+-
+-#define SSAM_EVENT_KIP_CID_CONNECTION 0x2c
+-
+-SSAM_DEFINE_SYNC_REQUEST_R(__ssam_kip_get_connection_state, u8, {
+- .target_category = SSAM_SSH_TC_KIP,
+- .target_id = 0x01,
+- .command_id = 0x2c,
+- .instance_id = 0x00,
+-});
+-
+-static int ssam_kip_get_connection_state(struct ssam_hub *hub, enum ssam_hub_state *state)
+-{
+- int status;
+- u8 connected;
+-
+- status = ssam_retry(__ssam_kip_get_connection_state, hub->sdev->ctrl, &connected);
+- if (status < 0) {
+- dev_err(&hub->sdev->dev, "failed to query KIP connection state: %d\n", status);
+- return status;
+- }
+-
+- *state = connected ? SSAM_HUB_CONNECTED : SSAM_HUB_DISCONNECTED;
+- return 0;
+-}
+-
+-static u32 ssam_kip_hub_notif(struct ssam_event_notifier *nf, const struct ssam_event *event)
+-{
+- struct ssam_hub *hub = container_of(nf, struct ssam_hub, notif);
+-
+- if (event->command_id != SSAM_EVENT_KIP_CID_CONNECTION)
+- return 0; /* Return "unhandled". */
+-
+- if (event->length < 1) {
+- dev_err(&hub->sdev->dev, "unexpected payload size: %u\n", event->length);
+- return 0;
+- }
+-
+- ssam_hub_update(hub, event->data[0]);
+- return SSAM_NOTIF_HANDLED;
+-}
+-
+-static int ssam_kip_hub_probe(struct ssam_device *sdev)
+-{
+- struct ssam_hub *hub;
+-
+- hub = devm_kzalloc(&sdev->dev, sizeof(*hub), GFP_KERNEL);
+- if (!hub)
+- return -ENOMEM;
+-
+- hub->notif.base.priority = INT_MAX; /* This notifier should run first. */
+- hub->notif.base.fn = ssam_kip_hub_notif;
+- hub->notif.event.reg = SSAM_EVENT_REGISTRY_SAM;
+- hub->notif.event.id.target_category = SSAM_SSH_TC_KIP,
+- hub->notif.event.id.instance = 0,
+- hub->notif.event.mask = SSAM_EVENT_MASK_TARGET;
+- hub->notif.event.flags = SSAM_EVENT_SEQUENCED;
+-
+- hub->connect_delay = SSAM_KIP_UPDATE_CONNECT_DELAY;
+- hub->get_state = ssam_kip_get_connection_state;
+-
+- return ssam_hub_setup(sdev, hub);
+-}
+-
+-static const struct ssam_device_id ssam_kip_hub_match[] = {
+- { SSAM_SDEV(KIP, 0x01, 0x00, 0x00) },
+- { },
+-};
+-
+-static struct ssam_device_driver ssam_kip_hub_driver = {
+- .probe = ssam_kip_hub_probe,
+- .remove = ssam_hub_remove,
+- .match_table = ssam_kip_hub_match,
+- .driver = {
+- .name = "surface_kip_hub",
+- .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+- .pm = &ssam_hub_pm_ops,
+- },
+-};
+-
+-
+ /* -- SSAM platform/meta-hub driver. ---------------------------------------- */
+
+ static const struct acpi_device_id ssam_platform_hub_match[] = {
+@@ -720,44 +388,7 @@ static struct platform_driver ssam_platform_hub_driver = {
+ .probe_type = PROBE_PREFER_ASYNCHRONOUS,
+ },
+ };
+-
+-
+-/* -- Module initialization. ------------------------------------------------ */
+-
+-static int __init ssam_device_hub_init(void)
+-{
+- int status;
+-
+- status = platform_driver_register(&ssam_platform_hub_driver);
+- if (status)
+- goto err_platform;
+-
+- status = ssam_device_driver_register(&ssam_base_hub_driver);
+- if (status)
+- goto err_base;
+-
+- status = ssam_device_driver_register(&ssam_kip_hub_driver);
+- if (status)
+- goto err_kip;
+-
+- return 0;
+-
+-err_kip:
+- ssam_device_driver_unregister(&ssam_base_hub_driver);
+-err_base:
+- platform_driver_unregister(&ssam_platform_hub_driver);
+-err_platform:
+- return status;
+-}
+-module_init(ssam_device_hub_init);
+-
+-static void __exit ssam_device_hub_exit(void)
+-{
+- ssam_device_driver_unregister(&ssam_kip_hub_driver);
+- ssam_device_driver_unregister(&ssam_base_hub_driver);
+- platform_driver_unregister(&ssam_platform_hub_driver);
+-}
+-module_exit(ssam_device_hub_exit);
++module_platform_driver(ssam_platform_hub_driver);
+
+ MODULE_AUTHOR("Maximilian Luz <luzmaximilian@gmail.com>");
+ MODULE_DESCRIPTION("Device-registry for Surface System Aggregator Module");
+--
+2.36.1
-From 82ae885ad1824b149d18d7ac938988d9a5b279d5 Mon Sep 17 00:00:00 2001
+From e2d2b665e1877096405e8c6b84922880d4bb795b Mon Sep 17 00:00:00 2001
+From: Maximilian Luz <luzmaximilian@gmail.com>
+Date: Sat, 21 May 2022 00:51:05 +0200
+Subject: [PATCH] platform/surface: aggregator: Be consistent with hub device
+ IDs
+
+Currently, we use a virtual device ID for the base (BAS) hub but an
+actual device ID for the KIP hub. Let's be consistent about the naming
+format and make all hubs virtual, with their instance ID reflecting the
+subsystem.
+
+Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
+Patchset: surface-sam
+---
+ drivers/platform/surface/surface_aggregator_hub.c | 4 ++--
+ .../platform/surface/surface_aggregator_registry.c | 12 ++++++------
+ 2 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/drivers/platform/surface/surface_aggregator_hub.c b/drivers/platform/surface/surface_aggregator_hub.c
+index 20b1c38debfe..c473bdebf90c 100644
+--- a/drivers/platform/surface/surface_aggregator_hub.c
++++ b/drivers/platform/surface/surface_aggregator_hub.c
+@@ -340,8 +340,8 @@ static const struct ssam_hub_info kip_hub = {
+ /* -- Driver registration. -------------------------------------------------- */
+
+ static const struct ssam_device_id ssam_hub_match[] = {
+- { SSAM_VDEV(HUB, 0x02, SSAM_ANY_IID, 0x00), (unsigned long)&base_hub },
+- { SSAM_SDEV(KIP, 0x01, 0x00, 0x00), (unsigned long)&kip_hub },
++ { SSAM_VDEV(HUB, 0x01, SSAM_SSH_TC_KIP, 0x00), (unsigned long)&kip_hub },
++ { SSAM_VDEV(HUB, 0x02, SSAM_SSH_TC_BAS, 0x00), (unsigned long)&base_hub },
+ { }
+ };
+ MODULE_DEVICE_TABLE(ssam, ssam_hub_match);
+diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
+index 11b51aa9ea73..cee7121e7fa6 100644
+--- a/drivers/platform/surface/surface_aggregator_registry.c
++++ b/drivers/platform/surface/surface_aggregator_registry.c
+@@ -38,15 +38,15 @@ static const struct software_node ssam_node_root = {
+ .name = "ssam_platform_hub",
+ };
+
+-/* Base device hub (devices attached to Surface Book 3 base). */
+-static const struct software_node ssam_node_hub_base = {
+- .name = "ssam:00:00:02:00:00",
++/* KIP device hub (connects keyboard cover devices on Surface Pro 8). */
++static const struct software_node ssam_node_hub_kip = {
++ .name = "ssam:00:00:01:0e:00",
+ .parent = &ssam_node_root,
+ };
+
+-/* KIP device hub (connects keyboard cover devices on Surface Pro 8). */
+-static const struct software_node ssam_node_hub_kip = {
+- .name = "ssam:01:0e:01:00:00",
++/* Base device hub (devices attached to Surface Book 3 base). */
++static const struct software_node ssam_node_hub_base = {
++ .name = "ssam:00:00:02:11:00",
+ .parent = &ssam_node_root,
+ };
+
+--
+2.36.1
+
+From 525b0a215a224a430766886ae4f382f5684095f2 Mon Sep 17 00:00:00 2001
+From: Maximilian Luz <luzmaximilian@gmail.com>
+Date: Sat, 21 May 2022 00:57:40 +0200
+Subject: [PATCH] platform/surface: Update copyright year of various drivers
+
+Update the copyright of various Surface drivers to the current year.
+
+Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
+Patchset: surface-sam
+---
+ drivers/platform/surface/aggregator/Kconfig | 2 +-
+ drivers/platform/surface/aggregator/Makefile | 2 +-
+ drivers/platform/surface/aggregator/bus.c | 2 +-
+ drivers/platform/surface/aggregator/bus.h | 2 +-
+ drivers/platform/surface/aggregator/controller.c | 2 +-
+ drivers/platform/surface/aggregator/controller.h | 2 +-
+ drivers/platform/surface/aggregator/core.c | 2 +-
+ drivers/platform/surface/aggregator/ssh_msgb.h | 2 +-
+ drivers/platform/surface/aggregator/ssh_packet_layer.c | 2 +-
+ drivers/platform/surface/aggregator/ssh_packet_layer.h | 2 +-
+ drivers/platform/surface/aggregator/ssh_parser.c | 2 +-
+ drivers/platform/surface/aggregator/ssh_parser.h | 2 +-
+ drivers/platform/surface/aggregator/ssh_request_layer.c | 2 +-
+ drivers/platform/surface/aggregator/ssh_request_layer.h | 2 +-
+ drivers/platform/surface/aggregator/trace.h | 2 +-
+ drivers/platform/surface/surface_acpi_notify.c | 2 +-
+ drivers/platform/surface/surface_aggregator_cdev.c | 2 +-
+ drivers/platform/surface/surface_aggregator_registry.c | 2 +-
+ drivers/platform/surface/surface_dtx.c | 2 +-
+ drivers/platform/surface/surface_gpe.c | 2 +-
+ drivers/platform/surface/surface_hotplug.c | 2 +-
+ drivers/platform/surface/surface_platform_profile.c | 2 +-
+ 22 files changed, 22 insertions(+), 22 deletions(-)
+
+diff --git a/drivers/platform/surface/aggregator/Kconfig b/drivers/platform/surface/aggregator/Kconfig
+index cab020324256..c114f9dd5fe1 100644
+--- a/drivers/platform/surface/aggregator/Kconfig
++++ b/drivers/platform/surface/aggregator/Kconfig
+@@ -1,5 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0+
+-# Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++# Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+
+ menuconfig SURFACE_AGGREGATOR
+ tristate "Microsoft Surface System Aggregator Module Subsystem and Drivers"
+diff --git a/drivers/platform/surface/aggregator/Makefile b/drivers/platform/surface/aggregator/Makefile
+index c0d550eda5cd..fdf664a217f9 100644
+--- a/drivers/platform/surface/aggregator/Makefile
++++ b/drivers/platform/surface/aggregator/Makefile
+@@ -1,5 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0+
+-# Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++# Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+
+ # For include/trace/define_trace.h to include trace.h
+ CFLAGS_core.o = -I$(src)
+diff --git a/drivers/platform/surface/aggregator/bus.c b/drivers/platform/surface/aggregator/bus.c
+index 4bba60884bb5..96986042a257 100644
+--- a/drivers/platform/surface/aggregator/bus.c
++++ b/drivers/platform/surface/aggregator/bus.c
+@@ -2,7 +2,7 @@
+ /*
+ * Surface System Aggregator Module bus and device integration.
+ *
+- * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #include <linux/device.h>
+diff --git a/drivers/platform/surface/aggregator/bus.h b/drivers/platform/surface/aggregator/bus.h
+index 6964ee84e79c..5b4dbf21906c 100644
+--- a/drivers/platform/surface/aggregator/bus.h
++++ b/drivers/platform/surface/aggregator/bus.h
+@@ -2,7 +2,7 @@
+ /*
+ * Surface System Aggregator Module bus and device integration.
+ *
+- * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #ifndef _SURFACE_AGGREGATOR_BUS_H
+diff --git a/drivers/platform/surface/aggregator/controller.c b/drivers/platform/surface/aggregator/controller.c
+index 6de834b52b63..43e765199137 100644
+--- a/drivers/platform/surface/aggregator/controller.c
++++ b/drivers/platform/surface/aggregator/controller.c
+@@ -2,7 +2,7 @@
+ /*
+ * Main SSAM/SSH controller structure and functionality.
+ *
+- * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #include <linux/acpi.h>
+diff --git a/drivers/platform/surface/aggregator/controller.h b/drivers/platform/surface/aggregator/controller.h
+index a0963c3562ff..f0d987abc51e 100644
+--- a/drivers/platform/surface/aggregator/controller.h
++++ b/drivers/platform/surface/aggregator/controller.h
+@@ -2,7 +2,7 @@
+ /*
+ * Main SSAM/SSH controller structure and functionality.
+ *
+- * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #ifndef _SURFACE_AGGREGATOR_CONTROLLER_H
+diff --git a/drivers/platform/surface/aggregator/core.c b/drivers/platform/surface/aggregator/core.c
+index a62c5dfe42d6..1a6373dea109 100644
+--- a/drivers/platform/surface/aggregator/core.c
++++ b/drivers/platform/surface/aggregator/core.c
+@@ -7,7 +7,7 @@
+ * Handles communication via requests as well as enabling, disabling, and
+ * relaying of events.
+ *
+- * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #include <linux/acpi.h>
+diff --git a/drivers/platform/surface/aggregator/ssh_msgb.h b/drivers/platform/surface/aggregator/ssh_msgb.h
+index e562958ffdf0..f3ecad92eefd 100644
+--- a/drivers/platform/surface/aggregator/ssh_msgb.h
++++ b/drivers/platform/surface/aggregator/ssh_msgb.h
+@@ -2,7 +2,7 @@
+ /*
+ * SSH message builder functions.
+ *
+- * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #ifndef _SURFACE_AGGREGATOR_SSH_MSGB_H
+diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.c b/drivers/platform/surface/aggregator/ssh_packet_layer.c
+index 8a4451c1ffe5..6748fe4ac5d5 100644
+--- a/drivers/platform/surface/aggregator/ssh_packet_layer.c
++++ b/drivers/platform/surface/aggregator/ssh_packet_layer.c
+@@ -2,7 +2,7 @@
+ /*
+ * SSH packet transport layer.
+ *
+- * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #include <asm/unaligned.h>
+diff --git a/drivers/platform/surface/aggregator/ssh_packet_layer.h b/drivers/platform/surface/aggregator/ssh_packet_layer.h
+index 2eb329f0b91a..64633522f971 100644
+--- a/drivers/platform/surface/aggregator/ssh_packet_layer.h
++++ b/drivers/platform/surface/aggregator/ssh_packet_layer.h
+@@ -2,7 +2,7 @@
+ /*
+ * SSH packet transport layer.
+ *
+- * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #ifndef _SURFACE_AGGREGATOR_SSH_PACKET_LAYER_H
+diff --git a/drivers/platform/surface/aggregator/ssh_parser.c b/drivers/platform/surface/aggregator/ssh_parser.c
+index b77912f8f13b..a6f668694365 100644
+--- a/drivers/platform/surface/aggregator/ssh_parser.c
++++ b/drivers/platform/surface/aggregator/ssh_parser.c
+@@ -2,7 +2,7 @@
+ /*
+ * SSH message parser.
+ *
+- * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #include <asm/unaligned.h>
+diff --git a/drivers/platform/surface/aggregator/ssh_parser.h b/drivers/platform/surface/aggregator/ssh_parser.h
+index 3bd6e180fd16..801d8fa69fb5 100644
+--- a/drivers/platform/surface/aggregator/ssh_parser.h
++++ b/drivers/platform/surface/aggregator/ssh_parser.h
+@@ -2,7 +2,7 @@
+ /*
+ * SSH message parser.
+ *
+- * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #ifndef _SURFACE_AGGREGATOR_SSH_PARSER_H
+diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.c b/drivers/platform/surface/aggregator/ssh_request_layer.c
+index 790f7f0eee98..f5565570f16c 100644
+--- a/drivers/platform/surface/aggregator/ssh_request_layer.c
++++ b/drivers/platform/surface/aggregator/ssh_request_layer.c
+@@ -2,7 +2,7 @@
+ /*
+ * SSH request transport layer.
+ *
+- * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #include <asm/unaligned.h>
+diff --git a/drivers/platform/surface/aggregator/ssh_request_layer.h b/drivers/platform/surface/aggregator/ssh_request_layer.h
+index 9c3cbae2d4bd..4e387a031351 100644
+--- a/drivers/platform/surface/aggregator/ssh_request_layer.h
++++ b/drivers/platform/surface/aggregator/ssh_request_layer.h
+@@ -2,7 +2,7 @@
+ /*
+ * SSH request transport layer.
+ *
+- * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #ifndef _SURFACE_AGGREGATOR_SSH_REQUEST_LAYER_H
+diff --git a/drivers/platform/surface/aggregator/trace.h b/drivers/platform/surface/aggregator/trace.h
+index de64cf169060..7be0bb097dea 100644
+--- a/drivers/platform/surface/aggregator/trace.h
++++ b/drivers/platform/surface/aggregator/trace.h
+@@ -2,7 +2,7 @@
+ /*
+ * Trace points for SSAM/SSH.
+ *
+- * Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #undef TRACE_SYSTEM
+diff --git a/drivers/platform/surface/surface_acpi_notify.c b/drivers/platform/surface/surface_acpi_notify.c
+index 8339988d95c1..acc958b43b57 100644
+--- a/drivers/platform/surface/surface_acpi_notify.c
++++ b/drivers/platform/surface/surface_acpi_notify.c
+@@ -8,7 +8,7 @@
+ * notifications sent from ACPI via the SAN interface by providing them to any
+ * registered external driver.
+ *
+- * Copyright (C) 2019-2020 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #include <asm/unaligned.h>
+diff --git a/drivers/platform/surface/surface_aggregator_cdev.c b/drivers/platform/surface/surface_aggregator_cdev.c
+index 30fb50fde450..492c82e69182 100644
+--- a/drivers/platform/surface/surface_aggregator_cdev.c
++++ b/drivers/platform/surface/surface_aggregator_cdev.c
+@@ -3,7 +3,7 @@
+ * Provides user-space access to the SSAM EC via the /dev/surface/aggregator
+ * misc device. Intended for debugging and development.
+ *
+- * Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #include <linux/fs.h>
+diff --git a/drivers/platform/surface/surface_aggregator_registry.c b/drivers/platform/surface/surface_aggregator_registry.c
+index cee7121e7fa6..3f81db28a702 100644
+--- a/drivers/platform/surface/surface_aggregator_registry.c
++++ b/drivers/platform/surface/surface_aggregator_registry.c
+@@ -6,7 +6,7 @@
+ * cannot be auto-detected. Provides device-hubs and performs instantiation
+ * for these devices.
+ *
+- * Copyright (C) 2020-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #include <linux/acpi.h>
+diff --git a/drivers/platform/surface/surface_dtx.c b/drivers/platform/surface/surface_dtx.c
+index 1203b9a82993..ed36944467f9 100644
+--- a/drivers/platform/surface/surface_dtx.c
++++ b/drivers/platform/surface/surface_dtx.c
+@@ -8,7 +8,7 @@
+ * acknowledge (to speed things up), abort (e.g. in case the dGPU is still in
+ * use), or request detachment via user-space.
+ *
+- * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #include <linux/fs.h>
+diff --git a/drivers/platform/surface/surface_gpe.c b/drivers/platform/surface/surface_gpe.c
+index c1775db29efb..b7e48ba100b6 100644
+--- a/drivers/platform/surface/surface_gpe.c
++++ b/drivers/platform/surface/surface_gpe.c
+@@ -4,7 +4,7 @@
+ * properly configuring the respective GPEs. Required for wakeup via lid on
+ * newer Intel-based Microsoft Surface devices.
+ *
+- * Copyright (C) 2020 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2020-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+diff --git a/drivers/platform/surface/surface_hotplug.c b/drivers/platform/surface/surface_hotplug.c
+index cfcc15cfbacb..f004a2495201 100644
+--- a/drivers/platform/surface/surface_hotplug.c
++++ b/drivers/platform/surface/surface_hotplug.c
+@@ -10,7 +10,7 @@
+ * Event signaling is handled via ACPI, which will generate the appropriate
+ * device-check notifications to be picked up by the PCIe hot-plug driver.
+ *
+- * Copyright (C) 2019-2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2019-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #include <linux/acpi.h>
+diff --git a/drivers/platform/surface/surface_platform_profile.c b/drivers/platform/surface/surface_platform_profile.c
+index 6373d3b5eb7f..fbf2e11fd6ce 100644
+--- a/drivers/platform/surface/surface_platform_profile.c
++++ b/drivers/platform/surface/surface_platform_profile.c
+@@ -3,7 +3,7 @@
+ * Surface Platform Profile / Performance Mode driver for Surface System
+ * Aggregator Module (thermal subsystem).
+ *
+- * Copyright (C) 2021 Maximilian Luz <luzmaximilian@gmail.com>
++ * Copyright (C) 2021-2022 Maximilian Luz <luzmaximilian@gmail.com>
+ */
+
+ #include <asm/unaligned.h>
+--
+2.36.1
+
+From 25d1faa2928596cc4902653225e57741688730a4 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
@@ -4239,9 +5986,9 @@ index 85ed4c1d4924..942c1c9a4ea5 100644
dev_warn(&adapter->dev, "protocol 0x%02x not supported for client 0x%02x\n",
accessor_type, client->addr);
--
-2.36.0
+2.36.1
-From 704aa16555465b0f83471aa84c3a5be3c7133d67 Mon Sep 17 00:00:00 2001
+From 2ec19064dafe6c2150f2fab606ad38fcfdc757d0 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 13 Feb 2021 16:41:18 +0100
Subject: [PATCH] platform/surface: Add driver for Surface Book 1 dGPU switch
@@ -4264,10 +6011,10 @@ Patchset: surface-sam-over-hid
create mode 100644 drivers/platform/surface/surfacebook1_dgpu_switch.c
diff --git a/drivers/platform/surface/Kconfig b/drivers/platform/surface/Kconfig
-index 9c228090c35b..c6c3c9bd3b57 100644
+index c685ec440535..3d3659b87ba4 100644
--- a/drivers/platform/surface/Kconfig
+++ b/drivers/platform/surface/Kconfig
-@@ -106,6 +106,13 @@ config SURFACE_AGGREGATOR_REGISTRY
+@@ -133,6 +133,13 @@ config SURFACE_AGGREGATOR_REGISTRY
the respective client devices. Drivers for these devices still need to
be selected via the other options.
@@ -4282,12 +6029,12 @@ index 9c228090c35b..c6c3c9bd3b57 100644
tristate "Surface DTX (Detachment System) Driver"
depends on SURFACE_AGGREGATOR
diff --git a/drivers/platform/surface/Makefile b/drivers/platform/surface/Makefile
-index 6d9291c993c4..9eb3a7e6382c 100644
+index fccd33e6780d..20408730f425 100644
--- a/drivers/platform/surface/Makefile
+++ b/drivers/platform/surface/Makefile
-@@ -11,6 +11,7 @@ obj-$(CONFIG_SURFACE_ACPI_NOTIFY) += surface_acpi_notify.o
- obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/
+@@ -12,6 +12,7 @@ obj-$(CONFIG_SURFACE_AGGREGATOR) += aggregator/
obj-$(CONFIG_SURFACE_AGGREGATOR_CDEV) += surface_aggregator_cdev.o
+ obj-$(CONFIG_SURFACE_AGGREGATOR_HUB) += surface_aggregator_hub.o
obj-$(CONFIG_SURFACE_AGGREGATOR_REGISTRY) += surface_aggregator_registry.o
+obj-$(CONFIG_SURFACE_BOOK1_DGPU_SWITCH) += surfacebook1_dgpu_switch.o
obj-$(CONFIG_SURFACE_DTX) += surface_dtx.o
@@ -4462,46 +6209,9 @@ index 000000000000..8b816ed8f35c
+MODULE_DESCRIPTION("Discrete GPU Power-Switch for Surface Book 1");
+MODULE_LICENSE("GPL");
--
-2.36.0
-
-From 5a6d26ae3ff1334f0540aef76b28c596ebb67d81 Mon Sep 17 00:00:00 2001
-From: Maximilian Luz <luzmaximilian@gmail.com>
-Date: Wed, 27 Oct 2021 00:56:11 +0200
-Subject: [PATCH] platform/surface: gpe: Add support for Surface Pro 8
-
-The new Surface Pro 8 uses GPEs for lid events as well. Add an entry for
-that so that the lid can be used to wake the device. Note that this is a
-device with a keyboard type cover, where this acts as the "lid".
-
-Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
-Patchset: surface-gpe
----
- drivers/platform/surface/surface_gpe.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
-
-diff --git a/drivers/platform/surface/surface_gpe.c b/drivers/platform/surface/surface_gpe.c
-index c1775db29efb..ec66fde28e75 100644
---- a/drivers/platform/surface/surface_gpe.c
-+++ b/drivers/platform/surface/surface_gpe.c
-@@ -99,6 +99,14 @@ static const struct dmi_system_id dmi_lid_device_table[] = {
- },
- .driver_data = (void *)lid_device_props_l4D,
- },
-+ {
-+ .ident = "Surface Pro 8",
-+ .matches = {
-+ DMI_EXACT_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
-+ DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "Surface Pro 8"),
-+ },
-+ .driver_data = (void *)lid_device_props_l4B,
-+ },
- {
- .ident = "Surface Book 1",
- .matches = {
---
-2.36.0
+2.36.1
-From 8944aec8973646c474c14bd6763adee38f0430a3 Mon Sep 17 00:00:00 2001
+From 0e6a0910bdec9c3b4d9658207c7b2cde6d86d375 Mon Sep 17 00:00:00 2001
From: Sachi King <nakato@nakato.io>
Date: Tue, 5 Oct 2021 00:05:09 +1100
Subject: [PATCH] Input: soc_button_array - support AMD variant Surface devices
@@ -4576,9 +6286,9 @@ index cb6ec59a045d..4e8944f59def 100644
/*
--
-2.36.0
+2.36.1
-From 421af81b0297af32e058cd79dcf3073eb3cf51fa Mon Sep 17 00:00:00 2001
+From 6224cf2d064ad98e8aa6153be11cbee3fc760cdc Mon Sep 17 00:00:00 2001
From: Sachi King <nakato@nakato.io>
Date: Tue, 5 Oct 2021 00:22:57 +1100
Subject: [PATCH] platform/surface: surfacepro3_button: don't load on amd
@@ -4648,9 +6358,9 @@ index 242fb690dcaf..30eea54dbb47 100644
--
-2.36.0
+2.36.1
-From 734da7d8f5beb9be996ba99a80f7e603b72130ab Mon Sep 17 00:00:00 2001
+From a8a665d668c8b626813a8fefe5c2be602fdabf31 Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 24 Feb 2022 12:02:40 +0100
Subject: [PATCH] Input: soc_button_array - add support for Microsoft Surface 3
@@ -4751,9 +6461,9 @@ index 4e8944f59def..f044c731c6a9 100644
{ }
--
-2.36.0
+2.36.1
-From 33b3e3c489a43b4c71d5886e10af33473a939ca9 Mon Sep 17 00:00:00 2001
+From 0e038f31633b889e5c4bd8b888fac74a69ac3b0f Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Thu, 24 Feb 2022 12:02:41 +0100
Subject: [PATCH] platform/surface: Remove Surface 3 Button driver
@@ -4774,7 +6484,7 @@ Patchset: surface-button
delete mode 100644 drivers/platform/surface/surface3_button.c
diff --git a/drivers/platform/surface/Kconfig b/drivers/platform/surface/Kconfig
-index c6c3c9bd3b57..df387ac34a79 100644
+index 3d3659b87ba4..126f940ee95a 100644
--- a/drivers/platform/surface/Kconfig
+++ b/drivers/platform/surface/Kconfig
@@ -28,13 +28,6 @@ config SURFACE3_WMI
@@ -4792,7 +6502,7 @@ index c6c3c9bd3b57..df387ac34a79 100644
tristate "Surface 3 battery platform operation region support"
depends on ACPI
diff --git a/drivers/platform/surface/Makefile b/drivers/platform/surface/Makefile
-index 9eb3a7e6382c..e4791b47f561 100644
+index 20408730f425..ea407549286c 100644
--- a/drivers/platform/surface/Makefile
+++ b/drivers/platform/surface/Makefile
@@ -5,7 +5,6 @@
@@ -5057,9 +6767,9 @@ index 48d77e7aae76..000000000000
-MODULE_DESCRIPTION("surface3 button array driver");
-MODULE_LICENSE("GPL v2");
--
-2.36.0
+2.36.1
-From 6854ba2ebc5761be240d5fd1d57555011f307f2c Mon Sep 17 00:00:00 2001
+From f5d22c97a860e9002ad31c8bf1c00b629c432ba7 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= <verdre@v0yd.nl>
Date: Thu, 5 Nov 2020 13:09:45 +0100
Subject: [PATCH] hid/multitouch: Turn off Type Cover keyboard backlight when
@@ -5290,67 +7000,440 @@ index 99eabfb4145b..bbfcae39f375 100644
{ .driver_data = MT_CLS_GOOGLE,
HID_DEVICE(HID_BUS_ANY, HID_GROUP_ANY, USB_VENDOR_ID_GOOGLE,
--
-2.36.0
-
-From 48eab1c5e0d9fe67384d6c2e91efdf0ec3ff54b5 Mon Sep 17 00:00:00 2001
-From: Maximilian Luz <luzmaximilian@gmail.com>
-Date: Tue, 8 Feb 2022 01:29:48 +0100
-Subject: [PATCH] ACPI: battery: Add "Not Charging" quirk for Microsoft Surface
- devices
-
-Microsoft Surface devices have a limiter that sets a fixed maximum
-charge capacity for the battery. When that maximum capacity has been
-reached, charging stops. In that case, _BST returns a battery state
-field with both "charging" and "discharging" bits cleared. The battery
-driver, however, returns "unknown" as status.
+2.36.1
+
+From f8ac6cc2a4f1f3020b1bcb476dc355a0e3d938ce Mon Sep 17 00:00:00 2001
+From: PJungkamp <p.jungkamp@gmail.com>
+Date: Fri, 25 Feb 2022 12:04:25 +0100
+Subject: [PATCH] hid/multitouch: Add support for surface pro type cover tablet
+ switch
+
+The Surface Pro Type Cover has several non standard HID usages in it's
+hid report descriptor.
+I noticed that, upon folding the typecover back, a vendor specific range
+of 4 32 bit integer hid usages is transmitted.
+Only the first byte of the message seems to convey reliable information
+about the keyboard state.
+
+0x22 => Normal (keys enabled)
+0x33 => Folded back (keys disabled)
+0x53 => Rotated left/right side up (keys disabled)
+0x13 => Cover closed (keys disabled)
+0x43 => Folded back and Tablet upside down (keys disabled)
+This list may not be exhaustive.
+
+The tablet mode switch will be disabled for a value of 0x22 and enabled
+on any other value.
-This seems to be the same behavior as observed on the ThinkPads, so
-let's use the same quirk to handle that as well.
+Patchset: surface-typecover
+---
+ drivers/hid/hid-multitouch.c | 148 +++++++++++++++++++++++++++++------
+ 1 file changed, 122 insertions(+), 26 deletions(-)
-Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
+diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
+index bbfcae39f375..d53228452501 100644
+--- a/drivers/hid/hid-multitouch.c
++++ b/drivers/hid/hid-multitouch.c
+@@ -76,6 +76,7 @@ MODULE_LICENSE("GPL");
+ #define MT_QUIRK_FORCE_MULTI_INPUT BIT(20)
+ #define MT_QUIRK_DISABLE_WAKEUP BIT(21)
+ #define MT_QUIRK_HAS_TYPE_COVER_BACKLIGHT BIT(22)
++#define MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH BIT(23)
+
+ #define MT_INPUTMODE_TOUCHSCREEN 0x02
+ #define MT_INPUTMODE_TOUCHPAD 0x03
+@@ -83,6 +84,8 @@ MODULE_LICENSE("GPL");
+ #define MT_BUTTONTYPE_CLICKPAD 0
+
+ #define MS_TYPE_COVER_FEATURE_REPORT_USAGE 0xff050086
++#define MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE 0xff050072
++#define MS_TYPE_COVER_APPLICATION 0xff050050
+
+ enum latency_mode {
+ HID_LATENCY_NORMAL = 0,
+@@ -398,6 +401,7 @@ static const struct mt_class mt_classes[] = {
+ },
+ { .name = MT_CLS_WIN_8_MS_SURFACE_TYPE_COVER,
+ .quirks = MT_QUIRK_HAS_TYPE_COVER_BACKLIGHT |
++ MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH |
+ MT_QUIRK_ALWAYS_VALID |
+ MT_QUIRK_IGNORE_DUPLICATES |
+ MT_QUIRK_HOVERING |
+@@ -1357,6 +1361,9 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ field->application != HID_CP_CONSUMER_CONTROL &&
+ field->application != HID_GD_WIRELESS_RADIO_CTLS &&
+ field->application != HID_GD_SYSTEM_MULTIAXIS &&
++ !(field->application == MS_TYPE_COVER_APPLICATION &&
++ application->quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH &&
++ usage->hid == MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE) &&
+ !(field->application == HID_VD_ASUS_CUSTOM_MEDIA_KEYS &&
+ application->quirks & MT_QUIRK_ASUS_CUSTOM_UP))
+ return -1;
+@@ -1384,6 +1391,21 @@ static int mt_input_mapping(struct hid_device *hdev, struct hid_input *hi,
+ return 1;
+ }
+
++ /*
++ * The Microsoft Surface Pro Typecover has a non-standard HID
++ * tablet mode switch on a vendor specific usage page with vendor
++ * specific usage.
++ */
++ if (field->application == MS_TYPE_COVER_APPLICATION &&
++ application->quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH &&
++ usage->hid == MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE) {
++ usage->type = EV_SW;
++ usage->code = SW_TABLET_MODE;
++ *max = SW_MAX;
++ *bit = hi->input->swbit;
++ return 1;
++ }
++
+ if (rdata->is_mt_collection)
+ return mt_touch_input_mapping(hdev, hi, field, usage, bit, max,
+ application);
+@@ -1405,6 +1427,7 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ {
+ struct mt_device *td = hid_get_drvdata(hdev);
+ struct mt_report_data *rdata;
++ struct input_dev *input;
+
+ rdata = mt_find_report_data(td, field->report);
+ if (rdata && rdata->is_mt_collection) {
+@@ -1412,6 +1435,19 @@ static int mt_input_mapped(struct hid_device *hdev, struct hid_input *hi,
+ return -1;
+ }
+
++ /*
++ * We own an input device which acts as a tablet mode switch for
++ * the Surface Pro Typecover.
++ */
++ if (field->application == MS_TYPE_COVER_APPLICATION &&
++ rdata->application->quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH &&
++ usage->hid == MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE) {
++ input = hi->input;
++ input_set_capability(input, EV_SW, SW_TABLET_MODE);
++ input_report_switch(input, SW_TABLET_MODE, 0);
++ return -1;
++ }
++
+ /* let hid-core decide for the others */
+ return 0;
+ }
+@@ -1421,11 +1457,21 @@ static int mt_event(struct hid_device *hid, struct hid_field *field,
+ {
+ struct mt_device *td = hid_get_drvdata(hid);
+ struct mt_report_data *rdata;
++ struct input_dev *input;
+
+ rdata = mt_find_report_data(td, field->report);
+ if (rdata && rdata->is_mt_collection)
+ return mt_touch_event(hid, field, usage, value);
+
++ if (field->application == MS_TYPE_COVER_APPLICATION &&
++ rdata->application->quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH &&
++ usage->hid == MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE) {
++ input = field->hidinput->input;
++ input_report_switch(input, SW_TABLET_MODE, (value & 0xFF) != 0x22);
++ input_sync(input);
++ return 1;
++ }
++
+ return 0;
+ }
+
+@@ -1578,6 +1624,42 @@ static void mt_post_parse(struct mt_device *td, struct mt_application *app)
+ app->quirks &= ~MT_QUIRK_CONTACT_CNT_ACCURATE;
+ }
+
++static int get_type_cover_field(struct hid_report_enum *rep_enum,
++ struct hid_field **field, int usage)
++{
++ struct hid_report *rep;
++ struct hid_field *cur_field;
++ int i, j;
++
++ list_for_each_entry(rep, &rep_enum->report_list, list) {
++ for (i = 0; i < rep->maxfield; i++) {
++ cur_field = rep->field[i];
++ if (cur_field->application != MS_TYPE_COVER_APPLICATION)
++ continue;
++ for (j = 0; j < cur_field->maxusage; j++) {
++ if (cur_field->usage[j].hid == usage) {
++ *field = cur_field;
++ return true;
++ }
++ }
++ }
++ }
++ return false;
++}
++
++static void request_type_cover_tablet_mode_switch(struct hid_device *hdev)
++{
++ struct hid_field *field;
++
++ if (get_type_cover_field(&hdev->report_enum[HID_INPUT_REPORT],
++ &field,
++ MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE)) {
++ hid_hw_request(hdev, field->report, HID_REQ_GET_REPORT);
++ } else {
++ hid_err(hdev, "couldn't find tablet mode field\n");
++ }
++}
++
+ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
+ {
+ struct mt_device *td = hid_get_drvdata(hdev);
+@@ -1627,6 +1709,13 @@ static int mt_input_configured(struct hid_device *hdev, struct hid_input *hi)
+ /* force BTN_STYLUS to allow tablet matching in udev */
+ __set_bit(BTN_STYLUS, hi->input->keybit);
+ break;
++ case MS_TYPE_COVER_APPLICATION:
++ if (td->mtclass.quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH) {
++ suffix = "Tablet Mode Switch";
++ request_type_cover_tablet_mode_switch(hdev);
++ break;
++ }
++ fallthrough;
+ default:
+ suffix = "UNKNOWN";
+ break;
+@@ -1715,30 +1804,6 @@ static void mt_expired_timeout(struct timer_list *t)
+ clear_bit(MT_IO_FLAGS_RUNNING, &td->mt_io_flags);
+ }
+
+-static void get_type_cover_backlight_field(struct hid_device *hdev,
+- struct hid_field **field)
+-{
+- struct hid_report_enum *rep_enum;
+- struct hid_report *rep;
+- struct hid_field *cur_field;
+- int i, j;
+-
+- rep_enum = &hdev->report_enum[HID_FEATURE_REPORT];
+- list_for_each_entry(rep, &rep_enum->report_list, list) {
+- for (i = 0; i < rep->maxfield; i++) {
+- cur_field = rep->field[i];
+-
+- for (j = 0; j < cur_field->maxusage; j++) {
+- if (cur_field->usage[j].hid
+- == MS_TYPE_COVER_FEATURE_REPORT_USAGE) {
+- *field = cur_field;
+- return;
+- }
+- }
+- }
+- }
+-}
+-
+ static void update_keyboard_backlight(struct hid_device *hdev, bool enabled)
+ {
+ struct usb_device *udev = hid_to_usb_dev(hdev);
+@@ -1747,8 +1812,9 @@ static void update_keyboard_backlight(struct hid_device *hdev, bool enabled)
+ /* Wake up the device in case it's already suspended */
+ pm_runtime_get_sync(&udev->dev);
+
+- get_type_cover_backlight_field(hdev, &field);
+- if (!field) {
++ if (!get_type_cover_field(&hdev->report_enum[HID_FEATURE_REPORT],
++ &field,
++ MS_TYPE_COVER_FEATURE_REPORT_USAGE)) {
+ hid_err(hdev, "couldn't find backlight field\n");
+ goto out;
+ }
+@@ -1874,13 +1940,24 @@ static int mt_suspend(struct hid_device *hdev, pm_message_t state)
+
+ static int mt_reset_resume(struct hid_device *hdev)
+ {
++ struct mt_device *td = hid_get_drvdata(hdev);
++
+ mt_release_contacts(hdev);
+ mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
++
++ /* Request an update on the typecover folding state on resume
++ * after reset.
++ */
++ if (td->mtclass.quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH)
++ request_type_cover_tablet_mode_switch(hdev);
++
+ return 0;
+ }
+
+ static int mt_resume(struct hid_device *hdev)
+ {
++ struct mt_device *td = hid_get_drvdata(hdev);
++
+ /* Some Elan legacy devices require SET_IDLE to be set on resume.
+ * It should be safe to send it to other devices too.
+ * Tested on 3M, Stantum, Cypress, Zytronic, eGalax, and Elan panels. */
+@@ -1889,6 +1966,10 @@ static int mt_resume(struct hid_device *hdev)
+
+ mt_set_modes(hdev, HID_LATENCY_NORMAL, true, true);
+
++ /* Request an update on the typecover folding state on resume. */
++ if (td->mtclass.quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH)
++ request_type_cover_tablet_mode_switch(hdev);
++
+ return 0;
+ }
+ #endif
+@@ -1896,6 +1977,21 @@ static int mt_resume(struct hid_device *hdev)
+ static void mt_remove(struct hid_device *hdev)
+ {
+ struct mt_device *td = hid_get_drvdata(hdev);
++ struct hid_field *field;
++ struct input_dev *input;
++
++ /* Reset tablet mode switch on disconnect. */
++ if (td->mtclass.quirks & MT_QUIRK_HAS_TYPE_COVER_TABLET_MODE_SWITCH) {
++ if (get_type_cover_field(&hdev->report_enum[HID_INPUT_REPORT],
++ &field,
++ MS_TYPE_COVER_TABLET_MODE_SWITCH_USAGE)) {
++ input = field->hidinput->input;
++ input_report_switch(input, SW_TABLET_MODE, 0);
++ input_sync(input);
++ } else {
++ hid_err(hdev, "couldn't find tablet mode field\n");
++ }
++ }
+
+ unregister_pm_notifier(&td->pm_notifier);
+ del_timer_sync(&td->release_timer);
+--
+2.36.1
+
+From 93fa65ace198e7abaa1a27e42f3ebcf509022902 Mon Sep 17 00:00:00 2001
+From: Werner Sembach <wse@tuxedocomputers.com>
+Date: Wed, 27 Apr 2022 17:40:53 +0200
+Subject: [PATCH] ACPI: battery: Make "not-charging" the default on no charging
+ or full info
+
+When the battery is neither charging or discharging and is not full,
+"not-charging" is a useful status description for the case in general.
+Currently this state is set as "unknown" by default, expect when this is
+explicitly replaced with "not-charging" on a per device or per vendor
+basis.
+
+A lot of devices have this state without a BIOS specification available
+explicitly describing it. e.g. some current Clevo barebones have a BIOS
+setting to stop charging at a user defined battery level.
+
+Signed-off-by: Werner Sembach <wse@tuxedocomputers.com>
+Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Patchset: surface-battery
-
----
-For what it's worth, I don't think the ACPI spec explicitly states that
-any of the status bits need to be set, or that there are only the
-"charging" and "discharging" states. As far as I can tell, ACPI only
-states:
-
- Notice that the Charging bit and the Discharging bit are mutually
- exclusive and must not both be set at the same time. Even in
- critical state, hardware should report the corresponding
- charging/discharging state.
-
-But that does not exclude the case that no bit is set. So, strictly
-going by spec, I don't think it's necessary to put all of this behind a
-quirk.
---
- drivers/acpi/battery.c | 8 ++++++++
- 1 file changed, 8 insertions(+)
+ drivers/acpi/battery.c | 24 +-----------------------
+ 1 file changed, 1 insertion(+), 23 deletions(-)
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
-index dc208f5f5a1f..db2aa56c746a 100644
+index dc208f5f5a1f..306513fec1e1 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
-@@ -1152,6 +1152,14 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = {
- DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"),
+@@ -52,7 +52,6 @@ static bool battery_driver_registered;
+ static int battery_bix_broken_package;
+ static int battery_notification_delay_ms;
+ static int battery_ac_is_broken;
+-static int battery_quirk_notcharging;
+ static unsigned int cache_time = 1000;
+ module_param(cache_time, uint, 0644);
+ MODULE_PARM_DESC(cache_time, "cache time in milliseconds");
+@@ -216,10 +215,8 @@ static int acpi_battery_get_property(struct power_supply *psy,
+ val->intval = POWER_SUPPLY_STATUS_CHARGING;
+ else if (acpi_battery_is_charged(battery))
+ val->intval = POWER_SUPPLY_STATUS_FULL;
+- else if (battery_quirk_notcharging)
+- val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ else
+- val->intval = POWER_SUPPLY_STATUS_UNKNOWN;
++ val->intval = POWER_SUPPLY_STATUS_NOT_CHARGING;
+ break;
+ case POWER_SUPPLY_PROP_PRESENT:
+ val->intval = acpi_battery_present(battery);
+@@ -1105,12 +1102,6 @@ battery_ac_is_broken_quirk(const struct dmi_system_id *d)
+ return 0;
+ }
+
+-static int __init battery_quirk_not_charging(const struct dmi_system_id *d)
+-{
+- battery_quirk_notcharging = 1;
+- return 0;
+-}
+-
+ static const struct dmi_system_id bat_dmi_table[] __initconst = {
+ {
+ /* NEC LZ750/LS */
+@@ -1139,19 +1130,6 @@ static const struct dmi_system_id bat_dmi_table[] __initconst = {
+ DMI_MATCH(DMI_BIOS_DATE, "08/22/2014"),
},
},
-+ {
-+ .callback = battery_quirk_not_charging,
-+ .ident = "Microsoft Surface",
-+ .matches = {
-+ DMI_MATCH(DMI_SYS_VENDOR, "Microsoft Corporation"),
-+ DMI_MATCH(DMI_PRODUCT_NAME, "Surface"),
-+ },
-+ },
+- {
+- /*
+- * On Lenovo ThinkPads the BIOS specification defines
+- * a state when the bits for charging and discharging
+- * are both set to 0. That state is "Not Charging".
+- */
+- .callback = battery_quirk_not_charging,
+- .ident = "Lenovo ThinkPad",
+- .matches = {
+- DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"),
+- DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad"),
+- },
+- },
{
/* Microsoft Surface Go 3 */
.callback = battery_notification_delay_quirk,
--
-2.36.0
+2.36.1
+
+From a29f2ab8670becc07a56ccdfe3a7a1fe64730803 Mon Sep 17 00:00:00 2001
+From: Maximilian Luz <luzmaximilian@gmail.com>
+Date: Wed, 25 May 2022 14:20:10 +0200
+Subject: [PATCH] HID: hid-input: add Surface Go battery quirk
+
+Similar to the Surface Go (1), the (Elantech) touchscreen/digitizer in
+the Surface Go 2 mistakenly reports the battery of the stylus. Instead
+of over the touchsreen device, battery information is provided via
+bluetooth and the touchscreen device reports an empty battery.
+
+Apply the HID_BATTERY_QUIRK_IGNORE quirk to to ignore this battery and
+prevent the erroneous low battery warnings.
+
+Signed-off-by: Maximilian Luz <luzmaximilian@gmail.com>
+Patchset: surface-battery
+---
+ drivers/hid/hid-ids.h | 1 +
+ drivers/hid/hid-input.c | 2 ++
+ 2 files changed, 3 insertions(+)
+
+diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h
+index 78bd3ddda442..288766674c6a 100644
+--- a/drivers/hid/hid-ids.h
++++ b/drivers/hid/hid-ids.h
+@@ -405,6 +405,7 @@
+ #define USB_DEVICE_ID_ASUS_UX550VE_TOUCHSCREEN 0x2544
+ #define USB_DEVICE_ID_ASUS_UX550_TOUCHSCREEN 0x2706
+ #define I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN 0x261A
++#define I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN 0x2A1C
+
+ #define USB_VENDOR_ID_ELECOM 0x056e
+ #define USB_DEVICE_ID_ELECOM_BM084 0x0061
+diff --git a/drivers/hid/hid-input.c b/drivers/hid/hid-input.c
+index 56ec27398a00..263a977801bf 100644
+--- a/drivers/hid/hid-input.c
++++ b/drivers/hid/hid-input.c
+@@ -336,6 +336,8 @@ static const struct hid_device_id hid_battery_quirks[] = {
+ HID_BATTERY_QUIRK_IGNORE },
+ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO_TOUCHSCREEN),
+ HID_BATTERY_QUIRK_IGNORE },
++ { HID_I2C_DEVICE(USB_VENDOR_ID_ELAN, I2C_DEVICE_ID_SURFACE_GO2_TOUCHSCREEN),
++ HID_BATTERY_QUIRK_IGNORE },
+ {}
+ };
+
+--
+2.36.1
-From f31a3ad42c2c04a17f8675438a1b5a6500bafea5 Mon Sep 17 00:00:00 2001
+From bab798deb7e8defbe4a0f5bb02e6254a3261c21c Mon Sep 17 00:00:00 2001
From: Hans de Goede <hdegoede@redhat.com>
Date: Sun, 10 Oct 2021 20:56:57 +0200
Subject: [PATCH] ACPI: delay enumeration of devices with a _DEP pointing to an
@@ -5424,9 +7507,126 @@ index c82b1bfa1c3d..2227625202aa 100644
* Do not enumerate devices with enumeration_by_parent flag set as
* they will be enumerated by their respective parents.
--
-2.36.0
+2.36.1
+
+From afc8f21e4250f6ff57c9385be877943253491d94 Mon Sep 17 00:00:00 2001
+From: zouxiaoh <xiaohong.zou@intel.com>
+Date: Fri, 25 Jun 2021 08:52:59 +0800
+Subject: [PATCH] iommu: intel-ipu: use IOMMU passthrough mode for Intel IPUs
+
+Intel IPU(Image Processing Unit) has its own (IO)MMU hardware,
+The IPU driver allocates its own page table that is not mapped
+via the DMA, and thus the Intel IOMMU driver blocks access giving
+this error: DMAR: DRHD: handling fault status reg 3 DMAR:
+[DMA Read] Request device [00:05.0] PASID ffffffff
+fault addr 76406000 [fault reason 06] PTE Read access is not set
+As IPU is not an external facing device which is not risky, so use
+IOMMU passthrough mode for Intel IPUs.
+
+Change-Id: I6dcccdadac308cf42e20a18e1b593381391e3e6b
+Depends-On: Iacd67578e8c6a9b9ac73285f52b4081b72fb68a6
+Tracked-On: #JIITL8-411
+Signed-off-by: Bingbu Cao <bingbu.cao@intel.com>
+Signed-off-by: zouxiaoh <xiaohong.zou@intel.com>
+Signed-off-by: Xu Chongyang <chongyang.xu@intel.com>
+Patchset: cameras
+---
+ drivers/iommu/intel/iommu.c | 30 ++++++++++++++++++++++++++++++
+ 1 file changed, 30 insertions(+)
+
+diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
+index a91eed82bb39..0d16c6bf0e0b 100644
+--- a/drivers/iommu/intel/iommu.c
++++ b/drivers/iommu/intel/iommu.c
+@@ -57,6 +57,12 @@
+ #define IS_GFX_DEVICE(pdev) ((pdev->class >> 16) == PCI_BASE_CLASS_DISPLAY)
+ #define IS_USB_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_SERIAL_USB)
+ #define IS_ISA_DEVICE(pdev) ((pdev->class >> 8) == PCI_CLASS_BRIDGE_ISA)
++#define IS_INTEL_IPU(pdev) ((pdev)->vendor == PCI_VENDOR_ID_INTEL && \
++ ((pdev)->device == 0x9a19 || \
++ (pdev)->device == 0x9a39 || \
++ (pdev)->device == 0x4e19 || \
++ (pdev)->device == 0x465d || \
++ (pdev)->device == 0x1919))
+ #define IS_IPTS(pdev) ((pdev)->vendor == PCI_VENDOR_ID_INTEL && \
+ ((pdev)->device == 0x9d3e))
+ #define IS_AZALIA(pdev) ((pdev)->vendor == 0x8086 && (pdev)->device == 0x3a3e)
+@@ -335,12 +341,14 @@ EXPORT_SYMBOL_GPL(intel_iommu_enabled);
+
+ static int dmar_map_gfx = 1;
+ static int dmar_map_ipts = 1;
++static int dmar_map_ipu = 1;
+ static int intel_iommu_superpage = 1;
+ static int iommu_identity_mapping;
+ static int iommu_skip_te_disable;
+
+ #define IDENTMAP_GFX 2
+ #define IDENTMAP_AZALIA 4
++#define IDENTMAP_IPU 8
+ #define IDENTMAP_IPTS 16
+
+ int intel_iommu_gfx_mapped;
+@@ -2992,6 +3000,9 @@ static int device_def_domain_type(struct device *dev)
+ if ((iommu_identity_mapping & IDENTMAP_GFX) && IS_GFX_DEVICE(pdev))
+ return IOMMU_DOMAIN_IDENTITY;
+
++ if ((iommu_identity_mapping & IDENTMAP_IPU) && IS_INTEL_IPU(pdev))
++ return IOMMU_DOMAIN_IDENTITY;
++
+ if ((iommu_identity_mapping & IDENTMAP_IPTS) && IS_IPTS(pdev))
+ return IOMMU_DOMAIN_IDENTITY;
+ }
+@@ -3430,6 +3441,9 @@ static int __init init_dmars(void)
+ if (!dmar_map_gfx)
+ iommu_identity_mapping |= IDENTMAP_GFX;
+
++ if (!dmar_map_ipu)
++ iommu_identity_mapping |= IDENTMAP_IPU;
++
+ if (!dmar_map_ipts)
+ iommu_identity_mapping |= IDENTMAP_IPTS;
+
+@@ -5674,6 +5688,18 @@ static void quirk_iommu_igfx(struct pci_dev *dev)
+ dmar_map_gfx = 0;
+ }
+
++static void quirk_iommu_ipu(struct pci_dev *dev)
++{
++ if (!IS_INTEL_IPU(dev))
++ return;
++
++ if (risky_device(dev))
++ return;
++
++ pci_info(dev, "Passthrough IOMMU for integrated Intel IPU\n");
++ dmar_map_ipu = 0;
++}
++
+ static void quirk_iommu_ipts(struct pci_dev *dev)
+ {
+ if (!IS_IPTS(dev))
+@@ -5685,6 +5711,7 @@ static void quirk_iommu_ipts(struct pci_dev *dev)
+ pci_info(dev, "Passthrough IOMMU for IPTS\n");
+ dmar_map_ipts = 0;
+ }
++
+ /* G4x/GM45 integrated gfx dmar support is totally busted. */
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2a40, quirk_iommu_igfx);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x2e00, quirk_iommu_igfx);
+@@ -5720,6 +5747,9 @@ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x1632, quirk_iommu_igfx);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163A, quirk_iommu_igfx);
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x163D, quirk_iommu_igfx);
+
++/* disable IPU dmar support */
++DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_ANY_ID, quirk_iommu_ipu);
++
+ /* disable IPTS dmar support */
+ DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, 0x9D3E, quirk_iommu_ipts);
+
+--
+2.36.1
-From 3f7aa178a14b5cdaa3ca424743299d0c271fd202 Mon Sep 17 00:00:00 2001
+From 997c2b1f0237bc456dc61e869e78a4487bca07d9 Mon Sep 17 00:00:00 2001
From: Daniel Scally <djrscally@gmail.com>
Date: Sun, 10 Oct 2021 20:57:02 +0200
Subject: [PATCH] platform/x86: int3472: Enable I2c daisy chain
@@ -5461,9 +7661,954 @@ index 22f61b47f9e5..e1de1ff40bba 100644
return 0;
--
-2.36.0
+2.36.1
+
+From c3c397ab746342288b4299b452c3ae2fd615be44 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Thu, 28 Oct 2021 21:55:16 +0100
+Subject: [PATCH] media: i2c: Add driver for DW9719 VCM
+
+Add a driver for the DW9719 VCM. The driver creates a v4l2 subdevice
+and registers a control to set the desired focus.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ MAINTAINERS | 7 +
+ drivers/media/i2c/Kconfig | 11 +
+ drivers/media/i2c/Makefile | 1 +
+ drivers/media/i2c/dw9719.c | 427 +++++++++++++++++++++++++++++++++++++
+ 4 files changed, 446 insertions(+)
+ create mode 100644 drivers/media/i2c/dw9719.c
+
+diff --git a/MAINTAINERS b/MAINTAINERS
+index 4d83cd26e299..0e0e1e53e49c 100644
+--- a/MAINTAINERS
++++ b/MAINTAINERS
+@@ -5865,6 +5865,13 @@ T: git git://linuxtv.org/media_tree.git
+ F: Documentation/devicetree/bindings/media/i2c/dongwoon,dw9714.txt
+ F: drivers/media/i2c/dw9714.c
+
++DONGWOON DW9719 LENS VOICE COIL DRIVER
++M: Daniel Scally <djrscally@gmail.com>
++L: linux-media@vger.kernel.org
++S: Maintained
++T: git git://linuxtv.org/media_tree.git
++F: drivers/media/i2c/dw9719.c
++
+ DONGWOON DW9768 LENS VOICE COIL DRIVER
+ M: Dongchun Zhu <dongchun.zhu@mediatek.com>
+ L: linux-media@vger.kernel.org
+diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
+index 69c56e24a612..d9fac304f451 100644
+--- a/drivers/media/i2c/Kconfig
++++ b/drivers/media/i2c/Kconfig
+@@ -1466,6 +1466,17 @@ config VIDEO_DW9714
+ capability. This is designed for linear control of
+ voice coil motors, controlled via I2C serial interface.
+
++config VIDEO_DW9719
++ tristate "DW9719 lens voice coil support"
++ depends on I2C && VIDEO_V4L2
++ select MEDIA_CONTROLLER
++ select VIDEO_V4L2_SUBDEV_API
++ select V4L2_ASYNC
++ help
++ This is a driver for the DW9719 camera lens voice coil.
++ This is designed for linear control of voice coil motors,
++ controlled via I2C serial interface.
++
+ config VIDEO_DW9768
+ tristate "DW9768 lens voice coil support"
+ depends on I2C && VIDEO_V4L2
+diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
+index b01f6cd05ee8..ba8b31d79222 100644
+--- a/drivers/media/i2c/Makefile
++++ b/drivers/media/i2c/Makefile
+@@ -24,6 +24,7 @@ obj-$(CONFIG_VIDEO_SAA6752HS) += saa6752hs.o
+ obj-$(CONFIG_VIDEO_AD5820) += ad5820.o
+ obj-$(CONFIG_VIDEO_AK7375) += ak7375.o
+ obj-$(CONFIG_VIDEO_DW9714) += dw9714.o
++obj-$(CONFIG_VIDEO_DW9719) += dw9719.o
+ obj-$(CONFIG_VIDEO_DW9768) += dw9768.o
+ obj-$(CONFIG_VIDEO_DW9807_VCM) += dw9807-vcm.o
+ obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
+diff --git a/drivers/media/i2c/dw9719.c b/drivers/media/i2c/dw9719.c
+new file mode 100644
+index 000000000000..8451c75b696b
+--- /dev/null
++++ b/drivers/media/i2c/dw9719.c
+@@ -0,0 +1,427 @@
++// SPDX-License-Identifier: GPL-2.0
++// Copyright (c) 2012 Intel Corporation
++
++/*
++ * Based on linux/modules/camera/drivers/media/i2c/imx/dw9719.c in this repo:
++ * https://github.com/ZenfoneArea/android_kernel_asus_zenfone5
++ */
++
++#include <asm/unaligned.h>
++
++#include <linux/delay.h>
++#include <linux/i2c.h>
++#include <linux/pm_runtime.h>
++#include <linux/regulator/consumer.h>
++#include <linux/types.h>
++
++#include <media/v4l2-common.h>
++#include <media/v4l2-ctrls.h>
++#include <media/v4l2-subdev.h>
++
++#define DW9719_MAX_FOCUS_POS 1023
++#define DW9719_CTRL_STEPS 16
++#define DW9719_CTRL_DELAY_US 1000
++#define DELAY_MAX_PER_STEP_NS (1000000 * 1023)
++
++#define DW9719_INFO 0
++#define DW9719_ID 0xF1
++#define DW9719_CONTROL 2
++#define DW9719_VCM_CURRENT 3
++
++#define DW9719_MODE 6
++#define DW9719_VCM_FREQ 7
++
++#define DW9719_MODE_SAC3 0x40
++#define DW9719_DEFAULT_VCM_FREQ 0x60
++#define DW9719_ENABLE_RINGING 0x02
++
++#define NUM_REGULATORS 2
++
++#define to_dw9719_device(x) container_of(x, struct dw9719_device, sd)
++
++struct dw9719_device {
++ struct device *dev;
++ struct i2c_client *client;
++ struct regulator_bulk_data regulators[NUM_REGULATORS];
++ struct v4l2_subdev sd;
++
++ struct dw9719_v4l2_ctrls {
++ struct v4l2_ctrl_handler handler;
++ struct v4l2_ctrl *focus;
++ } ctrls;
++};
++
++static int dw9719_i2c_rd8(struct i2c_client *client, u8 reg, u8 *val)
++{
++ struct i2c_msg msg[2];
++ u8 buf[2] = { reg };
++ int ret;
++
++ msg[0].addr = client->addr;
++ msg[0].flags = 0;
++ msg[0].len = 1;
++ msg[0].buf = buf;
++
++ msg[1].addr = client->addr;
++ msg[1].flags = I2C_M_RD;
++ msg[1].len = 1;
++ msg[1].buf = &buf[1];
++ *val = 0;
++
++ ret = i2c_transfer(client->adapter, msg, 2);
++ if (ret < 0)
++ return ret;
++
++ *val = buf[1];
++
++ return 0;
++}
++
++static int dw9719_i2c_wr8(struct i2c_client *client, u8 reg, u8 val)
++{
++ struct i2c_msg msg;
++ int ret;
++
++ u8 buf[2] = { reg, val };
++
++ msg.addr = client->addr;
++ msg.flags = 0;
++ msg.len = sizeof(buf);
++ msg.buf = buf;
++
++ ret = i2c_transfer(client->adapter, &msg, 1);
++
++ return ret < 0 ? ret : 0;
++}
++
++static int dw9719_i2c_wr16(struct i2c_client *client, u8 reg, u16 val)
++{
++ struct i2c_msg msg;
++ u8 buf[3] = { reg };
++ int ret;
++
++ put_unaligned_be16(val, buf + 1);
++
++ msg.addr = client->addr;
++ msg.flags = 0;
++ msg.len = sizeof(buf);
++ msg.buf = buf;
++
++ ret = i2c_transfer(client->adapter, &msg, 1);
++
++ return ret < 0 ? ret : 0;
++}
++
++static int dw9719_detect(struct dw9719_device *dw9719)
++{
++ int ret;
++ u8 val;
++
++ ret = dw9719_i2c_rd8(dw9719->client, DW9719_INFO, &val);
++ if (ret < 0)
++ return ret;
++
++ if (val != DW9719_ID) {
++ dev_err(dw9719->dev, "Failed to detect correct id\n");
++ ret = -ENXIO;
++ }
++
++ return 0;
++}
++
++static int dw9719_power_down(struct dw9719_device *dw9719)
++{
++ return regulator_bulk_disable(NUM_REGULATORS, dw9719->regulators);
++}
++
++static int dw9719_power_up(struct dw9719_device *dw9719)
++{
++ int ret;
++
++ ret = regulator_bulk_enable(NUM_REGULATORS, dw9719->regulators);
++ if (ret)
++ return ret;
++
++ /* Jiggle SCL pin to wake up device */
++ ret = dw9719_i2c_wr8(dw9719->client, DW9719_CONTROL, 1);
++
++ /* Need 100us to transit from SHUTDOWN to STANDBY*/
++ usleep_range(100, 1000);
++
++ ret = dw9719_i2c_wr8(dw9719->client, DW9719_CONTROL,
++ DW9719_ENABLE_RINGING);
++ if (ret < 0)
++ goto fail_powerdown;
++
++ ret = dw9719_i2c_wr8(dw9719->client, DW9719_MODE, DW9719_MODE_SAC3);
++ if (ret < 0)
++ goto fail_powerdown;
++
++ ret = dw9719_i2c_wr8(dw9719->client, DW9719_VCM_FREQ,
++ DW9719_DEFAULT_VCM_FREQ);
++ if (ret < 0)
++ goto fail_powerdown;
++
++ return 0;
++
++fail_powerdown:
++ dw9719_power_down(dw9719);
++ return ret;
++}
++
++static int dw9719_t_focus_abs(struct dw9719_device *dw9719, s32 value)
++{
++ int ret;
++
++ value = clamp(value, 0, DW9719_MAX_FOCUS_POS);
++ ret = dw9719_i2c_wr16(dw9719->client, DW9719_VCM_CURRENT, value);
++ if (ret < 0)
++ return ret;
++
++ return 0;
++}
++
++static int dw9719_set_ctrl(struct v4l2_ctrl *ctrl)
++{
++ struct dw9719_device *dw9719 = container_of(ctrl->handler,
++ struct dw9719_device,
++ ctrls.handler);
++ int ret;
++
++ /* Only apply changes to the controls if the device is powered up */
++ if (!pm_runtime_get_if_in_use(dw9719->dev))
++ return 0;
++
++ switch (ctrl->id) {
++ case V4L2_CID_FOCUS_ABSOLUTE:
++ ret = dw9719_t_focus_abs(dw9719, ctrl->val);
++ break;
++ default:
++ ret = -EINVAL;
++ }
++
++ pm_runtime_put(dw9719->dev);
++
++ return ret;
++}
++
++static const struct v4l2_ctrl_ops dw9719_ctrl_ops = {
++ .s_ctrl = dw9719_set_ctrl,
++};
++
++static int __maybe_unused dw9719_suspend(struct device *dev)
++{
++ struct v4l2_subdev *sd = dev_get_drvdata(dev);
++ struct dw9719_device *dw9719 = to_dw9719_device(sd);
++ int ret;
++ int val;
++
++ for (val = dw9719->ctrls.focus->val; val >= 0;
++ val -= DW9719_CTRL_STEPS) {
++ ret = dw9719_t_focus_abs(dw9719, val);
++ if (ret)
++ return ret;
++
++ usleep_range(DW9719_CTRL_DELAY_US, DW9719_CTRL_DELAY_US + 10);
++ }
++
++ return dw9719_power_down(dw9719);
++}
++
++static int __maybe_unused dw9719_resume(struct device *dev)
++{
++ struct v4l2_subdev *sd = dev_get_drvdata(dev);
++ struct dw9719_device *dw9719 = to_dw9719_device(sd);
++ int current_focus = dw9719->ctrls.focus->val;
++ int ret;
++ int val;
++
++ ret = dw9719_power_up(dw9719);
++ if (ret)
++ return ret;
++
++ for (val = current_focus % DW9719_CTRL_STEPS; val < current_focus;
++ val += DW9719_CTRL_STEPS) {
++ ret = dw9719_t_focus_abs(dw9719, val);
++ if (ret)
++ goto err_power_down;
++
++ usleep_range(DW9719_CTRL_DELAY_US, DW9719_CTRL_DELAY_US + 10);
++ }
++
++ return 0;
++
++err_power_down:
++ dw9719_power_down(dw9719);
++ return ret;
++}
++
++static int dw9719_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
++{
++ return pm_runtime_resume_and_get(sd->dev);
++}
++
++static int dw9719_close(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
++{
++ pm_runtime_put(sd->dev);
++
++ return 0;
++}
++
++static const struct v4l2_subdev_internal_ops dw9719_internal_ops = {
++ .open = dw9719_open,
++ .close = dw9719_close,
++};
++
++static int dw9719_init_controls(struct dw9719_device *dw9719)
++{
++ const struct v4l2_ctrl_ops *ops = &dw9719_ctrl_ops;
++ int ret;
++
++ ret = v4l2_ctrl_handler_init(&dw9719->ctrls.handler, 1);
++ if (ret)
++ return ret;
++
++ dw9719->ctrls.focus = v4l2_ctrl_new_std(&dw9719->ctrls.handler, ops,
++ V4L2_CID_FOCUS_ABSOLUTE, 0,
++ DW9719_MAX_FOCUS_POS, 1, 0);
++
++ if (dw9719->ctrls.handler.error) {
++ dev_err(dw9719->dev, "Error initialising v4l2 ctrls\n");
++ ret = dw9719->ctrls.handler.error;
++ goto err_free_handler;
++ }
++
++ dw9719->sd.ctrl_handler = &dw9719->ctrls.handler;
++
++ return ret;
++
++err_free_handler:
++ v4l2_ctrl_handler_free(&dw9719->ctrls.handler);
++ return ret;
++}
++
++static const struct v4l2_subdev_ops dw9719_ops = { };
++
++static int dw9719_probe(struct i2c_client *client)
++{
++ struct dw9719_device *dw9719;
++ int ret;
++
++ dw9719 = devm_kzalloc(&client->dev, sizeof(*dw9719), GFP_KERNEL);
++ if (!dw9719)
++ return -ENOMEM;
++
++ dw9719->client = client;
++ dw9719->dev = &client->dev;
++
++ dw9719->regulators[0].supply = "vdd";
++ /*
++ * The DW9719 has only the 1 VDD voltage input, but some PMICs such as
++ * the TPS68470 PMIC have I2C passthrough capability, to disconnect the
++ * sensor's I2C pins from the I2C bus when the sensors VSIO (Sensor-IO)
++ * is off, because some sensors then short these pins to ground;
++ * and the DW9719 might sit behind this passthrough, this it needs to
++ * enable VSIO as that will also enable the I2C passthrough.
++ */
++ dw9719->regulators[1].supply = "vsio";
++
++ ret = devm_regulator_bulk_get(&client->dev, NUM_REGULATORS,
++ dw9719->regulators);
++ if (ret)
++ return dev_err_probe(&client->dev, ret, "getting regulators\n");
++
++ v4l2_i2c_subdev_init(&dw9719->sd, client, &dw9719_ops);
++ dw9719->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
++ dw9719->sd.internal_ops = &dw9719_internal_ops;
++
++ ret = dw9719_init_controls(dw9719);
++ if (ret)
++ return ret;
++
++ ret = media_entity_pads_init(&dw9719->sd.entity, 0, NULL);
++ if (ret < 0)
++ goto err_free_ctrl_handler;
++
++ dw9719->sd.entity.function = MEDIA_ENT_F_LENS;
++
++ /*
++ * We need the driver to work in the event that pm runtime is disable in
++ * the kernel, so power up and verify the chip now. In the event that
++ * runtime pm is disabled this will leave the chip on, so that the lens
++ * will work.
++ */
++
++ ret = dw9719_power_up(dw9719);
++ if (ret)
++ goto err_cleanup_media;
++
++ ret = dw9719_detect(dw9719);
++ if (ret)
++ goto err_powerdown;
++
++ pm_runtime_set_active(&client->dev);
++ pm_runtime_get_noresume(&client->dev);
++ pm_runtime_enable(&client->dev);
++
++ ret = v4l2_async_register_subdev(&dw9719->sd);
++ if (ret < 0)
++ goto err_pm_runtime;
++
++ pm_runtime_set_autosuspend_delay(&client->dev, 1000);
++ pm_runtime_use_autosuspend(&client->dev);
++ pm_runtime_put_autosuspend(&client->dev);
++
++ return ret;
++
++err_pm_runtime:
++ pm_runtime_disable(&client->dev);
++ pm_runtime_put_noidle(&client->dev);
++err_powerdown:
++ dw9719_power_down(dw9719);
++err_cleanup_media:
++ media_entity_cleanup(&dw9719->sd.entity);
++err_free_ctrl_handler:
++ v4l2_ctrl_handler_free(&dw9719->ctrls.handler);
++
++ return ret;
++}
++
++static int dw9719_remove(struct i2c_client *client)
++{
++ struct v4l2_subdev *sd = i2c_get_clientdata(client);
++ struct dw9719_device *dw9719 = container_of(sd, struct dw9719_device,
++ sd);
++
++ pm_runtime_disable(&client->dev);
++ v4l2_async_unregister_subdev(sd);
++ v4l2_ctrl_handler_free(&dw9719->ctrls.handler);
++ media_entity_cleanup(&dw9719->sd.entity);
++
++ return 0;
++}
++
++static const struct i2c_device_id dw9719_id_table[] = {
++ { "dw9719" },
++ { }
++};
++MODULE_DEVICE_TABLE(i2c, dw9719_id_table);
++
++static const struct dev_pm_ops dw9719_pm_ops = {
++ SET_RUNTIME_PM_OPS(dw9719_suspend, dw9719_resume, NULL)
++};
++
++static struct i2c_driver dw9719_i2c_driver = {
++ .driver = {
++ .name = "dw9719",
++ .pm = &dw9719_pm_ops,
++ },
++ .probe_new = dw9719_probe,
++ .remove = dw9719_remove,
++ .id_table = dw9719_id_table,
++};
++module_i2c_driver(dw9719_i2c_driver);
++
++MODULE_AUTHOR("Daniel Scally <djrscally@gmail.com>");
++MODULE_DESCRIPTION("DW9719 VCM Driver");
++MODULE_LICENSE("GPL");
+--
+2.36.1
+
+From 49bf34135d89166093cfea5f817e5ac6862b0ccf Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 13 Dec 2021 22:38:17 +0000
+Subject: [PATCH] media: entity: Skip non-data links in graph iteration
+
+When iterating over the media graph, don't follow links that are not
+data links.
+
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/mc/mc-entity.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
+index b411f9796191..d0563ee4b28b 100644
+--- a/drivers/media/mc/mc-entity.c
++++ b/drivers/media/mc/mc-entity.c
+@@ -295,6 +295,12 @@ static void media_graph_walk_iter(struct media_graph *graph)
+
+ link = list_entry(link_top(graph), typeof(*link), list);
+
++ /* If the link is not a data link, don't follow it */
++ if ((link->flags & MEDIA_LNK_FL_LINK_TYPE) != MEDIA_LNK_FL_DATA_LINK) {
++ link_top(graph) = link_top(graph)->next;
++ return;
++ }
++
+ /* The link is not enabled so we do not follow. */
+ if (!(link->flags & MEDIA_LNK_FL_ENABLED)) {
+ link_top(graph) = link_top(graph)->next;
+--
+2.36.1
+
+From 84e122d9c2fa461ce17b61989b5676c695a07fba Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 13 Dec 2021 22:53:09 +0000
+Subject: [PATCH] media: media.h: Add new media link type
+
+To describe in the kernel the connection between devices and their
+supporting peripherals (for example, a camera sensor and the vcm
+driving the focusing lens for it), add a new type of media link
+to introduce the concept of these ancillary links.
+
+Add some elements to the uAPI documentation to explain the new link
+type, their purpose and some aspects of their current implementation.
+
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ .../media/mediactl/media-controller-model.rst | 6 ++++++
+ .../media/mediactl/media-types.rst | 17 ++++++++++++-----
+ include/uapi/linux/media.h | 1 +
+ 3 files changed, 19 insertions(+), 5 deletions(-)
+
+diff --git a/Documentation/userspace-api/media/mediactl/media-controller-model.rst b/Documentation/userspace-api/media/mediactl/media-controller-model.rst
+index 222cb99debb5..78bfdfb2a322 100644
+--- a/Documentation/userspace-api/media/mediactl/media-controller-model.rst
++++ b/Documentation/userspace-api/media/mediactl/media-controller-model.rst
+@@ -33,3 +33,9 @@ are:
+
+ - An **interface link** is a point-to-point bidirectional control
+ connection between a Linux Kernel interface and an entity.
++
++- An **ancillary link** is a point-to-point connection denoting that two
++ entities form a single logical unit. For example this could represent the
++ fact that a particular camera sensor and lens controller form a single
++ physical module, meaning this lens controller drives the lens for this
++ camera sensor.
+\ No newline at end of file
+diff --git a/Documentation/userspace-api/media/mediactl/media-types.rst b/Documentation/userspace-api/media/mediactl/media-types.rst
+index 0a26397bd01d..60747251d409 100644
+--- a/Documentation/userspace-api/media/mediactl/media-types.rst
++++ b/Documentation/userspace-api/media/mediactl/media-types.rst
+@@ -412,14 +412,21 @@ must be set for every pad.
+ is set by drivers and is read-only for applications.
+
+ * - ``MEDIA_LNK_FL_LINK_TYPE``
+- - This is a bitmask that defines the type of the link. Currently,
+- two types of links are supported:
++ - This is a bitmask that defines the type of the link. The following
++ link types are currently supported:
+
+ .. _MEDIA-LNK-FL-DATA-LINK:
+
+- ``MEDIA_LNK_FL_DATA_LINK`` if the link is between two pads
++ ``MEDIA_LNK_FL_DATA_LINK`` for links that represent a data connection
++ between two pads.
+
+ .. _MEDIA-LNK-FL-INTERFACE-LINK:
+
+- ``MEDIA_LNK_FL_INTERFACE_LINK`` if the link is between an
+- interface and an entity
++ ``MEDIA_LNK_FL_INTERFACE_LINK`` for links that associate an entity to its
++ interface.
++
++ .. _MEDIA-LNK-FL-ANCILLARY-LINK:
++
++ ``MEDIA_LNK_FL_ANCILLARY_LINK`` for links that represent a physical
++ relationship between two entities. The link may or may not be ummutable, so
++ applications must not assume either case.
+\ No newline at end of file
+diff --git a/include/uapi/linux/media.h b/include/uapi/linux/media.h
+index 200fa8462b90..afbae7213d35 100644
+--- a/include/uapi/linux/media.h
++++ b/include/uapi/linux/media.h
+@@ -226,6 +226,7 @@ struct media_pad_desc {
+ #define MEDIA_LNK_FL_LINK_TYPE (0xf << 28)
+ # define MEDIA_LNK_FL_DATA_LINK (0 << 28)
+ # define MEDIA_LNK_FL_INTERFACE_LINK (1 << 28)
++# define MEDIA_LNK_FL_ANCILLARY_LINK (2 << 28)
+
+ struct media_link_desc {
+ struct media_pad_desc source;
+--
+2.36.1
+
+From b9085eecf59dc89d1b82337697e455b31cdd4e1c Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 13 Dec 2021 22:36:31 +0000
+Subject: [PATCH] media: entity: Add link_type_name() helper
+
+Now we have three types of media link, printing the right name during
+debug output is slightly more complicated. Add a helper function to
+make it easier.
+
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/mc/mc-entity.c | 18 +++++++++++++++---
+ 1 file changed, 15 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
+index d0563ee4b28b..1a7d0a4fb9e8 100644
+--- a/drivers/media/mc/mc-entity.c
++++ b/drivers/media/mc/mc-entity.c
+@@ -44,6 +44,20 @@ static inline const char *intf_type(struct media_interface *intf)
+ }
+ };
+
++static inline const char *link_type_name(struct media_link *link)
++{
++ switch (link->flags & MEDIA_LNK_FL_LINK_TYPE) {
++ case MEDIA_LNK_FL_DATA_LINK:
++ return "data";
++ case MEDIA_LNK_FL_INTERFACE_LINK:
++ return "interface";
++ case MEDIA_LNK_FL_ANCILLARY_LINK:
++ return "ancillary";
++ default:
++ return "unknown";
++ }
++}
++
+ __must_check int __media_entity_enum_init(struct media_entity_enum *ent_enum,
+ int idx_max)
+ {
+@@ -89,9 +103,7 @@ static void dev_dbg_obj(const char *event_name, struct media_gobj *gobj)
+
+ dev_dbg(gobj->mdev->dev,
+ "%s id %u: %s link id %u ==> id %u\n",
+- event_name, media_id(gobj),
+- media_type(link->gobj0) == MEDIA_GRAPH_PAD ?
+- "data" : "interface",
++ event_name, media_id(gobj), link_type_name(link),
+ media_id(link->gobj0),
+ media_id(link->gobj1));
+ break;
+--
+2.36.1
+
+From 6f6547dac5f877a7c07c0f947167d3af109888fb Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Mon, 13 Dec 2021 22:54:10 +0000
+Subject: [PATCH] media: entity: Add support for ancillary links
+
+Add functions to create ancillary links, so that they don't need to
+be manually created by users.
+
+Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/mc/mc-entity.c | 22 ++++++++++++++++++++++
+ include/media/media-entity.h | 19 +++++++++++++++++++
+ 2 files changed, 41 insertions(+)
+
+diff --git a/drivers/media/mc/mc-entity.c b/drivers/media/mc/mc-entity.c
+index 1a7d0a4fb9e8..d7e2f78a83cc 100644
+--- a/drivers/media/mc/mc-entity.c
++++ b/drivers/media/mc/mc-entity.c
+@@ -1032,3 +1032,25 @@ void media_remove_intf_links(struct media_interface *intf)
+ mutex_unlock(&mdev->graph_mutex);
+ }
+ EXPORT_SYMBOL_GPL(media_remove_intf_links);
++
++struct media_link *media_create_ancillary_link(struct media_entity *primary,
++ struct media_entity *ancillary)
++{
++ struct media_link *link;
++
++ link = media_add_link(&primary->links);
++ if (!link)
++ return ERR_PTR(-ENOMEM);
++
++ link->gobj0 = &primary->graph_obj;
++ link->gobj1 = &ancillary->graph_obj;
++ link->flags = MEDIA_LNK_FL_IMMUTABLE | MEDIA_LNK_FL_ENABLED |
++ MEDIA_LNK_FL_ANCILLARY_LINK;
++
++ /* Initialize graph object embedded in the new link */
++ media_gobj_create(primary->graph_obj.mdev, MEDIA_GRAPH_LINK,
++ &link->graph_obj);
++
++ return link;
++}
++EXPORT_SYMBOL_GPL(media_create_ancillary_link);
+diff --git a/include/media/media-entity.h b/include/media/media-entity.h
+index fea489f03d57..2a58defc4886 100644
+--- a/include/media/media-entity.h
++++ b/include/media/media-entity.h
+@@ -1108,4 +1108,23 @@ void media_remove_intf_links(struct media_interface *intf);
+ (((entity)->ops && (entity)->ops->operation) ? \
+ (entity)->ops->operation((entity) , ##args) : -ENOIOCTLCMD)
+
++/**
++ * media_create_ancillary_link() - create an ancillary link between two
++ * instances of &media_entity
++ *
++ * @primary: pointer to the primary &media_entity
++ * @ancillary: pointer to the ancillary &media_entity
++ *
++ * Create an ancillary link between two entities, indicating that they
++ * represent two connected pieces of hardware that form a single logical unit.
++ * A typical example is a camera lens controller being linked to the sensor that
++ * it is supporting.
++ *
++ * The function sets both MEDIA_LNK_FL_ENABLED and MEDIA_LNK_FL_IMMUTABLE for
++ * the new link.
++ */
++struct media_link *
++media_create_ancillary_link(struct media_entity *primary,
++ struct media_entity *ancillary);
++
+ #endif
+--
+2.36.1
+
+From eb85a0a2c18d5596e996322286ffb1bcc326443c Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Fri, 26 Nov 2021 22:55:50 +0000
+Subject: [PATCH] media: v4l2-async: Create links during
+ v4l2_async_match_notify()
+
+Upon an async fwnode match, there's some typical behaviour that the
+notifier and matching subdev will want to do. For example, a notifier
+representing a sensor matching to an async subdev representing its
+VCM will want to create an ancillary link to expose that relationship
+to userspace.
+
+To avoid lots of code in individual drivers, try to build these links
+within v4l2 core.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/v4l2-core/v4l2-async.c | 31 ++++++++++++++++++++++++++++
+ 1 file changed, 31 insertions(+)
+
+diff --git a/drivers/media/v4l2-core/v4l2-async.c b/drivers/media/v4l2-core/v4l2-async.c
+index 0404267f1ae4..436bd6900fd8 100644
+--- a/drivers/media/v4l2-core/v4l2-async.c
++++ b/drivers/media/v4l2-core/v4l2-async.c
+@@ -275,6 +275,24 @@ v4l2_async_nf_try_complete(struct v4l2_async_notifier *notifier)
+ static int
+ v4l2_async_nf_try_all_subdevs(struct v4l2_async_notifier *notifier);
+
++static int v4l2_async_create_ancillary_links(struct v4l2_async_notifier *n,
++ struct v4l2_subdev *sd)
++{
++ struct media_link *link = NULL;
++
++#if IS_ENABLED(CONFIG_MEDIA_CONTROLLER)
++
++ if (sd->entity.function != MEDIA_ENT_F_LENS &&
++ sd->entity.function != MEDIA_ENT_F_FLASH)
++ return 0;
++
++ link = media_create_ancillary_link(&n->sd->entity, &sd->entity);
++
++#endif
++
++ return IS_ERR(link) ? PTR_ERR(link) : 0;
++}
++
+ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
+ struct v4l2_device *v4l2_dev,
+ struct v4l2_subdev *sd,
+@@ -293,6 +311,19 @@ static int v4l2_async_match_notify(struct v4l2_async_notifier *notifier,
+ return ret;
+ }
+
++ /*
++ * Depending of the function of the entities involved, we may want to
++ * create links between them (for example between a sensor and its lens
++ * or between a sensor's source pad and the connected device's sink
++ * pad).
++ */
++ ret = v4l2_async_create_ancillary_links(notifier, sd);
++ if (ret) {
++ v4l2_async_nf_call_unbind(notifier, sd, asd);
++ v4l2_device_unregister_subdev(sd);
++ return ret;
++ }
++
+ /* Remove from the waiting list */
+ list_del(&asd->list);
+ sd->asd = asd;
+--
+2.36.1
+
+From 613f354f08b44f7e0909c7ffde8f9ce69c81acc8 Mon Sep 17 00:00:00 2001
+From: Daniel Scally <djrscally@gmail.com>
+Date: Wed, 4 May 2022 23:21:45 +0100
+Subject: [PATCH] media: ipu3-cio2: Move functionality from .complete() to
+ .bound()
+
+Creating links and registering subdev nodes during the .complete()
+callback has the unfortunate effect of preventing all cameras that
+connect to a notifier from working if any one of their drivers fails
+to probe. Moving the functionality from .complete() to .bound() allows
+those camera sensor drivers that did probe correctly to work regardless.
+
+Signed-off-by: Daniel Scally <djrscally@gmail.com>
+Patchset: cameras
+---
+ drivers/media/pci/intel/ipu3/ipu3-cio2-main.c | 65 +++++++------------
+ 1 file changed, 23 insertions(+), 42 deletions(-)
+
+diff --git a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+index 0e9b0503b62a..50682a7b2a07 100644
+--- a/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
++++ b/drivers/media/pci/intel/ipu3/ipu3-cio2-main.c
+@@ -1382,7 +1382,10 @@ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier,
+ {
+ struct cio2_device *cio2 = to_cio2_device(notifier);
+ struct sensor_async_subdev *s_asd = to_sensor_asd(asd);
++ struct device *dev = &cio2->pci_dev->dev;
+ struct cio2_queue *q;
++ unsigned int pad;
++ int ret;
+
+ if (cio2->queue[s_asd->csi2.port].sensor)
+ return -EBUSY;
+@@ -1393,7 +1396,26 @@ static int cio2_notifier_bound(struct v4l2_async_notifier *notifier,
+ q->sensor = sd;
+ q->csi_rx_base = cio2->base + CIO2_REG_PIPE_BASE(q->csi2.port);
+
+- return 0;
++ for (pad = 0; pad < q->sensor->entity.num_pads; pad++)
++ if (q->sensor->entity.pads[pad].flags &
++ MEDIA_PAD_FL_SOURCE)
++ break;
++
++ if (pad == q->sensor->entity.num_pads) {
++ dev_err(dev, "failed to find src pad for %s\n",
++ q->sensor->name);
++ return -ENXIO;
++ }
++
++ ret = media_create_pad_link(&q->sensor->entity, pad, &q->subdev.entity,
++ CIO2_PAD_SINK, 0);
++ if (ret) {
++ dev_err(dev, "failed to create link for %s\n",
++ q->sensor->name);
++ return ret;
++ }
++
++ return v4l2_device_register_subdev_nodes(&cio2->v4l2_dev);
+ }
+
+ /* The .unbind callback */
+@@ -1407,50 +1429,9 @@ static void cio2_notifier_unbind(struct v4l2_async_notifier *notifier,
+ cio2->queue[s_asd->csi2.port].sensor = NULL;
+ }
+
+-/* .complete() is called after all subdevices have been located */
+-static int cio2_notifier_complete(struct v4l2_async_notifier *notifier)
+-{
+- struct cio2_device *cio2 = to_cio2_device(notifier);
+- struct device *dev = &cio2->pci_dev->dev;
+- struct sensor_async_subdev *s_asd;
+- struct v4l2_async_subdev *asd;
+- struct cio2_queue *q;
+- unsigned int pad;
+- int ret;
+-
+- list_for_each_entry(asd, &cio2->notifier.asd_list, asd_list) {
+- s_asd = to_sensor_asd(asd);
+- q = &cio2->queue[s_asd->csi2.port];
+-
+- for (pad = 0; pad < q->sensor->entity.num_pads; pad++)
+- if (q->sensor->entity.pads[pad].flags &
+- MEDIA_PAD_FL_SOURCE)
+- break;
+-
+- if (pad == q->sensor->entity.num_pads) {
+- dev_err(dev, "failed to find src pad for %s\n",
+- q->sensor->name);
+- return -ENXIO;
+- }
+-
+- ret = media_create_pad_link(
+- &q->sensor->entity, pad,
+- &q->subdev.entity, CIO2_PAD_SINK,
+- 0);
+- if (ret) {
+- dev_err(dev, "failed to create link for %s\n",
+- q->sensor->name);
+- return ret;
+- }
+- }
+-
+- return v4l2_device_register_subdev_nodes(&cio2->v4l2_dev);
+-}
+-
+ static const struct v4l2_async_notifier_operations cio2_async_ops = {
+ .bound = cio2_notifier_bound,
+ .unbind = cio2_notifier_unbind,
+- .complete = cio2_notifier_complete,
+ };
+
+ static int cio2_parse_firmware(struct cio2_device *cio2)
+--
+2.36.1
-From 2bd2d24b1a9f413760ef333262833def4c4c7ab2 Mon Sep 17 00:00:00 2001
+From cdc9fb2f64ebffa0f587d9dcebb5070703a784a3 Mon Sep 17 00:00:00 2001
From: Sachi King <nakato@nakato.io>
Date: Sat, 29 May 2021 17:47:38 +1000
Subject: [PATCH] ACPI: Add quirk for Surface Laptop 4 AMD missing irq 7
@@ -5528,9 +8673,9 @@ index 0d01e7f5078c..2b06cf5f2b1f 100644
mp_config_acpi_legacy_irqs();
--
-2.36.0
+2.36.1
-From 4413582ad25091f1ff7c163c97f938550430834a Mon Sep 17 00:00:00 2001
+From fceaab89173a0d9d3e55d3b90e06c15ca4f04cc7 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Thu, 3 Jun 2021 14:04:26 +0200
Subject: [PATCH] ACPI: Add AMD 13" Surface Laptop 4 model to irq 7 override
@@ -5570,5 +8715,5 @@ index 2b06cf5f2b1f..caaec200bea2 100644
};
--
-2.36.0
+2.36.1
diff --git a/SOURCES/patch-5.17-redhat.patch b/SOURCES/patch-5.17-redhat.patch
index 42a316d..187a9f9 100644
--- a/SOURCES/patch-5.17-redhat.patch
+++ b/SOURCES/patch-5.17-redhat.patch
@@ -24,6 +24,7 @@
drivers/firmware/efi/libstub/efistub.h | 74 ++++++++++++
drivers/firmware/efi/libstub/x86-stub.c | 119 +++++++++++++++++++-
drivers/firmware/efi/secureboot.c | 38 +++++++
+ drivers/firmware/sysfb.c | 18 ++-
drivers/gpu/drm/i915/display/intel_bios.c | 6 +
drivers/gpu/drm/i915/display/intel_psr.c | 9 ++
drivers/gpu/drm/i915/display/intel_vbt_defs.h | 3 +
@@ -59,7 +60,7 @@
security/lockdown/Kconfig | 13 +++
security/lockdown/lockdown.c | 1 +
security/security.c | 6 +
- 61 files changed, 980 insertions(+), 212 deletions(-)
+ 62 files changed, 997 insertions(+), 213 deletions(-)
diff --git a/Documentation/core-api/dma-attributes.rst b/Documentation/core-api/dma-attributes.rst
index 1887d92e8e92..17706dc91ec9 100644
@@ -111,7 +112,7 @@ index 000000000000..733a26bd887a
+
+endmenu
diff --git a/Makefile b/Makefile
-index aba139bbd1c7..01a8c0b291ac 100644
+index b821f270a4ca..72a7c6958ea5 100644
--- a/Makefile
+++ b/Makefile
@@ -18,6 +18,10 @@ $(if $(filter __%, $(MAKECMDGOALS)), \
@@ -1249,6 +1250,42 @@ index 000000000000..de0a3714a5d4
+ }
+ }
+}
+diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c
+index 2bfbb05f7d89..a504f7234f35 100644
+--- a/drivers/firmware/sysfb.c
++++ b/drivers/firmware/sysfb.c
+@@ -34,6 +34,22 @@
+ #include <linux/screen_info.h>
+ #include <linux/sysfb.h>
+
++static int skip_simpledrm;
++
++static int __init simpledrm_disable(char *opt)
++{
++ if (!opt)
++ return -EINVAL;
++
++ get_option(&opt, &skip_simpledrm);
++
++ if (skip_simpledrm)
++ pr_info("The simpledrm driver will not be probed\n");
++
++ return 0;
++}
++early_param("nvidia-drm.modeset", simpledrm_disable);
++
+ static __init int sysfb_init(void)
+ {
+ struct screen_info *si = &screen_info;
+@@ -45,7 +61,7 @@ static __init int sysfb_init(void)
+
+ /* try to create a simple-framebuffer device */
+ compatible = sysfb_parse_mode(si, &mode);
+- if (compatible) {
++ if (compatible && !skip_simpledrm) {
+ ret = sysfb_create_simplefb(si, &mode);
+ if (!ret)
+ return 0;
diff --git a/drivers/gpu/drm/i915/display/intel_bios.c b/drivers/gpu/drm/i915/display/intel_bios.c
index 9d989c9f5da4..5d97a251d3dc 100644
--- a/drivers/gpu/drm/i915/display/intel_bios.c
@@ -1684,7 +1721,7 @@ index 107dcf5938d6..225a9797e39d 100644
* Changes the default domain of an iommu group that has *only* one device
*
diff --git a/drivers/nvme/host/core.c b/drivers/nvme/host/core.c
-index 10f7c79caac2..8ac0161d2aef 100644
+index 0abd772c57f0..3c9889ce56ac 100644
--- a/drivers/nvme/host/core.c
+++ b/drivers/nvme/host/core.c
@@ -244,6 +244,9 @@ static void nvme_delete_ctrl_sync(struct nvme_ctrl *ctrl)
@@ -1751,7 +1788,7 @@ index 10f7c79caac2..8ac0161d2aef 100644
}
EXPORT_SYMBOL_GPL(nvme_complete_rq);
diff --git a/drivers/nvme/host/multipath.c b/drivers/nvme/host/multipath.c
-index a703f1f5fb64..d77c24333cb4 100644
+index 189175fff7e4..c0627a9d1274 100644
--- a/drivers/nvme/host/multipath.c
+++ b/drivers/nvme/host/multipath.c
@@ -101,14 +101,10 @@ bool nvme_mpath_set_disk_name(struct nvme_ns *ns, char *disk_name, int *flags)
@@ -1787,7 +1824,7 @@ index a703f1f5fb64..d77c24333cb4 100644
spin_lock_irqsave(&ns->head->requeue_lock, flags);
for (bio = req->bio; bio; bio = bio->bi_next) {
-@@ -870,8 +876,7 @@ int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
+@@ -891,8 +897,7 @@ int nvme_mpath_init_identify(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
int error = 0;
/* check if multipath is enabled and we have the capability */
@@ -1798,7 +1835,7 @@ index a703f1f5fb64..d77c24333cb4 100644
if (!ctrl->max_namespaces ||
diff --git a/drivers/nvme/host/nvme.h b/drivers/nvme/host/nvme.h
-index 68c42e831117..6a7091335257 100644
+index 85f3f55c71c5..aad43c21c0a4 100644
--- a/drivers/nvme/host/nvme.h
+++ b/drivers/nvme/host/nvme.h
@@ -794,6 +794,7 @@ void nvme_mpath_start_freeze(struct nvme_subsystem *subsys);
@@ -1809,7 +1846,7 @@ index 68c42e831117..6a7091335257 100644
void nvme_kick_requeue_lists(struct nvme_ctrl *ctrl);
int nvme_mpath_alloc_disk(struct nvme_ctrl *ctrl,struct nvme_ns_head *head);
void nvme_mpath_add_disk(struct nvme_ns *ns, struct nvme_id_ns *id);
-@@ -832,6 +833,9 @@ static inline bool nvme_mpath_set_disk_name(struct nvme_ns *ns, char *disk_name,
+@@ -833,6 +834,9 @@ static inline bool nvme_mpath_set_disk_name(struct nvme_ns *ns, char *disk_name,
static inline void nvme_failover_req(struct request *req)
{
}
@@ -2144,10 +2181,10 @@ index ab7eea01ab42..fff7c5f737fc 100644
int rmi_register_transport_device(struct rmi_transport_dev *xport);
diff --git a/include/linux/security.h b/include/linux/security.h
-index 25b3ef71f495..d37a6c88c69f 100644
+index 7fc4e9f49f54..6f0b0b2dc73d 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
-@@ -471,6 +471,7 @@ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
+@@ -473,6 +473,7 @@ int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
int security_locked_down(enum lockdown_reason what);
@@ -2155,7 +2192,7 @@ index 25b3ef71f495..d37a6c88c69f 100644
#else /* CONFIG_SECURITY */
static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data)
-@@ -1347,6 +1348,10 @@ static inline int security_locked_down(enum lockdown_reason what)
+@@ -1349,6 +1350,10 @@ static inline int security_locked_down(enum lockdown_reason what)
{
return 0;
}
@@ -2365,10 +2402,10 @@ index 87cbdc64d272..18555cf18da7 100644
static int __init lockdown_lsm_init(void)
diff --git a/security/security.c b/security/security.c
-index b7cf5cbfdc67..3cde9062fcf6 100644
+index aaf6566deb9f..86926966c15d 100644
--- a/security/security.c
+++ b/security/security.c
-@@ -2623,6 +2623,12 @@ int security_locked_down(enum lockdown_reason what)
+@@ -2625,6 +2625,12 @@ int security_locked_down(enum lockdown_reason what)
}
EXPORT_SYMBOL(security_locked_down);
diff --git a/SOURCES/simpledrm-nvidia.patch b/SOURCES/simpledrm-nvidia.patch
deleted file mode 100644
index 48be3c8..0000000
--- a/SOURCES/simpledrm-nvidia.patch
+++ /dev/null
@@ -1,87 +0,0 @@
-From 205bec68a0ea67b6bff6fea9603b7b8aeacc9d46 Mon Sep 17 00:00:00 2001
-From: Javier Martinez Canillas <javierm@redhat.com>
-Date: Thu, 19 May 2022 14:40:07 +0200
-Subject: [PATCH 1/2] drivers/firmware: skip simpledrm if nvidia-drm.modeset=1
- is set
-
-The Nvidia proprietary driver has some bugs that leads to issues if used
-with the simpledrm driver. The most noticeable is that does not register
-an emulated fbdev device.
-
-It just relies on a fbdev to be registered by another driver, that could
-be that could be attached to the framebuffer console. On UEFI machines,
-this is the efifb driver.
-
-This means that disabling the efifb driver will cause virtual consoles to
-not be present in the system when using the Nvidia driver. Legacy BIOS is
-not affected just because fbcon is not used there, but instead vgacon.
-
-Unless a VGA mode is specified using the vga= kernel command line option,
-in that case the vesafb driver is used instead and its fbdev attached to
-the fbcon.
-
-This is a problem because with CONFIG_SYSFB_SIMPLEFB=y, the sysfb platform
-code attempts to register a "simple-framebuffer" platform device (that is
-matched against simpledrm) and only registers either an "efi-framebuffer"
-or "vesa-framebuffer" if this fails to be registered due the video modes
-not being compatible.
-
-The Nvidia driver relying on another driver to register the fbdev is quite
-fragile, since it can't really assume those will stick around. For example
-there are patches posted to remove the EFI and VESA platform devices once
-a real DRM or fbdev driver probes.
-
-But in any case, moving to a simpledrm + emulated fbdev only breaks this
-assumption and causes users to not have VT if the Nvidia driver is used.
-
-So to prevent this, let's add a workaround and make the sysfb to skip the
-"simple-framebuffer" registration when nvidia-drm.modeset=1 option is set.
-
-This is quite horrible, but honestly I can't think of any other approach.
-
-For this to work, the CONFIG_FB_EFI and CONFIG_FB_VESA config options must
-be enabled besides CONFIG_DRM_SIMPLEDRM.
-
-Signed-off-by: Javier Martinez Canillas <javierm@redhat.com>
----
- drivers/firmware/sysfb.c | 18 +++++++++++++++++-
- 1 file changed, 17 insertions(+), 1 deletion(-)
-
-diff --git a/drivers/firmware/sysfb.c b/drivers/firmware/sysfb.c
-index 2bfbb05f7d89..a504f7234f35 100644
---- a/drivers/firmware/sysfb.c
-+++ b/drivers/firmware/sysfb.c
-@@ -34,6 +34,22 @@
- #include <linux/screen_info.h>
- #include <linux/sysfb.h>
-
-+static int skip_simpledrm;
-+
-+static int __init simpledrm_disable(char *opt)
-+{
-+ if (!opt)
-+ return -EINVAL;
-+
-+ get_option(&opt, &skip_simpledrm);
-+
-+ if (skip_simpledrm)
-+ pr_info("The simpledrm driver will not be probed\n");
-+
-+ return 0;
-+}
-+early_param("nvidia-drm.modeset", simpledrm_disable);
-+
- static __init int sysfb_init(void)
- {
- struct screen_info *si = &screen_info;
-@@ -45,7 +61,7 @@ static __init int sysfb_init(void)
-
- /* try to create a simple-framebuffer device */
- compatible = sysfb_parse_mode(si, &mode);
-- if (compatible) {
-+ if (compatible && !skip_simpledrm) {
- ret = sysfb_create_simplefb(si, &mode);
- if (!ret)
- return 0;
---
-GitLab