ソースを参照

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: https://github.com/linux-surface/kernel/commit/78e06bc87506ce79ce89cccb2bf5880c6756ef72
- SAM: https://github.com/linux-surface/surface-aggregator-module/commit/b9fe8f28b70b8a399c43177629a6a73641a87808
Maximilian Luz 4 年 前
コミット
23d3bc55ce

+ 1 - 1
patches/5.7/0001-surface3-oemb.patch

@@ -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>
 Date: Tue, 18 Sep 2018 11:01:37 +0800
 Subject: [PATCH 1/5] surface3-oemb

+ 295 - 101
patches/5.7/0002-surface-sam.patch

@@ -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>
 Date: Fri, 6 Dec 2019 11:56:12 +0100
 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_vhf.c     |  429 ++
  .../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_trace.h   |  532 ++
+ .../x86/surface_sam/surface_sam_ssh_trace.h   |  587 ++
  .../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/Makefile
  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 */
 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
-index 0000000000000..4144fe0b3d192
+index 0000000000000..4551b75570f22
 --- /dev/null
 +++ 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
 +/*
 + * 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;
 +}
 +
-+static inline u16 ssh_event_to_rqid(u16 event)
-+{
-+	return event + 1u;
-+}
-+
 +static inline u16 ssh_rqid_to_event(u16 rqid)
 +{
 +	return rqid - 1u;
@@ -5779,11 +5774,6 @@ index 0000000000000..4144fe0b3d192
 +	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)
 +{
 +	return channel - 1u;
@@ -5859,31 +5849,6 @@ index 0000000000000..4144fe0b3d192
 +	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)
 +{
 +	return msgb->ptr - msgb->begin;
@@ -6157,11 +6122,6 @@ index 0000000000000..4144fe0b3d192
 +	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)
 +{
 +	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,
-+				    struct ssh_packet *packet,
-+				    const unsigned char *buf,
-+				    size_t count)
++static int ssh_ptl_write_buf(struct ssh_ptl *ptl, struct ssh_packet *packet,
++			     const unsigned char *buf, size_t count)
 +{
 +	int status;
 +
@@ -6596,7 +6554,7 @@ index 0000000000000..4144fe0b3d192
 +	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)
 +	if (!packet->data.ptr || !packet->data.len)
@@ -6622,8 +6580,8 @@ index 0000000000000..4144fe0b3d192
 +	memset(packet->data.ptr, 0xb3, packet->data.len);
 +}
 +
-+static inline void ssh_ptl_rx_inject_invalid_syn(struct ssh_ptl *ptl,
-+						 struct ssam_span *data)
++static void ssh_ptl_rx_inject_invalid_syn(struct ssh_ptl *ptl,
++					  struct ssam_span *data)
 +{
 +	struct ssam_span frame;
 +
@@ -6639,8 +6597,8 @@ index 0000000000000..4144fe0b3d192
 +	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,
-+						  struct ssam_span *frame)
++static void ssh_ptl_rx_inject_invalid_data(struct ssh_ptl *ptl,
++					   struct ssam_span *frame)
 +{
 +	size_t payload_len, message_len;
 +	struct ssh_frame *sshf;
@@ -6756,41 +6714,51 @@ index 0000000000000..4144fe0b3d192
 +}
 +
 +
-+static int ptl_alloc_ctrl_packet(struct ssh_ptl *ptl,
-+				 struct ssh_packet **packet,
-+				 struct ssam_span *buffer, gfp_t flags)
++static struct kmem_cache *ssh_ctrl_packet_cache;
++
++static int __init ssh_ctrl_packet_cache_init(void)
 +{
-+	// TODO: cache packets
-+	// - 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
++	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;
++}
 +
-+	*packet = kzalloc(sizeof(struct ssh_packet) + SSH_MSG_LEN_CTRL, flags);
++static int ssh_ctrl_packet_alloc(struct ssh_packet **packet,
++				 struct ssam_span *buffer, gfp_t flags)
++{
++	*packet = kmem_cache_alloc(ssh_ctrl_packet_cache, flags);
 +	if (!*packet)
 +		return -ENOMEM;
 +
 +	buffer->ptr = (u8 *)(*packet + 1);
 +	buffer->len = SSH_MSG_LEN_CTRL;
 +
++	trace_ssam_ctrl_packet_alloc(*packet, buffer->len);
 +	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
-+
-+	kfree(p);
++	trace_ssam_ctrl_packet_free(p);
++	kmem_cache_free(ssh_ctrl_packet_cache, p);
 +}
 +
 +static const struct ssh_packet_ops ssh_ptl_ctrl_packet_ops = {
 +	.complete = NULL,
-+	.release = ptl_free_ctrl_packet,
++	.release = ssh_ctrl_packet_free,
 +};
 +
 +
@@ -7640,7 +7608,7 @@ index 0000000000000..4144fe0b3d192
 +	struct msgbuf msgb;
 +	int status;
 +
-+	status = ptl_alloc_ctrl_packet(ptl, &packet, &buf, GFP_KERNEL);
++	status = ssh_ctrl_packet_alloc(&packet, &buf, GFP_KERNEL);
 +	if (status) {
 +		ptl_err(ptl, "ptl: failed to allocate ACK packet\n");
 +		return;
@@ -7667,7 +7635,7 @@ index 0000000000000..4144fe0b3d192
 +	struct msgbuf msgb;
 +	int status;
 +
-+	status = ptl_alloc_ctrl_packet(ptl, &packet, &buf, GFP_KERNEL);
++	status = ssh_ctrl_packet_alloc(&packet, &buf, GFP_KERNEL);
 +	if (status) {
 +		ptl_err(ptl, "ptl: failed to allocate NAK packet\n");
 +		return;
@@ -7974,7 +7942,7 @@ index 0000000000000..4144fe0b3d192
 +
 +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,
@@ -9346,6 +9314,11 @@ index 0000000000000..4144fe0b3d192
 +	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,
 +			 struct ssam_event *event)
 +{
@@ -9414,10 +9387,17 @@ index 0000000000000..4144fe0b3d192
 +
 +
 +struct ssam_cplt;
++struct ssam_event_item;
++
++struct ssam_event_item_ops {
++	void (*free)(struct ssam_event_item *);
++};
 +
 +struct ssam_event_item {
 +	struct list_head node;
 +	u16 rqid;
++
++	struct ssam_event_item_ops ops;
 +	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,
 +				  struct ssam_event_item *item)
 +{
@@ -9539,7 +9592,7 @@ index 0000000000000..4144fe0b3d192
 +			return;
 +
 +		ssam_nf_call(nf, dev, item->rqid, &item->event);
-+		kfree(item);
++		ssam_event_item_free(item);
 +	}
 +
 +	if (!ssam_event_queue_is_empty(queue))
@@ -9582,6 +9635,12 @@ index 0000000000000..4144fe0b3d192
 +
 +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);
 +	ssam_nf_destroy(&cplt->event.notif);
 +}
@@ -9632,7 +9691,7 @@ index 0000000000000..4144fe0b3d192
 +
 +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);
 +
@@ -9644,7 +9703,7 @@ index 0000000000000..4144fe0b3d192
 +	struct ssam_controller *ctrl = to_ssam_controller(rtl, rtl);
 +	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)
 +		return;
 +
@@ -9653,7 +9712,6 @@ index 0000000000000..4144fe0b3d192
 +	item->event.command_id = cmd->cid;
 +	item->event.instance_id = cmd->iid;
 +	item->event.channel = cmd->chn_in;
-+	item->event.length  = data->len;
 +	memcpy(&item->event.data[0], data->ptr, data->len);
 +
 +	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_NOTIF_D0	8
 +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
 +	status = ssh_rtl_init(&ctrl->rtl, serdev, &ssam_rtl_ops);
 +	if (status) {
-+		ssam_cplt_flush(&ctrl->cplt);
 +		ssam_cplt_destroy(&ctrl->cplt);
 +		return status;
 +	}
@@ -9785,9 +9846,22 @@ index 0000000000000..4144fe0b3d192
 +			 status);
 +	}
 +
-+	// flush out all currently completing requests and events
++	// try to flush out all currently completing requests and events
 +	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
 +	ssh_rtl_tx_flush(&ctrl->rtl);
 +	ssh_rtl_shutdown(&ctrl->rtl);
@@ -9801,13 +9875,12 @@ index 0000000000000..4144fe0b3d192
 +		return;
 +
 +	/*
-+	 * Ensure _all_ events are completed. New ones could still have been
-+	 * received after the previous flush in ssam_controller_shutdown, before
-+	 * the request transport layer has been shut down. At this point we can
-+	 * be sure that no new requests will be queued for completion after this
-+	 * call.
++	 * Note: New events could still have been received after the previous
++	 * flush in ssam_controller_shutdown, before the request transport layer
++	 * has been shut down. At this point, after the shutdown, we can be sure
++	 * that no new events will be queued. The call to ssam_cplt_destroy will
++	 * ensure that those remaining are being completed and freed.
 +	 */
