]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Sat, 9 Dec 2023 02:36:58 +0000 (21:36 -0500)
committerSasha Levin <sashal@kernel.org>
Sat, 9 Dec 2023 02:36:58 +0000 (21:36 -0500)
Signed-off-by: Sasha Levin <sashal@kernel.org>
29 files changed:
queue-5.10/arcnet-restoring-support-for-multiple-sohard-arcnet-.patch [new file with mode: 0644]
queue-5.10/asus-wmi-add-dgpu-disable-method.patch [new file with mode: 0644]
queue-5.10/bpf-sockmap-updating-the-sg-structure-should-also-up.patch [new file with mode: 0644]
queue-5.10/hv_netvsc-rndis_filter-needs-to-select-nls.patch [new file with mode: 0644]
queue-5.10/i40e-fix-unexpected-mfs-warning-message.patch [new file with mode: 0644]
queue-5.10/ionic-fix-dim-work-handling-in-split-interrupt-mode.patch [new file with mode: 0644]
queue-5.10/ionic-fix-snprintf-format-length-warning.patch [new file with mode: 0644]
queue-5.10/ipv4-ip_gre-avoid-skb_pull-failure-in-ipgre_xmit.patch [new file with mode: 0644]
queue-5.10/ipv6-fix-potential-null-deref-in-fib6_add.patch [new file with mode: 0644]
queue-5.10/mlxbf-bootctl-correctly-identify-secure-boot-with-de.patch [new file with mode: 0644]
queue-5.10/net-arcnet-com20020-fix-error-handling.patch [new file with mode: 0644]
queue-5.10/net-bnxt-fix-a-potential-use-after-free-in-bnxt_init.patch [new file with mode: 0644]
queue-5.10/net-hns-fix-fake-link-up-on-xge-port.patch [new file with mode: 0644]
queue-5.10/netfilter-xt_owner-fix-for-unsafe-access-of-sk-sk_so.patch [new file with mode: 0644]
queue-5.10/octeontx2-pf-add-missing-mutex-lock-in-otx2_get_paus.patch [new file with mode: 0644]
queue-5.10/of-add-missing-return-section-in-kerneldoc-comments.patch [new file with mode: 0644]
queue-5.10/of-base-fix-some-formatting-issues-and-provide-missi.patch [new file with mode: 0644]
queue-5.10/of-dynamic-fix-of_reconfig_get_state_change-return-v.patch [new file with mode: 0644]
queue-5.10/of-fix-kerneldoc-output-formatting.patch [new file with mode: 0644]
queue-5.10/platform-x86-asus-nb-wmi-add-tablet_mode_sw-lid-flip.patch [new file with mode: 0644]
queue-5.10/platform-x86-asus-nb-wmi-allow-configuring-sw_tablet.patch [new file with mode: 0644]
queue-5.10/platform-x86-asus-wmi-add-support-for-rog-x13-tablet.patch [new file with mode: 0644]
queue-5.10/platform-x86-asus-wmi-add-support-for-sw_tablet_mode.patch [new file with mode: 0644]
queue-5.10/platform-x86-asus-wmi-adjust-tablet-lidflip-handling.patch [new file with mode: 0644]
queue-5.10/platform-x86-asus-wmi-move-i8042-filter-install-to-s.patch [new file with mode: 0644]
queue-5.10/platform-x86-asus-wmi-simplify-tablet-mode-switch-ha.patch [new file with mode: 0644]
queue-5.10/platform-x86-asus-wmi-simplify-tablet-mode-switch-pr.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/tcp-do-not-accept-ack-of-bytes-we-never-sent.patch [new file with mode: 0644]

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 (file)
index 0000000..b765f7c
--- /dev/null
@@ -0,0 +1,216 @@
+From d41f4df0cef7063e80a9233e82cf0cd5eadfe6ed Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 30 Nov 2023 12:35:03 +0100
+Subject: arcnet: restoring support for multiple Sohard Arcnet cards
+
+From: Thomas Reichinger <thomas.reichinger@sohard.de>
+
+[ 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 <thomas.reichinger@sohard.de>
+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 <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..28d41ec
--- /dev/null
@@ -0,0 +1,190 @@
+From fb1ba48f2fdac56eac87a200bba0ed9ddc3caf1d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 7 Aug 2021 14:36:55 +1200
+Subject: asus-wmi: Add dgpu disable method
+
+From: Luke D. Jones <luke@ljones.dev>
+
+[ 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 <luke@ljones.dev>
+Link: https://lore.kernel.org/r/20210807023656.25020-3-luke@ljones.dev
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <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 <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..06c4b13
--- /dev/null
@@ -0,0 +1,74 @@
+From 14794c422d775191580d14076b76737302da3e9f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 6 Dec 2023 15:27:06 -0800
+Subject: bpf: sockmap, updating the sg structure should also update curr
+
+From: John Fastabend <john.fastabend@gmail.com>
+
+[ 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 <john.fastabend@gmail.com>
+Link: https://lore.kernel.org/r/20231206232706.374377-3-john.fastabend@gmail.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..0f7f5b2
--- /dev/null
@@ -0,0 +1,44 @@
+From 33867301e25a2a0e8d72211007b40eeb6b711c74 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Nov 2023 21:58:53 -0800
+Subject: hv_netvsc: rndis_filter needs to select NLS
+
+From: Randy Dunlap <rdunlap@infradead.org>
+
+[ 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 <rdunlap@infradead.org>
+Cc: Haiyang Zhang <haiyangz@microsoft.com>
+Cc: K. Y. Srinivasan <kys@microsoft.com>
+Cc: Wei Liu <wei.liu@kernel.org>
+Cc: Dexuan Cui <decui@microsoft.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Tested-by: Simon Horman <horms@kernel.org> # build-tested
+Reviewed-by: Michael Kelley <mikelley@microsoft.com>
+Link: https://lore.kernel.org/r/20231130055853.19069-1-rdunlap@infradead.org
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..2b4cc42
--- /dev/null
@@ -0,0 +1,58 @@
+From aaa90ee5797e1a4aa7e793fe7218bd7ba9cfe05d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Nov 2023 09:12:09 +0100
+Subject: i40e: Fix unexpected MFS warning message
+
+From: Ivan Vecera <ivecera@redhat.com>
+
+[ 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:
+
+<code>
+...
+/* 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;
+                }
+        }
+...
+</code>
+
+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 <ivecera@redhat.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..5097333
--- /dev/null
@@ -0,0 +1,67 @@
+From 9a70f5a7463e07ef1a04f593e820750cbc553dd0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Dec 2023 11:22:34 -0800
+Subject: ionic: Fix dim work handling in split interrupt mode
+
+From: Brett Creeley <brett.creeley@amd.com>
+
+[ 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 <brett.creeley@amd.com>
+Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Link: https://lore.kernel.org/r/20231204192234.21017-3-shannon.nelson@amd.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..c66b0eb
--- /dev/null
@@ -0,0 +1,45 @@
+From 195a0444bd1456b551b385dfc24ab1381c76792b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Dec 2023 11:22:33 -0800
+Subject: ionic: fix snprintf format length warning
+
+From: Shannon Nelson <shannon.nelson@amd.com>
+
+[ 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 <lkp@intel.com>
+Closes: https://lore.kernel.org/oe-kbuild-all/202311300201.lO8v7mKU-lkp@intel.com/
+Signed-off-by: Shannon Nelson <shannon.nelson@amd.com>
+Reviewed-by: Brett Creeley <brett.creeley@amd.com>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Link: https://lore.kernel.org/r/20231204192234.21017-2-shannon.nelson@amd.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..93891f9
--- /dev/null
@@ -0,0 +1,58 @@
+From 34b09521fa1acff61ca73ac415f438c78c04eb19 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 3 Dec 2023 01:14:41 +0900
+Subject: ipv4: ip_gre: Avoid skb_pull() failure in ipgre_xmit()
+
+From: Shigeru Yoshida <syoshida@redhat.com>
+
+[ 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 <syoshida@redhat.com>
+Reviewed-by: Eric Dumazet <edumazet@google.com>
+Reviewed-by: Suman Ghosh <sumang@marvell.com>
+Link: https://lore.kernel.org/r/20231202161441.221135-1-syoshida@redhat.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..0e1ab89
--- /dev/null
@@ -0,0 +1,79 @@
+From 57b0c5ae6b6436c20335dce44e8a7600013a1745 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Nov 2023 16:06:30 +0000
+Subject: ipv6: fix potential NULL deref in fib6_add()
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ 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:
+<TASK>
+__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 <syzkaller@googlegroups.com>
+Signed-off-by: Eric Dumazet <edumazet@google.com>
+Cc: Wei Wang <weiwan@google.com>
+Reviewed-by: David Ahern <dsahern@kernel.org>
+Link: https://lore.kernel.org/r/20231129160630.3509216-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..f49e5bd
--- /dev/null
@@ -0,0 +1,120 @@
+From 656cb56fa56f40b920d27691a827c9207f954d16 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <davthompson@nvidia.com>
+
+[ 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 <kblaiech@nvidia.com>
+Signed-off-by: David Thompson <davthompson@nvidia.com>
+Link: https://lore.kernel.org/r/20231130183515.17214-1-davthompson@nvidia.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..5a381ac
--- /dev/null
@@ -0,0 +1,137 @@
+From 7ac1392bf27e4b114f4b2aeb9afc211074217c89 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 14 Mar 2021 14:08:36 -0400
+Subject: net: arcnet: com20020 fix error handling
+
+From: Tong Zhang <ztong0001@gmail.com>
+
+[ 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 <ztong0001@gmail.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Stable-dep-of: 6b17a597fc2f ("arcnet: restoring support for multiple Sohard Arcnet cards")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..b2bc1b3
--- /dev/null
@@ -0,0 +1,43 @@
+From 2a2737c9ba0d57c9bdc836e05d593576a45bba16 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <dinghao.liu@zju.edu.cn>
+
+[ 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 <dinghao.liu@zju.edu.cn>
+Reviewed-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
+Reviewed-by: Michael Chan <michael.chan@broadcom.com>
+Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
+Link: https://lore.kernel.org/r/20231204024004.8245-1-dinghao.liu@zju.edu.cn
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..7199b0d
--- /dev/null
@@ -0,0 +1,74 @@
+From 0f23f9c8b8faf8fe6371a06658cf7204ba0d197e Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 4 Dec 2023 22:32:32 +0800
+Subject: net: hns: fix fake link up on xge port
+
+From: Yonglong Liu <liuyonglong@huawei.com>
+
+[ 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 <liuyonglong@huawei.com>
+Signed-off-by: Jijie Shao <shaojijie@huawei.com>
+Reviewed-by: Wojciech Drewek <wojciech.drewek@intel.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../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 (file)
index 0000000..c0b2a30
--- /dev/null
@@ -0,0 +1,71 @@
+From fe7a436f8b59817030b24894b7cbfe306215dbfa Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Dec 2023 21:58:12 +0100
+Subject: netfilter: xt_owner: Fix for unsafe access of sk->sk_socket
+
+From: Phil Sutter <phil@nwl.cc>
+
+[ 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 <jannh@google.com>
+Signed-off-by: Phil Sutter <phil@nwl.cc>
+Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..45bb191
--- /dev/null
@@ -0,0 +1,51 @@
+From 353541f31e263ebd801002267af1f98ec455f3a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 29 Nov 2023 10:53:42 +0530
+Subject: octeontx2-pf: Add missing mutex lock in otx2_get_pauseparam
+
+From: Subbaraya Sundeep <sbhatta@marvell.com>
+
+[ 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 <sbhatta@marvell.com>
+Reviewed-by: Simon Horman <horms@kernel.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..128750f
--- /dev/null
@@ -0,0 +1,812 @@
+From 782a5cefddcf6cc56620d49cc1d8fb7f0f95786f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 25 Mar 2021 10:47:12 -0600
+Subject: of: Add missing 'Return' section in kerneldoc comments
+
+From: Rob Herring <robh@kernel.org>
+
+[ 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 <frowand.list@gmail.com>
+Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
+Signed-off-by: Rob Herring <robh@kernel.org>
+Reviewed-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+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 <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..c7a5804
--- /dev/null
@@ -0,0 +1,105 @@
+From 9db6e8c448984560af2124ce19a3d8cc9c542779 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 18 Mar 2021 10:40:30 +0000
+Subject: of: base: Fix some formatting issues and provide missing descriptions
+
+From: Lee Jones <lee.jones@linaro.org>
+
+[ 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 <robh+dt@kernel.org>
+Cc: Frank Rowand <frowand.list@gmail.com>
+Cc: "David S. Miller" <davem@davemloft.net>
+Cc: devicetree@vger.kernel.org
+Signed-off-by: Lee Jones <lee.jones@linaro.org>
+Signed-off-by: Rob Herring <robh@kernel.org>
+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 <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..e8fb4dd
--- /dev/null
@@ -0,0 +1,41 @@
+From 942200d505a9419ce353162fb3eae44bc0042493 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Nov 2023 15:47:18 +0100
+Subject: of: dynamic: Fix of_reconfig_get_state_change() return value
+ documentation
+
+From: Luca Ceresoli <luca.ceresoli@bootlin.com>
+
+[ 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 <luca.ceresoli@bootlin.com>
+Link: https://lore.kernel.org/r/20231123-fix-of_reconfig_get_state_change-docs-v1-1-f51892050ff9@bootlin.com
+Signed-off-by: Rob Herring <robh@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..bd3b299
--- /dev/null
@@ -0,0 +1,500 @@
+From 485b48c016bf70d57e00198c49f00122e1506ba6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 26 Mar 2021 13:26:06 -0600
+Subject: of: Fix kerneldoc output formatting
+
+From: Rob Herring <robh@kernel.org>
+
+[ 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 <frowand.list@gmail.com>
+Cc: Mauro Carvalho Chehab <mchehab@kernel.org>
+Signed-off-by: Rob Herring <robh@kernel.org>
+Reviewed-by: Mauro Carvalho Chehab <mchehab+huawei@kernel.org>
+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 <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..d44cc33
--- /dev/null
@@ -0,0 +1,46 @@
+From 83ecbc3856cb907c6f27bb642043fe5a18464cb1 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <hdegoede@redhat.com>
+
+[ 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 <hdegoede@redhat.com>
+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 <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..2a71c0e
--- /dev/null
@@ -0,0 +1,66 @@
+From 1972321e546ffae692bde4e402c6fe1b5f886b96 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <hdegoede@redhat.com>
+
+[ 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 <hdegoede@redhat.com>
+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 <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..313bfda
--- /dev/null
@@ -0,0 +1,175 @@
+From f5afacf02111af97232f2a51504ed2174d6c0639 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <luke@ljones.dev>
+
+[ 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 <luke@ljones.dev>
+Link: https://lore.kernel.org/r/20220813092753.6635-2-luke@ljones.dev
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <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 <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..f279d3d
--- /dev/null
@@ -0,0 +1,192 @@
+From db65ce9a7defab254150d415855def1aeae46d33 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <samuel@cavoj.net>
+
+[ 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 <samuel@cavoj.net>
+Cc: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20201020220944.1075530-1-samuel@cavoj.net
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <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 <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..b084581
--- /dev/null
@@ -0,0 +1,220 @@
+From 143436933c6f5239d89856c1af6fd2cb2ef5f983 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <luke@ljones.dev>
+
+[ 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 <luke@ljones.dev>
+Link: https://lore.kernel.org/r/20220813092753.6635-1-luke@ljones.dev
+Reviewed-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Hans de Goede <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 <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..71c2883
--- /dev/null
@@ -0,0 +1,111 @@
+From d9d643652071f6e506b9a24f9abf656056891628 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+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 <hdegoede@redhat.com>
+
+[ 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 <linux@rempel-privat.de>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Link: https://lore.kernel.org/r/20231120154235.610808-2-hdegoede@redhat.com
+Reviewed-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..43eb551
--- /dev/null
@@ -0,0 +1,192 @@
+From 13cecc503fe3ce962912b5d3dc61b4adebbf7adc Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Aug 2022 17:11:45 +0200
+Subject: platform/x86: asus-wmi: Simplify tablet-mode-switch handling
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ 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 <luke@ljones.dev>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+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 <sashal@kernel.org>
+---
+ 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 (file)
index 0000000..621d1a5
--- /dev/null
@@ -0,0 +1,107 @@
+From 3da0d35ae4ebee993714461e6e83613c65c7f1f4 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 24 Aug 2022 17:11:44 +0200
+Subject: platform/x86: asus-wmi: Simplify tablet-mode-switch probing
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+[ 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 <luke@ljones.dev>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+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 <sashal@kernel.org>
+---
+ 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
+
index 5958c9813a766d45f1b50741219cec5c27d2706a..d059bd616e7f129350f5368c810e645868895610 100644 (file)
@@ -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 (file)
index 0000000..73950b0
--- /dev/null
@@ -0,0 +1,106 @@
+From c02ab8ad87ca013e42f5cff7d33dcaa99e472539 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 5 Dec 2023 16:18:41 +0000
+Subject: tcp: do not accept ACK of bytes we never sent
+
+From: Eric Dumazet <edumazet@google.com>
+
+[ 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 <mss 1400,nop,wscale 14>
++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 <edumazet@google.com>
+Reported-by: Yepeng Pan <yepeng.pan@cispa.de>
+Reported-by: Christian Rossow <rossow@cispa.de>
+Acked-by: Neal Cardwell <ncardwell@google.com>
+Link: https://lore.kernel.org/r/20231205161841.2702925-1-edumazet@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ 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
+