--- /dev/null
+From 6460f2928f75e0db6289f78ff562d4b566193b7b Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Wed, 7 Feb 2024 14:47:32 -0500
+Subject: dmaengine: fsl-edma: correct max_segment_size setting
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit a79f949a5ce1d45329d63742c2a995f2b47f9852 ]
+
+Correcting the previous setting of 0x3fff to the actual value of 0x7fff.
+
+Introduced new macro 'EDMA_TCD_ITER_MASK' for improved code clarity and
+utilization of FIELD_GET to obtain the accurate maximum value.
+
+Cc: stable@vger.kernel.org
+Fixes: e06748539432 ("dmaengine: fsl-edma: support edma memcpy")
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20240207194733.2112870-1-Frank.Li@nxp.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/fsl-edma-common.h | 5 +++--
+ drivers/dma/fsl-edma-main.c | 4 +++-
+ 2 files changed, 6 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/dma/fsl-edma-common.h b/drivers/dma/fsl-edma-common.h
+index bb5221158a770..f5e216b157c75 100644
+--- a/drivers/dma/fsl-edma-common.h
++++ b/drivers/dma/fsl-edma-common.h
+@@ -30,8 +30,9 @@
+ #define EDMA_TCD_ATTR_SSIZE(x) (((x) & GENMASK(2, 0)) << 8)
+ #define EDMA_TCD_ATTR_SMOD(x) (((x) & GENMASK(4, 0)) << 11)
+
+-#define EDMA_TCD_CITER_CITER(x) ((x) & GENMASK(14, 0))
+-#define EDMA_TCD_BITER_BITER(x) ((x) & GENMASK(14, 0))
++#define EDMA_TCD_ITER_MASK GENMASK(14, 0)
++#define EDMA_TCD_CITER_CITER(x) ((x) & EDMA_TCD_ITER_MASK)
++#define EDMA_TCD_BITER_BITER(x) ((x) & EDMA_TCD_ITER_MASK)
+
+ #define EDMA_TCD_CSR_START BIT(0)
+ #define EDMA_TCD_CSR_INT_MAJOR BIT(1)
+diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c
+index 45cc419b1b4ac..d36e28b9c767a 100644
+--- a/drivers/dma/fsl-edma-main.c
++++ b/drivers/dma/fsl-edma-main.c
+@@ -10,6 +10,7 @@
+ */
+
+ #include <dt-bindings/dma/fsl-edma.h>
++#include <linux/bitfield.h>
+ #include <linux/module.h>
+ #include <linux/interrupt.h>
+ #include <linux/clk.h>
+@@ -582,7 +583,8 @@ static int fsl_edma_probe(struct platform_device *pdev)
+ DMAENGINE_ALIGN_32_BYTES;
+
+ /* Per worst case 'nbytes = 1' take CITER as the max_seg_size */
+- dma_set_max_seg_size(fsl_edma->dma_dev.dev, 0x3fff);
++ dma_set_max_seg_size(fsl_edma->dma_dev.dev,
++ FIELD_GET(EDMA_TCD_ITER_MASK, EDMA_TCD_ITER_MASK));
+
+ fsl_edma->dma_dev.residue_granularity = DMA_RESIDUE_GRANULARITY_SEGMENT;
+
+--
+2.43.0
+
--- /dev/null
+From ec7dd0a2ede3646cd4ef01d0026d36bd8f7bfb53 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Nov 2023 10:48:23 -0500
+Subject: dmaengine: fsl-edma: utilize common dt-binding header file
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit d0e217b72f9f5c5ef35e3423d393ea8093ce98ec ]
+
+Refactor the code to use the common dt-binding header file, fsl-edma.h.
+Renaming ARGS* to FSL_EDMA*, ensuring no functional changes.
+
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Link: https://lore.kernel.org/r/20231114154824.3617255-4-Frank.Li@nxp.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Stable-dep-of: a79f949a5ce1 ("dmaengine: fsl-edma: correct max_segment_size setting")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/dma/fsl-edma-main.c | 17 ++++++-----------
+ 1 file changed, 6 insertions(+), 11 deletions(-)
+
+diff --git a/drivers/dma/fsl-edma-main.c b/drivers/dma/fsl-edma-main.c
+index 75cae7ccae270..45cc419b1b4ac 100644
+--- a/drivers/dma/fsl-edma-main.c
++++ b/drivers/dma/fsl-edma-main.c
+@@ -9,6 +9,7 @@
+ * Vybrid and Layerscape SoCs.
+ */
+
++#include <dt-bindings/dma/fsl-edma.h>
+ #include <linux/module.h>
+ #include <linux/interrupt.h>
+ #include <linux/clk.h>
+@@ -21,12 +22,6 @@
+
+ #include "fsl-edma-common.h"
+
+-#define ARGS_RX BIT(0)
+-#define ARGS_REMOTE BIT(1)
+-#define ARGS_MULTI_FIFO BIT(2)
+-#define ARGS_EVEN_CH BIT(3)
+-#define ARGS_ODD_CH BIT(4)
+-
+ static void fsl_edma_synchronize(struct dma_chan *chan)
+ {
+ struct fsl_edma_chan *fsl_chan = to_fsl_edma_chan(chan);
+@@ -155,14 +150,14 @@ static struct dma_chan *fsl_edma3_xlate(struct of_phandle_args *dma_spec,
+ i = fsl_chan - fsl_edma->chans;
+
+ fsl_chan->priority = dma_spec->args[1];
+- fsl_chan->is_rxchan = dma_spec->args[2] & ARGS_RX;
+- fsl_chan->is_remote = dma_spec->args[2] & ARGS_REMOTE;
+- fsl_chan->is_multi_fifo = dma_spec->args[2] & ARGS_MULTI_FIFO;
++ fsl_chan->is_rxchan = dma_spec->args[2] & FSL_EDMA_RX;
++ fsl_chan->is_remote = dma_spec->args[2] & FSL_EDMA_REMOTE;
++ fsl_chan->is_multi_fifo = dma_spec->args[2] & FSL_EDMA_MULTI_FIFO;
+
+- if ((dma_spec->args[2] & ARGS_EVEN_CH) && (i & 0x1))
++ if ((dma_spec->args[2] & FSL_EDMA_EVEN_CH) && (i & 0x1))
+ continue;
+
+- if ((dma_spec->args[2] & ARGS_ODD_CH) && !(i & 0x1))
++ if ((dma_spec->args[2] & FSL_EDMA_ODD_CH) && !(i & 0x1))
+ continue;
+
+ if (!b_chmux && i == dma_spec->args[0]) {
+--
+2.43.0
+
--- /dev/null
+From 17e9df4c7836d0de0a085dca309eba6b7a2c2747 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 3 Dec 2023 14:43:28 +0300
+Subject: drm/bridge: add transparent bridge helper
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 2a04739139b2b2761571e18937e2400e71eff664 ]
+
+Define a helper for creating simple transparent bridges which serve the
+only purpose of linking devices into the bridge chain up to the last
+bridge representing the connector. This is especially useful for
+DP/USB-C bridge chains, which can span across several devices, but do
+not require any additional functionality from the intermediate bridges.
+
+Reviewed-by: Neil Armstrong <neil.armstrong@linaro.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20231203114333.1305826-2-dmitry.baryshkov@linaro.org
+Stable-dep-of: b979f2d50a09 ("soc: qcom: pmic_glink_altmode: fix drm bridge use-after-free")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/Kconfig | 9 ++
+ drivers/gpu/drm/bridge/Makefile | 1 +
+ drivers/gpu/drm/bridge/aux-bridge.c | 140 ++++++++++++++++++++++++++++
+ include/drm/bridge/aux-bridge.h | 19 ++++
+ 4 files changed, 169 insertions(+)
+ create mode 100644 drivers/gpu/drm/bridge/aux-bridge.c
+ create mode 100644 include/drm/bridge/aux-bridge.h
+
+diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
+index 3e6a4e2044c0e..a22645efe93a0 100644
+--- a/drivers/gpu/drm/bridge/Kconfig
++++ b/drivers/gpu/drm/bridge/Kconfig
+@@ -12,6 +12,15 @@ config DRM_PANEL_BRIDGE
+ help
+ DRM bridge wrapper of DRM panels
+
++config DRM_AUX_BRIDGE
++ tristate
++ depends on DRM_BRIDGE && OF
++ select AUXILIARY_BUS
++ select DRM_PANEL_BRIDGE
++ help
++ Simple transparent bridge that is used by several non-DRM drivers to
++ build bridges chain.
++
+ menu "Display Interface Bridges"
+ depends on DRM && DRM_BRIDGE
+
+diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
+index 2b892b7ed59e8..918e3bfff079c 100644
+--- a/drivers/gpu/drm/bridge/Makefile
++++ b/drivers/gpu/drm/bridge/Makefile
+@@ -1,4 +1,5 @@
+ # SPDX-License-Identifier: GPL-2.0
++obj-$(CONFIG_DRM_AUX_BRIDGE) += aux-bridge.o
+ obj-$(CONFIG_DRM_CHIPONE_ICN6211) += chipone-icn6211.o
+ obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o
+ obj-$(CONFIG_DRM_CROS_EC_ANX7688) += cros-ec-anx7688.o
+diff --git a/drivers/gpu/drm/bridge/aux-bridge.c b/drivers/gpu/drm/bridge/aux-bridge.c
+new file mode 100644
+index 0000000000000..49d7c2ab1ecc3
+--- /dev/null
++++ b/drivers/gpu/drm/bridge/aux-bridge.c
+@@ -0,0 +1,140 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright (C) 2023 Linaro Ltd.
++ *
++ * Author: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
++ */
++#include <linux/auxiliary_bus.h>
++#include <linux/module.h>
++
++#include <drm/drm_bridge.h>
++#include <drm/bridge/aux-bridge.h>
++
++static DEFINE_IDA(drm_aux_bridge_ida);
++
++static void drm_aux_bridge_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ ida_free(&drm_aux_bridge_ida, adev->id);
++
++ kfree(adev);
++}
++
++static void drm_aux_bridge_unregister_adev(void *_adev)
++{
++ struct auxiliary_device *adev = _adev;
++
++ auxiliary_device_delete(adev);
++ auxiliary_device_uninit(adev);
++}
++
++/**
++ * drm_aux_bridge_register - Create a simple bridge device to link the chain
++ * @parent: device instance providing this bridge
++ *
++ * Creates a simple DRM bridge that doesn't implement any drm_bridge
++ * operations. Such bridges merely fill a place in the bridge chain linking
++ * surrounding DRM bridges.
++ *
++ * Return: zero on success, negative error code on failure
++ */
++int drm_aux_bridge_register(struct device *parent)
++{
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return -ENOMEM;
++
++ ret = ida_alloc(&drm_aux_bridge_ida, GFP_KERNEL);
++ if (ret < 0) {
++ kfree(adev);
++ return ret;
++ }
++
++ adev->id = ret;
++ adev->name = "aux_bridge";
++ adev->dev.parent = parent;
++ adev->dev.of_node = parent->of_node;
++ adev->dev.release = drm_aux_bridge_release;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ ida_free(&drm_aux_bridge_ida, adev->id);
++ kfree(adev);
++ return ret;
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ret;
++ }
++
++ return devm_add_action_or_reset(parent, drm_aux_bridge_unregister_adev, adev);
++}
++EXPORT_SYMBOL_GPL(drm_aux_bridge_register);
++
++struct drm_aux_bridge_data {
++ struct drm_bridge bridge;
++ struct drm_bridge *next_bridge;
++ struct device *dev;
++};
++
++static int drm_aux_bridge_attach(struct drm_bridge *bridge,
++ enum drm_bridge_attach_flags flags)
++{
++ struct drm_aux_bridge_data *data;
++
++ if (!(flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR))
++ return -EINVAL;
++
++ data = container_of(bridge, struct drm_aux_bridge_data, bridge);
++
++ return drm_bridge_attach(bridge->encoder, data->next_bridge, bridge,
++ DRM_BRIDGE_ATTACH_NO_CONNECTOR);
++}
++
++static const struct drm_bridge_funcs drm_aux_bridge_funcs = {
++ .attach = drm_aux_bridge_attach,
++};
++
++static int drm_aux_bridge_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++{
++ struct drm_aux_bridge_data *data;
++
++ data = devm_kzalloc(&auxdev->dev, sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ data->dev = &auxdev->dev;
++ data->next_bridge = devm_drm_of_get_bridge(&auxdev->dev, auxdev->dev.of_node, 0, 0);
++ if (IS_ERR(data->next_bridge))
++ return dev_err_probe(&auxdev->dev, PTR_ERR(data->next_bridge),
++ "failed to acquire drm_bridge\n");
++
++ data->bridge.funcs = &drm_aux_bridge_funcs;
++ data->bridge.of_node = data->dev->of_node;
++
++ return devm_drm_bridge_add(data->dev, &data->bridge);
++}
++
++static const struct auxiliary_device_id drm_aux_bridge_table[] = {
++ { .name = KBUILD_MODNAME ".aux_bridge" },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, drm_aux_bridge_table);
++
++static struct auxiliary_driver drm_aux_bridge_drv = {
++ .name = "aux_bridge",
++ .id_table = drm_aux_bridge_table,
++ .probe = drm_aux_bridge_probe,
++};
++module_auxiliary_driver(drm_aux_bridge_drv);
++
++MODULE_AUTHOR("Dmitry Baryshkov <dmitry.baryshkov@linaro.org>");
++MODULE_DESCRIPTION("DRM transparent bridge");
++MODULE_LICENSE("GPL");
+diff --git a/include/drm/bridge/aux-bridge.h b/include/drm/bridge/aux-bridge.h
+new file mode 100644
+index 0000000000000..b3a9cc9c862fd
+--- /dev/null
++++ b/include/drm/bridge/aux-bridge.h
+@@ -0,0 +1,19 @@
++/* SPDX-License-Identifier: GPL-2.0+ */
++/*
++ * Copyright (C) 2023 Linaro Ltd.
++ *
++ * Author: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
++ */
++#ifndef DRM_AUX_BRIDGE_H
++#define DRM_AUX_BRIDGE_H
++
++#if IS_ENABLED(CONFIG_DRM_AUX_BRIDGE)
++int drm_aux_bridge_register(struct device *parent);
++#else
++static inline int drm_aux_bridge_register(struct device *parent)
++{
++ return 0;
++}
++#endif
++
++#endif
+--
+2.43.0
+
--- /dev/null
+From 357c636cf7159761a5bf455bd7e68e1c884eaa60 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 17 Feb 2024 16:02:24 +0100
+Subject: drm/bridge: aux-hpd: separate allocation and registration
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+[ Upstream commit e5ca263508f7e9d2cf711edf3258d11ca087885c ]
+
+Combining allocation and registration is an anti-pattern that should be
+avoided. Add two new functions for allocating and registering an dp-hpd
+bridge with a proper 'devm' prefix so that it is clear that these are
+device managed interfaces.
+
+ devm_drm_dp_hpd_bridge_alloc()
+ devm_drm_dp_hpd_bridge_add()
+
+The new interface will be used to fix a use-after-free bug in the
+Qualcomm PMIC GLINK driver and may prevent similar issues from being
+introduced elsewhere.
+
+The existing drm_dp_hpd_bridge_register() is reimplemented using the
+above and left in place for now.
+
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Reviewed-by: Bjorn Andersson <andersson@kernel.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240217150228.5788-3-johan+linaro@kernel.org
+Stable-dep-of: b979f2d50a09 ("soc: qcom: pmic_glink_altmode: fix drm bridge use-after-free")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/aux-hpd-bridge.c | 67 +++++++++++++++++++------
+ include/drm/bridge/aux-bridge.h | 15 ++++++
+ 2 files changed, 67 insertions(+), 15 deletions(-)
+
+diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
+index 5d2ab3a715f9c..44bb771211b82 100644
+--- a/drivers/gpu/drm/bridge/aux-hpd-bridge.c
++++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
+@@ -29,16 +29,13 @@ static void drm_aux_hpd_bridge_release(struct device *dev)
+ kfree(adev);
+ }
+
+-static void drm_aux_hpd_bridge_unregister_adev(void *_adev)
++static void drm_aux_hpd_bridge_free_adev(void *_adev)
+ {
+- struct auxiliary_device *adev = _adev;
+-
+- auxiliary_device_delete(adev);
+- auxiliary_device_uninit(adev);
++ auxiliary_device_uninit(_adev);
+ }
+
+ /**
+- * drm_dp_hpd_bridge_register - Create a simple HPD DisplayPort bridge
++ * devm_drm_dp_hpd_bridge_alloc - allocate a HPD DisplayPort bridge
+ * @parent: device instance providing this bridge
+ * @np: device node pointer corresponding to this bridge instance
+ *
+@@ -46,11 +43,9 @@ static void drm_aux_hpd_bridge_unregister_adev(void *_adev)
+ * DRM_MODE_CONNECTOR_DisplayPort, which terminates the bridge chain and is
+ * able to send the HPD events.
+ *
+- * Return: device instance that will handle created bridge or an error code
+- * encoded into the pointer.
++ * Return: bridge auxiliary device pointer or an error pointer
+ */
+-struct device *drm_dp_hpd_bridge_register(struct device *parent,
+- struct device_node *np)
++struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent, struct device_node *np)
+ {
+ struct auxiliary_device *adev;
+ int ret;
+@@ -79,13 +74,55 @@ struct device *drm_dp_hpd_bridge_register(struct device *parent,
+ return ERR_PTR(ret);
+ }
+
+- ret = auxiliary_device_add(adev);
+- if (ret) {
+- auxiliary_device_uninit(adev);
++ ret = devm_add_action_or_reset(parent, drm_aux_hpd_bridge_free_adev, adev);
++ if (ret)
+ return ERR_PTR(ret);
+- }
+
+- ret = devm_add_action_or_reset(parent, drm_aux_hpd_bridge_unregister_adev, adev);
++ return adev;
++}
++EXPORT_SYMBOL_GPL(devm_drm_dp_hpd_bridge_alloc);
++
++static void drm_aux_hpd_bridge_del_adev(void *_adev)
++{
++ auxiliary_device_delete(_adev);
++}
++
++/**
++ * devm_drm_dp_hpd_bridge_add - register a HDP DisplayPort bridge
++ * @dev: struct device to tie registration lifetime to
++ * @adev: bridge auxiliary device to be registered
++ *
++ * Returns: zero on success or a negative errno
++ */
++int devm_drm_dp_hpd_bridge_add(struct device *dev, struct auxiliary_device *adev)
++{
++ int ret;
++
++ ret = auxiliary_device_add(adev);
++ if (ret)
++ return ret;
++
++ return devm_add_action_or_reset(dev, drm_aux_hpd_bridge_del_adev, adev);
++}
++EXPORT_SYMBOL_GPL(devm_drm_dp_hpd_bridge_add);
++
++/**
++ * drm_dp_hpd_bridge_register - allocate and register a HDP DisplayPort bridge
++ * @parent: device instance providing this bridge
++ * @np: device node pointer corresponding to this bridge instance
++ *
++ * Return: device instance that will handle created bridge or an error pointer
++ */
++struct device *drm_dp_hpd_bridge_register(struct device *parent, struct device_node *np)
++{
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = devm_drm_dp_hpd_bridge_alloc(parent, np);
++ if (IS_ERR(adev))
++ return ERR_CAST(adev);
++
++ ret = devm_drm_dp_hpd_bridge_add(parent, adev);
+ if (ret)
+ return ERR_PTR(ret);
+
+diff --git a/include/drm/bridge/aux-bridge.h b/include/drm/bridge/aux-bridge.h
+index 66249ff0858e7..874f177381e34 100644
+--- a/include/drm/bridge/aux-bridge.h
++++ b/include/drm/bridge/aux-bridge.h
+@@ -9,6 +9,8 @@
+
+ #include <drm/drm_connector.h>
+
++struct auxiliary_device;
++
+ #if IS_ENABLED(CONFIG_DRM_AUX_BRIDGE)
+ int drm_aux_bridge_register(struct device *parent);
+ #else
+@@ -19,10 +21,23 @@ static inline int drm_aux_bridge_register(struct device *parent)
+ #endif
+
+ #if IS_ENABLED(CONFIG_DRM_AUX_HPD_BRIDGE)
++struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent, struct device_node *np);
++int devm_drm_dp_hpd_bridge_add(struct device *dev, struct auxiliary_device *adev);
+ struct device *drm_dp_hpd_bridge_register(struct device *parent,
+ struct device_node *np);
+ void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status);
+ #else
++static inline struct auxiliary_device *devm_drm_dp_hpd_bridge_alloc(struct device *parent,
++ struct device_node *np)
++{
++ return NULL;
++}
++
++static inline int devm_drm_dp_hpd_bridge_add(struct auxiliary_device *adev)
++{
++ return 0;
++}
++
+ static inline struct device *drm_dp_hpd_bridge_register(struct device *parent,
+ struct device_node *np)
+ {
+--
+2.43.0
+
--- /dev/null
+From 4230cbaf334c8b0e1edc5130623d2cd45ec4345d Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 3 Dec 2023 14:43:31 +0300
+Subject: drm/bridge: implement generic DP HPD bridge
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit e560518a6c2e60f1566473c146fddcff3281f617 ]
+
+Several USB-C controllers implement a pretty simple DRM bridge which
+implements just the HPD notification operations. Add special helper
+for creating such simple bridges.
+
+Acked-by: Neil Armstrong <neil.armstrong@linaro.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20231203114333.1305826-5-dmitry.baryshkov@linaro.org
+Stable-dep-of: b979f2d50a09 ("soc: qcom: pmic_glink_altmode: fix drm bridge use-after-free")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/gpu/drm/bridge/Kconfig | 8 ++
+ drivers/gpu/drm/bridge/Makefile | 1 +
+ drivers/gpu/drm/bridge/aux-hpd-bridge.c | 163 ++++++++++++++++++++++++
+ include/drm/bridge/aux-bridge.h | 18 +++
+ 4 files changed, 190 insertions(+)
+ create mode 100644 drivers/gpu/drm/bridge/aux-hpd-bridge.c
+
+diff --git a/drivers/gpu/drm/bridge/Kconfig b/drivers/gpu/drm/bridge/Kconfig
+index a22645efe93a0..efd996f6c1384 100644
+--- a/drivers/gpu/drm/bridge/Kconfig
++++ b/drivers/gpu/drm/bridge/Kconfig
+@@ -21,6 +21,14 @@ config DRM_AUX_BRIDGE
+ Simple transparent bridge that is used by several non-DRM drivers to
+ build bridges chain.
+
++config DRM_AUX_HPD_BRIDGE
++ tristate
++ depends on DRM_BRIDGE && OF
++ select AUXILIARY_BUS
++ help
++ Simple bridge that terminates the bridge chain and provides HPD
++ support.
++
+ menu "Display Interface Bridges"
+ depends on DRM && DRM_BRIDGE
+
+diff --git a/drivers/gpu/drm/bridge/Makefile b/drivers/gpu/drm/bridge/Makefile
+index 918e3bfff079c..017b5832733b2 100644
+--- a/drivers/gpu/drm/bridge/Makefile
++++ b/drivers/gpu/drm/bridge/Makefile
+@@ -1,5 +1,6 @@
+ # SPDX-License-Identifier: GPL-2.0
+ obj-$(CONFIG_DRM_AUX_BRIDGE) += aux-bridge.o
++obj-$(CONFIG_DRM_AUX_HPD_BRIDGE) += aux-hpd-bridge.o
+ obj-$(CONFIG_DRM_CHIPONE_ICN6211) += chipone-icn6211.o
+ obj-$(CONFIG_DRM_CHRONTEL_CH7033) += chrontel-ch7033.o
+ obj-$(CONFIG_DRM_CROS_EC_ANX7688) += cros-ec-anx7688.o
+diff --git a/drivers/gpu/drm/bridge/aux-hpd-bridge.c b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
+new file mode 100644
+index 0000000000000..5d2ab3a715f9c
+--- /dev/null
++++ b/drivers/gpu/drm/bridge/aux-hpd-bridge.c
+@@ -0,0 +1,163 @@
++// SPDX-License-Identifier: GPL-2.0+
++/*
++ * Copyright (C) 2023 Linaro Ltd.
++ *
++ * Author: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
++ */
++#include <linux/auxiliary_bus.h>
++#include <linux/module.h>
++#include <linux/of_device.h>
++
++#include <drm/drm_bridge.h>
++#include <drm/bridge/aux-bridge.h>
++
++static DEFINE_IDA(drm_aux_hpd_bridge_ida);
++
++struct drm_aux_hpd_bridge_data {
++ struct drm_bridge bridge;
++ struct device *dev;
++};
++
++static void drm_aux_hpd_bridge_release(struct device *dev)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++
++ ida_free(&drm_aux_hpd_bridge_ida, adev->id);
++
++ of_node_put(adev->dev.platform_data);
++
++ kfree(adev);
++}
++
++static void drm_aux_hpd_bridge_unregister_adev(void *_adev)
++{
++ struct auxiliary_device *adev = _adev;
++
++ auxiliary_device_delete(adev);
++ auxiliary_device_uninit(adev);
++}
++
++/**
++ * drm_dp_hpd_bridge_register - Create a simple HPD DisplayPort bridge
++ * @parent: device instance providing this bridge
++ * @np: device node pointer corresponding to this bridge instance
++ *
++ * Creates a simple DRM bridge with the type set to
++ * DRM_MODE_CONNECTOR_DisplayPort, which terminates the bridge chain and is
++ * able to send the HPD events.
++ *
++ * Return: device instance that will handle created bridge or an error code
++ * encoded into the pointer.
++ */
++struct device *drm_dp_hpd_bridge_register(struct device *parent,
++ struct device_node *np)
++{
++ struct auxiliary_device *adev;
++ int ret;
++
++ adev = kzalloc(sizeof(*adev), GFP_KERNEL);
++ if (!adev)
++ return ERR_PTR(-ENOMEM);
++
++ ret = ida_alloc(&drm_aux_hpd_bridge_ida, GFP_KERNEL);
++ if (ret < 0) {
++ kfree(adev);
++ return ERR_PTR(ret);
++ }
++
++ adev->id = ret;
++ adev->name = "dp_hpd_bridge";
++ adev->dev.parent = parent;
++ adev->dev.of_node = parent->of_node;
++ adev->dev.release = drm_aux_hpd_bridge_release;
++ adev->dev.platform_data = np;
++
++ ret = auxiliary_device_init(adev);
++ if (ret) {
++ ida_free(&drm_aux_hpd_bridge_ida, adev->id);
++ kfree(adev);
++ return ERR_PTR(ret);
++ }
++
++ ret = auxiliary_device_add(adev);
++ if (ret) {
++ auxiliary_device_uninit(adev);
++ return ERR_PTR(ret);
++ }
++
++ ret = devm_add_action_or_reset(parent, drm_aux_hpd_bridge_unregister_adev, adev);
++ if (ret)
++ return ERR_PTR(ret);
++
++ return &adev->dev;
++}
++EXPORT_SYMBOL_GPL(drm_dp_hpd_bridge_register);
++
++/**
++ * drm_aux_hpd_bridge_notify - notify hot plug detection events
++ * @dev: device created for the HPD bridge
++ * @status: output connection status
++ *
++ * A wrapper around drm_bridge_hpd_notify() that is used to report hot plug
++ * detection events for bridges created via drm_dp_hpd_bridge_register().
++ *
++ * This function shall be called in a context that can sleep.
++ */
++void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status)
++{
++ struct auxiliary_device *adev = to_auxiliary_dev(dev);
++ struct drm_aux_hpd_bridge_data *data = auxiliary_get_drvdata(adev);
++
++ if (!data)
++ return;
++
++ drm_bridge_hpd_notify(&data->bridge, status);
++}
++EXPORT_SYMBOL_GPL(drm_aux_hpd_bridge_notify);
++
++static int drm_aux_hpd_bridge_attach(struct drm_bridge *bridge,
++ enum drm_bridge_attach_flags flags)
++{
++ return flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR ? 0 : -EINVAL;
++}
++
++static const struct drm_bridge_funcs drm_aux_hpd_bridge_funcs = {
++ .attach = drm_aux_hpd_bridge_attach,
++};
++
++static int drm_aux_hpd_bridge_probe(struct auxiliary_device *auxdev,
++ const struct auxiliary_device_id *id)
++{
++ struct drm_aux_hpd_bridge_data *data;
++
++ data = devm_kzalloc(&auxdev->dev, sizeof(*data), GFP_KERNEL);
++ if (!data)
++ return -ENOMEM;
++
++ data->dev = &auxdev->dev;
++ data->bridge.funcs = &drm_aux_hpd_bridge_funcs;
++ data->bridge.of_node = dev_get_platdata(data->dev);
++ data->bridge.ops = DRM_BRIDGE_OP_HPD;
++ data->bridge.type = id->driver_data;
++
++ auxiliary_set_drvdata(auxdev, data);
++
++ return devm_drm_bridge_add(data->dev, &data->bridge);
++}
++
++static const struct auxiliary_device_id drm_aux_hpd_bridge_table[] = {
++ { .name = KBUILD_MODNAME ".dp_hpd_bridge", .driver_data = DRM_MODE_CONNECTOR_DisplayPort, },
++ {},
++};
++MODULE_DEVICE_TABLE(auxiliary, drm_aux_hpd_bridge_table);
++
++static struct auxiliary_driver drm_aux_hpd_bridge_drv = {
++ .name = "aux_hpd_bridge",
++ .id_table = drm_aux_hpd_bridge_table,
++ .probe = drm_aux_hpd_bridge_probe,
++};
++module_auxiliary_driver(drm_aux_hpd_bridge_drv);
++
++MODULE_AUTHOR("Dmitry Baryshkov <dmitry.baryshkov@linaro.org>");
++MODULE_DESCRIPTION("DRM HPD bridge");
++MODULE_LICENSE("GPL");
+diff --git a/include/drm/bridge/aux-bridge.h b/include/drm/bridge/aux-bridge.h
+index b3a9cc9c862fd..66249ff0858e7 100644
+--- a/include/drm/bridge/aux-bridge.h
++++ b/include/drm/bridge/aux-bridge.h
+@@ -7,6 +7,8 @@
+ #ifndef DRM_AUX_BRIDGE_H
+ #define DRM_AUX_BRIDGE_H
+
++#include <drm/drm_connector.h>
++
+ #if IS_ENABLED(CONFIG_DRM_AUX_BRIDGE)
+ int drm_aux_bridge_register(struct device *parent);
+ #else
+@@ -16,4 +18,20 @@ static inline int drm_aux_bridge_register(struct device *parent)
+ }
+ #endif
+
++#if IS_ENABLED(CONFIG_DRM_AUX_HPD_BRIDGE)
++struct device *drm_dp_hpd_bridge_register(struct device *parent,
++ struct device_node *np);
++void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status);
++#else
++static inline struct device *drm_dp_hpd_bridge_register(struct device *parent,
++ struct device_node *np)
++{
++ return 0;
++}
++
++static inline void drm_aux_hpd_bridge_notify(struct device *dev, enum drm_connector_status status)
++{
++}
++#endif
++
+ #endif
+--
+2.43.0
+
--- /dev/null
+From 82feb6d3481ed699bc0a8b95fb9846a5d5dd2bd0 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Tue, 14 Nov 2023 10:48:22 -0500
+Subject: dt-bindings: dma: fsl-edma: Add fsl-edma.h to prevent hardcoding in
+ dts
+
+From: Frank Li <Frank.Li@nxp.com>
+
+[ Upstream commit 1e9b05258271b76ccc04a4b535009d2cb596506a ]
+
+Introduce a common dt-bindings header file, fsl-edma.h, shared between
+the driver and dts files. This addition aims to eliminate hardcoded values
+in dts files, promoting maintainability and consistency.
+
+DTS header file not support BIT() macro yet. Directly use 2^n number.
+
+Signed-off-by: Frank Li <Frank.Li@nxp.com>
+Reviewed-by: Rob Herring <robh@kernel.org>
+Link: https://lore.kernel.org/r/20231114154824.3617255-3-Frank.Li@nxp.com
+Signed-off-by: Vinod Koul <vkoul@kernel.org>
+Stable-dep-of: a79f949a5ce1 ("dmaengine: fsl-edma: correct max_segment_size setting")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ include/dt-bindings/dma/fsl-edma.h | 21 +++++++++++++++++++++
+ 1 file changed, 21 insertions(+)
+ create mode 100644 include/dt-bindings/dma/fsl-edma.h
+
+diff --git a/include/dt-bindings/dma/fsl-edma.h b/include/dt-bindings/dma/fsl-edma.h
+new file mode 100644
+index 0000000000000..fd11478cfe9cc
+--- /dev/null
++++ b/include/dt-bindings/dma/fsl-edma.h
+@@ -0,0 +1,21 @@
++/* SPDX-License-Identifier: GPL-2.0 OR BSD-2-Clause */
++
++#ifndef _FSL_EDMA_DT_BINDING_H_
++#define _FSL_EDMA_DT_BINDING_H_
++
++/* Receive Channel */
++#define FSL_EDMA_RX 0x1
++
++/* iMX8 audio remote DMA */
++#define FSL_EDMA_REMOTE 0x2
++
++/* FIFO is continue memory region */
++#define FSL_EDMA_MULTI_FIFO 0x4
++
++/* Channel need stick to even channel */
++#define FSL_EDMA_EVEN_CH 0x8
++
++/* Channel need stick to odd channel */
++#define FSL_EDMA_ODD_CH 0x10
++
++#endif
+--
+2.43.0
+
--- /dev/null
+drm-bridge-add-transparent-bridge-helper.patch
+drm-bridge-implement-generic-dp-hpd-bridge.patch
+soc-qcom-pmic-glink-switch-to-drm_aux_hpd_bridge.patch
+drm-bridge-aux-hpd-separate-allocation-and-registrat.patch
+soc-qcom-pmic_glink_altmode-fix-drm-bridge-use-after.patch
+dt-bindings-dma-fsl-edma-add-fsl-edma.h-to-prevent-h.patch
+dmaengine-fsl-edma-utilize-common-dt-binding-header-.patch
+dmaengine-fsl-edma-correct-max_segment_size-setting.patch
--- /dev/null
+From c2f051c3e81e9216cc2ca7096b1dfd0093ae89a3 Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sun, 3 Dec 2023 14:43:32 +0300
+Subject: soc: qcom: pmic-glink: switch to DRM_AUX_HPD_BRIDGE
+
+From: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+
+[ Upstream commit 2bcca96abfbf89d26fc10fc92e40532bb2ae8891 ]
+
+Use the freshly defined DRM_AUX_HPD_BRIDGE instead of open-coding the
+same functionality for the DRM bridge chain termination.
+
+Reviewed-by: Bjorn Andersson <andersson@kernel.org>
+Acked-by: Bjorn Andersson <andersson@kernel.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20231203114333.1305826-6-dmitry.baryshkov@linaro.org
+Stable-dep-of: b979f2d50a09 ("soc: qcom: pmic_glink_altmode: fix drm bridge use-after-free")
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/qcom/Kconfig | 1 +
+ drivers/soc/qcom/pmic_glink_altmode.c | 33 ++++++++-------------------
+ 2 files changed, 10 insertions(+), 24 deletions(-)
+
+diff --git a/drivers/soc/qcom/Kconfig b/drivers/soc/qcom/Kconfig
+index b3634e10f6f5e..c954001ae79ec 100644
+--- a/drivers/soc/qcom/Kconfig
++++ b/drivers/soc/qcom/Kconfig
+@@ -86,6 +86,7 @@ config QCOM_PMIC_GLINK
+ depends on OF
+ select AUXILIARY_BUS
+ select QCOM_PDR_HELPERS
++ select DRM_AUX_HPD_BRIDGE
+ help
+ The Qualcomm PMIC GLINK driver provides access, over GLINK, to the
+ USB and battery firmware running on one of the coprocessors in
+diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c
+index 7ee52cf2570fa..1539ccb7a346d 100644
+--- a/drivers/soc/qcom/pmic_glink_altmode.c
++++ b/drivers/soc/qcom/pmic_glink_altmode.c
+@@ -11,7 +11,7 @@
+ #include <linux/mutex.h>
+ #include <linux/property.h>
+ #include <linux/soc/qcom/pdr.h>
+-#include <drm/drm_bridge.h>
++#include <drm/bridge/aux-bridge.h>
+
+ #include <linux/usb/typec_altmode.h>
+ #include <linux/usb/typec_dp.h>
+@@ -76,7 +76,7 @@ struct pmic_glink_altmode_port {
+
+ struct work_struct work;
+
+- struct drm_bridge bridge;
++ struct device *bridge;
+
+ enum typec_orientation orientation;
+ u16 svid;
+@@ -230,10 +230,10 @@ static void pmic_glink_altmode_worker(struct work_struct *work)
+ else
+ pmic_glink_altmode_enable_usb(altmode, alt_port);
+
+- if (alt_port->hpd_state)
+- drm_bridge_hpd_notify(&alt_port->bridge, connector_status_connected);
+- else
+- drm_bridge_hpd_notify(&alt_port->bridge, connector_status_disconnected);
++ drm_aux_hpd_bridge_notify(alt_port->bridge,
++ alt_port->hpd_state ?
++ connector_status_connected :
++ connector_status_disconnected);
+
+ pmic_glink_altmode_request(altmode, ALTMODE_PAN_ACK, alt_port->index);
+ };
+@@ -365,16 +365,6 @@ static void pmic_glink_altmode_callback(const void *data, size_t len, void *priv
+ }
+ }
+
+-static int pmic_glink_altmode_attach(struct drm_bridge *bridge,
+- enum drm_bridge_attach_flags flags)
+-{
+- return flags & DRM_BRIDGE_ATTACH_NO_CONNECTOR ? 0 : -EINVAL;
+-}
+-
+-static const struct drm_bridge_funcs pmic_glink_altmode_bridge_funcs = {
+- .attach = pmic_glink_altmode_attach,
+-};
+-
+ static void pmic_glink_altmode_put_retimer(void *data)
+ {
+ typec_retimer_put(data);
+@@ -464,15 +454,10 @@ static int pmic_glink_altmode_probe(struct auxiliary_device *adev,
+ alt_port->index = port;
+ INIT_WORK(&alt_port->work, pmic_glink_altmode_worker);
+
+- alt_port->bridge.funcs = &pmic_glink_altmode_bridge_funcs;
+- alt_port->bridge.of_node = to_of_node(fwnode);
+- alt_port->bridge.ops = DRM_BRIDGE_OP_HPD;
+- alt_port->bridge.type = DRM_MODE_CONNECTOR_DisplayPort;
+-
+- ret = devm_drm_bridge_add(dev, &alt_port->bridge);
+- if (ret) {
++ alt_port->bridge = drm_dp_hpd_bridge_register(dev, to_of_node(fwnode));
++ if (IS_ERR(alt_port->bridge)) {
+ fwnode_handle_put(fwnode);
+- return ret;
++ return PTR_ERR(alt_port->bridge);
+ }
+
+ alt_port->dp_alt.svid = USB_TYPEC_DP_SID;
+--
+2.43.0
+
--- /dev/null
+From 34ffd4992df436d6a57996dbb04e9105b44c6a9f Mon Sep 17 00:00:00 2001
+From: Sasha Levin <sashal@kernel.org>
+Date: Sat, 17 Feb 2024 16:02:25 +0100
+Subject: soc: qcom: pmic_glink_altmode: fix drm bridge use-after-free
+
+From: Johan Hovold <johan+linaro@kernel.org>
+
+[ Upstream commit b979f2d50a099f3402418d7ff5f26c3952fb08bb ]
+
+A recent DRM series purporting to simplify support for "transparent
+bridges" and handling of probe deferrals ironically exposed a
+use-after-free issue on pmic_glink_altmode probe deferral.
+
+This has manifested itself as the display subsystem occasionally failing
+to initialise and NULL-pointer dereferences during boot of machines like
+the Lenovo ThinkPad X13s.
+
+Specifically, the dp-hpd bridge is currently registered before all
+resources have been acquired which means that it can also be
+deregistered on probe deferrals.
+
+In the meantime there is a race window where the new aux bridge driver
+(or PHY driver previously) may have looked up the dp-hpd bridge and
+stored a (non-reference-counted) pointer to the bridge which is about to
+be deallocated.
+
+When the display controller is later initialised, this triggers a
+use-after-free when attaching the bridges:
+
+ dp -> aux -> dp-hpd (freed)
+
+which may, for example, result in the freed bridge failing to attach:
+
+ [drm:drm_bridge_attach [drm]] *ERROR* failed to attach bridge /soc@0/phy@88eb000 to encoder TMDS-31: -16
+
+or a NULL-pointer dereference:
+
+ Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
+ ...
+ Call trace:
+ drm_bridge_attach+0x70/0x1a8 [drm]
+ drm_aux_bridge_attach+0x24/0x38 [aux_bridge]
+ drm_bridge_attach+0x80/0x1a8 [drm]
+ dp_bridge_init+0xa8/0x15c [msm]
+ msm_dp_modeset_init+0x28/0xc4 [msm]
+
+The DRM bridge implementation is clearly fragile and implicitly built on
+the assumption that bridges may never go away. In this case, the fix is
+to move the bridge registration in the pmic_glink_altmode driver to
+after all resources have been looked up.
+
+Incidentally, with the new dp-hpd bridge implementation, which registers
+child devices, this is also a requirement due to a long-standing issue
+in driver core that can otherwise lead to a probe deferral loop (see
+commit fbc35b45f9f6 ("Add documentation on meaning of -EPROBE_DEFER")).
+
+[DB: slightly fixed commit message by adding the word 'commit']
+Fixes: 080b4e24852b ("soc: qcom: pmic_glink: Introduce altmode support")
+Fixes: 2bcca96abfbf ("soc: qcom: pmic-glink: switch to DRM_AUX_HPD_BRIDGE")
+Cc: <stable@vger.kernel.org> # 6.3
+Cc: Bjorn Andersson <andersson@kernel.org>
+Cc: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Johan Hovold <johan+linaro@kernel.org>
+Reviewed-by: Bjorn Andersson <andersson@kernel.org>
+Reviewed-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
+Link: https://patchwork.freedesktop.org/patch/msgid/20240217150228.5788-4-johan+linaro@kernel.org
+Signed-off-by: Sasha Levin <sashal@kernel.org>
+---
+ drivers/soc/qcom/pmic_glink_altmode.c | 16 +++++++++++++---
+ 1 file changed, 13 insertions(+), 3 deletions(-)
+
+diff --git a/drivers/soc/qcom/pmic_glink_altmode.c b/drivers/soc/qcom/pmic_glink_altmode.c
+index 1539ccb7a346d..e1d32e1b79902 100644
+--- a/drivers/soc/qcom/pmic_glink_altmode.c
++++ b/drivers/soc/qcom/pmic_glink_altmode.c
+@@ -76,7 +76,7 @@ struct pmic_glink_altmode_port {
+
+ struct work_struct work;
+
+- struct device *bridge;
++ struct auxiliary_device *bridge;
+
+ enum typec_orientation orientation;
+ u16 svid;
+@@ -230,7 +230,7 @@ static void pmic_glink_altmode_worker(struct work_struct *work)
+ else
+ pmic_glink_altmode_enable_usb(altmode, alt_port);
+
+- drm_aux_hpd_bridge_notify(alt_port->bridge,
++ drm_aux_hpd_bridge_notify(&alt_port->bridge->dev,
+ alt_port->hpd_state ?
+ connector_status_connected :
+ connector_status_disconnected);
+@@ -454,7 +454,7 @@ static int pmic_glink_altmode_probe(struct auxiliary_device *adev,
+ alt_port->index = port;
+ INIT_WORK(&alt_port->work, pmic_glink_altmode_worker);
+
+- alt_port->bridge = drm_dp_hpd_bridge_register(dev, to_of_node(fwnode));
++ alt_port->bridge = devm_drm_dp_hpd_bridge_alloc(dev, to_of_node(fwnode));
+ if (IS_ERR(alt_port->bridge)) {
+ fwnode_handle_put(fwnode);
+ return PTR_ERR(alt_port->bridge);
+@@ -510,6 +510,16 @@ static int pmic_glink_altmode_probe(struct auxiliary_device *adev,
+ }
+ }
+
++ for (port = 0; port < ARRAY_SIZE(altmode->ports); port++) {
++ alt_port = &altmode->ports[port];
++ if (!alt_port->bridge)
++ continue;
++
++ ret = devm_drm_dp_hpd_bridge_add(dev, alt_port->bridge);
++ if (ret)
++ return ret;
++ }
++
+ altmode->client = devm_pmic_glink_register_client(dev,
+ altmode->owner_id,
+ pmic_glink_altmode_callback,
+--
+2.43.0
+