--- /dev/null
+From 3049952ab66db9880b96789de72d7c34ae9d53da Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 21 Oct 2020 19:18:19 +0200
+Subject: bus: mhi: Add MHI PCI support for WWAN modems
+
+From: Loic Poulain <loic.poulain@linaro.org>
+
+[ Upstream commit 855a70c12021bdc5df60512f1d3f6d492dc715be ]
+
+This is a generic MHI-over-PCI controller driver for MHI only devices
+such as QCOM modems. For now it supports registering of Qualcomm SDX55
+based PCIe modules. The MHI channels have been extracted from mhi
+downstream driver.
+
+This driver is for MHI-only devices which have all functionalities
+exposed through MHI channels and accessed by the corresponding MHI
+device drivers (no out-of-band communication).
+
+Signed-off-by: Loic Poulain <loic.poulain@linaro.org>
+Reviewed-by: Bhaumik Bhatt <bbhatt@codeaurora.org>
+Reviewed-by: Hemant Kumar <hemantk@codeaurora.org>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+[mani: fixed up the Makefile rule]
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Stable-dep-of: 6a0c637bfee6 ("bus: mhi: host: Range check CHDBOFF and ERDBOFF")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bus/mhi/Kconfig | 9 +
+ drivers/bus/mhi/Makefile | 4 +
+ drivers/bus/mhi/pci_generic.c | 345 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 358 insertions(+)
+ create mode 100644 drivers/bus/mhi/pci_generic.c
+
+diff --git a/drivers/bus/mhi/Kconfig b/drivers/bus/mhi/Kconfig
+index e841c1097fb4d..da5cd0c9fc620 100644
+--- a/drivers/bus/mhi/Kconfig
++++ b/drivers/bus/mhi/Kconfig
+@@ -20,3 +20,12 @@ config MHI_BUS_DEBUG
+ Enable debugfs support for use with the MHI transport. Allows
+ reading and/or modifying some values within the MHI controller
+ for debug and test purposes.
++
++config MHI_BUS_PCI_GENERIC
++ tristate "MHI PCI controller driver"
++ depends on MHI_BUS
++ depends on PCI
++ help
++ This driver provides MHI PCI controller driver for devices such as
++ Qualcomm SDX55 based PCIe modems.
++
+diff --git a/drivers/bus/mhi/Makefile b/drivers/bus/mhi/Makefile
+index 19e6443b72df4..0a2d778d6fb42 100644
+--- a/drivers/bus/mhi/Makefile
++++ b/drivers/bus/mhi/Makefile
+@@ -1,2 +1,6 @@
+ # core layer
+ obj-y += core/
++
++obj-$(CONFIG_MHI_BUS_PCI_GENERIC) += mhi_pci_generic.o
++mhi_pci_generic-y += pci_generic.o
++
+diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/pci_generic.c
+new file mode 100644
+index 0000000000000..e3df838c3c80e
+--- /dev/null
++++ b/drivers/bus/mhi/pci_generic.c
+@@ -0,0 +1,345 @@
++// SPDX-License-Identifier: GPL-2.0-or-later
++/*
++ * MHI PCI driver - MHI over PCI controller driver
++ *
++ * This module is a generic driver for registering MHI-over-PCI devices,
++ * such as PCIe QCOM modems.
++ *
++ * Copyright (C) 2020 Linaro Ltd <loic.poulain@linaro.org>
++ */
++
++#include <linux/device.h>
++#include <linux/mhi.h>
++#include <linux/module.h>
++#include <linux/pci.h>
++
++#define MHI_PCI_DEFAULT_BAR_NUM 0
++
++/**
++ * struct mhi_pci_dev_info - MHI PCI device specific information
++ * @config: MHI controller configuration
++ * @name: name of the PCI module
++ * @fw: firmware path (if any)
++ * @edl: emergency download mode firmware path (if any)
++ * @bar_num: PCI base address register to use for MHI MMIO register space
++ * @dma_data_width: DMA transfer word size (32 or 64 bits)
++ */
++struct mhi_pci_dev_info {
++ const struct mhi_controller_config *config;
++ const char *name;
++ const char *fw;
++ const char *edl;
++ unsigned int bar_num;
++ unsigned int dma_data_width;
++};
++
++#define MHI_CHANNEL_CONFIG_UL(ch_num, ch_name, el_count, ev_ring) \
++ { \
++ .num = ch_num, \
++ .name = ch_name, \
++ .num_elements = el_count, \
++ .event_ring = ev_ring, \
++ .dir = DMA_TO_DEVICE, \
++ .ee_mask = BIT(MHI_EE_AMSS), \
++ .pollcfg = 0, \
++ .doorbell = MHI_DB_BRST_DISABLE, \
++ .lpm_notify = false, \
++ .offload_channel = false, \
++ .doorbell_mode_switch = false, \
++ } \
++
++#define MHI_CHANNEL_CONFIG_DL(ch_num, ch_name, el_count, ev_ring) \
++ { \
++ .num = ch_num, \
++ .name = ch_name, \
++ .num_elements = el_count, \
++ .event_ring = ev_ring, \
++ .dir = DMA_FROM_DEVICE, \
++ .ee_mask = BIT(MHI_EE_AMSS), \
++ .pollcfg = 0, \
++ .doorbell = MHI_DB_BRST_DISABLE, \
++ .lpm_notify = false, \
++ .offload_channel = false, \
++ .doorbell_mode_switch = false, \
++ }
++
++#define MHI_EVENT_CONFIG_CTRL(ev_ring) \
++ { \
++ .num_elements = 64, \
++ .irq_moderation_ms = 0, \
++ .irq = (ev_ring) + 1, \
++ .priority = 1, \
++ .mode = MHI_DB_BRST_DISABLE, \
++ .data_type = MHI_ER_CTRL, \
++ .hardware_event = false, \
++ .client_managed = false, \
++ .offload_channel = false, \
++ }
++
++#define MHI_EVENT_CONFIG_DATA(ev_ring) \
++ { \
++ .num_elements = 128, \
++ .irq_moderation_ms = 5, \
++ .irq = (ev_ring) + 1, \
++ .priority = 1, \
++ .mode = MHI_DB_BRST_DISABLE, \
++ .data_type = MHI_ER_DATA, \
++ .hardware_event = false, \
++ .client_managed = false, \
++ .offload_channel = false, \
++ }
++
++#define MHI_EVENT_CONFIG_HW_DATA(ev_ring, ch_num) \
++ { \
++ .num_elements = 128, \
++ .irq_moderation_ms = 5, \
++ .irq = (ev_ring) + 1, \
++ .priority = 1, \
++ .mode = MHI_DB_BRST_DISABLE, \
++ .data_type = MHI_ER_DATA, \
++ .hardware_event = true, \
++ .client_managed = false, \
++ .offload_channel = false, \
++ .channel = ch_num, \
++ }
++
++static const struct mhi_channel_config modem_qcom_v1_mhi_channels[] = {
++ MHI_CHANNEL_CONFIG_UL(12, "MBIM", 4, 0),
++ MHI_CHANNEL_CONFIG_DL(13, "MBIM", 4, 0),
++ MHI_CHANNEL_CONFIG_UL(14, "QMI", 4, 0),
++ MHI_CHANNEL_CONFIG_DL(15, "QMI", 4, 0),
++ MHI_CHANNEL_CONFIG_UL(20, "IPCR", 8, 0),
++ MHI_CHANNEL_CONFIG_DL(21, "IPCR", 8, 0),
++ MHI_CHANNEL_CONFIG_UL(100, "IP_HW0", 128, 1),
++ MHI_CHANNEL_CONFIG_DL(101, "IP_HW0", 128, 2),
++};
++
++static const struct mhi_event_config modem_qcom_v1_mhi_events[] = {
++ /* first ring is control+data ring */
++ MHI_EVENT_CONFIG_CTRL(0),
++ /* Hardware channels request dedicated hardware event rings */
++ MHI_EVENT_CONFIG_HW_DATA(1, 100),
++ MHI_EVENT_CONFIG_HW_DATA(2, 101)
++};
++
++static const struct mhi_controller_config modem_qcom_v1_mhiv_config = {
++ .max_channels = 128,
++ .timeout_ms = 5000,
++ .num_channels = ARRAY_SIZE(modem_qcom_v1_mhi_channels),
++ .ch_cfg = modem_qcom_v1_mhi_channels,
++ .num_events = ARRAY_SIZE(modem_qcom_v1_mhi_events),
++ .event_cfg = modem_qcom_v1_mhi_events,
++};
++
++static const struct mhi_pci_dev_info mhi_qcom_sdx55_info = {
++ .name = "qcom-sdx55m",
++ .fw = "qcom/sdx55m/sbl1.mbn",
++ .edl = "qcom/sdx55m/edl.mbn",
++ .config = &modem_qcom_v1_mhiv_config,
++ .bar_num = MHI_PCI_DEFAULT_BAR_NUM,
++ .dma_data_width = 32
++};
++
++static const struct pci_device_id mhi_pci_id_table[] = {
++ { PCI_DEVICE(PCI_VENDOR_ID_QCOM, 0x0306),
++ .driver_data = (kernel_ulong_t) &mhi_qcom_sdx55_info },
++ { }
++};
++MODULE_DEVICE_TABLE(pci, mhi_pci_id_table);
++
++static int mhi_pci_read_reg(struct mhi_controller *mhi_cntrl,
++ void __iomem *addr, u32 *out)
++{
++ *out = readl(addr);
++ return 0;
++}
++
++static void mhi_pci_write_reg(struct mhi_controller *mhi_cntrl,
++ void __iomem *addr, u32 val)
++{
++ writel(val, addr);
++}
++
++static void mhi_pci_status_cb(struct mhi_controller *mhi_cntrl,
++ enum mhi_callback cb)
++{
++ /* Nothing to do for now */
++}
++
++static int mhi_pci_claim(struct mhi_controller *mhi_cntrl,
++ unsigned int bar_num, u64 dma_mask)
++{
++ struct pci_dev *pdev = to_pci_dev(mhi_cntrl->cntrl_dev);
++ int err;
++
++ err = pci_assign_resource(pdev, bar_num);
++ if (err)
++ return err;
++
++ err = pcim_enable_device(pdev);
++ if (err) {
++ dev_err(&pdev->dev, "failed to enable pci device: %d\n", err);
++ return err;
++ }
++
++ err = pcim_iomap_regions(pdev, 1 << bar_num, pci_name(pdev));
++ if (err) {
++ dev_err(&pdev->dev, "failed to map pci region: %d\n", err);
++ return err;
++ }
++ mhi_cntrl->regs = pcim_iomap_table(pdev)[bar_num];
++
++ err = pci_set_dma_mask(pdev, dma_mask);
++ if (err) {
++ dev_err(&pdev->dev, "Cannot set proper DMA mask\n");
++ return err;
++ }
++
++ err = pci_set_consistent_dma_mask(pdev, dma_mask);
++ if (err) {
++ dev_err(&pdev->dev, "set consistent dma mask failed\n");
++ return err;
++ }
++
++ pci_set_master(pdev);
++
++ return 0;
++}
++
++static int mhi_pci_get_irqs(struct mhi_controller *mhi_cntrl,
++ const struct mhi_controller_config *mhi_cntrl_config)
++{
++ struct pci_dev *pdev = to_pci_dev(mhi_cntrl->cntrl_dev);
++ int nr_vectors, i;
++ int *irq;
++
++ /*
++ * Alloc one MSI vector for BHI + one vector per event ring, ideally...
++ * No explicit pci_free_irq_vectors required, done by pcim_release.
++ */
++ mhi_cntrl->nr_irqs = 1 + mhi_cntrl_config->num_events;
++
++ nr_vectors = pci_alloc_irq_vectors(pdev, 1, mhi_cntrl->nr_irqs, PCI_IRQ_MSI);
++ if (nr_vectors < 0) {
++ dev_err(&pdev->dev, "Error allocating MSI vectors %d\n",
++ nr_vectors);
++ return nr_vectors;
++ }
++
++ if (nr_vectors < mhi_cntrl->nr_irqs) {
++ dev_warn(&pdev->dev, "Not enough MSI vectors (%d/%d), use shared MSI\n",
++ nr_vectors, mhi_cntrl_config->num_events);
++ }
++
++ irq = devm_kcalloc(&pdev->dev, mhi_cntrl->nr_irqs, sizeof(int), GFP_KERNEL);
++ if (!irq)
++ return -ENOMEM;
++
++ for (i = 0; i < mhi_cntrl->nr_irqs; i++) {
++ int vector = i >= nr_vectors ? (nr_vectors - 1) : i;
++
++ irq[i] = pci_irq_vector(pdev, vector);
++ }
++
++ mhi_cntrl->irq = irq;
++
++ return 0;
++}
++
++static int mhi_pci_runtime_get(struct mhi_controller *mhi_cntrl)
++{
++ /* no PM for now */
++ return 0;
++}
++
++static void mhi_pci_runtime_put(struct mhi_controller *mhi_cntrl)
++{
++ /* no PM for now */
++}
++
++static int mhi_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
++{
++ const struct mhi_pci_dev_info *info = (struct mhi_pci_dev_info *) id->driver_data;
++ const struct mhi_controller_config *mhi_cntrl_config;
++ struct mhi_controller *mhi_cntrl;
++ int err;
++
++ dev_dbg(&pdev->dev, "MHI PCI device found: %s\n", info->name);
++
++ mhi_cntrl = mhi_alloc_controller();
++ if (!mhi_cntrl)
++ return -ENOMEM;
++
++ mhi_cntrl_config = info->config;
++ mhi_cntrl->cntrl_dev = &pdev->dev;
++ mhi_cntrl->iova_start = 0;
++ mhi_cntrl->iova_stop = DMA_BIT_MASK(info->dma_data_width);
++ mhi_cntrl->fw_image = info->fw;
++ mhi_cntrl->edl_image = info->edl;
++
++ mhi_cntrl->read_reg = mhi_pci_read_reg;
++ mhi_cntrl->write_reg = mhi_pci_write_reg;
++ mhi_cntrl->status_cb = mhi_pci_status_cb;
++ mhi_cntrl->runtime_get = mhi_pci_runtime_get;
++ mhi_cntrl->runtime_put = mhi_pci_runtime_put;
++
++ err = mhi_pci_claim(mhi_cntrl, info->bar_num, DMA_BIT_MASK(info->dma_data_width));
++ if (err)
++ goto err_release;
++
++ err = mhi_pci_get_irqs(mhi_cntrl, mhi_cntrl_config);
++ if (err)
++ goto err_release;
++
++ pci_set_drvdata(pdev, mhi_cntrl);
++
++ err = mhi_register_controller(mhi_cntrl, mhi_cntrl_config);
++ if (err)
++ goto err_release;
++
++ /* MHI bus does not power up the controller by default */
++ err = mhi_prepare_for_power_up(mhi_cntrl);
++ if (err) {
++ dev_err(&pdev->dev, "failed to prepare MHI controller\n");
++ goto err_unregister;
++ }
++
++ err = mhi_sync_power_up(mhi_cntrl);
++ if (err) {
++ dev_err(&pdev->dev, "failed to power up MHI controller\n");
++ goto err_unprepare;
++ }
++
++ return 0;
++
++err_unprepare:
++ mhi_unprepare_after_power_down(mhi_cntrl);
++err_unregister:
++ mhi_unregister_controller(mhi_cntrl);
++err_release:
++ mhi_free_controller(mhi_cntrl);
++
++ return err;
++}
++
++static void mhi_pci_remove(struct pci_dev *pdev)
++{
++ struct mhi_controller *mhi_cntrl = pci_get_drvdata(pdev);
++
++ mhi_power_down(mhi_cntrl, true);
++ mhi_unprepare_after_power_down(mhi_cntrl);
++ mhi_unregister_controller(mhi_cntrl);
++ mhi_free_controller(mhi_cntrl);
++}
++
++static struct pci_driver mhi_pci_driver = {
++ .name = "mhi-pci-generic",
++ .id_table = mhi_pci_id_table,
++ .probe = mhi_pci_probe,
++ .remove = mhi_pci_remove
++};
++module_pci_driver(mhi_pci_driver);
++
++MODULE_AUTHOR("Loic Poulain <loic.poulain@linaro.org>");
++MODULE_DESCRIPTION("Modem Host Interface (MHI) PCI controller driver");
++MODULE_LICENSE("GPL");
+--
+2.39.2
+
--- /dev/null
+From 02b448eda71c9e6080c4f49200ce601ea2bd175c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 2 Aug 2021 10:42:50 +0530
+Subject: bus: mhi: Add MMIO region length to controller structure
+
+From: Bhaumik Bhatt <bbhatt@codeaurora.org>
+
+[ Upstream commit baa7a08569358d9d16e71ce36f287c39a665d776 ]
+
+Make controller driver specify the MMIO register region length
+for range checking of BHI or BHIe space. This can help validate
+that offsets are in acceptable memory region or not and avoid any
+boot-up issues due to BHI or BHIe memory accesses.
+
+Link: https://lore.kernel.org/r/1620330705-40192-4-git-send-email-bbhatt@codeaurora.org
+Reviewed-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
+Reviewed-by: Hemant Kumar <hemantk@codeaurora.org>
+Reviewed-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Bhaumik Bhatt <bbhatt@codeaurora.org>
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Link: https://lore.kernel.org/r/20210802051255.5771-6-manivannan.sadhasivam@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 6a0c637bfee6 ("bus: mhi: host: Range check CHDBOFF and ERDBOFF")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/linux/mhi.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/include/linux/mhi.h b/include/linux/mhi.h
+index d4841e5a5f458..5d9f8c6f3d40f 100644
+--- a/include/linux/mhi.h
++++ b/include/linux/mhi.h
+@@ -303,6 +303,7 @@ struct mhi_controller_config {
+ * @rddm_size: RAM dump size that host should allocate for debugging purpose
+ * @sbl_size: SBL image size downloaded through BHIe (optional)
+ * @seg_len: BHIe vector size (optional)
++ * @reg_len: Length of the MHI MMIO region (required)
+ * @fbc_image: Points to firmware image buffer
+ * @rddm_image: Points to RAM dump buffer
+ * @mhi_chan: Points to the channel configuration table
+@@ -383,6 +384,7 @@ struct mhi_controller {
+ size_t rddm_size;
+ size_t sbl_size;
+ size_t seg_len;
++ size_t reg_len;
+ struct image_info *fbc_image;
+ struct image_info *rddm_image;
+ struct mhi_chan *mhi_chan;
+--
+2.39.2
+
--- /dev/null
+From ffecd7beda1bb049865050fd0b57b0861def8409 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 24 Mar 2023 10:13:04 -0600
+Subject: bus: mhi: host: Range check CHDBOFF and ERDBOFF
+
+From: Jeffrey Hugo <quic_jhugo@quicinc.com>
+
+[ Upstream commit 6a0c637bfee69a74c104468544d9f2a6579626d0 ]
+
+If the value read from the CHDBOFF and ERDBOFF registers is outside the
+range of the MHI register space then an invalid address might be computed
+which later causes a kernel panic. Range check the read value to prevent
+a crash due to bad data from the device.
+
+Fixes: 6cd330ae76ff ("bus: mhi: core: Add support for ringing channel/event ring doorbells")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jeffrey Hugo <quic_jhugo@quicinc.com>
+Reviewed-by: Pranjal Ramajor Asha Kanojiya <quic_pkanojiy@quicinc.com>
+Reviewed-by: Manivannan Sadhasivam <mani@kernel.org>
+Link: https://lore.kernel.org/r/1679674384-27209-1-git-send-email-quic_jhugo@quicinc.com
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bus/mhi/host/init.c | 12 ++++++++++++
+ 1 file changed, 12 insertions(+)
+
+diff --git a/drivers/bus/mhi/host/init.c b/drivers/bus/mhi/host/init.c
+index 0d0386f67ffe2..2cc48f96afdbc 100644
+--- a/drivers/bus/mhi/host/init.c
++++ b/drivers/bus/mhi/host/init.c
+@@ -498,6 +498,12 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl)
+ return -EIO;
+ }
+
++ if (val >= mhi_cntrl->reg_len - (8 * MHI_DEV_WAKE_DB)) {
++ dev_err(dev, "CHDB offset: 0x%x is out of range: 0x%zx\n",
++ val, mhi_cntrl->reg_len - (8 * MHI_DEV_WAKE_DB));
++ return -ERANGE;
++ }
++
+ /* Setup wake db */
+ mhi_cntrl->wake_db = base + val + (8 * MHI_DEV_WAKE_DB);
+ mhi_write_reg(mhi_cntrl, mhi_cntrl->wake_db, 4, 0);
+@@ -517,6 +523,12 @@ int mhi_init_mmio(struct mhi_controller *mhi_cntrl)
+ return -EIO;
+ }
+
++ if (val >= mhi_cntrl->reg_len - (8 * mhi_cntrl->total_ev_rings)) {
++ dev_err(dev, "ERDB offset: 0x%x is out of range: 0x%zx\n",
++ val, mhi_cntrl->reg_len - (8 * mhi_cntrl->total_ev_rings));
++ return -ERANGE;
++ }
++
+ /* Setup event db address for each ev_ring */
+ mhi_event = mhi_cntrl->mhi_event;
+ for (i = 0; i < mhi_cntrl->total_ev_rings; i++, val += 8, mhi_event++) {
+--
+2.39.2
+
--- /dev/null
+From 49980807fded019a68228a20da8e9a0c64c637f8 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 1 Mar 2022 21:33:02 +0530
+Subject: bus: mhi: Move host MHI code to "host" directory
+
+From: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+
+[ Upstream commit a0f5a630668cb8b2ebf5204f08e957875e991780 ]
+
+In preparation of the endpoint MHI support, let's move the host MHI code
+to its own "host" directory and adjust the toplevel MHI Kconfig & Makefile.
+
+While at it, let's also move the "pci_generic" driver to "host" directory
+as it is a host MHI controller driver.
+
+Reviewed-by: Hemant Kumar <hemantk@codeaurora.org>
+Reviewed-by: Alex Elder <elder@linaro.org>
+Signed-off-by: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+Link: https://lore.kernel.org/r/20220301160308.107452-5-manivannan.sadhasivam@linaro.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 6a0c637bfee6 ("bus: mhi: host: Range check CHDBOFF and ERDBOFF")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/bus/Makefile | 2 +-
+ drivers/bus/mhi/Kconfig | 27 ++------------------
+ drivers/bus/mhi/Makefile | 8 ++----
+ drivers/bus/mhi/host/Kconfig | 31 +++++++++++++++++++++++
+ drivers/bus/mhi/{core => host}/Makefile | 4 ++-
+ drivers/bus/mhi/{core => host}/boot.c | 0
+ drivers/bus/mhi/{core => host}/debugfs.c | 0
+ drivers/bus/mhi/{core => host}/init.c | 0
+ drivers/bus/mhi/{core => host}/internal.h | 0
+ drivers/bus/mhi/{core => host}/main.c | 0
+ drivers/bus/mhi/{ => host}/pci_generic.c | 0
+ drivers/bus/mhi/{core => host}/pm.c | 0
+ 12 files changed, 39 insertions(+), 33 deletions(-)
+ create mode 100644 drivers/bus/mhi/host/Kconfig
+ rename drivers/bus/mhi/{core => host}/Makefile (54%)
+ rename drivers/bus/mhi/{core => host}/boot.c (100%)
+ rename drivers/bus/mhi/{core => host}/debugfs.c (100%)
+ rename drivers/bus/mhi/{core => host}/init.c (100%)
+ rename drivers/bus/mhi/{core => host}/internal.h (100%)
+ rename drivers/bus/mhi/{core => host}/main.c (100%)
+ rename drivers/bus/mhi/{ => host}/pci_generic.c (100%)
+ rename drivers/bus/mhi/{core => host}/pm.c (100%)
+
+diff --git a/drivers/bus/Makefile b/drivers/bus/Makefile
+index 397e35392bff8..16c47a0616ae4 100644
+--- a/drivers/bus/Makefile
++++ b/drivers/bus/Makefile
+@@ -38,4 +38,4 @@ obj-$(CONFIG_VEXPRESS_CONFIG) += vexpress-config.o
+ obj-$(CONFIG_DA8XX_MSTPRI) += da8xx-mstpri.o
+
+ # MHI
+-obj-$(CONFIG_MHI_BUS) += mhi/
++obj-y += mhi/
+diff --git a/drivers/bus/mhi/Kconfig b/drivers/bus/mhi/Kconfig
+index da5cd0c9fc620..4748df7f9cd58 100644
+--- a/drivers/bus/mhi/Kconfig
++++ b/drivers/bus/mhi/Kconfig
+@@ -2,30 +2,7 @@
+ #
+ # MHI bus
+ #
+-# Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
++# Copyright (c) 2021, Linaro Ltd.
+ #
+
+-config MHI_BUS
+- tristate "Modem Host Interface (MHI) bus"
+- help
+- Bus driver for MHI protocol. Modem Host Interface (MHI) is a
+- communication protocol used by the host processors to control
+- and communicate with modem devices over a high speed peripheral
+- bus or shared memory.
+-
+-config MHI_BUS_DEBUG
+- bool "Debugfs support for the MHI bus"
+- depends on MHI_BUS && DEBUG_FS
+- help
+- Enable debugfs support for use with the MHI transport. Allows
+- reading and/or modifying some values within the MHI controller
+- for debug and test purposes.
+-
+-config MHI_BUS_PCI_GENERIC
+- tristate "MHI PCI controller driver"
+- depends on MHI_BUS
+- depends on PCI
+- help
+- This driver provides MHI PCI controller driver for devices such as
+- Qualcomm SDX55 based PCIe modems.
+-
++source "drivers/bus/mhi/host/Kconfig"
+diff --git a/drivers/bus/mhi/Makefile b/drivers/bus/mhi/Makefile
+index 0a2d778d6fb42..5f5708a249f54 100644
+--- a/drivers/bus/mhi/Makefile
++++ b/drivers/bus/mhi/Makefile
+@@ -1,6 +1,2 @@
+-# core layer
+-obj-y += core/
+-
+-obj-$(CONFIG_MHI_BUS_PCI_GENERIC) += mhi_pci_generic.o
+-mhi_pci_generic-y += pci_generic.o
+-
++# Host MHI stack
++obj-y += host/
+diff --git a/drivers/bus/mhi/host/Kconfig b/drivers/bus/mhi/host/Kconfig
+new file mode 100644
+index 0000000000000..da5cd0c9fc620
+--- /dev/null
++++ b/drivers/bus/mhi/host/Kconfig
+@@ -0,0 +1,31 @@
++# SPDX-License-Identifier: GPL-2.0
++#
++# MHI bus
++#
++# Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
++#
++
++config MHI_BUS
++ tristate "Modem Host Interface (MHI) bus"
++ help
++ Bus driver for MHI protocol. Modem Host Interface (MHI) is a
++ communication protocol used by the host processors to control
++ and communicate with modem devices over a high speed peripheral
++ bus or shared memory.
++
++config MHI_BUS_DEBUG
++ bool "Debugfs support for the MHI bus"
++ depends on MHI_BUS && DEBUG_FS
++ help
++ Enable debugfs support for use with the MHI transport. Allows
++ reading and/or modifying some values within the MHI controller
++ for debug and test purposes.
++
++config MHI_BUS_PCI_GENERIC
++ tristate "MHI PCI controller driver"
++ depends on MHI_BUS
++ depends on PCI
++ help
++ This driver provides MHI PCI controller driver for devices such as
++ Qualcomm SDX55 based PCIe modems.
++
+diff --git a/drivers/bus/mhi/core/Makefile b/drivers/bus/mhi/host/Makefile
+similarity index 54%
+rename from drivers/bus/mhi/core/Makefile
+rename to drivers/bus/mhi/host/Makefile
+index c3feb4130aa37..859c2f38451c6 100644
+--- a/drivers/bus/mhi/core/Makefile
++++ b/drivers/bus/mhi/host/Makefile
+@@ -1,4 +1,6 @@
+ obj-$(CONFIG_MHI_BUS) += mhi.o
+-
+ mhi-y := init.o main.o pm.o boot.o
+ mhi-$(CONFIG_MHI_BUS_DEBUG) += debugfs.o
++
++obj-$(CONFIG_MHI_BUS_PCI_GENERIC) += mhi_pci_generic.o
++mhi_pci_generic-y += pci_generic.o
+diff --git a/drivers/bus/mhi/core/boot.c b/drivers/bus/mhi/host/boot.c
+similarity index 100%
+rename from drivers/bus/mhi/core/boot.c
+rename to drivers/bus/mhi/host/boot.c
+diff --git a/drivers/bus/mhi/core/debugfs.c b/drivers/bus/mhi/host/debugfs.c
+similarity index 100%
+rename from drivers/bus/mhi/core/debugfs.c
+rename to drivers/bus/mhi/host/debugfs.c
+diff --git a/drivers/bus/mhi/core/init.c b/drivers/bus/mhi/host/init.c
+similarity index 100%
+rename from drivers/bus/mhi/core/init.c
+rename to drivers/bus/mhi/host/init.c
+diff --git a/drivers/bus/mhi/core/internal.h b/drivers/bus/mhi/host/internal.h
+similarity index 100%
+rename from drivers/bus/mhi/core/internal.h
+rename to drivers/bus/mhi/host/internal.h
+diff --git a/drivers/bus/mhi/core/main.c b/drivers/bus/mhi/host/main.c
+similarity index 100%
+rename from drivers/bus/mhi/core/main.c
+rename to drivers/bus/mhi/host/main.c
+diff --git a/drivers/bus/mhi/pci_generic.c b/drivers/bus/mhi/host/pci_generic.c
+similarity index 100%
+rename from drivers/bus/mhi/pci_generic.c
+rename to drivers/bus/mhi/host/pci_generic.c
+diff --git a/drivers/bus/mhi/core/pm.c b/drivers/bus/mhi/host/pm.c
+similarity index 100%
+rename from drivers/bus/mhi/core/pm.c
+rename to drivers/bus/mhi/host/pm.c
+--
+2.39.2
+
--- /dev/null
+From e2f16238d3d5b418689c908c491607162d77507c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 28 Mar 2023 15:16:36 +0000
+Subject: crypto: ccp - Clear PSP interrupt status register before calling
+ handler
+
+From: Jeremi Piotrowski <jpiotrowski@linux.microsoft.com>
+
+[ Upstream commit 45121ad4a1750ca47ce3f32bd434bdb0cdbf0043 ]
+
+The PSP IRQ is edge-triggered (MSI or MSI-X) in all cases supported by
+the psp module so clear the interrupt status register early in the
+handler to prevent missed interrupts. sev_irq_handler() calls wake_up()
+on a wait queue, which can result in a new command being submitted from
+a different CPU. This then races with the clearing of isr and can result
+in missed interrupts. A missed interrupt results in a command waiting
+until it times out, which results in the psp being declared dead.
+
+This is unlikely on bare metal, but has been observed when running
+virtualized. In the cases where this is observed, sev->cmdresp_reg has
+PSP_CMDRESP_RESP set which indicates that the command was processed
+correctly but no interrupt was asserted.
+
+The full sequence of events looks like this:
+
+CPU 1: submits SEV cmd #1
+CPU 1: calls wait_event_timeout()
+CPU 0: enters psp_irq_handler()
+CPU 0: calls sev_handler()->wake_up()
+CPU 1: wakes up; finishes processing cmd #1
+CPU 1: submits SEV cmd #2
+CPU 1: calls wait_event_timeout()
+PSP: finishes processing cmd #2; interrupt status is still set; no interrupt
+CPU 0: clears intsts
+CPU 0: exits psp_irq_handler()
+CPU 1: wait_event_timeout() times out; psp_dead=true
+
+Fixes: 200664d5237f ("crypto: ccp: Add Secure Encrypted Virtualization (SEV) command support")
+Cc: stable@vger.kernel.org
+Signed-off-by: Jeremi Piotrowski <jpiotrowski@linux.microsoft.com>
+Acked-by: Tom Lendacky <thomas.lendacky@amd.com>
+Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/crypto/ccp/psp-dev.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/crypto/ccp/psp-dev.c b/drivers/crypto/ccp/psp-dev.c
+index ae7b445999144..4bf9eaab4456f 100644
+--- a/drivers/crypto/ccp/psp-dev.c
++++ b/drivers/crypto/ccp/psp-dev.c
+@@ -42,6 +42,9 @@ static irqreturn_t psp_irq_handler(int irq, void *data)
+ /* Read the interrupt status: */
+ status = ioread32(psp->io_regs + psp->vdata->intsts_reg);
+
++ /* Clear the interrupt status by writing the same value we read. */
++ iowrite32(status, psp->io_regs + psp->vdata->intsts_reg);
++
+ /* invoke subdevice interrupt handlers */
+ if (status) {
+ if (psp->sev_irq_handler)
+@@ -51,9 +54,6 @@ static irqreturn_t psp_irq_handler(int irq, void *data)
+ psp->tee_irq_handler(irq, psp->tee_irq_data, status);
+ }
+
+- /* Clear the interrupt status by writing the same value we read. */
+- iowrite32(status, psp->io_regs + psp->vdata->intsts_reg);
+-
+ return IRQ_HANDLED;
+ }
+
+--
+2.39.2
+
--- /dev/null
+From 3f8dcc1c1e3ddcc7dfa6beb71863a66eb07daded Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 20 Mar 2023 15:59:32 +0900
+Subject: dm verity: fix error handling for check_at_most_once on FEC
+
+From: Yeongjin Gil <youngjin.gil@samsung.com>
+
+[ Upstream commit e8c5d45f82ce0c238a4817739892fe8897a3dcc3 ]
+
+In verity_end_io(), if bi_status is not BLK_STS_OK, it can be return
+directly. But if FEC configured, it is desired to correct the data page
+through verity_verify_io. And the return value will be converted to
+blk_status and passed to verity_finish_io().
+
+BTW, when a bit is set in v->validated_blocks, verity_verify_io() skips
+verification regardless of I/O error for the corresponding bio. In this
+case, the I/O error could not be returned properly, and as a result,
+there is a problem that abnormal data could be read for the
+corresponding block.
+
+To fix this problem, when an I/O error occurs, do not skip verification
+even if the bit related is set in v->validated_blocks.
+
+Fixes: 843f38d382b1 ("dm verity: add 'check_at_most_once' option to only validate hashes once")
+Cc: stable@vger.kernel.org
+Reviewed-by: Sungjong Seo <sj1557.seo@samsung.com>
+Signed-off-by: Yeongjin Gil <youngjin.gil@samsung.com>
+Signed-off-by: Mike Snitzer <snitzer@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-verity-target.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
+index d9c388e6ce76c..0c2048d2b847e 100644
+--- a/drivers/md/dm-verity-target.c
++++ b/drivers/md/dm-verity-target.c
+@@ -482,7 +482,7 @@ static int verity_verify_io(struct dm_verity_io *io)
+ sector_t cur_block = io->block + b;
+ struct ahash_request *req = verity_io_hash_req(v, io);
+
+- if (v->validated_blocks &&
++ if (v->validated_blocks && bio->bi_status == BLK_STS_OK &&
+ likely(test_bit(cur_block, v->validated_blocks))) {
+ verity_bv_skip_block(v, io, &io->iter);
+ continue;
+--
+2.39.2
+
--- /dev/null
+From 7635f7aa2fa037de98c77a081dde4219e99edaf7 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 13 Sep 2021 09:26:42 +0000
+Subject: dm verity: skip redundant verity_handle_err() on I/O errors
+
+From: Akilesh Kailash <akailash@google.com>
+
+[ Upstream commit 2c0468e054c0adb660ac055fc396622ec7235df9 ]
+
+Without FEC, dm-verity won't call verity_handle_err() when I/O fails,
+but with FEC enabled, it currently does even if an I/O error has
+occurred.
+
+If there is an I/O error and FEC correction fails, return the error
+instead of calling verity_handle_err() again.
+
+Suggested-by: Sami Tolvanen <samitolvanen@google.com>
+Signed-off-by: Akilesh Kailash <akailash@google.com>
+Reviewed-by: Sami Tolvanen <samitolvanen@google.com>
+Signed-off-by: Mike Snitzer <snitzer@redhat.com>
+Stable-dep-of: e8c5d45f82ce ("dm verity: fix error handling for check_at_most_once on FEC")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/md/dm-verity-target.c | 15 ++++++++++++---
+ 1 file changed, 12 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/md/dm-verity-target.c b/drivers/md/dm-verity-target.c
+index c801f6b93b7b4..d9c388e6ce76c 100644
+--- a/drivers/md/dm-verity-target.c
++++ b/drivers/md/dm-verity-target.c
+@@ -475,6 +475,7 @@ static int verity_verify_io(struct dm_verity_io *io)
+ struct bvec_iter start;
+ unsigned b;
+ struct crypto_wait wait;
++ struct bio *bio = dm_bio_from_per_bio_data(io, v->ti->per_io_data_size);
+
+ for (b = 0; b < io->n_blocks; b++) {
+ int r;
+@@ -529,9 +530,17 @@ static int verity_verify_io(struct dm_verity_io *io)
+ else if (verity_fec_decode(v, io, DM_VERITY_BLOCK_TYPE_DATA,
+ cur_block, NULL, &start) == 0)
+ continue;
+- else if (verity_handle_err(v, DM_VERITY_BLOCK_TYPE_DATA,
+- cur_block))
+- return -EIO;
++ else {
++ if (bio->bi_status) {
++ /*
++ * Error correction failed; Just return error
++ */
++ return -EIO;
++ }
++ if (verity_handle_err(v, DM_VERITY_BLOCK_TYPE_DATA,
++ cur_block))
++ return -EIO;
++ }
+ }
+
+ return 0;
+--
+2.39.2
+
--- /dev/null
+From a4f1f128b99c9fba1cacf1ca7220b71ccad4c799 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 20 Nov 2022 09:25:54 +0100
+Subject: mailbox: zynq: Switch to flexible array to simplify code
+
+From: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+
+[ Upstream commit 043f85ce81cb1714e14d31c322c5646513dde3fb ]
+
+Using flexible array is more straight forward. It
+ - saves 1 pointer in the 'zynqmp_ipi_pdata' structure
+ - saves an indirection when using this array
+ - saves some LoC and avoids some always spurious pointer arithmetic
+
+Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
+Signed-off-by: Jassi Brar <jaswinder.singh@linaro.org>
+Stable-dep-of: f72f805e7288 ("mailbox: zynqmp: Fix counts of child nodes")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mailbox/zynqmp-ipi-mailbox.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/mailbox/zynqmp-ipi-mailbox.c b/drivers/mailbox/zynqmp-ipi-mailbox.c
+index 05e36229622e3..136a84ad871cc 100644
+--- a/drivers/mailbox/zynqmp-ipi-mailbox.c
++++ b/drivers/mailbox/zynqmp-ipi-mailbox.c
+@@ -110,7 +110,7 @@ struct zynqmp_ipi_pdata {
+ unsigned int method;
+ u32 local_id;
+ int num_mboxes;
+- struct zynqmp_ipi_mbox *ipi_mboxes;
++ struct zynqmp_ipi_mbox ipi_mboxes[];
+ };
+
+ static struct device_driver zynqmp_ipi_mbox_driver = {
+@@ -635,7 +635,7 @@ static int zynqmp_ipi_probe(struct platform_device *pdev)
+ int num_mboxes, ret = -EINVAL;
+
+ num_mboxes = of_get_child_count(np);
+- pdata = devm_kzalloc(dev, sizeof(*pdata) + (num_mboxes * sizeof(*mbox)),
++ pdata = devm_kzalloc(dev, struct_size(pdata, ipi_mboxes, num_mboxes),
+ GFP_KERNEL);
+ if (!pdata)
+ return -ENOMEM;
+@@ -649,8 +649,6 @@ static int zynqmp_ipi_probe(struct platform_device *pdev)
+ }
+
+ pdata->num_mboxes = num_mboxes;
+- pdata->ipi_mboxes = (struct zynqmp_ipi_mbox *)
+- ((char *)pdata + sizeof(*pdata));
+
+ mbox = pdata->ipi_mboxes;
+ for_each_available_child_of_node(np, nc) {
+--
+2.39.2
+
--- /dev/null
+From 161fadf64f3d03ff02d2a1bc90d17576ae7b8374 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 10 Mar 2023 17:24:04 -0800
+Subject: mailbox: zynqmp: Fix counts of child nodes
+
+From: Tanmay Shah <tanmay.shah@amd.com>
+
+[ Upstream commit f72f805e72882c361e2a612c64a6e549f3da7152 ]
+
+If child mailbox node status is disabled it causes
+crash in interrupt handler. Fix this by assigning
+only available child node during driver probe.
+
+Fixes: 4981b82ba2ff ("mailbox: ZynqMP IPI mailbox controller")
+Signed-off-by: Tanmay Shah <tanmay.shah@amd.com>
+Acked-by: Michal Simek <michal.simek@amd.com>
+Cc: stable@vger.kernel.org
+Link: https://lore.kernel.org/r/20230311012407.1292118-2-tanmay.shah@amd.com
+Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/mailbox/zynqmp-ipi-mailbox.c | 7 ++++++-
+ 1 file changed, 6 insertions(+), 1 deletion(-)
+
+diff --git a/drivers/mailbox/zynqmp-ipi-mailbox.c b/drivers/mailbox/zynqmp-ipi-mailbox.c
+index 136a84ad871cc..be06de791c544 100644
+--- a/drivers/mailbox/zynqmp-ipi-mailbox.c
++++ b/drivers/mailbox/zynqmp-ipi-mailbox.c
+@@ -634,7 +634,12 @@ static int zynqmp_ipi_probe(struct platform_device *pdev)
+ struct zynqmp_ipi_mbox *mbox;
+ int num_mboxes, ret = -EINVAL;
+
+- num_mboxes = of_get_child_count(np);
++ num_mboxes = of_get_available_child_count(np);
++ if (num_mboxes == 0) {
++ dev_err(dev, "mailbox nodes not available\n");
++ return -EINVAL;
++ }
++
+ pdata = devm_kzalloc(dev, struct_size(pdata, ipi_mboxes, num_mboxes),
+ GFP_KERNEL);
+ if (!pdata)
+--
+2.39.2
+
--- /dev/null
+From 5550b9391d989815469ac923e65bf8f87c2b477c Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 26 Apr 2023 14:20:23 +0800
+Subject: ring-buffer: Ensure proper resetting of atomic variables in
+ ring_buffer_reset_online_cpus
+
+From: Tze-nan Wu <Tze-nan.Wu@mediatek.com>
+
+[ Upstream commit 7c339fb4d8577792378136c15fde773cfb863cb8 ]
+
+In ring_buffer_reset_online_cpus, the buffer_size_kb write operation
+may permanently fail if the cpu_online_mask changes between two
+for_each_online_buffer_cpu loops. The number of increases and decreases
+on both cpu_buffer->resize_disabled and cpu_buffer->record_disabled may be
+inconsistent, causing some CPUs to have non-zero values for these atomic
+variables after the function returns.
+
+This issue can be reproduced by "echo 0 > trace" while hotplugging cpu.
+After reproducing success, we can find out buffer_size_kb will not be
+functional anymore.
+
+To prevent leaving 'resize_disabled' and 'record_disabled' non-zero after
+ring_buffer_reset_online_cpus returns, we ensure that each atomic variable
+has been set up before atomic_sub() to it.
+
+Link: https://lore.kernel.org/linux-trace-kernel/20230426062027.17451-1-Tze-nan.Wu@mediatek.com
+
+Cc: stable@vger.kernel.org
+Cc: <mhiramat@kernel.org>
+Cc: npiggin@gmail.com
+Fixes: b23d7a5f4a07 ("ring-buffer: speed up buffer resets by avoiding synchronize_rcu for each CPU")
+Reviewed-by: Cheng-Jui Wang <cheng-jui.wang@mediatek.com>
+Signed-off-by: Tze-nan Wu <Tze-nan.Wu@mediatek.com>
+Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ kernel/trace/ring_buffer.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/kernel/trace/ring_buffer.c b/kernel/trace/ring_buffer.c
+index 1fe6b29366f10..f08904914166b 100644
+--- a/kernel/trace/ring_buffer.c
++++ b/kernel/trace/ring_buffer.c
+@@ -5051,6 +5051,9 @@ void ring_buffer_reset_cpu(struct trace_buffer *buffer, int cpu)
+ }
+ EXPORT_SYMBOL_GPL(ring_buffer_reset_cpu);
+
++/* Flag to ensure proper resetting of atomic variables */
++#define RESET_BIT (1 << 30)
++
+ /**
+ * ring_buffer_reset_cpu - reset a ring buffer per CPU buffer
+ * @buffer: The ring buffer to reset a per cpu buffer of
+@@ -5067,20 +5070,27 @@ void ring_buffer_reset_online_cpus(struct trace_buffer *buffer)
+ for_each_online_buffer_cpu(buffer, cpu) {
+ cpu_buffer = buffer->buffers[cpu];
+
+- atomic_inc(&cpu_buffer->resize_disabled);
++ atomic_add(RESET_BIT, &cpu_buffer->resize_disabled);
+ atomic_inc(&cpu_buffer->record_disabled);
+ }
+
+ /* Make sure all commits have finished */
+ synchronize_rcu();
+
+- for_each_online_buffer_cpu(buffer, cpu) {
++ for_each_buffer_cpu(buffer, cpu) {
+ cpu_buffer = buffer->buffers[cpu];
+
++ /*
++ * If a CPU came online during the synchronize_rcu(), then
++ * ignore it.
++ */
++ if (!(atomic_read(&cpu_buffer->resize_disabled) & RESET_BIT))
++ continue;
++
+ reset_disabled_cpu_buffer(cpu_buffer);
+
+ atomic_dec(&cpu_buffer->record_disabled);
+- atomic_dec(&cpu_buffer->resize_disabled);
++ atomic_sub(RESET_BIT, &cpu_buffer->resize_disabled);
+ }
+
+ mutex_unlock(&buffer->mutex);
+--
+2.39.2
+
arm64-dts-qcom-sdm845-correct-dynamic-power-coefficients.patch
scsi-target-core-avoid-smp_processor_id-in-preemptible-code.patch
netfilter-nf_tables-deactivate-anonymous-set-from-preparation-phase.patch
+tty-create-internal-tty.h-file.patch
+tty-audit-move-some-local-functions-out-of-tty.h.patch
+tty-move-some-internal-tty-lock-enums-and-functions-.patch
+tty-move-some-tty-only-functions-to-drivers-tty-tty..patch
+tty-clean-include-linux-tty.h-up.patch
+tty-prevent-writing-chars-during-tcsetattr-tcsadrain.patch
+ring-buffer-ensure-proper-resetting-of-atomic-variab.patch
+crypto-ccp-clear-psp-interrupt-status-register-befor.patch
+mailbox-zynq-switch-to-flexible-array-to-simplify-co.patch
+mailbox-zynqmp-fix-counts-of-child-nodes.patch
+dm-verity-skip-redundant-verity_handle_err-on-i-o-er.patch
+dm-verity-fix-error-handling-for-check_at_most_once-.patch
+bus-mhi-add-mhi-pci-support-for-wwan-modems.patch
+bus-mhi-add-mmio-region-length-to-controller-structu.patch
+bus-mhi-move-host-mhi-code-to-host-directory.patch
+bus-mhi-host-range-check-chdboff-and-erdboff.patch
--- /dev/null
+From 0d423bc5c3c2759150160553eaf7de7f4d527058 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Apr 2021 14:51:29 +0200
+Subject: tty: audit: move some local functions out of tty.h
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+[ Upstream commit da5d669e00d2c437b3f508d60add417fc74f4bb6 ]
+
+The functions tty_audit_add_data() and tty_audit_tiocsti() are local to
+the tty core code, and do not need to be in a "kernel-wide" header file
+so move them to drivers/tty/tty.h
+
+Cc: Jiri Slaby <jirislaby@kernel.org>
+Link: https://lore.kernel.org/r/20210408125134.3016837-9-gregkh@linuxfoundation.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 094fb49a2d0d ("tty: Prevent writing chars during tcsetattr TCSADRAIN/FLUSH")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/tty.h | 14 ++++++++++++++
+ drivers/tty/tty_audit.c | 1 +
+ include/linux/tty.h | 10 ----------
+ 3 files changed, 15 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/tty/tty.h b/drivers/tty/tty.h
+index f4cd20261e914..f131d538b62b9 100644
+--- a/drivers/tty/tty.h
++++ b/drivers/tty/tty.h
+@@ -18,4 +18,18 @@
+ #define tty_info_ratelimited(tty, f, ...) \
+ tty_msg(pr_info_ratelimited, tty, f, ##__VA_ARGS__)
+
++/* tty_audit.c */
++#ifdef CONFIG_AUDIT
++void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size);
++void tty_audit_tiocsti(struct tty_struct *tty, char ch);
++#else
++static inline void tty_audit_add_data(struct tty_struct *tty, const void *data,
++ size_t size)
++{
++}
++static inline void tty_audit_tiocsti(struct tty_struct *tty, char ch)
++{
++}
++#endif
++
+ #endif
+diff --git a/drivers/tty/tty_audit.c b/drivers/tty/tty_audit.c
+index 9f906a5b8e810..9b30edee71fe9 100644
+--- a/drivers/tty/tty_audit.c
++++ b/drivers/tty/tty_audit.c
+@@ -10,6 +10,7 @@
+ #include <linux/audit.h>
+ #include <linux/slab.h>
+ #include <linux/tty.h>
++#include "tty.h"
+
+ struct tty_audit_buf {
+ struct mutex mutex; /* Protects all data below */
+diff --git a/include/linux/tty.h b/include/linux/tty.h
+index 9e3725589214e..a1a9c4b8210ea 100644
+--- a/include/linux/tty.h
++++ b/include/linux/tty.h
+@@ -731,20 +731,10 @@ static inline void n_tty_init(void) { }
+
+ /* tty_audit.c */
+ #ifdef CONFIG_AUDIT
+-extern void tty_audit_add_data(struct tty_struct *tty, const void *data,
+- size_t size);
+ extern void tty_audit_exit(void);
+ extern void tty_audit_fork(struct signal_struct *sig);
+-extern void tty_audit_tiocsti(struct tty_struct *tty, char ch);
+ extern int tty_audit_push(void);
+ #else
+-static inline void tty_audit_add_data(struct tty_struct *tty, const void *data,
+- size_t size)
+-{
+-}
+-static inline void tty_audit_tiocsti(struct tty_struct *tty, char ch)
+-{
+-}
+ static inline void tty_audit_exit(void)
+ {
+ }
+--
+2.39.2
+
--- /dev/null
+From fa08aea744f9685e1415b03dc5ad953394c627dd Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Apr 2021 14:51:34 +0200
+Subject: tty: clean include/linux/tty.h up
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+[ Upstream commit 5ffa6e344a1c92a27c242f500fc74e6eb361a4bc ]
+
+There are a lot of tty-core-only functions that are listed in
+include/linux/tty.h. Move them to drivers/tty/tty.h so that no one else
+can accidentally call them or think that they are public functions.
+
+Cc: Jiri Slaby <jirislaby@kernel.org>
+Link: https://lore.kernel.org/r/20210408125134.3016837-14-gregkh@linuxfoundation.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 094fb49a2d0d ("tty: Prevent writing chars during tcsetattr TCSADRAIN/FLUSH")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/n_gsm.c | 1 +
+ drivers/tty/n_hdlc.c | 1 +
+ drivers/tty/tty.h | 37 +++++++++++++++++++++++++++++++++++++
+ drivers/tty/tty_baudrate.c | 1 +
+ include/linux/tty.h | 33 ---------------------------------
+ 5 files changed, 40 insertions(+), 33 deletions(-)
+
+diff --git a/drivers/tty/n_gsm.c b/drivers/tty/n_gsm.c
+index f5063499f9cf6..23b014b8c9199 100644
+--- a/drivers/tty/n_gsm.c
++++ b/drivers/tty/n_gsm.c
+@@ -50,6 +50,7 @@
+ #include <linux/netdevice.h>
+ #include <linux/etherdevice.h>
+ #include <linux/gsmmux.h>
++#include "tty.h"
+
+ static int debug;
+ module_param(debug, int, 0600);
+diff --git a/drivers/tty/n_hdlc.c b/drivers/tty/n_hdlc.c
+index 48c64e68017cd..697199a3ca019 100644
+--- a/drivers/tty/n_hdlc.c
++++ b/drivers/tty/n_hdlc.c
+@@ -100,6 +100,7 @@
+
+ #include <asm/termios.h>
+ #include <linux/uaccess.h>
++#include "tty.h"
+
+ /*
+ * Buffers for individual HDLC frames
+diff --git a/drivers/tty/tty.h b/drivers/tty/tty.h
+index 9eda9e5f8ad5e..74ed99bc5449a 100644
+--- a/drivers/tty/tty.h
++++ b/drivers/tty/tty.h
+@@ -59,6 +59,43 @@ static inline void tty_set_flow_change(struct tty_struct *tty, int val)
+ int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout);
+ void tty_ldisc_unlock(struct tty_struct *tty);
+
++int __tty_check_change(struct tty_struct *tty, int sig);
++int tty_check_change(struct tty_struct *tty);
++void __stop_tty(struct tty_struct *tty);
++void __start_tty(struct tty_struct *tty);
++void tty_vhangup_session(struct tty_struct *tty);
++void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty);
++int tty_signal_session_leader(struct tty_struct *tty, int exit_session);
++void session_clear_tty(struct pid *session);
++void tty_buffer_free_all(struct tty_port *port);
++void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld);
++void tty_buffer_init(struct tty_port *port);
++void tty_buffer_set_lock_subclass(struct tty_port *port);
++bool tty_buffer_restart_work(struct tty_port *port);
++bool tty_buffer_cancel_work(struct tty_port *port);
++void tty_buffer_flush_work(struct tty_port *port);
++speed_t tty_termios_input_baud_rate(struct ktermios *termios);
++void tty_ldisc_hangup(struct tty_struct *tty, bool reset);
++int tty_ldisc_reinit(struct tty_struct *tty, int disc);
++long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
++long tty_jobctrl_ioctl(struct tty_struct *tty, struct tty_struct *real_tty,
++ struct file *file, unsigned int cmd, unsigned long arg);
++void tty_default_fops(struct file_operations *fops);
++struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx);
++int tty_alloc_file(struct file *file);
++void tty_add_file(struct tty_struct *tty, struct file *file);
++void tty_free_file(struct file *file);
++int tty_release(struct inode *inode, struct file *filp);
++
++#define tty_is_writelocked(tty) (mutex_is_locked(&tty->atomic_write_lock))
++
++int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty);
++void tty_ldisc_release(struct tty_struct *tty);
++int __must_check tty_ldisc_init(struct tty_struct *tty);
++void tty_ldisc_deinit(struct tty_struct *tty);
++
++void tty_sysctl_init(void);
++
+ /* tty_audit.c */
+ #ifdef CONFIG_AUDIT
+ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size);
+diff --git a/drivers/tty/tty_baudrate.c b/drivers/tty/tty_baudrate.c
+index 84fec3c62d6a4..9d0093d84e085 100644
+--- a/drivers/tty/tty_baudrate.c
++++ b/drivers/tty/tty_baudrate.c
+@@ -8,6 +8,7 @@
+ #include <linux/termios.h>
+ #include <linux/tty.h>
+ #include <linux/export.h>
++#include "tty.h"
+
+
+ /*
+diff --git a/include/linux/tty.h b/include/linux/tty.h
+index a641fc6a7fa8b..e51d75f5165b5 100644
+--- a/include/linux/tty.h
++++ b/include/linux/tty.h
+@@ -432,11 +432,7 @@ static inline struct tty_struct *tty_kref_get(struct tty_struct *tty)
+
+ extern const char *tty_driver_name(const struct tty_struct *tty);
+ extern void tty_wait_until_sent(struct tty_struct *tty, long timeout);
+-extern int __tty_check_change(struct tty_struct *tty, int sig);
+-extern int tty_check_change(struct tty_struct *tty);
+-extern void __stop_tty(struct tty_struct *tty);
+ extern void stop_tty(struct tty_struct *tty);
+-extern void __start_tty(struct tty_struct *tty);
+ extern void start_tty(struct tty_struct *tty);
+ extern int tty_register_driver(struct tty_driver *driver);
+ extern int tty_unregister_driver(struct tty_driver *driver);
+@@ -461,23 +457,11 @@ extern int tty_do_resize(struct tty_struct *tty, struct winsize *ws);
+ extern int is_current_pgrp_orphaned(void);
+ extern void tty_hangup(struct tty_struct *tty);
+ extern void tty_vhangup(struct tty_struct *tty);
+-extern void tty_vhangup_session(struct tty_struct *tty);
+ extern int tty_hung_up_p(struct file *filp);
+ extern void do_SAK(struct tty_struct *tty);
+ extern void __do_SAK(struct tty_struct *tty);
+-extern void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty);
+-extern int tty_signal_session_leader(struct tty_struct *tty, int exit_session);
+-extern void session_clear_tty(struct pid *session);
+ extern void no_tty(void);
+-extern void tty_buffer_free_all(struct tty_port *port);
+-extern void tty_buffer_flush(struct tty_struct *tty, struct tty_ldisc *ld);
+-extern void tty_buffer_init(struct tty_port *port);
+-extern void tty_buffer_set_lock_subclass(struct tty_port *port);
+-extern bool tty_buffer_restart_work(struct tty_port *port);
+-extern bool tty_buffer_cancel_work(struct tty_port *port);
+-extern void tty_buffer_flush_work(struct tty_port *port);
+ extern speed_t tty_termios_baud_rate(struct ktermios *termios);
+-extern speed_t tty_termios_input_baud_rate(struct ktermios *termios);
+ extern void tty_termios_encode_baud_rate(struct ktermios *termios,
+ speed_t ibaud, speed_t obaud);
+ extern void tty_encode_baud_rate(struct tty_struct *tty,
+@@ -505,27 +489,16 @@ extern int tty_set_termios(struct tty_struct *tty, struct ktermios *kt);
+ extern struct tty_ldisc *tty_ldisc_ref(struct tty_struct *);
+ extern void tty_ldisc_deref(struct tty_ldisc *);
+ extern struct tty_ldisc *tty_ldisc_ref_wait(struct tty_struct *);
+-extern void tty_ldisc_hangup(struct tty_struct *tty, bool reset);
+-extern int tty_ldisc_reinit(struct tty_struct *tty, int disc);
+ extern const struct seq_operations tty_ldiscs_seq_ops;
+
+ extern void tty_wakeup(struct tty_struct *tty);
+ extern void tty_ldisc_flush(struct tty_struct *tty);
+
+-extern long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+ extern int tty_mode_ioctl(struct tty_struct *tty, struct file *file,
+ unsigned int cmd, unsigned long arg);
+-extern long tty_jobctrl_ioctl(struct tty_struct *tty, struct tty_struct *real_tty,
+- struct file *file, unsigned int cmd, unsigned long arg);
+ extern int tty_perform_flush(struct tty_struct *tty, unsigned long arg);
+-extern void tty_default_fops(struct file_operations *fops);
+-extern struct tty_struct *alloc_tty_struct(struct tty_driver *driver, int idx);
+-extern int tty_alloc_file(struct file *file);
+-extern void tty_add_file(struct tty_struct *tty, struct file *file);
+-extern void tty_free_file(struct file *file);
+ extern struct tty_struct *tty_init_dev(struct tty_driver *driver, int idx);
+ extern void tty_release_struct(struct tty_struct *tty, int idx);
+-extern int tty_release(struct inode *inode, struct file *filp);
+ extern void tty_init_termios(struct tty_struct *tty);
+ extern void tty_save_termios(struct tty_struct *tty);
+ extern int tty_standard_install(struct tty_driver *driver,
+@@ -533,8 +506,6 @@ extern int tty_standard_install(struct tty_driver *driver,
+
+ extern struct mutex tty_mutex;
+
+-#define tty_is_writelocked(tty) (mutex_is_locked(&tty->atomic_write_lock))
+-
+ extern void tty_port_init(struct tty_port *port);
+ extern void tty_port_link_device(struct tty_port *port,
+ struct tty_driver *driver, unsigned index);
+@@ -672,10 +643,6 @@ static inline int tty_port_users(struct tty_port *port)
+ extern int tty_register_ldisc(int disc, struct tty_ldisc_ops *new_ldisc);
+ extern int tty_unregister_ldisc(int disc);
+ extern int tty_set_ldisc(struct tty_struct *tty, int disc);
+-extern int tty_ldisc_setup(struct tty_struct *tty, struct tty_struct *o_tty);
+-extern void tty_ldisc_release(struct tty_struct *tty);
+-extern int __must_check tty_ldisc_init(struct tty_struct *tty);
+-extern void tty_ldisc_deinit(struct tty_struct *tty);
+ extern int tty_ldisc_receive_buf(struct tty_ldisc *ld, const unsigned char *p,
+ char *f, int count);
+
+--
+2.39.2
+
--- /dev/null
+From fb4bcfcc709fb8749e2b59ee2ef73d17e9682c07 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Apr 2021 14:51:22 +0200
+Subject: tty: create internal tty.h file
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+[ Upstream commit 98602c010ceba82f2c2384122dbd07bc965fd367 ]
+
+There are a number of functions and #defines in include/linux/tty.h that
+do not belong there as they are private to the tty core code.
+
+Create an initial drivers/tty/tty.h file and copy the odd "tty logging"
+macros into it to seed the file with some initial things that we know
+nothing outside of the tty core should be calling.
+
+Cc: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
+Cc: Jiri Slaby <jirislaby@kernel.org>
+Link: https://lore.kernel.org/r/20210408125134.3016837-2-gregkh@linuxfoundation.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 094fb49a2d0d ("tty: Prevent writing chars during tcsetattr TCSADRAIN/FLUSH")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/n_tty.c | 1 +
+ drivers/tty/pty.c | 1 +
+ drivers/tty/tty.h | 21 +++++++++++++++++++++
+ drivers/tty/tty_io.c | 1 +
+ drivers/tty/tty_jobctrl.c | 1 +
+ drivers/tty/tty_ldisc.c | 1 +
+ drivers/tty/tty_port.c | 1 +
+ include/linux/tty.h | 12 ------------
+ 8 files changed, 27 insertions(+), 12 deletions(-)
+ create mode 100644 drivers/tty/tty.h
+
+diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
+index 12dde01e576b5..8e7931d935438 100644
+--- a/drivers/tty/n_tty.c
++++ b/drivers/tty/n_tty.c
+@@ -49,6 +49,7 @@
+ #include <linux/module.h>
+ #include <linux/ratelimit.h>
+ #include <linux/vmalloc.h>
++#include "tty.h"
+
+ /*
+ * Until this number of characters is queued in the xmit buffer, select will
+diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
+index 16498f5fba64d..ca3e5a6c1a497 100644
+--- a/drivers/tty/pty.c
++++ b/drivers/tty/pty.c
+@@ -29,6 +29,7 @@
+ #include <linux/file.h>
+ #include <linux/ioctl.h>
+ #include <linux/compat.h>
++#include "tty.h"
+
+ #undef TTY_DEBUG_HANGUP
+ #ifdef TTY_DEBUG_HANGUP
+diff --git a/drivers/tty/tty.h b/drivers/tty/tty.h
+new file mode 100644
+index 0000000000000..f4cd20261e914
+--- /dev/null
++++ b/drivers/tty/tty.h
+@@ -0,0 +1,21 @@
++/* SPDX-License-Identifier: GPL-2.0 */
++/*
++ * TTY core internal functions
++ */
++
++#ifndef _TTY_INTERNAL_H
++#define _TTY_INTERNAL_H
++
++#define tty_msg(fn, tty, f, ...) \
++ fn("%s %s: " f, tty_driver_name(tty), tty_name(tty), ##__VA_ARGS__)
++
++#define tty_debug(tty, f, ...) tty_msg(pr_debug, tty, f, ##__VA_ARGS__)
++#define tty_info(tty, f, ...) tty_msg(pr_info, tty, f, ##__VA_ARGS__)
++#define tty_notice(tty, f, ...) tty_msg(pr_notice, tty, f, ##__VA_ARGS__)
++#define tty_warn(tty, f, ...) tty_msg(pr_warn, tty, f, ##__VA_ARGS__)
++#define tty_err(tty, f, ...) tty_msg(pr_err, tty, f, ##__VA_ARGS__)
++
++#define tty_info_ratelimited(tty, f, ...) \
++ tty_msg(pr_info_ratelimited, tty, f, ##__VA_ARGS__)
++
++#endif
+diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
+index c37d2657308cd..86fbfe42ce0ac 100644
+--- a/drivers/tty/tty_io.c
++++ b/drivers/tty/tty_io.c
+@@ -108,6 +108,7 @@
+
+ #include <linux/kmod.h>
+ #include <linux/nsproxy.h>
++#include "tty.h"
+
+ #undef TTY_DEBUG_HANGUP
+ #ifdef TTY_DEBUG_HANGUP
+diff --git a/drivers/tty/tty_jobctrl.c b/drivers/tty/tty_jobctrl.c
+index aa6d0537b379e..95d67613b25b6 100644
+--- a/drivers/tty/tty_jobctrl.c
++++ b/drivers/tty/tty_jobctrl.c
+@@ -11,6 +11,7 @@
+ #include <linux/tty.h>
+ #include <linux/fcntl.h>
+ #include <linux/uaccess.h>
++#include "tty.h"
+
+ static int is_ignored(int sig)
+ {
+diff --git a/drivers/tty/tty_ldisc.c b/drivers/tty/tty_ldisc.c
+index fe37ec331289b..c23938b8628d1 100644
+--- a/drivers/tty/tty_ldisc.c
++++ b/drivers/tty/tty_ldisc.c
+@@ -19,6 +19,7 @@
+ #include <linux/seq_file.h>
+ #include <linux/uaccess.h>
+ #include <linux/ratelimit.h>
++#include "tty.h"
+
+ #undef LDISC_DEBUG_HANGUP
+
+diff --git a/drivers/tty/tty_port.c b/drivers/tty/tty_port.c
+index ea80bf872f543..cbb56f725bc4a 100644
+--- a/drivers/tty/tty_port.c
++++ b/drivers/tty/tty_port.c
+@@ -18,6 +18,7 @@
+ #include <linux/delay.h>
+ #include <linux/module.h>
+ #include <linux/serdev.h>
++#include "tty.h"
+
+ static int tty_port_default_receive_buf(struct tty_port *port,
+ const unsigned char *p,
+diff --git a/include/linux/tty.h b/include/linux/tty.h
+index 5972f43b9d5ae..9e3725589214e 100644
+--- a/include/linux/tty.h
++++ b/include/linux/tty.h
+@@ -786,16 +786,4 @@ static inline void proc_tty_register_driver(struct tty_driver *d) {}
+ static inline void proc_tty_unregister_driver(struct tty_driver *d) {}
+ #endif
+
+-#define tty_msg(fn, tty, f, ...) \
+- fn("%s %s: " f, tty_driver_name(tty), tty_name(tty), ##__VA_ARGS__)
+-
+-#define tty_debug(tty, f, ...) tty_msg(pr_debug, tty, f, ##__VA_ARGS__)
+-#define tty_info(tty, f, ...) tty_msg(pr_info, tty, f, ##__VA_ARGS__)
+-#define tty_notice(tty, f, ...) tty_msg(pr_notice, tty, f, ##__VA_ARGS__)
+-#define tty_warn(tty, f, ...) tty_msg(pr_warn, tty, f, ##__VA_ARGS__)
+-#define tty_err(tty, f, ...) tty_msg(pr_err, tty, f, ##__VA_ARGS__)
+-
+-#define tty_info_ratelimited(tty, f, ...) \
+- tty_msg(pr_info_ratelimited, tty, f, ##__VA_ARGS__)
+-
+ #endif
+--
+2.39.2
+
--- /dev/null
+From dd6e69f340b3611b32fcbedfaf3b150c4e80584d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Apr 2021 14:51:30 +0200
+Subject: tty: move some internal tty lock enums and functions out of tty.h
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+[ Upstream commit 6c80c0b94b94192d9a34b400f8237703c6475f4d ]
+
+Move the TTY_LOCK_* enums and tty_ldisc lock functions out of the global
+tty.h into the local header file to clean things up.
+
+Cc: Jiri Slaby <jirislaby@kernel.org>
+Link: https://lore.kernel.org/r/20210408125134.3016837-10-gregkh@linuxfoundation.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 094fb49a2d0d ("tty: Prevent writing chars during tcsetattr TCSADRAIN/FLUSH")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/tty.h | 26 ++++++++++++++++++++++++++
+ drivers/tty/tty_buffer.c | 2 +-
+ drivers/tty/tty_mutex.c | 1 +
+ include/linux/tty.h | 26 --------------------------
+ 4 files changed, 28 insertions(+), 27 deletions(-)
+
+diff --git a/drivers/tty/tty.h b/drivers/tty/tty.h
+index f131d538b62b9..552e263e02dfb 100644
+--- a/drivers/tty/tty.h
++++ b/drivers/tty/tty.h
+@@ -18,6 +18,32 @@
+ #define tty_info_ratelimited(tty, f, ...) \
+ tty_msg(pr_info_ratelimited, tty, f, ##__VA_ARGS__)
+
++/*
++ * Lock subclasses for tty locks
++ *
++ * TTY_LOCK_NORMAL is for normal ttys and master ptys.
++ * TTY_LOCK_SLAVE is for slave ptys only.
++ *
++ * Lock subclasses are necessary for handling nested locking with pty pairs.
++ * tty locks which use nested locking:
++ *
++ * legacy_mutex - Nested tty locks are necessary for releasing pty pairs.
++ * The stable lock order is master pty first, then slave pty.
++ * termios_rwsem - The stable lock order is tty_buffer lock->termios_rwsem.
++ * Subclassing this lock enables the slave pty to hold its
++ * termios_rwsem when claiming the master tty_buffer lock.
++ * tty_buffer lock - slave ptys can claim nested buffer lock when handling
++ * signal chars. The stable lock order is slave pty, then
++ * master.
++ */
++enum {
++ TTY_LOCK_NORMAL = 0,
++ TTY_LOCK_SLAVE,
++};
++
++int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout);
++void tty_ldisc_unlock(struct tty_struct *tty);
++
+ /* tty_audit.c */
+ #ifdef CONFIG_AUDIT
+ void tty_audit_add_data(struct tty_struct *tty, const void *data, size_t size);
+diff --git a/drivers/tty/tty_buffer.c b/drivers/tty/tty_buffer.c
+index 5bbc2e010b483..9f23798155573 100644
+--- a/drivers/tty/tty_buffer.c
++++ b/drivers/tty/tty_buffer.c
+@@ -17,7 +17,7 @@
+ #include <linux/delay.h>
+ #include <linux/module.h>
+ #include <linux/ratelimit.h>
+-
++#include "tty.h"
+
+ #define MIN_TTYB_SIZE 256
+ #define TTYB_ALIGN_MASK 255
+diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c
+index 2640635ee177d..393518a24cfe2 100644
+--- a/drivers/tty/tty_mutex.c
++++ b/drivers/tty/tty_mutex.c
+@@ -4,6 +4,7 @@
+ #include <linux/kallsyms.h>
+ #include <linux/semaphore.h>
+ #include <linux/sched.h>
++#include "tty.h"
+
+ /* Legacy tty mutex glue */
+
+diff --git a/include/linux/tty.h b/include/linux/tty.h
+index a1a9c4b8210ea..af398d0aa9fdc 100644
+--- a/include/linux/tty.h
++++ b/include/linux/tty.h
+@@ -16,30 +16,6 @@
+ #include <linux/llist.h>
+
+
+-/*
+- * Lock subclasses for tty locks
+- *
+- * TTY_LOCK_NORMAL is for normal ttys and master ptys.
+- * TTY_LOCK_SLAVE is for slave ptys only.
+- *
+- * Lock subclasses are necessary for handling nested locking with pty pairs.
+- * tty locks which use nested locking:
+- *
+- * legacy_mutex - Nested tty locks are necessary for releasing pty pairs.
+- * The stable lock order is master pty first, then slave pty.
+- * termios_rwsem - The stable lock order is tty_buffer lock->termios_rwsem.
+- * Subclassing this lock enables the slave pty to hold its
+- * termios_rwsem when claiming the master tty_buffer lock.
+- * tty_buffer lock - slave ptys can claim nested buffer lock when handling
+- * signal chars. The stable lock order is slave pty, then
+- * master.
+- */
+-
+-enum {
+- TTY_LOCK_NORMAL = 0,
+- TTY_LOCK_SLAVE,
+-};
+-
+ /*
+ * (Note: the *_driver.minor_start values 1, 64, 128, 192 are
+ * hardcoded at present.)
+@@ -419,8 +395,6 @@ extern const char *tty_name(const struct tty_struct *tty);
+ extern struct tty_struct *tty_kopen(dev_t device);
+ extern void tty_kclose(struct tty_struct *tty);
+ extern int tty_dev_name_to_number(const char *name, dev_t *number);
+-extern int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout);
+-extern void tty_ldisc_unlock(struct tty_struct *tty);
+ extern ssize_t redirected_tty_write(struct kiocb *, struct iov_iter *);
+ #else
+ static inline void tty_kref_put(struct tty_struct *tty)
+--
+2.39.2
+
--- /dev/null
+From 1ac68ce477bef50cf4e1bfaad0497e1124898492 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 8 Apr 2021 14:51:32 +0200
+Subject: tty: move some tty-only functions to drivers/tty/tty.h
+
+From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+
+[ Upstream commit 9f72cab1596327e1011ab4599c07b165e0fb45db ]
+
+The flow change and restricted_tty_write() logic is internal to the tty
+core only, so move it out of the include/linux/tty.h file.
+
+Cc: Jiri Slaby <jirislaby@kernel.org>
+Link: https://lore.kernel.org/r/20210408125134.3016837-12-gregkh@linuxfoundation.org
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: 094fb49a2d0d ("tty: Prevent writing chars during tcsetattr TCSADRAIN/FLUSH")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/tty.h | 17 +++++++++++++++++
+ drivers/tty/tty_ioctl.c | 1 +
+ include/linux/tty.h | 16 ----------------
+ 3 files changed, 18 insertions(+), 16 deletions(-)
+
+diff --git a/drivers/tty/tty.h b/drivers/tty/tty.h
+index 552e263e02dfb..9eda9e5f8ad5e 100644
+--- a/drivers/tty/tty.h
++++ b/drivers/tty/tty.h
+@@ -41,6 +41,21 @@ enum {
+ TTY_LOCK_SLAVE,
+ };
+
++/* Values for tty->flow_change */
++#define TTY_THROTTLE_SAFE 1
++#define TTY_UNTHROTTLE_SAFE 2
++
++static inline void __tty_set_flow_change(struct tty_struct *tty, int val)
++{
++ tty->flow_change = val;
++}
++
++static inline void tty_set_flow_change(struct tty_struct *tty, int val)
++{
++ tty->flow_change = val;
++ smp_mb();
++}
++
+ int tty_ldisc_lock(struct tty_struct *tty, unsigned long timeout);
+ void tty_ldisc_unlock(struct tty_struct *tty);
+
+@@ -58,4 +73,6 @@ static inline void tty_audit_tiocsti(struct tty_struct *tty, char ch)
+ }
+ #endif
+
++ssize_t redirected_tty_write(struct kiocb *, struct iov_iter *);
++
+ #endif
+diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
+index 803da2d111c8c..50e65784fbf77 100644
+--- a/drivers/tty/tty_ioctl.c
++++ b/drivers/tty/tty_ioctl.c
+@@ -21,6 +21,7 @@
+ #include <linux/bitops.h>
+ #include <linux/mutex.h>
+ #include <linux/compat.h>
++#include "tty.h"
+
+ #include <asm/io.h>
+ #include <linux/uaccess.h>
+diff --git a/include/linux/tty.h b/include/linux/tty.h
+index af398d0aa9fdc..a641fc6a7fa8b 100644
+--- a/include/linux/tty.h
++++ b/include/linux/tty.h
+@@ -350,21 +350,6 @@ struct tty_file_private {
+ #define TTY_LDISC_CHANGING 20 /* Change pending - non-block IO */
+ #define TTY_LDISC_HALTED 22 /* Line discipline is halted */
+
+-/* Values for tty->flow_change */
+-#define TTY_THROTTLE_SAFE 1
+-#define TTY_UNTHROTTLE_SAFE 2
+-
+-static inline void __tty_set_flow_change(struct tty_struct *tty, int val)
+-{
+- tty->flow_change = val;
+-}
+-
+-static inline void tty_set_flow_change(struct tty_struct *tty, int val)
+-{
+- tty->flow_change = val;
+- smp_mb();
+-}
+-
+ static inline bool tty_io_nonblock(struct tty_struct *tty, struct file *file)
+ {
+ return file->f_flags & O_NONBLOCK ||
+@@ -395,7 +380,6 @@ extern const char *tty_name(const struct tty_struct *tty);
+ extern struct tty_struct *tty_kopen(dev_t device);
+ extern void tty_kclose(struct tty_struct *tty);
+ extern int tty_dev_name_to_number(const char *name, dev_t *number);
+-extern ssize_t redirected_tty_write(struct kiocb *, struct iov_iter *);
+ #else
+ static inline void tty_kref_put(struct tty_struct *tty)
+ { }
+--
+2.39.2
+
--- /dev/null
+From 6b07c2a8bb385c913227145ac39aaad33a3628eb Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 17 Mar 2023 13:33:17 +0200
+Subject: tty: Prevent writing chars during tcsetattr TCSADRAIN/FLUSH
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+
+[ Upstream commit 094fb49a2d0d6827c86d2e0840873e6db0c491d2 ]
+
+If userspace races tcsetattr() with a write, the drained condition
+might not be guaranteed by the kernel. There is a race window after
+checking Tx is empty before tty_set_termios() takes termios_rwsem for
+write. During that race window, more characters can be queued by a
+racing writer.
+
+Any ongoing transmission might produce garbage during HW's
+->set_termios() call. The intent of TCSADRAIN/FLUSH seems to be
+preventing such a character corruption. If those flags are set, take
+tty's write lock to stop any writer before performing the lower layer
+Tx empty check and wait for the pending characters to be sent (if any).
+
+The initial wait for all-writers-done must be placed outside of tty's
+write lock to avoid deadlock which makes it impossible to use
+tty_wait_until_sent(). The write lock is retried if a racing write is
+detected.
+
+Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
+Cc: stable@vger.kernel.org
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Link: https://lore.kernel.org/r/20230317113318.31327-2-ilpo.jarvinen@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/tty.h | 2 ++
+ drivers/tty/tty_io.c | 4 ++--
+ drivers/tty/tty_ioctl.c | 45 ++++++++++++++++++++++++++++++-----------
+ 3 files changed, 37 insertions(+), 14 deletions(-)
+
+diff --git a/drivers/tty/tty.h b/drivers/tty/tty.h
+index 74ed99bc5449a..1908f27a795a0 100644
+--- a/drivers/tty/tty.h
++++ b/drivers/tty/tty.h
+@@ -63,6 +63,8 @@ int __tty_check_change(struct tty_struct *tty, int sig);
+ int tty_check_change(struct tty_struct *tty);
+ void __stop_tty(struct tty_struct *tty);
+ void __start_tty(struct tty_struct *tty);
++void tty_write_unlock(struct tty_struct *tty);
++int tty_write_lock(struct tty_struct *tty, int ndelay);
+ void tty_vhangup_session(struct tty_struct *tty);
+ void tty_open_proc_set_tty(struct file *filp, struct tty_struct *tty);
+ int tty_signal_session_leader(struct tty_struct *tty, int exit_session);
+diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
+index 86fbfe42ce0ac..094e82a12d298 100644
+--- a/drivers/tty/tty_io.c
++++ b/drivers/tty/tty_io.c
+@@ -942,13 +942,13 @@ static ssize_t tty_read(struct kiocb *iocb, struct iov_iter *to)
+ return i;
+ }
+
+-static void tty_write_unlock(struct tty_struct *tty)
++void tty_write_unlock(struct tty_struct *tty)
+ {
+ mutex_unlock(&tty->atomic_write_lock);
+ wake_up_interruptible_poll(&tty->write_wait, EPOLLOUT);
+ }
+
+-static int tty_write_lock(struct tty_struct *tty, int ndelay)
++int tty_write_lock(struct tty_struct *tty, int ndelay)
+ {
+ if (!mutex_trylock(&tty->atomic_write_lock)) {
+ if (ndelay)
+diff --git a/drivers/tty/tty_ioctl.c b/drivers/tty/tty_ioctl.c
+index 50e65784fbf77..68b07250dcb60 100644
+--- a/drivers/tty/tty_ioctl.c
++++ b/drivers/tty/tty_ioctl.c
+@@ -398,21 +398,42 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
+ tmp_termios.c_ispeed = tty_termios_input_baud_rate(&tmp_termios);
+ tmp_termios.c_ospeed = tty_termios_baud_rate(&tmp_termios);
+
+- ld = tty_ldisc_ref(tty);
++ if (opt & (TERMIOS_FLUSH|TERMIOS_WAIT)) {
++retry_write_wait:
++ retval = wait_event_interruptible(tty->write_wait, !tty_chars_in_buffer(tty));
++ if (retval < 0)
++ return retval;
+
+- if (ld != NULL) {
+- if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
+- ld->ops->flush_buffer(tty);
+- tty_ldisc_deref(ld);
+- }
++ if (tty_write_lock(tty, 0) < 0)
++ goto retry_write_wait;
+
+- if (opt & TERMIOS_WAIT) {
+- tty_wait_until_sent(tty, 0);
+- if (signal_pending(current))
+- return -ERESTARTSYS;
+- }
++ /* Racing writer? */
++ if (tty_chars_in_buffer(tty)) {
++ tty_write_unlock(tty);
++ goto retry_write_wait;
++ }
+
+- tty_set_termios(tty, &tmp_termios);
++ ld = tty_ldisc_ref(tty);
++ if (ld != NULL) {
++ if ((opt & TERMIOS_FLUSH) && ld->ops->flush_buffer)
++ ld->ops->flush_buffer(tty);
++ tty_ldisc_deref(ld);
++ }
++
++ if ((opt & TERMIOS_WAIT) && tty->ops->wait_until_sent) {
++ tty->ops->wait_until_sent(tty, 0);
++ if (signal_pending(current)) {
++ tty_write_unlock(tty);
++ return -ERESTARTSYS;
++ }
++ }
++
++ tty_set_termios(tty, &tmp_termios);
++
++ tty_write_unlock(tty);
++ } else {
++ tty_set_termios(tty, &tmp_termios);
++ }
+
+ /* FIXME: Arguably if tmp_termios == tty->termios AND the
+ actual requested termios was not tmp_termios then we may
+--
+2.39.2
+