--- /dev/null
+From 27cab9fa2cdee6d12a88e50075a1ad6778c4be29 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 15 Jun 2023 17:18:53 +0900
+Subject: ata: libata-scsi: Avoid deadlock on rescan after device resume
+
+From: Damien Le Moal <dlemoal@kernel.org>
+
+[ Upstream commit 6aa0365a3c8512587fffd42fe438768709ddef8e ]
+
+When an ATA port is resumed from sleep, the port is reset and a power
+management request issued to libata EH to reset the port and rescanning
+the device(s) attached to the port. Device rescanning is done by
+scheduling an ata_scsi_dev_rescan() work, which will execute
+scsi_rescan_device().
+
+However, scsi_rescan_device() takes the generic device lock, which is
+also taken by dpm_resume() when the SCSI device is resumed as well. If
+a device rescan execution starts before the completion of the SCSI
+device resume, the rcu locking used to refresh the cached VPD pages of
+the device, combined with the generic device locking from
+scsi_rescan_device() and from dpm_resume() can cause a deadlock.
+
+Avoid this situation by changing struct ata_port scsi_rescan_task to be
+a delayed work instead of a simple work_struct. ata_scsi_dev_rescan() is
+modified to check if the SCSI device associated with the ATA device that
+must be rescanned is not suspended. If the SCSI device is still
+suspended, ata_scsi_dev_rescan() returns early and reschedule itself for
+execution after an arbitrary delay of 5ms.
+
+Reported-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Reported-by: Joe Breuer <linux-kernel@jmbreuer.net>
+Closes: https://bugzilla.kernel.org/show_bug.cgi?id=217530
+Fixes: a19a93e4c6a9 ("scsi: core: pm: Rely on the device driver core for async power management")
+Signed-off-by: Damien Le Moal <dlemoal@kernel.org>
+Reviewed-by: Hannes Reinecke <hare@suse.de>
+Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
+Tested-by: Joe Breuer <linux-kernel@jmbreuer.net>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/ata/libata-core.c | 3 ++-
+ drivers/ata/libata-eh.c | 2 +-
+ drivers/ata/libata-scsi.c | 22 +++++++++++++++++++++-
+ include/linux/libata.h | 2 +-
+ 4 files changed, 25 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
+index a5ea144722fa3..0ba0c3d1613f1 100644
+--- a/drivers/ata/libata-core.c
++++ b/drivers/ata/libata-core.c
+@@ -5313,7 +5313,7 @@ struct ata_port *ata_port_alloc(struct ata_host *host)
+
+ mutex_init(&ap->scsi_scan_mutex);
+ INIT_DELAYED_WORK(&ap->hotplug_task, ata_scsi_hotplug);
+- INIT_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
++ INIT_DELAYED_WORK(&ap->scsi_rescan_task, ata_scsi_dev_rescan);
+ INIT_LIST_HEAD(&ap->eh_done_q);
+ init_waitqueue_head(&ap->eh_wait_q);
+ init_completion(&ap->park_req_pending);
+@@ -5919,6 +5919,7 @@ static void ata_port_detach(struct ata_port *ap)
+ WARN_ON(!(ap->pflags & ATA_PFLAG_UNLOADED));
+
+ cancel_delayed_work_sync(&ap->hotplug_task);
++ cancel_delayed_work_sync(&ap->scsi_rescan_task);
+
+ skip_eh:
+ /* clean up zpodd on port removal */
+diff --git a/drivers/ata/libata-eh.c b/drivers/ata/libata-eh.c
+index 08e11bc312c28..a3ae5fc2a42fc 100644
+--- a/drivers/ata/libata-eh.c
++++ b/drivers/ata/libata-eh.c
+@@ -2973,7 +2973,7 @@ static int ata_eh_revalidate_and_attach(struct ata_link *link,
+ ehc->i.flags |= ATA_EHI_SETMODE;
+
+ /* schedule the scsi_rescan_device() here */
+- schedule_work(&(ap->scsi_rescan_task));
++ schedule_delayed_work(&ap->scsi_rescan_task, 0);
+ } else if (dev->class == ATA_DEV_UNKNOWN &&
+ ehc->tries[dev->devno] &&
+ ata_class_enabled(ehc->classes[dev->devno])) {
+diff --git a/drivers/ata/libata-scsi.c b/drivers/ata/libata-scsi.c
+index 39e1ff9b686b9..9c0052d28078a 100644
+--- a/drivers/ata/libata-scsi.c
++++ b/drivers/ata/libata-scsi.c
+@@ -4601,10 +4601,11 @@ int ata_scsi_user_scan(struct Scsi_Host *shost, unsigned int channel,
+ void ata_scsi_dev_rescan(struct work_struct *work)
+ {
+ struct ata_port *ap =
+- container_of(work, struct ata_port, scsi_rescan_task);
++ container_of(work, struct ata_port, scsi_rescan_task.work);
+ struct ata_link *link;
+ struct ata_device *dev;
+ unsigned long flags;
++ bool delay_rescan = false;
+
+ mutex_lock(&ap->scsi_scan_mutex);
+ spin_lock_irqsave(ap->lock, flags);
+@@ -4618,6 +4619,21 @@ void ata_scsi_dev_rescan(struct work_struct *work)
+ if (scsi_device_get(sdev))
+ continue;
+
++ /*
++ * If the rescan work was scheduled because of a resume
++ * event, the port is already fully resumed, but the
++ * SCSI device may not yet be fully resumed. In such
++ * case, executing scsi_rescan_device() may cause a
++ * deadlock with the PM code on device_lock(). Prevent
++ * this by giving up and retrying rescan after a short
++ * delay.
++ */
++ delay_rescan = sdev->sdev_gendev.power.is_suspended;
++ if (delay_rescan) {
++ scsi_device_put(sdev);
++ break;
++ }
++
+ spin_unlock_irqrestore(ap->lock, flags);
+ scsi_rescan_device(&(sdev->sdev_gendev));
+ scsi_device_put(sdev);
+@@ -4627,4 +4643,8 @@ void ata_scsi_dev_rescan(struct work_struct *work)
+
+ spin_unlock_irqrestore(ap->lock, flags);
+ mutex_unlock(&ap->scsi_scan_mutex);
++
++ if (delay_rescan)
++ schedule_delayed_work(&ap->scsi_rescan_task,
++ msecs_to_jiffies(5));
+ }
+diff --git a/include/linux/libata.h b/include/linux/libata.h
+index fe990176e6ee9..9713f4d8f15f4 100644
+--- a/include/linux/libata.h
++++ b/include/linux/libata.h
+@@ -834,7 +834,7 @@ struct ata_port {
+
+ struct mutex scsi_scan_mutex;
+ struct delayed_work hotplug_task;
+- struct work_struct scsi_rescan_task;
++ struct delayed_work scsi_rescan_task;
+
+ unsigned int hsm_task_state;
+
+--
+2.39.2
+
--- /dev/null
+From 4643e048dfd25c91d15772d37f62acc642bd0060 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 23 Feb 2023 11:36:08 -0700
+Subject: drm/amd/display: Add wrapper to call planes and stream update
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+[ Upstream commit 81f743a08f3b214638aa389e252ae5e6c3592e7c ]
+
+[Why & How]
+This commit is part of a sequence of changes that replaces the commit
+sequence used in the DC with a new one. As a result of this transition,
+we moved some specific parts from the commit sequence and brought them
+to amdgpu_dm. This commit adds a wrapper inside DM that enable our
+drivers to do any necessary preparation or change before we offload the
+plane/stream update to DC.
+
+Reviewed-by: Harry Wentland <Harry.Wentland@amd.com>
+Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
+Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: ea2062dd1f03 ("drm/amd/display: fix the system hang while disable PSR")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 51 +++++++++++++++----
+ 1 file changed, 41 insertions(+), 10 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index a7bc57529e6c9..91f074f4f262c 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -348,6 +348,35 @@ static inline bool is_dc_timing_adjust_needed(struct dm_crtc_state *old_state,
+ return false;
+ }
+
++/**
++ * update_planes_and_stream_adapter() - Send planes to be updated in DC
++ *
++ * DC has a generic way to update planes and stream via
++ * dc_update_planes_and_stream function; however, DM might need some
++ * adjustments and preparation before calling it. This function is a wrapper
++ * for the dc_update_planes_and_stream that does any required configuration
++ * before passing control to DC.
++ */
++static inline bool update_planes_and_stream_adapter(struct dc *dc,
++ int update_type,
++ int planes_count,
++ struct dc_stream_state *stream,
++ struct dc_stream_update *stream_update,
++ struct dc_surface_update *array_of_surface_update)
++{
++ /*
++ * Previous frame finished and HW is ready for optimization.
++ */
++ if (update_type == UPDATE_TYPE_FAST)
++ dc_post_update_surfaces_to_stream(dc);
++
++ return dc_update_planes_and_stream(dc,
++ array_of_surface_update,
++ planes_count,
++ stream,
++ stream_update);
++}
++
+ /**
+ * dm_pflip_high_irq() - Handle pageflip interrupt
+ * @interrupt_params: ignored
+@@ -2633,11 +2662,12 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
+ true;
+ }
+
+- dc_update_planes_and_stream(dm->dc,
+- bundle->surface_updates,
+- dc_state->stream_status->plane_count,
+- dc_state->streams[k],
+- &bundle->stream_update);
++ update_planes_and_stream_adapter(dm->dc,
++ UPDATE_TYPE_FULL,
++ dc_state->stream_status->plane_count,
++ dc_state->streams[k],
++ &bundle->stream_update,
++ bundle->surface_updates);
+ }
+
+ cleanup:
+@@ -7889,11 +7919,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
+ acrtc_state->stream->link->psr_settings.psr_allow_active)
+ amdgpu_dm_psr_disable(acrtc_state->stream);
+
+- dc_update_planes_and_stream(dm->dc,
+- bundle->surface_updates,
+- planes_count,
+- acrtc_state->stream,
+- &bundle->stream_update);
++ update_planes_and_stream_adapter(dm->dc,
++ acrtc_state->update_type,
++ planes_count,
++ acrtc_state->stream,
++ &bundle->stream_update,
++ bundle->surface_updates);
+
+ /**
+ * Enable or disable the interrupts on the backend.
+--
+2.39.2
+
--- /dev/null
+From 4f8cdc5fed65ebd746232fac1a98a98be8f684d3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 29 May 2023 18:00:09 +0800
+Subject: drm/amd/display: fix the system hang while disable PSR
+
+From: Tom Chung <chiahsuan.chung@amd.com>
+
+[ Upstream commit ea2062dd1f0384ae1b136d333ee4ced15bedae38 ]
+
+[Why]
+When the PSR enabled. If you try to adjust the timing parameters,
+it may cause system hang. Because the timing mismatch with the
+DMCUB settings.
+
+[How]
+Disable the PSR before adjusting timing parameters.
+
+Cc: Mario Limonciello <mario.limonciello@amd.com>
+Cc: Alex Deucher <alexander.deucher@amd.com>
+Cc: stable@vger.kernel.org
+Acked-by: Stylon Wang <stylon.wang@amd.com>
+Signed-off-by: Tom Chung <chiahsuan.chung@amd.com>
+Reviewed-by: Wayne Lin <Wayne.Lin@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 10 ++++++----
+ 1 file changed, 6 insertions(+), 4 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 91f074f4f262c..91c308cf27eb2 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -7902,6 +7902,12 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
+ if (acrtc_state->abm_level != dm_old_crtc_state->abm_level)
+ bundle->stream_update.abm_level = &acrtc_state->abm_level;
+
++ mutex_lock(&dm->dc_lock);
++ if ((acrtc_state->update_type > UPDATE_TYPE_FAST) &&
++ acrtc_state->stream->link->psr_settings.psr_allow_active)
++ amdgpu_dm_psr_disable(acrtc_state->stream);
++ mutex_unlock(&dm->dc_lock);
++
+ /*
+ * If FreeSync state on the stream has changed then we need to
+ * re-adjust the min/max bounds now that DC doesn't handle this
+@@ -7915,10 +7921,6 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
+ spin_unlock_irqrestore(&pcrtc->dev->event_lock, flags);
+ }
+ mutex_lock(&dm->dc_lock);
+- if ((acrtc_state->update_type > UPDATE_TYPE_FAST) &&
+- acrtc_state->stream->link->psr_settings.psr_allow_active)
+- amdgpu_dm_psr_disable(acrtc_state->stream);
+-
+ update_planes_and_stream_adapter(dm->dc,
+ acrtc_state->update_type,
+ planes_count,
+--
+2.39.2
+
--- /dev/null
+From 64f7536f7557f7c03a70c90464cbfea220c87ee6 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Thu, 6 Oct 2022 16:40:55 -0400
+Subject: drm/amd/display: Use dc_update_planes_and_stream
+
+From: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+
+[ Upstream commit f7511289821ffccc07579406d6ab520aa11049f5 ]
+
+[Why & How]
+The old dc_commit_updates_for_stream lacks manipulation for many corner
+cases where the DC feature requires special attention; as a result, it
+starts to show its limitation (e.g., the SubVP feature is not supported
+by it, among other cases). To modernize and unify our internal API, this
+commit replaces the old dc_commit_updates_for_stream with
+dc_update_planes_and_stream, which has more features.
+
+Reviewed-by: Harry Wentland <Harry.Wentland@amd.com>
+Acked-by: Qingqing Zhuo <qingqing.zhuo@amd.com>
+Signed-off-by: Rodrigo Siqueira <Rodrigo.Siqueira@amd.com>
+Tested-by: Daniel Wheeler <daniel.wheeler@amd.com>
+Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
+Stable-dep-of: ea2062dd1f03 ("drm/amd/display: fix the system hang while disable PSR")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ .../gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c | 30 +++++++++----------
+ 1 file changed, 15 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+index 53687de6c0530..a7bc57529e6c9 100644
+--- a/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
++++ b/drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm.c
+@@ -2632,10 +2632,12 @@ static void dm_gpureset_commit_state(struct dc_state *dc_state,
+ bundle->surface_updates[m].surface->force_full_update =
+ true;
+ }
+- dc_commit_updates_for_stream(
+- dm->dc, bundle->surface_updates,
++
++ dc_update_planes_and_stream(dm->dc,
++ bundle->surface_updates,
+ dc_state->stream_status->plane_count,
+- dc_state->streams[k], &bundle->stream_update, dc_state);
++ dc_state->streams[k],
++ &bundle->stream_update);
+ }
+
+ cleanup:
+@@ -7887,12 +7889,11 @@ static void amdgpu_dm_commit_planes(struct drm_atomic_state *state,
+ acrtc_state->stream->link->psr_settings.psr_allow_active)
+ amdgpu_dm_psr_disable(acrtc_state->stream);
+
+- dc_commit_updates_for_stream(dm->dc,
+- bundle->surface_updates,
+- planes_count,
+- acrtc_state->stream,
+- &bundle->stream_update,
+- dc_state);
++ dc_update_planes_and_stream(dm->dc,
++ bundle->surface_updates,
++ planes_count,
++ acrtc_state->stream,
++ &bundle->stream_update);
+
+ /**
+ * Enable or disable the interrupts on the backend.
+@@ -8334,12 +8335,11 @@ static void amdgpu_dm_atomic_commit_tail(struct drm_atomic_state *state)
+
+
+ mutex_lock(&dm->dc_lock);
+- dc_commit_updates_for_stream(dm->dc,
+- dummy_updates,
+- status->plane_count,
+- dm_new_crtc_state->stream,
+- &stream_update,
+- dc_state);
++ dc_update_planes_and_stream(dm->dc,
++ dummy_updates,
++ status->plane_count,
++ dm_new_crtc_state->stream,
++ &stream_update);
+ mutex_unlock(&dm->dc_lock);
+ }
+
+--
+2.39.2
+
--- /dev/null
+drm-amd-display-use-dc_update_planes_and_stream.patch
+drm-amd-display-add-wrapper-to-call-planes-and-strea.patch
+drm-amd-display-fix-the-system-hang-while-disable-ps.patch
+tty-serial-fsl_lpuart-make-rx_watermark-configurable.patch
+tty-serial-fsl_lpuart-reduce-rx-watermark-to-0-on-ls.patch
+ata-libata-scsi-avoid-deadlock-on-rescan-after-devic.patch
--- /dev/null
+From 188f738da662b7eee811bf53bec71cd8a543bc18 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Mon, 30 Jan 2023 14:44:44 +0800
+Subject: tty: serial: fsl_lpuart: make rx_watermark configurable for different
+ platforms
+
+From: Sherry Sun <sherry.sun@nxp.com>
+
+[ Upstream commit 34ebb26f12a84b744f43c5c4869516f122a2dfaa ]
+
+Add rx_watermark parameter for struct lpuart_port to make the receive
+watermark configurable for different platforms.
+No function changed.
+
+Signed-off-by: Sherry Sun <sherry.sun@nxp.com>
+Link: https://lore.kernel.org/r/20230130064449.9564-2-sherry.sun@nxp.com
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Stable-dep-of: a82c3df955f8 ("tty: serial: fsl_lpuart: reduce RX watermark to 0 on LS1028A")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/fsl_lpuart.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
+index dc7ac1ddbca5e..82066f17bdfb1 100644
+--- a/drivers/tty/serial/fsl_lpuart.c
++++ b/drivers/tty/serial/fsl_lpuart.c
+@@ -257,6 +257,7 @@ struct lpuart_port {
+ unsigned int txfifo_size;
+ unsigned int rxfifo_size;
+
++ u8 rx_watermark;
+ bool lpuart_dma_tx_use;
+ bool lpuart_dma_rx_use;
+ struct dma_chan *dma_tx_chan;
+@@ -283,38 +284,45 @@ struct lpuart_soc_data {
+ enum lpuart_type devtype;
+ char iotype;
+ u8 reg_off;
++ u8 rx_watermark;
+ };
+
+ static const struct lpuart_soc_data vf_data = {
+ .devtype = VF610_LPUART,
+ .iotype = UPIO_MEM,
++ .rx_watermark = 1,
+ };
+
+ static const struct lpuart_soc_data ls1021a_data = {
+ .devtype = LS1021A_LPUART,
+ .iotype = UPIO_MEM32BE,
++ .rx_watermark = 1,
+ };
+
+ static const struct lpuart_soc_data ls1028a_data = {
+ .devtype = LS1028A_LPUART,
+ .iotype = UPIO_MEM32,
++ .rx_watermark = 1,
+ };
+
+ static struct lpuart_soc_data imx7ulp_data = {
+ .devtype = IMX7ULP_LPUART,
+ .iotype = UPIO_MEM32,
+ .reg_off = IMX_REG_OFF,
++ .rx_watermark = 1,
+ };
+
+ static struct lpuart_soc_data imx8qxp_data = {
+ .devtype = IMX8QXP_LPUART,
+ .iotype = UPIO_MEM32,
+ .reg_off = IMX_REG_OFF,
++ .rx_watermark = 1,
+ };
+ static struct lpuart_soc_data imxrt1050_data = {
+ .devtype = IMXRT1050_LPUART,
+ .iotype = UPIO_MEM32,
+ .reg_off = IMX_REG_OFF,
++ .rx_watermark = 1,
+ };
+
+ static const struct of_device_id lpuart_dt_ids[] = {
+@@ -1533,7 +1541,7 @@ static void lpuart_setup_watermark(struct lpuart_port *sport)
+ }
+
+ writeb(0, sport->port.membase + UARTTWFIFO);
+- writeb(1, sport->port.membase + UARTRWFIFO);
++ writeb(sport->rx_watermark, sport->port.membase + UARTRWFIFO);
+
+ /* Restore cr2 */
+ writeb(cr2_saved, sport->port.membase + UARTCR2);
+@@ -1568,7 +1576,8 @@ static void lpuart32_setup_watermark(struct lpuart_port *sport)
+ lpuart32_write(&sport->port, val, UARTFIFO);
+
+ /* set the watermark */
+- val = (0x1 << UARTWATER_RXWATER_OFF) | (0x0 << UARTWATER_TXWATER_OFF);
++ val = (sport->rx_watermark << UARTWATER_RXWATER_OFF) |
++ (0x0 << UARTWATER_TXWATER_OFF);
+ lpuart32_write(&sport->port, val, UARTWATER);
+
+ /* Restore cr2 */
+@@ -2714,6 +2723,7 @@ static int lpuart_probe(struct platform_device *pdev)
+ sport->port.dev = &pdev->dev;
+ sport->port.type = PORT_LPUART;
+ sport->devtype = sdata->devtype;
++ sport->rx_watermark = sdata->rx_watermark;
+ ret = platform_get_irq(pdev, 0);
+ if (ret < 0)
+ return ret;
+--
+2.39.2
+
--- /dev/null
+From aba04d59fa845ed313893f76f1bed54852391059 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Fri, 9 Jun 2023 14:13:34 +0200
+Subject: tty: serial: fsl_lpuart: reduce RX watermark to 0 on LS1028A
+
+From: Robert Hodaszi <robert.hodaszi@digi.com>
+
+[ Upstream commit a82c3df955f8c1c726e4976527aa6ae924a67dd9 ]
+
+LS1028A is using DMA with LPUART. Having RX watermark set to 1, means
+DMA transactions are started only after receiving the second character.
+
+On other platforms with newer LPUART IP, Receiver Idle Empty function
+initiates the DMA request after the receiver is idling for 4 characters.
+But this feature is missing on LS1028A, which is causing a 1-character
+delay in the RX direction on this platform.
+
+Set RX watermark to 0 to initiate RX DMA after each character.
+
+Link: https://lore.kernel.org/linux-serial/20230607103459.1222426-1-robert.hodaszi@digi.com/
+Fixes: 9ad9df844754 ("tty: serial: fsl_lpuart: Fix the wrong RXWATER setting for rx dma case")
+Cc: stable <stable@kernel.org>
+Signed-off-by: Robert Hodaszi <robert.hodaszi@digi.com>
+Message-ID: <20230609121334.1878626-1-robert.hodaszi@digi.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/tty/serial/fsl_lpuart.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
+index 82066f17bdfb1..1093c74b52840 100644
+--- a/drivers/tty/serial/fsl_lpuart.c
++++ b/drivers/tty/serial/fsl_lpuart.c
+@@ -302,7 +302,7 @@ static const struct lpuart_soc_data ls1021a_data = {
+ static const struct lpuart_soc_data ls1028a_data = {
+ .devtype = LS1028A_LPUART,
+ .iotype = UPIO_MEM32,
+- .rx_watermark = 1,
++ .rx_watermark = 0,
+ };
+
+ static struct lpuart_soc_data imx7ulp_data = {
+--
+2.39.2
+