]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 6.3
authorSasha Levin <sashal@kernel.org>
Thu, 25 May 2023 14:38:15 +0000 (10:38 -0400)
committerSasha Levin <sashal@kernel.org>
Thu, 25 May 2023 14:38:15 +0000 (10:38 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
queue-6.3/series [new file with mode: 0644]
queue-6.3/tpm-prevent-hwrng-from-activating-during-resume.patch [new file with mode: 0644]
queue-6.3/tpm-re-enable-tpm-chip-boostrapping-non-tpm_tis-tpm-.patch [new file with mode: 0644]
queue-6.3/tpm-tpm_tis-avoid-cache-incoherency-in-test-for-inte.patch [new file with mode: 0644]
queue-6.3/tpm-tpm_tis-only-handle-supported-interrupts.patch [new file with mode: 0644]
queue-6.3/tpm-tpm_tis-startup-chip-before-testing-for-interrup.patch [new file with mode: 0644]
queue-6.3/tpm_tis-use-tpm_chip_-start-stop-decoration-inside-t.patch [new file with mode: 0644]
queue-6.3/usb-dwc3-fix-gadget-mode-suspend-interrupt-handler-i.patch [new file with mode: 0644]
queue-6.3/wifi-rtw89-8852b-adjust-quota-to-avoid-ser-l1-caused.patch [new file with mode: 0644]
queue-6.3/zsmalloc-move-lru-update-from-zs_map_object-to-zs_ma.patch [new file with mode: 0644]

diff --git a/queue-6.3/series b/queue-6.3/series
new file mode 100644 (file)
index 0000000..f69a140
--- /dev/null
@@ -0,0 +1,9 @@
+wifi-rtw89-8852b-adjust-quota-to-avoid-ser-l1-caused.patch
+usb-dwc3-fix-gadget-mode-suspend-interrupt-handler-i.patch
+tpm-tpm_tis-avoid-cache-incoherency-in-test-for-inte.patch
+tpm-tpm_tis-only-handle-supported-interrupts.patch
+tpm_tis-use-tpm_chip_-start-stop-decoration-inside-t.patch
+tpm-tpm_tis-startup-chip-before-testing-for-interrup.patch
+tpm-re-enable-tpm-chip-boostrapping-non-tpm_tis-tpm-.patch
+tpm-prevent-hwrng-from-activating-during-resume.patch
+zsmalloc-move-lru-update-from-zs_map_object-to-zs_ma.patch
diff --git a/queue-6.3/tpm-prevent-hwrng-from-activating-during-resume.patch b/queue-6.3/tpm-prevent-hwrng-from-activating-during-resume.patch
new file mode 100644 (file)
index 0000000..7cc98a7
--- /dev/null
@@ -0,0 +1,82 @@
+From de5046897a02437941da794b1fc27e7059f7aa16 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Apr 2023 20:29:28 +0300
+Subject: tpm: Prevent hwrng from activating during resume
+
+From: Jarkko Sakkinen <jarkko@kernel.org>
+
+[ Upstream commit 99d46450625590d410f86fe4660a5eff7d3b8343 ]
+
+Set TPM_CHIP_FLAG_SUSPENDED in tpm_pm_suspend() and reset in
+tpm_pm_resume(). While the flag is set, tpm_hwrng() gives back zero
+bytes. This prevents hwrng from racing during resume.
+
+Cc: stable@vger.kernel.org
+Fixes: 6e592a065d51 ("tpm: Move Linux RNG connection to hwrng")
+Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/tpm/tpm-chip.c      |  4 ++++
+ drivers/char/tpm/tpm-interface.c | 10 ++++++++++
+ include/linux/tpm.h              |  1 +
+ 3 files changed, 15 insertions(+)
+
+diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
+index 9c0a6aad81140..5be91591cb3b2 100644
+--- a/drivers/char/tpm/tpm-chip.c
++++ b/drivers/char/tpm/tpm-chip.c
+@@ -572,6 +572,10 @@ static int tpm_hwrng_read(struct hwrng *rng, void *data, size_t max, bool wait)
+ {
+       struct tpm_chip *chip = container_of(rng, struct tpm_chip, hwrng);
++      /* Give back zero bytes, as TPM chip has not yet fully resumed: */
++      if (chip->flags & TPM_CHIP_FLAG_SUSPENDED)
++              return 0;
++
+       return tpm_get_random(chip, data, max);
+ }
+diff --git a/drivers/char/tpm/tpm-interface.c b/drivers/char/tpm/tpm-interface.c
+index 7e513b7718320..0f941cb32eb17 100644
+--- a/drivers/char/tpm/tpm-interface.c
++++ b/drivers/char/tpm/tpm-interface.c
+@@ -412,6 +412,8 @@ int tpm_pm_suspend(struct device *dev)
+       }
+ suspended:
++      chip->flags |= TPM_CHIP_FLAG_SUSPENDED;
++
+       if (rc)
+               dev_err(dev, "Ignoring error %d while suspending\n", rc);
+       return 0;
+@@ -429,6 +431,14 @@ int tpm_pm_resume(struct device *dev)
+       if (chip == NULL)
+               return -ENODEV;
++      chip->flags &= ~TPM_CHIP_FLAG_SUSPENDED;
++
++      /*
++       * Guarantee that SUSPENDED is written last, so that hwrng does not
++       * activate before the chip has been fully resumed.
++       */
++      wmb();
++
+       return 0;
+ }
+ EXPORT_SYMBOL_GPL(tpm_pm_resume);
+diff --git a/include/linux/tpm.h b/include/linux/tpm.h
+index 77693389c3f9a..6a1e8f1572551 100644
+--- a/include/linux/tpm.h
++++ b/include/linux/tpm.h
+@@ -282,6 +282,7 @@ enum tpm_chip_flags {
+       TPM_CHIP_FLAG_ALWAYS_POWERED            = BIT(5),
+       TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED    = BIT(6),
+       TPM_CHIP_FLAG_FIRMWARE_UPGRADE          = BIT(7),
++      TPM_CHIP_FLAG_SUSPENDED                 = BIT(8),
+ };
+ #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
+-- 
+2.39.2
+
diff --git a/queue-6.3/tpm-re-enable-tpm-chip-boostrapping-non-tpm_tis-tpm-.patch b/queue-6.3/tpm-re-enable-tpm-chip-boostrapping-non-tpm_tis-tpm-.patch
new file mode 100644 (file)
index 0000000..f031422
--- /dev/null
@@ -0,0 +1,141 @@
+From 083c65c6f80f05b42ee5c34664a80bf979381d75 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Apr 2023 21:49:37 +0300
+Subject: tpm: Re-enable TPM chip boostrapping non-tpm_tis TPM drivers
+
+From: Jarkko Sakkinen <jarkko@kernel.org>
+
+[ Upstream commit 0c8862de05c1a087795ee0a87bf61a6394306cc0 ]
+
+TPM chip bootstrapping was removed from tpm_chip_register(), and it
+was relocated to tpm_tis_core. This breaks all drivers which are not
+based on tpm_tis because the chip will not get properly initialized.
+
+Take the corrective steps:
+1. Rename tpm_chip_startup() as tpm_chip_bootstrap() and make it one-shot.
+2. Call tpm_chip_bootstrap() in tpm_chip_register(), which reverts the
+   things  as tehy used to be.
+
+Cc: Lino Sanfilippo <l.sanfilippo@kunbus.com>
+Fixes: 548eb516ec0f ("tpm, tpm_tis: startup chip before testing for interrupts")
+Reported-by: Pengfei Xu <pengfei.xu@intel.com>
+Link: https://lore.kernel.org/all/ZEjqhwHWBnxcaRV5@xpf.sh.intel.com/
+Tested-by: Pengfei Xu <pengfei.xu@intel.com>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Stable-dep-of: 99d464506255 ("tpm: Prevent hwrng from activating during resume")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/tpm/tpm-chip.c     | 22 +++++++++++++++++++---
+ drivers/char/tpm/tpm.h          |  2 +-
+ drivers/char/tpm/tpm_tis_core.c |  2 +-
+ include/linux/tpm.h             | 13 +++++++------
+ 4 files changed, 28 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
+index 6fdfa65a00c37..9c0a6aad81140 100644
+--- a/drivers/char/tpm/tpm-chip.c
++++ b/drivers/char/tpm/tpm-chip.c
+@@ -606,13 +606,19 @@ static int tpm_get_pcr_allocation(struct tpm_chip *chip)
+ }
+ /*
+- * tpm_chip_startup() - performs auto startup and allocates the PCRs
++ * tpm_chip_bootstrap() - Boostrap TPM chip after power on
+  * @chip: TPM chip to use.
++ *
++ * Initialize TPM chip after power on. This a one-shot function: subsequent
++ * calls will have no effect.
+  */
+-int tpm_chip_startup(struct tpm_chip *chip)
++int tpm_chip_bootstrap(struct tpm_chip *chip)
+ {
+       int rc;
++      if (chip->flags & TPM_CHIP_FLAG_BOOTSTRAPPED)
++              return 0;
++
+       rc = tpm_chip_start(chip);
+       if (rc)
+               return rc;
+@@ -625,9 +631,15 @@ int tpm_chip_startup(struct tpm_chip *chip)
+ stop:
+       tpm_chip_stop(chip);
++      /*
++       * Unconditionally set, as driver initialization should cease, when the
++       * boostrapping process fails.
++       */
++      chip->flags |= TPM_CHIP_FLAG_BOOTSTRAPPED;
++
+       return rc;
+ }
+-EXPORT_SYMBOL_GPL(tpm_chip_startup);
++EXPORT_SYMBOL_GPL(tpm_chip_bootstrap);
+ /*
+  * tpm_chip_register() - create a character device for the TPM chip
+@@ -644,6 +656,10 @@ int tpm_chip_register(struct tpm_chip *chip)
+ {
+       int rc;
++      rc = tpm_chip_bootstrap(chip);
++      if (rc)
++              return rc;
++
+       tpm_sysfs_add_device(chip);
+       tpm_bios_log_setup(chip);
+diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
+index 88d3bd76e0760..f6c99b3f00458 100644
+--- a/drivers/char/tpm/tpm.h
++++ b/drivers/char/tpm/tpm.h
+@@ -263,7 +263,7 @@ static inline void tpm_msleep(unsigned int delay_msec)
+                    delay_msec * 1000);
+ };
+-int tpm_chip_startup(struct tpm_chip *chip);
++int tpm_chip_bootstrap(struct tpm_chip *chip);
+ int tpm_chip_start(struct tpm_chip *chip);
+ void tpm_chip_stop(struct tpm_chip *chip);
+ struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip);
+diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
+index 9f76c9a5aa422..f02b583005a53 100644
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -1125,7 +1125,7 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
+       init_waitqueue_head(&priv->read_queue);
+       init_waitqueue_head(&priv->int_queue);
+-      rc = tpm_chip_startup(chip);
++      rc = tpm_chip_bootstrap(chip);
+       if (rc)
+               goto out_err;
+diff --git a/include/linux/tpm.h b/include/linux/tpm.h
+index 4dc97b9f65fb0..77693389c3f9a 100644
+--- a/include/linux/tpm.h
++++ b/include/linux/tpm.h
+@@ -274,13 +274,14 @@ enum tpm2_cc_attrs {
+ #define TPM_VID_ATML     0x1114
+ enum tpm_chip_flags {
+-      TPM_CHIP_FLAG_TPM2              = BIT(1),
+-      TPM_CHIP_FLAG_IRQ               = BIT(2),
+-      TPM_CHIP_FLAG_VIRTUAL           = BIT(3),
+-      TPM_CHIP_FLAG_HAVE_TIMEOUTS     = BIT(4),
+-      TPM_CHIP_FLAG_ALWAYS_POWERED    = BIT(5),
++      TPM_CHIP_FLAG_BOOTSTRAPPED              = BIT(0),
++      TPM_CHIP_FLAG_TPM2                      = BIT(1),
++      TPM_CHIP_FLAG_IRQ                       = BIT(2),
++      TPM_CHIP_FLAG_VIRTUAL                   = BIT(3),
++      TPM_CHIP_FLAG_HAVE_TIMEOUTS             = BIT(4),
++      TPM_CHIP_FLAG_ALWAYS_POWERED            = BIT(5),
+       TPM_CHIP_FLAG_FIRMWARE_POWER_MANAGED    = BIT(6),
+-      TPM_CHIP_FLAG_FIRMWARE_UPGRADE  = BIT(7),
++      TPM_CHIP_FLAG_FIRMWARE_UPGRADE          = BIT(7),
+ };
+ #define to_tpm_chip(d) container_of(d, struct tpm_chip, dev)
+-- 
+2.39.2
+
diff --git a/queue-6.3/tpm-tpm_tis-avoid-cache-incoherency-in-test-for-inte.patch b/queue-6.3/tpm-tpm_tis-avoid-cache-incoherency-in-test-for-inte.patch
new file mode 100644 (file)
index 0000000..7337981
--- /dev/null
@@ -0,0 +1,157 @@
+From f035c8381e593048a921c503c776672fb183d04b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Nov 2022 14:55:25 +0100
+Subject: tpm, tpm_tis: Avoid cache incoherency in test for interrupts
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lino Sanfilippo <l.sanfilippo@kunbus.com>
+
+[ Upstream commit 858e8b792d06f45c427897bd90205a1d90bf430f ]
+
+The interrupt handler that sets the boolean variable irq_tested may run on
+another CPU as the thread that checks irq_tested as part of the irq test in
+tpm_tis_send().
+
+Since nothing guarantees cache coherency between CPUs for unsynchronized
+accesses to boolean variables the testing thread might not perceive the
+value change done in the interrupt handler.
+
+Avoid this issue by setting the bit TPM_TIS_IRQ_TESTED in the flags field
+of the tpm_tis_data struct and by accessing this field with the bit
+manipulating functions that provide cache coherency.
+
+Also convert all other existing sites to use the proper macros when
+accessing this bitfield.
+
+Signed-off-by: Lino Sanfilippo <l.sanfilippo@kunbus.com>
+Tested-by: Michael Niewöhner <linux@mniewoehner.de>
+Tested-by: Jarkko Sakkinen <jarkko@kernel.org>
+Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Stable-dep-of: 1398aa803f19 ("tpm_tis: Use tpm_chip_{start,stop} decoration inside tpm_tis_resume")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/tpm/tpm_tis.c      |  2 +-
+ drivers/char/tpm/tpm_tis_core.c | 21 +++++++++++----------
+ drivers/char/tpm/tpm_tis_core.h |  2 +-
+ 3 files changed, 13 insertions(+), 12 deletions(-)
+
+diff --git a/drivers/char/tpm/tpm_tis.c b/drivers/char/tpm/tpm_tis.c
+index 4be19d8f3ca95..0d084d6652c41 100644
+--- a/drivers/char/tpm/tpm_tis.c
++++ b/drivers/char/tpm/tpm_tis.c
+@@ -243,7 +243,7 @@ static int tpm_tis_init(struct device *dev, struct tpm_info *tpm_info)
+               irq = tpm_info->irq;
+       if (itpm || is_itpm(ACPI_COMPANION(dev)))
+-              phy->priv.flags |= TPM_TIS_ITPM_WORKAROUND;
++              set_bit(TPM_TIS_ITPM_WORKAROUND, &phy->priv.flags);
+       return tpm_tis_core_init(dev, &phy->priv, irq, &tpm_tcg,
+                                ACPI_HANDLE(dev));
+diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
+index eecfbd7e97867..6b05a84c3a206 100644
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -376,7 +376,7 @@ static int tpm_tis_send_data(struct tpm_chip *chip, const u8 *buf, size_t len)
+       struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+       int rc, status, burstcnt;
+       size_t count = 0;
+-      bool itpm = priv->flags & TPM_TIS_ITPM_WORKAROUND;
++      bool itpm = test_bit(TPM_TIS_ITPM_WORKAROUND, &priv->flags);
+       status = tpm_tis_status(chip);
+       if ((status & TPM_STS_COMMAND_READY) == 0) {
+@@ -509,7 +509,8 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
+       int rc, irq;
+       struct tpm_tis_data *priv = dev_get_drvdata(&chip->dev);
+-      if (!(chip->flags & TPM_CHIP_FLAG_IRQ) || priv->irq_tested)
++      if (!(chip->flags & TPM_CHIP_FLAG_IRQ) ||
++           test_bit(TPM_TIS_IRQ_TESTED, &priv->flags))
+               return tpm_tis_send_main(chip, buf, len);
+       /* Verify receipt of the expected IRQ */
+@@ -519,11 +520,11 @@ static int tpm_tis_send(struct tpm_chip *chip, u8 *buf, size_t len)
+       rc = tpm_tis_send_main(chip, buf, len);
+       priv->irq = irq;
+       chip->flags |= TPM_CHIP_FLAG_IRQ;
+-      if (!priv->irq_tested)
++      if (!test_bit(TPM_TIS_IRQ_TESTED, &priv->flags))
+               tpm_msleep(1);
+-      if (!priv->irq_tested)
++      if (!test_bit(TPM_TIS_IRQ_TESTED, &priv->flags))
+               disable_interrupts(chip);
+-      priv->irq_tested = true;
++      set_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
+       return rc;
+ }
+@@ -666,7 +667,7 @@ static int probe_itpm(struct tpm_chip *chip)
+       size_t len = sizeof(cmd_getticks);
+       u16 vendor;
+-      if (priv->flags & TPM_TIS_ITPM_WORKAROUND)
++      if (test_bit(TPM_TIS_ITPM_WORKAROUND, &priv->flags))
+               return 0;
+       rc = tpm_tis_read16(priv, TPM_DID_VID(0), &vendor);
+@@ -686,13 +687,13 @@ static int probe_itpm(struct tpm_chip *chip)
+       tpm_tis_ready(chip);
+-      priv->flags |= TPM_TIS_ITPM_WORKAROUND;
++      set_bit(TPM_TIS_ITPM_WORKAROUND, &priv->flags);
+       rc = tpm_tis_send_data(chip, cmd_getticks, len);
+       if (rc == 0)
+               dev_info(&chip->dev, "Detected an iTPM.\n");
+       else {
+-              priv->flags &= ~TPM_TIS_ITPM_WORKAROUND;
++              clear_bit(TPM_TIS_ITPM_WORKAROUND, &priv->flags);
+               rc = -EFAULT;
+       }
+@@ -736,7 +737,7 @@ static irqreturn_t tis_int_handler(int dummy, void *dev_id)
+       if (interrupt == 0)
+               return IRQ_NONE;
+-      priv->irq_tested = true;
++      set_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
+       if (interrupt & TPM_INTF_DATA_AVAIL_INT)
+               wake_up_interruptible(&priv->read_queue);
+       if (interrupt & TPM_INTF_LOCALITY_CHANGE_INT)
+@@ -819,7 +820,7 @@ static int tpm_tis_probe_irq_single(struct tpm_chip *chip, u32 intmask,
+       if (rc < 0)
+               goto restore_irqs;
+-      priv->irq_tested = false;
++      clear_bit(TPM_TIS_IRQ_TESTED, &priv->flags);
+       /* Generate an interrupt by having the core call through to
+        * tpm_tis_send
+diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
+index 1d51d5168fb6e..4a58b870b4188 100644
+--- a/drivers/char/tpm/tpm_tis_core.h
++++ b/drivers/char/tpm/tpm_tis_core.h
+@@ -87,6 +87,7 @@ enum tpm_tis_flags {
+       TPM_TIS_ITPM_WORKAROUND         = BIT(0),
+       TPM_TIS_INVALID_STATUS          = BIT(1),
+       TPM_TIS_DEFAULT_CANCELLATION    = BIT(2),
++      TPM_TIS_IRQ_TESTED              = BIT(3),
+ };
+ struct tpm_tis_data {
+@@ -95,7 +96,6 @@ struct tpm_tis_data {
+       unsigned int locality_count;
+       int locality;
+       int irq;
+-      bool irq_tested;
+       unsigned long flags;
+       void __iomem *ilb_base_addr;
+       u16 clkrun_enabled;
+-- 
+2.39.2
+
diff --git a/queue-6.3/tpm-tpm_tis-only-handle-supported-interrupts.patch b/queue-6.3/tpm-tpm_tis-only-handle-supported-interrupts.patch
new file mode 100644 (file)
index 0000000..e9a08f4
--- /dev/null
@@ -0,0 +1,231 @@
+From f8b479fb55f95efdfc06f09f858b22bf7bc9980f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Nov 2022 14:55:30 +0100
+Subject: tpm, tpm_tis: Only handle supported interrupts
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Lino Sanfilippo <l.sanfilippo@kunbus.com>
+
+[ Upstream commit e87fcf0dc2b47fac5b4824f00f74dfbcd4acd363 ]
+
+According to the TPM Interface Specification (TIS) support for "stsValid"
+and "commandReady" interrupts is only optional.
+This has to be taken into account when handling the interrupts in functions
+like wait_for_tpm_stat(). To determine the supported interrupts use the
+capability query.
+
+Also adjust wait_for_tpm_stat() to only wait for interrupt reported status
+changes. After that process all the remaining status changes by polling
+the status register.
+
+Signed-off-by: Lino Sanfilippo <l.sanfilippo@kunbus.com>
+Tested-by: Michael Niewöhner <linux@mniewoehner.de>
+Tested-by: Jarkko Sakkinen <jarkko@kernel.org>
+Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Stable-dep-of: 1398aa803f19 ("tpm_tis: Use tpm_chip_{start,stop} decoration inside tpm_tis_resume")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/tpm/tpm_tis_core.c | 120 +++++++++++++++++++-------------
+ drivers/char/tpm/tpm_tis_core.h |   1 +
+ 2 files changed, 73 insertions(+), 48 deletions(-)
+
+diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
+index 6b05a84c3a206..a35c117ee7c80 100644
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -53,41 +53,63 @@ static int wait_for_tpm_stat(struct tpm_chip *chip, u8 mask,
+       long rc;
+       u8 status;
+       bool canceled = false;
++      u8 sts_mask = 0;
++      int ret = 0;
+       /* check current status */
+       status = chip->ops->status(chip);
+       if ((status & mask) == mask)
+               return 0;
+-      stop = jiffies + timeout;
++      /* check what status changes can be handled by irqs */
++      if (priv->int_mask & TPM_INTF_STS_VALID_INT)
++              sts_mask |= TPM_STS_VALID;
+-      if (chip->flags & TPM_CHIP_FLAG_IRQ) {
++      if (priv->int_mask & TPM_INTF_DATA_AVAIL_INT)
++              sts_mask |= TPM_STS_DATA_AVAIL;
++
++      if (priv->int_mask & TPM_INTF_CMD_READY_INT)
++              sts_mask |= TPM_STS_COMMAND_READY;
++
++      sts_mask &= mask;
++
++      stop = jiffies + timeout;
++      /* process status changes with irq support */
++      if (sts_mask) {
++              ret = -ETIME;
+ again:
+               timeout = stop - jiffies;
+               if ((long)timeout <= 0)
+                       return -ETIME;
+               rc = wait_event_interruptible_timeout(*queue,
+-                      wait_for_tpm_stat_cond(chip, mask, check_cancel,
++                      wait_for_tpm_stat_cond(chip, sts_mask, check_cancel,
+                                              &canceled),
+                       timeout);
+               if (rc > 0) {
+                       if (canceled)
+                               return -ECANCELED;
+-                      return 0;
++                      ret = 0;
+               }
+               if (rc == -ERESTARTSYS && freezing(current)) {
+                       clear_thread_flag(TIF_SIGPENDING);
+                       goto again;
+               }
+-      } else {
+-              do {
+-                      usleep_range(priv->timeout_min,
+-                                   priv->timeout_max);
+-                      status = chip->ops->status(chip);
+-                      if ((status & mask) == mask)
+-                              return 0;
+-              } while (time_before(jiffies, stop));
+       }
++
++      if (ret)
++              return ret;
++
++      mask &= ~sts_mask;
++      if (!mask) /* all done */
++              return 0;
++      /* process status changes without irq support */
++      do {
++              status = chip->ops->status(chip);
++              if ((status & mask) == mask)
++                      return 0;
++              usleep_range(priv->timeout_min,
++                           priv->timeout_max);
++      } while (time_before(jiffies, stop));
+       return -ETIME;
+ }
+@@ -1032,8 +1054,40 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
+       if (rc < 0)
+               goto out_err;
+-      intmask |= TPM_INTF_CMD_READY_INT | TPM_INTF_LOCALITY_CHANGE_INT |
+-                 TPM_INTF_DATA_AVAIL_INT | TPM_INTF_STS_VALID_INT;
++      /* Figure out the capabilities */
++      rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
++      if (rc < 0)
++              goto out_err;
++
++      dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
++              intfcaps);
++      if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
++              dev_dbg(dev, "\tBurst Count Static\n");
++      if (intfcaps & TPM_INTF_CMD_READY_INT) {
++              intmask |= TPM_INTF_CMD_READY_INT;
++              dev_dbg(dev, "\tCommand Ready Int Support\n");
++      }
++      if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
++              dev_dbg(dev, "\tInterrupt Edge Falling\n");
++      if (intfcaps & TPM_INTF_INT_EDGE_RISING)
++              dev_dbg(dev, "\tInterrupt Edge Rising\n");
++      if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
++              dev_dbg(dev, "\tInterrupt Level Low\n");
++      if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
++              dev_dbg(dev, "\tInterrupt Level High\n");
++      if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT) {
++              intmask |= TPM_INTF_LOCALITY_CHANGE_INT;
++              dev_dbg(dev, "\tLocality Change Int Support\n");
++      }
++      if (intfcaps & TPM_INTF_STS_VALID_INT) {
++              intmask |= TPM_INTF_STS_VALID_INT;
++              dev_dbg(dev, "\tSts Valid Int Support\n");
++      }
++      if (intfcaps & TPM_INTF_DATA_AVAIL_INT) {
++              intmask |= TPM_INTF_DATA_AVAIL_INT;
++              dev_dbg(dev, "\tData Avail Int Support\n");
++      }
++
+       intmask &= ~TPM_GLOBAL_INT_ENABLE;
+       rc = tpm_tis_request_locality(chip, 0);
+@@ -1067,32 +1121,6 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
+               goto out_err;
+       }
+-      /* Figure out the capabilities */
+-      rc = tpm_tis_read32(priv, TPM_INTF_CAPS(priv->locality), &intfcaps);
+-      if (rc < 0)
+-              goto out_err;
+-
+-      dev_dbg(dev, "TPM interface capabilities (0x%x):\n",
+-              intfcaps);
+-      if (intfcaps & TPM_INTF_BURST_COUNT_STATIC)
+-              dev_dbg(dev, "\tBurst Count Static\n");
+-      if (intfcaps & TPM_INTF_CMD_READY_INT)
+-              dev_dbg(dev, "\tCommand Ready Int Support\n");
+-      if (intfcaps & TPM_INTF_INT_EDGE_FALLING)
+-              dev_dbg(dev, "\tInterrupt Edge Falling\n");
+-      if (intfcaps & TPM_INTF_INT_EDGE_RISING)
+-              dev_dbg(dev, "\tInterrupt Edge Rising\n");
+-      if (intfcaps & TPM_INTF_INT_LEVEL_LOW)
+-              dev_dbg(dev, "\tInterrupt Level Low\n");
+-      if (intfcaps & TPM_INTF_INT_LEVEL_HIGH)
+-              dev_dbg(dev, "\tInterrupt Level High\n");
+-      if (intfcaps & TPM_INTF_LOCALITY_CHANGE_INT)
+-              dev_dbg(dev, "\tLocality Change Int Support\n");
+-      if (intfcaps & TPM_INTF_STS_VALID_INT)
+-              dev_dbg(dev, "\tSts Valid Int Support\n");
+-      if (intfcaps & TPM_INTF_DATA_AVAIL_INT)
+-              dev_dbg(dev, "\tData Avail Int Support\n");
+-
+       /* INTERRUPT Setup */
+       init_waitqueue_head(&priv->read_queue);
+       init_waitqueue_head(&priv->int_queue);
+@@ -1123,7 +1151,9 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
+               else
+                       tpm_tis_probe_irq(chip, intmask);
+-              if (!(chip->flags & TPM_CHIP_FLAG_IRQ)) {
++              if (chip->flags & TPM_CHIP_FLAG_IRQ) {
++                      priv->int_mask = intmask;
++              } else {
+                       dev_err(&chip->dev, FW_BUG
+                                       "TPM interrupt not working, polling instead\n");
+@@ -1170,13 +1200,7 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
+       if (rc < 0)
+               goto out;
+-      rc = tpm_tis_read32(priv, TPM_INT_ENABLE(priv->locality), &intmask);
+-      if (rc < 0)
+-              goto out;
+-
+-      intmask |= TPM_INTF_CMD_READY_INT
+-          | TPM_INTF_LOCALITY_CHANGE_INT | TPM_INTF_DATA_AVAIL_INT
+-          | TPM_INTF_STS_VALID_INT | TPM_GLOBAL_INT_ENABLE;
++      intmask = priv->int_mask | TPM_GLOBAL_INT_ENABLE;
+       tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
+diff --git a/drivers/char/tpm/tpm_tis_core.h b/drivers/char/tpm/tpm_tis_core.h
+index 4a58b870b4188..e978f457fd4d4 100644
+--- a/drivers/char/tpm/tpm_tis_core.h
++++ b/drivers/char/tpm/tpm_tis_core.h
+@@ -96,6 +96,7 @@ struct tpm_tis_data {
+       unsigned int locality_count;
+       int locality;
+       int irq;
++      unsigned int int_mask;
+       unsigned long flags;
+       void __iomem *ilb_base_addr;
+       u16 clkrun_enabled;
+-- 
+2.39.2
+
diff --git a/queue-6.3/tpm-tpm_tis-startup-chip-before-testing-for-interrup.patch b/queue-6.3/tpm-tpm_tis-startup-chip-before-testing-for-interrup.patch
new file mode 100644 (file)
index 0000000..907d8a0
--- /dev/null
@@ -0,0 +1,117 @@
+From f3f4e16e311a02e7eef98e3a71e813567019a8ff Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 24 Nov 2022 14:55:37 +0100
+Subject: tpm, tpm_tis: startup chip before testing for interrupts
+
+From: Lino Sanfilippo <l.sanfilippo@kunbus.com>
+
+[ Upstream commit 548eb516ec0f7a484a23a902835899341164b8ea ]
+
+In tpm_tis_gen_interrupt() a request for a property value is sent to the
+TPM to test if interrupts are generated. However after a power cycle the
+TPM responds with TPM_RC_INITIALIZE which indicates that the TPM is not
+yet properly initialized.
+Fix this by first starting the TPM up before the request is sent. For this
+the startup implementation is removed from tpm_chip_register() and put
+into the new function tpm_chip_startup() which is called before the
+interrupts are tested.
+
+Signed-off-by: Lino Sanfilippo <l.sanfilippo@kunbus.com>
+Tested-by: Jarkko Sakkinen <jarkko@kernel.org>
+Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Stable-dep-of: 99d464506255 ("tpm: Prevent hwrng from activating during resume")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/tpm/tpm-chip.c     | 38 +++++++++++++++++++++------------
+ drivers/char/tpm/tpm.h          |  1 +
+ drivers/char/tpm/tpm_tis_core.c |  5 +++++
+ 3 files changed, 30 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/char/tpm/tpm-chip.c b/drivers/char/tpm/tpm-chip.c
+index 2a05d8cc0e795..6fdfa65a00c37 100644
+--- a/drivers/char/tpm/tpm-chip.c
++++ b/drivers/char/tpm/tpm-chip.c
+@@ -605,6 +605,30 @@ static int tpm_get_pcr_allocation(struct tpm_chip *chip)
+       return rc;
+ }
++/*
++ * tpm_chip_startup() - performs auto startup and allocates the PCRs
++ * @chip: TPM chip to use.
++ */
++int tpm_chip_startup(struct tpm_chip *chip)
++{
++      int rc;
++
++      rc = tpm_chip_start(chip);
++      if (rc)
++              return rc;
++
++      rc = tpm_auto_startup(chip);
++      if (rc)
++              goto stop;
++
++      rc = tpm_get_pcr_allocation(chip);
++stop:
++      tpm_chip_stop(chip);
++
++      return rc;
++}
++EXPORT_SYMBOL_GPL(tpm_chip_startup);
++
+ /*
+  * tpm_chip_register() - create a character device for the TPM chip
+  * @chip: TPM chip to use.
+@@ -620,20 +644,6 @@ int tpm_chip_register(struct tpm_chip *chip)
+ {
+       int rc;
+-      rc = tpm_chip_start(chip);
+-      if (rc)
+-              return rc;
+-      rc = tpm_auto_startup(chip);
+-      if (rc) {
+-              tpm_chip_stop(chip);
+-              return rc;
+-      }
+-
+-      rc = tpm_get_pcr_allocation(chip);
+-      tpm_chip_stop(chip);
+-      if (rc)
+-              return rc;
+-
+       tpm_sysfs_add_device(chip);
+       tpm_bios_log_setup(chip);
+diff --git a/drivers/char/tpm/tpm.h b/drivers/char/tpm/tpm.h
+index 830014a266090..88d3bd76e0760 100644
+--- a/drivers/char/tpm/tpm.h
++++ b/drivers/char/tpm/tpm.h
+@@ -263,6 +263,7 @@ static inline void tpm_msleep(unsigned int delay_msec)
+                    delay_msec * 1000);
+ };
++int tpm_chip_startup(struct tpm_chip *chip);
+ int tpm_chip_start(struct tpm_chip *chip);
+ void tpm_chip_stop(struct tpm_chip *chip);
+ struct tpm_chip *tpm_find_get_ops(struct tpm_chip *chip);
+diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
+index a5c22fb4ad428..9f76c9a5aa422 100644
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -1124,6 +1124,11 @@ int tpm_tis_core_init(struct device *dev, struct tpm_tis_data *priv, int irq,
+       /* INTERRUPT Setup */
+       init_waitqueue_head(&priv->read_queue);
+       init_waitqueue_head(&priv->int_queue);
++
++      rc = tpm_chip_startup(chip);
++      if (rc)
++              goto out_err;
++
+       if (irq != -1) {
+               /*
+                * Before doing irq testing issue a command to the TPM in polling mode
+-- 
+2.39.2
+
diff --git a/queue-6.3/tpm_tis-use-tpm_chip_-start-stop-decoration-inside-t.patch b/queue-6.3/tpm_tis-use-tpm_chip_-start-stop-decoration-inside-t.patch
new file mode 100644 (file)
index 0000000..84294f9
--- /dev/null
@@ -0,0 +1,110 @@
+From bbf9bb3ea7787de45d6adbab39375b987643c8f3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Apr 2023 20:29:27 +0300
+Subject: tpm_tis: Use tpm_chip_{start,stop} decoration inside tpm_tis_resume
+
+From: Jarkko Sakkinen <jarkko@kernel.org>
+
+[ Upstream commit 1398aa803f198b7a386fdd8404666043e95f4c16 ]
+
+Before sending a TPM command, CLKRUN protocol must be disabled. This is not
+done in the case of tpm1_do_selftest() call site inside tpm_tis_resume().
+
+Address this by decorating the calls with tpm_chip_{start,stop}, which
+should be always used to arm and disarm the TPM chip for transmission.
+
+Finally, move the call to the main TPM driver callback as the last step
+because it should arm the chip by itself, if it needs that type of
+functionality.
+
+Cc: stable@vger.kernel.org
+Reported-by: Jason A. Donenfeld <Jason@zx2c4.com>
+Closes: https://lore.kernel.org/linux-integrity/CS68AWILHXS4.3M36M1EKZLUMS@suppilovahvero/
+Fixes: a3fbfae82b4c ("tpm: take TPM chip power gating out of tpm_transmit()")
+Reviewed-by: Jerry Snitselaar <jsnitsel@redhat.com>
+Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/char/tpm/tpm_tis_core.c | 43 +++++++++++++++------------------
+ 1 file changed, 19 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/char/tpm/tpm_tis_core.c b/drivers/char/tpm/tpm_tis_core.c
+index a35c117ee7c80..a5c22fb4ad428 100644
+--- a/drivers/char/tpm/tpm_tis_core.c
++++ b/drivers/char/tpm/tpm_tis_core.c
+@@ -1190,25 +1190,20 @@ static void tpm_tis_reenable_interrupts(struct tpm_chip *chip)
+       u32 intmask;
+       int rc;
+-      if (chip->ops->clk_enable != NULL)
+-              chip->ops->clk_enable(chip, true);
+-
+-      /* reenable interrupts that device may have lost or
+-       * BIOS/firmware may have disabled
++      /*
++       * Re-enable interrupts that device may have lost or BIOS/firmware may
++       * have disabled.
+        */
+       rc = tpm_tis_write8(priv, TPM_INT_VECTOR(priv->locality), priv->irq);
+-      if (rc < 0)
+-              goto out;
++      if (rc < 0) {
++              dev_err(&chip->dev, "Setting IRQ failed.\n");
++              return;
++      }
+       intmask = priv->int_mask | TPM_GLOBAL_INT_ENABLE;
+-
+-      tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
+-
+-out:
+-      if (chip->ops->clk_enable != NULL)
+-              chip->ops->clk_enable(chip, false);
+-
+-      return;
++      rc = tpm_tis_write32(priv, TPM_INT_ENABLE(priv->locality), intmask);
++      if (rc < 0)
++              dev_err(&chip->dev, "Enabling interrupts failed.\n");
+ }
+ int tpm_tis_resume(struct device *dev)
+@@ -1216,27 +1211,27 @@ int tpm_tis_resume(struct device *dev)
+       struct tpm_chip *chip = dev_get_drvdata(dev);
+       int ret;
+-      ret = tpm_tis_request_locality(chip, 0);
+-      if (ret < 0)
++      ret = tpm_chip_start(chip);
++      if (ret)
+               return ret;
+       if (chip->flags & TPM_CHIP_FLAG_IRQ)
+               tpm_tis_reenable_interrupts(chip);
+-      ret = tpm_pm_resume(dev);
+-      if (ret)
+-              goto out;
+-
+       /*
+        * TPM 1.2 requires self-test on resume. This function actually returns
+        * an error code but for unknown reason it isn't handled.
+        */
+       if (!(chip->flags & TPM_CHIP_FLAG_TPM2))
+               tpm1_do_selftest(chip);
+-out:
+-      tpm_tis_relinquish_locality(chip, 0);
+-      return ret;
++      tpm_chip_stop(chip);
++
++      ret = tpm_pm_resume(dev);
++      if (ret)
++              return ret;
++
++      return 0;
+ }
+ EXPORT_SYMBOL_GPL(tpm_tis_resume);
+ #endif
+-- 
+2.39.2
+
diff --git a/queue-6.3/usb-dwc3-fix-gadget-mode-suspend-interrupt-handler-i.patch b/queue-6.3/usb-dwc3-fix-gadget-mode-suspend-interrupt-handler-i.patch
new file mode 100644 (file)
index 0000000..0907f6b
--- /dev/null
@@ -0,0 +1,98 @@
+From 426d034028687092d05d8e3c942768551b6cd2a9 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 12 May 2023 08:45:24 +0800
+Subject: usb: dwc3: fix gadget mode suspend interrupt handler issue
+
+From: Linyu Yuan <quic_linyyuan@quicinc.com>
+
+[ Upstream commit 4e8ef34e36f2839ef8c8da521ab7035956436818 ]
+
+When work in gadget mode, currently driver doesn't update software level
+link_state correctly as link state change event is not enabled for most
+devices, in function dwc3_gadget_suspend_interrupt(), it will only pass
+suspend event to UDC core when software level link state changes, so when
+interrupt generated in sequences of suspend -> reset -> conndone ->
+suspend, link state is not updated during reset and conndone, so second
+suspend interrupt event will not pass to UDC core.
+
+Remove link_state compare in dwc3_gadget_suspend_interrupt() and add a
+suspended flag to replace the compare function.
+
+Fixes: 799e9dc82968 ("usb: dwc3: gadget: conditionally disable Link State change events")
+Cc: stable <stable@kernel.org>
+Acked-by: Thinh Nguyen <Thinh.Nguyen@synopsys.com>
+Signed-off-by: Linyu Yuan <quic_linyyuan@quicinc.com>
+Link: https://lore.kernel.org/r/20230512004524.31950-1-quic_linyyuan@quicinc.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/usb/dwc3/core.h   |  2 ++
+ drivers/usb/dwc3/gadget.c | 10 +++++++++-
+ 2 files changed, 11 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/usb/dwc3/core.h b/drivers/usb/dwc3/core.h
+index 4743e918dcafa..54ce9907a408c 100644
+--- a/drivers/usb/dwc3/core.h
++++ b/drivers/usb/dwc3/core.h
+@@ -1110,6 +1110,7 @@ struct dwc3_scratchpad_array {
+  *    3       - Reserved
+  * @dis_metastability_quirk: set to disable metastability quirk.
+  * @dis_split_quirk: set to disable split boundary.
++ * @suspended: set to track suspend event due to U3/L2.
+  * @imod_interval: set the interrupt moderation interval in 250ns
+  *                    increments or 0 to disable.
+  * @max_cfg_eps: current max number of IN eps used across all USB configs.
+@@ -1327,6 +1328,7 @@ struct dwc3 {
+       unsigned                dis_split_quirk:1;
+       unsigned                async_callbacks:1;
++      unsigned                suspended:1;
+       u16                     imod_interval;
+diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c
+index 80ae308448451..1cf352fbe7039 100644
+--- a/drivers/usb/dwc3/gadget.c
++++ b/drivers/usb/dwc3/gadget.c
+@@ -3838,6 +3838,8 @@ static void dwc3_gadget_disconnect_interrupt(struct dwc3 *dwc)
+ {
+       int                     reg;
++      dwc->suspended = false;
++
+       dwc3_gadget_set_link_state(dwc, DWC3_LINK_STATE_RX_DET);
+       reg = dwc3_readl(dwc->regs, DWC3_DCTL);
+@@ -3869,6 +3871,8 @@ static void dwc3_gadget_reset_interrupt(struct dwc3 *dwc)
+ {
+       u32                     reg;
++      dwc->suspended = false;
++
+       /*
+        * Ideally, dwc3_reset_gadget() would trigger the function
+        * drivers to stop any active transfers through ep disable.
+@@ -4098,6 +4102,8 @@ static void dwc3_gadget_conndone_interrupt(struct dwc3 *dwc)
+ static void dwc3_gadget_wakeup_interrupt(struct dwc3 *dwc)
+ {
++      dwc->suspended = false;
++
+       /*
+        * TODO take core out of low power mode when that's
+        * implemented.
+@@ -4213,8 +4219,10 @@ static void dwc3_gadget_suspend_interrupt(struct dwc3 *dwc,
+ {
+       enum dwc3_link_state next = evtinfo & DWC3_LINK_STATE_MASK;
+-      if (dwc->link_state != next && next == DWC3_LINK_STATE_U3)
++      if (!dwc->suspended && next == DWC3_LINK_STATE_U3) {
++              dwc->suspended = true;
+               dwc3_suspend_gadget(dwc);
++      }
+       dwc->link_state = next;
+ }
+-- 
+2.39.2
+
diff --git a/queue-6.3/wifi-rtw89-8852b-adjust-quota-to-avoid-ser-l1-caused.patch b/queue-6.3/wifi-rtw89-8852b-adjust-quota-to-avoid-ser-l1-caused.patch
new file mode 100644 (file)
index 0000000..2acd598
--- /dev/null
@@ -0,0 +1,125 @@
+From b89eaa03f72e9a7ac42c36390e017e27e4e74f8c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Apr 2023 11:47:37 +0800
+Subject: wifi: rtw89: 8852b: adjust quota to avoid SER L1 caused by access
+ null page
+
+From: Ping-Ke Shih <pkshih@realtek.com>
+
+[ Upstream commit c0426c446d92023d344131d01d929bc25db7a24e ]
+
+Though SER can recover this case, traffic can get stuck for a while. Fix it
+by adjusting page quota to avoid hardware access null page of CMAC/DMAC.
+
+Fixes: a1cb097168fa ("wifi: rtw89: 8852b: configure DLE mem")
+Fixes: 3e870b481733 ("wifi: rtw89: 8852b: add HFC quota arrays")
+Cc: stable@vger.kernel.org
+Tested-by: Larry Finger <Larry.Finger@lwfinger.net>
+Link: https://github.com/lwfinger/rtw89/issues/226#issuecomment-1520776761
+Link: https://github.com/lwfinger/rtw89/issues/240
+Signed-off-by: Ping-Ke Shih <pkshih@realtek.com>
+Signed-off-by: Kalle Valo <kvalo@kernel.org>
+Link: https://lore.kernel.org/r/20230426034737.24870-1-pkshih@realtek.com
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/net/wireless/realtek/rtw89/mac.c      |  4 ++++
+ drivers/net/wireless/realtek/rtw89/mac.h      |  2 ++
+ drivers/net/wireless/realtek/rtw89/rtw8852b.c | 22 +++++++++----------
+ 3 files changed, 17 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/net/wireless/realtek/rtw89/mac.c b/drivers/net/wireless/realtek/rtw89/mac.c
+index 2e2a2b6eab09d..d0cafe813cdb4 100644
+--- a/drivers/net/wireless/realtek/rtw89/mac.c
++++ b/drivers/net/wireless/realtek/rtw89/mac.c
+@@ -1425,6 +1425,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
+       .wde_size4 = {RTW89_WDE_PG_64, 0, 4096,},
+       /* PCIE 64 */
+       .wde_size6 = {RTW89_WDE_PG_64, 512, 0,},
++      /* 8852B PCIE SCC */
++      .wde_size7 = {RTW89_WDE_PG_64, 510, 2,},
+       /* DLFW */
+       .wde_size9 = {RTW89_WDE_PG_64, 0, 1024,},
+       /* 8852C DLFW */
+@@ -1449,6 +1451,8 @@ const struct rtw89_mac_size_set rtw89_mac_size = {
+       .wde_qt4 = {0, 0, 0, 0,},
+       /* PCIE 64 */
+       .wde_qt6 = {448, 48, 0, 16,},
++      /* 8852B PCIE SCC */
++      .wde_qt7 = {446, 48, 0, 16,},
+       /* 8852C DLFW */
+       .wde_qt17 = {0, 0, 0,  0,},
+       /* 8852C PCIE SCC */
+diff --git a/drivers/net/wireless/realtek/rtw89/mac.h b/drivers/net/wireless/realtek/rtw89/mac.h
+index 8064d3953d7f2..85c02c1f36bd7 100644
+--- a/drivers/net/wireless/realtek/rtw89/mac.h
++++ b/drivers/net/wireless/realtek/rtw89/mac.h
+@@ -791,6 +791,7 @@ struct rtw89_mac_size_set {
+       const struct rtw89_dle_size wde_size0;
+       const struct rtw89_dle_size wde_size4;
+       const struct rtw89_dle_size wde_size6;
++      const struct rtw89_dle_size wde_size7;
+       const struct rtw89_dle_size wde_size9;
+       const struct rtw89_dle_size wde_size18;
+       const struct rtw89_dle_size wde_size19;
+@@ -803,6 +804,7 @@ struct rtw89_mac_size_set {
+       const struct rtw89_wde_quota wde_qt0;
+       const struct rtw89_wde_quota wde_qt4;
+       const struct rtw89_wde_quota wde_qt6;
++      const struct rtw89_wde_quota wde_qt7;
+       const struct rtw89_wde_quota wde_qt17;
+       const struct rtw89_wde_quota wde_qt18;
+       const struct rtw89_ple_quota ple_qt4;
+diff --git a/drivers/net/wireless/realtek/rtw89/rtw8852b.c b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+index 45c374d025cbd..355e515364611 100644
+--- a/drivers/net/wireless/realtek/rtw89/rtw8852b.c
++++ b/drivers/net/wireless/realtek/rtw89/rtw8852b.c
+@@ -13,25 +13,25 @@
+ #include "txrx.h"
+ static const struct rtw89_hfc_ch_cfg rtw8852b_hfc_chcfg_pcie[] = {
+-      {5, 343, grp_0}, /* ACH 0 */
+-      {5, 343, grp_0}, /* ACH 1 */
+-      {5, 343, grp_0}, /* ACH 2 */
+-      {5, 343, grp_0}, /* ACH 3 */
++      {5, 341, grp_0}, /* ACH 0 */
++      {5, 341, grp_0}, /* ACH 1 */
++      {4, 342, grp_0}, /* ACH 2 */
++      {4, 342, grp_0}, /* ACH 3 */
+       {0, 0, grp_0}, /* ACH 4 */
+       {0, 0, grp_0}, /* ACH 5 */
+       {0, 0, grp_0}, /* ACH 6 */
+       {0, 0, grp_0}, /* ACH 7 */
+-      {4, 344, grp_0}, /* B0MGQ */
+-      {4, 344, grp_0}, /* B0HIQ */
++      {4, 342, grp_0}, /* B0MGQ */
++      {4, 342, grp_0}, /* B0HIQ */
+       {0, 0, grp_0}, /* B1MGQ */
+       {0, 0, grp_0}, /* B1HIQ */
+       {40, 0, 0} /* FWCMDQ */
+ };
+ static const struct rtw89_hfc_pub_cfg rtw8852b_hfc_pubcfg_pcie = {
+-      448, /* Group 0 */
++      446, /* Group 0 */
+       0, /* Group 1 */
+-      448, /* Public Max */
++      446, /* Public Max */
+       0 /* WP threshold */
+ };
+@@ -44,9 +44,9 @@ static const struct rtw89_hfc_param_ini rtw8852b_hfc_param_ini_pcie[] = {
+ };
+ static const struct rtw89_dle_mem rtw8852b_dle_mem_pcie[] = {
+-      [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size6,
+-                         &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt6,
+-                         &rtw89_mac_size.wde_qt6, &rtw89_mac_size.ple_qt18,
++      [RTW89_QTA_SCC] = {RTW89_QTA_SCC, &rtw89_mac_size.wde_size7,
++                         &rtw89_mac_size.ple_size6, &rtw89_mac_size.wde_qt7,
++                         &rtw89_mac_size.wde_qt7, &rtw89_mac_size.ple_qt18,
+                          &rtw89_mac_size.ple_qt58},
+       [RTW89_QTA_DLFW] = {RTW89_QTA_DLFW, &rtw89_mac_size.wde_size9,
+                           &rtw89_mac_size.ple_size8, &rtw89_mac_size.wde_qt4,
+-- 
+2.39.2
+
diff --git a/queue-6.3/zsmalloc-move-lru-update-from-zs_map_object-to-zs_ma.patch b/queue-6.3/zsmalloc-move-lru-update-from-zs_map_object-to-zs_ma.patch
new file mode 100644 (file)
index 0000000..ecc2267
--- /dev/null
@@ -0,0 +1,182 @@
+From 6660a6be528d52babf342cc3d66bccd4f55b9b46 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 5 May 2023 11:50:54 -0700
+Subject: zsmalloc: move LRU update from zs_map_object() to zs_malloc()
+
+From: Nhat Pham <nphamcs@gmail.com>
+
+[ Upstream commit d461aac924b937bcb4fd0ca1242b3ef6868ecddd ]
+
+Under memory pressure, we sometimes observe the following crash:
+
+[ 5694.832838] ------------[ cut here ]------------
+[ 5694.842093] list_del corruption, ffff888014b6a448->next is LIST_POISON1 (dead000000000100)
+[ 5694.858677] WARNING: CPU: 33 PID: 418824 at lib/list_debug.c:47 __list_del_entry_valid+0x42/0x80
+[ 5694.961820] CPU: 33 PID: 418824 Comm: fuse_counters.s Kdump: loaded Tainted: G S                5.19.0-0_fbk3_rc3_hoangnhatpzsdynshrv41_10870_g85a9558a25de #1
+[ 5694.990194] Hardware name: Wiwynn Twin Lakes MP/Twin Lakes Passive MP, BIOS YMM16 05/24/2021
+[ 5695.007072] RIP: 0010:__list_del_entry_valid+0x42/0x80
+[ 5695.017351] Code: 08 48 83 c2 22 48 39 d0 74 24 48 8b 10 48 39 f2 75 2c 48 8b 51 08 b0 01 48 39 f2 75 34 c3 48 c7 c7 55 d7 78 82 e8 4e 45 3b 00 <0f> 0b eb 31 48 c7 c7 27 a8 70 82 e8 3e 45 3b 00 0f 0b eb 21 48 c7
+[ 5695.054919] RSP: 0018:ffffc90027aef4f0 EFLAGS: 00010246
+[ 5695.065366] RAX: 41fe484987275300 RBX: ffff888008988180 RCX: 0000000000000000
+[ 5695.079636] RDX: ffff88886006c280 RSI: ffff888860060480 RDI: ffff888860060480
+[ 5695.093904] RBP: 0000000000000002 R08: 0000000000000000 R09: ffffc90027aef370
+[ 5695.108175] R10: 0000000000000000 R11: ffffffff82fdf1c0 R12: 0000000010000002
+[ 5695.122447] R13: ffff888014b6a448 R14: ffff888014b6a420 R15: 00000000138dc240
+[ 5695.136717] FS:  00007f23a7d3f740(0000) GS:ffff888860040000(0000) knlGS:0000000000000000
+[ 5695.152899] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
+[ 5695.164388] CR2: 0000560ceaab6ac0 CR3: 000000001c06c001 CR4: 00000000007706e0
+[ 5695.178659] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
+[ 5695.192927] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
+[ 5695.207197] PKRU: 55555554
+[ 5695.212602] Call Trace:
+[ 5695.217486]  <TASK>
+[ 5695.221674]  zs_map_object+0x91/0x270
+[ 5695.229000]  zswap_frontswap_store+0x33d/0x870
+[ 5695.237885]  ? do_raw_spin_lock+0x5d/0xa0
+[ 5695.245899]  __frontswap_store+0x51/0xb0
+[ 5695.253742]  swap_writepage+0x3c/0x60
+[ 5695.261063]  shrink_page_list+0x738/0x1230
+[ 5695.269255]  shrink_lruvec+0x5ec/0xcd0
+[ 5695.276749]  ? shrink_slab+0x187/0x5f0
+[ 5695.284240]  ? mem_cgroup_iter+0x6e/0x120
+[ 5695.292255]  shrink_node+0x293/0x7b0
+[ 5695.299402]  do_try_to_free_pages+0xea/0x550
+[ 5695.307940]  try_to_free_pages+0x19a/0x490
+[ 5695.316126]  __folio_alloc+0x19ff/0x3e40
+[ 5695.323971]  ? __filemap_get_folio+0x8a/0x4e0
+[ 5695.332681]  ? walk_component+0x2a8/0xb50
+[ 5695.340697]  ? generic_permission+0xda/0x2a0
+[ 5695.349231]  ? __filemap_get_folio+0x8a/0x4e0
+[ 5695.357940]  ? walk_component+0x2a8/0xb50
+[ 5695.365955]  vma_alloc_folio+0x10e/0x570
+[ 5695.373796]  ? walk_component+0x52/0xb50
+[ 5695.381634]  wp_page_copy+0x38c/0xc10
+[ 5695.388953]  ? filename_lookup+0x378/0xbc0
+[ 5695.397140]  handle_mm_fault+0x87f/0x1800
+[ 5695.405157]  do_user_addr_fault+0x1bd/0x570
+[ 5695.413520]  exc_page_fault+0x5d/0x110
+[ 5695.421017]  asm_exc_page_fault+0x22/0x30
+
+After some investigation, I have found the following issue: unlike other
+zswap backends, zsmalloc performs the LRU list update at the object
+mapping time, rather than when the slot for the object is allocated.
+This deviation was discussed and agreed upon during the review process
+of the zsmalloc writeback patch series:
+
+https://lore.kernel.org/lkml/Y3flcAXNxxrvy3ZH@cmpxchg.org/
+
+Unfortunately, this introduces a subtle bug that occurs when there is a
+concurrent store and reclaim, which interleave as follows:
+
+zswap_frontswap_store()            shrink_worker()
+  zs_malloc()                        zs_zpool_shrink()
+    spin_lock(&pool->lock)             zs_reclaim_page()
+    zspage = find_get_zspage()
+    spin_unlock(&pool->lock)
+                                         spin_lock(&pool->lock)
+                                         zspage = list_first_entry(&pool->lru)
+                                         list_del(&zspage->lru)
+                                           zspage->lru.next = LIST_POISON1
+                                           zspage->lru.prev = LIST_POISON2
+                                         spin_unlock(&pool->lock)
+  zs_map_object()
+    spin_lock(&pool->lock)
+    if (!list_empty(&zspage->lru))
+      list_del(&zspage->lru)
+        CHECK_DATA_CORRUPTION(next == LIST_POISON1) /* BOOM */
+
+With the current upstream code, this issue rarely happens. zswap only
+triggers writeback when the pool is already full, at which point all
+further store attempts are short-circuited. This creates an implicit
+pseudo-serialization between reclaim and store. I am working on a new
+zswap shrinking mechanism, which makes interleaving reclaim and store
+more likely, exposing this bug.
+
+zbud and z3fold do not have this problem, because they perform the LRU
+list update in the alloc function, while still holding the pool's lock.
+This patch fixes the aforementioned bug by moving the LRU update back to
+zs_malloc(), analogous to zbud and z3fold.
+
+Link: https://lkml.kernel.org/r/20230505185054.2417128-1-nphamcs@gmail.com
+Fixes: 64f768c6b32e ("zsmalloc: add a LRU to zs_pool to keep track of zspages in LRU order")
+Signed-off-by: Nhat Pham <nphamcs@gmail.com>
+Suggested-by: Johannes Weiner <hannes@cmpxchg.org>
+Acked-by: Johannes Weiner <hannes@cmpxchg.org>
+Reviewed-by: Sergey Senozhatsky <senozhatsky@chromium.org>
+Acked-by: Minchan Kim <minchan@kernel.org>
+Cc: Dan Streetman <ddstreet@ieee.org>
+Cc: Nitin Gupta <ngupta@vflare.org>
+Cc: Seth Jennings <sjenning@redhat.com>
+Cc: Vitaly Wool <vitaly.wool@konsulko.com>
+Cc: <stable@vger.kernel.org>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ mm/zsmalloc.c | 36 +++++++++---------------------------
+ 1 file changed, 9 insertions(+), 27 deletions(-)
+
+diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
+index 3aed46ab7e6cb..0d451b61573cb 100644
+--- a/mm/zsmalloc.c
++++ b/mm/zsmalloc.c
+@@ -1350,31 +1350,6 @@ void *zs_map_object(struct zs_pool *pool, unsigned long handle,
+       obj_to_location(obj, &page, &obj_idx);
+       zspage = get_zspage(page);
+-#ifdef CONFIG_ZPOOL
+-      /*
+-       * Move the zspage to front of pool's LRU.
+-       *
+-       * Note that this is swap-specific, so by definition there are no ongoing
+-       * accesses to the memory while the page is swapped out that would make
+-       * it "hot". A new entry is hot, then ages to the tail until it gets either
+-       * written back or swaps back in.
+-       *
+-       * Furthermore, map is also called during writeback. We must not put an
+-       * isolated page on the LRU mid-reclaim.
+-       *
+-       * As a result, only update the LRU when the page is mapped for write
+-       * when it's first instantiated.
+-       *
+-       * This is a deviation from the other backends, which perform this update
+-       * in the allocation function (zbud_alloc, z3fold_alloc).
+-       */
+-      if (mm == ZS_MM_WO) {
+-              if (!list_empty(&zspage->lru))
+-                      list_del(&zspage->lru);
+-              list_add(&zspage->lru, &pool->lru);
+-      }
+-#endif
+-
+       /*
+        * migration cannot move any zpages in this zspage. Here, pool->lock
+        * is too heavy since callers would take some time until they calls
+@@ -1544,9 +1519,8 @@ unsigned long zs_malloc(struct zs_pool *pool, size_t size, gfp_t gfp)
+               fix_fullness_group(class, zspage);
+               record_obj(handle, obj);
+               class_stat_inc(class, OBJ_USED, 1);
+-              spin_unlock(&pool->lock);
+-              return handle;
++              goto out;
+       }
+       spin_unlock(&pool->lock);
+@@ -1570,6 +1544,14 @@ unsigned long zs_malloc(struct zs_pool *pool, size_t size, gfp_t gfp)
+       /* We completely set up zspage so mark them as movable */
+       SetZsPageMovable(pool, zspage);
++out:
++#ifdef CONFIG_ZPOOL
++      /* Add/move zspage to beginning of LRU */
++      if (!list_empty(&zspage->lru))
++              list_del(&zspage->lru);
++      list_add(&zspage->lru, &pool->lru);
++#endif
++
+       spin_unlock(&pool->lock);
+       return handle;
+-- 
+2.39.2
+