-+	ssam_cplt_flush(&ctrl->cplt);
 +
 +	// actually free resources
 +	ssam_cplt_destroy(&ctrl->cplt);
@@ -9816,7 +9889,7 @@ index 0000000000000..4144fe0b3d192
 +	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)
 +		return -EINVAL;
@@ -9826,7 +9899,7 @@ index 0000000000000..4144fe0b3d192
 +	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)
 +		return -EINVAL;
@@ -10306,14 +10379,16 @@ index 0000000000000..4144fe0b3d192
 +	if (!ssh_rqid_is_event(rqid))
 +		return -EINVAL;
 +
-+	if (smp_load_acquire(&ctrl->state) != SSAM_CONTROLLER_STARTED)
-+		return -ENXIO;
-+
 +	nf = &ctrl->cplt.event.notif;
 +	nf_head = &nf->head[ssh_rqid_to_event(rqid)];
 +
 +	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);
 +	if (rc < 0) {
 +		mutex_unlock(&nf->lock);
@@ -10360,14 +10435,16 @@ index 0000000000000..4144fe0b3d192
 +	if (!ssh_rqid_is_event(rqid))
 +		return -EINVAL;
 +
-+	if (smp_load_acquire(&ctrl->state) != SSAM_CONTROLLER_STARTED)
-+		return -ENXIO;
-+
 +	nf = &ctrl->cplt.event.notif;
 +	nf_head = &nf->head[ssh_rqid_to_event(rqid)];
 +
 +	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);
 +	if (rc < 0) {
 +		mutex_unlock(&nf->lock);
@@ -10391,6 +10468,33 @@ index 0000000000000..4144fe0b3d192
 +}
 +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. ----------------------------------------------------------- */
 +
