|
@@ -1,4 +1,4 @@
|
|
|
-From b18cbfbe9d487c24e272578afcf74cc68af93636 Mon Sep 17 00:00:00 2001
|
|
|
+From 6c8e2dd5a9a23b45a58996063801a1d56d16afc7 Mon Sep 17 00:00:00 2001
|
|
|
From: qzed <qzed@users.noreply.github.com>
|
|
|
Date: Mon, 26 Aug 2019 01:15:40 +0200
|
|
|
Subject: [PATCH] ACPI: Fix buffer/integer type mismatch
|
|
@@ -79,9 +79,9 @@ index b272c329d45d..cf547883a993 100644
|
|
|
} else { /* IPMI */
|
|
|
|
|
|
--
|
|
|
-2.31.1
|
|
|
+2.32.0
|
|
|
|
|
|
-From 9528beca1088b8ab0b21aaf0b93864c36cf4b441 Mon Sep 17 00:00:00 2001
|
|
|
+From d9cbdb64b648fe4a54efdc663d0b31e54f6c9667 Mon Sep 17 00:00:00 2001
|
|
|
From: Maximilian Luz <luzmaximilian@gmail.com>
|
|
|
Date: Tue, 24 Sep 2019 17:38:12 +0200
|
|
|
Subject: [PATCH] serdev: Add ACPI devices by ResourceSource field
|
|
@@ -267,9 +267,9 @@ index c66a04d24f1d..1b18d12d217f 100644
|
|
|
if (!ctrl->serdev)
|
|
|
return -ENODEV;
|
|
|
--
|
|
|
-2.31.1
|
|
|
+2.32.0
|
|
|
|
|
|
-From d3efb7a6b79a5c4b2fcef1d86c4a99f3279acb67 Mon Sep 17 00:00:00 2001
|
|
|
+From 94ede501339d351a6849891e0ce504310903bb78 Mon Sep 17 00:00:00 2001
|
|
|
From: Maximilian Luz <luzmaximilian@gmail.com>
|
|
|
Date: Mon, 17 Aug 2020 01:23:20 +0200
|
|
|
Subject: [PATCH] Add file2alias support for Surface Aggregator devices
|
|
@@ -368,9 +368,9 @@ index 7f40b6aab689..76e3b1d7db45 100644
|
|
|
|
|
|
/* Create MODULE_ALIAS() statements.
|
|
|
--
|
|
|
-2.31.1
|
|
|
+2.32.0
|
|
|
|
|
|
-From 97b74a8f0b897844b8659e667d56d113c6ea19be Mon Sep 17 00:00:00 2001
|
|
|
+From 3d64f7437ffd03985911d1c6286c4d39d5a6c3f7 Mon Sep 17 00:00:00 2001
|
|
|
From: Maximilian Luz <luzmaximilian@gmail.com>
|
|
|
Date: Mon, 17 Aug 2020 01:44:30 +0200
|
|
|
Subject: [PATCH] platform/x86: Add support for Surface System Aggregator
|
|
@@ -399,7 +399,7 @@ Patchset: surface-sam
|
|
|
.../surface_aggregator/internal-api.rst | 67 +
|
|
|
.../surface_aggregator/internal.rst | 577 ++++
|
|
|
.../surface_aggregator/overview.rst | 77 +
|
|
|
- .../driver-api/surface_aggregator/ssh.rst | 344 +++
|
|
|
+ .../driver-api/surface_aggregator/ssh.rst | 344 ++
|
|
|
drivers/hid/Kconfig | 2 +
|
|
|
drivers/hid/Makefile | 2 +
|
|
|
drivers/hid/surface-hid/Kconfig | 42 +
|
|
@@ -415,18 +415,18 @@ Patchset: surface-sam
|
|
|
.../platform/x86/surface_aggregator/Makefile | 17 +
|
|
|
drivers/platform/x86/surface_aggregator/bus.c | 415 +++
|
|
|
drivers/platform/x86/surface_aggregator/bus.h | 27 +
|
|
|
- .../x86/surface_aggregator/controller.c | 2718 +++++++++++++++++
|
|
|
+ .../x86/surface_aggregator/controller.c | 2780 +++++++++++++++++
|
|
|
.../x86/surface_aggregator/controller.h | 285 ++
|
|
|
- .../platform/x86/surface_aggregator/core.c | 850 ++++++
|
|
|
+ .../platform/x86/surface_aggregator/core.c | 850 +++++
|
|
|
.../x86/surface_aggregator/ssh_msgb.h | 205 ++
|
|
|
- .../x86/surface_aggregator/ssh_packet_layer.c | 2074 +++++++++++++
|
|
|
+ .../x86/surface_aggregator/ssh_packet_layer.c | 2074 ++++++++++++
|
|
|
.../x86/surface_aggregator/ssh_packet_layer.h | 190 ++
|
|
|
.../x86/surface_aggregator/ssh_parser.c | 228 ++
|
|
|
.../x86/surface_aggregator/ssh_parser.h | 154 +
|
|
|
.../surface_aggregator/ssh_request_layer.c | 1263 ++++++++
|
|
|
.../surface_aggregator/ssh_request_layer.h | 143 +
|
|
|
.../platform/x86/surface_aggregator/trace.h | 632 ++++
|
|
|
- .../platform/x86/surface_aggregator_cdev.c | 804 +++++
|
|
|
+ .../platform/x86/surface_aggregator_cdev.c | 810 +++++
|
|
|
.../x86/surface_aggregator_registry.c | 618 ++++
|
|
|
drivers/platform/x86/surface_dtx.c | 1281 ++++++++
|
|
|
drivers/platform/x86/surface_perfmode.c | 122 +
|
|
@@ -443,7 +443,7 @@ Patchset: surface-sam
|
|
|
include/uapi/linux/surface_aggregator/dtx.h | 146 +
|
|
|
scripts/mod/devicetable-offsets.c | 3 +-
|
|
|
scripts/mod/file2alias.c | 10 +-
|
|
|
- 55 files changed, 19953 insertions(+), 7 deletions(-)
|
|
|
+ 55 files changed, 20021 insertions(+), 7 deletions(-)
|
|
|
create mode 100644 Documentation/driver-api/surface_aggregator/client-api.rst
|
|
|
create mode 100644 Documentation/driver-api/surface_aggregator/client.rst
|
|
|
create mode 100644 Documentation/driver-api/surface_aggregator/clients/cdev.rst
|
|
@@ -3151,7 +3151,7 @@ index 000000000000..4ae11cf09b25
|
|
|
+obj-$(CONFIG_SURFACE_KBD) += surface_kbd.o
|
|
|
diff --git a/drivers/hid/surface-hid/surface_hid.c b/drivers/hid/surface-hid/surface_hid.c
|
|
|
new file mode 100644
|
|
|
-index 000000000000..80e4d185b66f
|
|
|
+index 000000000000..82767dd3e088
|
|
|
--- /dev/null
|
|
|
+++ b/drivers/hid/surface-hid/surface_hid.c
|
|
|
@@ -0,0 +1,251 @@
|
|
@@ -3298,7 +3298,7 @@ index 000000000000..80e4d185b66f
|
|
|
+ rqst.target_id = shid->uid.target;
|
|
|
+ rqst.instance_id = shid->uid.instance;
|
|
|
+ rqst.command_id = SURFACE_HID_CID_GET_FEATURE_REPORT;
|
|
|
-+ rqst.flags = 0;
|
|
|
++ rqst.flags = SSAM_REQUEST_HAS_RESPONSE;
|
|
|
+ rqst.length = sizeof(rprt_id);
|
|
|
+ rqst.payload = &rprt_id;
|
|
|
+
|
|
@@ -5652,10 +5652,10 @@ index 000000000000..ed032c2cbdb2
|
|
|
+#endif /* _SURFACE_AGGREGATOR_BUS_H */
|
|
|
diff --git a/drivers/platform/x86/surface_aggregator/controller.c b/drivers/platform/x86/surface_aggregator/controller.c
|
|
|
new file mode 100644
|
|
|
-index 000000000000..b5ddce8c35cb
|
|
|
+index 000000000000..caf76333f8b3
|
|
|
--- /dev/null
|
|
|
+++ b/drivers/platform/x86/surface_aggregator/controller.c
|
|
|
-@@ -0,0 +1,2718 @@
|
|
|
+@@ -0,0 +1,2780 @@
|
|
|
+// SPDX-License-Identifier: GPL-2.0+
|
|
|
+/*
|
|
|
+ * Main SSAM/SSH controller structure and functionality.
|
|
@@ -6065,6 +6065,31 @@ index 000000000000..b5ddce8c35cb
|
|
|
+}
|
|
|
+
|
|
|
+/**
|
|
|
++ * ssam_nf_refcount_dec_free() - Decrement reference-/activation-count of the
|
|
|
++ * given event and free its entry if the reference count reaches zero.
|
|
|
++ * @nf: The notifier system reference.
|
|
|
++ * @reg: The registry used to enable/disable the event.
|
|
|
++ * @id: The event ID.
|
|
|
++ *
|
|
|
++ * Decrements the reference-/activation-count of the specified event, freeing
|
|
|
++ * its entry if it reaches zero.
|
|
|
++ *
|
|
|
++ * Note: ``nf->lock`` must be held when calling this function.
|
|
|
++ */
|
|
|
++static void ssam_nf_refcount_dec_free(struct ssam_nf *nf,
|
|
|
++ struct ssam_event_registry reg,
|
|
|
++ struct ssam_event_id id)
|
|
|
++{
|
|
|
++ struct ssam_nf_refcount_entry *entry;
|
|
|
++
|
|
|
++ lockdep_assert_held(&nf->lock);
|
|
|
++
|
|
|
++ entry = ssam_nf_refcount_dec(nf, reg, id);
|
|
|
++ if (entry && entry->refcount == 0)
|
|
|
++ kfree(entry);
|
|
|
++}
|
|
|
++
|
|
|
++/**
|
|
|
+ * ssam_nf_refcount_empty() - Test if the notification system has any
|
|
|
+ * enabled/active events.
|
|
|
+ * @nf: The notification system.
|
|
@@ -7772,6 +7797,109 @@ index 000000000000..b5ddce8c35cb
|
|
|
+/* -- Top-level event registry interface. ----------------------------------- */
|
|
|
+
|
|
|
+/**
|
|
|
++ * ssam_nf_refcount_enable() - Enable event for reference count entry if it has
|
|
|
++ * not already been enabled.
|
|
|
++ * @ctrl: The controller to enable the event on.
|
|
|
++ * @entry: The reference count entry for the event to be enabled.
|
|
|
++ * @flags: The flags used for enabling the event on the EC.
|
|
|
++ *
|
|
|
++ * Enable the event associated with the given reference count entry if the
|
|
|
++ * reference count equals one, i.e. the event has not previously been enabled.
|
|
|
++ * If the event has already been enabled (i.e. reference count not equal to
|
|
|
++ * one), check that the flags used for enabling match and warn about this if
|
|
|
++ * they do not.
|
|
|
++ *
|
|
|
++ * This does not modify the reference count itself, which is done with
|
|
|
++ * ssam_nf_refcount_inc() / ssam_nf_refcount_dec().
|
|
|
++ *
|
|
|
++ * Note: ``nf->lock`` must be held when calling this function.
|
|
|
++ *
|
|
|
++ * Return: Returns zero on success. If the event is enabled by this call,
|
|
|
++ * returns the status of the event-enable EC command.
|
|
|
++ */
|
|
|
++static int ssam_nf_refcount_enable(struct ssam_controller *ctrl,
|
|
|
++ struct ssam_nf_refcount_entry *entry, u8 flags)
|
|
|
++{
|
|
|
++ const struct ssam_event_registry reg = entry->key.reg;
|
|
|
++ const struct ssam_event_id id = entry->key.id;
|
|
|
++ struct ssam_nf *nf = &ctrl->cplt.event.notif;
|
|
|
++ int status;
|
|
|
++
|
|
|
++ lockdep_assert_held(&nf->lock);
|
|
|
++
|
|
|
++ ssam_dbg(ctrl, "enabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
|
|
|
++ reg.target_category, id.target_category, id.instance, entry->refcount);
|
|
|
++
|
|
|
++ if (entry->refcount == 1) {
|
|
|
++ status = ssam_ssh_event_enable(ctrl, reg, id, flags);
|
|
|
++ if (status)
|
|
|
++ return status;
|
|
|
++
|
|
|
++ entry->flags = flags;
|
|
|
++
|
|
|
++ } else if (entry->flags != flags) {
|
|
|
++ ssam_warn(ctrl,
|
|
|
++ "inconsistent flags when enabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
|
|
|
++ flags, entry->flags, reg.target_category, id.target_category,
|
|
|
++ id.instance);
|
|
|
++ }
|
|
|
++
|
|
|
++ return 0;
|
|
|
++}
|
|
|
++
|
|
|
++/**
|
|
|
++ * ssam_nf_refcount_disable_free() - Disable event for reference count entry if it is
|
|
|
++ * no longer in use and free the corresponding entry.
|
|
|
++ * @ctrl: The controller to disable the event on.
|
|
|
++ * @entry: The reference count entry for the event to be disabled.
|
|
|
++ * @flags: The flags used for enabling the event on the EC.
|
|
|
++ *
|
|
|
++ * If the reference count equals zero, i.e. the event is no longer requested by
|
|
|
++ * any client, the event will be disabled and the corresponding reference count
|
|
|
++ * entry freed. The reference count entry must not be used any more after a
|
|
|
++ * call to this function.
|
|
|
++ *
|
|
|
++ * Also checks if the flags used for disabling the event match the flags used
|
|
|
++ * for enabling the event and warns if they do not (regardless of reference
|
|
|
++ * count).
|
|
|
++ *
|
|
|
++ * This does not modify the reference count itself, which is done with
|
|
|
++ * ssam_nf_refcount_inc() / ssam_nf_refcount_dec().
|
|
|
++ *
|
|
|
++ * Note: ``nf->lock`` must be held when calling this function.
|
|
|
++ *
|
|
|
++ * Return: Returns zero on success. If the event is disabled by this call,
|
|
|
++ * returns the status of the event-enable EC command.
|
|
|
++ */
|
|
|
++static int ssam_nf_refcount_disable_free(struct ssam_controller *ctrl,
|
|
|
++ struct ssam_nf_refcount_entry *entry, u8 flags)
|
|
|
++{
|
|
|
++ const struct ssam_event_registry reg = entry->key.reg;
|
|
|
++ const struct ssam_event_id id = entry->key.id;
|
|
|
++ struct ssam_nf *nf = &ctrl->cplt.event.notif;
|
|
|
++ int status = 0;
|
|
|
++
|
|
|
++ lockdep_assert_held(&nf->lock);
|
|
|
++
|
|
|
++ ssam_dbg(ctrl, "disabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
|
|
|
++ reg.target_category, id.target_category, id.instance, entry->refcount);
|
|
|
++
|
|
|
++ if (entry->flags != flags) {
|
|
|
++ ssam_warn(ctrl,
|
|
|
++ "inconsistent flags when disabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
|
|
|
++ flags, entry->flags, reg.target_category, id.target_category,
|
|
|
++ id.instance);
|
|
|
++ }
|
|
|
++
|
|
|
++ if (entry->refcount == 0) {
|
|
|
++ status = ssam_ssh_event_disable(ctrl, reg, id, flags);
|
|
|
++ kfree(entry);
|
|
|
++ }
|
|
|
++
|
|
|
++ return status;
|
|
|
++}
|
|
|
++
|
|
|
++/**
|
|
|
+ * ssam_notifier_register() - Register an event notifier.
|
|
|
+ * @ctrl: The controller to register the notifier on.
|
|
|
+ * @n: The event notifier to register.
|
|
@@ -7815,41 +7943,26 @@ index 000000000000..b5ddce8c35cb
|
|
|
+ mutex_unlock(&nf->lock);
|
|
|
+ return PTR_ERR(entry);
|
|
|
+ }
|
|
|
-+
|
|
|
-+ ssam_dbg(ctrl, "enabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
|
|
|
-+ n->event.reg.target_category, n->event.id.target_category,
|
|
|
-+ n->event.id.instance, entry->refcount);
|
|
|
+ }
|
|
|
+
|
|
|
+ status = ssam_nfblk_insert(nf_head, &n->base);
|
|
|
+ if (status) {
|
|
|
-+ if (entry) {
|
|
|
-+ entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id);
|
|
|
-+ if (entry->refcount == 0)
|
|
|
-+ kfree(entry);
|
|
|
-+ }
|
|
|
++ if (entry)
|
|
|
++ ssam_nf_refcount_dec_free(nf, n->event.reg, n->event.id);
|
|
|
+
|
|
|
+ mutex_unlock(&nf->lock);
|
|
|
+ return status;
|
|
|
+ }
|
|
|
+
|
|
|
-+ if (entry && entry->refcount == 1) {
|
|
|
-+ status = ssam_ssh_event_enable(ctrl, n->event.reg, n->event.id, n->event.flags);
|
|
|
++ if (entry) {
|
|
|
++ status = ssam_nf_refcount_enable(ctrl, entry, n->event.flags);
|
|
|
+ if (status) {
|
|
|
+ ssam_nfblk_remove(&n->base);
|
|
|
-+ kfree(ssam_nf_refcount_dec(nf, n->event.reg, n->event.id));
|
|
|
++ ssam_nf_refcount_dec_free(nf, n->event.reg, n->event.id);
|
|
|
+ mutex_unlock(&nf->lock);
|
|
|
+ synchronize_srcu(&nf_head->srcu);
|
|
|
+ return status;
|
|
|
+ }
|
|
|
-+
|
|
|
-+ entry->flags = n->event.flags;
|
|
|
-+
|
|
|
-+ } else if (entry && entry->flags != n->event.flags) {
|
|
|
-+ ssam_warn(ctrl,
|
|
|
-+ "inconsistent flags when enabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
|
|
|
-+ n->event.flags, entry->flags, n->event.reg.target_category,
|
|
|
-+ n->event.id.target_category, n->event.id.instance);
|
|
|
+ }
|
|
|
+
|
|
|
+ mutex_unlock(&nf->lock);
|
|
@@ -7896,35 +8009,20 @@ index 000000000000..b5ddce8c35cb
|
|
|
+ * If this is an observer notifier, do not attempt to disable the
|
|
|
+ * event, just remove it.
|
|
|
+ */
|
|
|
-+ if (n->flags & SSAM_EVENT_NOTIFIER_OBSERVER)
|
|
|
-+ goto remove;
|
|
|
-+
|
|
|
-+ entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id);
|
|
|
-+ if (WARN_ON(!entry)) {
|
|
|
-+ /*
|
|
|
-+ * If this does not return an entry, there's a logic error
|
|
|
-+ * somewhere: The notifier block is registered, but the event
|
|
|
-+ * refcount entry is not there. Remove the notifier block
|
|
|
-+ * anyways.
|
|
|
-+ */
|
|
|
-+ status = -ENOENT;
|
|
|
-+ goto remove;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ ssam_dbg(ctrl, "disabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
|
|
|
-+ n->event.reg.target_category, n->event.id.target_category,
|
|
|
-+ n->event.id.instance, entry->refcount);
|
|
|
-+
|
|
|
-+ if (entry->flags != n->event.flags) {
|
|
|
-+ ssam_warn(ctrl,
|
|
|
-+ "inconsistent flags when disabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
|
|
|
-+ n->event.flags, entry->flags, n->event.reg.target_category,
|
|
|
-+ n->event.id.target_category, n->event.id.instance);
|
|
|
-+ }
|
|
|
++ if (!(n->flags & SSAM_EVENT_NOTIFIER_OBSERVER)) {
|
|
|
++ entry = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id);
|
|
|
++ if (WARN_ON(!entry)) {
|
|
|
++ /*
|
|
|
++ * If this does not return an entry, there's a logic
|
|
|
++ * error somewhere: The notifier block is registered,
|
|
|
++ * but the event refcount entry is not there. Remove
|
|
|
++ * the notifier block anyways.
|
|
|
++ */
|
|
|
++ status = -ENOENT;
|
|
|
++ goto remove;
|
|
|
++ }
|
|
|
+
|
|
|
-+ if (entry->refcount == 0) {
|
|
|
-+ status = ssam_ssh_event_disable(ctrl, n->event.reg, n->event.id, n->event.flags);
|
|
|
-+ kfree(entry);
|
|
|
++ status = ssam_nf_refcount_disable_free(ctrl, entry, n->event.flags);
|
|
|
+ }
|
|
|
+
|
|
|
+remove:
|
|
@@ -7962,17 +8060,13 @@ index 000000000000..b5ddce8c35cb
|
|
|
+ struct ssam_event_id id, u8 flags)
|
|
|
+{
|
|
|
+ u16 rqid = ssh_tc_to_rqid(id.target_category);
|
|
|
++ struct ssam_nf *nf = &ctrl->cplt.event.notif;
|
|
|
+ struct ssam_nf_refcount_entry *entry;
|
|
|
-+ struct ssam_nf_head *nf_head;
|
|
|
-+ struct ssam_nf *nf;
|
|
|
+ int status;
|
|
|
+
|
|
|
+ if (!ssh_rqid_is_event(rqid))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
-+ nf = &ctrl->cplt.event.notif;
|
|
|
-+ nf_head = &nf->head[ssh_rqid_to_event(rqid)];
|
|
|
-+
|
|
|
+ mutex_lock(&nf->lock);
|
|
|
+
|
|
|
+ entry = ssam_nf_refcount_inc(nf, reg, id);
|
|
@@ -7981,25 +8075,11 @@ index 000000000000..b5ddce8c35cb
|
|
|
+ return PTR_ERR(entry);
|
|
|
+ }
|
|
|
+
|
|
|
-+ ssam_dbg(ctrl, "enabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
|
|
|
-+ reg.target_category, id.target_category, id.instance,
|
|
|
-+ entry->refcount);
|
|
|
-+
|
|
|
-+ if (entry->refcount == 1) {
|
|
|
-+ status = ssam_ssh_event_enable(ctrl, reg, id, flags);
|
|
|
-+ if (status) {
|
|
|
-+ kfree(ssam_nf_refcount_dec(nf, reg, id));
|
|
|
-+ mutex_unlock(&nf->lock);
|
|
|
-+ return status;
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ entry->flags = flags;
|
|
|
-+
|
|
|
-+ } else if (entry->flags != flags) {
|
|
|
-+ ssam_warn(ctrl,
|
|
|
-+ "inconsistent flags when enabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
|
|
|
-+ flags, entry->flags, reg.target_category,
|
|
|
-+ id.target_category, id.instance);
|
|
|
++ status = ssam_nf_refcount_enable(ctrl, entry, flags);
|
|
|
++ if (status) {
|
|
|
++ ssam_nf_refcount_dec_free(nf, reg, id);
|
|
|
++ mutex_unlock(&nf->lock);
|
|
|
++ return status;
|
|
|
+ }
|
|
|
+
|
|
|
+ mutex_unlock(&nf->lock);
|
|
@@ -8031,40 +8111,22 @@ index 000000000000..b5ddce8c35cb
|
|
|
+ struct ssam_event_id id, u8 flags)
|
|
|
+{
|
|
|
+ u16 rqid = ssh_tc_to_rqid(id.target_category);
|
|
|
++ struct ssam_nf *nf = &ctrl->cplt.event.notif;
|
|
|
+ struct ssam_nf_refcount_entry *entry;
|
|
|
-+ struct ssam_nf_head *nf_head;
|
|
|
-+ struct ssam_nf *nf;
|
|
|
-+ int status = 0;
|
|
|
++ int status;
|
|
|
+
|
|
|
+ if (!ssh_rqid_is_event(rqid))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
-+ nf = &ctrl->cplt.event.notif;
|
|
|
-+ nf_head = &nf->head[ssh_rqid_to_event(rqid)];
|
|
|
-+
|
|
|
+ mutex_lock(&nf->lock);
|
|
|
+
|
|
|
+ entry = ssam_nf_refcount_dec(nf, reg, id);
|
|
|
-+ if (WARN_ON(!entry)) {
|
|
|
++ if (!entry) {
|
|
|
+ mutex_unlock(&nf->lock);
|
|
|
+ return -ENOENT;
|
|
|
+ }
|
|
|
+
|
|
|
-+ ssam_dbg(ctrl, "disabling event (reg: %#04x, tc: %#04x, iid: %#04x, rc: %d)\n",
|
|
|
-+ reg.target_category, id.target_category, id.instance,
|
|
|
-+ entry->refcount);
|
|
|
-+
|
|
|
-+ if (entry->flags != flags) {
|
|
|
-+ ssam_warn(ctrl,
|
|
|
-+ "inconsistent flags when disabling event: got %#04x, expected %#04x (reg: %#04x, tc: %#04x, iid: %#04x)\n",
|
|
|
-+ flags, entry->flags, reg.target_category,
|
|
|
-+ id.target_category, id.instance);
|
|
|
-+ }
|
|
|
-+
|
|
|
-+ if (entry->refcount == 0) {
|
|
|
-+ status = ssam_ssh_event_disable(ctrl, reg, id, flags);
|
|
|
-+ kfree(entry);
|
|
|
-+ }
|
|
|
++ status = ssam_nf_refcount_disable_free(ctrl, entry, flags);
|
|
|
+
|
|
|
+ mutex_unlock(&nf->lock);
|
|
|
+ return status;
|
|
@@ -14460,10 +14522,10 @@ index 000000000000..de64cf169060
|
|
|
+#include <trace/define_trace.h>
|
|
|
diff --git a/drivers/platform/x86/surface_aggregator_cdev.c b/drivers/platform/x86/surface_aggregator_cdev.c
|
|
|
new file mode 100644
|
|
|
-index 000000000000..93969d9f7f9a
|
|
|
+index 000000000000..bbc0fc57ba13
|
|
|
--- /dev/null
|
|
|
+++ b/drivers/platform/x86/surface_aggregator_cdev.c
|
|
|
-@@ -0,0 +1,804 @@
|
|
|
+@@ -0,0 +1,810 @@
|
|
|
+// SPDX-License-Identifier: GPL-2.0+
|
|
|
+/*
|
|
|
+ * Provides user-space access to the SSAM EC via the /dev/surface/aggregator
|
|
@@ -14488,6 +14550,7 @@ index 000000000000..93969d9f7f9a
|
|
|
+
|
|
|
+#include <linux/surface_aggregator/cdev.h>
|
|
|
+#include <linux/surface_aggregator/controller.h>
|
|
|
++#include <linux/surface_aggregator/serial_hub.h>
|
|
|
+
|
|
|
+#define SSAM_CDEV_DEVICE_NAME "surface_aggregator_cdev"
|
|
|
+
|
|
@@ -14597,22 +14660,23 @@ index 000000000000..93969d9f7f9a
|
|
|
+ return 0;
|
|
|
+}
|
|
|
+
|
|
|
-+static int ssam_cdev_notifier_register(struct ssam_cdev_client *client, u8 category, int priority)
|
|
|
++static int ssam_cdev_notifier_register(struct ssam_cdev_client *client, u8 tc, int priority)
|
|
|
+{
|
|
|
++ const u16 rqid = ssh_tc_to_rqid(tc);
|
|
|
++ const u16 event = ssh_rqid_to_event(rqid);
|
|
|
+ struct ssam_cdev_notifier *nf;
|
|
|
-+ int index = ((int)category) - 1;
|
|
|
+ int status;
|
|
|
+
|
|
|
+ lockdep_assert_held_read(&client->cdev->lock);
|
|
|
+
|
|
|
+ /* Validate notifier target category. */
|
|
|
-+ if (index < 0 || index >= SSH_NUM_EVENTS)
|
|
|
++ if (!ssh_rqid_is_event(rqid))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ mutex_lock(&client->notifier_lock);
|
|
|
+
|
|
|
+ /* Check if the notifier has already been registered. */
|
|
|
-+ if (client->notifier[index]) {
|
|
|
++ if (client->notifier[event]) {
|
|
|
+ mutex_unlock(&client->notifier_lock);
|
|
|
+ return -EEXIST;
|
|
|
+ }
|
|
@@ -14633,7 +14697,7 @@ index 000000000000..93969d9f7f9a
|
|
|
+ nf->client = client;
|
|
|
+ nf->nf.base.fn = ssam_cdev_notifier;
|
|
|
+ nf->nf.base.priority = priority;
|
|
|
-+ nf->nf.event.id.target_category = category;
|
|
|
++ nf->nf.event.id.target_category = tc;
|
|
|
+ nf->nf.event.mask = 0; /* Do not do any matching. */
|
|
|
+ nf->nf.flags = SSAM_EVENT_NOTIFIER_OBSERVER;
|
|
|
+
|
|
@@ -14642,35 +14706,36 @@ index 000000000000..93969d9f7f9a
|
|
|
+ if (status)
|
|
|
+ kfree(nf);
|
|
|
+ else
|
|
|
-+ client->notifier[index] = nf;
|
|
|
++ client->notifier[event] = nf;
|
|
|
+
|
|
|
+ mutex_unlock(&client->notifier_lock);
|
|
|
+ return status;
|
|
|
+}
|
|
|
+
|
|
|
-+static int ssam_cdev_notifier_unregister(struct ssam_cdev_client *client, u8 category)
|
|
|
++static int ssam_cdev_notifier_unregister(struct ssam_cdev_client *client, u8 tc)
|
|
|
+{
|
|
|
-+ int index = ((int)category) - 1;
|
|
|
++ const u16 rqid = ssh_tc_to_rqid(tc);
|
|
|
++ const u16 event = ssh_rqid_to_event(rqid);
|
|
|
+ int status;
|
|
|
+
|
|
|
+ lockdep_assert_held_read(&client->cdev->lock);
|
|
|
+
|
|
|
+ /* Validate notifier target category. */
|
|
|
-+ if (index < 0 || index >= SSH_NUM_EVENTS)
|
|
|
++ if (!ssh_rqid_is_event(rqid))
|
|
|
+ return -EINVAL;
|
|
|
+
|
|
|
+ mutex_lock(&client->notifier_lock);
|
|
|
+
|
|
|
+ /* Check if the notifier is currently registered. */
|
|
|
-+ if (!client->notifier[index]) {
|
|
|
++ if (!client->notifier[event]) {
|
|
|
+ mutex_unlock(&client->notifier_lock);
|
|
|
+ return -ENOENT;
|
|
|
+ }
|
|
|
+
|
|
|
+ /* Unregister and free notifier. */
|
|
|
-+ status = ssam_notifier_unregister(client->cdev->ctrl, &client->notifier[index]->nf);
|
|
|
-+ kfree(client->notifier[index]);
|
|
|
-+ client->notifier[index] = NULL;
|
|
|
++ status = ssam_notifier_unregister(client->cdev->ctrl, &client->notifier[event]->nf);
|
|
|
++ kfree(client->notifier[event]);
|
|
|
++ client->notifier[event] = NULL;
|
|
|
+
|
|
|
+ mutex_unlock(&client->notifier_lock);
|
|
|
+ return status;
|
|
@@ -14948,6 +15013,9 @@ index 000000000000..93969d9f7f9a
|
|
|
+
|
|
|
+ if (test_bit(SSAM_CDEV_DEVICE_SHUTDOWN_BIT, &cdev->flags)) {
|
|
|
+ up_write(&cdev->client_lock);
|
|
|
++ mutex_destroy(&client->write_lock);
|
|
|
++ mutex_destroy(&client->read_lock);
|
|
|
++ mutex_destroy(&client->notifier_lock);
|
|
|
+ ssam_cdev_put(client->cdev);
|
|
|
+ vfree(client);
|
|
|
+ return -ENODEV;
|
|
@@ -20846,5 +20914,5 @@ index 76e3b1d7db45..f171616ab318 100644
|
|
|
ADD(alias, "f", match_flags & SSAM_MATCH_FUNCTION, function);
|
|
|
|
|
|
--
|
|
|
-2.31.1
|
|
|
+2.32.0
|
|
|
|