From: Sasha Levin Date: Thu, 25 May 2023 14:38:15 +0000 (-0400) Subject: Fixes for 6.3 X-Git-Tag: review~97 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=2e2c2581363bd9d248b328e1943f7596bd8915eb;p=thirdparty%2Fkernel%2Fstable-queue.git Fixes for 6.3 Signed-off-by: Sasha Levin --- diff --git a/queue-6.3/series b/queue-6.3/series new file mode 100644 index 00000000000..f69a1407709 --- /dev/null +++ b/queue-6.3/series @@ -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 index 00000000000..7cc98a7f0d2 --- /dev/null +++ b/queue-6.3/tpm-prevent-hwrng-from-activating-during-resume.patch @@ -0,0 +1,82 @@ +From de5046897a02437941da794b1fc27e7059f7aa16 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Apr 2023 20:29:28 +0300 +Subject: tpm: Prevent hwrng from activating during resume + +From: Jarkko Sakkinen + +[ 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 +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..f03142240a7 --- /dev/null +++ b/queue-6.3/tpm-re-enable-tpm-chip-boostrapping-non-tpm_tis-tpm-.patch @@ -0,0 +1,141 @@ +From 083c65c6f80f05b42ee5c34664a80bf979381d75 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 26 Apr 2023 21:49:37 +0300 +Subject: tpm: Re-enable TPM chip boostrapping non-tpm_tis TPM drivers + +From: Jarkko Sakkinen + +[ 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 +Fixes: 548eb516ec0f ("tpm, tpm_tis: startup chip before testing for interrupts") +Reported-by: Pengfei Xu +Link: https://lore.kernel.org/all/ZEjqhwHWBnxcaRV5@xpf.sh.intel.com/ +Tested-by: Pengfei Xu +Signed-off-by: Jarkko Sakkinen +Stable-dep-of: 99d464506255 ("tpm: Prevent hwrng from activating during resume") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..73379816c52 --- /dev/null +++ b/queue-6.3/tpm-tpm_tis-avoid-cache-incoherency-in-test-for-inte.patch @@ -0,0 +1,157 @@ +From f035c8381e593048a921c503c776672fb183d04b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Tested-by: Michael Niewöhner +Tested-by: Jarkko Sakkinen +Reviewed-by: Jarkko Sakkinen +Signed-off-by: Jarkko Sakkinen +Stable-dep-of: 1398aa803f19 ("tpm_tis: Use tpm_chip_{start,stop} decoration inside tpm_tis_resume") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..e9a08f42b65 --- /dev/null +++ b/queue-6.3/tpm-tpm_tis-only-handle-supported-interrupts.patch @@ -0,0 +1,231 @@ +From f8b479fb55f95efdfc06f09f858b22bf7bc9980f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Tested-by: Michael Niewöhner +Tested-by: Jarkko Sakkinen +Reviewed-by: Jarkko Sakkinen +Signed-off-by: Jarkko Sakkinen +Stable-dep-of: 1398aa803f19 ("tpm_tis: Use tpm_chip_{start,stop} decoration inside tpm_tis_resume") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..907d8a05286 --- /dev/null +++ b/queue-6.3/tpm-tpm_tis-startup-chip-before-testing-for-interrup.patch @@ -0,0 +1,117 @@ +From f3f4e16e311a02e7eef98e3a71e813567019a8ff Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Thu, 24 Nov 2022 14:55:37 +0100 +Subject: tpm, tpm_tis: startup chip before testing for interrupts + +From: Lino Sanfilippo + +[ 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 +Tested-by: Jarkko Sakkinen +Reviewed-by: Jarkko Sakkinen +Signed-off-by: Jarkko Sakkinen +Stable-dep-of: 99d464506255 ("tpm: Prevent hwrng from activating during resume") +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..84294f90de4 --- /dev/null +++ b/queue-6.3/tpm_tis-use-tpm_chip_-start-stop-decoration-inside-t.patch @@ -0,0 +1,110 @@ +From bbf9bb3ea7787de45d6adbab39375b987643c8f3 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +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 +Signed-off-by: Jarkko Sakkinen +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..0907f6bb457 --- /dev/null +++ b/queue-6.3/usb-dwc3-fix-gadget-mode-suspend-interrupt-handler-i.patch @@ -0,0 +1,98 @@ +From 426d034028687092d05d8e3c942768551b6cd2a9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 12 May 2023 08:45:24 +0800 +Subject: usb: dwc3: fix gadget mode suspend interrupt handler issue + +From: Linyu Yuan + +[ 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 +Acked-by: Thinh Nguyen +Signed-off-by: Linyu Yuan +Link: https://lore.kernel.org/r/20230512004524.31950-1-quic_linyyuan@quicinc.com +Signed-off-by: Greg Kroah-Hartman +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..2acd598e9c2 --- /dev/null +++ b/queue-6.3/wifi-rtw89-8852b-adjust-quota-to-avoid-ser-l1-caused.patch @@ -0,0 +1,125 @@ +From b89eaa03f72e9a7ac42c36390e017e27e4e74f8c Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Link: https://github.com/lwfinger/rtw89/issues/226#issuecomment-1520776761 +Link: https://github.com/lwfinger/rtw89/issues/240 +Signed-off-by: Ping-Ke Shih +Signed-off-by: Kalle Valo +Link: https://lore.kernel.org/r/20230426034737.24870-1-pkshih@realtek.com +Signed-off-by: Sasha Levin +--- + 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 index 00000000000..ecc2267fb36 --- /dev/null +++ b/queue-6.3/zsmalloc-move-lru-update-from-zs_map_object-to-zs_ma.patch @@ -0,0 +1,182 @@ +From 6660a6be528d52babf342cc3d66bccd4f55b9b46 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 5 May 2023 11:50:54 -0700 +Subject: zsmalloc: move LRU update from zs_map_object() to zs_malloc() + +From: Nhat Pham + +[ 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] +[ 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 +Suggested-by: Johannes Weiner +Acked-by: Johannes Weiner +Reviewed-by: Sergey Senozhatsky +Acked-by: Minchan Kim +Cc: Dan Streetman +Cc: Nitin Gupta +Cc: Seth Jennings +Cc: Vitaly Wool +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + 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 +