@@ -10433,12 +10537,24 @@ index 0000000000000..4144fe0b3d192
 +
 +static int ssam_irq_setup(struct ssam_controller *ctrl)
 +{
-+	const int irqf = IRQF_SHARED | IRQF_ONESHOT;
 +	struct device *dev = ssam_controller_device(ctrl);
 +	struct gpio_desc *gpiod;
 +	int irq;
 +	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);
 +	if (IS_ERR(gpiod))
 +		return PTR_ERR(gpiod);
@@ -10855,12 +10971,35 @@ index 0000000000000..4144fe0b3d192
 +
 +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)
 +{
 +	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 */
 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
-index 0000000000000..4755183fa423b
+index 0000000000000..8ea9a2fc99d7e
 --- /dev/null
 +++ b/drivers/platform/x86/surface_sam/surface_sam_ssh_trace.h
-@@ -0,0 +1,532 @@
+@@ -0,0 +1,587 @@
 +#undef TRACE_SYSTEM
 +#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,
 +	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_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 */
 +
 +/* This part must be outside protection */

+ 1 - 1
patches/5.7/0003-surface-sam-over-hid.patch

@@ -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>
 Date: Sat, 25 Jul 2020 17:19:53 +0200
 Subject: [PATCH 3/5] surface-sam-over-hid

+ 1 - 1
patches/5.7/0004-wifi.patch

@@ -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>
 Date: Thu, 20 Feb 2020 16:51:11 +0900
 Subject: [PATCH 4/5] wifi

+ 1 - 1
patches/5.7/0005-ipts.patch

@@ -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>
 Date: Mon, 27 Jan 2020 21:16:20 +0100
 Subject: [PATCH 5/5] ipts

+ 5 - 5
pkg/arch/kernel/PKGBUILD

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