From efd3825f54f0e06304396332030893bb8a3950fc Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Fri, 8 Dec 2023 21:36:58 -0500 Subject: [PATCH] Fixes for 5.10 Signed-off-by: Sasha Levin --- ...-support-for-multiple-sohard-arcnet-.patch | 216 +++++ .../asus-wmi-add-dgpu-disable-method.patch | 190 ++++ ...ting-the-sg-structure-should-also-up.patch | 74 ++ ...vsc-rndis_filter-needs-to-select-nls.patch | 44 + ...e-fix-unexpected-mfs-warning-message.patch | 58 ++ ...ork-handling-in-split-interrupt-mode.patch | 67 ++ ...c-fix-snprintf-format-length-warning.patch | 45 + ...avoid-skb_pull-failure-in-ipgre_xmit.patch | 58 ++ ...fix-potential-null-deref-in-fib6_add.patch | 79 ++ ...rrectly-identify-secure-boot-with-de.patch | 120 +++ ...t-arcnet-com20020-fix-error-handling.patch | 137 +++ ...otential-use-after-free-in-bnxt_init.patch | 43 + ...net-hns-fix-fake-link-up-on-xge-port.patch | 74 ++ ...er-fix-for-unsafe-access-of-sk-sk_so.patch | 71 ++ ...-missing-mutex-lock-in-otx2_get_paus.patch | 51 ++ ...return-section-in-kerneldoc-comments.patch | 812 ++++++++++++++++++ ...-formatting-issues-and-provide-missi.patch | 105 +++ ...f_reconfig_get_state_change-return-v.patch | 41 + .../of-fix-kerneldoc-output-formatting.patch | 500 +++++++++++ ...s-nb-wmi-add-tablet_mode_sw-lid-flip.patch | 46 + ...s-nb-wmi-allow-configuring-sw_tablet.patch | 66 ++ ...s-wmi-add-support-for-rog-x13-tablet.patch | 175 ++++ ...s-wmi-add-support-for-sw_tablet_mode.patch | 192 +++++ ...s-wmi-adjust-tablet-lidflip-handling.patch | 220 +++++ ...s-wmi-move-i8042-filter-install-to-s.patch | 111 +++ ...s-wmi-simplify-tablet-mode-switch-ha.patch | 192 +++++ ...s-wmi-simplify-tablet-mode-switch-pr.patch | 107 +++ queue-5.10/series | 28 + ...ot-accept-ack-of-bytes-we-never-sent.patch | 106 +++ 29 files changed, 4028 insertions(+) create mode 100644 queue-5.10/arcnet-restoring-support-for-multiple-sohard-arcnet-.patch create mode 100644 queue-5.10/asus-wmi-add-dgpu-disable-method.patch create mode 100644 queue-5.10/bpf-sockmap-updating-the-sg-structure-should-also-up.patch create mode 100644 queue-5.10/hv_netvsc-rndis_filter-needs-to-select-nls.patch create mode 100644 queue-5.10/i40e-fix-unexpected-mfs-warning-message.patch create mode 100644 queue-5.10/ionic-fix-dim-work-handling-in-split-interrupt-mode.patch create mode 100644 queue-5.10/ionic-fix-snprintf-format-length-warning.patch create mode 100644 queue-5.10/ipv4-ip_gre-avoid-skb_pull-failure-in-ipgre_xmit.patch create mode 100644 queue-5.10/ipv6-fix-potential-null-deref-in-fib6_add.patch create mode 100644 queue-5.10/mlxbf-bootctl-correctly-identify-secure-boot-with-de.patch create mode 100644 queue-5.10/net-arcnet-com20020-fix-error-handling.patch create mode 100644 queue-5.10/net-bnxt-fix-a-potential-use-after-free-in-bnxt_init.patch create mode 100644 queue-5.10/net-hns-fix-fake-link-up-on-xge-port.patch create mode 100644 queue-5.10/netfilter-xt_owner-fix-for-unsafe-access-of-sk-sk_so.patch create mode 100644 queue-5.10/octeontx2-pf-add-missing-mutex-lock-in-otx2_get_paus.patch create mode 100644 queue-5.10/of-add-missing-return-section-in-kerneldoc-comments.patch create mode 100644 queue-5.10/of-base-fix-some-formatting-issues-and-provide-missi.patch create mode 100644 queue-5.10/of-dynamic-fix-of_reconfig_get_state_change-return-v.patch create mode 100644 queue-5.10/of-fix-kerneldoc-output-formatting.patch create mode 100644 queue-5.10/platform-x86-asus-nb-wmi-add-tablet_mode_sw-lid-flip.patch create mode 100644 queue-5.10/platform-x86-asus-nb-wmi-allow-configuring-sw_tablet.patch create mode 100644 queue-5.10/platform-x86-asus-wmi-add-support-for-rog-x13-tablet.patch create mode 100644 queue-5.10/platform-x86-asus-wmi-add-support-for-sw_tablet_mode.patch create mode 100644 queue-5.10/platform-x86-asus-wmi-adjust-tablet-lidflip-handling.patch create mode 100644 queue-5.10/platform-x86-asus-wmi-move-i8042-filter-install-to-s.patch create mode 100644 queue-5.10/platform-x86-asus-wmi-simplify-tablet-mode-switch-ha.patch create mode 100644 queue-5.10/platform-x86-asus-wmi-simplify-tablet-mode-switch-pr.patch create mode 100644 queue-5.10/tcp-do-not-accept-ack-of-bytes-we-never-sent.patch diff --git a/queue-5.10/arcnet-restoring-support-for-multiple-sohard-arcnet-.patch b/queue-5.10/arcnet-restoring-support-for-multiple-sohard-arcnet-.patch new file mode 100644 index 00000000000..b765f7c4e13 --- /dev/null +++ b/queue-5.10/arcnet-restoring-support-for-multiple-sohard-arcnet-.patch @@ -0,0 +1,216 @@ +From d41f4df0cef7063e80a9233e82cf0cd5eadfe6ed Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Nov 2023 12:35:03 +0100 +Subject: arcnet: restoring support for multiple Sohard Arcnet cards + +From: Thomas Reichinger + +[ Upstream commit 6b17a597fc2f13aaaa0a2780eb7edb9ae7ac9aea ] + +Probe of Sohard Arcnet cards fails, +if 2 or more cards are installed in a system. +See kernel log: +[ 2.759203] arcnet: arcnet loaded +[ 2.763648] arcnet:com20020: COM20020 chipset support (by David Woodhouse et al.) +[ 2.770585] arcnet:com20020_pci: COM20020 PCI support +[ 2.772295] com20020 0000:02:00.0: enabling device (0000 -> 0003) +[ 2.772354] (unnamed net_device) (uninitialized): PLX-PCI Controls +... +[ 3.071301] com20020 0000:02:00.0 arc0-0 (uninitialized): PCI COM20020: station FFh found at F080h, IRQ 101. +[ 3.071305] com20020 0000:02:00.0 arc0-0 (uninitialized): Using CKP 64 - data rate 2.5 Mb/s +[ 3.071534] com20020 0000:07:00.0: enabling device (0000 -> 0003) +[ 3.071581] (unnamed net_device) (uninitialized): PLX-PCI Controls +... +[ 3.369501] com20020 0000:07:00.0: Led pci:green:tx:0-0 renamed to pci:green:tx:0-0_1 due to name collision +[ 3.369535] com20020 0000:07:00.0: Led pci:red:recon:0-0 renamed to pci:red:recon:0-0_1 due to name collision +[ 3.370586] com20020 0000:07:00.0 arc0-0 (uninitialized): PCI COM20020: station E1h found at C000h, IRQ 35. +[ 3.370589] com20020 0000:07:00.0 arc0-0 (uninitialized): Using CKP 64 - data rate 2.5 Mb/s +[ 3.370608] com20020: probe of 0000:07:00.0 failed with error -5 + +commit 5ef216c1f848 ("arcnet: com20020-pci: add rotary index support") +changes the device name of all COM20020 based PCI cards, +even if only some cards support this: + snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i); + +The error happens because all Sohard Arcnet cards would be called arc0-0, +since the Sohard Arcnet cards don't have a PLX rotary coder. +I.e. EAE Arcnet cards have a PLX rotary coder, +which sets the first decimal, ensuring unique devices names. + +This patch adds two new card feature flags to indicate +which cards support LEDs and the PLX rotary coder. +For EAE based cards the names still depend on the PLX rotary coder +(untested, since missing EAE hardware). +For Sohard based cards, this patch will result in devices +being called arc0, arc1, ... (tested). + +Signed-off-by: Thomas Reichinger +Fixes: 5ef216c1f848 ("arcnet: com20020-pci: add rotary index support") +Link: https://lore.kernel.org/r/20231130113503.6812-1-thomas.reichinger@sohard.de +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/arcnet/arcdevice.h | 2 + + drivers/net/arcnet/com20020-pci.c | 89 ++++++++++++++++--------------- + 2 files changed, 48 insertions(+), 43 deletions(-) + +diff --git a/drivers/net/arcnet/arcdevice.h b/drivers/net/arcnet/arcdevice.h +index 5d4a4c7efbbff..deeabd6ec2e81 100644 +--- a/drivers/net/arcnet/arcdevice.h ++++ b/drivers/net/arcnet/arcdevice.h +@@ -186,6 +186,8 @@ do { \ + #define ARC_IS_5MBIT 1 /* card default speed is 5MBit */ + #define ARC_CAN_10MBIT 2 /* card uses COM20022, supporting 10MBit, + but default is 2.5MBit. */ ++#define ARC_HAS_LED 4 /* card has software controlled LEDs */ ++#define ARC_HAS_ROTARY 8 /* card has rotary encoder */ + + /* information needed to define an encapsulation driver */ + struct ArcProto { +diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c +index 28dccbc0e8d8f..9d9e4200064f9 100644 +--- a/drivers/net/arcnet/com20020-pci.c ++++ b/drivers/net/arcnet/com20020-pci.c +@@ -213,12 +213,13 @@ static int com20020pci_probe(struct pci_dev *pdev, + if (!strncmp(ci->name, "EAE PLX-PCI FB2", 15)) + lp->backplane = 1; + +- /* Get the dev_id from the PLX rotary coder */ +- if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15)) +- dev_id_mask = 0x3; +- dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask; +- +- snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i); ++ if (ci->flags & ARC_HAS_ROTARY) { ++ /* Get the dev_id from the PLX rotary coder */ ++ if (!strncmp(ci->name, "EAE PLX-PCI MA1", 15)) ++ dev_id_mask = 0x3; ++ dev->dev_id = (inb(priv->misc + ci->rotary) >> 4) & dev_id_mask; ++ snprintf(dev->name, sizeof(dev->name), "arc%d-%d", dev->dev_id, i); ++ } + + if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) { + pr_err("IO address %Xh is empty!\n", ioaddr); +@@ -230,6 +231,10 @@ static int com20020pci_probe(struct pci_dev *pdev, + goto err_free_arcdev; + } + ++ ret = com20020_found(dev, IRQF_SHARED); ++ if (ret) ++ goto err_free_arcdev; ++ + card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev), + GFP_KERNEL); + if (!card) { +@@ -239,41 +244,39 @@ static int com20020pci_probe(struct pci_dev *pdev, + + card->index = i; + card->pci_priv = priv; +- card->tx_led.brightness_set = led_tx_set; +- card->tx_led.default_trigger = devm_kasprintf(&pdev->dev, +- GFP_KERNEL, "arc%d-%d-tx", +- dev->dev_id, i); +- card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, +- "pci:green:tx:%d-%d", +- dev->dev_id, i); +- +- card->tx_led.dev = &dev->dev; +- card->recon_led.brightness_set = led_recon_set; +- card->recon_led.default_trigger = devm_kasprintf(&pdev->dev, +- GFP_KERNEL, "arc%d-%d-recon", +- dev->dev_id, i); +- card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, +- "pci:red:recon:%d-%d", +- dev->dev_id, i); +- card->recon_led.dev = &dev->dev; +- card->dev = dev; +- +- ret = devm_led_classdev_register(&pdev->dev, &card->tx_led); +- if (ret) +- goto err_free_arcdev; + +- ret = devm_led_classdev_register(&pdev->dev, &card->recon_led); +- if (ret) +- goto err_free_arcdev; +- +- dev_set_drvdata(&dev->dev, card); +- +- ret = com20020_found(dev, IRQF_SHARED); +- if (ret) +- goto err_free_arcdev; +- +- devm_arcnet_led_init(dev, dev->dev_id, i); ++ if (ci->flags & ARC_HAS_LED) { ++ card->tx_led.brightness_set = led_tx_set; ++ card->tx_led.default_trigger = devm_kasprintf(&pdev->dev, ++ GFP_KERNEL, "arc%d-%d-tx", ++ dev->dev_id, i); ++ card->tx_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, ++ "pci:green:tx:%d-%d", ++ dev->dev_id, i); ++ ++ card->tx_led.dev = &dev->dev; ++ card->recon_led.brightness_set = led_recon_set; ++ card->recon_led.default_trigger = devm_kasprintf(&pdev->dev, ++ GFP_KERNEL, "arc%d-%d-recon", ++ dev->dev_id, i); ++ card->recon_led.name = devm_kasprintf(&pdev->dev, GFP_KERNEL, ++ "pci:red:recon:%d-%d", ++ dev->dev_id, i); ++ card->recon_led.dev = &dev->dev; ++ ++ ret = devm_led_classdev_register(&pdev->dev, &card->tx_led); ++ if (ret) ++ goto err_free_arcdev; ++ ++ ret = devm_led_classdev_register(&pdev->dev, &card->recon_led); ++ if (ret) ++ goto err_free_arcdev; ++ ++ dev_set_drvdata(&dev->dev, card); ++ devm_arcnet_led_init(dev, dev->dev_id, i); ++ } + ++ card->dev = dev; + list_add(&card->list, &priv->list_dev); + continue; + +@@ -329,7 +332,7 @@ static struct com20020_pci_card_info card_info_5mbit = { + }; + + static struct com20020_pci_card_info card_info_sohard = { +- .name = "PLX-PCI", ++ .name = "SOHARD SH ARC-PCI", + .devcount = 1, + /* SOHARD needs PCI base addr 4 */ + .chan_map_tbl = { +@@ -364,7 +367,7 @@ static struct com20020_pci_card_info card_info_eae_arc1 = { + }, + }, + .rotary = 0x0, +- .flags = ARC_CAN_10MBIT, ++ .flags = ARC_HAS_ROTARY | ARC_HAS_LED | ARC_CAN_10MBIT, + }; + + static struct com20020_pci_card_info card_info_eae_ma1 = { +@@ -396,7 +399,7 @@ static struct com20020_pci_card_info card_info_eae_ma1 = { + }, + }, + .rotary = 0x0, +- .flags = ARC_CAN_10MBIT, ++ .flags = ARC_HAS_ROTARY | ARC_HAS_LED | ARC_CAN_10MBIT, + }; + + static struct com20020_pci_card_info card_info_eae_fb2 = { +@@ -421,7 +424,7 @@ static struct com20020_pci_card_info card_info_eae_fb2 = { + }, + }, + .rotary = 0x0, +- .flags = ARC_CAN_10MBIT, ++ .flags = ARC_HAS_ROTARY | ARC_HAS_LED | ARC_CAN_10MBIT, + }; + + static const struct pci_device_id com20020pci_id_table[] = { +-- +2.42.0 + diff --git a/queue-5.10/asus-wmi-add-dgpu-disable-method.patch b/queue-5.10/asus-wmi-add-dgpu-disable-method.patch new file mode 100644 index 00000000000..28d41ecc33a --- /dev/null +++ b/queue-5.10/asus-wmi-add-dgpu-disable-method.patch @@ -0,0 +1,190 @@ +From fb1ba48f2fdac56eac87a200bba0ed9ddc3caf1d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 7 Aug 2021 14:36:55 +1200 +Subject: asus-wmi: Add dgpu disable method + +From: Luke D. Jones + +[ Upstream commit 98829e84dc67630efb7de675f0a70066620468a3 ] + +In Windows the ASUS Armory Crate program can enable or disable the +dGPU via a WMI call. This functions much the same as various Linux +methods in software where the dGPU is removed from the device tree. + +However the WMI call saves the state of dGPU (enabled or not) and +this then changes the dGPU visibility in Linux with no way for +Linux users to re-enable it. We expose the WMI method so users can +see and change the dGPU ACPI state. + +Signed-off-by: Luke D. Jones +Link: https://lore.kernel.org/r/20210807023656.25020-3-luke@ljones.dev +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Stable-dep-of: b52cbca22cbf ("platform/x86: asus-wmi: Move i8042 filter install to shared asus-wmi code") +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/asus-wmi.c | 98 ++++++++++++++++++++++ + include/linux/platform_data/x86/asus-wmi.h | 3 + + 2 files changed, 101 insertions(+) + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index ca3b97b7a6ad8..93b4c61130837 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -207,6 +207,9 @@ struct asus_wmi { + u8 fan_boost_mode_mask; + u8 fan_boost_mode; + ++ bool dgpu_disable_available; ++ bool dgpu_disable; ++ + bool throttle_thermal_policy_available; + u8 throttle_thermal_policy_mode; + +@@ -421,6 +424,93 @@ static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus) + } + } + ++/* dGPU ********************************************************************/ ++static int dgpu_disable_check_present(struct asus_wmi *asus) ++{ ++ u32 result; ++ int err; ++ ++ asus->dgpu_disable_available = false; ++ ++ err = asus_wmi_get_devstate(asus, ASUS_WMI_DEVID_DGPU, &result); ++ if (err) { ++ if (err == -ENODEV) ++ return 0; ++ return err; ++ } ++ ++ if (result & ASUS_WMI_DSTS_PRESENCE_BIT) { ++ asus->dgpu_disable_available = true; ++ asus->dgpu_disable = result & ASUS_WMI_DSTS_STATUS_BIT; ++ } ++ ++ return 0; ++} ++ ++static int dgpu_disable_write(struct asus_wmi *asus) ++{ ++ u32 retval; ++ u8 value; ++ int err; ++ ++ /* Don't rely on type conversion */ ++ value = asus->dgpu_disable ? 1 : 0; ++ ++ err = asus_wmi_set_devstate(ASUS_WMI_DEVID_DGPU, value, &retval); ++ if (err) { ++ pr_warn("Failed to set dgpu disable: %d\n", err); ++ return err; ++ } ++ ++ if (retval > 1 || retval < 0) { ++ pr_warn("Failed to set dgpu disable (retval): 0x%x\n", retval); ++ return -EIO; ++ } ++ ++ sysfs_notify(&asus->platform_device->dev.kobj, NULL, "dgpu_disable"); ++ ++ return 0; ++} ++ ++static ssize_t dgpu_disable_show(struct device *dev, ++ struct device_attribute *attr, char *buf) ++{ ++ struct asus_wmi *asus = dev_get_drvdata(dev); ++ u8 mode = asus->dgpu_disable; ++ ++ return sysfs_emit(buf, "%d\n", mode); ++} ++ ++/* ++ * A user may be required to store the value twice, typcial store first, then ++ * rescan PCI bus to activate power, then store a second time to save correctly. ++ * The reason for this is that an extra code path in the ACPI is enabled when ++ * the device and bus are powered. ++ */ ++static ssize_t dgpu_disable_store(struct device *dev, ++ struct device_attribute *attr, ++ const char *buf, size_t count) ++{ ++ bool disable; ++ int result; ++ ++ struct asus_wmi *asus = dev_get_drvdata(dev); ++ ++ result = kstrtobool(buf, &disable); ++ if (result) ++ return result; ++ ++ asus->dgpu_disable = disable; ++ ++ result = dgpu_disable_write(asus); ++ if (result) ++ return result; ++ ++ return count; ++} ++ ++static DEVICE_ATTR_RW(dgpu_disable); ++ + /* Battery ********************************************************************/ + + /* The battery maximum charging percentage */ +@@ -2319,6 +2409,7 @@ static struct attribute *platform_attributes[] = { + &dev_attr_camera.attr, + &dev_attr_cardr.attr, + &dev_attr_touchpad.attr, ++ &dev_attr_dgpu_disable.attr, + &dev_attr_lid_resume.attr, + &dev_attr_als_enable.attr, + &dev_attr_fan_boost_mode.attr, +@@ -2344,6 +2435,8 @@ static umode_t asus_sysfs_is_visible(struct kobject *kobj, + devid = ASUS_WMI_DEVID_LID_RESUME; + else if (attr == &dev_attr_als_enable.attr) + devid = ASUS_WMI_DEVID_ALS_ENABLE; ++ else if (attr == &dev_attr_dgpu_disable.attr) ++ ok = asus->dgpu_disable_available; + else if (attr == &dev_attr_fan_boost_mode.attr) + ok = asus->fan_boost_mode_available; + else if (attr == &dev_attr_throttle_thermal_policy.attr) +@@ -2603,6 +2696,10 @@ static int asus_wmi_add(struct platform_device *pdev) + if (err) + goto fail_platform; + ++ err = dgpu_disable_check_present(asus); ++ if (err) ++ goto fail_dgpu_disable; ++ + err = fan_boost_mode_check_present(asus); + if (err) + goto fail_fan_boost_mode; +@@ -2699,6 +2796,7 @@ static int asus_wmi_add(struct platform_device *pdev) + fail_sysfs: + fail_throttle_thermal_policy: + fail_fan_boost_mode: ++fail_dgpu_disable: + fail_platform: + kfree(asus); + return err; +diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h +index 2f274cf528050..7d8d3e9c45d62 100644 +--- a/include/linux/platform_data/x86/asus-wmi.h ++++ b/include/linux/platform_data/x86/asus-wmi.h +@@ -89,6 +89,9 @@ + /* Keyboard dock */ + #define ASUS_WMI_DEVID_KBD_DOCK 0x00120063 + ++/* dgpu on/off */ ++#define ASUS_WMI_DEVID_DGPU 0x00090020 ++ + /* DSTS masks */ + #define ASUS_WMI_DSTS_STATUS_BIT 0x00000001 + #define ASUS_WMI_DSTS_UNKNOWN_BIT 0x00000002 +-- +2.42.0 + diff --git a/queue-5.10/bpf-sockmap-updating-the-sg-structure-should-also-up.patch b/queue-5.10/bpf-sockmap-updating-the-sg-structure-should-also-up.patch new file mode 100644 index 00000000000..06c4b138b7d --- /dev/null +++ b/queue-5.10/bpf-sockmap-updating-the-sg-structure-should-also-up.patch @@ -0,0 +1,74 @@ +From 14794c422d775191580d14076b76737302da3e9f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 6 Dec 2023 15:27:06 -0800 +Subject: bpf: sockmap, updating the sg structure should also update curr + +From: John Fastabend + +[ Upstream commit bb9aefde5bbaf6c168c77ba635c155b4980c2287 ] + +Curr pointer should be updated when the sg structure is shifted. + +Fixes: 7246d8ed4dcce ("bpf: helper to pop data from messages") +Signed-off-by: John Fastabend +Link: https://lore.kernel.org/r/20231206232706.374377-3-john.fastabend@gmail.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/core/filter.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/net/core/filter.c b/net/core/filter.c +index ea8ab9c704832..6cfc8fb0562a2 100644 +--- a/net/core/filter.c ++++ b/net/core/filter.c +@@ -2595,6 +2595,22 @@ BPF_CALL_2(bpf_msg_cork_bytes, struct sk_msg *, msg, u32, bytes) + return 0; + } + ++static void sk_msg_reset_curr(struct sk_msg *msg) ++{ ++ u32 i = msg->sg.start; ++ u32 len = 0; ++ ++ do { ++ len += sk_msg_elem(msg, i)->length; ++ sk_msg_iter_var_next(i); ++ if (len >= msg->sg.size) ++ break; ++ } while (i != msg->sg.end); ++ ++ msg->sg.curr = i; ++ msg->sg.copybreak = 0; ++} ++ + static const struct bpf_func_proto bpf_msg_cork_bytes_proto = { + .func = bpf_msg_cork_bytes, + .gpl_only = false, +@@ -2714,6 +2730,7 @@ BPF_CALL_4(bpf_msg_pull_data, struct sk_msg *, msg, u32, start, + msg->sg.end - shift + NR_MSG_FRAG_IDS : + msg->sg.end - shift; + out: ++ sk_msg_reset_curr(msg); + msg->data = sg_virt(&msg->sg.data[first_sge]) + start - offset; + msg->data_end = msg->data + bytes; + return 0; +@@ -2850,6 +2867,7 @@ BPF_CALL_4(bpf_msg_push_data, struct sk_msg *, msg, u32, start, + msg->sg.data[new] = rsge; + } + ++ sk_msg_reset_curr(msg); + sk_msg_compute_data_pointers(msg); + return 0; + } +@@ -3018,6 +3036,7 @@ BPF_CALL_4(bpf_msg_pop_data, struct sk_msg *, msg, u32, start, + + sk_mem_uncharge(msg->sk, len - pop); + msg->sg.size -= (len - pop); ++ sk_msg_reset_curr(msg); + sk_msg_compute_data_pointers(msg); + return 0; + } +-- +2.42.0 + diff --git a/queue-5.10/hv_netvsc-rndis_filter-needs-to-select-nls.patch b/queue-5.10/hv_netvsc-rndis_filter-needs-to-select-nls.patch new file mode 100644 index 00000000000..0f7f5b26f12 --- /dev/null +++ b/queue-5.10/hv_netvsc-rndis_filter-needs-to-select-nls.patch @@ -0,0 +1,44 @@ +From 33867301e25a2a0e8d72211007b40eeb6b711c74 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Nov 2023 21:58:53 -0800 +Subject: hv_netvsc: rndis_filter needs to select NLS + +From: Randy Dunlap + +[ Upstream commit 6c89f49964375c904cea33c0247467873f4daf2c ] + +rndis_filter uses utf8s_to_utf16s() which is provided by setting +NLS, so select NLS to fix the build error: + +ERROR: modpost: "utf8s_to_utf16s" [drivers/net/hyperv/hv_netvsc.ko] undefined! + +Fixes: 1ce09e899d28 ("hyperv: Add support for setting MAC from within guests") +Signed-off-by: Randy Dunlap +Cc: Haiyang Zhang +Cc: K. Y. Srinivasan +Cc: Wei Liu +Cc: Dexuan Cui +Reviewed-by: Simon Horman +Tested-by: Simon Horman # build-tested +Reviewed-by: Michael Kelley +Link: https://lore.kernel.org/r/20231130055853.19069-1-rdunlap@infradead.org +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/hyperv/Kconfig | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/hyperv/Kconfig b/drivers/net/hyperv/Kconfig +index ca7bf7f897d36..c8cbd85adcf99 100644 +--- a/drivers/net/hyperv/Kconfig ++++ b/drivers/net/hyperv/Kconfig +@@ -3,5 +3,6 @@ config HYPERV_NET + tristate "Microsoft Hyper-V virtual network driver" + depends on HYPERV + select UCS2_STRING ++ select NLS + help + Select this option to enable the Hyper-V virtual network driver. +-- +2.42.0 + diff --git a/queue-5.10/i40e-fix-unexpected-mfs-warning-message.patch b/queue-5.10/i40e-fix-unexpected-mfs-warning-message.patch new file mode 100644 index 00000000000..2b4cc42f741 --- /dev/null +++ b/queue-5.10/i40e-fix-unexpected-mfs-warning-message.patch @@ -0,0 +1,58 @@ +From aaa90ee5797e1a4aa7e793fe7218bd7ba9cfe05d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 10 Nov 2023 09:12:09 +0100 +Subject: i40e: Fix unexpected MFS warning message + +From: Ivan Vecera + +[ Upstream commit 7d9f22b3d3ef379ed05bd3f3e2de83dfa8da8258 ] + +Commit 3a2c6ced90e1 ("i40e: Add a check to see if MFS is set") added +a warning message that reports unexpected size of port's MFS (max +frame size) value. This message use for the port number local +variable 'i' that is wrong. +In i40e_probe() this 'i' variable is used only to iterate VSIs +to find FDIR VSI: + + +... +/* if FDIR VSI was set up, start it now */ + for (i = 0; i < pf->num_alloc_vsi; i++) { + if (pf->vsi[i] && pf->vsi[i]->type == I40E_VSI_FDIR) { + i40e_vsi_open(pf->vsi[i]); + break; + } + } +... + + +So the warning message use for the port number index of FDIR VSI +if this exists or pf->num_alloc_vsi if not. + +Fix the message by using 'pf->hw.port' for the port number. + +Fixes: 3a2c6ced90e1 ("i40e: Add a check to see if MFS is set") +Signed-off-by: Ivan Vecera +Reviewed-by: Simon Horman +Signed-off-by: Tony Nguyen +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/intel/i40e/i40e_main.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c +index 64e1f6f407b48..36e387ae967f7 100644 +--- a/drivers/net/ethernet/intel/i40e/i40e_main.c ++++ b/drivers/net/ethernet/intel/i40e/i40e_main.c +@@ -15480,7 +15480,7 @@ static int i40e_probe(struct pci_dev *pdev, const struct pci_device_id *ent) + I40E_PRTGL_SAH_MFS_MASK) >> I40E_PRTGL_SAH_MFS_SHIFT; + if (val < MAX_FRAME_SIZE_DEFAULT) + dev_warn(&pdev->dev, "MFS for port %x has been set below the default: %x\n", +- i, val); ++ pf->hw.port, val); + + /* Add a filter to drop all Flow control frames from any VSI from being + * transmitted. By doing so we stop a malicious VF from sending out +-- +2.42.0 + diff --git a/queue-5.10/ionic-fix-dim-work-handling-in-split-interrupt-mode.patch b/queue-5.10/ionic-fix-dim-work-handling-in-split-interrupt-mode.patch new file mode 100644 index 00000000000..50973337578 --- /dev/null +++ b/queue-5.10/ionic-fix-dim-work-handling-in-split-interrupt-mode.patch @@ -0,0 +1,67 @@ +From 9a70f5a7463e07ef1a04f593e820750cbc553dd0 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Dec 2023 11:22:34 -0800 +Subject: ionic: Fix dim work handling in split interrupt mode + +From: Brett Creeley + +[ Upstream commit 4115ba677c35f694b62298e55f0e04ce84eed469 ] + +Currently ionic_dim_work() is incorrect when in +split interrupt mode. This is because the interrupt +rate is only being changed for the Rx side even for +dim running on Tx. Fix this by using the qcq from +the container_of macro. Also, introduce some local +variables for a bit of cleanup. + +Fixes: a6ff85e0a2d9 ("ionic: remove intr coalesce update from napi") +Signed-off-by: Brett Creeley +Signed-off-by: Shannon Nelson +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/20231204192234.21017-3-shannon.nelson@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/pensando/ionic/ionic_lif.c | 16 ++++++++-------- + 1 file changed, 8 insertions(+), 8 deletions(-) + +diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +index 098772601df8c..49c28134ac2cc 100644 +--- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c ++++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c +@@ -45,24 +45,24 @@ static void ionic_lif_queue_identify(struct ionic_lif *lif); + static void ionic_dim_work(struct work_struct *work) + { + struct dim *dim = container_of(work, struct dim, work); ++ struct ionic_intr_info *intr; + struct dim_cq_moder cur_moder; + struct ionic_qcq *qcq; ++ struct ionic_lif *lif; + u32 new_coal; + + cur_moder = net_dim_get_rx_moderation(dim->mode, dim->profile_ix); + qcq = container_of(dim, struct ionic_qcq, dim); +- new_coal = ionic_coal_usec_to_hw(qcq->q.lif->ionic, cur_moder.usec); ++ lif = qcq->q.lif; ++ new_coal = ionic_coal_usec_to_hw(lif->ionic, cur_moder.usec); + new_coal = new_coal ? new_coal : 1; + +- if (qcq->intr.dim_coal_hw != new_coal) { +- unsigned int qi = qcq->cq.bound_q->index; +- struct ionic_lif *lif = qcq->q.lif; +- +- qcq->intr.dim_coal_hw = new_coal; ++ intr = &qcq->intr; ++ if (intr->dim_coal_hw != new_coal) { ++ intr->dim_coal_hw = new_coal; + + ionic_intr_coal_init(lif->ionic->idev.intr_ctrl, +- lif->rxqcqs[qi]->intr.index, +- qcq->intr.dim_coal_hw); ++ intr->index, intr->dim_coal_hw); + } + + dim->state = DIM_START_MEASURE; +-- +2.42.0 + diff --git a/queue-5.10/ionic-fix-snprintf-format-length-warning.patch b/queue-5.10/ionic-fix-snprintf-format-length-warning.patch new file mode 100644 index 00000000000..c66b0eb67a1 --- /dev/null +++ b/queue-5.10/ionic-fix-snprintf-format-length-warning.patch @@ -0,0 +1,45 @@ +From 195a0444bd1456b551b385dfc24ab1381c76792b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Dec 2023 11:22:33 -0800 +Subject: ionic: fix snprintf format length warning + +From: Shannon Nelson + +[ Upstream commit 0ceb3860a67652f9d36dfdecfcd2cb3eb2f4537d ] + +Our friendly kernel test robot has reminded us that with a new +check we have a warning about a potential string truncation. +In this case it really doesn't hurt anything, but it is worth +addressing especially since there really is no reason to reserve +so many bytes for our queue names. It seems that cutting the +queue name buffer length in half stops the complaint. + +Fixes: c06107cabea3 ("ionic: more ionic name tweaks") +Reported-by: kernel test robot +Closes: https://lore.kernel.org/oe-kbuild-all/202311300201.lO8v7mKU-lkp@intel.com/ +Signed-off-by: Shannon Nelson +Reviewed-by: Brett Creeley +Reviewed-by: Florian Fainelli +Link: https://lore.kernel.org/r/20231204192234.21017-2-shannon.nelson@amd.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/pensando/ionic/ionic_dev.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/pensando/ionic/ionic_dev.h b/drivers/net/ethernet/pensando/ionic/ionic_dev.h +index 6c243b17312c7..64d27e8e07725 100644 +--- a/drivers/net/ethernet/pensando/ionic/ionic_dev.h ++++ b/drivers/net/ethernet/pensando/ionic/ionic_dev.h +@@ -191,7 +191,7 @@ struct ionic_desc_info { + void *cb_arg; + }; + +-#define IONIC_QUEUE_NAME_MAX_SZ 32 ++#define IONIC_QUEUE_NAME_MAX_SZ 16 + + struct ionic_queue { + struct device *dev; +-- +2.42.0 + diff --git a/queue-5.10/ipv4-ip_gre-avoid-skb_pull-failure-in-ipgre_xmit.patch b/queue-5.10/ipv4-ip_gre-avoid-skb_pull-failure-in-ipgre_xmit.patch new file mode 100644 index 00000000000..93891f97c98 --- /dev/null +++ b/queue-5.10/ipv4-ip_gre-avoid-skb_pull-failure-in-ipgre_xmit.patch @@ -0,0 +1,58 @@ +From 34b09521fa1acff61ca73ac415f438c78c04eb19 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Dec 2023 01:14:41 +0900 +Subject: ipv4: ip_gre: Avoid skb_pull() failure in ipgre_xmit() + +From: Shigeru Yoshida + +[ Upstream commit 80d875cfc9d3711a029f234ef7d680db79e8fa4b ] + +In ipgre_xmit(), skb_pull() may fail even if pskb_inet_may_pull() returns +true. For example, applications can use PF_PACKET to create a malformed +packet with no IP header. This type of packet causes a problem such as +uninit-value access. + +This patch ensures that skb_pull() can pull the required size by checking +the skb with pskb_network_may_pull() before skb_pull(). + +Fixes: c54419321455 ("GRE: Refactor GRE tunneling code.") +Signed-off-by: Shigeru Yoshida +Reviewed-by: Eric Dumazet +Reviewed-by: Suman Ghosh +Link: https://lore.kernel.org/r/20231202161441.221135-1-syoshida@redhat.com +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + net/ipv4/ip_gre.c | 11 +++++++---- + 1 file changed, 7 insertions(+), 4 deletions(-) + +diff --git a/net/ipv4/ip_gre.c b/net/ipv4/ip_gre.c +index 9d1a506571043..a6ad0fe1387c0 100644 +--- a/net/ipv4/ip_gre.c ++++ b/net/ipv4/ip_gre.c +@@ -629,15 +629,18 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb, + } + + if (dev->header_ops) { ++ int pull_len = tunnel->hlen + sizeof(struct iphdr); ++ + if (skb_cow_head(skb, 0)) + goto free_skb; + + tnl_params = (const struct iphdr *)skb->data; + +- /* Pull skb since ip_tunnel_xmit() needs skb->data pointing +- * to gre header. +- */ +- skb_pull(skb, tunnel->hlen + sizeof(struct iphdr)); ++ if (!pskb_network_may_pull(skb, pull_len)) ++ goto free_skb; ++ ++ /* ip_tunnel_xmit() needs skb->data pointing to gre header. */ ++ skb_pull(skb, pull_len); + skb_reset_mac_header(skb); + + if (skb->ip_summed == CHECKSUM_PARTIAL && +-- +2.42.0 + diff --git a/queue-5.10/ipv6-fix-potential-null-deref-in-fib6_add.patch b/queue-5.10/ipv6-fix-potential-null-deref-in-fib6_add.patch new file mode 100644 index 00000000000..0e1ab899769 --- /dev/null +++ b/queue-5.10/ipv6-fix-potential-null-deref-in-fib6_add.patch @@ -0,0 +1,79 @@ +From 57b0c5ae6b6436c20335dce44e8a7600013a1745 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Nov 2023 16:06:30 +0000 +Subject: ipv6: fix potential NULL deref in fib6_add() + +From: Eric Dumazet + +[ Upstream commit 75475bb51e78a3f54ad2f69380f2a1c985e85f2d ] + +If fib6_find_prefix() returns NULL, we should silently fallback +using fib6_null_entry regardless of RT6_DEBUG value. + +syzbot reported: + +WARNING: CPU: 0 PID: 5477 at net/ipv6/ip6_fib.c:1516 fib6_add+0x310d/0x3fa0 net/ipv6/ip6_fib.c:1516 +Modules linked in: +CPU: 0 PID: 5477 Comm: syz-executor.0 Not tainted 6.7.0-rc2-syzkaller-00029-g9b6de136b5f0 #0 +Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 11/10/2023 +RIP: 0010:fib6_add+0x310d/0x3fa0 net/ipv6/ip6_fib.c:1516 +Code: 00 48 8b 54 24 68 e8 42 22 00 00 48 85 c0 74 14 49 89 c6 e8 d5 d3 c2 f7 eb 5d e8 ce d3 c2 f7 e9 ca 00 00 00 e8 c4 d3 c2 f7 90 <0f> 0b 90 48 b8 00 00 00 00 00 fc ff df 48 8b 4c 24 38 80 3c 01 00 +RSP: 0018:ffffc90005067740 EFLAGS: 00010293 +RAX: ffffffff89cba5bc RBX: ffffc90005067ab0 RCX: ffff88801a2e9dc0 +RDX: 0000000000000000 RSI: 0000000000000001 RDI: 0000000000000000 +RBP: ffffc90005067980 R08: ffffffff89cbca85 R09: 1ffff110040d4b85 +R10: dffffc0000000000 R11: ffffed10040d4b86 R12: 00000000ffffffff +R13: 1ffff110051c3904 R14: ffff8880206a5c00 R15: ffff888028e1c820 +FS: 00007f763783c6c0(0000) GS:ffff8880b9800000(0000) knlGS:0000000000000000 +CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +CR2: 00007f763783bff8 CR3: 000000007f74d000 CR4: 00000000003506f0 +DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +Call Trace: + +__ip6_ins_rt net/ipv6/route.c:1303 [inline] +ip6_route_add+0x88/0x120 net/ipv6/route.c:3847 +ipv6_route_ioctl+0x525/0x7b0 net/ipv6/route.c:4467 +inet6_ioctl+0x21a/0x270 net/ipv6/af_inet6.c:575 +sock_do_ioctl+0x152/0x460 net/socket.c:1220 +sock_ioctl+0x615/0x8c0 net/socket.c:1339 +vfs_ioctl fs/ioctl.c:51 [inline] +__do_sys_ioctl fs/ioctl.c:871 [inline] +__se_sys_ioctl+0xf8/0x170 fs/ioctl.c:857 +do_syscall_x64 arch/x86/entry/common.c:51 [inline] +do_syscall_64+0x45/0x110 arch/x86/entry/common.c:82 + +Fixes: 7bbfe00e0252 ("ipv6: fix general protection fault in fib6_add()") +Reported-by: syzbot +Signed-off-by: Eric Dumazet +Cc: Wei Wang +Reviewed-by: David Ahern +Link: https://lore.kernel.org/r/20231129160630.3509216-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv6/ip6_fib.c | 6 +----- + 1 file changed, 1 insertion(+), 5 deletions(-) + +diff --git a/net/ipv6/ip6_fib.c b/net/ipv6/ip6_fib.c +index c783b91231321..608205c632c8c 100644 +--- a/net/ipv6/ip6_fib.c ++++ b/net/ipv6/ip6_fib.c +@@ -1499,13 +1499,9 @@ int fib6_add(struct fib6_node *root, struct fib6_info *rt, + if (!pn_leaf && !(pn->fn_flags & RTN_RTINFO)) { + pn_leaf = fib6_find_prefix(info->nl_net, table, + pn); +-#if RT6_DEBUG >= 2 +- if (!pn_leaf) { +- WARN_ON(!pn_leaf); ++ if (!pn_leaf) + pn_leaf = + info->nl_net->ipv6.fib6_null_entry; +- } +-#endif + fib6_info_hold(pn_leaf); + rcu_assign_pointer(pn->leaf, pn_leaf); + } +-- +2.42.0 + diff --git a/queue-5.10/mlxbf-bootctl-correctly-identify-secure-boot-with-de.patch b/queue-5.10/mlxbf-bootctl-correctly-identify-secure-boot-with-de.patch new file mode 100644 index 00000000000..f49e5bdecfd --- /dev/null +++ b/queue-5.10/mlxbf-bootctl-correctly-identify-secure-boot-with-de.patch @@ -0,0 +1,120 @@ +From 656cb56fa56f40b920d27691a827c9207f954d16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 30 Nov 2023 13:35:15 -0500 +Subject: mlxbf-bootctl: correctly identify secure boot with development keys +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: David Thompson + +[ Upstream commit d4eef75279f5e9d594f5785502038c763ce42268 ] + +The secure boot state of the BlueField SoC is represented by two bits: + 0 = production state + 1 = secure boot enabled + 2 = non-secure (secure boot disabled) + 3 = RMA state +There is also a single bit to indicate whether production keys or +development keys are being used when secure boot is enabled. +This single bit (specified by MLXBF_BOOTCTL_SB_DEV_MASK) only has +meaning if secure boot state equals 1 (secure boot enabled). + +The secure boot states are as follows: +- “GA secured” is when secure boot is enabled with official production keys. +- “Secured (development)” is when secure boot is enabled with development keys. + +Without this fix “GA Secured” is displayed on development cards which is +misleading. This patch updates the logic in "lifecycle_state_show()" to +handle the case where the SoC is configured for secure boot and is using +development keys. + +Fixes: 79e29cb8fbc5c ("platform/mellanox: Add bootctl driver for Mellanox BlueField Soc") +Reviewed-by: Khalil Blaiech +Signed-off-by: David Thompson +Link: https://lore.kernel.org/r/20231130183515.17214-1-davthompson@nvidia.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/mellanox/mlxbf-bootctl.c | 39 +++++++++++++++-------- + 1 file changed, 26 insertions(+), 13 deletions(-) + +diff --git a/drivers/platform/mellanox/mlxbf-bootctl.c b/drivers/platform/mellanox/mlxbf-bootctl.c +index 5d21c6adf1ab6..9911d4f854696 100644 +--- a/drivers/platform/mellanox/mlxbf-bootctl.c ++++ b/drivers/platform/mellanox/mlxbf-bootctl.c +@@ -17,6 +17,7 @@ + + #define MLXBF_BOOTCTL_SB_SECURE_MASK 0x03 + #define MLXBF_BOOTCTL_SB_TEST_MASK 0x0c ++#define MLXBF_BOOTCTL_SB_DEV_MASK BIT(4) + + #define MLXBF_SB_KEY_NUM 4 + +@@ -37,11 +38,18 @@ static struct mlxbf_bootctl_name boot_names[] = { + { MLXBF_BOOTCTL_NONE, "none" }, + }; + ++enum { ++ MLXBF_BOOTCTL_SB_LIFECYCLE_PRODUCTION = 0, ++ MLXBF_BOOTCTL_SB_LIFECYCLE_GA_SECURE = 1, ++ MLXBF_BOOTCTL_SB_LIFECYCLE_GA_NON_SECURE = 2, ++ MLXBF_BOOTCTL_SB_LIFECYCLE_RMA = 3 ++}; ++ + static const char * const mlxbf_bootctl_lifecycle_states[] = { +- [0] = "Production", +- [1] = "GA Secured", +- [2] = "GA Non-Secured", +- [3] = "RMA", ++ [MLXBF_BOOTCTL_SB_LIFECYCLE_PRODUCTION] = "Production", ++ [MLXBF_BOOTCTL_SB_LIFECYCLE_GA_SECURE] = "GA Secured", ++ [MLXBF_BOOTCTL_SB_LIFECYCLE_GA_NON_SECURE] = "GA Non-Secured", ++ [MLXBF_BOOTCTL_SB_LIFECYCLE_RMA] = "RMA", + }; + + /* ARM SMC call which is atomic and no need for lock. */ +@@ -165,25 +173,30 @@ static ssize_t second_reset_action_store(struct device *dev, + static ssize_t lifecycle_state_show(struct device *dev, + struct device_attribute *attr, char *buf) + { ++ int status_bits; ++ int use_dev_key; ++ int test_state; + int lc_state; + +- lc_state = mlxbf_bootctl_smc(MLXBF_BOOTCTL_GET_TBB_FUSE_STATUS, +- MLXBF_BOOTCTL_FUSE_STATUS_LIFECYCLE); +- if (lc_state < 0) +- return lc_state; ++ status_bits = mlxbf_bootctl_smc(MLXBF_BOOTCTL_GET_TBB_FUSE_STATUS, ++ MLXBF_BOOTCTL_FUSE_STATUS_LIFECYCLE); ++ if (status_bits < 0) ++ return status_bits; + +- lc_state &= +- MLXBF_BOOTCTL_SB_TEST_MASK | MLXBF_BOOTCTL_SB_SECURE_MASK; ++ use_dev_key = status_bits & MLXBF_BOOTCTL_SB_DEV_MASK; ++ test_state = status_bits & MLXBF_BOOTCTL_SB_TEST_MASK; ++ lc_state = status_bits & MLXBF_BOOTCTL_SB_SECURE_MASK; + + /* + * If the test bits are set, we specify that the current state may be + * due to using the test bits. + */ +- if (lc_state & MLXBF_BOOTCTL_SB_TEST_MASK) { +- lc_state &= MLXBF_BOOTCTL_SB_SECURE_MASK; +- ++ if (test_state) { + return sprintf(buf, "%s(test)\n", + mlxbf_bootctl_lifecycle_states[lc_state]); ++ } else if (use_dev_key && ++ (lc_state == MLXBF_BOOTCTL_SB_LIFECYCLE_GA_SECURE)) { ++ return sprintf(buf, "Secured (development)\n"); + } + + return sprintf(buf, "%s\n", mlxbf_bootctl_lifecycle_states[lc_state]); +-- +2.42.0 + diff --git a/queue-5.10/net-arcnet-com20020-fix-error-handling.patch b/queue-5.10/net-arcnet-com20020-fix-error-handling.patch new file mode 100644 index 00000000000..5a381ac86c8 --- /dev/null +++ b/queue-5.10/net-arcnet-com20020-fix-error-handling.patch @@ -0,0 +1,137 @@ +From 7ac1392bf27e4b114f4b2aeb9afc211074217c89 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 14 Mar 2021 14:08:36 -0400 +Subject: net: arcnet: com20020 fix error handling + +From: Tong Zhang + +[ Upstream commit 6577b9a551aedb86bca6d4438c28386361845108 ] + +There are two issues when handling error case in com20020pci_probe() + +1. priv might be not initialized yet when calling com20020pci_remove() +from com20020pci_probe(), since the priv is set at the very last but it +can jump to error handling in the middle and priv remains NULL. +2. memory leak - the net device is allocated in alloc_arcdev but not +properly released if error happens in the middle of the big for loop + +[ 1.529110] BUG: kernel NULL pointer dereference, address: 0000000000000008 +[ 1.531447] RIP: 0010:com20020pci_remove+0x15/0x60 [com20020_pci] +[ 1.536805] Call Trace: +[ 1.536939] com20020pci_probe+0x3f2/0x48c [com20020_pci] +[ 1.537226] local_pci_probe+0x48/0x80 +[ 1.539918] com20020pci_init+0x3f/0x1000 [com20020_pci] + +Signed-off-by: Tong Zhang +Signed-off-by: David S. Miller +Stable-dep-of: 6b17a597fc2f ("arcnet: restoring support for multiple Sohard Arcnet cards") +Signed-off-by: Sasha Levin +--- + drivers/net/arcnet/com20020-pci.c | 34 +++++++++++++++++-------------- + 1 file changed, 19 insertions(+), 15 deletions(-) + +diff --git a/drivers/net/arcnet/com20020-pci.c b/drivers/net/arcnet/com20020-pci.c +index b4f8798d8c509..28dccbc0e8d8f 100644 +--- a/drivers/net/arcnet/com20020-pci.c ++++ b/drivers/net/arcnet/com20020-pci.c +@@ -127,6 +127,8 @@ static int com20020pci_probe(struct pci_dev *pdev, + int i, ioaddr, ret; + struct resource *r; + ++ ret = 0; ++ + if (pci_enable_device(pdev)) + return -EIO; + +@@ -142,6 +144,8 @@ static int com20020pci_probe(struct pci_dev *pdev, + priv->ci = ci; + mm = &ci->misc_map; + ++ pci_set_drvdata(pdev, priv); ++ + INIT_LIST_HEAD(&priv->list_dev); + + if (mm->size) { +@@ -164,7 +168,7 @@ static int com20020pci_probe(struct pci_dev *pdev, + dev = alloc_arcdev(device); + if (!dev) { + ret = -ENOMEM; +- goto out_port; ++ break; + } + dev->dev_port = i; + +@@ -181,7 +185,7 @@ static int com20020pci_probe(struct pci_dev *pdev, + pr_err("IO region %xh-%xh already allocated\n", + ioaddr, ioaddr + cm->size - 1); + ret = -EBUSY; +- goto out_port; ++ goto err_free_arcdev; + } + + /* Dummy access after Reset +@@ -219,18 +223,18 @@ static int com20020pci_probe(struct pci_dev *pdev, + if (arcnet_inb(ioaddr, COM20020_REG_R_STATUS) == 0xFF) { + pr_err("IO address %Xh is empty!\n", ioaddr); + ret = -EIO; +- goto out_port; ++ goto err_free_arcdev; + } + if (com20020_check(dev)) { + ret = -EIO; +- goto out_port; ++ goto err_free_arcdev; + } + + card = devm_kzalloc(&pdev->dev, sizeof(struct com20020_dev), + GFP_KERNEL); + if (!card) { + ret = -ENOMEM; +- goto out_port; ++ goto err_free_arcdev; + } + + card->index = i; +@@ -256,29 +260,29 @@ static int com20020pci_probe(struct pci_dev *pdev, + + ret = devm_led_classdev_register(&pdev->dev, &card->tx_led); + if (ret) +- goto out_port; ++ goto err_free_arcdev; + + ret = devm_led_classdev_register(&pdev->dev, &card->recon_led); + if (ret) +- goto out_port; ++ goto err_free_arcdev; + + dev_set_drvdata(&dev->dev, card); + + ret = com20020_found(dev, IRQF_SHARED); + if (ret) +- goto out_port; ++ goto err_free_arcdev; + + devm_arcnet_led_init(dev, dev->dev_id, i); + + list_add(&card->list, &priv->list_dev); +- } ++ continue; + +- pci_set_drvdata(pdev, priv); +- +- return 0; +- +-out_port: +- com20020pci_remove(pdev); ++err_free_arcdev: ++ free_arcdev(dev); ++ break; ++ } ++ if (ret) ++ com20020pci_remove(pdev); + return ret; + } + +-- +2.42.0 + diff --git a/queue-5.10/net-bnxt-fix-a-potential-use-after-free-in-bnxt_init.patch b/queue-5.10/net-bnxt-fix-a-potential-use-after-free-in-bnxt_init.patch new file mode 100644 index 00000000000..b2bc1b3b6a3 --- /dev/null +++ b/queue-5.10/net-bnxt-fix-a-potential-use-after-free-in-bnxt_init.patch @@ -0,0 +1,43 @@ +From 2a2737c9ba0d57c9bdc836e05d593576a45bba16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Dec 2023 10:40:04 +0800 +Subject: net: bnxt: fix a potential use-after-free in bnxt_init_tc + +From: Dinghao Liu + +[ Upstream commit d007caaaf052f82ca2340d4c7b32d04a3f5dbf3f ] + +When flow_indr_dev_register() fails, bnxt_init_tc will free +bp->tc_info through kfree(). However, the caller function +bnxt_init_one() will ignore this failure and call +bnxt_shutdown_tc() on failure of bnxt_dl_register(), where +a use-after-free happens. Fix this issue by setting +bp->tc_info to NULL after kfree(). + +Fixes: 627c89d00fb9 ("bnxt_en: flow_offload: offload tunnel decap rules via indirect callbacks") +Signed-off-by: Dinghao Liu +Reviewed-by: Pavan Chebbi +Reviewed-by: Michael Chan +Reviewed-by: Somnath Kotur +Link: https://lore.kernel.org/r/20231204024004.8245-1-dinghao.liu@zju.edu.cn +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c +index 3e9b1f59e381d..775d0b7521ca0 100644 +--- a/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c ++++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_tc.c +@@ -2061,6 +2061,7 @@ int bnxt_init_tc(struct bnxt *bp) + rhashtable_destroy(&tc_info->flow_table); + free_tc_info: + kfree(tc_info); ++ bp->tc_info = NULL; + return rc; + } + +-- +2.42.0 + diff --git a/queue-5.10/net-hns-fix-fake-link-up-on-xge-port.patch b/queue-5.10/net-hns-fix-fake-link-up-on-xge-port.patch new file mode 100644 index 00000000000..7199b0d1cdb --- /dev/null +++ b/queue-5.10/net-hns-fix-fake-link-up-on-xge-port.patch @@ -0,0 +1,74 @@ +From 0f23f9c8b8faf8fe6371a06658cf7204ba0d197e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 4 Dec 2023 22:32:32 +0800 +Subject: net: hns: fix fake link up on xge port + +From: Yonglong Liu + +[ Upstream commit f708aba40f9c1eeb9c7e93ed4863b5f85b09b288 ] + +If a xge port just connect with an optical module and no fiber, +it may have a fake link up because there may be interference on +the hardware. This patch adds an anti-shake to avoid the problem. +And the time of anti-shake is base on tests. + +Fixes: b917078c1c10 ("net: hns: Add ACPI support to check SFP present") +Signed-off-by: Yonglong Liu +Signed-off-by: Jijie Shao +Reviewed-by: Wojciech Drewek +Signed-off-by: Paolo Abeni +Signed-off-by: Sasha Levin +--- + .../net/ethernet/hisilicon/hns/hns_dsaf_mac.c | 29 +++++++++++++++++++ + 1 file changed, 29 insertions(+) + +diff --git a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +index 4a448138b4ec1..1f44a6463f45b 100644 +--- a/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c ++++ b/drivers/net/ethernet/hisilicon/hns/hns_dsaf_mac.c +@@ -66,6 +66,27 @@ static enum mac_mode hns_get_enet_interface(const struct hns_mac_cb *mac_cb) + } + } + ++static u32 hns_mac_link_anti_shake(struct mac_driver *mac_ctrl_drv) ++{ ++#define HNS_MAC_LINK_WAIT_TIME 5 ++#define HNS_MAC_LINK_WAIT_CNT 40 ++ ++ u32 link_status = 0; ++ int i; ++ ++ if (!mac_ctrl_drv->get_link_status) ++ return link_status; ++ ++ for (i = 0; i < HNS_MAC_LINK_WAIT_CNT; i++) { ++ msleep(HNS_MAC_LINK_WAIT_TIME); ++ mac_ctrl_drv->get_link_status(mac_ctrl_drv, &link_status); ++ if (!link_status) ++ break; ++ } ++ ++ return link_status; ++} ++ + void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status) + { + struct mac_driver *mac_ctrl_drv; +@@ -83,6 +104,14 @@ void hns_mac_get_link_status(struct hns_mac_cb *mac_cb, u32 *link_status) + &sfp_prsnt); + if (!ret) + *link_status = *link_status && sfp_prsnt; ++ ++ /* for FIBER port, it may have a fake link up. ++ * when the link status changes from down to up, we need to do ++ * anti-shake. the anti-shake time is base on tests. ++ * only FIBER port need to do this. ++ */ ++ if (*link_status && !mac_cb->link) ++ *link_status = hns_mac_link_anti_shake(mac_ctrl_drv); + } + + mac_cb->link = *link_status; +-- +2.42.0 + diff --git a/queue-5.10/netfilter-xt_owner-fix-for-unsafe-access-of-sk-sk_so.patch b/queue-5.10/netfilter-xt_owner-fix-for-unsafe-access-of-sk-sk_so.patch new file mode 100644 index 00000000000..c0b2a302aa6 --- /dev/null +++ b/queue-5.10/netfilter-xt_owner-fix-for-unsafe-access-of-sk-sk_so.patch @@ -0,0 +1,71 @@ +From fe7a436f8b59817030b24894b7cbfe306215dbfa Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Dec 2023 21:58:12 +0100 +Subject: netfilter: xt_owner: Fix for unsafe access of sk->sk_socket + +From: Phil Sutter + +[ Upstream commit 7ae836a3d630e146b732fe8ef7d86b243748751f ] + +A concurrently running sock_orphan() may NULL the sk_socket pointer in +between check and deref. Follow other users (like nft_meta.c for +instance) and acquire sk_callback_lock before dereferencing sk_socket. + +Fixes: 0265ab44bacc ("[NETFILTER]: merge ipt_owner/ip6t_owner in xt_owner") +Reported-by: Jann Horn +Signed-off-by: Phil Sutter +Signed-off-by: Pablo Neira Ayuso +Signed-off-by: Sasha Levin +--- + net/netfilter/xt_owner.c | 16 ++++++++++++---- + 1 file changed, 12 insertions(+), 4 deletions(-) + +diff --git a/net/netfilter/xt_owner.c b/net/netfilter/xt_owner.c +index e85ce69924aee..50332888c8d23 100644 +--- a/net/netfilter/xt_owner.c ++++ b/net/netfilter/xt_owner.c +@@ -76,18 +76,23 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par) + */ + return false; + +- filp = sk->sk_socket->file; +- if (filp == NULL) ++ read_lock_bh(&sk->sk_callback_lock); ++ filp = sk->sk_socket ? sk->sk_socket->file : NULL; ++ if (filp == NULL) { ++ read_unlock_bh(&sk->sk_callback_lock); + return ((info->match ^ info->invert) & + (XT_OWNER_UID | XT_OWNER_GID)) == 0; ++ } + + if (info->match & XT_OWNER_UID) { + kuid_t uid_min = make_kuid(net->user_ns, info->uid_min); + kuid_t uid_max = make_kuid(net->user_ns, info->uid_max); + if ((uid_gte(filp->f_cred->fsuid, uid_min) && + uid_lte(filp->f_cred->fsuid, uid_max)) ^ +- !(info->invert & XT_OWNER_UID)) ++ !(info->invert & XT_OWNER_UID)) { ++ read_unlock_bh(&sk->sk_callback_lock); + return false; ++ } + } + + if (info->match & XT_OWNER_GID) { +@@ -112,10 +117,13 @@ owner_mt(const struct sk_buff *skb, struct xt_action_param *par) + } + } + +- if (match ^ !(info->invert & XT_OWNER_GID)) ++ if (match ^ !(info->invert & XT_OWNER_GID)) { ++ read_unlock_bh(&sk->sk_callback_lock); + return false; ++ } + } + ++ read_unlock_bh(&sk->sk_callback_lock); + return true; + } + +-- +2.42.0 + diff --git a/queue-5.10/octeontx2-pf-add-missing-mutex-lock-in-otx2_get_paus.patch b/queue-5.10/octeontx2-pf-add-missing-mutex-lock-in-otx2_get_paus.patch new file mode 100644 index 00000000000..45bb1919ee8 --- /dev/null +++ b/queue-5.10/octeontx2-pf-add-missing-mutex-lock-in-otx2_get_paus.patch @@ -0,0 +1,51 @@ +From 353541f31e263ebd801002267af1f98ec455f3a3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 29 Nov 2023 10:53:42 +0530 +Subject: octeontx2-pf: Add missing mutex lock in otx2_get_pauseparam + +From: Subbaraya Sundeep + +[ Upstream commit 9572c949385aa2ef10368287c439bcb7935137c8 ] + +All the mailbox messages sent to AF needs to be guarded +by mutex lock. Add the missing lock in otx2_get_pauseparam +function. + +Fixes: 75f36270990c ("octeontx2-pf: Support to enable/disable pause frames via ethtool") +Signed-off-by: Subbaraya Sundeep +Reviewed-by: Simon Horman +Signed-off-by: David S. Miller +Signed-off-by: Sasha Levin +--- + drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c +index c6d408de06050..fc4ca8246df24 100644 +--- a/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c ++++ b/drivers/net/ethernet/marvell/octeontx2/nic/otx2_ethtool.c +@@ -254,9 +254,12 @@ static void otx2_get_pauseparam(struct net_device *netdev, + if (is_otx2_lbkvf(pfvf->pdev)) + return; + ++ mutex_lock(&pfvf->mbox.lock); + req = otx2_mbox_alloc_msg_cgx_cfg_pause_frm(&pfvf->mbox); +- if (!req) ++ if (!req) { ++ mutex_unlock(&pfvf->mbox.lock); + return; ++ } + + if (!otx2_sync_mbox_msg(&pfvf->mbox)) { + rsp = (struct cgx_pause_frm_cfg *) +@@ -264,6 +267,7 @@ static void otx2_get_pauseparam(struct net_device *netdev, + pause->rx_pause = rsp->rx_pause; + pause->tx_pause = rsp->tx_pause; + } ++ mutex_unlock(&pfvf->mbox.lock); + } + + static int otx2_set_pauseparam(struct net_device *netdev, +-- +2.42.0 + diff --git a/queue-5.10/of-add-missing-return-section-in-kerneldoc-comments.patch b/queue-5.10/of-add-missing-return-section-in-kerneldoc-comments.patch new file mode 100644 index 00000000000..128750fc66c --- /dev/null +++ b/queue-5.10/of-add-missing-return-section-in-kerneldoc-comments.patch @@ -0,0 +1,812 @@ +From 782a5cefddcf6cc56620d49cc1d8fb7f0f95786f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 25 Mar 2021 10:47:12 -0600 +Subject: of: Add missing 'Return' section in kerneldoc comments + +From: Rob Herring + +[ Upstream commit 8c8239c2c1fb82f171cb22a707f3bb88a2f22109 ] + +Many of the DT kerneldoc comments are lacking a 'Return' section. Let's +add the section in cases we have a description of return values. There's +still some cases where the return values are not documented. + +Cc: Frank Rowand +Cc: Mauro Carvalho Chehab +Signed-off-by: Rob Herring +Reviewed-by: Mauro Carvalho Chehab +Link: https://lore.kernel.org/r/20210325164713.1296407-8-robh@kernel.org +Stable-dep-of: d79972789d17 ("of: dynamic: Fix of_reconfig_get_state_change() return value documentation") +Signed-off-by: Sasha Levin +--- + drivers/of/base.c | 39 +++++++++++++------------ + drivers/of/dynamic.c | 19 ++++++++----- + drivers/of/fdt.c | 8 +++--- + drivers/of/irq.c | 14 ++++----- + drivers/of/overlay.c | 16 +++++------ + drivers/of/platform.c | 10 +++---- + drivers/of/property.c | 66 +++++++++++++++++++++++++++---------------- + include/linux/of.h | 63 ++++++++++++++++++++++++++--------------- + 8 files changed, 140 insertions(+), 95 deletions(-) + +diff --git a/drivers/of/base.c b/drivers/of/base.c +index 85a55cfd00f11..eb02974f36bdb 100644 +--- a/drivers/of/base.c ++++ b/drivers/of/base.c +@@ -244,7 +244,7 @@ struct device_node *__of_find_all_nodes(struct device_node *prev) + * @prev: Previous node or NULL to start iteration + * of_node_put() will be called on it + * +- * Returns a node pointer with refcount incremented, use ++ * Return: A node pointer with refcount incremented, use + * of_node_put() on it when done. + */ + struct device_node *of_find_all_nodes(struct device_node *prev) +@@ -374,7 +374,7 @@ bool __weak arch_find_n_match_cpu_physical_id(struct device_node *cpun, + * before booting secondary cores. This function uses arch_match_cpu_phys_id + * which can be overridden by architecture specific implementation. + * +- * Returns a node pointer for the logical cpu with refcount incremented, use ++ * Return: A node pointer for the logical cpu with refcount incremented, use + * of_node_put() on it when done. Returns NULL if not found. + */ + struct device_node *of_get_cpu_node(int cpu, unsigned int *thread) +@@ -394,8 +394,8 @@ EXPORT_SYMBOL(of_get_cpu_node); + * + * @cpu_node: Pointer to the device_node for CPU. + * +- * Returns the logical CPU number of the given CPU device_node. +- * Returns -ENODEV if the CPU is not found. ++ * Return: The logical CPU number of the given CPU device_node or -ENODEV if the ++ * CPU is not found. + */ + int of_cpu_node_to_id(struct device_node *cpu_node) + { +@@ -427,7 +427,7 @@ EXPORT_SYMBOL(of_cpu_node_to_id); + * bindings. This function check for both and returns the idle state node for + * the requested index. + * +- * In case an idle state node is found at @index, the refcount is incremented ++ * Return: An idle state node if found at @index. The refcount is incremented + * for it, so call of_node_put() on it when done. Returns NULL if not found. + */ + struct device_node *of_get_cpu_state_node(struct device_node *cpu_node, +@@ -561,7 +561,7 @@ int of_device_compatible_match(struct device_node *device, + * of_machine_is_compatible - Test root of device tree for a given compatible value + * @compat: compatible string to look for in root node's compatible property. + * +- * Returns a positive integer if the root node has the given value in its ++ * Return: A positive integer if the root node has the given value in its + * compatible property. + */ + int of_machine_is_compatible(const char *compat) +@@ -583,7 +583,7 @@ EXPORT_SYMBOL(of_machine_is_compatible); + * + * @device: Node to check for availability, with locks already held + * +- * Returns true if the status property is absent or set to "okay" or "ok", ++ * Return: True if the status property is absent or set to "okay" or "ok", + * false otherwise + */ + static bool __of_device_is_available(const struct device_node *device) +@@ -611,7 +611,7 @@ static bool __of_device_is_available(const struct device_node *device) + * + * @device: Node to check for availability + * +- * Returns true if the status property is absent or set to "okay" or "ok", ++ * Return: True if the status property is absent or set to "okay" or "ok", + * false otherwise + */ + bool of_device_is_available(const struct device_node *device) +@@ -632,7 +632,7 @@ EXPORT_SYMBOL(of_device_is_available); + * + * @device: Node to check for endianness + * +- * Returns true if the device has a "big-endian" property, or if the kernel ++ * Return: True if the device has a "big-endian" property, or if the kernel + * was compiled for BE *and* the device has a "native-endian" property. + * Returns false otherwise. + * +@@ -816,7 +816,7 @@ EXPORT_SYMBOL(of_get_next_cpu_node); + * Lookup child node whose compatible property contains the given compatible + * string. + * +- * Returns a node pointer with refcount incremented, use of_node_put() on it ++ * Return: a node pointer with refcount incremented, use of_node_put() on it + * when done; or NULL if not found. + */ + struct device_node *of_get_compatible_child(const struct device_node *parent, +@@ -1170,7 +1170,7 @@ EXPORT_SYMBOL(of_find_matching_node_and_match); + * It does this by stripping the manufacturer prefix (as delimited by a ',') + * from the first entry in the compatible list property. + * +- * This routine returns 0 on success, <0 on failure. ++ * Return: This routine returns 0 on success, <0 on failure. + */ + int of_modalias_node(struct device_node *node, char *modalias, int len) + { +@@ -1190,7 +1190,7 @@ EXPORT_SYMBOL_GPL(of_modalias_node); + * of_find_node_by_phandle - Find a node given a phandle + * @handle: phandle of the node to find + * +- * Returns a node pointer with refcount incremented, use ++ * Return: A node pointer with refcount incremented, use + * of_node_put() on it when done. + */ + struct device_node *of_find_node_by_phandle(phandle handle) +@@ -1431,7 +1431,7 @@ static int __of_parse_phandle_with_args(const struct device_node *np, + * @index: For properties holding a table of phandles, this is the index into + * the table + * +- * Returns the device_node pointer with refcount incremented. Use ++ * Return: The device_node pointer with refcount incremented. Use + * of_node_put() on it when done. + */ + struct device_node *of_parse_phandle(const struct device_node *np, +@@ -1731,7 +1731,7 @@ EXPORT_SYMBOL(of_parse_phandle_with_fixed_args); + * @list_name: property name that contains a list + * @cells_name: property name that specifies phandles' arguments count + * +- * Returns the number of phandle + argument tuples within a property. It ++ * Return: The number of phandle + argument tuples within a property. It + * is a typical pattern to encode a list of phandle and variable + * arguments into a single property. The number of arguments is encoded + * by a property in the phandle-target node. For example, a gpios +@@ -2031,7 +2031,9 @@ void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) + * @stem: Alias stem of the given device_node + * + * The function travels the lookup table to get the alias id for the given +- * device_node and alias stem. It returns the alias id if found. ++ * device_node and alias stem. ++ * ++ * Return: The alias id if found. + */ + int of_alias_get_id(struct device_node *np, const char *stem) + { +@@ -2140,8 +2142,9 @@ EXPORT_SYMBOL_GPL(of_alias_get_highest_id); + * @index: Index to use for preferred console. + * + * Check if the given device node matches the stdout-path property in the +- * /chosen node. If it does then register it as the preferred console and return +- * TRUE. Otherwise return FALSE. ++ * /chosen node. If it does then register it as the preferred console. ++ * ++ * Return: TRUE if console successfully setup. Otherwise return FALSE. + */ + bool of_console_check(struct device_node *dn, char *name, int index) + { +@@ -2192,7 +2195,7 @@ struct device_node *of_find_next_cache_node(const struct device_node *np) + * + * @cpu: cpu number(logical index) for which the last cache level is needed + * +- * Returns the the level at which the last cache is present. It is exactly ++ * Return: The the level at which the last cache is present. It is exactly + * same as the total number of cache levels for the given logical cpu. + */ + int of_find_last_cache_level(unsigned int cpu) +diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c +index 7d0232af9c23d..1f55e46919004 100644 +--- a/drivers/of/dynamic.c ++++ b/drivers/of/dynamic.c +@@ -27,7 +27,7 @@ static struct device_node *kobj_to_device_node(struct kobject *kobj) + * @node: Node to inc refcount, NULL is supported to simplify writing of + * callers + * +- * Returns node. ++ * Return: The node with refcount incremented. + */ + struct device_node *of_node_get(struct device_node *node) + { +@@ -103,7 +103,8 @@ int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p) + * @arg - argument of the of notifier + * + * Returns the new state of a device based on the notifier used. +- * Returns 0 on device going from enabled to disabled, 1 on device ++ * ++ * Return: 0 on device going from enabled to disabled, 1 on device + * going from disabled to enabled and -1 on no change. + */ + int of_reconfig_get_state_change(unsigned long action, struct of_reconfig_data *pr) +@@ -370,7 +371,8 @@ void of_node_release(struct kobject *kobj) + * property structure and the property name & contents. The property's + * flags have the OF_DYNAMIC bit set so that we can differentiate between + * dynamically allocated properties and not. +- * Returns the newly allocated property or NULL on out of memory error. ++ * ++ * Return: The newly allocated property or NULL on out of memory error. + */ + struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags) + { +@@ -413,7 +415,7 @@ struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags) + * another node. The node data are dynamically allocated and all the node + * flags have the OF_DYNAMIC & OF_DETACHED bits set. + * +- * Returns the newly allocated node or NULL on out of memory error. ++ * Return: The newly allocated node or NULL on out of memory error. + */ + struct device_node *__of_node_dup(const struct device_node *np, + const char *full_name) +@@ -764,7 +766,8 @@ static int __of_changeset_apply(struct of_changeset *ocs) + * Any side-effects of live tree state changes are applied here on + * success, like creation/destruction of devices and side-effects + * like creation of sysfs properties and directories. +- * Returns 0 on success, a negative error value in case of an error. ++ * ++ * Return: 0 on success, a negative error value in case of an error. + * On error the partially applied effects are reverted. + */ + int of_changeset_apply(struct of_changeset *ocs) +@@ -858,7 +861,8 @@ static int __of_changeset_revert(struct of_changeset *ocs) + * was before the application. + * Any side-effects like creation/destruction of devices and + * removal of sysfs properties and directories are applied. +- * Returns 0 on success, a negative error value in case of an error. ++ * ++ * Return: 0 on success, a negative error value in case of an error. + */ + int of_changeset_revert(struct of_changeset *ocs) + { +@@ -886,7 +890,8 @@ EXPORT_SYMBOL_GPL(of_changeset_revert); + * + OF_RECONFIG_ADD_PROPERTY + * + OF_RECONFIG_REMOVE_PROPERTY, + * + OF_RECONFIG_UPDATE_PROPERTY +- * Returns 0 on success, a negative error value in case of an error. ++ * ++ * Return: 0 on success, a negative error value in case of an error. + */ + int of_changeset_action(struct of_changeset *ocs, unsigned long action, + struct device_node *np, struct property *prop) +diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c +index 81e03bd896751..384510d0200cd 100644 +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -282,7 +282,7 @@ static void reverse_nodes(struct device_node *parent) + * @dad: Parent struct device_node + * @nodepp: The device_node tree created by the call + * +- * It returns the size of unflattened device tree or error code ++ * Return: The size of unflattened device tree or error code + */ + static int unflatten_dt_nodes(const void *blob, + void *mem, +@@ -360,7 +360,7 @@ static int unflatten_dt_nodes(const void *blob, + * fills the "name" and "type" pointers of the nodes so the normal device-tree + * walking functions can be used. + * +- * Returns NULL on failure or the memory chunk containing the unflattened ++ * Return: NULL on failure or the memory chunk containing the unflattened + * device tree on success. + */ + void *__unflatten_device_tree(const void *blob, +@@ -441,7 +441,7 @@ static DEFINE_MUTEX(of_fdt_unflatten_mutex); + * pointers of the nodes so the normal device-tree walking functions + * can be used. + * +- * Returns NULL on failure or the memory chunk containing the unflattened ++ * Return: NULL on failure or the memory chunk containing the unflattened + * device tree on success. + */ + void *of_fdt_unflatten_tree(const unsigned long *blob, +@@ -715,7 +715,7 @@ const void *__init of_get_flat_dt_prop(unsigned long node, const char *name, + * @node: node to test + * @compat: compatible string to compare with compatible list. + * +- * On match, returns a non-zero value with smaller values returned for more ++ * Return: a non-zero value on match with smaller values returned for more + * specific compatible values. + */ + static int of_fdt_is_compatible(const void *blob, +diff --git a/drivers/of/irq.c b/drivers/of/irq.c +index 25d17b8a1a1aa..352e14b007e78 100644 +--- a/drivers/of/irq.c ++++ b/drivers/of/irq.c +@@ -48,7 +48,7 @@ EXPORT_SYMBOL_GPL(irq_of_parse_and_map); + * of_irq_find_parent - Given a device node, find its interrupt parent node + * @child: pointer to device node + * +- * Returns a pointer to the interrupt parent node, or NULL if the interrupt ++ * Return: A pointer to the interrupt parent node, or NULL if the interrupt + * parent could not be determined. + */ + struct device_node *of_irq_find_parent(struct device_node *child) +@@ -81,14 +81,14 @@ EXPORT_SYMBOL_GPL(of_irq_find_parent); + * @addr: address specifier (start of "reg" property of the device) in be32 format + * @out_irq: structure of_phandle_args updated by this function + * +- * Returns 0 on success and a negative number on error +- * + * This function is a low-level interrupt tree walking function. It + * can be used to do a partial walk with synthetized reg and interrupts + * properties, for example when resolving PCI interrupts when no device + * node exist for the parent. It takes an interrupt specifier structure as + * input, walks the tree looking for any interrupt-map properties, translates + * the specifier for each map, and then returns the translated map. ++ * ++ * Return: 0 on success and a negative number on error + */ + int of_irq_parse_raw(const __be32 *addr, struct of_phandle_args *out_irq) + { +@@ -380,7 +380,7 @@ EXPORT_SYMBOL_GPL(of_irq_to_resource); + * @dev: pointer to device tree node + * @index: zero-based index of the IRQ + * +- * Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or ++ * Return: Linux IRQ number on success, or 0 on the IRQ mapping failure, or + * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case + * of any other failure. + */ +@@ -407,7 +407,7 @@ EXPORT_SYMBOL_GPL(of_irq_get); + * @dev: pointer to device tree node + * @name: IRQ name + * +- * Returns Linux IRQ number on success, or 0 on the IRQ mapping failure, or ++ * Return: Linux IRQ number on success, or 0 on the IRQ mapping failure, or + * -EPROBE_DEFER if the IRQ domain is not yet created, or error code in case + * of any other failure. + */ +@@ -447,7 +447,7 @@ int of_irq_count(struct device_node *dev) + * @res: array of resources to fill in + * @nr_irqs: the number of IRQs (and upper bound for num of @res elements) + * +- * Returns the size of the filled in table (up to @nr_irqs). ++ * Return: The size of the filled in table (up to @nr_irqs). + */ + int of_irq_to_resource_table(struct device_node *dev, struct resource *res, + int nr_irqs) +@@ -602,7 +602,7 @@ static u32 __of_msi_map_id(struct device *dev, struct device_node **np, + * Walk up the device hierarchy looking for devices with a "msi-map" + * property. If found, apply the mapping to @id_in. + * +- * Returns the mapped MSI ID. ++ * Return: The mapped MSI ID. + */ + u32 of_msi_map_id(struct device *dev, struct device_node *msi_np, u32 id_in) + { +diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c +index 67b404f36e79c..3ac874e2be080 100644 +--- a/drivers/of/overlay.c ++++ b/drivers/of/overlay.c +@@ -296,7 +296,7 @@ static struct property *dup_and_fixup_symbol_prop( + * + * Update of property in symbols node is not allowed. + * +- * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if ++ * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid @overlay. + */ + static int add_changeset_property(struct overlay_changeset *ovcs, +@@ -401,7 +401,7 @@ static int add_changeset_property(struct overlay_changeset *ovcs, + * + * NOTE_2: Multiple mods of created nodes not supported. + * +- * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if ++ * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid @overlay. + */ + static int add_changeset_node(struct overlay_changeset *ovcs, +@@ -473,7 +473,7 @@ static int add_changeset_node(struct overlay_changeset *ovcs, + * + * Do not allow symbols node to have any children. + * +- * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if ++ * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid @overlay_node. + */ + static int build_changeset_next_level(struct overlay_changeset *ovcs, +@@ -604,7 +604,7 @@ static int find_dup_cset_prop(struct overlay_changeset *ovcs, + * the same node or duplicate {add, delete, or update} properties entries + * for the same property. + * +- * Returns 0 on success, or -EINVAL if duplicate changeset entry found. ++ * Return: 0 on success, or -EINVAL if duplicate changeset entry found. + */ + static int changeset_dup_entry_check(struct overlay_changeset *ovcs) + { +@@ -628,7 +628,7 @@ static int changeset_dup_entry_check(struct overlay_changeset *ovcs) + * any portions of the changeset that were successfully created will remain + * in @ovcs->cset. + * +- * Returns 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if ++ * Return: 0 on success, -ENOMEM if memory allocation failure, or -EINVAL if + * invalid overlay in @ovcs->fragments[]. + */ + static int build_changeset(struct overlay_changeset *ovcs) +@@ -724,7 +724,7 @@ static struct device_node *find_target(struct device_node *info_node) + * the top level of @tree. The relevant top level nodes are the fragment + * nodes and the __symbols__ node. Any other top level node will be ignored. + * +- * Returns 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error ++ * Return: 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error + * detected in @tree, or -ENOSPC if idr_alloc() error. + */ + static int init_overlay_changeset(struct overlay_changeset *ovcs, +@@ -1179,7 +1179,7 @@ static int overlay_removal_is_ok(struct overlay_changeset *remove_ovcs) + * If an error is returned by an overlay changeset post-remove notifier + * then no further overlay changeset post-remove notifier will be called. + * +- * Returns 0 on success, or a negative error number. *ovcs_id is set to ++ * Return: 0 on success, or a negative error number. *ovcs_id is set to + * zero after reverting the changeset, even if a subsequent error occurs. + */ + int of_overlay_remove(int *ovcs_id) +@@ -1257,7 +1257,7 @@ EXPORT_SYMBOL_GPL(of_overlay_remove); + * + * Removes all overlays from the system in the correct order. + * +- * Returns 0 on success, or a negative error number ++ * Return: 0 on success, or a negative error number + */ + int of_overlay_remove_all(void) + { +diff --git a/drivers/of/platform.c b/drivers/of/platform.c +index b557a0fcd4ba0..43748c6480c80 100644 +--- a/drivers/of/platform.c ++++ b/drivers/of/platform.c +@@ -44,7 +44,7 @@ static const struct of_device_id of_skipped_node_table[] = { + * Takes a reference to the embedded struct device which needs to be dropped + * after use. + * +- * Returns platform_device pointer, or NULL if not found ++ * Return: platform_device pointer, or NULL if not found + */ + struct platform_device *of_find_device_by_node(struct device_node *np) + { +@@ -160,7 +160,7 @@ EXPORT_SYMBOL(of_device_alloc); + * @platform_data: pointer to populate platform_data pointer with + * @parent: Linux device model parent device. + * +- * Returns pointer to created platform device, or NULL if a device was not ++ * Return: Pointer to created platform device, or NULL if a device was not + * registered. Unavailable devices will not get registered. + */ + static struct platform_device *of_platform_device_create_pdata( +@@ -204,7 +204,7 @@ static struct platform_device *of_platform_device_create_pdata( + * @bus_id: name to assign device + * @parent: Linux device model parent device. + * +- * Returns pointer to created platform device, or NULL if a device was not ++ * Return: Pointer to created platform device, or NULL if a device was not + * registered. Unavailable devices will not get registered. + */ + struct platform_device *of_platform_device_create(struct device_node *np, +@@ -463,7 +463,7 @@ EXPORT_SYMBOL(of_platform_bus_probe); + * New board support should be using this function instead of + * of_platform_bus_probe(). + * +- * Returns 0 on success, < 0 on failure. ++ * Return: 0 on success, < 0 on failure. + */ + int of_platform_populate(struct device_node *root, + const struct of_device_id *matches, +@@ -608,7 +608,7 @@ static void devm_of_platform_populate_release(struct device *dev, void *res) + * Similar to of_platform_populate(), but will automatically call + * of_platform_depopulate() when the device is unbound from the bus. + * +- * Returns 0 on success, < 0 on failure. ++ * Return: 0 on success, < 0 on failure. + */ + int devm_of_platform_populate(struct device *dev) + { +diff --git a/drivers/of/property.c b/drivers/of/property.c +index 8f998351bf4fb..a411460d2b211 100644 +--- a/drivers/of/property.c ++++ b/drivers/of/property.c +@@ -60,9 +60,11 @@ EXPORT_SYMBOL(of_graph_is_present); + * @elem_size: size of the individual element + * + * Search for a property in a device node and count the number of elements of +- * size elem_size in it. Returns number of elements on sucess, -EINVAL if the +- * property does not exist or its length does not match a multiple of elem_size +- * and -ENODATA if the property does not have a value. ++ * size elem_size in it. ++ * ++ * Return: The number of elements on sucess, -EINVAL if the property does not ++ * exist or its length does not match a multiple of elem_size and -ENODATA if ++ * the property does not have a value. + */ + int of_property_count_elems_of_size(const struct device_node *np, + const char *propname, int elem_size) +@@ -94,8 +96,9 @@ EXPORT_SYMBOL_GPL(of_property_count_elems_of_size); + * @len: if !=NULL, actual length is written to here + * + * Search for a property in a device node and valid the requested size. +- * Returns the property value on success, -EINVAL if the property does not +- * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the ++ * ++ * Return: The property value on success, -EINVAL if the property does not ++ * exist, -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data is too small or too large. + * + */ +@@ -128,7 +131,9 @@ static void *of_find_property_value_of_size(const struct device_node *np, + * @out_value: pointer to return value, modified only if no error. + * + * Search for a property in a device node and read nth 32-bit value from +- * it. Returns 0 on success, -EINVAL if the property does not exist, ++ * it. ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * +@@ -160,7 +165,9 @@ EXPORT_SYMBOL_GPL(of_property_read_u32_index); + * @out_value: pointer to return value, modified only if no error. + * + * Search for a property in a device node and read nth 64-bit value from +- * it. Returns 0 on success, -EINVAL if the property does not exist, ++ * it. ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * +@@ -195,12 +202,14 @@ EXPORT_SYMBOL_GPL(of_property_read_u64_index); + * sz_min will be read. + * + * Search for a property in a device node and read 8-bit value(s) from +- * it. Returns number of elements read on success, -EINVAL if the property +- * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW +- * if the property data is smaller than sz_min or longer than sz_max. ++ * it. + * + * dts entry of array should be like: +- * property = /bits/ 8 <0x50 0x60 0x70>; ++ * ``property = /bits/ 8 <0x50 0x60 0x70>;`` ++ * ++ * Return: The number of elements read on success, -EINVAL if the property ++ * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW ++ * if the property data is smaller than sz_min or longer than sz_max. + * + * The out_values is modified only if a valid u8 value can be decoded. + */ +@@ -243,12 +252,14 @@ EXPORT_SYMBOL_GPL(of_property_read_variable_u8_array); + * sz_min will be read. + * + * Search for a property in a device node and read 16-bit value(s) from +- * it. Returns number of elements read on success, -EINVAL if the property +- * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW +- * if the property data is smaller than sz_min or longer than sz_max. ++ * it. + * + * dts entry of array should be like: +- * property = /bits/ 16 <0x5000 0x6000 0x7000>; ++ * ``property = /bits/ 16 <0x5000 0x6000 0x7000>;`` ++ * ++ * Return: The number of elements read on success, -EINVAL if the property ++ * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW ++ * if the property data is smaller than sz_min or longer than sz_max. + * + * The out_values is modified only if a valid u16 value can be decoded. + */ +@@ -291,7 +302,9 @@ EXPORT_SYMBOL_GPL(of_property_read_variable_u16_array); + * sz_min will be read. + * + * Search for a property in a device node and read 32-bit value(s) from +- * it. Returns number of elements read on success, -EINVAL if the property ++ * it. ++ * ++ * Return: The number of elements read on success, -EINVAL if the property + * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW + * if the property data is smaller than sz_min or longer than sz_max. + * +@@ -330,7 +343,9 @@ EXPORT_SYMBOL_GPL(of_property_read_variable_u32_array); + * @out_value: pointer to return value, modified only if return value is 0. + * + * Search for a property in a device node and read a 64-bit value from +- * it. Returns 0 on success, -EINVAL if the property does not exist, ++ * it. ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * +@@ -365,7 +380,9 @@ EXPORT_SYMBOL_GPL(of_property_read_u64); + * sz_min will be read. + * + * Search for a property in a device node and read 64-bit value(s) from +- * it. Returns number of elements read on success, -EINVAL if the property ++ * it. ++ * ++ * Return: The number of elements read on success, -EINVAL if the property + * does not exist, -ENODATA if property does not have a value, and -EOVERFLOW + * if the property data is smaller than sz_min or longer than sz_max. + * +@@ -407,10 +424,11 @@ EXPORT_SYMBOL_GPL(of_property_read_variable_u64_array); + * return value is 0. + * + * Search for a property in a device tree node and retrieve a null +- * terminated string value (pointer to data, not a copy). Returns 0 on +- * success, -EINVAL if the property does not exist, -ENODATA if property +- * does not have a value, and -EILSEQ if the string is not null-terminated +- * within the length of the property data. ++ * terminated string value (pointer to data, not a copy). ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, -ENODATA if ++ * property does not have a value, and -EILSEQ if the string is not ++ * null-terminated within the length of the property data. + * + * The out_string pointer is modified only if a valid string can be decoded. + */ +@@ -774,7 +792,7 @@ EXPORT_SYMBOL(of_graph_get_remote_port_parent); + * @node: pointer to a local endpoint device_node + * + * Return: Remote port node associated with remote endpoint node linked +- * to @node. Use of_node_put() on it when done. ++ * to @node. Use of_node_put() on it when done. + */ + struct device_node *of_graph_get_remote_port(const struct device_node *node) + { +@@ -807,7 +825,7 @@ EXPORT_SYMBOL(of_graph_get_endpoint_count); + * @endpoint: identifier (value of reg property) of the endpoint node + * + * Return: Remote device node associated with remote endpoint node linked +- * to @node. Use of_node_put() on it when done. ++ * to @node. Use of_node_put() on it when done. + */ + struct device_node *of_graph_get_remote_node(const struct device_node *node, + u32 port, u32 endpoint) +diff --git a/include/linux/of.h b/include/linux/of.h +index 0f4e81e6fb232..57f2d3dddc0ce 100644 +--- a/include/linux/of.h ++++ b/include/linux/of.h +@@ -424,12 +424,14 @@ extern int of_detach_node(struct device_node *); + * @sz: number of array elements to read + * + * Search for a property in a device node and read 8-bit value(s) from +- * it. Returns 0 on success, -EINVAL if the property does not exist, +- * -ENODATA if property does not have a value, and -EOVERFLOW if the +- * property data isn't large enough. ++ * it. + * + * dts entry of array should be like: +- * property = /bits/ 8 <0x50 0x60 0x70>; ++ * ``property = /bits/ 8 <0x50 0x60 0x70>;`` ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, ++ * -ENODATA if property does not have a value, and -EOVERFLOW if the ++ * property data isn't large enough. + * + * The out_values is modified only if a valid u8 value can be decoded. + */ +@@ -454,12 +456,14 @@ static inline int of_property_read_u8_array(const struct device_node *np, + * @sz: number of array elements to read + * + * Search for a property in a device node and read 16-bit value(s) from +- * it. Returns 0 on success, -EINVAL if the property does not exist, +- * -ENODATA if property does not have a value, and -EOVERFLOW if the +- * property data isn't large enough. ++ * it. + * + * dts entry of array should be like: +- * property = /bits/ 16 <0x5000 0x6000 0x7000>; ++ * ``property = /bits/ 16 <0x5000 0x6000 0x7000>;`` ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, ++ * -ENODATA if property does not have a value, and -EOVERFLOW if the ++ * property data isn't large enough. + * + * The out_values is modified only if a valid u16 value can be decoded. + */ +@@ -485,7 +489,9 @@ static inline int of_property_read_u16_array(const struct device_node *np, + * @sz: number of array elements to read + * + * Search for a property in a device node and read 32-bit value(s) from +- * it. Returns 0 on success, -EINVAL if the property does not exist, ++ * it. ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * +@@ -513,7 +519,9 @@ static inline int of_property_read_u32_array(const struct device_node *np, + * @sz: number of array elements to read + * + * Search for a property in a device node and read 64-bit value(s) from +- * it. Returns 0 on success, -EINVAL if the property does not exist, ++ * it. ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, + * -ENODATA if property does not have a value, and -EOVERFLOW if the + * property data isn't large enough. + * +@@ -1063,7 +1071,9 @@ static inline bool of_node_is_type(const struct device_node *np, const char *typ + * @propname: name of the property to be searched. + * + * Search for a property in a device node and count the number of u8 elements +- * in it. Returns number of elements on sucess, -EINVAL if the property does ++ * in it. ++ * ++ * Return: The number of elements on sucess, -EINVAL if the property does + * not exist or its length does not match a multiple of u8 and -ENODATA if the + * property does not have a value. + */ +@@ -1080,7 +1090,9 @@ static inline int of_property_count_u8_elems(const struct device_node *np, + * @propname: name of the property to be searched. + * + * Search for a property in a device node and count the number of u16 elements +- * in it. Returns number of elements on sucess, -EINVAL if the property does ++ * in it. ++ * ++ * Return: The number of elements on sucess, -EINVAL if the property does + * not exist or its length does not match a multiple of u16 and -ENODATA if the + * property does not have a value. + */ +@@ -1097,7 +1109,9 @@ static inline int of_property_count_u16_elems(const struct device_node *np, + * @propname: name of the property to be searched. + * + * Search for a property in a device node and count the number of u32 elements +- * in it. Returns number of elements on sucess, -EINVAL if the property does ++ * in it. ++ * ++ * Return: The number of elements on sucess, -EINVAL if the property does + * not exist or its length does not match a multiple of u32 and -ENODATA if the + * property does not have a value. + */ +@@ -1114,7 +1128,9 @@ static inline int of_property_count_u32_elems(const struct device_node *np, + * @propname: name of the property to be searched. + * + * Search for a property in a device node and count the number of u64 elements +- * in it. Returns number of elements on sucess, -EINVAL if the property does ++ * in it. ++ * ++ * Return: The number of elements on sucess, -EINVAL if the property does + * not exist or its length does not match a multiple of u64 and -ENODATA if the + * property does not have a value. + */ +@@ -1135,7 +1151,7 @@ static inline int of_property_count_u64_elems(const struct device_node *np, + * Search for a property in a device tree node and retrieve a list of + * terminated string values (pointer to data, not a copy) in that property. + * +- * If @out_strs is NULL, the number of strings in the property is returned. ++ * Return: If @out_strs is NULL, the number of strings in the property is returned. + */ + static inline int of_property_read_string_array(const struct device_node *np, + const char *propname, const char **out_strs, +@@ -1151,10 +1167,11 @@ static inline int of_property_read_string_array(const struct device_node *np, + * @propname: name of the property to be searched. + * + * Search for a property in a device tree node and retrieve the number of null +- * terminated string contain in it. Returns the number of strings on +- * success, -EINVAL if the property does not exist, -ENODATA if property +- * does not have a value, and -EILSEQ if the string is not null-terminated +- * within the length of the property data. ++ * terminated string contain in it. ++ * ++ * Return: The number of strings on success, -EINVAL if the property does not ++ * exist, -ENODATA if property does not have a value, and -EILSEQ if the string ++ * is not null-terminated within the length of the property data. + */ + static inline int of_property_count_strings(const struct device_node *np, + const char *propname) +@@ -1174,7 +1191,8 @@ static inline int of_property_count_strings(const struct device_node *np, + * Search for a property in a device tree node and retrieve a null + * terminated string value (pointer to data, not a copy) in the list of strings + * contained in that property. +- * Returns 0 on success, -EINVAL if the property does not exist, -ENODATA if ++ * ++ * Return: 0 on success, -EINVAL if the property does not exist, -ENODATA if + * property does not have a value, and -EILSEQ if the string is not + * null-terminated within the length of the property data. + * +@@ -1194,7 +1212,8 @@ static inline int of_property_read_string_index(const struct device_node *np, + * @propname: name of the property to be searched. + * + * Search for a property in a device node. +- * Returns true if the property exists false otherwise. ++ * ++ * Return: true if the property exists false otherwise. + */ + static inline bool of_property_read_bool(const struct device_node *np, + const char *propname) +@@ -1440,7 +1459,7 @@ static inline int of_reconfig_get_state_change(unsigned long action, + * of_device_is_system_power_controller - Tells if system-power-controller is found for device_node + * @np: Pointer to the given device_node + * +- * return true if present false otherwise ++ * Return: true if present false otherwise + */ + static inline bool of_device_is_system_power_controller(const struct device_node *np) + { +-- +2.42.0 + diff --git a/queue-5.10/of-base-fix-some-formatting-issues-and-provide-missi.patch b/queue-5.10/of-base-fix-some-formatting-issues-and-provide-missi.patch new file mode 100644 index 00000000000..c7a58040e7e --- /dev/null +++ b/queue-5.10/of-base-fix-some-formatting-issues-and-provide-missi.patch @@ -0,0 +1,105 @@ +From 9db6e8c448984560af2124ce19a3d8cc9c542779 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 18 Mar 2021 10:40:30 +0000 +Subject: of: base: Fix some formatting issues and provide missing descriptions + +From: Lee Jones + +[ Upstream commit 3637d49e11219512920aca8b8ccd0994be33fa8b ] + +Fixes the following W=1 kernel build warning(s): + + drivers/of/base.c:315: warning: Function parameter or member 'cpun' not described in '__of_find_n_match_cpu_property' + drivers/of/base.c:315: warning: Function parameter or member 'prop_name' not described in '__of_find_n_match_cpu_property' + drivers/of/base.c:315: warning: Function parameter or member 'cpu' not described in '__of_find_n_match_cpu_property' + drivers/of/base.c:315: warning: Function parameter or member 'thread' not described in '__of_find_n_match_cpu_property' + drivers/of/base.c:315: warning: expecting prototype for property holds the physical id of the(). Prototype was for __of_find_n_match_cpu_property() instead + drivers/of/base.c:1139: warning: Function parameter or member 'match' not described in 'of_find_matching_node_and_match' + drivers/of/base.c:1779: warning: Function parameter or member 'np' not described in '__of_add_property' + drivers/of/base.c:1779: warning: Function parameter or member 'prop' not described in '__of_add_property' + drivers/of/base.c:1800: warning: Function parameter or member 'np' not described in 'of_add_property' + drivers/of/base.c:1800: warning: Function parameter or member 'prop' not described in 'of_add_property' + drivers/of/base.c:1849: warning: Function parameter or member 'np' not described in 'of_remove_property' + drivers/of/base.c:1849: warning: Function parameter or member 'prop' not described in 'of_remove_property' + drivers/of/base.c:2137: warning: Function parameter or member 'dn' not described in 'of_console_check' + drivers/of/base.c:2137: warning: Function parameter or member 'name' not described in 'of_console_check' + drivers/of/base.c:2137: warning: Function parameter or member 'index' not described in 'of_console_check' + +Cc: Rob Herring +Cc: Frank Rowand +Cc: "David S. Miller" +Cc: devicetree@vger.kernel.org +Signed-off-by: Lee Jones +Signed-off-by: Rob Herring +Link: https://lore.kernel.org/r/20210318104036.3175910-5-lee.jones@linaro.org +Stable-dep-of: d79972789d17 ("of: dynamic: Fix of_reconfig_get_state_change() return value documentation") +Signed-off-by: Sasha Levin +--- + drivers/of/base.c | 16 +++++++++++----- + 1 file changed, 11 insertions(+), 5 deletions(-) + +diff --git a/drivers/of/base.c b/drivers/of/base.c +index a44a0e7ba2510..fa45a681267cd 100644 +--- a/drivers/of/base.c ++++ b/drivers/of/base.c +@@ -305,7 +305,7 @@ bool __weak arch_match_cpu_phys_id(int cpu, u64 phys_id) + return (u32)phys_id == cpu; + } + +-/** ++/* + * Checks if the given "prop_name" property holds the physical id of the + * core/thread corresponding to the logical cpu 'cpu'. If 'thread' is not + * NULL, local thread number within the core is returned in it. +@@ -1128,7 +1128,7 @@ EXPORT_SYMBOL(of_match_node); + * will; typically, you pass what the previous call + * returned. of_node_put() will be called on it + * @matches: array of of device match structures to search in +- * @match Updated to point at the matches entry which matched ++ * @match: Updated to point at the matches entry which matched + * + * Returns a node pointer with refcount incremented, use + * of_node_put() on it when done. +@@ -1779,6 +1779,8 @@ EXPORT_SYMBOL(of_count_phandle_with_args); + + /** + * __of_add_property - Add a property to a node without lock operations ++ * @np: Caller's Device Node ++ * @prob: Property to add + */ + int __of_add_property(struct device_node *np, struct property *prop) + { +@@ -1800,6 +1802,8 @@ int __of_add_property(struct device_node *np, struct property *prop) + + /** + * of_add_property - Add a property to a node ++ * @np: Caller's Device Node ++ * @prob: Property to add + */ + int of_add_property(struct device_node *np, struct property *prop) + { +@@ -1844,6 +1848,8 @@ int __of_remove_property(struct device_node *np, struct property *prop) + + /** + * of_remove_property - Remove a property from a node. ++ * @np: Caller's Device Node ++ * @prob: Property to remove + * + * Note that we don't actually remove it, since we have given out + * who-knows-how-many pointers to the data using get-property. +@@ -2130,9 +2136,9 @@ EXPORT_SYMBOL_GPL(of_alias_get_highest_id); + + /** + * of_console_check() - Test and setup console for DT setup +- * @dn - Pointer to device node +- * @name - Name to use for preferred console without index. ex. "ttyS" +- * @index - Index to use for preferred console. ++ * @dn: Pointer to device node ++ * @name: Name to use for preferred console without index. ex. "ttyS" ++ * @index: Index to use for preferred console. + * + * Check if the given device node matches the stdout-path property in the + * /chosen node. If it does then register it as the preferred console and return +-- +2.42.0 + diff --git a/queue-5.10/of-dynamic-fix-of_reconfig_get_state_change-return-v.patch b/queue-5.10/of-dynamic-fix-of_reconfig_get_state_change-return-v.patch new file mode 100644 index 00000000000..e8fb4dde789 --- /dev/null +++ b/queue-5.10/of-dynamic-fix-of_reconfig_get_state_change-return-v.patch @@ -0,0 +1,41 @@ +From 942200d505a9419ce353162fb3eae44bc0042493 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 23 Nov 2023 15:47:18 +0100 +Subject: of: dynamic: Fix of_reconfig_get_state_change() return value + documentation + +From: Luca Ceresoli + +[ Upstream commit d79972789d17499b6091ded2fc0c6763c501a5ba ] + +The documented numeric return values do not match the actual returned +values. Fix them by using the enum names instead of raw numbers. + +Fixes: b53a2340d0d3 ("of/reconfig: Add of_reconfig_get_state_change() of notifier helper.") +Signed-off-by: Luca Ceresoli +Link: https://lore.kernel.org/r/20231123-fix-of_reconfig_get_state_change-docs-v1-1-f51892050ff9@bootlin.com +Signed-off-by: Rob Herring +Signed-off-by: Sasha Levin +--- + drivers/of/dynamic.c | 5 +++-- + 1 file changed, 3 insertions(+), 2 deletions(-) + +diff --git a/drivers/of/dynamic.c b/drivers/of/dynamic.c +index 1f55e46919004..b6a3ee65437b9 100644 +--- a/drivers/of/dynamic.c ++++ b/drivers/of/dynamic.c +@@ -104,8 +104,9 @@ int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p) + * + * Returns the new state of a device based on the notifier used. + * +- * Return: 0 on device going from enabled to disabled, 1 on device +- * going from disabled to enabled and -1 on no change. ++ * Return: OF_RECONFIG_CHANGE_REMOVE on device going from enabled to ++ * disabled, OF_RECONFIG_CHANGE_ADD on device going from disabled to ++ * enabled and OF_RECONFIG_NO_CHANGE on no change. + */ + int of_reconfig_get_state_change(unsigned long action, struct of_reconfig_data *pr) + { +-- +2.42.0 + diff --git a/queue-5.10/of-fix-kerneldoc-output-formatting.patch b/queue-5.10/of-fix-kerneldoc-output-formatting.patch new file mode 100644 index 00000000000..bd3b299841a --- /dev/null +++ b/queue-5.10/of-fix-kerneldoc-output-formatting.patch @@ -0,0 +1,500 @@ +From 485b48c016bf70d57e00198c49f00122e1506ba6 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 26 Mar 2021 13:26:06 -0600 +Subject: of: Fix kerneldoc output formatting + +From: Rob Herring + +[ Upstream commit 62f026f082e4d762a47b43ea693b38f025122332 ] + +The indentation of the kerneldoc comments affects the output formatting. +Leading tabs in particular don't work, sections need to be indented +under the section header, and several code blocks are reformatted. + +Cc: Frank Rowand +Cc: Mauro Carvalho Chehab +Signed-off-by: Rob Herring +Reviewed-by: Mauro Carvalho Chehab +Link: https://lore.kernel.org/r/20210326192606.3702739-1-robh@kernel.org +Stable-dep-of: d79972789d17 ("of: dynamic: Fix of_reconfig_get_state_change() return value documentation") +Signed-off-by: Sasha Levin +--- + drivers/of/base.c | 275 +++++++++++++++++++++++----------------------- + drivers/of/fdt.c | 9 +- + 2 files changed, 141 insertions(+), 143 deletions(-) + +diff --git a/drivers/of/base.c b/drivers/of/base.c +index fa45a681267cd..85a55cfd00f11 100644 +--- a/drivers/of/base.c ++++ b/drivers/of/base.c +@@ -651,11 +651,11 @@ bool of_device_is_big_endian(const struct device_node *device) + EXPORT_SYMBOL(of_device_is_big_endian); + + /** +- * of_get_parent - Get a node's parent if any +- * @node: Node to get parent ++ * of_get_parent - Get a node's parent if any ++ * @node: Node to get parent + * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_get_parent(const struct device_node *node) + { +@@ -673,15 +673,15 @@ struct device_node *of_get_parent(const struct device_node *node) + EXPORT_SYMBOL(of_get_parent); + + /** +- * of_get_next_parent - Iterate to a node's parent +- * @node: Node to get parent of ++ * of_get_next_parent - Iterate to a node's parent ++ * @node: Node to get parent of + * +- * This is like of_get_parent() except that it drops the +- * refcount on the passed node, making it suitable for iterating +- * through a node's parents. ++ * This is like of_get_parent() except that it drops the ++ * refcount on the passed node, making it suitable for iterating ++ * through a node's parents. + * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_get_next_parent(struct device_node *node) + { +@@ -719,13 +719,13 @@ static struct device_node *__of_get_next_child(const struct device_node *node, + child = __of_get_next_child(parent, child)) + + /** +- * of_get_next_child - Iterate a node childs +- * @node: parent node +- * @prev: previous child of the parent node, or NULL to get first ++ * of_get_next_child - Iterate a node childs ++ * @node: parent node ++ * @prev: previous child of the parent node, or NULL to get first + * +- * Returns a node pointer with refcount incremented, use of_node_put() on +- * it when done. Returns NULL when prev is the last child. Decrements the +- * refcount of prev. ++ * Return: A node pointer with refcount incremented, use of_node_put() on ++ * it when done. Returns NULL when prev is the last child. Decrements the ++ * refcount of prev. + */ + struct device_node *of_get_next_child(const struct device_node *node, + struct device_node *prev) +@@ -741,12 +741,12 @@ struct device_node *of_get_next_child(const struct device_node *node, + EXPORT_SYMBOL(of_get_next_child); + + /** +- * of_get_next_available_child - Find the next available child node +- * @node: parent node +- * @prev: previous child of the parent node, or NULL to get first ++ * of_get_next_available_child - Find the next available child node ++ * @node: parent node ++ * @prev: previous child of the parent node, or NULL to get first + * +- * This function is like of_get_next_child(), except that it +- * automatically skips any disabled nodes (i.e. status = "disabled"). ++ * This function is like of_get_next_child(), except that it ++ * automatically skips any disabled nodes (i.e. status = "disabled"). + */ + struct device_node *of_get_next_available_child(const struct device_node *node, + struct device_node *prev) +@@ -772,12 +772,12 @@ struct device_node *of_get_next_available_child(const struct device_node *node, + EXPORT_SYMBOL(of_get_next_available_child); + + /** +- * of_get_next_cpu_node - Iterate on cpu nodes +- * @prev: previous child of the /cpus node, or NULL to get first ++ * of_get_next_cpu_node - Iterate on cpu nodes ++ * @prev: previous child of the /cpus node, or NULL to get first + * +- * Returns a cpu node pointer with refcount incremented, use of_node_put() +- * on it when done. Returns NULL when prev is the last child. Decrements +- * the refcount of prev. ++ * Return: A cpu node pointer with refcount incremented, use of_node_put() ++ * on it when done. Returns NULL when prev is the last child. Decrements ++ * the refcount of prev. + */ + struct device_node *of_get_next_cpu_node(struct device_node *prev) + { +@@ -834,15 +834,15 @@ struct device_node *of_get_compatible_child(const struct device_node *parent, + EXPORT_SYMBOL(of_get_compatible_child); + + /** +- * of_get_child_by_name - Find the child node by name for a given parent +- * @node: parent node +- * @name: child name to look for. ++ * of_get_child_by_name - Find the child node by name for a given parent ++ * @node: parent node ++ * @name: child name to look for. + * +- * This function looks for child node for given matching name ++ * This function looks for child node for given matching name + * +- * Returns a node pointer if found, with refcount incremented, use +- * of_node_put() on it when done. +- * Returns NULL if node is not found. ++ * Return: A node pointer if found, with refcount incremented, use ++ * of_node_put() on it when done. ++ * Returns NULL if node is not found. + */ + struct device_node *of_get_child_by_name(const struct device_node *node, + const char *name) +@@ -893,22 +893,22 @@ struct device_node *__of_find_node_by_full_path(struct device_node *node, + } + + /** +- * of_find_node_opts_by_path - Find a node matching a full OF path +- * @path: Either the full path to match, or if the path does not +- * start with '/', the name of a property of the /aliases +- * node (an alias). In the case of an alias, the node +- * matching the alias' value will be returned. +- * @opts: Address of a pointer into which to store the start of +- * an options string appended to the end of the path with +- * a ':' separator. +- * +- * Valid paths: +- * /foo/bar Full path +- * foo Valid alias +- * foo/bar Valid alias + relative path +- * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * of_find_node_opts_by_path - Find a node matching a full OF path ++ * @path: Either the full path to match, or if the path does not ++ * start with '/', the name of a property of the /aliases ++ * node (an alias). In the case of an alias, the node ++ * matching the alias' value will be returned. ++ * @opts: Address of a pointer into which to store the start of ++ * an options string appended to the end of the path with ++ * a ':' separator. ++ * ++ * Valid paths: ++ * * /foo/bar Full path ++ * * foo Valid alias ++ * * foo/bar Valid alias + relative path ++ * ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_find_node_opts_by_path(const char *path, const char **opts) + { +@@ -958,15 +958,15 @@ struct device_node *of_find_node_opts_by_path(const char *path, const char **opt + EXPORT_SYMBOL(of_find_node_opts_by_path); + + /** +- * of_find_node_by_name - Find a node by its "name" property +- * @from: The node to start searching from or NULL; the node ++ * of_find_node_by_name - Find a node by its "name" property ++ * @from: The node to start searching from or NULL; the node + * you pass will not be searched, only the next one + * will. Typically, you pass what the previous call + * returned. of_node_put() will be called on @from. +- * @name: The name string to match against ++ * @name: The name string to match against + * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_find_node_by_name(struct device_node *from, + const char *name) +@@ -985,16 +985,16 @@ struct device_node *of_find_node_by_name(struct device_node *from, + EXPORT_SYMBOL(of_find_node_by_name); + + /** +- * of_find_node_by_type - Find a node by its "device_type" property +- * @from: The node to start searching from, or NULL to start searching ++ * of_find_node_by_type - Find a node by its "device_type" property ++ * @from: The node to start searching from, or NULL to start searching + * the entire device tree. The node you pass will not be + * searched, only the next one will; typically, you pass + * what the previous call returned. of_node_put() will be + * called on from for you. +- * @type: The type string to match against ++ * @type: The type string to match against + * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_find_node_by_type(struct device_node *from, + const char *type) +@@ -1013,18 +1013,18 @@ struct device_node *of_find_node_by_type(struct device_node *from, + EXPORT_SYMBOL(of_find_node_by_type); + + /** +- * of_find_compatible_node - Find a node based on type and one of the ++ * of_find_compatible_node - Find a node based on type and one of the + * tokens in its "compatible" property +- * @from: The node to start searching from or NULL, the node +- * you pass will not be searched, only the next one +- * will; typically, you pass what the previous call +- * returned. of_node_put() will be called on it +- * @type: The type string to match "device_type" or NULL to ignore +- * @compatible: The string to match to one of the tokens in the device +- * "compatible" list. +- * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * @from: The node to start searching from or NULL, the node ++ * you pass will not be searched, only the next one ++ * will; typically, you pass what the previous call ++ * returned. of_node_put() will be called on it ++ * @type: The type string to match "device_type" or NULL to ignore ++ * @compatible: The string to match to one of the tokens in the device ++ * "compatible" list. ++ * ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_find_compatible_node(struct device_node *from, + const char *type, const char *compatible) +@@ -1044,16 +1044,16 @@ struct device_node *of_find_compatible_node(struct device_node *from, + EXPORT_SYMBOL(of_find_compatible_node); + + /** +- * of_find_node_with_property - Find a node which has a property with +- * the given name. +- * @from: The node to start searching from or NULL, the node +- * you pass will not be searched, only the next one +- * will; typically, you pass what the previous call +- * returned. of_node_put() will be called on it +- * @prop_name: The name of the property to look for. +- * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * of_find_node_with_property - Find a node which has a property with ++ * the given name. ++ * @from: The node to start searching from or NULL, the node ++ * you pass will not be searched, only the next one ++ * will; typically, you pass what the previous call ++ * returned. of_node_put() will be called on it ++ * @prop_name: The name of the property to look for. ++ * ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_find_node_with_property(struct device_node *from, + const char *prop_name) +@@ -1102,10 +1102,10 @@ const struct of_device_id *__of_match_node(const struct of_device_id *matches, + + /** + * of_match_node - Tell if a device_node has a matching of_match structure +- * @matches: array of of device match structures to search in +- * @node: the of device structure to match against ++ * @matches: array of of device match structures to search in ++ * @node: the of device structure to match against + * +- * Low level utility function used by device matching. ++ * Low level utility function used by device matching. + */ + const struct of_device_id *of_match_node(const struct of_device_id *matches, + const struct device_node *node) +@@ -1121,17 +1121,17 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches, + EXPORT_SYMBOL(of_match_node); + + /** +- * of_find_matching_node_and_match - Find a node based on an of_device_id +- * match table. +- * @from: The node to start searching from or NULL, the node +- * you pass will not be searched, only the next one +- * will; typically, you pass what the previous call +- * returned. of_node_put() will be called on it +- * @matches: array of of device match structures to search in +- * @match: Updated to point at the matches entry which matched +- * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. ++ * of_find_matching_node_and_match - Find a node based on an of_device_id ++ * match table. ++ * @from: The node to start searching from or NULL, the node ++ * you pass will not be searched, only the next one ++ * will; typically, you pass what the previous call ++ * returned. of_node_put() will be called on it ++ * @matches: array of of device match structures to search in ++ * @match: Updated to point at the matches entry which matched ++ * ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. + */ + struct device_node *of_find_matching_node_and_match(struct device_node *from, + const struct of_device_id *matches, +@@ -1465,21 +1465,21 @@ EXPORT_SYMBOL(of_parse_phandle); + * Caller is responsible to call of_node_put() on the returned out_args->np + * pointer. + * +- * Example: ++ * Example:: + * +- * phandle1: node1 { ++ * phandle1: node1 { + * #list-cells = <2>; +- * } ++ * }; + * +- * phandle2: node2 { ++ * phandle2: node2 { + * #list-cells = <1>; +- * } ++ * }; + * +- * node3 { ++ * node3 { + * list = <&phandle1 1 2 &phandle2 3>; +- * } ++ * }; + * +- * To get a device_node of the `node2' node you may call this: ++ * To get a device_node of the ``node2`` node you may call this: + * of_parse_phandle_with_args(node3, "list", "#list-cells", 1, &args); + */ + int of_parse_phandle_with_args(const struct device_node *np, const char *list_name, +@@ -1517,29 +1517,29 @@ EXPORT_SYMBOL(of_parse_phandle_with_args); + * Caller is responsible to call of_node_put() on the returned out_args->np + * pointer. + * +- * Example: ++ * Example:: + * +- * phandle1: node1 { +- * #list-cells = <2>; +- * } ++ * phandle1: node1 { ++ * #list-cells = <2>; ++ * }; + * +- * phandle2: node2 { +- * #list-cells = <1>; +- * } ++ * phandle2: node2 { ++ * #list-cells = <1>; ++ * }; + * +- * phandle3: node3 { +- * #list-cells = <1>; +- * list-map = <0 &phandle2 3>, +- * <1 &phandle2 2>, +- * <2 &phandle1 5 1>; +- * list-map-mask = <0x3>; +- * }; ++ * phandle3: node3 { ++ * #list-cells = <1>; ++ * list-map = <0 &phandle2 3>, ++ * <1 &phandle2 2>, ++ * <2 &phandle1 5 1>; ++ * list-map-mask = <0x3>; ++ * }; + * +- * node4 { +- * list = <&phandle1 1 2 &phandle3 0>; +- * } ++ * node4 { ++ * list = <&phandle1 1 2 &phandle3 0>; ++ * }; + * +- * To get a device_node of the `node2' node you may call this: ++ * To get a device_node of the ``node2`` node you may call this: + * of_parse_phandle_with_args(node4, "list", "list", 1, &args); + */ + int of_parse_phandle_with_args_map(const struct device_node *np, +@@ -1699,19 +1699,19 @@ EXPORT_SYMBOL(of_parse_phandle_with_args_map); + * Caller is responsible to call of_node_put() on the returned out_args->np + * pointer. + * +- * Example: ++ * Example:: + * +- * phandle1: node1 { +- * } ++ * phandle1: node1 { ++ * }; + * +- * phandle2: node2 { +- * } ++ * phandle2: node2 { ++ * }; + * +- * node3 { +- * list = <&phandle1 0 2 &phandle2 2 3>; +- * } ++ * node3 { ++ * list = <&phandle1 0 2 &phandle2 2 3>; ++ * }; + * +- * To get a device_node of the `node2' node you may call this: ++ * To get a device_node of the ``node2`` node you may call this: + * of_parse_phandle_with_fixed_args(node3, "list", 2, 1, &args); + */ + int of_parse_phandle_with_fixed_args(const struct device_node *np, +@@ -1957,13 +1957,12 @@ static void of_alias_add(struct alias_prop *ap, struct device_node *np, + + /** + * of_alias_scan - Scan all properties of the 'aliases' node ++ * @dt_alloc: An allocator that provides a virtual address to memory ++ * for storing the resulting tree + * + * The function scans all the properties of the 'aliases' node and populates + * the global lookup table with the properties. It returns the + * number of alias properties found, or an error code in case of failure. +- * +- * @dt_alloc: An allocator that provides a virtual address to memory +- * for storing the resulting tree + */ + void of_alias_scan(void * (*dt_alloc)(u64 size, u64 align)) + { +@@ -2158,12 +2157,12 @@ bool of_console_check(struct device_node *dn, char *name, int index) + EXPORT_SYMBOL_GPL(of_console_check); + + /** +- * of_find_next_cache_node - Find a node's subsidiary cache +- * @np: node of type "cpu" or "cache" ++ * of_find_next_cache_node - Find a node's subsidiary cache ++ * @np: node of type "cpu" or "cache" + * +- * Returns a node pointer with refcount incremented, use +- * of_node_put() on it when done. Caller should hold a reference +- * to np. ++ * Return: A node pointer with refcount incremented, use ++ * of_node_put() on it when done. Caller should hold a reference ++ * to np. + */ + struct device_node *of_find_next_cache_node(const struct device_node *np) + { +diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c +index 5a1b8688b4605..81e03bd896751 100644 +--- a/drivers/of/fdt.c ++++ b/drivers/of/fdt.c +@@ -349,11 +349,6 @@ static int unflatten_dt_nodes(const void *blob, + + /** + * __unflatten_device_tree - create tree of device_nodes from flat blob +- * +- * unflattens a device-tree, creating the +- * tree of struct device_node. It also fills the "name" and "type" +- * pointers of the nodes so the normal device-tree walking functions +- * can be used. + * @blob: The blob to expand + * @dad: Parent device node + * @mynodes: The device_node tree created by the call +@@ -361,6 +356,10 @@ static int unflatten_dt_nodes(const void *blob, + * for the resulting tree + * @detached: if true set OF_DETACHED on @mynodes + * ++ * unflattens a device-tree, creating the tree of struct device_node. It also ++ * fills the "name" and "type" pointers of the nodes so the normal device-tree ++ * walking functions can be used. ++ * + * Returns NULL on failure or the memory chunk containing the unflattened + * device tree on success. + */ +-- +2.42.0 + diff --git a/queue-5.10/platform-x86-asus-nb-wmi-add-tablet_mode_sw-lid-flip.patch b/queue-5.10/platform-x86-asus-nb-wmi-add-tablet_mode_sw-lid-flip.patch new file mode 100644 index 00000000000..d44cc33b09d --- /dev/null +++ b/queue-5.10/platform-x86-asus-nb-wmi-add-tablet_mode_sw-lid-flip.patch @@ -0,0 +1,46 @@ +From 83ecbc3856cb907c6f27bb642043fe5a18464cb1 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Aug 2021 16:55:13 +0200 +Subject: platform/x86: asus-nb-wmi: Add tablet_mode_sw=lid-flip quirk for the + TP200s + +From: Hans de Goede + +[ Upstream commit 411f48bb58f49c40a627b052402a90e8301cd07e ] + +The Asus TP200s / E205SA 360 degree hinges 2-in-1 supports reporting +SW_TABLET_MODE info through the ASUS_WMI_DEVID_LID_FLIP WMI device-id. +Add a quirk to enable this. + +BugLink: https://gitlab.freedesktop.org/libinput/libinput/-/issues/639 +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20210812145513.39117-2-hdegoede@redhat.com +Stable-dep-of: b52cbca22cbf ("platform/x86: asus-wmi: Move i8042 filter install to shared asus-wmi code") +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/asus-nb-wmi.c | 9 +++++++++ + 1 file changed, 9 insertions(+) + +diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c +index b7eacf54f2862..59ca3dab59e10 100644 +--- a/drivers/platform/x86/asus-nb-wmi.c ++++ b/drivers/platform/x86/asus-nb-wmi.c +@@ -462,6 +462,15 @@ static const struct dmi_system_id asus_quirks[] = { + }, + .driver_data = &quirk_asus_use_lid_flip_devid, + }, ++ { ++ .callback = dmi_matched, ++ .ident = "ASUS TP200s / E205SA", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "E205SA"), ++ }, ++ .driver_data = &quirk_asus_use_lid_flip_devid, ++ }, + {}, + }; + +-- +2.42.0 + diff --git a/queue-5.10/platform-x86-asus-nb-wmi-allow-configuring-sw_tablet.patch b/queue-5.10/platform-x86-asus-nb-wmi-allow-configuring-sw_tablet.patch new file mode 100644 index 00000000000..2a71c0eeb35 --- /dev/null +++ b/queue-5.10/platform-x86-asus-nb-wmi-allow-configuring-sw_tablet.patch @@ -0,0 +1,66 @@ +From 1972321e546ffae692bde4e402c6fe1b5f886b96 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 12 Aug 2021 16:55:12 +0200 +Subject: platform/x86: asus-nb-wmi: Allow configuring SW_TABLET_MODE method + with a module option + +From: Hans de Goede + +[ Upstream commit 6be70ccdd989e40af151ce52db5b2d93e97fc9fb ] + +Unfortunately we have been unable to find a reliable way to detect if +and how SW_TABLET_MODE reporting is supported, so we are relying on +DMI quirks for this. + +Add a module-option to specify the SW_TABLET_MODE method so that this can +be easily tested without needing to rebuild the kernel. + +BugLink: https://gitlab.freedesktop.org/libinput/libinput/-/issues/639 +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20210812145513.39117-1-hdegoede@redhat.com +Stable-dep-of: b52cbca22cbf ("platform/x86: asus-wmi: Move i8042 filter install to shared asus-wmi code") +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/asus-nb-wmi.c | 19 +++++++++++++++++++ + 1 file changed, 19 insertions(+) + +diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c +index f47b6f30599de..b7eacf54f2862 100644 +--- a/drivers/platform/x86/asus-nb-wmi.c ++++ b/drivers/platform/x86/asus-nb-wmi.c +@@ -41,6 +41,10 @@ static int wapf = -1; + module_param(wapf, uint, 0444); + MODULE_PARM_DESC(wapf, "WAPF value"); + ++static int tablet_mode_sw = -1; ++module_param(tablet_mode_sw, uint, 0444); ++MODULE_PARM_DESC(tablet_mode_sw, "Tablet mode detect: -1:auto 0:disable 1:kbd-dock 2:lid-flip"); ++ + static struct quirk_entry *quirks; + + static bool asus_q500a_i8042_filter(unsigned char data, unsigned char str, +@@ -477,6 +481,21 @@ static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver) + else + wapf = quirks->wapf; + ++ switch (tablet_mode_sw) { ++ case 0: ++ quirks->use_kbd_dock_devid = false; ++ quirks->use_lid_flip_devid = false; ++ break; ++ case 1: ++ quirks->use_kbd_dock_devid = true; ++ quirks->use_lid_flip_devid = false; ++ break; ++ case 2: ++ quirks->use_kbd_dock_devid = false; ++ quirks->use_lid_flip_devid = true; ++ break; ++ } ++ + if (quirks->i8042_filter) { + ret = i8042_install_filter(quirks->i8042_filter); + if (ret) { +-- +2.42.0 + diff --git a/queue-5.10/platform-x86-asus-wmi-add-support-for-rog-x13-tablet.patch b/queue-5.10/platform-x86-asus-wmi-add-support-for-rog-x13-tablet.patch new file mode 100644 index 00000000000..313bfdae98e --- /dev/null +++ b/queue-5.10/platform-x86-asus-wmi-add-support-for-rog-x13-tablet.patch @@ -0,0 +1,175 @@ +From f5afacf02111af97232f2a51504ed2174d6c0639 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 13 Aug 2022 21:27:53 +1200 +Subject: platform/x86: asus-wmi: Add support for ROG X13 tablet mode + +From: Luke D. Jones + +[ Upstream commit e397c3c460bf3849384f2f55516d1887617cfca9 ] + +Add quirk for ASUS ROG X13 Flow 2-in-1 to enable tablet mode with +lid flip (all screen rotations). + +Signed-off-by: Luke D. Jones +Link: https://lore.kernel.org/r/20220813092753.6635-2-luke@ljones.dev +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Stable-dep-of: b52cbca22cbf ("platform/x86: asus-wmi: Move i8042 filter install to shared asus-wmi code") +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/asus-nb-wmi.c | 15 +++++++++ + drivers/platform/x86/asus-wmi.c | 37 ++++++++++++++++++++++ + drivers/platform/x86/asus-wmi.h | 1 + + include/linux/platform_data/x86/asus-wmi.h | 1 + + 4 files changed, 54 insertions(+) + +diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c +index f723af0106a1f..2857678efa2eb 100644 +--- a/drivers/platform/x86/asus-nb-wmi.c ++++ b/drivers/platform/x86/asus-nb-wmi.c +@@ -123,6 +123,11 @@ static struct quirk_entry quirk_asus_use_lid_flip_devid = { + .tablet_switch_mode = asus_wmi_lid_flip_devid, + }; + ++static struct quirk_entry quirk_asus_tablet_mode = { ++ .wmi_backlight_set_devstate = true, ++ .tablet_switch_mode = asus_wmi_lid_flip_rog_devid, ++}; ++ + static int dmi_matched(const struct dmi_system_id *dmi) + { + pr_info("Identified laptop model '%s'\n", dmi->ident); +@@ -471,6 +476,15 @@ static const struct dmi_system_id asus_quirks[] = { + }, + .driver_data = &quirk_asus_use_lid_flip_devid, + }, ++ { ++ .callback = dmi_matched, ++ .ident = "ASUS ROG FLOW X13", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), ++ DMI_MATCH(DMI_PRODUCT_NAME, "GV301Q"), ++ }, ++ .driver_data = &quirk_asus_tablet_mode, ++ }, + {}, + }; + +@@ -581,6 +595,7 @@ static const struct key_entry asus_nb_wmi_keymap[] = { + { KE_KEY, 0xC5, { KEY_KBDILLUMDOWN } }, + { KE_IGNORE, 0xC6, }, /* Ambient Light Sensor notification */ + { KE_KEY, 0xFA, { KEY_PROG2 } }, /* Lid flip action */ ++ { KE_KEY, 0xBD, { KEY_PROG2 } }, /* Lid flip action on ROG xflow laptops */ + { KE_END, 0}, + }; + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index 80a442a392cb2..31f5e4df43910 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -64,6 +64,7 @@ MODULE_LICENSE("GPL"); + #define NOTIFY_KBD_FBM 0x99 + #define NOTIFY_KBD_TTP 0xae + #define NOTIFY_LID_FLIP 0xfa ++#define NOTIFY_LID_FLIP_ROG 0xbd + + #define ASUS_WMI_FNLOCK_BIOS_DISABLED BIT(0) + +@@ -397,6 +398,19 @@ static int asus_wmi_input_init(struct asus_wmi *asus) + dev_err(dev, "Error checking for lid-flip: %d\n", result); + } + break; ++ case asus_wmi_lid_flip_rog_devid: ++ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP_ROG); ++ if (result < 0) ++ asus->driver->quirks->tablet_switch_mode = asus_wmi_no_tablet_switch; ++ if (result >= 0) { ++ input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE); ++ input_report_switch(asus->inputdev, SW_TABLET_MODE, result); ++ } else if (result == -ENODEV) { ++ dev_err(dev, "This device has lid-flip-rog quirk but got ENODEV checking it. This is a bug."); ++ } else { ++ dev_err(dev, "Error checking for lid-flip: %d\n", result); ++ } ++ break; + } + + err = input_register_device(asus->inputdev); +@@ -431,6 +445,17 @@ static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus) + } + } + ++static void lid_flip_rog_tablet_mode_get_state(struct asus_wmi *asus) ++{ ++ int result; ++ ++ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP_ROG); ++ if (result >= 0) { ++ input_report_switch(asus->inputdev, SW_TABLET_MODE, result); ++ input_sync(asus->inputdev); ++ } ++} ++ + /* dGPU ********************************************************************/ + static int dgpu_disable_check_present(struct asus_wmi *asus) + { +@@ -2261,6 +2286,12 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) + return; + } + ++ if (asus->driver->quirks->tablet_switch_mode == asus_wmi_lid_flip_rog_devid && ++ code == NOTIFY_LID_FLIP_ROG) { ++ lid_flip_rog_tablet_mode_get_state(asus); ++ return; ++ } ++ + if (asus->fan_boost_mode_available && code == NOTIFY_KBD_FBM) { + fan_boost_mode_switch_next(asus); + return; +@@ -2868,6 +2899,9 @@ static int asus_hotk_resume(struct device *device) + case asus_wmi_lid_flip_devid: + lid_flip_tablet_mode_get_state(asus); + break; ++ case asus_wmi_lid_flip_rog_devid: ++ lid_flip_rog_tablet_mode_get_state(asus); ++ break; + } + + return 0; +@@ -2916,6 +2950,9 @@ static int asus_hotk_restore(struct device *device) + case asus_wmi_lid_flip_devid: + lid_flip_tablet_mode_get_state(asus); + break; ++ case asus_wmi_lid_flip_rog_devid: ++ lid_flip_rog_tablet_mode_get_state(asus); ++ break; + } + + return 0; +diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h +index f0302a51c5196..b817a312f2e1a 100644 +--- a/drivers/platform/x86/asus-wmi.h ++++ b/drivers/platform/x86/asus-wmi.h +@@ -29,6 +29,7 @@ enum asus_wmi_tablet_switch_mode { + asus_wmi_no_tablet_switch, + asus_wmi_kbd_dock_devid, + asus_wmi_lid_flip_devid, ++ asus_wmi_lid_flip_rog_devid, + }; + + struct quirk_entry { +diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h +index 7d8d3e9c45d62..60cad2aac5c1c 100644 +--- a/include/linux/platform_data/x86/asus-wmi.h ++++ b/include/linux/platform_data/x86/asus-wmi.h +@@ -63,6 +63,7 @@ + /* Misc */ + #define ASUS_WMI_DEVID_CAMERA 0x00060013 + #define ASUS_WMI_DEVID_LID_FLIP 0x00060062 ++#define ASUS_WMI_DEVID_LID_FLIP_ROG 0x00060077 + + /* Storage */ + #define ASUS_WMI_DEVID_CARDREADER 0x00080013 +-- +2.42.0 + diff --git a/queue-5.10/platform-x86-asus-wmi-add-support-for-sw_tablet_mode.patch b/queue-5.10/platform-x86-asus-wmi-add-support-for-sw_tablet_mode.patch new file mode 100644 index 00000000000..f279d3d192b --- /dev/null +++ b/queue-5.10/platform-x86-asus-wmi-add-support-for-sw_tablet_mode.patch @@ -0,0 +1,192 @@ +From db65ce9a7defab254150d415855def1aeae46d33 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 21 Oct 2020 00:09:44 +0200 +Subject: platform/x86: asus-wmi: Add support for SW_TABLET_MODE on UX360 +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Samuel Čavoj + +[ Upstream commit ea856ec266c1e6aecd2b107032d5b5d661f0686d ] + +The UX360CA has a WMI device id 0x00060062, which reports whether the +lid is flipped in tablet mode (1) or in normal laptop mode (0). + +Add a quirk (quirk_asus_use_lid_flip_devid) for devices on which this +WMI device should be used to figure out the SW_TABLET_MODE state, as +opposed to the quirk_asus_use_kbd_dock_devid. + +Additionally, the device needs to be queried on resume and restore +because the firmware does not generate an event if the laptop is put to +sleep while in tablet mode, flipped to normal mode, and later awoken. + +It is assumed other UX360* models have the same WMI device. As such, the +quirk is applied to devices with DMI_MATCH(DMI_PRODUCT_NAME, "UX360"). +More devices with this feature need to be tested and added accordingly. + +The reason for using an allowlist via the quirk mechanism is that the new +WMI device (0x00060062) is also present on some models which do not have +a 360 degree hinge (at least FX503VD and GL503VD from Hans' DSTS +collection) and therefore its presence cannot be relied on. + +Signed-off-by: Samuel Čavoj +Cc: Hans de Goede +Link: https://lore.kernel.org/r/20201020220944.1075530-1-samuel@cavoj.net +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Stable-dep-of: b52cbca22cbf ("platform/x86: asus-wmi: Move i8042 filter install to shared asus-wmi code") +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/asus-nb-wmi.c | 15 ++++++++ + drivers/platform/x86/asus-wmi.c | 40 ++++++++++++++++++++++ + drivers/platform/x86/asus-wmi.h | 1 + + include/linux/platform_data/x86/asus-wmi.h | 1 + + 4 files changed, 57 insertions(+) + +diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c +index 04503ad6c7fb0..f47b6f30599de 100644 +--- a/drivers/platform/x86/asus-nb-wmi.c ++++ b/drivers/platform/x86/asus-nb-wmi.c +@@ -114,6 +114,11 @@ static struct quirk_entry quirk_asus_use_kbd_dock_devid = { + .use_kbd_dock_devid = true, + }; + ++static struct quirk_entry quirk_asus_use_lid_flip_devid = { ++ .wmi_backlight_set_devstate = true, ++ .use_lid_flip_devid = true, ++}; ++ + static int dmi_matched(const struct dmi_system_id *dmi) + { + pr_info("Identified laptop model '%s'\n", dmi->ident); +@@ -443,6 +448,16 @@ static const struct dmi_system_id asus_quirks[] = { + }, + .driver_data = &quirk_asus_use_kbd_dock_devid, + }, ++ { ++ .callback = dmi_matched, ++ .ident = "ASUS ZenBook Flip UX360", ++ .matches = { ++ DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), ++ /* Match UX360* */ ++ DMI_MATCH(DMI_PRODUCT_NAME, "UX360"), ++ }, ++ .driver_data = &quirk_asus_use_lid_flip_devid, ++ }, + {}, + }; + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index db369cf261119..ca3b97b7a6ad8 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -63,6 +63,7 @@ MODULE_LICENSE("GPL"); + #define NOTIFY_KBD_BRTTOGGLE 0xc7 + #define NOTIFY_KBD_FBM 0x99 + #define NOTIFY_KBD_TTP 0xae ++#define NOTIFY_LID_FLIP 0xfa + + #define ASUS_WMI_FNLOCK_BIOS_DISABLED BIT(0) + +@@ -375,6 +376,20 @@ static int asus_wmi_input_init(struct asus_wmi *asus) + } + } + ++ if (asus->driver->quirks->use_lid_flip_devid) { ++ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP); ++ if (result < 0) ++ asus->driver->quirks->use_lid_flip_devid = 0; ++ if (result >= 0) { ++ input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE); ++ input_report_switch(asus->inputdev, SW_TABLET_MODE, result); ++ } else if (result == -ENODEV) { ++ pr_err("This device has lid_flip quirk but got ENODEV checking it. This is a bug."); ++ } else { ++ pr_err("Error checking for lid-flip: %d\n", result); ++ } ++ } ++ + err = input_register_device(asus->inputdev); + if (err) + goto err_free_dev; +@@ -394,6 +409,18 @@ static void asus_wmi_input_exit(struct asus_wmi *asus) + asus->inputdev = NULL; + } + ++/* Tablet mode ****************************************************************/ ++ ++static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus) ++{ ++ int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP); ++ ++ if (result >= 0) { ++ input_report_switch(asus->inputdev, SW_TABLET_MODE, result); ++ input_sync(asus->inputdev); ++ } ++} ++ + /* Battery ********************************************************************/ + + /* The battery maximum charging percentage */ +@@ -2130,6 +2157,11 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) + return; + } + ++ if (asus->driver->quirks->use_lid_flip_devid && code == NOTIFY_LID_FLIP) { ++ lid_flip_tablet_mode_get_state(asus); ++ return; ++ } ++ + if (asus->fan_boost_mode_available && code == NOTIFY_KBD_FBM) { + fan_boost_mode_switch_next(asus); + return; +@@ -2721,6 +2753,10 @@ static int asus_hotk_resume(struct device *device) + + if (asus_wmi_has_fnlock_key(asus)) + asus_wmi_fnlock_update(asus); ++ ++ if (asus->driver->quirks->use_lid_flip_devid) ++ lid_flip_tablet_mode_get_state(asus); ++ + return 0; + } + +@@ -2759,6 +2795,10 @@ static int asus_hotk_restore(struct device *device) + + if (asus_wmi_has_fnlock_key(asus)) + asus_wmi_fnlock_update(asus); ++ ++ if (asus->driver->quirks->use_lid_flip_devid) ++ lid_flip_tablet_mode_get_state(asus); ++ + return 0; + } + +diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h +index 1d0b592e2651b..49f2b8f8ad3eb 100644 +--- a/drivers/platform/x86/asus-wmi.h ++++ b/drivers/platform/x86/asus-wmi.h +@@ -34,6 +34,7 @@ struct quirk_entry { + bool wmi_backlight_set_devstate; + bool wmi_force_als_set; + bool use_kbd_dock_devid; ++ bool use_lid_flip_devid; + int wapf; + /* + * For machines with AMD graphic chips, it will send out WMI event +diff --git a/include/linux/platform_data/x86/asus-wmi.h b/include/linux/platform_data/x86/asus-wmi.h +index 897b8332a39f4..2f274cf528050 100644 +--- a/include/linux/platform_data/x86/asus-wmi.h ++++ b/include/linux/platform_data/x86/asus-wmi.h +@@ -62,6 +62,7 @@ + + /* Misc */ + #define ASUS_WMI_DEVID_CAMERA 0x00060013 ++#define ASUS_WMI_DEVID_LID_FLIP 0x00060062 + + /* Storage */ + #define ASUS_WMI_DEVID_CARDREADER 0x00080013 +-- +2.42.0 + diff --git a/queue-5.10/platform-x86-asus-wmi-adjust-tablet-lidflip-handling.patch b/queue-5.10/platform-x86-asus-wmi-adjust-tablet-lidflip-handling.patch new file mode 100644 index 00000000000..b084581205f --- /dev/null +++ b/queue-5.10/platform-x86-asus-wmi-adjust-tablet-lidflip-handling.patch @@ -0,0 +1,220 @@ +From 143436933c6f5239d89856c1af6fd2cb2ef5f983 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 13 Aug 2022 21:27:52 +1200 +Subject: platform/x86: asus-wmi: Adjust tablet/lidflip handling to use enum + +From: Luke D. Jones + +[ Upstream commit 00aa846955fbfb04f7bc0c26c49febfe5395eca1 ] + +Due to multiple types of tablet/lidflip, the existing code for +handling these events is refactored to use an enum for each type. + +Signed-off-by: Luke D. Jones +Link: https://lore.kernel.org/r/20220813092753.6635-1-luke@ljones.dev +Reviewed-by: Hans de Goede +Signed-off-by: Hans de Goede +Stable-dep-of: b52cbca22cbf ("platform/x86: asus-wmi: Move i8042 filter install to shared asus-wmi code") +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/asus-nb-wmi.c | 13 +++----- + drivers/platform/x86/asus-wmi.c | 49 +++++++++++++++++++++--------- + drivers/platform/x86/asus-wmi.h | 9 ++++-- + 3 files changed, 47 insertions(+), 24 deletions(-) + +diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c +index 59ca3dab59e10..f723af0106a1f 100644 +--- a/drivers/platform/x86/asus-nb-wmi.c ++++ b/drivers/platform/x86/asus-nb-wmi.c +@@ -115,12 +115,12 @@ static struct quirk_entry quirk_asus_forceals = { + }; + + static struct quirk_entry quirk_asus_use_kbd_dock_devid = { +- .use_kbd_dock_devid = true, ++ .tablet_switch_mode = asus_wmi_kbd_dock_devid, + }; + + static struct quirk_entry quirk_asus_use_lid_flip_devid = { + .wmi_backlight_set_devstate = true, +- .use_lid_flip_devid = true, ++ .tablet_switch_mode = asus_wmi_lid_flip_devid, + }; + + static int dmi_matched(const struct dmi_system_id *dmi) +@@ -492,16 +492,13 @@ static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver) + + switch (tablet_mode_sw) { + case 0: +- quirks->use_kbd_dock_devid = false; +- quirks->use_lid_flip_devid = false; ++ quirks->tablet_switch_mode = asus_wmi_no_tablet_switch; + break; + case 1: +- quirks->use_kbd_dock_devid = true; +- quirks->use_lid_flip_devid = false; ++ quirks->tablet_switch_mode = asus_wmi_kbd_dock_devid; + break; + case 2: +- quirks->use_kbd_dock_devid = false; +- quirks->use_lid_flip_devid = true; ++ quirks->tablet_switch_mode = asus_wmi_lid_flip_devid; + break; + } + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index 93b4c61130837..80a442a392cb2 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -353,8 +353,11 @@ static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id) + + static int asus_wmi_input_init(struct asus_wmi *asus) + { ++ struct device *dev; + int err, result; + ++ dev = &asus->platform_device->dev; ++ + asus->inputdev = input_allocate_device(); + if (!asus->inputdev) + return -ENOMEM; +@@ -362,35 +365,38 @@ static int asus_wmi_input_init(struct asus_wmi *asus) + asus->inputdev->name = asus->driver->input_name; + asus->inputdev->phys = asus->driver->input_phys; + asus->inputdev->id.bustype = BUS_HOST; +- asus->inputdev->dev.parent = &asus->platform_device->dev; ++ asus->inputdev->dev.parent = dev; + set_bit(EV_REP, asus->inputdev->evbit); + + err = sparse_keymap_setup(asus->inputdev, asus->driver->keymap, NULL); + if (err) + goto err_free_dev; + +- if (asus->driver->quirks->use_kbd_dock_devid) { ++ switch (asus->driver->quirks->tablet_switch_mode) { ++ case asus_wmi_no_tablet_switch: ++ break; ++ case asus_wmi_kbd_dock_devid: + result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_KBD_DOCK); + if (result >= 0) { + input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE); + input_report_switch(asus->inputdev, SW_TABLET_MODE, !result); + } else if (result != -ENODEV) { +- pr_err("Error checking for keyboard-dock: %d\n", result); ++ dev_err(dev, "Error checking for keyboard-dock: %d\n", result); + } +- } +- +- if (asus->driver->quirks->use_lid_flip_devid) { ++ break; ++ case asus_wmi_lid_flip_devid: + result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP); + if (result < 0) +- asus->driver->quirks->use_lid_flip_devid = 0; ++ asus->driver->quirks->tablet_switch_mode = asus_wmi_no_tablet_switch; + if (result >= 0) { + input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE); + input_report_switch(asus->inputdev, SW_TABLET_MODE, result); + } else if (result == -ENODEV) { +- pr_err("This device has lid_flip quirk but got ENODEV checking it. This is a bug."); ++ dev_err(dev, "This device has lid_flip quirk but got ENODEV checking it. This is a bug."); + } else { +- pr_err("Error checking for lid-flip: %d\n", result); ++ dev_err(dev, "Error checking for lid-flip: %d\n", result); + } ++ break; + } + + err = input_register_device(asus->inputdev); +@@ -416,8 +422,9 @@ static void asus_wmi_input_exit(struct asus_wmi *asus) + + static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus) + { +- int result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP); ++ int result; + ++ result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP); + if (result >= 0) { + input_report_switch(asus->inputdev, SW_TABLET_MODE, result); + input_sync(asus->inputdev); +@@ -2236,7 +2243,8 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) + return; + } + +- if (asus->driver->quirks->use_kbd_dock_devid && code == NOTIFY_KBD_DOCK_CHANGE) { ++ if (asus->driver->quirks->tablet_switch_mode == asus_wmi_kbd_dock_devid && ++ code == NOTIFY_KBD_DOCK_CHANGE) { + result = asus_wmi_get_devstate_simple(asus, + ASUS_WMI_DEVID_KBD_DOCK); + if (result >= 0) { +@@ -2247,7 +2255,8 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) + return; + } + +- if (asus->driver->quirks->use_lid_flip_devid && code == NOTIFY_LID_FLIP) { ++ if (asus->driver->quirks->tablet_switch_mode == asus_wmi_lid_flip_devid && ++ code == NOTIFY_LID_FLIP) { + lid_flip_tablet_mode_get_state(asus); + return; + } +@@ -2852,8 +2861,14 @@ static int asus_hotk_resume(struct device *device) + if (asus_wmi_has_fnlock_key(asus)) + asus_wmi_fnlock_update(asus); + +- if (asus->driver->quirks->use_lid_flip_devid) ++ switch (asus->driver->quirks->tablet_switch_mode) { ++ case asus_wmi_no_tablet_switch: ++ case asus_wmi_kbd_dock_devid: ++ break; ++ case asus_wmi_lid_flip_devid: + lid_flip_tablet_mode_get_state(asus); ++ break; ++ } + + return 0; + } +@@ -2894,8 +2909,14 @@ static int asus_hotk_restore(struct device *device) + if (asus_wmi_has_fnlock_key(asus)) + asus_wmi_fnlock_update(asus); + +- if (asus->driver->quirks->use_lid_flip_devid) ++ switch (asus->driver->quirks->tablet_switch_mode) { ++ case asus_wmi_no_tablet_switch: ++ case asus_wmi_kbd_dock_devid: ++ break; ++ case asus_wmi_lid_flip_devid: + lid_flip_tablet_mode_get_state(asus); ++ break; ++ } + + return 0; + } +diff --git a/drivers/platform/x86/asus-wmi.h b/drivers/platform/x86/asus-wmi.h +index 49f2b8f8ad3eb..f0302a51c5196 100644 +--- a/drivers/platform/x86/asus-wmi.h ++++ b/drivers/platform/x86/asus-wmi.h +@@ -25,6 +25,12 @@ struct module; + struct key_entry; + struct asus_wmi; + ++enum asus_wmi_tablet_switch_mode { ++ asus_wmi_no_tablet_switch, ++ asus_wmi_kbd_dock_devid, ++ asus_wmi_lid_flip_devid, ++}; ++ + struct quirk_entry { + bool hotplug_wireless; + bool scalar_panel_brightness; +@@ -33,8 +39,7 @@ struct quirk_entry { + bool wmi_backlight_native; + bool wmi_backlight_set_devstate; + bool wmi_force_als_set; +- bool use_kbd_dock_devid; +- bool use_lid_flip_devid; ++ enum asus_wmi_tablet_switch_mode tablet_switch_mode; + int wapf; + /* + * For machines with AMD graphic chips, it will send out WMI event +-- +2.42.0 + diff --git a/queue-5.10/platform-x86-asus-wmi-move-i8042-filter-install-to-s.patch b/queue-5.10/platform-x86-asus-wmi-move-i8042-filter-install-to-s.patch new file mode 100644 index 00000000000..71c28831059 --- /dev/null +++ b/queue-5.10/platform-x86-asus-wmi-move-i8042-filter-install-to-s.patch @@ -0,0 +1,111 @@ +From d9d643652071f6e506b9a24f9abf656056891628 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 20 Nov 2023 16:42:33 +0100 +Subject: platform/x86: asus-wmi: Move i8042 filter install to shared asus-wmi + code +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +From: Hans de Goede + +[ Upstream commit b52cbca22cbf6c9d2700c1e576d0ddcc670e49d5 ] + +asus-nb-wmi calls i8042_install_filter() in some cases, but it never +calls i8042_remove_filter(). This means that a dangling pointer to +the filter function is left after rmmod leading to crashes. + +Fix this by moving the i8042-filter installation to the shared +asus-wmi code and also remove it from the shared code on driver unbind. + +Fixes: b5643539b825 ("platform/x86: asus-wmi: Filter buggy scan codes on ASUS Q500A") +Cc: Oleksij Rempel +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20231120154235.610808-2-hdegoede@redhat.com +Reviewed-by: Ilpo Järvinen +Signed-off-by: Ilpo Järvinen +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/Kconfig | 2 +- + drivers/platform/x86/asus-nb-wmi.c | 11 ----------- + drivers/platform/x86/asus-wmi.c | 8 ++++++++ + 3 files changed, 9 insertions(+), 12 deletions(-) + +diff --git a/drivers/platform/x86/Kconfig b/drivers/platform/x86/Kconfig +index 84c5b922f245e..c14c145b88d80 100644 +--- a/drivers/platform/x86/Kconfig ++++ b/drivers/platform/x86/Kconfig +@@ -243,6 +243,7 @@ config ASUS_WMI + depends on RFKILL || RFKILL = n + depends on HOTPLUG_PCI + depends on ACPI_VIDEO || ACPI_VIDEO = n ++ depends on SERIO_I8042 || SERIO_I8042 = n + select INPUT_SPARSEKMAP + select LEDS_CLASS + select NEW_LEDS +@@ -256,7 +257,6 @@ config ASUS_WMI + config ASUS_NB_WMI + tristate "Asus Notebook WMI Driver" + depends on ASUS_WMI +- depends on SERIO_I8042 || SERIO_I8042 = n + help + This is a driver for newer Asus notebooks. It adds extra features + like wireless radio and bluetooth control, leds, hotkeys, backlight... +diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c +index 7b8942fee76dd..49505939352ae 100644 +--- a/drivers/platform/x86/asus-nb-wmi.c ++++ b/drivers/platform/x86/asus-nb-wmi.c +@@ -490,8 +490,6 @@ static const struct dmi_system_id asus_quirks[] = { + + static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver) + { +- int ret; +- + quirks = &quirk_asus_unknown; + dmi_check_system(asus_quirks); + +@@ -506,15 +504,6 @@ static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver) + + if (tablet_mode_sw != -1) + quirks->tablet_switch_mode = tablet_mode_sw; +- +- if (quirks->i8042_filter) { +- ret = i8042_install_filter(quirks->i8042_filter); +- if (ret) { +- pr_warn("Unable to install key filter\n"); +- return; +- } +- pr_info("Using i8042 filter function for receiving events\n"); +- } + } + + static const struct key_entry asus_nb_wmi_keymap[] = { +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index a1008af0741c6..695907c6503c0 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -2779,6 +2779,12 @@ static int asus_wmi_add(struct platform_device *pdev) + goto fail_wmi_handler; + } + ++ if (asus->driver->quirks->i8042_filter) { ++ err = i8042_install_filter(asus->driver->quirks->i8042_filter); ++ if (err) ++ pr_warn("Unable to install key filter - %d\n", err); ++ } ++ + asus_wmi_battery_init(asus); + + asus_wmi_debugfs_init(asus); +@@ -2810,6 +2816,8 @@ static int asus_wmi_remove(struct platform_device *device) + struct asus_wmi *asus; + + asus = platform_get_drvdata(device); ++ if (asus->driver->quirks->i8042_filter) ++ i8042_remove_filter(asus->driver->quirks->i8042_filter); + wmi_remove_notify_handler(asus->driver->event_guid); + asus_wmi_backlight_exit(asus); + asus_wmi_input_exit(asus); +-- +2.42.0 + diff --git a/queue-5.10/platform-x86-asus-wmi-simplify-tablet-mode-switch-ha.patch b/queue-5.10/platform-x86-asus-wmi-simplify-tablet-mode-switch-ha.patch new file mode 100644 index 00000000000..43eb551ad84 --- /dev/null +++ b/queue-5.10/platform-x86-asus-wmi-simplify-tablet-mode-switch-ha.patch @@ -0,0 +1,192 @@ +From 13cecc503fe3ce962912b5d3dc61b4adebbf7adc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Aug 2022 17:11:45 +0200 +Subject: platform/x86: asus-wmi: Simplify tablet-mode-switch handling + +From: Hans de Goede + +[ Upstream commit 1ea0d3b46798afc35c3185f6058b8bc08525d56c ] + +Simplify tablet-mode-switch handling: +1. The code is the same for all variants, the only difference is the + dev_id and notify event code. Store the dev_id + code in struct asus_wmi + and unify the handling +2. Make the new unified asus_wmi_tablet_mode_get_state() check dev_id has + been set and make it a no-op when not set. This allows calling it + unconditionally at resume/restore time +3. Simplify the tablet_mode_sw module-param handling, this also allows + selecting the new lid-flip-rog type through the module-param. + +Cc: Luke D. Jones +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20220824151145.1448010-2-hdegoede@redhat.com +Stable-dep-of: b52cbca22cbf ("platform/x86: asus-wmi: Move i8042 filter install to shared asus-wmi code") +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/asus-nb-wmi.c | 13 +---- + drivers/platform/x86/asus-wmi.c | 76 ++++++------------------------ + 2 files changed, 16 insertions(+), 73 deletions(-) + +diff --git a/drivers/platform/x86/asus-nb-wmi.c b/drivers/platform/x86/asus-nb-wmi.c +index 2857678efa2eb..7b8942fee76dd 100644 +--- a/drivers/platform/x86/asus-nb-wmi.c ++++ b/drivers/platform/x86/asus-nb-wmi.c +@@ -504,17 +504,8 @@ static void asus_nb_wmi_quirks(struct asus_wmi_driver *driver) + else + wapf = quirks->wapf; + +- switch (tablet_mode_sw) { +- case 0: +- quirks->tablet_switch_mode = asus_wmi_no_tablet_switch; +- break; +- case 1: +- quirks->tablet_switch_mode = asus_wmi_kbd_dock_devid; +- break; +- case 2: +- quirks->tablet_switch_mode = asus_wmi_lid_flip_devid; +- break; +- } ++ if (tablet_mode_sw != -1) ++ quirks->tablet_switch_mode = tablet_mode_sw; + + if (quirks->i8042_filter) { + ret = i8042_install_filter(quirks->i8042_filter); +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index a1a6e48d0c04e..a1008af0741c6 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -200,6 +200,9 @@ struct asus_wmi { + struct asus_rfkill gps; + struct asus_rfkill uwb; + ++ int tablet_switch_event_code; ++ u32 tablet_switch_dev_id; ++ + enum fan_type fan_type; + int fan_pwm_mode; + int agfn_pwm; +@@ -357,11 +360,11 @@ static void asus_wmi_tablet_sw_init(struct asus_wmi *asus, u32 dev_id, int event + int result; + + result = asus_wmi_get_devstate_simple(asus, dev_id); +- if (result < 0) +- asus->driver->quirks->tablet_switch_mode = asus_wmi_no_tablet_switch; + if (result >= 0) { + input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE); + input_report_switch(asus->inputdev, SW_TABLET_MODE, result); ++ asus->tablet_switch_dev_id = dev_id; ++ asus->tablet_switch_event_code = event_code; + } else if (result == -ENODEV) { + dev_err(dev, "This device has tablet-mode-switch quirk but got ENODEV checking it. This is a bug."); + } else { +@@ -423,22 +426,14 @@ static void asus_wmi_input_exit(struct asus_wmi *asus) + + /* Tablet mode ****************************************************************/ + +-static void lid_flip_tablet_mode_get_state(struct asus_wmi *asus) ++static void asus_wmi_tablet_mode_get_state(struct asus_wmi *asus) + { + int result; + +- result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP); +- if (result >= 0) { +- input_report_switch(asus->inputdev, SW_TABLET_MODE, result); +- input_sync(asus->inputdev); +- } +-} +- +-static void lid_flip_rog_tablet_mode_get_state(struct asus_wmi *asus) +-{ +- int result; ++ if (!asus->tablet_switch_dev_id) ++ return; + +- result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP_ROG); ++ result = asus_wmi_get_devstate_simple(asus, asus->tablet_switch_dev_id); + if (result >= 0) { + input_report_switch(asus->inputdev, SW_TABLET_MODE, result); + input_sync(asus->inputdev); +@@ -2212,9 +2207,7 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) + { + unsigned int key_value = 1; + bool autorelease = 1; +- int result, orig_code; +- +- orig_code = code; ++ int orig_code = code; + + if (asus->driver->key_filter) { + asus->driver->key_filter(asus->driver, &code, &key_value, +@@ -2257,27 +2250,8 @@ static void asus_wmi_handle_event_code(int code, struct asus_wmi *asus) + return; + } + +- if (asus->driver->quirks->tablet_switch_mode == asus_wmi_kbd_dock_devid && +- code == NOTIFY_KBD_DOCK_CHANGE) { +- result = asus_wmi_get_devstate_simple(asus, +- ASUS_WMI_DEVID_KBD_DOCK); +- if (result >= 0) { +- input_report_switch(asus->inputdev, SW_TABLET_MODE, +- !result); +- input_sync(asus->inputdev); +- } +- return; +- } +- +- if (asus->driver->quirks->tablet_switch_mode == asus_wmi_lid_flip_devid && +- code == NOTIFY_LID_FLIP) { +- lid_flip_tablet_mode_get_state(asus); +- return; +- } +- +- if (asus->driver->quirks->tablet_switch_mode == asus_wmi_lid_flip_rog_devid && +- code == NOTIFY_LID_FLIP_ROG) { +- lid_flip_rog_tablet_mode_get_state(asus); ++ if (code == asus->tablet_switch_event_code) { ++ asus_wmi_tablet_mode_get_state(asus); + return; + } + +@@ -2881,18 +2855,7 @@ static int asus_hotk_resume(struct device *device) + if (asus_wmi_has_fnlock_key(asus)) + asus_wmi_fnlock_update(asus); + +- switch (asus->driver->quirks->tablet_switch_mode) { +- case asus_wmi_no_tablet_switch: +- case asus_wmi_kbd_dock_devid: +- break; +- case asus_wmi_lid_flip_devid: +- lid_flip_tablet_mode_get_state(asus); +- break; +- case asus_wmi_lid_flip_rog_devid: +- lid_flip_rog_tablet_mode_get_state(asus); +- break; +- } +- ++ asus_wmi_tablet_mode_get_state(asus); + return 0; + } + +@@ -2932,18 +2895,7 @@ static int asus_hotk_restore(struct device *device) + if (asus_wmi_has_fnlock_key(asus)) + asus_wmi_fnlock_update(asus); + +- switch (asus->driver->quirks->tablet_switch_mode) { +- case asus_wmi_no_tablet_switch: +- case asus_wmi_kbd_dock_devid: +- break; +- case asus_wmi_lid_flip_devid: +- lid_flip_tablet_mode_get_state(asus); +- break; +- case asus_wmi_lid_flip_rog_devid: +- lid_flip_rog_tablet_mode_get_state(asus); +- break; +- } +- ++ asus_wmi_tablet_mode_get_state(asus); + return 0; + } + +-- +2.42.0 + diff --git a/queue-5.10/platform-x86-asus-wmi-simplify-tablet-mode-switch-pr.patch b/queue-5.10/platform-x86-asus-wmi-simplify-tablet-mode-switch-pr.patch new file mode 100644 index 00000000000..621d1a5830e --- /dev/null +++ b/queue-5.10/platform-x86-asus-wmi-simplify-tablet-mode-switch-pr.patch @@ -0,0 +1,107 @@ +From 3da0d35ae4ebee993714461e6e83613c65c7f1f4 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 24 Aug 2022 17:11:44 +0200 +Subject: platform/x86: asus-wmi: Simplify tablet-mode-switch probing + +From: Hans de Goede + +[ Upstream commit c98dc61ee08f833e68337700546e120e2edac7c9 ] + +The 3 different tablet-mode-switch initialization paths repeat a lot +of the same code. Add a helper function for this. + +This also makes the error-handling for the kbd_dock_devid case consistent +with the other 2 cases. + +Cc: Luke D. Jones +Signed-off-by: Hans de Goede +Link: https://lore.kernel.org/r/20220824151145.1448010-1-hdegoede@redhat.com +Stable-dep-of: b52cbca22cbf ("platform/x86: asus-wmi: Move i8042 filter install to shared asus-wmi code") +Signed-off-by: Sasha Levin +--- + drivers/platform/x86/asus-wmi.c | 55 +++++++++++++-------------------- + 1 file changed, 22 insertions(+), 33 deletions(-) + +diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c +index 31f5e4df43910..a1a6e48d0c04e 100644 +--- a/drivers/platform/x86/asus-wmi.c ++++ b/drivers/platform/x86/asus-wmi.c +@@ -351,13 +351,28 @@ static bool asus_wmi_dev_is_present(struct asus_wmi *asus, u32 dev_id) + } + + /* Input **********************************************************************/ ++static void asus_wmi_tablet_sw_init(struct asus_wmi *asus, u32 dev_id, int event_code) ++{ ++ struct device *dev = &asus->platform_device->dev; ++ int result; ++ ++ result = asus_wmi_get_devstate_simple(asus, dev_id); ++ if (result < 0) ++ asus->driver->quirks->tablet_switch_mode = asus_wmi_no_tablet_switch; ++ if (result >= 0) { ++ input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE); ++ input_report_switch(asus->inputdev, SW_TABLET_MODE, result); ++ } else if (result == -ENODEV) { ++ dev_err(dev, "This device has tablet-mode-switch quirk but got ENODEV checking it. This is a bug."); ++ } else { ++ dev_err(dev, "Error checking for tablet-mode-switch: %d\n", result); ++ } ++} + + static int asus_wmi_input_init(struct asus_wmi *asus) + { +- struct device *dev; +- int err, result; +- +- dev = &asus->platform_device->dev; ++ struct device *dev = &asus->platform_device->dev; ++ int err; + + asus->inputdev = input_allocate_device(); + if (!asus->inputdev) +@@ -377,39 +392,13 @@ static int asus_wmi_input_init(struct asus_wmi *asus) + case asus_wmi_no_tablet_switch: + break; + case asus_wmi_kbd_dock_devid: +- result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_KBD_DOCK); +- if (result >= 0) { +- input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE); +- input_report_switch(asus->inputdev, SW_TABLET_MODE, !result); +- } else if (result != -ENODEV) { +- dev_err(dev, "Error checking for keyboard-dock: %d\n", result); +- } ++ asus_wmi_tablet_sw_init(asus, ASUS_WMI_DEVID_KBD_DOCK, NOTIFY_KBD_DOCK_CHANGE); + break; + case asus_wmi_lid_flip_devid: +- result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP); +- if (result < 0) +- asus->driver->quirks->tablet_switch_mode = asus_wmi_no_tablet_switch; +- if (result >= 0) { +- input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE); +- input_report_switch(asus->inputdev, SW_TABLET_MODE, result); +- } else if (result == -ENODEV) { +- dev_err(dev, "This device has lid_flip quirk but got ENODEV checking it. This is a bug."); +- } else { +- dev_err(dev, "Error checking for lid-flip: %d\n", result); +- } ++ asus_wmi_tablet_sw_init(asus, ASUS_WMI_DEVID_LID_FLIP, NOTIFY_LID_FLIP); + break; + case asus_wmi_lid_flip_rog_devid: +- result = asus_wmi_get_devstate_simple(asus, ASUS_WMI_DEVID_LID_FLIP_ROG); +- if (result < 0) +- asus->driver->quirks->tablet_switch_mode = asus_wmi_no_tablet_switch; +- if (result >= 0) { +- input_set_capability(asus->inputdev, EV_SW, SW_TABLET_MODE); +- input_report_switch(asus->inputdev, SW_TABLET_MODE, result); +- } else if (result == -ENODEV) { +- dev_err(dev, "This device has lid-flip-rog quirk but got ENODEV checking it. This is a bug."); +- } else { +- dev_err(dev, "Error checking for lid-flip: %d\n", result); +- } ++ asus_wmi_tablet_sw_init(asus, ASUS_WMI_DEVID_LID_FLIP_ROG, NOTIFY_LID_FLIP_ROG); + break; + } + +-- +2.42.0 + diff --git a/queue-5.10/series b/queue-5.10/series index 5958c9813a7..d059bd616e7 100644 --- a/queue-5.10/series +++ b/queue-5.10/series @@ -5,3 +5,31 @@ tg3-move-the-rt-x_dropped-counters-to-tg3_napi.patch tg3-increment-tx_dropped-in-tg3_tso_bug.patch kconfig-fix-memory-leak-from-range-properties.patch drm-amdgpu-correct-chunk_ptr-to-a-pointer-to-chunk.patch +platform-x86-asus-wmi-add-support-for-sw_tablet_mode.patch +platform-x86-asus-nb-wmi-allow-configuring-sw_tablet.patch +platform-x86-asus-nb-wmi-add-tablet_mode_sw-lid-flip.patch +asus-wmi-add-dgpu-disable-method.patch +platform-x86-asus-wmi-adjust-tablet-lidflip-handling.patch +platform-x86-asus-wmi-add-support-for-rog-x13-tablet.patch +platform-x86-asus-wmi-simplify-tablet-mode-switch-pr.patch +platform-x86-asus-wmi-simplify-tablet-mode-switch-ha.patch +platform-x86-asus-wmi-move-i8042-filter-install-to-s.patch +of-base-fix-some-formatting-issues-and-provide-missi.patch +of-fix-kerneldoc-output-formatting.patch +of-add-missing-return-section-in-kerneldoc-comments.patch +of-dynamic-fix-of_reconfig_get_state_change-return-v.patch +ipv6-fix-potential-null-deref-in-fib6_add.patch +octeontx2-pf-add-missing-mutex-lock-in-otx2_get_paus.patch +hv_netvsc-rndis_filter-needs-to-select-nls.patch +mlxbf-bootctl-correctly-identify-secure-boot-with-de.patch +net-arcnet-com20020-fix-error-handling.patch +arcnet-restoring-support-for-multiple-sohard-arcnet-.patch +i40e-fix-unexpected-mfs-warning-message.patch +net-bnxt-fix-a-potential-use-after-free-in-bnxt_init.patch +ionic-fix-snprintf-format-length-warning.patch +ionic-fix-dim-work-handling-in-split-interrupt-mode.patch +ipv4-ip_gre-avoid-skb_pull-failure-in-ipgre_xmit.patch +net-hns-fix-fake-link-up-on-xge-port.patch +netfilter-xt_owner-fix-for-unsafe-access-of-sk-sk_so.patch +tcp-do-not-accept-ack-of-bytes-we-never-sent.patch +bpf-sockmap-updating-the-sg-structure-should-also-up.patch diff --git a/queue-5.10/tcp-do-not-accept-ack-of-bytes-we-never-sent.patch b/queue-5.10/tcp-do-not-accept-ack-of-bytes-we-never-sent.patch new file mode 100644 index 00000000000..73950b0ca2e --- /dev/null +++ b/queue-5.10/tcp-do-not-accept-ack-of-bytes-we-never-sent.patch @@ -0,0 +1,106 @@ +From c02ab8ad87ca013e42f5cff7d33dcaa99e472539 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 5 Dec 2023 16:18:41 +0000 +Subject: tcp: do not accept ACK of bytes we never sent + +From: Eric Dumazet + +[ Upstream commit 3d501dd326fb1c73f1b8206d4c6e1d7b15c07e27 ] + +This patch is based on a detailed report and ideas from Yepeng Pan +and Christian Rossow. + +ACK seq validation is currently following RFC 5961 5.2 guidelines: + + The ACK value is considered acceptable only if + it is in the range of ((SND.UNA - MAX.SND.WND) <= SEG.ACK <= + SND.NXT). All incoming segments whose ACK value doesn't satisfy the + above condition MUST be discarded and an ACK sent back. It needs to + be noted that RFC 793 on page 72 (fifth check) says: "If the ACK is a + duplicate (SEG.ACK < SND.UNA), it can be ignored. If the ACK + acknowledges something not yet sent (SEG.ACK > SND.NXT) then send an + ACK, drop the segment, and return". The "ignored" above implies that + the processing of the incoming data segment continues, which means + the ACK value is treated as acceptable. This mitigation makes the + ACK check more stringent since any ACK < SND.UNA wouldn't be + accepted, instead only ACKs that are in the range ((SND.UNA - + MAX.SND.WND) <= SEG.ACK <= SND.NXT) get through. + +This can be refined for new (and possibly spoofed) flows, +by not accepting ACK for bytes that were never sent. + +This greatly improves TCP security at a little cost. + +I added a Fixes: tag to make sure this patch will reach stable trees, +even if the 'blamed' patch was adhering to the RFC. + +tp->bytes_acked was added in linux-4.2 + +Following packetdrill test (courtesy of Yepeng Pan) shows +the issue at hand: + +0 socket(..., SOCK_STREAM, IPPROTO_TCP) = 3 ++0 setsockopt(3, SOL_SOCKET, SO_REUSEADDR, [1], 4) = 0 ++0 bind(3, ..., ...) = 0 ++0 listen(3, 1024) = 0 + +// ---------------- Handshake ------------------- // + +// when window scale is set to 14 the window size can be extended to +// 65535 * (2^14) = 1073725440. Linux would accept an ACK packet +// with ack number in (Server_ISN+1-1073725440. Server_ISN+1) +// ,though this ack number acknowledges some data never +// sent by the server. + ++0 < S 0:0(0) win 65535 ++0 > S. 0:0(0) ack 1 <...> ++0 < . 1:1(0) ack 1 win 65535 ++0 accept(3, ..., ...) = 4 + +// For the established connection, we send an ACK packet, +// the ack packet uses ack number 1 - 1073725300 + 2^32, +// where 2^32 is used to wrap around. +// Note: we used 1073725300 instead of 1073725440 to avoid possible +// edge cases. +// 1 - 1073725300 + 2^32 = 3221241997 + +// Oops, old kernels happily accept this packet. ++0 < . 1:1001(1000) ack 3221241997 win 65535 + +// After the kernel fix the following will be replaced by a challenge ACK, +// and prior malicious frame would be dropped. ++0 > . 1:1(0) ack 1001 + +Fixes: 354e4aa391ed ("tcp: RFC 5961 5.2 Blind Data Injection Attack Mitigation") +Signed-off-by: Eric Dumazet +Reported-by: Yepeng Pan +Reported-by: Christian Rossow +Acked-by: Neal Cardwell +Link: https://lore.kernel.org/r/20231205161841.2702925-1-edumazet@google.com +Signed-off-by: Jakub Kicinski +Signed-off-by: Sasha Levin +--- + net/ipv4/tcp_input.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c +index a8948c76d19b6..0f9fe5edad142 100644 +--- a/net/ipv4/tcp_input.c ++++ b/net/ipv4/tcp_input.c +@@ -3772,8 +3772,12 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag) + * then we can probably ignore it. + */ + if (before(ack, prior_snd_una)) { ++ u32 max_window; ++ ++ /* do not accept ACK for bytes we never sent. */ ++ max_window = min_t(u64, tp->max_window, tp->bytes_acked); + /* RFC 5961 5.2 [Blind Data Injection Attack].[Mitigation] */ +- if (before(ack, prior_snd_una - tp->max_window)) { ++ if (before(ack, prior_snd_una - max_window)) { + if (!(flag & FLAG_NO_CHALLENGE_ACK)) + tcp_send_challenge_ack(sk, skb); + return -1; +-- +2.42.0 + -- 2.47.3