Update v5.7 patches

Changes:
  SAM:
    - Fix bug that can cause IRQ storm when SSAM wake IRQ gets triggered.
    - Continued internal restructuring.
    - Other small bug fixes.

Links:
- kernel: 78e06bc875
- SAM: b9fe8f28b7
This commit is contained in:
Maximilian Luz 2020-08-03 18:23:42 +02:00
parent 8e8811cd28
commit 23d3bc55ce
No known key found for this signature in database
GPG key ID: 70EC0937F6C26F02
6 changed files with 304 additions and 110 deletions

View file

@ -1,4 +1,4 @@
From b39f1ffc5acaf5fb37349604be84dcf7bae99db8 Mon Sep 17 00:00:00 2001 From f84531c61f54f39715533f820c29efa54ba0ab65 Mon Sep 17 00:00:00 2001
From: Chih-Wei Huang <cwhuang@linux.org.tw> From: Chih-Wei Huang <cwhuang@linux.org.tw>
Date: Tue, 18 Sep 2018 11:01:37 +0800 Date: Tue, 18 Sep 2018 11:01:37 +0800
Subject: [PATCH 1/5] surface3-oemb Subject: [PATCH 1/5] surface3-oemb

View file

@ -1,4 +1,4 @@
From 2b32e9bcc1f80ce457608b84bb74f0e5f191ae0a Mon Sep 17 00:00:00 2001 From e3c13b807bf54be7d176493a0e104ae807245ffc Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com> From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Fri, 6 Dec 2019 11:56:12 +0100 Date: Fri, 6 Dec 2019 11:56:12 +0100
Subject: [PATCH 2/5] surface-sam Subject: [PATCH 2/5] surface-sam
@ -20,11 +20,11 @@ Subject: [PATCH 2/5] surface-sam
.../x86/surface_sam/surface_sam_sid_power.h | 16 + .../x86/surface_sam/surface_sam_sid_power.h | 16 +
.../x86/surface_sam/surface_sam_sid_vhf.c | 429 ++ .../x86/surface_sam/surface_sam_sid_vhf.c | 429 ++
.../x86/surface_sam/surface_sam_sid_vhf.h | 14 + .../x86/surface_sam/surface_sam_sid_vhf.h | 14 +
.../x86/surface_sam/surface_sam_ssh.c | 5190 +++++++++++++++++ .../x86/surface_sam/surface_sam_ssh.c | 5329 +++++++++++++++++
.../x86/surface_sam/surface_sam_ssh.h | 717 +++ .../x86/surface_sam/surface_sam_ssh.h | 717 +++
.../x86/surface_sam/surface_sam_ssh_trace.h | 532 ++ .../x86/surface_sam/surface_sam_ssh_trace.h | 587 ++
.../x86/surface_sam/surface_sam_vhf.c | 266 + .../x86/surface_sam/surface_sam_vhf.c | 266 +
20 files changed, 12241 insertions(+) 20 files changed, 12435 insertions(+)
create mode 100644 drivers/platform/x86/surface_sam/Kconfig create mode 100644 drivers/platform/x86/surface_sam/Kconfig
create mode 100644 drivers/platform/x86/surface_sam/Makefile create mode 100644 drivers/platform/x86/surface_sam/Makefile
create mode 100644 drivers/platform/x86/surface_sam/surface_sam_debugfs.c create mode 100644 drivers/platform/x86/surface_sam/surface_sam_debugfs.c
@ -5685,10 +5685,10 @@ index 0000000000000..d956de5cf877a
+#endif /* _SURFACE_SAM_SID_VHF_H */ +#endif /* _SURFACE_SAM_SID_VHF_H */
diff --git a/drivers/platform/x86/surface_sam/surface_sam_ssh.c b/drivers/platform/x86/surface_sam/surface_sam_ssh.c diff --git a/drivers/platform/x86/surface_sam/surface_sam_ssh.c b/drivers/platform/x86/surface_sam/surface_sam_ssh.c
new file mode 100644 new file mode 100644
index 0000000000000..4144fe0b3d192 index 0000000000000..4551b75570f22
--- /dev/null --- /dev/null
+++ b/drivers/platform/x86/surface_sam/surface_sam_ssh.c +++ b/drivers/platform/x86/surface_sam/surface_sam_ssh.c
@@ -0,0 +1,5190 @@ @@ -0,0 +1,5329 @@
+// SPDX-License-Identifier: GPL-2.0-or-later +// SPDX-License-Identifier: GPL-2.0-or-later
+/* +/*
+ * Surface Serial Hub (SSH) driver for communication with the Surface/System + * Surface Serial Hub (SSH) driver for communication with the Surface/System
@ -5759,11 +5759,6 @@ index 0000000000000..4144fe0b3d192
+ return rqid > 0 ? rqid + 1u : rqid + SSH_NUM_EVENTS + 1u; + return rqid > 0 ? rqid + 1u : rqid + SSH_NUM_EVENTS + 1u;
+} +}
+ +
+static inline u16 ssh_event_to_rqid(u16 event)
+{
+ return event + 1u;
+}
+
+static inline u16 ssh_rqid_to_event(u16 rqid) +static inline u16 ssh_rqid_to_event(u16 rqid)
+{ +{
+ return rqid - 1u; + return rqid - 1u;
@ -5779,11 +5774,6 @@ index 0000000000000..4144fe0b3d192
+ return tc; + return tc;
+} +}
+ +
+static inline int ssh_tc_to_event(u8 tc)
+{
+ return ssh_rqid_to_event(ssh_tc_to_rqid(tc));
+}
+
+static inline u8 ssh_channel_to_index(u8 channel) +static inline u8 ssh_channel_to_index(u8 channel)
+{ +{
+ return channel - 1u; + return channel - 1u;
@ -5859,31 +5849,6 @@ index 0000000000000..4144fe0b3d192
+ msgb->ptr = ptr; + msgb->ptr = ptr;
+} +}
+ +
+static inline int msgb_alloc(struct msgbuf *msgb, size_t cap, gfp_t flags)
+{
+ u8 *buf;
+
+ buf = kzalloc(cap, flags);
+ if (!buf)
+ return -ENOMEM;
+
+ msgb_init(msgb, buf, cap);
+ return 0;
+}
+
+static inline void msgb_free(struct msgbuf *msgb)
+{
+ kfree(msgb->begin);
+ msgb->begin = NULL;
+ msgb->end = NULL;
+ msgb->ptr = NULL;
+}
+
+static inline void msgb_reset(struct msgbuf *msgb)
+{
+ msgb->ptr = msgb->begin;
+}
+
+static inline size_t msgb_bytes_used(const struct msgbuf *msgb) +static inline size_t msgb_bytes_used(const struct msgbuf *msgb)
+{ +{
+ return msgb->ptr - msgb->begin; + return msgb->ptr - msgb->begin;
@ -6157,11 +6122,6 @@ index 0000000000000..4144fe0b3d192
+ buf->cap = 0; + buf->cap = 0;
+} +}
+ +
+static inline void sshp_buf_reset(struct sshp_buf *buf)
+{
+ buf->len = 0;
+}
+
+static inline void sshp_buf_drop(struct sshp_buf *buf, size_t n) +static inline void sshp_buf_drop(struct sshp_buf *buf, size_t n)
+{ +{
+ memmove(buf->ptr, buf->ptr + n, buf->len - n); + memmove(buf->ptr, buf->ptr + n, buf->len - n);
@ -6576,10 +6536,8 @@ index 0000000000000..4144fe0b3d192
+ } + }
+} +}
+ +
+static inline int ssh_ptl_write_buf(struct ssh_ptl *ptl, +static int ssh_ptl_write_buf(struct ssh_ptl *ptl, struct ssh_packet *packet,
+ struct ssh_packet *packet, + const unsigned char *buf, size_t count)
+ const unsigned char *buf,
+ size_t count)
+{ +{
+ int status; + int status;
+ +
@ -6596,7 +6554,7 @@ index 0000000000000..4144fe0b3d192
+ return serdev_device_write_buf(ptl->serdev, buf, count); + return serdev_device_write_buf(ptl->serdev, buf, count);
+} +}
+ +
+static inline void ssh_ptl_tx_inject_invalid_data(struct ssh_packet *packet) +static void ssh_ptl_tx_inject_invalid_data(struct ssh_packet *packet)
+{ +{
+ // ignore packets that don't carry any data (i.e. flush) + // ignore packets that don't carry any data (i.e. flush)
+ if (!packet->data.ptr || !packet->data.len) + if (!packet->data.ptr || !packet->data.len)
@ -6622,8 +6580,8 @@ index 0000000000000..4144fe0b3d192
+ memset(packet->data.ptr, 0xb3, packet->data.len); + memset(packet->data.ptr, 0xb3, packet->data.len);
+} +}
+ +
+static inline void ssh_ptl_rx_inject_invalid_syn(struct ssh_ptl *ptl, +static void ssh_ptl_rx_inject_invalid_syn(struct ssh_ptl *ptl,
+ struct ssam_span *data) + struct ssam_span *data)
+{ +{
+ struct ssam_span frame; + struct ssam_span frame;
+ +
@ -6639,8 +6597,8 @@ index 0000000000000..4144fe0b3d192
+ data->ptr[1] = 0xb3; // set second byte of SYN to "random" value + data->ptr[1] = 0xb3; // set second byte of SYN to "random" value
+} +}
+ +
+static inline void ssh_ptl_rx_inject_invalid_data(struct ssh_ptl *ptl, +static void ssh_ptl_rx_inject_invalid_data(struct ssh_ptl *ptl,
+ struct ssam_span *frame) + struct ssam_span *frame)
+{ +{
+ size_t payload_len, message_len; + size_t payload_len, message_len;
+ struct ssh_frame *sshf; + struct ssh_frame *sshf;
@ -6756,41 +6714,51 @@ index 0000000000000..4144fe0b3d192
+} +}
+ +
+ +
+static int ptl_alloc_ctrl_packet(struct ssh_ptl *ptl, +static struct kmem_cache *ssh_ctrl_packet_cache;
+ struct ssh_packet **packet, +
+static int __init ssh_ctrl_packet_cache_init(void)
+{
+ const unsigned int size = sizeof(struct ssh_packet) + SSH_MSG_LEN_CTRL;
+ const unsigned int align = __alignof__(struct ssh_packet);
+ struct kmem_cache *cache;
+
+ cache = kmem_cache_create("ssam_ctrl_packet", size, align, 0, NULL);
+ if (!cache)
+ return -ENOMEM;
+
+ ssh_ctrl_packet_cache = cache;
+ return 0;
+}
+
+static void __exit ssh_ctrl_packet_cache_destroy(void)
+{
+ kmem_cache_destroy(ssh_ctrl_packet_cache);
+ ssh_ctrl_packet_cache = NULL;
+}
+
+static int ssh_ctrl_packet_alloc(struct ssh_packet **packet,
+ struct ssam_span *buffer, gfp_t flags) + struct ssam_span *buffer, gfp_t flags)
+{ +{
+ // TODO: cache packets + *packet = kmem_cache_alloc(ssh_ctrl_packet_cache, flags);
+ // - Potential problem with kmem_cache: Minimum alloc size of that is
+ // PAGE_SIZE (???), which is somewhat overkill here.
+ // - Note: Mempool always tries to allocate with alloc callback first.
+ // Buffered objects are only chosen on allocation failure.
+ //
+ // => either kmem_cache or custom, try kmem_cache first and check via
+ // /proc/slabinfo
+ //
+ // Note: kmem_cache_create needs unique name
+
+ *packet = kzalloc(sizeof(struct ssh_packet) + SSH_MSG_LEN_CTRL, flags);
+ if (!*packet) + if (!*packet)
+ return -ENOMEM; + return -ENOMEM;
+ +
+ buffer->ptr = (u8 *)(*packet + 1); + buffer->ptr = (u8 *)(*packet + 1);
+ buffer->len = SSH_MSG_LEN_CTRL; + buffer->len = SSH_MSG_LEN_CTRL;
+ +
+ trace_ssam_ctrl_packet_alloc(*packet, buffer->len);
+ return 0; + return 0;
+} +}
+ +
+static void ptl_free_ctrl_packet(struct ssh_packet *p) +static void ssh_ctrl_packet_free(struct ssh_packet *p)
+{ +{
+ // TODO: cache packets + trace_ssam_ctrl_packet_free(p);
+ + kmem_cache_free(ssh_ctrl_packet_cache, p);
+ kfree(p);
+} +}
+ +
+static const struct ssh_packet_ops ssh_ptl_ctrl_packet_ops = { +static const struct ssh_packet_ops ssh_ptl_ctrl_packet_ops = {
+ .complete = NULL, + .complete = NULL,
+ .release = ptl_free_ctrl_packet, + .release = ssh_ctrl_packet_free,
+}; +};
+ +
+ +
@ -7640,7 +7608,7 @@ index 0000000000000..4144fe0b3d192
+ struct msgbuf msgb; + struct msgbuf msgb;
+ int status; + int status;
+ +
+ status = ptl_alloc_ctrl_packet(ptl, &packet, &buf, GFP_KERNEL); + status = ssh_ctrl_packet_alloc(&packet, &buf, GFP_KERNEL);
+ if (status) { + if (status) {
+ ptl_err(ptl, "ptl: failed to allocate ACK packet\n"); + ptl_err(ptl, "ptl: failed to allocate ACK packet\n");
+ return; + return;
@ -7667,7 +7635,7 @@ index 0000000000000..4144fe0b3d192
+ struct msgbuf msgb; + struct msgbuf msgb;
+ int status; + int status;
+ +
+ status = ptl_alloc_ctrl_packet(ptl, &packet, &buf, GFP_KERNEL); + status = ssh_ctrl_packet_alloc(&packet, &buf, GFP_KERNEL);
+ if (status) { + if (status) {
+ ptl_err(ptl, "ptl: failed to allocate NAK packet\n"); + ptl_err(ptl, "ptl: failed to allocate NAK packet\n");
+ return; + return;
@ -7974,7 +7942,7 @@ index 0000000000000..4144fe0b3d192
+ +
+static inline struct device *ssh_ptl_get_device(struct ssh_ptl *ptl) +static inline struct device *ssh_ptl_get_device(struct ssh_ptl *ptl)
+{ +{
+ return &ptl->serdev->dev; + return ptl->serdev ? &ptl->serdev->dev : NULL;
+} +}
+ +
+static int ssh_ptl_init(struct ssh_ptl *ptl, struct serdev_device *serdev, +static int ssh_ptl_init(struct ssh_ptl *ptl, struct serdev_device *serdev,
@ -9346,6 +9314,11 @@ index 0000000000000..4144fe0b3d192
+ return -ENOENT; + return -ENOENT;
+} +}
+ +
+static bool ssam_nf_refcount_empty(struct ssam_nf *nf)
+{
+ return RB_EMPTY_ROOT(&nf->refcount);
+}
+
+static void ssam_nf_call(struct ssam_nf *nf, struct device *dev, u16 rqid, +static void ssam_nf_call(struct ssam_nf *nf, struct device *dev, u16 rqid,
+ struct ssam_event *event) + struct ssam_event *event)
+{ +{
@ -9414,10 +9387,17 @@ index 0000000000000..4144fe0b3d192
+ +
+ +
+struct ssam_cplt; +struct ssam_cplt;
+struct ssam_event_item;
+
+struct ssam_event_item_ops {
+ void (*free)(struct ssam_event_item *);
+};
+ +
+struct ssam_event_item { +struct ssam_event_item {
+ struct list_head node; + struct list_head node;
+ u16 rqid; + u16 rqid;
+
+ struct ssam_event_item_ops ops;
+ struct ssam_event event; // must be last + struct ssam_event event; // must be last
+}; +};
+ +
@ -9444,6 +9424,79 @@ index 0000000000000..4144fe0b3d192
+}; +};
+ +
+ +
+/**
+ * Maximum payload length for cached `ssam_event_item`s.
+ *
+ * This length has been chosen to be accomodate standard touchpad and keyboard
+ * input events. Events with larger payloads will be allocated separately.
+ */
+#define SSAM_EVENT_ITEM_CACHE_PAYLOAD_LEN 32
+
+static struct kmem_cache *ssam_event_item_cache;
+
+static int ssam_event_item_cache_init(void)
+{
+ const unsigned int size = sizeof(struct ssam_event_item)
+ + SSAM_EVENT_ITEM_CACHE_PAYLOAD_LEN;
+ const unsigned int align = __alignof__(struct ssam_event_item);
+ struct kmem_cache *cache;
+
+ cache = kmem_cache_create("ssam_event_item", size, align, 0, NULL);
+ if (!cache)
+ return -ENOMEM;
+
+ ssam_event_item_cache = cache;
+ return 0;
+}
+
+static void ssam_event_item_cache_destroy(void)
+{
+ kmem_cache_destroy(ssam_event_item_cache);
+ ssam_event_item_cache = NULL;
+}
+
+static void __ssam_event_item_free_cached(struct ssam_event_item *item)
+{
+ kmem_cache_free(ssam_event_item_cache, item);
+}
+
+static void __ssam_event_item_free_generic(struct ssam_event_item *item)
+{
+ kfree(item);
+}
+
+static inline void ssam_event_item_free(struct ssam_event_item *item)
+{
+ trace_ssam_event_item_free(item);
+ item->ops.free(item);
+}
+
+static struct ssam_event_item *ssam_event_item_alloc(size_t len, gfp_t flags)
+{
+ struct ssam_event_item *item;
+
+ if (len <= SSAM_EVENT_ITEM_CACHE_PAYLOAD_LEN) {
+ item = kmem_cache_alloc(ssam_event_item_cache, GFP_KERNEL);
+ if (!item)
+ return NULL;
+
+ item->ops.free = __ssam_event_item_free_cached;
+ } else {
+ const size_t n = sizeof(struct ssam_event_item) + len;
+ item = kzalloc(n, GFP_KERNEL);
+ if (!item)
+ return NULL;
+
+ item->ops.free = __ssam_event_item_free_generic;
+ }
+
+ item->event.length = len;
+
+ trace_ssam_event_item_alloc(item, len);
+ return item;
+}
+
+
+static void ssam_event_queue_push(struct ssam_event_queue *q, +static void ssam_event_queue_push(struct ssam_event_queue *q,
+ struct ssam_event_item *item) + struct ssam_event_item *item)
+{ +{
@ -9539,7 +9592,7 @@ index 0000000000000..4144fe0b3d192
+ return; + return;
+ +
+ ssam_nf_call(nf, dev, item->rqid, &item->event); + ssam_nf_call(nf, dev, item->rqid, &item->event);
+ kfree(item); + ssam_event_item_free(item);
+ } + }
+ +
+ if (!ssam_event_queue_is_empty(queue)) + if (!ssam_event_queue_is_empty(queue))
@ -9582,6 +9635,12 @@ index 0000000000000..4144fe0b3d192
+ +
+static void ssam_cplt_destroy(struct ssam_cplt *cplt) +static void ssam_cplt_destroy(struct ssam_cplt *cplt)
+{ +{
+ /*
+ * Note: destroy_workqueue ensures that all currently queued work will
+ * be fully completed and the workqueue drained. This means that this
+ * call will inherently also free any queued ssam_event_items, thus we
+ * don't have to take care of that here explicitly.
+ */
+ destroy_workqueue(cplt->wq); + destroy_workqueue(cplt->wq);
+ ssam_nf_destroy(&cplt->event.notif); + ssam_nf_destroy(&cplt->event.notif);
+} +}
@ -9632,7 +9691,7 @@ index 0000000000000..4144fe0b3d192
+ +
+struct device *ssam_controller_device(struct ssam_controller *c) +struct device *ssam_controller_device(struct ssam_controller *c)
+{ +{
+ return (c && c->rtl.ptl.serdev) ? &c->rtl.ptl.serdev->dev : NULL; + return ssh_rtl_get_device(&c->rtl);
+} +}
+EXPORT_SYMBOL_GPL(ssam_controller_device); +EXPORT_SYMBOL_GPL(ssam_controller_device);
+ +
@ -9644,7 +9703,7 @@ index 0000000000000..4144fe0b3d192
+ struct ssam_controller *ctrl = to_ssam_controller(rtl, rtl); + struct ssam_controller *ctrl = to_ssam_controller(rtl, rtl);
+ struct ssam_event_item *item; + struct ssam_event_item *item;
+ +
+ item = kzalloc(sizeof(struct ssam_event_item) + data->len, GFP_KERNEL); + item = ssam_event_item_alloc(data->len, GFP_KERNEL);
+ if (!item) + if (!item)
+ return; + return;
+ +
@ -9653,7 +9712,6 @@ index 0000000000000..4144fe0b3d192
+ item->event.command_id = cmd->cid; + item->event.command_id = cmd->cid;
+ item->event.instance_id = cmd->iid; + item->event.instance_id = cmd->iid;
+ item->event.channel = cmd->chn_in; + item->event.channel = cmd->chn_in;
+ item->event.length = data->len;
+ memcpy(&item->event.data[0], data->ptr, data->len); + memcpy(&item->event.data[0], data->ptr, data->len);
+ +
+ ssam_cplt_submit_event(&ctrl->cplt, item); + ssam_cplt_submit_event(&ctrl->cplt, item);
@ -9664,6 +9722,10 @@ index 0000000000000..4144fe0b3d192
+}; +};
+ +
+ +
+static bool ssam_notifier_empty(struct ssam_controller *ctrl);
+static void ssam_notifier_unregister_all(struct ssam_controller *ctrl);
+
+
+#define SSAM_SSH_DSM_REVISION 0 +#define SSAM_SSH_DSM_REVISION 0
+#define SSAM_SSH_DSM_NOTIF_D0 8 +#define SSAM_SSH_DSM_NOTIF_D0 8
+static const guid_t SSAM_SSH_DSM_UUID = GUID_INIT(0xd5e383e1, 0xd892, 0x4a76, +static const guid_t SSAM_SSH_DSM_UUID = GUID_INIT(0xd5e383e1, 0xd892, 0x4a76,
@ -9739,7 +9801,6 @@ index 0000000000000..4144fe0b3d192
+ // initialize request and packet transmission layers + // initialize request and packet transmission layers
+ status = ssh_rtl_init(&ctrl->rtl, serdev, &ssam_rtl_ops); + status = ssh_rtl_init(&ctrl->rtl, serdev, &ssam_rtl_ops);
+ if (status) { + if (status) {
+ ssam_cplt_flush(&ctrl->cplt);
+ ssam_cplt_destroy(&ctrl->cplt); + ssam_cplt_destroy(&ctrl->cplt);
+ return status; + return status;
+ } + }
@ -9785,9 +9846,22 @@ index 0000000000000..4144fe0b3d192
+ status); + status);
+ } + }
+ +
+ // flush out all currently completing requests and events + // try to flush out all currently completing requests and events
+ ssam_cplt_flush(&ctrl->cplt); + ssam_cplt_flush(&ctrl->cplt);
+ +
+ /*
+ * We expect all notifiers to have been removed by the respective client
+ * driver that set them up at this point. If this warning occurs, some
+ * client driver has not done that...
+ */
+ WARN_ON(!ssam_notifier_empty(ctrl));
+
+ /*
+ * Nevertheless, we should still take care of drivers that don't behave
+ * well. Thus disable all enabled events, unregister all notifiers.
+ */
+ ssam_notifier_unregister_all(ctrl);
+
+ // cancel rem. requests, ensure no new ones can be queued, stop threads + // cancel rem. requests, ensure no new ones can be queued, stop threads
+ ssh_rtl_tx_flush(&ctrl->rtl); + ssh_rtl_tx_flush(&ctrl->rtl);
+ ssh_rtl_shutdown(&ctrl->rtl); + ssh_rtl_shutdown(&ctrl->rtl);
@ -9801,13 +9875,12 @@ index 0000000000000..4144fe0b3d192
+ return; + return;
+ +
+ /* + /*
+ * Ensure _all_ events are completed. New ones could still have been + * Note: New events could still have been received after the previous
+ * received after the previous flush in ssam_controller_shutdown, before + * flush in ssam_controller_shutdown, before the request transport layer
+ * the request transport layer has been shut down. At this point we can + * has been shut down. At this point, after the shutdown, we can be sure
+ * be sure that no new requests will be queued for completion after this + * that no new events will be queued. The call to ssam_cplt_destroy will
+ * call. + * ensure that those remaining are being completed and freed.
+ */ + */
+ ssam_cplt_flush(&ctrl->cplt);
+ +
+ // actually free resources + // actually free resources
+ ssam_cplt_destroy(&ctrl->cplt); + ssam_cplt_destroy(&ctrl->cplt);
@ -9816,7 +9889,7 @@ index 0000000000000..4144fe0b3d192
+ smp_store_release(&ctrl->state, SSAM_CONTROLLER_UNINITIALIZED); + smp_store_release(&ctrl->state, SSAM_CONTROLLER_UNINITIALIZED);
+} +}
+ +
+static inline int ssam_controller_suspend(struct ssam_controller *ctrl) +static int ssam_controller_suspend(struct ssam_controller *ctrl)
+{ +{
+ if (smp_load_acquire(&ctrl->state) != SSAM_CONTROLLER_STARTED) + if (smp_load_acquire(&ctrl->state) != SSAM_CONTROLLER_STARTED)
+ return -EINVAL; + return -EINVAL;
@ -9826,7 +9899,7 @@ index 0000000000000..4144fe0b3d192
+ return 0; + return 0;
+} +}
+ +
+static inline int ssam_controller_resume(struct ssam_controller *ctrl) +static int ssam_controller_resume(struct ssam_controller *ctrl)
+{ +{
+ if (smp_load_acquire(&ctrl->state) != SSAM_CONTROLLER_SUSPENDED) + if (smp_load_acquire(&ctrl->state) != SSAM_CONTROLLER_SUSPENDED)
+ return -EINVAL; + return -EINVAL;
@ -10306,14 +10379,16 @@ index 0000000000000..4144fe0b3d192
+ if (!ssh_rqid_is_event(rqid)) + if (!ssh_rqid_is_event(rqid))
+ return -EINVAL; + return -EINVAL;
+ +
+ if (smp_load_acquire(&ctrl->state) != SSAM_CONTROLLER_STARTED)
+ return -ENXIO;
+
+ nf = &ctrl->cplt.event.notif; + nf = &ctrl->cplt.event.notif;
+ nf_head = &nf->head[ssh_rqid_to_event(rqid)]; + nf_head = &nf->head[ssh_rqid_to_event(rqid)];
+ +
+ mutex_lock(&nf->lock); + mutex_lock(&nf->lock);
+ +
+ if (smp_load_acquire(&ctrl->state) != SSAM_CONTROLLER_STARTED) {
+ mutex_unlock(&nf->lock);
+ return -ENXIO;
+ }
+
+ rc = ssam_nf_refcount_inc(nf, n->event.reg, n->event.id); + rc = ssam_nf_refcount_inc(nf, n->event.reg, n->event.id);
+ if (rc < 0) { + if (rc < 0) {
+ mutex_unlock(&nf->lock); + mutex_unlock(&nf->lock);
@ -10360,14 +10435,16 @@ index 0000000000000..4144fe0b3d192
+ if (!ssh_rqid_is_event(rqid)) + if (!ssh_rqid_is_event(rqid))
+ return -EINVAL; + return -EINVAL;
+ +
+ if (smp_load_acquire(&ctrl->state) != SSAM_CONTROLLER_STARTED)
+ return -ENXIO;
+
+ nf = &ctrl->cplt.event.notif; + nf = &ctrl->cplt.event.notif;
+ nf_head = &nf->head[ssh_rqid_to_event(rqid)]; + nf_head = &nf->head[ssh_rqid_to_event(rqid)];
+ +
+ mutex_lock(&nf->lock); + mutex_lock(&nf->lock);
+ +
+ if (smp_load_acquire(&ctrl->state) != SSAM_CONTROLLER_STARTED) {
+ mutex_unlock(&nf->lock);
+ return -ENXIO;
+ }
+
+ rc = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id); + rc = ssam_nf_refcount_dec(nf, n->event.reg, n->event.id);
+ if (rc < 0) { + if (rc < 0) {
+ mutex_unlock(&nf->lock); + mutex_unlock(&nf->lock);
@ -10391,6 +10468,33 @@ index 0000000000000..4144fe0b3d192
+} +}
+EXPORT_SYMBOL_GPL(ssam_notifier_unregister); +EXPORT_SYMBOL_GPL(ssam_notifier_unregister);
+ +
+static bool ssam_notifier_empty(struct ssam_controller *ctrl)
+{
+ struct ssam_nf *nf = &ctrl->cplt.event.notif;
+ bool result;
+
+ mutex_lock(&nf->lock);
+ result = ssam_nf_refcount_empty(nf);
+ mutex_unlock(&nf->lock);
+
+ return result;
+}
+
+static void ssam_notifier_unregister_all(struct ssam_controller *ctrl)
+{
+ struct ssam_nf *nf = &ctrl->cplt.event.notif;
+ struct ssam_nf_refcount_entry *pos, *n;
+
+ mutex_lock(&nf->lock);
+ rbtree_postorder_for_each_entry_safe(pos, n, &nf->refcount, node) {
+ // ignore errors, will get logged in call
+ ssam_ssh_event_disable(ctrl, pos->key.reg, pos->key.id, 0);
+ kfree(pos);
+ }
+ nf->refcount = RB_ROOT;
+ mutex_unlock(&nf->lock);
+}
+
+ +
+/* -- Wakeup IRQ. ----------------------------------------------------------- */ +/* -- Wakeup IRQ. ----------------------------------------------------------- */
+ +
@ -10433,12 +10537,24 @@ index 0000000000000..4144fe0b3d192
+ +
+static int ssam_irq_setup(struct ssam_controller *ctrl) +static int ssam_irq_setup(struct ssam_controller *ctrl)
+{ +{
+ const int irqf = IRQF_SHARED | IRQF_ONESHOT;
+ struct device *dev = ssam_controller_device(ctrl); + struct device *dev = ssam_controller_device(ctrl);
+ struct gpio_desc *gpiod; + struct gpio_desc *gpiod;
+ int irq; + int irq;
+ int status; + int status;
+ +
+ /*
+ * The actual GPIO interrupt is declared in ACPI as TRIGGER_HIGH.
+ * However, the GPIO line only gets reset by sending the GPIO callback
+ * command to SAM (or alternatively the display-on notification). As
+ * proper handling for this interrupt is not implemented yet, leaving
+ * the IRQ at TRIGGER_HIGH would cause an IRQ storm (as the callback
+ * never gets sent and thus the line line never gets reset). To avoid
+ * this, mark the IRQ as TRIGGER_RISING for now, only creating a single
+ * interrupt, and let the SAM resume callback during the controller
+ * resume process clear it.
+ */
+ const int irqf = IRQF_SHARED | IRQF_ONESHOT | IRQF_TRIGGER_RISING;
+
+ gpiod = gpiod_get(dev, "ssam_wakeup-int", GPIOD_ASIS); + gpiod = gpiod_get(dev, "ssam_wakeup-int", GPIOD_ASIS);
+ if (IS_ERR(gpiod)) + if (IS_ERR(gpiod))
+ return PTR_ERR(gpiod); + return PTR_ERR(gpiod);
@ -10855,12 +10971,35 @@ index 0000000000000..4144fe0b3d192
+ +
+static int __init surface_sam_ssh_init(void) +static int __init surface_sam_ssh_init(void)
+{ +{
+ return serdev_device_driver_register(&surface_sam_ssh); + int status;
+
+ status = ssh_ctrl_packet_cache_init();
+ if (status)
+ goto err_cpkg;
+
+ status = ssam_event_item_cache_init();
+ if (status)
+ goto err_evitem;
+
+ status = serdev_device_driver_register(&surface_sam_ssh);
+ if (status)
+ goto err_register;
+
+ return 0;
+
+err_register:
+ ssam_event_item_cache_destroy();
+err_evitem:
+ ssh_ctrl_packet_cache_destroy();
+err_cpkg:
+ return status;
+} +}
+ +
+static void __exit surface_sam_ssh_exit(void) +static void __exit surface_sam_ssh_exit(void)
+{ +{
+ serdev_device_driver_unregister(&surface_sam_ssh); + serdev_device_driver_unregister(&surface_sam_ssh);
+ ssam_event_item_cache_destroy();
+ ssh_ctrl_packet_cache_destroy();
+} +}
+ +
+/* +/*
@ -11604,10 +11743,10 @@ index 0000000000000..ba57adb2a3c9d
+#endif /* _SURFACE_SAM_SSH_H */ +#endif /* _SURFACE_SAM_SSH_H */
diff --git a/drivers/platform/x86/surface_sam/surface_sam_ssh_trace.h b/drivers/platform/x86/surface_sam/surface_sam_ssh_trace.h diff --git a/drivers/platform/x86/surface_sam/surface_sam_ssh_trace.h b/drivers/platform/x86/surface_sam/surface_sam_ssh_trace.h
new file mode 100644 new file mode 100644
index 0000000000000..4755183fa423b index 0000000000000..8ea9a2fc99d7e
--- /dev/null --- /dev/null
+++ b/drivers/platform/x86/surface_sam/surface_sam_ssh_trace.h +++ b/drivers/platform/x86/surface_sam/surface_sam_ssh_trace.h
@@ -0,0 +1,532 @@ @@ -0,0 +1,587 @@
+#undef TRACE_SYSTEM +#undef TRACE_SYSTEM
+#define TRACE_SYSTEM surface_sam_ssh +#define TRACE_SYSTEM surface_sam_ssh
+ +
@ -12078,6 +12217,55 @@ index 0000000000000..4755183fa423b
+ ) + )
+ +
+ +
+DECLARE_EVENT_CLASS(ssam_alloc_class,
+ TP_PROTO(void *ptr, size_t len),
+
+ TP_ARGS(ptr, len),
+
+ TP_STRUCT__entry(
+ __array(char, uid, SSAM_PTR_UID_LEN)
+ __field(size_t, len)
+ ),
+
+ TP_fast_assign(
+ ssam_trace_ptr_uid(ptr, __entry->uid);
+ __entry->len = len;
+ ),
+
+ TP_printk("uid=%s, len=%zu", __entry->uid, __entry->len)
+);
+
+#define DEFINE_SSAM_ALLOC_EVENT(name) \
+ DEFINE_EVENT(ssam_alloc_class, ssam_##name, \
+ TP_PROTO(void *ptr, size_t len), \
+ TP_ARGS(ptr, len) \
+ )
+
+
+DECLARE_EVENT_CLASS(ssam_free_class,
+ TP_PROTO(void *ptr),
+
+ TP_ARGS(ptr),
+
+ TP_STRUCT__entry(
+ __array(char, uid, SSAM_PTR_UID_LEN)
+ __field(size_t, len)
+ ),
+
+ TP_fast_assign(
+ ssam_trace_ptr_uid(ptr, __entry->uid);
+ ),
+
+ TP_printk("uid=%s", __entry->uid)
+);
+
+#define DEFINE_SSAM_FREE_EVENT(name) \
+ DEFINE_EVENT(ssam_free_class, ssam_##name, \
+ TP_PROTO(void *ptr), \
+ TP_ARGS(ptr) \
+ )
+
+
+DECLARE_EVENT_CLASS(ssam_generic_uint_class, +DECLARE_EVENT_CLASS(ssam_generic_uint_class,
+ TP_PROTO(const char* property, unsigned int value), + TP_PROTO(const char* property, unsigned int value),
+ +
@ -12130,6 +12318,12 @@ index 0000000000000..4755183fa423b
+DEFINE_SSAM_FRAME_EVENT(ei_rx_corrupt_data); +DEFINE_SSAM_FRAME_EVENT(ei_rx_corrupt_data);
+DEFINE_SSAM_REQUEST_EVENT(ei_rx_drop_response); +DEFINE_SSAM_REQUEST_EVENT(ei_rx_drop_response);
+ +
+DEFINE_SSAM_ALLOC_EVENT(ctrl_packet_alloc);
+DEFINE_SSAM_FREE_EVENT(ctrl_packet_free);
+
+DEFINE_SSAM_ALLOC_EVENT(event_item_alloc);
+DEFINE_SSAM_FREE_EVENT(event_item_free);
+
+#endif /* _SURFACE_SAM_SSH_TRACE_H */ +#endif /* _SURFACE_SAM_SSH_TRACE_H */
+ +
+/* This part must be outside protection */ +/* This part must be outside protection */

View file

@ -1,4 +1,4 @@
From 145e87fbe43296e4f4b5ace50f4634f7dc1e5617 Mon Sep 17 00:00:00 2001 From e297db45f20ccda2c78c52c6940f2fed262f31e6 Mon Sep 17 00:00:00 2001
From: Maximilian Luz <luzmaximilian@gmail.com> From: Maximilian Luz <luzmaximilian@gmail.com>
Date: Sat, 25 Jul 2020 17:19:53 +0200 Date: Sat, 25 Jul 2020 17:19:53 +0200
Subject: [PATCH 3/5] surface-sam-over-hid Subject: [PATCH 3/5] surface-sam-over-hid

View file

@ -1,4 +1,4 @@
From 9038ba92f1b8c0045b3bd90ec87b95c6ea6ce0a3 Mon Sep 17 00:00:00 2001 From c57872db78690f190ccbd4d47e6474c94db346d0 Mon Sep 17 00:00:00 2001
From: kitakar5525 <34676735+kitakar5525@users.noreply.github.com> From: kitakar5525 <34676735+kitakar5525@users.noreply.github.com>
Date: Thu, 20 Feb 2020 16:51:11 +0900 Date: Thu, 20 Feb 2020 16:51:11 +0900
Subject: [PATCH 4/5] wifi Subject: [PATCH 4/5] wifi

View file

@ -1,4 +1,4 @@
From 1755348b5ee91d63b397657d2de6489c465fb586 Mon Sep 17 00:00:00 2001 From 9e76df4f4c5a0e693275e49ba2eb7eb431883a63 Mon Sep 17 00:00:00 2001
From: Dorian Stoll <dorian.stoll@tmsp.io> From: Dorian Stoll <dorian.stoll@tmsp.io>
Date: Mon, 27 Jan 2020 21:16:20 +0100 Date: Mon, 27 Jan 2020 21:16:20 +0100
Subject: [PATCH 5/5] ipts Subject: [PATCH 5/5] ipts

View file

@ -39,11 +39,11 @@ sha256sums=('2c4a02d9b6fdde80330d1ee335c454449f2ad2266077c80aa5db5657a990d5f1'
'623601ed9d7879dd9dba1cd50fc8051f9db508b49b4fc0c47c5a9eb9165fc04e' '623601ed9d7879dd9dba1cd50fc8051f9db508b49b4fc0c47c5a9eb9165fc04e'
'4029e92c3bbf9a2a6fde0822be48f7ecfa061dc411859fea7ed56d94dda54ee4' '4029e92c3bbf9a2a6fde0822be48f7ecfa061dc411859fea7ed56d94dda54ee4'
'8dbaa21d2c03621b0c5d96c4fbcc7a839bea5a34a5f2279a409c3b404756e753' '8dbaa21d2c03621b0c5d96c4fbcc7a839bea5a34a5f2279a409c3b404756e753'
'094ae6976a21ae8eecc835cf8342d5c62ac54c6d3c8686bf9ba45b8c8133f802' '82e6cad7497fe6472555fa5b2ee9b4107d7443260f4641eec5e0b5c89bc4bdcd'
'd90dc7ea1d4dae35fc26466e7d029591372c050e55abb09cb600311fe5b381e4' 'f78695acef48a292c36241e943362914bff96d4834d1c68fc9738ab019302bb1'
'789c9a68eb94e1f532f77e67d2d8a9db05f7f8ba8b5f8212901acb56d5ab0965' '7848abaac0f13951827eb92146179545a0ade3dde2cc26334fecade9ea888477'
'be4777910aa70ce9e29af587f0ed7138d212c451db000dad2eba06977734c0d8' 'd77fa45c1e6932ceb402ed3b164b65e62a7013e4e6d38ad4a823b5d75e9f766b'
'27cf02268fb37ab97f20187b2e96f4b80ed89b1accc8054f9ca29a14a6c94f85') '4f1df3a09d93917eefe5e7e9f268e33f6d2dbff2170d95b9c495c0745bb8623f')
export KBUILD_BUILD_HOST=archlinux export KBUILD_BUILD_HOST=archlinux