--- /dev/null
+From 3899d94e3831ee07ea6821c032dc297aec80586a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Christoph=20B=C3=B6hmwalder?=
+ <christoph.boehmwalder@linbit.com>
+Date: Wed, 3 May 2023 14:19:37 +0200
+Subject: drbd: correctly submit flush bio on barrier
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
+
+commit 3899d94e3831ee07ea6821c032dc297aec80586a upstream.
+
+When we receive a flush command (or "barrier" in DRBD), we currently use
+a REQ_OP_FLUSH with the REQ_PREFLUSH flag set.
+
+The correct way to submit a flush bio is by using a REQ_OP_WRITE without
+any data, and set the REQ_PREFLUSH flag.
+
+Since commit b4a6bb3a67aa ("block: add a sanity check for non-write
+flush/fua bios"), this triggers a warning in the block layer, but this
+has been broken for quite some time before that.
+
+So use the correct set of flags to actually make the flush happen.
+
+Cc: Christoph Hellwig <hch@infradead.org>
+Cc: stable@vger.kernel.org
+Fixes: f9ff0da56437 ("drbd: allow parallel flushes for multi-volume resources")
+Reported-by: Thomas Voegtle <tv@lio96.de>
+Signed-off-by: Christoph Böhmwalder <christoph.boehmwalder@linbit.com>
+Reviewed-by: Christoph Hellwig <hch@lst.de>
+Link: https://lore.kernel.org/r/20230503121937.17232-1-christoph.boehmwalder@linbit.com
+Signed-off-by: Jens Axboe <axboe@kernel.dk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/block/drbd/drbd_receiver.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/block/drbd/drbd_receiver.c
++++ b/drivers/block/drbd/drbd_receiver.c
+@@ -1310,7 +1310,7 @@ static void submit_one_flush(struct drbd
+ bio_set_dev(bio, device->ldev->backing_bdev);
+ bio->bi_private = octx;
+ bio->bi_end_io = one_flush_endio;
+- bio->bi_opf = REQ_OP_FLUSH | REQ_PREFLUSH;
++ bio->bi_opf = REQ_OP_WRITE | REQ_PREFLUSH;
+
+ device->flush_jif = jiffies;
+ set_bit(FLUSH_PENDING, &device->flags);
--- /dev/null
+From stable-owner@vger.kernel.org Tue May 9 15:08:56 2023
+From: Lukas Wunner <lukas@wunner.de>
+Date: Tue, 9 May 2023 14:55:19 +0200
+Subject: PCI: pciehp: Fix AB-BA deadlock between reset_lock and device_lock
+To: stable@vger.kernel.org
+Cc: Anatoli.Antonovitch@amd.com, alex.williamson@redhat.com, amichon@kalrayinc.com, andrey2805@gmail.com, ashok.raj@intel.com, bhelgaas@google.com, dstein@hpe.com, ian.may@canonical.com, michael.haeuptle@hpe.com, mika.westerberg@linux.intel.com, rahul.kumar1@amd.com, sathyanarayanan.kuppuswamy@linux.intel.com, wangxiongfeng2@huawei.com, zhangjialin11@huawei.com
+Message-ID: <4efe2952d1c46481f5b3b53403173fc8ecc8c0cd.1683636753.git.lukas@wunner.de>
+
+From: Lukas Wunner <lukas@wunner.de>
+
+commit f5eff5591b8f9c5effd25c92c758a127765f74c1 upstream.
+
+In 2013, commits
+
+ 2e35afaefe64 ("PCI: pciehp: Add reset_slot() method")
+ 608c388122c7 ("PCI: Add slot reset option to pci_dev_reset()")
+
+amended PCIe hotplug to mask Presence Detect Changed events during a
+Secondary Bus Reset. The reset thus no longer causes gratuitous slot
+bringdown and bringup.
+
+However the commits neglected to serialize reset with code paths reading
+slot registers. For instance, a slot bringup due to an earlier hotplug
+event may see the Presence Detect State bit cleared during a concurrent
+Secondary Bus Reset.
+
+In 2018, commit
+
+ 5b3f7b7d062b ("PCI: pciehp: Avoid slot access during reset")
+
+retrofitted the missing locking. It introduced a reset_lock which
+serializes a Secondary Bus Reset with other parts of pciehp.
+
+Unfortunately the locking turns out to be overzealous: reset_lock is
+held for the entire enumeration and de-enumeration of hotplugged devices,
+including driver binding and unbinding.
+
+Driver binding and unbinding acquires device_lock while the reset_lock
+of the ancestral hotplug port is held. A concurrent Secondary Bus Reset
+acquires the ancestral reset_lock while already holding the device_lock.
+The asymmetric locking order in the two code paths can lead to AB-BA
+deadlocks.
+
+Michael Haeuptle reports such deadlocks on simultaneous hot-removal and
+vfio release (the latter implies a Secondary Bus Reset):
+
+ pciehp_ist() # down_read(reset_lock)
+ pciehp_handle_presence_or_link_change()
+ pciehp_disable_slot()
+ __pciehp_disable_slot()
+ remove_board()
+ pciehp_unconfigure_device()
+ pci_stop_and_remove_bus_device()
+ pci_stop_bus_device()
+ pci_stop_dev()
+ device_release_driver()
+ device_release_driver_internal()
+ __device_driver_lock() # device_lock()
+
+ SYS_munmap()
+ vfio_device_fops_release()
+ vfio_device_group_close()
+ vfio_device_close()
+ vfio_device_last_close()
+ vfio_pci_core_close_device()
+ vfio_pci_core_disable() # device_lock()
+ __pci_reset_function_locked()
+ pci_reset_bus_function()
+ pci_dev_reset_slot_function()
+ pci_reset_hotplug_slot()
+ pciehp_reset_slot() # down_write(reset_lock)
+
+Ian May reports the same deadlock on simultaneous hot-removal and an
+AER-induced Secondary Bus Reset:
+
+ aer_recover_work_func()
+ pcie_do_recovery()
+ aer_root_reset()
+ pci_bus_error_reset()
+ pci_slot_reset()
+ pci_slot_lock() # device_lock()
+ pci_reset_hotplug_slot()
+ pciehp_reset_slot() # down_write(reset_lock)
+
+Fix by releasing the reset_lock during driver binding and unbinding,
+thereby splitting and shrinking the critical section.
+
+Driver binding and unbinding is protected by the device_lock() and thus
+serialized with a Secondary Bus Reset. There's no need to additionally
+protect it with the reset_lock. However, pciehp does not bind and
+unbind devices directly, but rather invokes PCI core functions which
+also perform certain enumeration and de-enumeration steps.
+
+The reset_lock's purpose is to protect slot registers, not enumeration
+and de-enumeration of hotplugged devices. That would arguably be the
+job of the PCI core, not the PCIe hotplug driver. After all, an
+AER-induced Secondary Bus Reset may as well happen during boot-time
+enumeration of the PCI hierarchy and there's no locking to prevent that
+either.
+
+Exempting *de-enumeration* from the reset_lock is relatively harmless:
+A concurrent Secondary Bus Reset may foil config space accesses such as
+PME interrupt disablement. But if the device is physically gone, those
+accesses are pointless anyway. If the device is physically present and
+only logically removed through an Attention Button press or the sysfs
+"power" attribute, PME interrupts as well as DMA cannot come through
+because pciehp_unconfigure_device() disables INTx and Bus Master bits.
+That's still protected by the reset_lock in the present commit.
+
+Exempting *enumeration* from the reset_lock also has limited impact:
+The exempted call to pci_bus_add_device() may perform device accesses
+through pcibios_bus_add_device() and pci_fixup_device() which are now
+no longer protected from a concurrent Secondary Bus Reset. Otherwise
+there should be no impact.
+
+In essence, the present commit seeks to fix the AB-BA deadlocks while
+still retaining a best-effort reset protection for enumeration and
+de-enumeration of hotplugged devices -- until a general solution is
+implemented in the PCI core.
+
+Link: https://lore.kernel.org/linux-pci/CS1PR8401MB0728FC6FDAB8A35C22BD90EC95F10@CS1PR8401MB0728.NAMPRD84.PROD.OUTLOOK.COM
+Link: https://lore.kernel.org/linux-pci/20200615143250.438252-1-ian.may@canonical.com
+Link: https://lore.kernel.org/linux-pci/ce878dab-c0c4-5bd0-a725-9805a075682d@amd.com
+Link: https://lore.kernel.org/linux-pci/ed831249-384a-6d35-0831-70af191e9bce@huawei.com
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=215590
+Fixes: 5b3f7b7d062b ("PCI: pciehp: Avoid slot access during reset")
+Link: https://lore.kernel.org/r/fef2b2e9edf245c049a8c5b94743c0f74ff5008a.1681191902.git.lukas@wunner.de
+Reported-by: Michael Haeuptle <michael.haeuptle@hpe.com>
+Reported-by: Ian May <ian.may@canonical.com>
+Reported-by: Andrey Grodzovsky <andrey2805@gmail.com>
+Reported-by: Rahul Kumar <rahul.kumar1@amd.com>
+Reported-by: Jialin Zhang <zhangjialin11@huawei.com>
+Tested-by: Anatoli Antonovitch <Anatoli.Antonovitch@amd.com>
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Cc: stable@vger.kernel.org # v4.19+
+Cc: Dan Stein <dstein@hpe.com>
+Cc: Ashok Raj <ashok.raj@intel.com>
+Cc: Alex Michon <amichon@kalrayinc.com>
+Cc: Xiongfeng Wang <wangxiongfeng2@huawei.com>
+Cc: Alex Williamson <alex.williamson@redhat.com>
+Cc: Mika Westerberg <mika.westerberg@linux.intel.com>
+Cc: Sathyanarayanan Kuppuswamy <sathyanarayanan.kuppuswamy@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/hotplug/pciehp_pci.c | 15 +++++++++++++++
+ 1 file changed, 15 insertions(+)
+
+--- a/drivers/pci/hotplug/pciehp_pci.c
++++ b/drivers/pci/hotplug/pciehp_pci.c
+@@ -55,7 +55,14 @@ int pciehp_configure_device(struct slot
+
+ pci_assign_unassigned_bridge_resources(bridge);
+ pcie_bus_configure_settings(parent);
++
++ /*
++ * Release reset_lock during driver binding
++ * to avoid AB-BA deadlock with device_lock.
++ */
++ up_read(&ctrl->reset_lock);
+ pci_bus_add_devices(parent);
++ down_read_nested(&ctrl->reset_lock, ctrl->depth);
+
+ out:
+ pci_unlock_rescan_remove();
+@@ -91,7 +98,15 @@ void pciehp_unconfigure_device(struct sl
+ pci_walk_bus(dev->subordinate,
+ pci_dev_set_disconnected, NULL);
+ }
++
++ /*
++ * Release reset_lock during driver unbinding
++ * to avoid AB-BA deadlock with device_lock.
++ */
++ up_read(&ctrl->reset_lock);
+ pci_stop_and_remove_bus_device(dev);
++ down_read_nested(&ctrl->reset_lock, ctrl->depth);
++
+ /*
+ * Ensure that no new Requests will be generated from
+ * the device.
--- /dev/null
+From stable-owner@vger.kernel.org Tue May 9 14:56:33 2023
+From: Lukas Wunner <lukas@wunner.de>
+Date: Tue, 9 May 2023 14:55:09 +0200
+Subject: PCI: pciehp: Use down_read/write_nested(reset_lock) to fix lockdep errors
+To: stable@vger.kernel.org
+Cc: Anatoli.Antonovitch@amd.com, alex.williamson@redhat.com, amichon@kalrayinc.com, andrey2805@gmail.com, ashok.raj@intel.com, bhelgaas@google.com, dstein@hpe.com, ian.may@canonical.com, michael.haeuptle@hpe.com, mika.westerberg@linux.intel.com, rahul.kumar1@amd.com, sathyanarayanan.kuppuswamy@linux.intel.com, wangxiongfeng2@huawei.com, zhangjialin11@huawei.com, hdegoede@redhat.com
+Message-ID: <8017b674a87ae89a0577f008d7cef15e002b88d1.1683636753.git.lukas@wunner.de>
+
+From: Hans de Goede <hdegoede@redhat.com>
+
+commit 085a9f43433f30cbe8a1ade62d9d7827c3217f4d upstream.
+
+Use down_read_nested() and down_write_nested() when taking the
+ctrl->reset_lock rw-sem, passing the number of PCIe hotplug controllers in
+the path to the PCI root bus as lock subclass parameter.
+
+This fixes the following false-positive lockdep report when unplugging a
+Lenovo X1C8 from a Lenovo 2nd gen TB3 dock:
+
+ pcieport 0000:06:01.0: pciehp: Slot(1): Link Down
+ pcieport 0000:06:01.0: pciehp: Slot(1): Card not present
+ ============================================
+ WARNING: possible recursive locking detected
+ 5.16.0-rc2+ #621 Not tainted
+ --------------------------------------------
+ irq/124-pciehp/86 is trying to acquire lock:
+ ffff8e5ac4299ef8 (&ctrl->reset_lock){.+.+}-{3:3}, at: pciehp_check_presence+0x23/0x80
+
+ but task is already holding lock:
+ ffff8e5ac4298af8 (&ctrl->reset_lock){.+.+}-{3:3}, at: pciehp_ist+0xf3/0x180
+
+ other info that might help us debug this:
+ Possible unsafe locking scenario:
+
+ CPU0
+ ----
+ lock(&ctrl->reset_lock);
+ lock(&ctrl->reset_lock);
+
+ *** DEADLOCK ***
+
+ May be due to missing lock nesting notation
+
+ 3 locks held by irq/124-pciehp/86:
+ #0: ffff8e5ac4298af8 (&ctrl->reset_lock){.+.+}-{3:3}, at: pciehp_ist+0xf3/0x180
+ #1: ffffffffa3b024e8 (pci_rescan_remove_lock){+.+.}-{3:3}, at: pciehp_unconfigure_device+0x31/0x110
+ #2: ffff8e5ac1ee2248 (&dev->mutex){....}-{3:3}, at: device_release_driver+0x1c/0x40
+
+ stack backtrace:
+ CPU: 4 PID: 86 Comm: irq/124-pciehp Not tainted 5.16.0-rc2+ #621
+ Hardware name: LENOVO 20U90SIT19/20U90SIT19, BIOS N2WET30W (1.20 ) 08/26/2021
+ Call Trace:
+ <TASK>
+ dump_stack_lvl+0x59/0x73
+ __lock_acquire.cold+0xc5/0x2c6
+ lock_acquire+0xb5/0x2b0
+ down_read+0x3e/0x50
+ pciehp_check_presence+0x23/0x80
+ pciehp_runtime_resume+0x5c/0xa0
+ device_for_each_child+0x45/0x70
+ pcie_port_device_runtime_resume+0x20/0x30
+ pci_pm_runtime_resume+0xa7/0xc0
+ __rpm_callback+0x41/0x110
+ rpm_callback+0x59/0x70
+ rpm_resume+0x512/0x7b0
+ __pm_runtime_resume+0x4a/0x90
+ __device_release_driver+0x28/0x240
+ device_release_driver+0x26/0x40
+ pci_stop_bus_device+0x68/0x90
+ pci_stop_bus_device+0x2c/0x90
+ pci_stop_and_remove_bus_device+0xe/0x20
+ pciehp_unconfigure_device+0x6c/0x110
+ pciehp_disable_slot+0x5b/0xe0
+ pciehp_handle_presence_or_link_change+0xc3/0x2f0
+ pciehp_ist+0x179/0x180
+
+This lockdep warning is triggered because with Thunderbolt, hotplug ports
+are nested. When removing multiple devices in a daisy-chain, each hotplug
+port's reset_lock may be acquired recursively. It's never the same lock, so
+the lockdep splat is a false positive.
+
+Because locks at the same hierarchy level are never acquired recursively, a
+per-level lockdep class is sufficient to fix the lockdep warning.
+
+The choice to use one lockdep subclass per pcie-hotplug controller in the
+path to the root-bus was made to conserve class keys because their number
+is limited and the complexity grows quadratically with number of keys
+according to Documentation/locking/lockdep-design.rst.
+
+Link: https://lore.kernel.org/linux-pci/20190402021933.GA2966@mit.edu/
+Link: https://lore.kernel.org/linux-pci/de684a28-9038-8fc6-27ca-3f6f2f6400d7@redhat.com/
+Link: https://lore.kernel.org/r/20211217141709.379663-1-hdegoede@redhat.com
+Link: https://bugzilla.kernel.org/show_bug.cgi?id=208855
+Reported-by: "Theodore Ts'o" <tytso@mit.edu>
+Signed-off-by: Hans de Goede <hdegoede@redhat.com>
+Signed-off-by: Bjorn Helgaas <bhelgaas@google.com>
+Reviewed-by: Lukas Wunner <lukas@wunner.de>
+Cc: stable@vger.kernel.org
+[lukas: backport to v4.19-stable]
+Signed-off-by: Lukas Wunner <lukas@wunner.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/pci/hotplug/pciehp.h | 3 +++
+ drivers/pci/hotplug/pciehp_core.c | 2 +-
+ drivers/pci/hotplug/pciehp_hpc.c | 19 +++++++++++++++++--
+ 3 files changed, 21 insertions(+), 3 deletions(-)
+
+--- a/drivers/pci/hotplug/pciehp.h
++++ b/drivers/pci/hotplug/pciehp.h
+@@ -84,6 +84,8 @@ struct slot {
+ * @reset_lock: prevents access to the Data Link Layer Link Active bit in the
+ * Link Status register and to the Presence Detect State bit in the Slot
+ * Status register during a slot reset which may cause them to flap
++ * @depth: Number of additional hotplug ports in the path to the root bus,
++ * used as lock subclass for @reset_lock
+ * @slot: pointer to the controller's slot structure
+ * @queue: wait queue to wake up on reception of a Command Completed event,
+ * used for synchronous writes to the Slot Control register
+@@ -115,6 +117,7 @@ struct controller {
+ struct mutex ctrl_lock;
+ struct pcie_device *pcie;
+ struct rw_semaphore reset_lock;
++ unsigned int depth;
+ struct slot *slot;
+ wait_queue_head_t queue;
+ u32 slot_cap;
+--- a/drivers/pci/hotplug/pciehp_core.c
++++ b/drivers/pci/hotplug/pciehp_core.c
+@@ -215,7 +215,7 @@ static void pciehp_check_presence(struct
+ struct slot *slot = ctrl->slot;
+ u8 occupied;
+
+- down_read(&ctrl->reset_lock);
++ down_read_nested(&ctrl->reset_lock, ctrl->depth);
+ mutex_lock(&slot->lock);
+
+ pciehp_get_adapter_status(slot, &occupied);
+--- a/drivers/pci/hotplug/pciehp_hpc.c
++++ b/drivers/pci/hotplug/pciehp_hpc.c
+@@ -674,7 +674,7 @@ static irqreturn_t pciehp_ist(int irq, v
+ * Disable requests have higher priority than Presence Detect Changed
+ * or Data Link Layer State Changed events.
+ */
+- down_read(&ctrl->reset_lock);
++ down_read_nested(&ctrl->reset_lock, ctrl->depth);
+ if (events & DISABLE_SLOT)
+ pciehp_handle_disable_request(slot);
+ else if (events & (PCI_EXP_SLTSTA_PDC | PCI_EXP_SLTSTA_DLLSC))
+@@ -785,7 +785,7 @@ int pciehp_reset_slot(struct slot *slot,
+ if (probe)
+ return 0;
+
+- down_write(&ctrl->reset_lock);
++ down_write_nested(&ctrl->reset_lock, ctrl->depth);
+
+ if (!ATTN_BUTTN(ctrl)) {
+ ctrl_mask |= PCI_EXP_SLTCTL_PDCE;
+@@ -872,6 +872,20 @@ static inline void dbg_ctrl(struct contr
+
+ #define FLAG(x, y) (((x) & (y)) ? '+' : '-')
+
++static inline int pcie_hotplug_depth(struct pci_dev *dev)
++{
++ struct pci_bus *bus = dev->bus;
++ int depth = 0;
++
++ while (bus->parent) {
++ bus = bus->parent;
++ if (bus->self && bus->self->is_hotplug_bridge)
++ depth++;
++ }
++
++ return depth;
++}
++
+ struct controller *pcie_init(struct pcie_device *dev)
+ {
+ struct controller *ctrl;
+@@ -884,6 +898,7 @@ struct controller *pcie_init(struct pcie
+ goto abort;
+
+ ctrl->pcie = dev;
++ ctrl->depth = pcie_hotplug_depth(dev->port);
+ pcie_capability_read_dword(pdev, PCI_EXP_SLTCAP, &slot_cap);
+
+ if (pdev->hotplug_user_indicators)
--- /dev/null
+From stable-owner@vger.kernel.org Thu May 11 14:33:08 2023
+From: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
+Date: Thu, 11 May 2023 15:32:44 +0300
+Subject: serial: 8250: Fix serial8250_tx_empty() race with DMA Tx
+To: stable@vger.kernel.org
+Cc: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>, "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>
+Message-ID: <20230511123244.38514-2-ilpo.jarvinen@linux.intel.com>
+
+From: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
+
+There's a potential race before THRE/TEMT deasserts when DMA Tx is
+starting up (or the next batch of continuous Tx is being submitted).
+This can lead to misdetecting Tx empty condition.
+
+It is entirely normal for THRE/TEMT to be set for some time after the
+DMA Tx had been setup in serial8250_tx_dma(). As Tx side is definitely
+not empty at that point, it seems incorrect for serial8250_tx_empty()
+claim Tx is empty.
+
+Fix the race by also checking in serial8250_tx_empty() whether there's
+DMA Tx active.
+
+Note: This fix only addresses in-kernel race mainly to make using
+TCSADRAIN/FLUSH robust. Userspace can still cause other races but they
+seem userspace concurrency control problems.
+
+Fixes: 9ee4b83e51f74 ("serial: 8250: Add support for dmaengine")
+Cc: stable@vger.kernel.org
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Link: https://lore.kernel.org/r/20230317113318.31327-3-ilpo.jarvinen@linux.intel.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+(cherry picked from commit 146a37e05d620cef4ad430e5d1c9c077fe6fa76f)
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/serial/8250/8250.h | 12 ++++++++++++
+ drivers/tty/serial/8250/8250_port.c | 12 +++++++++---
+ 2 files changed, 21 insertions(+), 3 deletions(-)
+
+--- a/drivers/tty/serial/8250/8250.h
++++ b/drivers/tty/serial/8250/8250.h
+@@ -217,6 +217,13 @@ extern int serial8250_rx_dma(struct uart
+ extern void serial8250_rx_dma_flush(struct uart_8250_port *);
+ extern int serial8250_request_dma(struct uart_8250_port *);
+ extern void serial8250_release_dma(struct uart_8250_port *);
++
++static inline bool serial8250_tx_dma_running(struct uart_8250_port *p)
++{
++ struct uart_8250_dma *dma = p->dma;
++
++ return dma && dma->tx_running;
++}
+ #else
+ static inline int serial8250_tx_dma(struct uart_8250_port *p)
+ {
+@@ -232,6 +239,11 @@ static inline int serial8250_request_dma
+ return -1;
+ }
+ static inline void serial8250_release_dma(struct uart_8250_port *p) { }
++
++static inline bool serial8250_tx_dma_running(struct uart_8250_port *p)
++{
++ return false;
++}
+ #endif
+
+ static inline int ns16550a_goto_highspeed(struct uart_8250_port *up)
+--- a/drivers/tty/serial/8250/8250_port.c
++++ b/drivers/tty/serial/8250/8250_port.c
+@@ -1967,19 +1967,25 @@ static int serial8250_tx_threshold_handl
+ static unsigned int serial8250_tx_empty(struct uart_port *port)
+ {
+ struct uart_8250_port *up = up_to_u8250p(port);
++ unsigned int result = 0;
+ unsigned long flags;
+ unsigned int lsr;
+
+ serial8250_rpm_get(up);
+
+ spin_lock_irqsave(&port->lock, flags);
+- lsr = serial_port_in(port, UART_LSR);
+- up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
++ if (!serial8250_tx_dma_running(up)) {
++ lsr = serial_port_in(port, UART_LSR);
++ up->lsr_saved_flags |= lsr & LSR_SAVE_FLAGS;
++
++ if ((lsr & BOTH_EMPTY) == BOTH_EMPTY)
++ result = TIOCSER_TEMT;
++ }
+ spin_unlock_irqrestore(&port->lock, flags);
+
+ serial8250_rpm_put(up);
+
+- return (lsr & BOTH_EMPTY) == BOTH_EMPTY ? TIOCSER_TEMT : 0;
++ return result;
+ }
+
+ unsigned int serial8250_do_get_mctrl(struct uart_port *port)
ext4-bail-out-of-ext4_xattr_ibody_get-fails-for-any-reason.patch
ext4-remove-a-bug_on-in-ext4_mb_release_group_pa.patch
ext4-fix-invalid-free-tracking-in-ext4_xattr_move_to_block.patch
+tty-prevent-writing-chars-during-tcsetattr-tcsadrain-flush.patch
+serial-8250-fix-serial8250_tx_empty-race-with-dma-tx.patch
+drbd-correctly-submit-flush-bio-on-barrier.patch
+pci-pciehp-use-down_read-write_nested-reset_lock-to-fix-lockdep-errors.patch
+pci-pciehp-fix-ab-ba-deadlock-between-reset_lock-and-device_lock.patch
--- /dev/null
+From stable-owner@vger.kernel.org Thu May 11 14:33:03 2023
+From: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
+Date: Thu, 11 May 2023 15:32:43 +0300
+Subject: tty: Prevent writing chars during tcsetattr TCSADRAIN/FLUSH
+To: stable@vger.kernel.org
+Cc: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>, "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>
+Message-ID: <20230511123244.38514-1-ilpo.jarvinen@linux.intel.com>
+
+From: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
+
+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>
+(cherry picked from commit 094fb49a2d0d6827c86d2e0840873e6db0c491d2)
+Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ drivers/tty/tty_io.c | 4 ++--
+ drivers/tty/tty_ioctl.c | 45 +++++++++++++++++++++++++++++++++------------
+ include/linux/tty.h | 2 ++
+ 3 files changed, 37 insertions(+), 14 deletions(-)
+
+--- a/drivers/tty/tty_io.c
++++ b/drivers/tty/tty_io.c
+@@ -875,13 +875,13 @@ static ssize_t tty_read(struct file *fil
+ 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)
+--- a/drivers/tty/tty_ioctl.c
++++ b/drivers/tty/tty_ioctl.c
+@@ -397,21 +397,42 @@ static int set_termios(struct tty_struct
+ 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;
++ }
++
++ 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);
++ }
+
+- tty_set_termios(tty, &tmp_termios);
++ 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
+--- a/include/linux/tty.h
++++ b/include/linux/tty.h
+@@ -480,6 +480,8 @@ extern void __stop_tty(struct tty_struct
+ extern void stop_tty(struct tty_struct *tty);
+ extern void __start_tty(struct tty_struct *tty);
+ extern 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);
+ extern int tty_register_driver(struct tty_driver *driver);
+ extern int tty_unregister_driver(struct tty_driver *driver);
+ extern struct device *tty_register_device(struct tty_driver *driver,