diff options
-rw-r--r-- | SOURCES/steam-deck.patch | 1557 | ||||
-rw-r--r-- | SOURCES/steamdeck-oled-legion-go-bluetooth-hang.patch | 289 | ||||
-rw-r--r-- | SOURCES/steamdeck-oled-refresh-rate.patch (renamed from SOURCES/oled-deck-refresh-rate.patch) | 171 | ||||
-rw-r--r-- | SPECS/kernel.spec | 15 |
4 files changed, 479 insertions, 1553 deletions
diff --git a/SOURCES/steam-deck.patch b/SOURCES/steam-deck.patch index bbdb9ce..0630ca3 100644 --- a/SOURCES/steam-deck.patch +++ b/SOURCES/steam-deck.patch @@ -225,7 +225,7 @@ diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile index 11d076cad8a2..d03c1e1d339f 100644 --- a/drivers/hwmon/Makefile +++ b/drivers/hwmon/Makefile -@@ -199,6 +199,7 @@ +@@ -200,6 +200,7 @@ obj-$(CONFIG_SENSORS_SMSC47M1) += smsc47m1.o obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o obj-$(CONFIG_SENSORS_SPARX5) += sparx5-temp.o @@ -609,7 +609,7 @@ diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index 290186e44e6b..4d444a9e2c1f 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig -@@ -202,4 +202,11 @@ +@@ -202,4 +202,12 @@ The DHC (Digital Home Hub) RTD series SoC contains a type c module. This driver will detect the status of the type-c port. @@ -620,12 +620,13 @@ index 290186e44e6b..4d444a9e2c1f 100644 + Say Y here to enable support of USB Type C cable detection extcon + support on Steam Deck devices + ++ endif diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile index 1b390d934ca9..1c7e217f29e4 100644 --- a/drivers/extcon/Makefile +++ b/drivers/extcon/Makefile -@@ -26,3 +26,4 @@ +@@ -25,3 +25,4 @@ obj-$(CONFIG_EXTCON_SM5502) += extcon-sm5502.o obj-$(CONFIG_EXTCON_USBC_CROS_EC) += extcon-usbc-cros-ec.o obj-$(CONFIG_EXTCON_USBC_TUSB320) += extcon-usbc-tusb320.o obj-$(CONFIG_EXTCON_RTK_TYPE_C) += extcon-rtk-type-c.o @@ -975,1523 +976,89 @@ index 0e504b3c2796..a60fa7db9141 100644 NULL }; -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Vicki Pfau <vi@endrift.com> -Date: Thu, 30 Jun 2022 18:42:10 -0700 -Subject: [PATCH 01/10] USB: gadget: f_hid: Add Get-Feature report - -While the HID gadget implementation has been sufficient for devices that only -use INTERRUPT transfers, the USB HID standard includes provisions for Set- and -Get-Feature report CONTROL transfers that go over endpoint 0. These were -previously impossible with the existing implementation, and would either send -an empty reply, or stall out. +From: Matthew Schwartz <njtransit215@gmail.com> Mon Sep 17 00:00:00 2001 +From: Andrey Smirnov <andrew.smirnov@gmail.com> +Date: Mon, 20 Nov 2023 05:42:03 -0800 +Subject: [PATCH] leds-steamdeck: Add support for LED birghtness multiplier -As the feature is a standard part of USB HID, it stands to reason that devices -would use it, and that the HID gadget should support it. This patch adds -support for (polled) device-to-host Get-Feature reports through a new ioctl -interface to the hidg class dev nodes. +Add support for LED birghtness multiplier exposed via custom sysfs +attribute (led_brightness_multiplier). -Signed-off-by: Vicki Pfau <vi@endrift.com> -(cherry picked from commit 8437fa3861c7198a3e286f393c8637c4fc08d2bc) +Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> +(cherry picked from commit c4ea057992e189ec8821cde3a65e2cc0529a5088) +(cherry picked from commit e90fb9bec45c15c0c541ce60b994bab3922ddadf) Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com> --- - drivers/usb/gadget/function/f_hid.c | 121 ++++++++++++++++++++++++++-- - include/uapi/linux/usb/g_hid.h | 38 +++++++++ - include/uapi/linux/usb/gadgetfs.h | 2 +- - 3 files changed, 154 insertions(+), 7 deletions(-) - create mode 100644 include/uapi/linux/usb/g_hid.h + drivers/leds/leds-steamdeck.c | 49 +++++++++++++++++++++++++++++++++++ + 1 file changed, 49 insertions(+) -diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c -index ea85e2c701a15..6fec92b5a0bd9 100644 ---- a/drivers/usb/gadget/function/f_hid.c -+++ b/drivers/usb/gadget/function/f_hid.c -@@ -16,6 +16,7 @@ - #include <linux/wait.h> - #include <linux/sched.h> - #include <linux/usb/g_hid.h> -+#include <uapi/linux/usb/g_hid.h> - - #include "u_f.h" - #include "u_hid.h" -@@ -75,6 +76,13 @@ struct f_hidg { - wait_queue_head_t write_queue; - struct usb_request *req; - -+ /* get report */ -+ struct usb_request *get_req; -+ struct usb_hidg_report get_report; -+ spinlock_t get_spinlock; -+ bool get_pending; -+ wait_queue_head_t get_queue; -+ - struct device dev; - struct cdev cdev; - struct usb_function func; -@@ -523,6 +531,64 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, - return status; - } +diff --git a/drivers/leds/leds-steamdeck.c b/drivers/leds/leds-steamdeck.c +index 686500b8de736..ada9fffc0a420 100644 +--- a/drivers/leds/leds-steamdeck.c ++++ b/drivers/leds/leds-steamdeck.c +@@ -16,6 +16,54 @@ struct steamdeck_led { + struct led_classdev cdev; + }; -+ -+static int f_hidg_get_report(struct file *file, struct usb_hidg_report __user *buffer) ++static ssize_t led_brightness_multiplier_show(struct device *dev, ++ struct device_attribute *attr, ++ char *buf) +{ -+ struct f_hidg *hidg = file->private_data; -+ struct usb_composite_dev *cdev = hidg->func.config->cdev; -+ -+ int status = 0; -+ unsigned long flags; -+ -+ spin_lock_irqsave(&hidg->get_spinlock, flags); -+ -+#define GET_REPORT_COND (!hidg->get_pending) -+ -+ while (!GET_REPORT_COND) { -+ spin_unlock_irqrestore(&hidg->get_spinlock, flags); -+ -+ if (file->f_flags & O_NONBLOCK) -+ return -EAGAIN; -+ -+ if (wait_event_interruptible_exclusive(hidg->get_queue, -+ GET_REPORT_COND)) -+ return -ERESTARTSYS; -+ -+ spin_lock_irqsave(&hidg->get_spinlock, flags); -+ if (!hidg->get_pending) { -+ spin_unlock_irqrestore(&hidg->get_spinlock, flags); -+ return -EINVAL; -+ } -+ } -+ -+ hidg->get_pending = true; -+ spin_unlock_irqrestore(&hidg->get_spinlock, flags); -+ -+ status = copy_from_user(&hidg->get_report, buffer, -+ sizeof(struct usb_hidg_report)); -+ if (status != 0) { -+ ERROR(cdev, "copy_from_user error\n"); -+ status = -EINVAL; -+ } ++ struct led_classdev *cdev = dev_get_drvdata(dev); ++ struct steamdeck_led *sd = container_of(cdev, struct steamdeck_led, ++ cdev); ++ unsigned long long led_brightness_multiplier; + -+ spin_lock_irqsave(&hidg->get_spinlock, flags); -+ hidg->get_pending = false; -+ spin_unlock_irqrestore(&hidg->get_spinlock, flags); ++ if (ACPI_FAILURE(acpi_evaluate_integer(sd->adev->handle, ++ "GLDM", ++ NULL, ++ &led_brightness_multiplier))) ++ return -EIO; + -+ wake_up(&hidg->get_queue); -+ return status; -+} + -+static long f_hidg_ioctl(struct file *file, unsigned int code, unsigned long arg) -+{ -+ switch (code) { -+ case GADGET_HID_WRITE_GET_REPORT: -+ return f_hidg_get_report(file, (struct usb_hidg_report __user *)arg); -+ default: -+ return -ENOTTY; -+ } ++ return sprintf(buf, "%llu", led_brightness_multiplier); +} + - static __poll_t f_hidg_poll(struct file *file, poll_table *wait) - { - struct f_hidg *hidg = file->private_data; -@@ -548,6 +614,7 @@ static __poll_t f_hidg_poll(struct file *file, poll_table *wait) - #undef WRITE_COND - #undef READ_COND_SSREPORT - #undef READ_COND_INTOUT -+#undef GET_REPORT_COND - - static int f_hidg_release(struct inode *inode, struct file *fd) - { -@@ -640,6 +707,10 @@ static void hidg_ssreport_complete(struct usb_ep *ep, struct usb_request *req) - wake_up(&hidg->read_queue); - } - -+static void hidg_get_report_complete(struct usb_ep *ep, struct usb_request *req) ++static ssize_t led_brightness_multiplier_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) +{ -+} -+ - static int hidg_setup(struct usb_function *f, - const struct usb_ctrlrequest *ctrl) - { -@@ -647,6 +718,8 @@ static int hidg_setup(struct usb_function *f, - struct usb_composite_dev *cdev = f->config->cdev; - struct usb_request *req = cdev->req; - int status = 0; -+ unsigned long flags; -+ bool do_wake = false; - __u16 value, length; - - value = __le16_to_cpu(ctrl->wValue); -@@ -659,14 +732,29 @@ static int hidg_setup(struct usb_function *f, - switch ((ctrl->bRequestType << 8) | ctrl->bRequest) { - case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 - | HID_REQ_GET_REPORT): -- VDBG(cdev, "get_report\n"); -+ VDBG(cdev, "get_report | wLength=%d\n", ctrl->wLength); - -- /* send an empty report */ -- length = min_t(unsigned, length, hidg->report_length); -- memset(req->buf, 0x0, length); -+ req = hidg->get_req; -+ req->zero = 0; -+ req->length = min_t(unsigned, length, hidg->report_length); -+ status = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); -+ if (status < 0) { -+ ERROR(cdev, "usb_ep_queue error on get_report %d\n", -+ status); - -- goto respond; -- break; -+ spin_lock_irqsave(&hidg->get_spinlock, flags); -+ if (hidg->get_pending) { -+ hidg->get_pending = false; -+ do_wake = true; -+ } -+ spin_unlock_irqrestore(&hidg->get_spinlock, flags); -+ -+ if (do_wake) { -+ wake_up(&hidg->get_queue); -+ } -+ } -+ -+ return status; - - case ((USB_DIR_IN | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 - | HID_REQ_GET_PROTOCOL): -@@ -800,6 +888,14 @@ static void hidg_disable(struct usb_function *f) - - hidg->req = NULL; - spin_unlock_irqrestore(&hidg->write_spinlock, flags); -+ -+ spin_lock_irqsave(&hidg->get_spinlock, flags); -+ if (!hidg->get_pending) { -+ usb_ep_free_request(f->config->cdev->gadget->ep0, hidg->get_req); -+ hidg->get_pending = true; -+ } -+ hidg->get_req = NULL; -+ spin_unlock_irqrestore(&hidg->get_spinlock, flags); - } - - static int hidg_set_alt(struct usb_function *f, unsigned intf, unsigned alt) -@@ -908,6 +1004,7 @@ static const struct file_operations f_hidg_fops = { - .write = f_hidg_write, - .read = f_hidg_read, - .poll = f_hidg_poll, -+ .unlocked_ioctl = f_hidg_ioctl, - .llseek = noop_llseek, - }; - -@@ -918,6 +1015,14 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) - struct usb_string *us; - int status; - -+ hidg->get_req = usb_ep_alloc_request(c->cdev->gadget->ep0, GFP_ATOMIC); -+ if (!hidg->get_req) -+ return -ENOMEM; -+ hidg->get_req->buf = hidg->get_report.data; -+ hidg->get_req->zero = 0; -+ hidg->get_req->complete = hidg_get_report_complete; -+ hidg->get_req->context = hidg; -+ - /* maybe allocate device-global string IDs, and patch descriptors */ - us = usb_gstrings_attach(c->cdev, ct_func_strings, - ARRAY_SIZE(ct_func_string_defs)); -@@ -1003,8 +1108,10 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) - hidg->write_pending = 1; - hidg->req = NULL; - spin_lock_init(&hidg->read_spinlock); -+ spin_lock_init(&hidg->get_spinlock); - init_waitqueue_head(&hidg->write_queue); - init_waitqueue_head(&hidg->read_queue); -+ init_waitqueue_head(&hidg->get_queue); - INIT_LIST_HEAD(&hidg->completed_out_req); - - /* create char device */ -@@ -1021,6 +1128,8 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) - if (hidg->req != NULL) - free_ep_req(hidg->in_ep, hidg->req); - -+ usb_ep_free_request(c->cdev->gadget->ep0, hidg->get_req); -+ - return status; - } - -diff --git a/include/uapi/linux/usb/g_hid.h b/include/uapi/linux/usb/g_hid.h -new file mode 100644 -index 0000000000000..c6068b4863543 ---- /dev/null -+++ b/include/uapi/linux/usb/g_hid.h -@@ -0,0 +1,38 @@ -+/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ -+/* -+ * g_hid.h -- Header file for USB HID gadget driver -+ * -+ * Copyright (C) 2022 Valve Software -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License as published by -+ * the Free Software Foundation; either version 2 of the License, or -+ * (at your option) any later version. -+ * -+ * This program is distributed in the hope that it will be useful, -+ * but WITHOUT ANY WARRANTY; without even the implied warranty of -+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -+ * GNU General Public License for more details. -+ * -+ * You should have received a copy of the GNU General Public License -+ * along with this program; if not, write to the Free Software -+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -+ */ -+ -+#ifndef __UAPI_LINUX_USB_G_HID_H -+#define __UAPI_LINUX_USB_G_HID_H -+ -+#include <linux/types.h> -+ -+struct usb_hidg_report { -+ __u16 length; -+ __u8 data[512]; -+}; -+ -+/* The 'g' code is also used by gadgetfs and hid gadget ioctl requests. -+ * Don't add any colliding codes to either driver, and keep -+ * them in unique ranges (size 0x20 for now). -+ */ -+#define GADGET_HID_WRITE_GET_REPORT _IOW('g', 0x42, struct usb_hidg_report) -+ -+#endif /* __UAPI_LINUX_USB_G_HID_H */ -diff --git a/include/uapi/linux/usb/gadgetfs.h b/include/uapi/linux/usb/gadgetfs.h -index 835473910a498..9754822b2a409 100644 ---- a/include/uapi/linux/usb/gadgetfs.h -+++ b/include/uapi/linux/usb/gadgetfs.h -@@ -62,7 +62,7 @@ struct usb_gadgetfs_event { - }; - - --/* The 'g' code is also used by printer gadget ioctl requests. -+/* The 'g' code is also used by printer and hid gadget ioctl requests. - * Don't add any colliding codes to either driver, and keep - * them in unique ranges (size 0x20 for now). - */ --- -2.41.0 - - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Vicki Pfau <vi@endrift.com> -Date: Thu, 30 Jun 2022 18:43:10 -0700 -Subject: [PATCH 02/10] USB: gadget: f_hid: Add Set-Feature report - -While the HID gadget implementation has been sufficient for devices that only -use INTERRUPT transfers, the USB HID standard includes provisions for Set- and -Get-Feature report CONTROL transfers that go over endpoint 0. These were -previously impossible with the existing implementation, and would either send -an empty reply, or stall out. - -As the feature is a standard part of USB HID, it stands to reason that devices -would use it, and that the HID gadget should support it. This patch adds -support for host-to-device Set-Feature reports through a new ioctl -interface to the hidg class dev nodes. - -Signed-off-by: Vicki Pfau <vi@endrift.com> -(cherry picked from commit 3d82be0ec3aa3b947d9c927d7b06c433de15be8b) -Signed-off-by: Cristian Ciocaltea <cristian.ciocaltea@collabora.com> ---- - drivers/usb/gadget/function/f_hid.c | 110 ++++++++++++++++++++++++++-- - include/uapi/linux/usb/g_hid.h | 24 +----- - 2 files changed, 106 insertions(+), 28 deletions(-) - -diff --git a/drivers/usb/gadget/function/f_hid.c b/drivers/usb/gadget/function/f_hid.c -index 6fec92b5a0bd9..172cba91aded1 100644 ---- a/drivers/usb/gadget/function/f_hid.c -+++ b/drivers/usb/gadget/function/f_hid.c -@@ -76,6 +76,11 @@ struct f_hidg { - wait_queue_head_t write_queue; - struct usb_request *req; - -+ /* set report */ -+ struct list_head completed_set_req; -+ spinlock_t set_spinlock; -+ wait_queue_head_t set_queue; -+ - /* get report */ - struct usb_request *get_req; - struct usb_hidg_report get_report; -@@ -531,6 +536,54 @@ static ssize_t f_hidg_write(struct file *file, const char __user *buffer, - return status; - } - -+static int f_hidg_set_report(struct file *file, struct usb_hidg_report __user *buffer) -+{ -+ struct f_hidg *hidg = file->private_data; -+ struct f_hidg_req_list *list; -+ struct usb_request *req; -+ unsigned long flags; -+ unsigned short length; -+ int status; -+ -+ spin_lock_irqsave(&hidg->set_spinlock, flags); -+ -+#define SET_REPORT_COND (!list_empty(&hidg->completed_set_req)) -+ -+ /* wait for at least one buffer to complete */ -+ while (!SET_REPORT_COND) { -+ spin_unlock_irqrestore(&hidg->set_spinlock, flags); -+ if (file->f_flags & O_NONBLOCK) -+ return -EAGAIN; -+ -+ if (wait_event_interruptible(hidg->set_queue, SET_REPORT_COND)) -+ return -ERESTARTSYS; -+ -+ spin_lock_irqsave(&hidg->set_spinlock, flags); -+ } -+ -+ /* pick the first one */ -+ list = list_first_entry(&hidg->completed_set_req, -+ struct f_hidg_req_list, list); -+ -+ /* -+ * Remove this from list to protect it from being free() -+ * while host disables our function -+ */ -+ list_del(&list->list); -+ -+ req = list->req; -+ spin_unlock_irqrestore(&hidg->set_spinlock, flags); ++ struct led_classdev *cdev = dev_get_drvdata(dev); ++ struct steamdeck_led *sd = container_of(cdev, struct steamdeck_led, ++ cdev); ++ unsigned long value; + -+ /* copy to user outside spinlock */ -+ length = min_t(unsigned short, sizeof(buffer->data), req->actual); -+ status = copy_to_user(&buffer->length, &length, sizeof(buffer->length)); -+ if (!status) { -+ status = copy_to_user(&buffer->data, req->buf, length); -+ } -+ kfree(list); -+ free_ep_req(hidg->func.config->cdev->gadget->ep0, req); -+ return status; -+} - - static int f_hidg_get_report(struct file *file, struct usb_hidg_report __user *buffer) - { -@@ -582,6 +635,8 @@ static int f_hidg_get_report(struct file *file, struct usb_hidg_report __user *b - static long f_hidg_ioctl(struct file *file, unsigned int code, unsigned long arg) - { - switch (code) { -+ case GADGET_HID_READ_SET_REPORT: -+ return f_hidg_set_report(file, (struct usb_hidg_report __user *)arg); - case GADGET_HID_WRITE_GET_REPORT: - return f_hidg_get_report(file, (struct usb_hidg_report __user *)arg); - default: -@@ -596,6 +651,7 @@ static __poll_t f_hidg_poll(struct file *file, poll_table *wait) - - poll_wait(file, &hidg->read_queue, wait); - poll_wait(file, &hidg->write_queue, wait); -+ poll_wait(file, &hidg->set_queue, wait); - - if (WRITE_COND) - ret |= EPOLLOUT | EPOLLWRNORM; -@@ -608,12 +664,16 @@ static __poll_t f_hidg_poll(struct file *file, poll_table *wait) - ret |= EPOLLIN | EPOLLRDNORM; - } - -+ if (SET_REPORT_COND) -+ ret |= EPOLLPRI; ++ if (kstrtoul(buf, 10, &value) || value > 100) ++ return -EINVAL; + - return ret; - } - - #undef WRITE_COND - #undef READ_COND_SSREPORT - #undef READ_COND_INTOUT -+#undef SET_REPORT_COND - #undef GET_REPORT_COND - - static int f_hidg_release(struct inode *inode, struct file *fd) -@@ -658,11 +718,19 @@ static void hidg_intout_complete(struct usb_ep *ep, struct usb_request *req) - - req_list->req = req; - -- spin_lock_irqsave(&hidg->read_spinlock, flags); -- list_add_tail(&req_list->list, &hidg->completed_out_req); -- spin_unlock_irqrestore(&hidg->read_spinlock, flags); -+ if (ep == cdev->gadget->ep0) { -+ spin_lock_irqsave(&hidg->set_spinlock, flags); -+ list_add_tail(&req_list->list, &hidg->completed_set_req); -+ spin_unlock_irqrestore(&hidg->set_spinlock, flags); - -- wake_up(&hidg->read_queue); -+ wake_up(&hidg->set_queue); -+ } else { -+ spin_lock_irqsave(&hidg->read_spinlock, flags); -+ list_add_tail(&req_list->list, &hidg->completed_out_req); -+ spin_unlock_irqrestore(&hidg->read_spinlock, flags); -+ -+ wake_up(&hidg->read_queue); -+ } - break; - default: - ERROR(cdev, "Set report failed %d\n", req->status); -@@ -775,12 +843,27 @@ static int hidg_setup(struct usb_function *f, - case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 - | HID_REQ_SET_REPORT): - VDBG(cdev, "set_report | wLength=%d\n", ctrl->wLength); -- if (hidg->use_out_ep) -+ if (!hidg->use_out_ep) { -+ req->complete = hidg_ssreport_complete; -+ req->context = hidg; -+ goto respond; -+ } -+ if (!length) - goto stall; -- req->complete = hidg_ssreport_complete; -+ req = alloc_ep_req(cdev->gadget->ep0, GFP_ATOMIC); -+ if (!req) -+ return -ENOMEM; -+ req->complete = hidg_intout_complete; - req->context = hidg; -- goto respond; -- break; -+ req->zero = 0; -+ req->length = length; -+ status = usb_ep_queue(cdev->gadget->ep0, req, GFP_ATOMIC); -+ if (status < 0) { -+ ERROR(cdev, "usb_ep_queue error on set_report %d\n", status); -+ free_ep_req(cdev->gadget->ep0, req); -+ } + -+ return status; - - case ((USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE) << 8 - | HID_REQ_SET_PROTOCOL): -@@ -880,6 +963,14 @@ static void hidg_disable(struct usb_function *f) - spin_unlock_irqrestore(&hidg->read_spinlock, flags); - } - -+ spin_lock_irqsave(&hidg->set_spinlock, flags); -+ list_for_each_entry_safe(list, next, &hidg->completed_set_req, list) { -+ free_ep_req(f->config->cdev->gadget->ep0, list->req); -+ list_del(&list->list); -+ kfree(list); -+ } -+ spin_unlock_irqrestore(&hidg->set_spinlock, flags); -+ - spin_lock_irqsave(&hidg->write_spinlock, flags); - if (!hidg->write_pending) { - free_ep_req(hidg->in_ep, hidg->req); -@@ -1108,11 +1199,14 @@ static int hidg_bind(struct usb_configuration *c, struct usb_function *f) - hidg->write_pending = 1; - hidg->req = NULL; - spin_lock_init(&hidg->read_spinlock); -+ spin_lock_init(&hidg->set_spinlock); - spin_lock_init(&hidg->get_spinlock); - init_waitqueue_head(&hidg->write_queue); - init_waitqueue_head(&hidg->read_queue); -+ init_waitqueue_head(&hidg->set_queue); - init_waitqueue_head(&hidg->get_queue); - INIT_LIST_HEAD(&hidg->completed_out_req); -+ INIT_LIST_HEAD(&hidg->completed_set_req); - - /* create char device */ - cdev_init(&hidg->cdev, &f_hidg_fops); -diff --git a/include/uapi/linux/usb/g_hid.h b/include/uapi/linux/usb/g_hid.h -index c6068b4863543..54814c2c68d60 100644 ---- a/include/uapi/linux/usb/g_hid.h -+++ b/include/uapi/linux/usb/g_hid.h -@@ -1,38 +1,22 @@ - /* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */ --/* -- * g_hid.h -- Header file for USB HID gadget driver -- * -- * Copyright (C) 2022 Valve Software -- * -- * This program is free software; you can redistribute it and/or modify -- * it under the terms of the GNU General Public License as published by -- * the Free Software Foundation; either version 2 of the License, or -- * (at your option) any later version. -- * -- * This program is distributed in the hope that it will be useful, -- * but WITHOUT ANY WARRANTY; without even the implied warranty of -- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -- * GNU General Public License for more details. -- * -- * You should have received a copy of the GNU General Public License -- * along with this program; if not, write to the Free Software -- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA -- */ - - #ifndef __UAPI_LINUX_USB_G_HID_H - #define __UAPI_LINUX_USB_G_HID_H - - #include <linux/types.h> - -+#define HIDG_REPORT_SIZE_MAX 64 ++ if (ACPI_FAILURE(acpi_execute_simple_method(sd->adev->handle, ++ "SLDM", value))) ++ return -EIO; + - struct usb_hidg_report { - __u16 length; -- __u8 data[512]; -+ __u8 data[HIDG_REPORT_SIZE_MAX]; - }; - - /* The 'g' code is also used by gadgetfs and hid gadget ioctl requests. - * Don't add any colliding codes to either driver, and keep - * them in unique ranges (size 0x20 for now). - */ -+#define GADGET_HID_READ_SET_REPORT _IOR('g', 0x41, struct usb_hidg_report) - #define GADGET_HID_WRITE_GET_REPORT _IOW('g', 0x42, struct usb_hidg_report) - - #endif /* __UAPI_LINUX_USB_G_HID_H */ --- -2.41.0 - - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Vicki Pfau <vi@endrift.com> -Date: Tue, 29 Nov 2022 18:32:58 -0800 -Subject: [PATCH 03/10] HID: hid-steam: Update list of identifiers from SDL - -SDL includes a list of settings (registers), reports (cmds), and various other -identifiers that were provided by Valve. This commit imports a significant -chunk of that list as well as updating the guessed names and replacing a -handful of magic constants. It also replaces bitmask definitions that used hex -with the BIT macro. - -Signed-off-by: Vicki Pfau <vi@endrift.com> ---- - drivers/hid/hid-steam.c | 156 +++++++++++++++++++++++++++++++--------- - 1 file changed, 121 insertions(+), 35 deletions(-) - -diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c -index b110818fc9458..39a9bf3b7f77d 100644 ---- a/drivers/hid/hid-steam.c -+++ b/drivers/hid/hid-steam.c -@@ -71,7 +71,7 @@ static LIST_HEAD(steam_devices); - - /* - * Commands that can be sent in a feature report. -- * Thanks to Valve for some valuable hints. -+ * Thanks to Valve and SDL for some valuable hints. - */ - #define STEAM_CMD_SET_MAPPINGS 0x80 - #define STEAM_CMD_CLEAR_MAPPINGS 0x81 -@@ -80,27 +80,98 @@ static LIST_HEAD(steam_devices); - #define STEAM_CMD_GET_ATTRIB_LABEL 0x84 - #define STEAM_CMD_DEFAULT_MAPPINGS 0x85 - #define STEAM_CMD_FACTORY_RESET 0x86 --#define STEAM_CMD_WRITE_REGISTER 0x87 -+#define STEAM_CMD_SET_REGISTER 0x87 - #define STEAM_CMD_CLEAR_REGISTER 0x88 --#define STEAM_CMD_READ_REGISTER 0x89 -+#define STEAM_CMD_GET_REGISTER 0x89 - #define STEAM_CMD_GET_REGISTER_LABEL 0x8a - #define STEAM_CMD_GET_REGISTER_MAX 0x8b - #define STEAM_CMD_GET_REGISTER_DEFAULT 0x8c - #define STEAM_CMD_SET_MODE 0x8d --#define STEAM_CMD_DEFAULT_MOUSE 0x8e --#define STEAM_CMD_FORCEFEEDBAK 0x8f --#define STEAM_CMD_REQUEST_COMM_STATUS 0xb4 --#define STEAM_CMD_GET_SERIAL 0xae -+#define STEAM_CMD_DEFAULT_REGISTER 0x8e -+#define STEAM_CMD_HAPTIC_PULSE 0x8f -+#define STEAM_CMD_TURN_OFF_CONTROLLER 0x9f -+#define STEAM_CMD_GET_DEVICE_IFNO 0xa1 -+#define STEAM_CMD_CALIBRATE_TRACKPADS 0xa7 -+#define STEAM_CMD_SET_SERIAL 0xa9 -+#define STEAM_CMD_GET_TRACKPAD_CALIB 0xaa -+#define STEAM_CMD_GET_TRACKPAD_FACTORY_CALIB 0xab -+#define STEAM_CMD_GET_TRACKPAD_RAW_DATA 0xac -+#define STEAM_CMD_ENABLE_PAIRING 0xad -+#define STEAM_CMD_GET_STRING_ATTRIB 0xae -+#define STEAM_CMD_RADIO_ERASE_RECORDS 0xaf -+#define STEAM_CMD_RADIO_WRITE_RECORD 0xb0 -+#define STEAM_CMD_SET_DONGLE_SETTING 0xb1 -+#define STEAM_CMD_DONGLE_DISCONNECT_DEV 0xb2 -+#define STEAM_CMD_DONGLE_COMMIT_DEV 0xb3 -+#define STEAM_CMD_DONGLE_GET_STATE 0xb4 -+#define STEAM_CMD_CALIBRATE_GYRO 0xb5 -+#define STEAM_CMD_PLAY_AUDIO 0xb6 -+#define STEAM_CMD_AUDIO_UPDATE_START 0xb7 -+#define STEAM_CMD_AUDIO_UPDATE_DATA 0xb8 -+#define STEAM_CMD_AUDIO_UPDATE_COMPLETE 0xb9 -+#define STEAM_CMD_GET_CHIPID 0xba -+#define STEAM_CMD_CALIBRATE_JOYSTICK 0xbf -+#define STEAM_CMD_CALIBRATE_TRIGGERS 0xc0 -+#define STEAM_CMD_SET_AUDIO_MAPPING 0xc1 -+#define STEAM_CMD_CHECK_GYRO_FW_LOAD 0xc2 -+#define STEAM_CMD_CALIBRATE_ANALOG 0xc3 -+#define STEAM_CMD_DONGLE_GET_CONN_SLOTS 0xc4 -+#define STEAM_CMD_HAPTIC_CMD 0xea - #define STEAM_CMD_HAPTIC_RUMBLE 0xeb - - /* Some useful register ids */ --#define STEAM_REG_LPAD_MODE 0x07 --#define STEAM_REG_RPAD_MODE 0x08 --#define STEAM_REG_RPAD_MARGIN 0x18 --#define STEAM_REG_LED 0x2d --#define STEAM_REG_GYRO_MODE 0x30 --#define STEAM_REG_LPAD_CLICK_PRESSURE 0x34 --#define STEAM_REG_RPAD_CLICK_PRESSURE 0x35 -+#define STEAM_REG_MOUSE_SENSITIVITY 0x00 -+#define STEAM_REG_MOUSE_ACCELERATION 0x01 -+#define STEAM_REG_TRACKBALL_ROTATION_ANGLE 0x02 -+#define STEAM_REG_HAPTIC_INTENSITY 0x03 -+#define STEAM_REG_LEFT_GAMEPAD_STICK_ENABLED 0x04 -+#define STEAM_REG_RIGHT_GAMEPAD_STICK_ENABLED 0x05 -+#define STEAM_REG_USB_DEBUG_MODE 0x06 -+#define STEAM_REG_LEFT_TRACKPAD_MODE 0x07 -+#define STEAM_REG_RIGHT_TRACKPAD_MODE 0x08 -+#define STEAM_REG_MOUSE_POINTER_ENABLED 0x09 -+#define STEAM_REG_DPAD_DEADZONE 0x0a -+#define STEAM_REG_MINIMUM_MOMENTUM_VEL 0x0b -+#define STEAM_REG_MOMENTUM_DECAY_AMOUNT 0x0c -+#define STEAM_REG_PAD_REL_MODE_TICKS_PER_PIXEL 0x0d -+#define STEAM_REG_HAPTIC_INCREMENT 0x0e -+#define STEAM_REG_DPAD_ANGLE_SIN 0x0f -+#define STEAM_REG_DPAD_ANGLE_COS 0x10 -+#define STEAM_REG_MOMENTUM_VERTICAL_DIVISOR 0x11 -+#define STEAM_REG_MOMENTUM_MAXIMUM_VELOCITY 0x12 -+#define STEAM_REG_TRACKPAD_Z_ON 0x13 -+#define STEAM_REG_TRACKPAD_Z_OFF 0x14 -+#define STEAM_REG_SENSITIVY_SCALE_AMOUNT 0x15 -+#define STEAM_REG_LEFT_TRACKPAD_SECONDARY_MODE 0x16 -+#define STEAM_REG_RIGHT_TRACKPAD_SECONDARY_MODE 0x17 -+#define STEAM_REG_SMOOTH_ABSOLUTE_MOUSE 0x18 -+#define STEAM_REG_STEAMBUTTON_POWEROFF_TIME 0x19 -+#define STEAM_REG_TRACKPAD_OUTER_RADIUS 0x1b -+#define STEAM_REG_TRACKPAD_Z_ON_LEFT 0x1c -+#define STEAM_REG_TRACKPAD_Z_OFF_LEFT 0x1d -+#define STEAM_REG_TRACKPAD_OUTER_SPIN_VEL 0x1e -+#define STEAM_REG_TRACKPAD_OUTER_SPIN_RADIUS 0x1f -+#define STEAM_REG_TRACKPAD_OUTER_SPIN_HORIZONTAL_ONLY 0x20 -+#define STEAM_REG_TRACKPAD_RELATIVE_MODE_DEADZONE 0x21 -+#define STEAM_REG_TRACKPAD_RELATIVE_MODE_MAX_VEL 0x22 -+#define STEAM_REG_TRACKPAD_RELATIVE_MODE_INVERT_Y 0x23 -+#define STEAM_REG_TRACKPAD_DOUBLE_TAP_BEEP_ENABLED 0x24 -+#define STEAM_REG_TRACKPAD_DOUBLE_TAP_BEEP_PERIOD 0x25 -+#define STEAM_REG_TRACKPAD_DOUBLE_TAP_BEEP_COUNT 0x26 -+#define STEAM_REG_TRACKPAD_OUTER_RADIUS_RELEASE_ON_TRANSITION 0x27 -+#define STEAM_REG_RADIAL_MODE_ANGLE 0x28 -+#define STEAM_REG_HAPTIC_INTENSITY_MOUSE_MODE 0x29 -+#define STEAM_REG_LEFT_DPAD_REQUIRES_CLICK 0x2a -+#define STEAM_REG_RIGHT_DPAD_REQUIRES_CLICK 0x2b -+#define STEAM_REG_LED_BASELINE_BRIGHTNESS 0x2c -+#define STEAM_REG_LED_USER_BRIGHTNESS 0x2d -+#define STEAM_REG_ENABLE_RAW_JOYSTICK 0x2e -+#define STEAM_REG_ENABLE_FAST_SCAN 0x2f -+#define STEAM_REG_GYRO_MODE 0x30 -+#define STEAM_REG_WIRELESS_PACKET_VERSION 0x31 -+#define STEAM_REG_SLEEP_INACTIVITY_TIMEOUT 0x32 -+#define STEAM_REG_LEFT_TRACKPAD_CLICK_PRESSURE 0x34 -+#define STEAM_REG_RIGHT_TRACKPAD_CLICK_PRESSURE 0x35 - - /* Raw event identifiers */ - #define STEAM_EV_INPUT_DATA 0x01 -@@ -108,13 +179,28 @@ static LIST_HEAD(steam_devices); - #define STEAM_EV_BATTERY 0x04 - #define STEAM_EV_DECK_INPUT_DATA 0x09 - -+/* String attribute idenitifiers */ -+#define STEAM_ATTRIB_STR_BOARD_SERIAL 0x00 -+#define STEAM_ATTRIB_STR_UNIT_SERIAL 0x01 -+ - /* Values for GYRO_MODE (bitmask) */ --#define STEAM_GYRO_MODE_OFF 0x0000 --#define STEAM_GYRO_MODE_STEERING 0x0001 --#define STEAM_GYRO_MODE_TILT 0x0002 --#define STEAM_GYRO_MODE_SEND_ORIENTATION 0x0004 --#define STEAM_GYRO_MODE_SEND_RAW_ACCEL 0x0008 --#define STEAM_GYRO_MODE_SEND_RAW_GYRO 0x0010 -+#define STEAM_GYRO_MODE_OFF 0 -+#define STEAM_GYRO_MODE_STEERING BIT(0) -+#define STEAM_GYRO_MODE_TILT BIT(1) -+#define STEAM_GYRO_MODE_SEND_ORIENTATION BIT(2) -+#define STEAM_GYRO_MODE_SEND_RAW_ACCEL BIT(3) -+#define STEAM_GYRO_MODE_SEND_RAW_GYRO BIT(4) -+ -+/* Trackpad modes */ -+#define STEAM_TRACKPAD_ABSOLUTE_MOUSE 0x00 -+#define STEAM_TRACKPAD_RELATIVE_MOUSE 0x01 -+#define STEAM_TRACKPAD_DPAD_FOUR_WAY_DISCRETE 0x02 -+#define STEAM_TRACKPAD_DPAD_FOUR_WAY_OVERLAP 0x03 -+#define STEAM_TRACKPAD_DPAD_EIGHT_WAY 0x04 -+#define STEAM_TRACKPAD_RADIAL_MODE 0x05 -+#define STEAM_TRACKPAD_ABSOLUTE_DPAD 0x06 -+#define STEAM_TRACKPAD_NONE 0x07 -+#define STEAM_TRACKPAD_GESTURE_KEYBOARD 0x08 - - /* Other random constants */ - #define STEAM_SERIAL_LEN 10 -@@ -232,7 +318,7 @@ static int steam_write_registers(struct steam_device *steam, - /* Send: 0x87 len (reg valLo valHi)* */ - u8 reg; - u16 val; -- u8 cmd[64] = {STEAM_CMD_WRITE_REGISTER, 0x00}; -+ u8 cmd[64] = {STEAM_CMD_SET_REGISTER, 0x00}; - int ret; - va_list args; - -@@ -268,7 +354,7 @@ static int steam_get_serial(struct steam_device *steam) - * Recv: 0xae 0x15 0x01 serialnumber (10 chars) - */ - int ret; -- u8 cmd[] = {STEAM_CMD_GET_SERIAL, 0x15, 0x01}; -+ u8 cmd[] = {STEAM_CMD_GET_STRING_ATTRIB, 0x15, STEAM_ATTRIB_STR_UNIT_SERIAL}; - u8 reply[3 + STEAM_SERIAL_LEN + 1]; - - ret = steam_send_report(steam, cmd, sizeof(cmd)); -@@ -277,7 +363,7 @@ static int steam_get_serial(struct steam_device *steam) - ret = steam_recv_report(steam, reply, sizeof(reply)); - if (ret < 0) - return ret; -- if (reply[0] != 0xae || reply[1] != 0x15 || reply[2] != 0x01) -+ if (reply[0] != 0xae || reply[1] != 0x15 || reply[2] != STEAM_ATTRIB_STR_UNIT_SERIAL) - return -EIO; - reply[3 + STEAM_SERIAL_LEN] = 0; - strscpy(steam->serial_no, reply + 3, sizeof(steam->serial_no)); -@@ -291,7 +377,7 @@ static int steam_get_serial(struct steam_device *steam) - */ - static inline int steam_request_conn_status(struct steam_device *steam) - { -- return steam_send_report_byte(steam, STEAM_CMD_REQUEST_COMM_STATUS); -+ return steam_send_report_byte(steam, STEAM_CMD_DONGLE_GET_STATE); - } - - static inline int steam_haptic_rumble(struct steam_device *steam, -@@ -339,9 +425,9 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) - /* enable esc, enter, cursors */ - steam_send_report_byte(steam, STEAM_CMD_DEFAULT_MAPPINGS); - /* enable mouse */ -- steam_send_report_byte(steam, STEAM_CMD_DEFAULT_MOUSE); -+ steam_send_report_byte(steam, STEAM_CMD_DEFAULT_REGISTER); - steam_write_registers(steam, -- STEAM_REG_RPAD_MARGIN, 0x01, /* enable margin */ -+ STEAM_REG_SMOOTH_ABSOLUTE_MOUSE, 0x01, /* enable smooth */ - 0); - - cancel_delayed_work_sync(&steam->heartbeat); -@@ -351,11 +437,11 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) - - if (steam->quirks & STEAM_QUIRK_DECK) { - steam_write_registers(steam, -- STEAM_REG_RPAD_MARGIN, 0x00, /* disable margin */ -- STEAM_REG_LPAD_MODE, 0x07, /* disable mouse */ -- STEAM_REG_RPAD_MODE, 0x07, /* disable mouse */ -- STEAM_REG_LPAD_CLICK_PRESSURE, 0xFFFF, /* disable clicky pad */ -- STEAM_REG_RPAD_CLICK_PRESSURE, 0xFFFF, /* disable clicky pad */ -+ STEAM_REG_SMOOTH_ABSOLUTE_MOUSE, 0x00, /* disable smooth */ -+ STEAM_REG_LEFT_TRACKPAD_MODE, STEAM_TRACKPAD_NONE, /* disable mouse */ -+ STEAM_REG_RIGHT_TRACKPAD_MODE, STEAM_TRACKPAD_NONE, /* disable mouse */ -+ STEAM_REG_LEFT_TRACKPAD_CLICK_PRESSURE, 0xFFFF, /* disable clicky pad */ -+ STEAM_REG_RIGHT_TRACKPAD_CLICK_PRESSURE, 0xFFFF, /* disable clicky pad */ - 0); - /* - * The Steam Deck has a watchdog that automatically enables -@@ -365,9 +451,9 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) - schedule_delayed_work(&steam->heartbeat, 5 * HZ); - } else { - steam_write_registers(steam, -- STEAM_REG_RPAD_MARGIN, 0x00, /* disable margin */ -- STEAM_REG_LPAD_MODE, 0x07, /* disable mouse */ -- STEAM_REG_RPAD_MODE, 0x07, /* disable mouse */ -+ STEAM_REG_SMOOTH_ABSOLUTE_MOUSE, 0x00, /* disable smooth */ -+ STEAM_REG_LEFT_TRACKPAD_MODE, STEAM_TRACKPAD_NONE, /* disable mouse */ -+ STEAM_REG_RIGHT_TRACKPAD_MODE, STEAM_TRACKPAD_NONE, /* disable mouse */ - 0); - } - } -@@ -747,7 +833,7 @@ static void steam_lizard_mode_heartbeat(struct work_struct *work) - if (!steam->client_opened && steam->client_hdev) { - steam_send_report_byte(steam, STEAM_CMD_CLEAR_MAPPINGS); - steam_write_registers(steam, -- STEAM_REG_RPAD_MODE, 0x07, /* disable mouse */ -+ STEAM_REG_RIGHT_TRACKPAD_MODE, STEAM_TRACKPAD_NONE, /* disable mouse */ - 0); - schedule_delayed_work(&steam->heartbeat, 5 * HZ); - } --- -2.41.0 - - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Vicki Pfau <vi@endrift.com> -Date: Wed, 16 Nov 2022 19:54:26 -0800 -Subject: [PATCH 04/10] HID: hid-steam: Add gamepad-only mode switched to by - holding options - -Signed-off-by: Vicki Pfau <vi@endrift.com> ---- - drivers/hid/hid-steam.c | 72 +++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 72 insertions(+) - -diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c -index 39a9bf3b7f77d..0620046b142ef 100644 ---- a/drivers/hid/hid-steam.c -+++ b/drivers/hid/hid-steam.c -@@ -202,6 +202,11 @@ static LIST_HEAD(steam_devices); - #define STEAM_TRACKPAD_NONE 0x07 - #define STEAM_TRACKPAD_GESTURE_KEYBOARD 0x08 - -+/* Pad identifiers for the deck */ -+#define STEAM_PAD_LEFT 0 -+#define STEAM_PAD_RIGHT 1 -+#define STEAM_PAD_BOTH 2 + - /* Other random constants */ - #define STEAM_SERIAL_LEN 10 - -@@ -221,6 +226,9 @@ struct steam_device { - u8 battery_charge; - u16 voltage; - struct delayed_work heartbeat; -+ struct delayed_work mode_switch; -+ bool did_mode_switch; -+ bool gamepad_mode; - struct work_struct rumble_work; - u16 rumble_left; - u16 rumble_right; -@@ -380,6 +388,33 @@ static inline int steam_request_conn_status(struct steam_device *steam) - return steam_send_report_byte(steam, STEAM_CMD_DONGLE_GET_STATE); - } - -+/* -+ * Send a haptic pulse to the trackpads -+ * Duration and interval are measured in microseconds, count is the number -+ * of pulses to send for duration time with interval microseconds between them -+ * and gain is measured in decibels, ranging from -24 to +6 -+ */ -+static inline int steam_haptic_pulse(struct steam_device *steam, u8 pad, -+ u16 duration, u16 interval, u16 count, u8 gain) -+{ -+ u8 report[10] = {STEAM_CMD_HAPTIC_PULSE, 8}; -+ -+ /* Left and right are swapped on this report for legacy reasons */ -+ if (pad < STEAM_PAD_BOTH) -+ pad ^= 1; -+ -+ report[2] = pad; -+ report[3] = duration & 0xFF; -+ report[4] = duration >> 8; -+ report[5] = interval & 0xFF; -+ report[6] = interval >> 8; -+ report[7] = count & 0xFF; -+ report[8] = count >> 8; -+ report[9] = gain; -+ -+ return steam_send_report(steam, report, sizeof(report)); ++ return count; +} + - static inline int steam_haptic_rumble(struct steam_device *steam, - u16 intensity, u16 left_speed, u16 right_speed, - u8 left_gain, u8 right_gain) -@@ -421,6 +456,9 @@ static int steam_play_effect(struct input_dev *dev, void *data, - - static void steam_set_lizard_mode(struct steam_device *steam, bool enable) - { -+ if (steam->gamepad_mode) -+ enable = false; -+ - if (enable) { - /* enable esc, enter, cursors */ - steam_send_report_byte(steam, STEAM_CMD_DEFAULT_MAPPINGS); -@@ -805,6 +843,29 @@ static void steam_work_connect_cb(struct work_struct *work) - } - } - -+static void steam_mode_switch_cb(struct work_struct *work) -+{ -+ struct steam_device *steam = container_of(to_delayed_work(work), -+ struct steam_device, mode_switch); -+ steam->gamepad_mode = !steam->gamepad_mode; -+ if (!lizard_mode) -+ return; ++static DEVICE_ATTR_RW(led_brightness_multiplier); + -+ mutex_lock(&steam->mutex); -+ if (steam->gamepad_mode) -+ steam_set_lizard_mode(steam, false); -+ else if (!steam->client_opened) -+ steam_set_lizard_mode(steam, lizard_mode); -+ mutex_unlock(&steam->mutex); -+ -+ steam_haptic_pulse(steam, STEAM_PAD_RIGHT, 0x190, 0, 1, 0); -+ if (steam->gamepad_mode) { -+ steam_haptic_pulse(steam, STEAM_PAD_LEFT, 0x14D, 0x14D, 0x2D, 0); -+ } else { -+ steam_haptic_pulse(steam, STEAM_PAD_LEFT, 0x1F4, 0x1F4, 0x1E, 0); -+ } -+} ++static struct attribute *steamdeck_led_attrs[] = { ++ &dev_attr_led_brightness_multiplier.attr, ++ NULL ++}; ++ATTRIBUTE_GROUPS(steamdeck_led); + - static bool steam_is_valve_interface(struct hid_device *hdev) - { - struct hid_report_enum *rep_enum; -@@ -977,6 +1038,7 @@ static int steam_probe(struct hid_device *hdev, - mutex_init(&steam->mutex); - steam->quirks = id->driver_data; - INIT_WORK(&steam->work_connect, steam_work_connect_cb); -+ INIT_DELAYED_WORK(&steam->mode_switch, steam_mode_switch_cb); - INIT_LIST_HEAD(&steam->list); - INIT_DEFERRABLE_WORK(&steam->heartbeat, steam_lizard_mode_heartbeat); - INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb); -@@ -1036,6 +1098,7 @@ static int steam_probe(struct hid_device *hdev, - client_hdev_fail: - cancel_work_sync(&steam->work_connect); - cancel_delayed_work_sync(&steam->heartbeat); -+ cancel_delayed_work_sync(&steam->mode_switch); - cancel_work_sync(&steam->rumble_work); - steam_alloc_fail: - hid_err(hdev, "%s: failed with error %d\n", -@@ -1059,6 +1122,7 @@ static void steam_remove(struct hid_device *hdev) - cancel_delayed_work_sync(&steam->heartbeat); - mutex_unlock(&steam->mutex); - cancel_work_sync(&steam->work_connect); -+ cancel_delayed_work_sync(&steam->mode_switch); - if (steam->quirks & STEAM_QUIRK_WIRELESS) { - hid_info(hdev, "Steam wireless receiver disconnected"); - } -@@ -1393,6 +1457,14 @@ static void steam_do_deck_input_event(struct steam_device *steam, - input_event(input, EV_KEY, BTN_BASE, !!(b14 & BIT(2))); - - input_sync(input); -+ -+ if (!(b9 & BIT(6)) && steam->did_mode_switch) { -+ steam->did_mode_switch = false; -+ cancel_delayed_work_sync(&steam->mode_switch); -+ } else if (!steam->client_opened && (b9 & BIT(6)) && !steam->did_mode_switch) { -+ steam->did_mode_switch = true; -+ schedule_delayed_work(&steam->mode_switch, 45 * HZ / 100); -+ } - } - - /* --- -2.41.0 - - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Vicki Pfau <vi@endrift.com> -Date: Mon, 8 May 2023 20:24:56 -0700 -Subject: [PATCH 05/10] HID: hid-steam: Clean up locking - -This cleans up the locking logic so that the spinlock is consistently used for -access to a small handful of struct variables, and the mutex is exclusively and -consistently used for ensuring that mutliple threads aren't trying to -send/receive reports at the same time. Previously, only some report -transactions were guarded by this mutex, potentially breaking atomicity. The -mutex has been renamed to reflect this usage. - -Signed-off-by: Vicki Pfau <vi@endrift.com> ---- - drivers/hid/hid-steam.c | 148 ++++++++++++++++++++++++---------------- - 1 file changed, 90 insertions(+), 58 deletions(-) - -diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c -index 0620046b142ef..845ca71b8bd3a 100644 ---- a/drivers/hid/hid-steam.c -+++ b/drivers/hid/hid-steam.c -@@ -214,7 +214,7 @@ struct steam_device { - struct list_head list; - spinlock_t lock; - struct hid_device *hdev, *client_hdev; -- struct mutex mutex; -+ struct mutex report_mutex; - bool client_opened; - struct input_dev __rcu *input; - unsigned long quirks; -@@ -361,21 +361,26 @@ static int steam_get_serial(struct steam_device *steam) - * Send: 0xae 0x15 0x01 - * Recv: 0xae 0x15 0x01 serialnumber (10 chars) - */ -- int ret; -+ int ret = 0; - u8 cmd[] = {STEAM_CMD_GET_STRING_ATTRIB, 0x15, STEAM_ATTRIB_STR_UNIT_SERIAL}; - u8 reply[3 + STEAM_SERIAL_LEN + 1]; - -+ mutex_lock(&steam->report_mutex); - ret = steam_send_report(steam, cmd, sizeof(cmd)); - if (ret < 0) -- return ret; -+ goto out; - ret = steam_recv_report(steam, reply, sizeof(reply)); - if (ret < 0) -- return ret; -- if (reply[0] != 0xae || reply[1] != 0x15 || reply[2] != STEAM_ATTRIB_STR_UNIT_SERIAL) -- return -EIO; -+ goto out; -+ if (reply[0] != 0xae || reply[1] != 0x15 || reply[2] != STEAM_ATTRIB_STR_UNIT_SERIAL) { -+ ret = -EIO; -+ goto out; -+ } - reply[3 + STEAM_SERIAL_LEN] = 0; - strscpy(steam->serial_no, reply + 3, sizeof(steam->serial_no)); -- return 0; -+out: -+ mutex_unlock(&steam->report_mutex); -+ return ret; - } - - /* -@@ -385,7 +390,11 @@ static int steam_get_serial(struct steam_device *steam) - */ - static inline int steam_request_conn_status(struct steam_device *steam) - { -- return steam_send_report_byte(steam, STEAM_CMD_DONGLE_GET_STATE); -+ int ret; -+ mutex_lock(&steam->report_mutex); -+ ret = steam_send_report_byte(steam, STEAM_CMD_DONGLE_GET_STATE); -+ mutex_unlock(&steam->report_mutex); -+ return ret; - } - - /* -@@ -397,6 +406,7 @@ static inline int steam_request_conn_status(struct steam_device *steam) - static inline int steam_haptic_pulse(struct steam_device *steam, u8 pad, - u16 duration, u16 interval, u16 count, u8 gain) + static int steamdeck_leds_brightness_set(struct led_classdev *cdev, + enum led_brightness value) { -+ int ret; - u8 report[10] = {STEAM_CMD_HAPTIC_PULSE, 8}; - - /* Left and right are swapped on this report for legacy reasons */ -@@ -412,13 +422,17 @@ static inline int steam_haptic_pulse(struct steam_device *steam, u8 pad, - report[8] = count >> 8; - report[9] = gain; - -- return steam_send_report(steam, report, sizeof(report)); -+ mutex_lock(&steam->report_mutex); -+ ret = steam_send_report(steam, report, sizeof(report)); -+ mutex_unlock(&steam->report_mutex); -+ return ret; - } - - static inline int steam_haptic_rumble(struct steam_device *steam, - u16 intensity, u16 left_speed, u16 right_speed, - u8 left_gain, u8 right_gain) - { -+ int ret; - u8 report[11] = {STEAM_CMD_HAPTIC_RUMBLE, 9}; - - report[3] = intensity & 0xFF; -@@ -430,7 +444,10 @@ static inline int steam_haptic_rumble(struct steam_device *steam, - report[9] = left_gain; - report[10] = right_gain; +@@ -44,6 +92,7 @@ static int steamdeck_leds_probe(struct platform_device *pdev) + sd->cdev.name = "status:white"; + sd->cdev.brightness_set_blocking = steamdeck_leds_brightness_set; + sd->cdev.max_brightness = 100; ++ sd->cdev.groups = steamdeck_led_groups; -- return steam_send_report(steam, report, sizeof(report)); -+ mutex_lock(&steam->report_mutex); -+ ret = steam_send_report(steam, report, sizeof(report)); -+ mutex_unlock(&steam->report_mutex); -+ return ret; - } - - static void steam_haptic_rumble_cb(struct work_struct *work) -@@ -460,6 +477,7 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) - enable = false; - - if (enable) { -+ mutex_lock(&steam->report_mutex); - /* enable esc, enter, cursors */ - steam_send_report_byte(steam, STEAM_CMD_DEFAULT_MAPPINGS); - /* enable mouse */ -@@ -467,9 +485,11 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) - steam_write_registers(steam, - STEAM_REG_SMOOTH_ABSOLUTE_MOUSE, 0x01, /* enable smooth */ - 0); -+ mutex_unlock(&steam->report_mutex); - - cancel_delayed_work_sync(&steam->heartbeat); - } else { -+ mutex_lock(&steam->report_mutex); - /* disable esc, enter, cursor */ - steam_send_report_byte(steam, STEAM_CMD_CLEAR_MAPPINGS); - -@@ -481,18 +501,19 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) - STEAM_REG_LEFT_TRACKPAD_CLICK_PRESSURE, 0xFFFF, /* disable clicky pad */ - STEAM_REG_RIGHT_TRACKPAD_CLICK_PRESSURE, 0xFFFF, /* disable clicky pad */ - 0); -+ mutex_unlock(&steam->report_mutex); - /* - * The Steam Deck has a watchdog that automatically enables - * lizard mode if it doesn't see any traffic for too long - */ -- if (!work_busy(&steam->heartbeat.work)) -- schedule_delayed_work(&steam->heartbeat, 5 * HZ); -+ schedule_delayed_work(&steam->heartbeat, 5 * HZ); - } else { - steam_write_registers(steam, - STEAM_REG_SMOOTH_ABSOLUTE_MOUSE, 0x00, /* disable smooth */ - STEAM_REG_LEFT_TRACKPAD_MODE, STEAM_TRACKPAD_NONE, /* disable mouse */ - STEAM_REG_RIGHT_TRACKPAD_MODE, STEAM_TRACKPAD_NONE, /* disable mouse */ - 0); -+ mutex_unlock(&steam->report_mutex); - } - } - } -@@ -500,22 +521,29 @@ static void steam_set_lizard_mode(struct steam_device *steam, bool enable) - static int steam_input_open(struct input_dev *dev) - { - struct steam_device *steam = input_get_drvdata(dev); -+ unsigned long flags; -+ bool set_lizard_mode; - -- mutex_lock(&steam->mutex); -- if (!steam->client_opened && lizard_mode) -+ spin_lock_irqsave(&steam->lock, flags); -+ set_lizard_mode = !steam->client_opened && lizard_mode; -+ spin_unlock_irqrestore(&steam->lock, flags); -+ if (set_lizard_mode) - steam_set_lizard_mode(steam, false); -- mutex_unlock(&steam->mutex); -+ - return 0; - } - - static void steam_input_close(struct input_dev *dev) - { - struct steam_device *steam = input_get_drvdata(dev); -+ unsigned long flags; -+ bool set_lizard_mode; - -- mutex_lock(&steam->mutex); -- if (!steam->client_opened && lizard_mode) -+ spin_lock_irqsave(&steam->lock, flags); -+ set_lizard_mode = !steam->client_opened && lizard_mode; -+ spin_unlock_irqrestore(&steam->lock, flags); -+ if (set_lizard_mode) - steam_set_lizard_mode(steam, true); -- mutex_unlock(&steam->mutex); - } - - static enum power_supply_property steam_battery_props[] = { -@@ -760,6 +788,7 @@ static int steam_register(struct steam_device *steam) - { - int ret; - bool client_opened; -+ unsigned long flags; - - /* - * This function can be called several times in a row with the -@@ -772,11 +801,9 @@ static int steam_register(struct steam_device *steam) - * Unlikely, but getting the serial could fail, and it is not so - * important, so make up a serial number and go on. - */ -- mutex_lock(&steam->mutex); - if (steam_get_serial(steam) < 0) - strscpy(steam->serial_no, "XXXXXXXXXX", - sizeof(steam->serial_no)); -- mutex_unlock(&steam->mutex); - - hid_info(steam->hdev, "Steam Controller '%s' connected", - steam->serial_no); -@@ -791,11 +818,11 @@ static int steam_register(struct steam_device *steam) - mutex_unlock(&steam_devices_lock); - } - -- mutex_lock(&steam->mutex); -+ spin_lock_irqsave(&steam->lock, flags); - client_opened = steam->client_opened; -+ spin_unlock_irqrestore(&steam->lock, flags); - if (!client_opened) - steam_set_lizard_mode(steam, lizard_mode); -- mutex_unlock(&steam->mutex); - - if (!client_opened) - ret = steam_input_register(steam); -@@ -847,16 +874,21 @@ static void steam_mode_switch_cb(struct work_struct *work) - { - struct steam_device *steam = container_of(to_delayed_work(work), - struct steam_device, mode_switch); -+ unsigned long flags; -+ bool client_opened; - steam->gamepad_mode = !steam->gamepad_mode; - if (!lizard_mode) - return; - -- mutex_lock(&steam->mutex); - if (steam->gamepad_mode) - steam_set_lizard_mode(steam, false); -- else if (!steam->client_opened) -- steam_set_lizard_mode(steam, lizard_mode); -- mutex_unlock(&steam->mutex); -+ else { -+ spin_lock_irqsave(&steam->lock, flags); -+ client_opened = steam->client_opened; -+ spin_unlock_irqrestore(&steam->lock, flags); -+ if (!client_opened) -+ steam_set_lizard_mode(steam, lizard_mode); -+ } - - steam_haptic_pulse(steam, STEAM_PAD_RIGHT, 0x190, 0, 1, 0); - if (steam->gamepad_mode) { -@@ -889,16 +921,21 @@ static void steam_lizard_mode_heartbeat(struct work_struct *work) - { - struct steam_device *steam = container_of(work, struct steam_device, - heartbeat.work); -+ bool client_opened; -+ unsigned long flags; - -- mutex_lock(&steam->mutex); -- if (!steam->client_opened && steam->client_hdev) { -+ spin_lock_irqsave(&steam->lock, flags); -+ client_opened = steam->client_opened; -+ spin_unlock_irqrestore(&steam->lock, flags); -+ if (!client_opened) { -+ mutex_lock(&steam->report_mutex); - steam_send_report_byte(steam, STEAM_CMD_CLEAR_MAPPINGS); - steam_write_registers(steam, - STEAM_REG_RIGHT_TRACKPAD_MODE, STEAM_TRACKPAD_NONE, /* disable mouse */ - 0); -+ mutex_unlock(&steam->report_mutex); - schedule_delayed_work(&steam->heartbeat, 5 * HZ); - } -- mutex_unlock(&steam->mutex); - } - - static int steam_client_ll_parse(struct hid_device *hdev) -@@ -921,10 +958,11 @@ static void steam_client_ll_stop(struct hid_device *hdev) - static int steam_client_ll_open(struct hid_device *hdev) - { - struct steam_device *steam = hdev->driver_data; -+ unsigned long flags; - -- mutex_lock(&steam->mutex); -+ spin_lock_irqsave(&steam->lock, flags); - steam->client_opened = true; -- mutex_unlock(&steam->mutex); -+ spin_unlock_irqrestore(&steam->lock, flags); - - steam_input_unregister(steam); - -@@ -939,14 +977,12 @@ static void steam_client_ll_close(struct hid_device *hdev) - bool connected; - - spin_lock_irqsave(&steam->lock, flags); -- connected = steam->connected; -+ steam->client_opened = false; -+ connected = steam->connected && !steam->client_opened; - spin_unlock_irqrestore(&steam->lock, flags); - -- mutex_lock(&steam->mutex); -- steam->client_opened = false; - if (connected) - steam_set_lizard_mode(steam, lizard_mode); -- mutex_unlock(&steam->mutex); - - if (connected) - steam_input_register(steam); -@@ -1035,7 +1071,7 @@ static int steam_probe(struct hid_device *hdev, - steam->hdev = hdev; - hid_set_drvdata(hdev, steam); - spin_lock_init(&steam->lock); -- mutex_init(&steam->mutex); -+ mutex_init(&steam->report_mutex); - steam->quirks = id->driver_data; - INIT_WORK(&steam->work_connect, steam_work_connect_cb); - INIT_DELAYED_WORK(&steam->mode_switch, steam_mode_switch_cb); -@@ -1043,13 +1079,6 @@ static int steam_probe(struct hid_device *hdev, - INIT_DEFERRABLE_WORK(&steam->heartbeat, steam_lizard_mode_heartbeat); - INIT_WORK(&steam->rumble_work, steam_haptic_rumble_cb); - -- steam->client_hdev = steam_create_client_hid(hdev); -- if (IS_ERR(steam->client_hdev)) { -- ret = PTR_ERR(steam->client_hdev); -- goto client_hdev_fail; -- } -- steam->client_hdev->driver_data = steam; -- - /* - * With the real steam controller interface, do not connect hidraw. - * Instead, create the client_hid and connect that. -@@ -1058,10 +1087,6 @@ static int steam_probe(struct hid_device *hdev, - if (ret) - goto hid_hw_start_fail; - -- ret = hid_add_device(steam->client_hdev); -- if (ret) -- goto client_hdev_add_fail; -- - ret = hid_hw_open(hdev); + ret = devm_led_classdev_register(dev, &sd->cdev); if (ret) { - hid_err(hdev, -@@ -1087,15 +1112,26 @@ static int steam_probe(struct hid_device *hdev, - } - } - -+ steam->client_hdev = steam_create_client_hid(hdev); -+ if (IS_ERR(steam->client_hdev)) { -+ ret = PTR_ERR(steam->client_hdev); -+ goto client_hdev_fail; -+ } -+ steam->client_hdev->driver_data = steam; -+ -+ ret = hid_add_device(steam->client_hdev); -+ if (ret) -+ goto client_hdev_add_fail; -+ - return 0; - --input_register_fail: --hid_hw_open_fail: - client_hdev_add_fail: - hid_hw_stop(hdev); --hid_hw_start_fail: -- hid_destroy_device(steam->client_hdev); - client_hdev_fail: -+ hid_destroy_device(steam->client_hdev); -+input_register_fail: -+hid_hw_open_fail: -+hid_hw_start_fail: - cancel_work_sync(&steam->work_connect); - cancel_delayed_work_sync(&steam->heartbeat); - cancel_delayed_work_sync(&steam->mode_switch); -@@ -1115,14 +1151,12 @@ static void steam_remove(struct hid_device *hdev) - return; - } - -+ cancel_delayed_work_sync(&steam->heartbeat); -+ cancel_delayed_work_sync(&steam->mode_switch); -+ cancel_work_sync(&steam->work_connect); - hid_destroy_device(steam->client_hdev); -- mutex_lock(&steam->mutex); - steam->client_hdev = NULL; - steam->client_opened = false; -- cancel_delayed_work_sync(&steam->heartbeat); -- mutex_unlock(&steam->mutex); -- cancel_work_sync(&steam->work_connect); -- cancel_delayed_work_sync(&steam->mode_switch); - if (steam->quirks & STEAM_QUIRK_WIRELESS) { - hid_info(hdev, "Steam wireless receiver disconnected"); - } -@@ -1597,10 +1631,8 @@ static int steam_param_set_lizard_mode(const char *val, - - mutex_lock(&steam_devices_lock); - list_for_each_entry(steam, &steam_devices, list) { -- mutex_lock(&steam->mutex); - if (!steam->client_opened) - steam_set_lizard_mode(steam, lizard_mode); -- mutex_unlock(&steam->mutex); - } - mutex_unlock(&steam_devices_lock); - return 0; --- -2.41.0 - - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Vicki Pfau <vi@endrift.com> -Date: Wed, 10 May 2023 17:27:12 -0700 -Subject: [PATCH 06/10] HID: hid-steam: Make client_opened a counter - -The client_opened variable was used to track if the hidraw was opened by any -clients to silence keyboard/mouse events while opened. However, there was no -counting of how many clients were opened, so opening two at the same time and -then closing one would fool the driver into thinking it had no remaining opened -clients. - -Signed-off-by: Vicki Pfau <vi@endrift.com> ---- - drivers/hid/hid-steam.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c -index 845ca71b8bd3a..0c2fe51b29bc1 100644 ---- a/drivers/hid/hid-steam.c -+++ b/drivers/hid/hid-steam.c -@@ -215,7 +215,7 @@ struct steam_device { - spinlock_t lock; - struct hid_device *hdev, *client_hdev; - struct mutex report_mutex; -- bool client_opened; -+ unsigned long client_opened; - struct input_dev __rcu *input; - unsigned long quirks; - struct work_struct work_connect; -@@ -787,7 +787,7 @@ static void steam_battery_unregister(struct steam_device *steam) - static int steam_register(struct steam_device *steam) - { - int ret; -- bool client_opened; -+ unsigned long client_opened; - unsigned long flags; - - /* -@@ -961,7 +961,7 @@ static int steam_client_ll_open(struct hid_device *hdev) - unsigned long flags; - - spin_lock_irqsave(&steam->lock, flags); -- steam->client_opened = true; -+ steam->client_opened++; - spin_unlock_irqrestore(&steam->lock, flags); - - steam_input_unregister(steam); -@@ -977,7 +977,7 @@ static void steam_client_ll_close(struct hid_device *hdev) - bool connected; - - spin_lock_irqsave(&steam->lock, flags); -- steam->client_opened = false; -+ steam->client_opened--; - connected = steam->connected && !steam->client_opened; - spin_unlock_irqrestore(&steam->lock, flags); - -@@ -1156,7 +1156,7 @@ static void steam_remove(struct hid_device *hdev) - cancel_work_sync(&steam->work_connect); - hid_destroy_device(steam->client_hdev); - steam->client_hdev = NULL; -- steam->client_opened = false; -+ steam->client_opened = 0; - if (steam->quirks & STEAM_QUIRK_WIRELESS) { - hid_info(hdev, "Steam wireless receiver disconnected"); - } --- -2.41.0 - - -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: Vicki Pfau <vi@endrift.com> -Date: Thu, 18 May 2023 18:00:35 -0700 -Subject: [PATCH 07/10] HID: hid-steam: Better handling of serial number length - -The second byte of the GET_STRING_ATTRIB report is a length, so we should set -the size of the buffer to be the size we're actually requesting, and only -reject the reply if the length out is nonsensical. - -Signed-off-by: Vicki Pfau <vi@endrift.com> ---- - drivers/hid/hid-steam.c | 10 +++++----- - 1 file changed, 5 insertions(+), 5 deletions(-) - -diff --git a/drivers/hid/hid-steam.c b/drivers/hid/hid-steam.c -index 0c2fe51b29bc1..92e3e1052fa42 100644 ---- a/drivers/hid/hid-steam.c -+++ b/drivers/hid/hid-steam.c -@@ -208,7 +208,7 @@ static LIST_HEAD(steam_devices); - #define STEAM_PAD_BOTH 2 - - /* Other random constants */ --#define STEAM_SERIAL_LEN 10 -+#define STEAM_SERIAL_LEN 0x15 - - struct steam_device { - struct list_head list; -@@ -359,10 +359,10 @@ static int steam_get_serial(struct steam_device *steam) - { - /* - * Send: 0xae 0x15 0x01 -- * Recv: 0xae 0x15 0x01 serialnumber (10 chars) -+ * Recv: 0xae 0x15 0x01 serialnumber - */ - int ret = 0; -- u8 cmd[] = {STEAM_CMD_GET_STRING_ATTRIB, 0x15, STEAM_ATTRIB_STR_UNIT_SERIAL}; -+ u8 cmd[] = {STEAM_CMD_GET_STRING_ATTRIB, sizeof(steam->serial_no), STEAM_ATTRIB_STR_UNIT_SERIAL}; - u8 reply[3 + STEAM_SERIAL_LEN + 1]; - mutex_lock(&steam->report_mutex); -@@ -372,12 +372,12 @@ static int steam_get_serial(struct steam_device *steam) - ret = steam_recv_report(steam, reply, sizeof(reply)); - if (ret < 0) - goto out; -- if (reply[0] != 0xae || reply[1] != 0x15 || reply[2] != STEAM_ATTRIB_STR_UNIT_SERIAL) { -+ if (reply[0] != 0xae || reply[1] < 1 || reply[1] > sizeof(steam->serial_no) || reply[2] != STEAM_ATTRIB_STR_UNIT_SERIAL) { - ret = -EIO; - goto out; - } - reply[3 + STEAM_SERIAL_LEN] = 0; -- strscpy(steam->serial_no, reply + 3, sizeof(steam->serial_no)); -+ strscpy(steam->serial_no, reply + 3, reply[1]); - out: - mutex_unlock(&steam->report_mutex); - return ret; -- 2.41.0 diff --git a/SOURCES/steamdeck-oled-legion-go-bluetooth-hang.patch b/SOURCES/steamdeck-oled-legion-go-bluetooth-hang.patch new file mode 100644 index 0000000..031b8df --- /dev/null +++ b/SOURCES/steamdeck-oled-legion-go-bluetooth-hang.patch @@ -0,0 +1,289 @@ +From 5426751e00c32e914ff9aa37af934cf3873cccf4 Mon Sep 17 00:00:00 2001 +From: Matthew Schwartz <njtransit215@gmail.com> +Date: Thu, 18 Apr 2024 11:36:01 -0700 +Subject: [PATCH 0/7] revert series of drivers/bluetooth/hci commits to fix Galileo/OLED Deck + Legion Go failing to suspend on 6.8 kernels + +Revert series of commits that causes a bluetooth regression where toggling Bluetooth on the Galileo/OLED Deck and Legion Go can cause the device to fail to suspend properly. Instead, the display turns dims for 5-10s before waking up automatically again. + +Logs show: + +"Failed to add UUID: Failed (0x03)" +"Failed to set mode: Authentication Failed (0x05)" + +hci0: Retry BT power ON:0 +hci0: command tx timeout +hci0: Reading QCA version information failed (-110) + +`sudo rmmod hci_uart` was a workaround, while this patch removes the need for that until it is sorted out upstream. + +Matthew Schwartz (7): + Revert "Bluetooth: qca: fix device-address endianness" + Reapply "Bluetooth: hci_qca: Set BDA quirk bit if fwnode exists in DT" + Revert "Bluetooth: btrtl: fix out of bounds memory access" + Revert "Bluetooth: hci_h5: Add ability to allocate memory for private + data" + Revert "Bluetooth: hci_qca: don't use IS_ERR_OR_NULL() with + gpiod_get_optional()" + Revert "Bluetooth: qca: Fix triggering coredump implementation" + Revert "Bluetooth: hci_qca: Set BDA quirk bit if fwnode exists in DT" + + drivers/bluetooth/hci_h5.c | 5 +---- + drivers/bluetooth/hci_qca.c | 25 ++++++++----------------- + drivers/bluetooth/hci_serdev.c | 9 ++++----- + drivers/bluetooth/hci_uart.h | 12 +----------- + 5 files changed, 16 insertions(+), 43 deletions(-) + +-- +2.44.0 + + +From 4406334f2f6736f390508c0e3c916484e7e4e0f7 Mon Sep 17 00:00:00 2001 +From: Matthew Schwartz <njtransit215@gmail.com> +Date: Thu, 18 Apr 2024 11:30:39 -0700 +Subject: [PATCH 3/7] Revert "Bluetooth: btrtl: fix out of bounds memory + access" + +This reverts commit 0c657e641df1e77d6087688190f632cad9c0439b. +--- + drivers/bluetooth/hci_h5.c | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c +index c0436881a533..b66136348bd6 100644 +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -1072,7 +1072,6 @@ static struct h5_vnd rtl_vnd = { + .suspend = h5_btrtl_suspend, + .resume = h5_btrtl_resume, + .acpi_gpio_map = acpi_btrtl_gpios, +- .sizeof_priv = sizeof(struct btrealtek_data), + }; + + static const struct h5_device_data h5_data_rtl8822cs = { +-- +2.44.0 + + +From af2120f2a4f714215f5c576dfc1cee2fe0c1e842 Mon Sep 17 00:00:00 2001 +From: Matthew Schwartz <njtransit215@gmail.com> +Date: Thu, 18 Apr 2024 11:30:43 -0700 +Subject: [PATCH 4/7] Revert "Bluetooth: hci_h5: Add ability to allocate memory + for private data" + +This reverts commit 46a7d9aa6e456c161746744cc08961bb83dc97b3. +--- + drivers/bluetooth/hci_h5.c | 4 +--- + drivers/bluetooth/hci_serdev.c | 9 ++++----- + drivers/bluetooth/hci_uart.h | 12 +----------- + 3 files changed, 6 insertions(+), 19 deletions(-) + +diff --git a/drivers/bluetooth/hci_h5.c b/drivers/bluetooth/hci_h5.c +index b66136348bd6..71e748a9477e 100644 +--- a/drivers/bluetooth/hci_h5.c ++++ b/drivers/bluetooth/hci_h5.c +@@ -113,7 +113,6 @@ struct h5_vnd { + int (*suspend)(struct h5 *h5); + int (*resume)(struct h5 *h5); + const struct acpi_gpio_mapping *acpi_gpio_map; +- int sizeof_priv; + }; + + struct h5_device_data { +@@ -864,8 +863,7 @@ static int h5_serdev_probe(struct serdev_device *serdev) + if (IS_ERR(h5->device_wake_gpio)) + return PTR_ERR(h5->device_wake_gpio); + +- return hci_uart_register_device_priv(&h5->serdev_hu, &h5p, +- h5->vnd->sizeof_priv); ++ return hci_uart_register_device(&h5->serdev_hu, &h5p); + } + + static void h5_serdev_remove(struct serdev_device *serdev) +diff --git a/drivers/bluetooth/hci_serdev.c b/drivers/bluetooth/hci_serdev.c +index 214fff876eae..39c8b567da3c 100644 +--- a/drivers/bluetooth/hci_serdev.c ++++ b/drivers/bluetooth/hci_serdev.c +@@ -300,9 +300,8 @@ static const struct serdev_device_ops hci_serdev_client_ops = { + .write_wakeup = hci_uart_write_wakeup, + }; + +-int hci_uart_register_device_priv(struct hci_uart *hu, +- const struct hci_uart_proto *p, +- int sizeof_priv) ++int hci_uart_register_device(struct hci_uart *hu, ++ const struct hci_uart_proto *p) + { + int err; + struct hci_dev *hdev; +@@ -326,7 +325,7 @@ int hci_uart_register_device_priv(struct hci_uart *hu, + set_bit(HCI_UART_PROTO_READY, &hu->flags); + + /* Initialize and register HCI device */ +- hdev = hci_alloc_dev_priv(sizeof_priv); ++ hdev = hci_alloc_dev(); + if (!hdev) { + BT_ERR("Can't allocate HCI device"); + err = -ENOMEM; +@@ -395,7 +394,7 @@ int hci_uart_register_device_priv(struct hci_uart *hu, + percpu_free_rwsem(&hu->proto_lock); + return err; + } +-EXPORT_SYMBOL_GPL(hci_uart_register_device_priv); ++EXPORT_SYMBOL_GPL(hci_uart_register_device); + + void hci_uart_unregister_device(struct hci_uart *hu) + { +diff --git a/drivers/bluetooth/hci_uart.h b/drivers/bluetooth/hci_uart.h +index 68c8c7e95d64..fb4a2d0d8cc8 100644 +--- a/drivers/bluetooth/hci_uart.h ++++ b/drivers/bluetooth/hci_uart.h +@@ -97,17 +97,7 @@ struct hci_uart { + + int hci_uart_register_proto(const struct hci_uart_proto *p); + int hci_uart_unregister_proto(const struct hci_uart_proto *p); +- +-int hci_uart_register_device_priv(struct hci_uart *hu, +- const struct hci_uart_proto *p, +- int sizeof_priv); +- +-static inline int hci_uart_register_device(struct hci_uart *hu, +- const struct hci_uart_proto *p) +-{ +- return hci_uart_register_device_priv(hu, p, 0); +-} +- ++int hci_uart_register_device(struct hci_uart *hu, const struct hci_uart_proto *p); + void hci_uart_unregister_device(struct hci_uart *hu); + + int hci_uart_tx_wakeup(struct hci_uart *hu); +-- +2.44.0 + + +From b224374f230579fe13fdb363f11171bc15e22a77 Mon Sep 17 00:00:00 2001 +From: Matthew Schwartz <njtransit215@gmail.com> +Date: Thu, 18 Apr 2024 11:30:50 -0700 +Subject: [PATCH 5/7] Revert "Bluetooth: hci_qca: don't use IS_ERR_OR_NULL() + with gpiod_get_optional()" + +This reverts commit d8c7785e8104359f139cdfa99e2511575c4d4823. +--- + drivers/bluetooth/hci_qca.c | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c +index 8a60ad7acd70..edd2a81b4d5e 100644 +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -2326,7 +2326,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) + + qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable", + GPIOD_OUT_LOW); +- if (IS_ERR(qcadev->bt_en) && ++ if (IS_ERR_OR_NULL(qcadev->bt_en) && + (data->soc_type == QCA_WCN6750 || + data->soc_type == QCA_WCN6855)) { + dev_err(&serdev->dev, "failed to acquire BT_EN gpio\n"); +@@ -2335,7 +2335,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) + + qcadev->sw_ctrl = devm_gpiod_get_optional(&serdev->dev, "swctrl", + GPIOD_IN); +- if (IS_ERR(qcadev->sw_ctrl) && ++ if (IS_ERR_OR_NULL(qcadev->sw_ctrl) && + (data->soc_type == QCA_WCN6750 || + data->soc_type == QCA_WCN6855 || + data->soc_type == QCA_WCN7850)) +@@ -2357,7 +2357,7 @@ static int qca_serdev_probe(struct serdev_device *serdev) + default: + qcadev->bt_en = devm_gpiod_get_optional(&serdev->dev, "enable", + GPIOD_OUT_LOW); +- if (IS_ERR(qcadev->bt_en)) { ++ if (IS_ERR_OR_NULL(qcadev->bt_en)) { + dev_warn(&serdev->dev, "failed to acquire enable gpio\n"); + power_ctrl_enabled = false; + } +-- +2.44.0 + + +From 804d00250b22aa2976278047bbefe5cec6e69c6b Mon Sep 17 00:00:00 2001 +From: Matthew Schwartz <njtransit215@gmail.com> +Date: Thu, 18 Apr 2024 11:30:54 -0700 +Subject: [PATCH 6/7] Revert "Bluetooth: qca: Fix triggering coredump + implementation" + +This reverts commit 6abf9dd26bb1699c17d601b9a292577d01827c0e. +--- + drivers/bluetooth/hci_qca.c | 9 +++++---- + 1 file changed, 5 insertions(+), 4 deletions(-) + +diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c +index edd2a81b4d5e..06193546ebb6 100644 +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -1807,12 +1807,13 @@ + + static void hci_coredump_qca(struct hci_dev *hdev) + { +- int err; + static const u8 param[] = { 0x26 }; ++ struct sk_buff *skb; + +- err = __hci_cmd_send(hdev, 0xfc0c, 1, param); +- if (err < 0) +- bt_dev_err(hdev, "%s: trigger crash failed (%d)", __func__, err); ++ skb = __hci_cmd_sync(hdev, 0xfc0c, 1, param, HCI_CMD_TIMEOUT); ++ if (IS_ERR(skb)) ++ bt_dev_err(hdev, "%s: trigger crash failed (%ld)", __func__, PTR_ERR(skb)); ++ kfree_skb(skb); + } + + static int qca_setup(struct hci_uart *hu) +-- +2.44.0 + + +From dfc6025cea81507afd56689f99496b234c3e9816 Mon Sep 17 00:00:00 2001 +From: Matthew Schwartz <njtransit215@gmail.com> +Date: Thu, 18 Apr 2024 11:30:58 -0700 +Subject: [PATCH 7/7] Revert "Bluetooth: hci_qca: Set BDA quirk bit if fwnode + exists in DT" + +This reverts commit 7dcd3e014aa7faeeaf4047190b22d8a19a0db696. +--- + drivers/bluetooth/hci_qca.c | 13 +------------ + 1 file changed, 1 insertion(+), 12 deletions(-) + +diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c +index 06193546ebb6..94b8c406f0c0 100644 +--- a/drivers/bluetooth/hci_qca.c ++++ b/drivers/bluetooth/hci_qca.c +@@ -7,7 +7,6 @@ + * + * Copyright (C) 2007 Texas Instruments, Inc. + * Copyright (c) 2010, 2012, 2018 The Linux Foundation. All rights reserved. +- * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved. + * + * Acknowledgements: + * This file is based on hci_ll.c, which was... +@@ -1905,17 +1904,7 @@ static int qca_setup(struct hci_uart *hu) + case QCA_WCN6750: + case QCA_WCN6855: + case QCA_WCN7850: +- +- /* Set BDA quirk bit for reading BDA value from fwnode property +- * only if that property exist in DT. +- */ +- if (fwnode_property_present(dev_fwnode(hdev->dev.parent), "local-bd-address")) { +- set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); +- bt_dev_info(hdev, "setting quirk bit to read BDA from fwnode later"); +- } else { +- bt_dev_dbg(hdev, "local-bd-address` is not present in the devicetree so not setting quirk bit for BDA"); +- } +- ++ set_bit(HCI_QUIRK_USE_BDADDR_PROPERTY, &hdev->quirks); + hci_set_aosp_capable(hdev); + + ret = qca_read_soc_version(hdev, &ver, soc_type); +-- +2.44.0 diff --git a/SOURCES/oled-deck-refresh-rate.patch b/SOURCES/steamdeck-oled-refresh-rate.patch index d6643f9..9f82ab9 100644 --- a/SOURCES/oled-deck-refresh-rate.patch +++ b/SOURCES/steamdeck-oled-refresh-rate.patch @@ -1,5 +1,119 @@ +From 74b669e1b1296dfb2987a29840ddae29c2b31353 Mon Sep 17 00:00:00 2001 +From: Matthew Schwartz <njtransit215@gmail.com> +Date: Wed, 17 Apr 2024 21:31:14 -0700 +Subject: [PATCH 0/2] fix Galileo/OLED Deck refresh rate modesetting + +For some bizarre reason, these amdgpu_freesync_vid_mode parameters are the key to letting the Galileo/OLED Deck's 90hz display modeset properly within gamescope and gamescope-session. This adds the parameters back until a fix comes from upstream. + +Alex Deucher (2): + Reapply "Revert drm/amd/display: Enable Freesync Video Mode by + default" + Revert "drm/amd: Remove freesync video mode amdgpu parameter" + + drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 27 +++++++++++++++++++ + .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 +++++---- + 3 files changed, 35 insertions(+), 5 deletions(-) + +-- +2.44.0 + +From dbdedb7714422407d78a715031304e1be54680e1 Mon Sep 17 00:00:00 2001 +From: Alex Deucher <alexander.deucher@amd.com> +Date: Tue, 27 Feb 2024 13:08:12 -0500 +Subject: [PATCH 1/2] Reapply "Revert drm/amd/display: Enable Freesync Video + Mode by default" + +This reverts commit 11b92df8a2f7f4605ccc764ce6ae4a72760674df. + +This conflicts with how compositors want to handle VRR. Now +that compositors actually handle VRR, we probably don't need +freesync video. + +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/2985 +Acked-by: Hamza Mahfooz <hamza.mahfooz@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 12 +++++++----- + 1 file changed, 7 insertions(+), 5 deletions(-) + +diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +index 46dd06e8fc7e..1010a89a17e6 100644 +--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c ++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c +@@ -6233,7 +6233,8 @@ create_stream_for_sink(struct drm_connector *connector, + */ + DRM_DEBUG_DRIVER("No preferred mode found\n"); + } else if (aconnector) { +- recalculate_timing = is_freesync_video_mode(&mode, aconnector); ++ recalculate_timing = amdgpu_freesync_vid_mode && ++ is_freesync_video_mode(&mode, aconnector); + if (recalculate_timing) { + freesync_mode = get_highest_refresh_rate_mode(aconnector, false); + drm_mode_copy(&saved_mode, &mode); +@@ -7544,7 +7545,7 @@ static void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connect + struct amdgpu_dm_connector *amdgpu_dm_connector = + to_amdgpu_dm_connector(connector); + +- if (!edid) ++ if (!(amdgpu_freesync_vid_mode && edid)) + return; + + if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10) +@@ -9838,7 +9839,8 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, + * TODO: Refactor this function to allow this check to work + * in all conditions. + */ +- if (dm_new_crtc_state->stream && ++ if (amdgpu_freesync_vid_mode && ++ dm_new_crtc_state->stream && + is_timing_unchanged_for_freesync(new_crtc_state, old_crtc_state)) + goto skip_modeset; + +@@ -9878,7 +9880,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, + } + + /* Now check if we should set freesync video mode */ +- if (dm_new_crtc_state->stream && ++ if (amdgpu_freesync_vid_mode && dm_new_crtc_state->stream && + dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) && + dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream) && + is_timing_unchanged_for_freesync(new_crtc_state, +@@ -9891,7 +9893,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, + set_freesync_fixed_config(dm_new_crtc_state); + + goto skip_modeset; +- } else if (aconnector && ++ } else if (amdgpu_freesync_vid_mode && aconnector && + is_freesync_video_mode(&new_crtc_state->mode, + aconnector)) { + struct drm_display_mode *high_mode; +-- +2.44.0 + + +From 74b669e1b1296dfb2987a29840ddae29c2b31353 Mon Sep 17 00:00:00 2001 +From: Alex Deucher <alexander.deucher@amd.com> +Date: Tue, 27 Feb 2024 13:03:40 -0500 +Subject: [PATCH 2/2] Revert "drm/amd: Remove freesync video mode amdgpu + parameter" + +This reverts commit e94e787e37b99645e7c02d20d0a1ba0f8a18a82a. + +This conflicts with how compositors want to handle VRR. Now +that compositors actually handle VRR, we probably don't need +freesync video. + +Closes: https://gitlab.freedesktop.org/drm/amd/-/issues/2985 +Acked-by: Hamza Mahfooz <hamza.mahfooz@amd.com> +Signed-off-by: Alex Deucher <alexander.deucher@amd.com> +--- + drivers/gpu/drm/amd/amdgpu/amdgpu.h | 1 + + drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c | 27 +++++++++++++++++++++++++ + 2 files changed, 28 insertions(+) + diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h -index 9246bca0a0089b24cf315de75d9bee155c74d32d..9c62552bec344e370996a028d809934e4a6f4420 100644 +index 9246bca0a008..9c62552bec34 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -196,6 +196,7 @@ @@ -11,7 +125,7 @@ index 9246bca0a0089b24cf315de75d9bee155c74d32d..9c62552bec344e370996a028d809934e extern uint amdgpu_dc_visual_confirm; extern uint amdgpu_dm_abm_level; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c -index af7fae7907d71ed9efb771f50acdf483b4230113..8e1299fe2c54a809761301c15e8bcbe918986bac 100644 +index af7fae7907d7..8e1299fe2c54 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -199,6 +199,7 @@ int amdgpu_mes_kiq; @@ -55,55 +169,6 @@ index af7fae7907d71ed9efb771f50acdf483b4230113..8e1299fe2c54a809761301c15e8bcbe9 /** * DOC: reset_method (int) * GPU reset method (-1 = auto (default), 0 = legacy, 1 = mode0, 2 = mode1, 3 = mode2, 4 = baco) -diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -index 46dd06e8fc7e127dbaa0d7c8c96632c7972b901a..1010a89a17e627845c322fc4874fd1dba2f55cff 100644 ---- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -+++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c -@@ -6233,7 +6233,8 @@ create_stream_for_sink(struct drm_connector *connector, - */ - DRM_DEBUG_DRIVER("No preferred mode found\n"); - } else if (aconnector) { -- recalculate_timing = is_freesync_video_mode(&mode, aconnector); -+ recalculate_timing = amdgpu_freesync_vid_mode && -+ is_freesync_video_mode(&mode, aconnector); - if (recalculate_timing) { - freesync_mode = get_highest_refresh_rate_mode(aconnector, false); - drm_mode_copy(&saved_mode, &mode); -@@ -7544,7 +7545,7 @@ static void amdgpu_dm_connector_add_freesync_modes(struct drm_connector *connect - struct amdgpu_dm_connector *amdgpu_dm_connector = - to_amdgpu_dm_connector(connector); - -- if (!edid) -+ if (!(amdgpu_freesync_vid_mode && edid)) - return; - - if (amdgpu_dm_connector->max_vfreq - amdgpu_dm_connector->min_vfreq > 10) -@@ -9838,7 +9839,8 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, - * TODO: Refactor this function to allow this check to work - * in all conditions. - */ -- if (dm_new_crtc_state->stream && -+ if (amdgpu_freesync_vid_mode && -+ dm_new_crtc_state->stream && - is_timing_unchanged_for_freesync(new_crtc_state, old_crtc_state)) - goto skip_modeset; - -@@ -9878,7 +9880,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, - } - - /* Now check if we should set freesync video mode */ -- if (dm_new_crtc_state->stream && -+ if (amdgpu_freesync_vid_mode && dm_new_crtc_state->stream && - dc_is_stream_unchanged(new_stream, dm_old_crtc_state->stream) && - dc_is_stream_scaling_unchanged(new_stream, dm_old_crtc_state->stream) && - is_timing_unchanged_for_freesync(new_crtc_state, -@@ -9891,7 +9893,7 @@ static int dm_update_crtc_state(struct amdgpu_display_manager *dm, - set_freesync_fixed_config(dm_new_crtc_state); - - goto skip_modeset; -- } else if (aconnector && -+ } else if (amdgpu_freesync_vid_mode && aconnector && - is_freesync_video_mode(&new_crtc_state->mode, - aconnector)) { - struct drm_display_mode *high_mode; +-- +2.44.0 diff --git a/SPECS/kernel.spec b/SPECS/kernel.spec index 525d5b8..7af7564 100644 --- a/SPECS/kernel.spec +++ b/SPECS/kernel.spec @@ -169,7 +169,7 @@ Summary: The Linux kernel # This is needed to do merge window version magic %define patchlevel 7 # This allows pkg_release to have configurable %%{?dist} tag -%define specrelease 202%{?buildid}%{?dist} +%define specrelease 203%{?buildid}%{?dist} # This defines the kabi tarball version %define kabiversion 6.7.12 @@ -1014,7 +1014,7 @@ Patch309: 0002-drm-i915-add-kernel-parameter-to-disable-async-page-.patch # improve AMD SFH 1.1 gyro and accel sensitivity Patch324: 0001-bump-the-sensitivity-of-AMD-SFH.patch # ROG Ally -Patch315: rog-ally-audio-fix.patch +Patch316: rog-ally-audio-fix.patch Patch317: ROG-ALLY-NCT6775-PLATFORM.patch Patch318: v14.8-0001-HID-asus-fix-more-n-key-report-descriptors-if-.patch Patch319: v14.8-0002-HID-asus-make-asus_kbd_init-generic-remove-rog.patch @@ -1041,7 +1041,8 @@ Patch331: amdgpu-HAINAN-variant-fixup.patch Patch310: steamdeck-oled-wifi.patch Patch312: steamdeck-oled-audio.patch Patch313: steamdeck-oled-hw-quirks.patch -Patch314: oled-deck-refresh-rate.patch +Patch314: steamdeck-oled-refresh-rate.patch +Patch315: steamdeck-oled-legion-go-bluetooth-hang.patch # t2 macbook patches Patch332: t2linux.patch @@ -1912,7 +1913,8 @@ ApplyOptionalPatch amdgpu-HAINAN-variant-fixup.patch ApplyOptionalPatch steamdeck-oled-wifi.patch ApplyOptionalPatch steamdeck-oled-audio.patch ApplyOptionalPatch steamdeck-oled-hw-quirks.patch -ApplyOptionalPatch oled-deck-refresh-rate.patch +ApplyOptionalPatch steamdeck-oled-refresh-rate.patch +ApplyOptionalPatch steamdeck-oled-legion-go-bluetooth-hang.patch # t2 macbook patches ApplyOptionalPatch t2linux.patch @@ -4000,7 +4002,10 @@ fi\ # # %changelog -* Wed Apr 17 2024 Jan200101 <sentrycraft123@gmail.com> - 6.7.12-202.fsync.1 +* Sat Apr 20 2024 Jan200101 <sentrycraft123@gmail.com> - 6.7.12-203.fsync +- kernel-fsync v6.7.12 update + +* Wed Apr 17 2024 Jan200101 <sentrycraft123@gmail.com> - 6.7.12-202.fsync - kernel-fsync v6.7.12 oled refresh rate patch * Mon Apr 15 2024 Jan200101 <sentrycraft123@gmail.com> - 6.7.12-201.fsync |