]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
Fixes for 5.10
authorSasha Levin <sashal@kernel.org>
Thu, 11 May 2023 15:48:36 +0000 (11:48 -0400)
committerSasha Levin <sashal@kernel.org>
Thu, 11 May 2023 15:48:36 +0000 (11:48 -0400)
Signed-off-by: Sasha Levin <sashal@kernel.org>
17 files changed:
queue-5.10/bus-mhi-add-mhi-pci-support-for-wwan-modems.patch [new file with mode: 0644]
queue-5.10/bus-mhi-add-mmio-region-length-to-controller-structu.patch [new file with mode: 0644]
queue-5.10/bus-mhi-host-range-check-chdboff-and-erdboff.patch [new file with mode: 0644]
queue-5.10/bus-mhi-move-host-mhi-code-to-host-directory.patch [new file with mode: 0644]
queue-5.10/crypto-ccp-clear-psp-interrupt-status-register-befor.patch [new file with mode: 0644]
queue-5.10/dm-verity-fix-error-handling-for-check_at_most_once-.patch [new file with mode: 0644]
queue-5.10/dm-verity-skip-redundant-verity_handle_err-on-i-o-er.patch [new file with mode: 0644]
queue-5.10/mailbox-zynq-switch-to-flexible-array-to-simplify-co.patch [new file with mode: 0644]
queue-5.10/mailbox-zynqmp-fix-counts-of-child-nodes.patch [new file with mode: 0644]
queue-5.10/ring-buffer-ensure-proper-resetting-of-atomic-variab.patch [new file with mode: 0644]
queue-5.10/series
queue-5.10/tty-audit-move-some-local-functions-out-of-tty.h.patch [new file with mode: 0644]
queue-5.10/tty-clean-include-linux-tty.h-up.patch [new file with mode: 0644]
queue-5.10/tty-create-internal-tty.h-file.patch [new file with mode: 0644]
queue-5.10/tty-move-some-internal-tty-lock-enums-and-functions-.patch [new file with mode: 0644]
queue-5.10/tty-move-some-tty-only-functions-to-drivers-tty-tty..patch [new file with mode: 0644]
queue-5.10/tty-prevent-writing-chars-during-tcsetattr-tcsadrain.patch [new file with mode: 0644]

diff --git a/queue-5.10/bus-mhi-add-mhi-pci-support-for-wwan-modems.patch b/queue-5.10/bus-mhi-add-mhi-pci-support-for-wwan-modems.patch
new file mode 100644 (file)
index 0000000..fbdf272
--- /dev/null
@@ -0,0 +1,415 @@
+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
+
diff --git a/queue-5.10/bus-mhi-add-mmio-region-length-to-controller-structu.patch b/queue-5.10/bus-mhi-add-mmio-region-length-to-controller-structu.patch
new file mode 100644 (file)
index 0000000..076242c
--- /dev/null
@@ -0,0 +1,51 @@
+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
+
diff --git a/queue-5.10/bus-mhi-host-range-check-chdboff-and-erdboff.patch b/queue-5.10/bus-mhi-host-range-check-chdboff-and-erdboff.patch
new file mode 100644 (file)
index 0000000..040aa0e
--- /dev/null
@@ -0,0 +1,59 @@
+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
+
diff --git a/queue-5.10/bus-mhi-move-host-mhi-code-to-host-directory.patch b/queue-5.10/bus-mhi-move-host-mhi-code-to-host-directory.patch
new file mode 100644 (file)
index 0000000..9240136
--- /dev/null
@@ -0,0 +1,189 @@
+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
+
diff --git a/queue-5.10/crypto-ccp-clear-psp-interrupt-status-register-befor.patch b/queue-5.10/crypto-ccp-clear-psp-interrupt-status-register-befor.patch
new file mode 100644 (file)
index 0000000..b89a84b
--- /dev/null
@@ -0,0 +1,74 @@
+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
+
diff --git a/queue-5.10/dm-verity-fix-error-handling-for-check_at_most_once-.patch b/queue-5.10/dm-verity-fix-error-handling-for-check_at_most_once-.patch
new file mode 100644 (file)
index 0000000..7088467
--- /dev/null
@@ -0,0 +1,49 @@
+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
+
diff --git a/queue-5.10/dm-verity-skip-redundant-verity_handle_err-on-i-o-er.patch b/queue-5.10/dm-verity-skip-redundant-verity_handle_err-on-i-o-er.patch
new file mode 100644 (file)
index 0000000..1e115fe
--- /dev/null
@@ -0,0 +1,62 @@
+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
+
diff --git a/queue-5.10/mailbox-zynq-switch-to-flexible-array-to-simplify-co.patch b/queue-5.10/mailbox-zynq-switch-to-flexible-array-to-simplify-co.patch
new file mode 100644 (file)
index 0000000..32bd7aa
--- /dev/null
@@ -0,0 +1,56 @@
+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
+
diff --git a/queue-5.10/mailbox-zynqmp-fix-counts-of-child-nodes.patch b/queue-5.10/mailbox-zynqmp-fix-counts-of-child-nodes.patch
new file mode 100644 (file)
index 0000000..d015d4e
--- /dev/null
@@ -0,0 +1,45 @@
+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
+
diff --git a/queue-5.10/ring-buffer-ensure-proper-resetting-of-atomic-variab.patch b/queue-5.10/ring-buffer-ensure-proper-resetting-of-atomic-variab.patch
new file mode 100644 (file)
index 0000000..5ebfe2c
--- /dev/null
@@ -0,0 +1,87 @@
+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
+
index c8193c8db2faef539a5653d7f899b71c69eb01c9..8a6f469ba6537c86ea97c9d7d2b79b5f7cb61db2 100644 (file)
@@ -293,3 +293,19 @@ sound-oss-dmasound-fix-dmasound_setup-defined-but-not-used.patch
 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
diff --git a/queue-5.10/tty-audit-move-some-local-functions-out-of-tty.h.patch b/queue-5.10/tty-audit-move-some-local-functions-out-of-tty.h.patch
new file mode 100644 (file)
index 0000000..92937db
--- /dev/null
@@ -0,0 +1,87 @@
+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
+
diff --git a/queue-5.10/tty-clean-include-linux-tty.h-up.patch b/queue-5.10/tty-clean-include-linux-tty.h-up.patch
new file mode 100644 (file)
index 0000000..ec95dcf
--- /dev/null
@@ -0,0 +1,201 @@
+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
+
diff --git a/queue-5.10/tty-create-internal-tty.h-file.patch b/queue-5.10/tty-create-internal-tty.h-file.patch
new file mode 100644 (file)
index 0000000..9855ee9
--- /dev/null
@@ -0,0 +1,157 @@
+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
+
diff --git a/queue-5.10/tty-move-some-internal-tty-lock-enums-and-functions-.patch b/queue-5.10/tty-move-some-internal-tty-lock-enums-and-functions-.patch
new file mode 100644 (file)
index 0000000..e19b4dd
--- /dev/null
@@ -0,0 +1,133 @@
+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
+
diff --git a/queue-5.10/tty-move-some-tty-only-functions-to-drivers-tty-tty..patch b/queue-5.10/tty-move-some-tty-only-functions-to-drivers-tty-tty..patch
new file mode 100644 (file)
index 0000000..b76bb9e
--- /dev/null
@@ -0,0 +1,105 @@
+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
+
diff --git a/queue-5.10/tty-prevent-writing-chars-during-tcsetattr-tcsadrain.patch b/queue-5.10/tty-prevent-writing-chars-during-tcsetattr-tcsadrain.patch
new file mode 100644 (file)
index 0000000..5274fd6
--- /dev/null
@@ -0,0 +1,136 @@
+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
+