From 29e86a0e43085c260c2f8d8122157bd2be709d06 Mon Sep 17 00:00:00 2001 From: Sasha Levin Date: Thu, 7 Mar 2024 11:56:25 -0500 Subject: [PATCH] Fixes for 6.6 Signed-off-by: Sasha Levin --- ...orrected-encoding-of-max_xattr_size-.patch | 78 ++++++ ...dma-correct-max_segment_size-setting.patch | 66 +++++ ...ma-utilize-common-dt-binding-header-.patch | 69 +++++ ...bridge-add-transparent-bridge-helper.patch | 233 ++++++++++++++++ ...pd-separate-allocation-and-registrat.patch | 175 ++++++++++++ ...idge-implement-generic-dp-hpd-bridge.patch | 262 ++++++++++++++++++ ...fsl-edma-add-fsl-edma.h-to-prevent-h.patch | 57 ++++ ...rt-numamigrate_isolate_page-to-numam.patch | 87 ++++++ ...e-pagetranshuge-check-in-numamigrate.patch | 63 +++++ ...e-thp-mapcount-check-in-numamigrate_.patch | 50 ++++ ...bug-calling-wakeup_kswapd-with-a-wro.patch | 98 +++++++ queue-6.6/series | 13 + ...c-glink-switch-to-drm_aux_hpd_bridge.patch | 111 ++++++++ ...ink_altmode-fix-drm-bridge-use-after.patch | 123 ++++++++ 14 files changed, 1485 insertions(+) create mode 100644 queue-6.6/ceph-switch-to-corrected-encoding-of-max_xattr_size-.patch create mode 100644 queue-6.6/dmaengine-fsl-edma-correct-max_segment_size-setting.patch create mode 100644 queue-6.6/dmaengine-fsl-edma-utilize-common-dt-binding-header-.patch create mode 100644 queue-6.6/drm-bridge-add-transparent-bridge-helper.patch create mode 100644 queue-6.6/drm-bridge-aux-hpd-separate-allocation-and-registrat.patch create mode 100644 queue-6.6/drm-bridge-implement-generic-dp-hpd-bridge.patch create mode 100644 queue-6.6/dt-bindings-dma-fsl-edma-add-fsl-edma.h-to-prevent-h.patch create mode 100644 queue-6.6/mm-migrate-convert-numamigrate_isolate_page-to-numam.patch create mode 100644 queue-6.6/mm-migrate-remove-pagetranshuge-check-in-numamigrate.patch create mode 100644 queue-6.6/mm-migrate-remove-thp-mapcount-check-in-numamigrate_.patch create mode 100644 queue-6.6/mm-vmscan-fix-a-bug-calling-wakeup_kswapd-with-a-wro.patch create mode 100644 queue-6.6/series create mode 100644 queue-6.6/soc-qcom-pmic-glink-switch-to-drm_aux_hpd_bridge.patch create mode 100644 queue-6.6/soc-qcom-pmic_glink_altmode-fix-drm-bridge-use-after.patch diff --git a/queue-6.6/ceph-switch-to-corrected-encoding-of-max_xattr_size-.patch b/queue-6.6/ceph-switch-to-corrected-encoding-of-max_xattr_size-.patch new file mode 100644 index 00000000000..add1f79e09f --- /dev/null +++ b/queue-6.6/ceph-switch-to-corrected-encoding-of-max_xattr_size-.patch @@ -0,0 +1,78 @@ +From a45dad957afacdc339c1bceb10b9274da8afe32e Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Mon, 19 Feb 2024 13:14:32 +0800 +Subject: ceph: switch to corrected encoding of max_xattr_size in mdsmap + +From: Xiubo Li + +[ Upstream commit 51d31149a88b5c5a8d2d33f06df93f6187a25b4c ] + +The addition of bal_rank_mask with encoding version 17 was merged +into ceph.git in Oct 2022 and made it into v18.2.0 release normally. +A few months later, the much delayed addition of max_xattr_size got +merged, also with encoding version 17, placed before bal_rank_mask +in the encoding -- but it didn't make v18.2.0 release. + +The way this ended up being resolved on the MDS side is that +bal_rank_mask will continue to be encoded in version 17 while +max_xattr_size is now encoded in version 18. This does mean that +older kernels will misdecode version 17, but this is also true for +v18.2.0 and v18.2.1 clients in userspace. + +The best we can do is backport this adjustment -- see ceph.git +commit 78abfeaff27fee343fb664db633de5b221699a73 for details. + +[ idryomov: changelog ] + +Cc: stable@vger.kernel.org +Link: https://tracker.ceph.com/issues/64440 +Fixes: d93231a6bc8a ("ceph: prevent a client from exceeding the MDS maximum xattr size") +Signed-off-by: Xiubo Li +Reviewed-by: Patrick Donnelly +Reviewed-by: Venky Shankar +Signed-off-by: Ilya Dryomov +Signed-off-by: Sasha Levin +--- + fs/ceph/mdsmap.c | 7 ++++--- + include/linux/ceph/mdsmap.h | 6 +++++- + 2 files changed, 9 insertions(+), 4 deletions(-) + +diff --git a/fs/ceph/mdsmap.c b/fs/ceph/mdsmap.c +index 7dac21ee6ce76..3bb3b610d403e 100644 +--- a/fs/ceph/mdsmap.c ++++ b/fs/ceph/mdsmap.c +@@ -379,10 +379,11 @@ struct ceph_mdsmap *ceph_mdsmap_decode(void **p, void *end, bool msgr2) + ceph_decode_skip_8(p, end, bad_ext); + /* required_client_features */ + ceph_decode_skip_set(p, end, 64, bad_ext); ++ /* bal_rank_mask */ ++ ceph_decode_skip_string(p, end, bad_ext); ++ } ++ if (mdsmap_ev >= 18) { + ceph_decode_64_safe(p, end, m->m_max_xattr_size, bad_ext); +- } else { +- /* This forces the usage of the (sync) SETXATTR Op */ +- m->m_max_xattr_size = 0; + } + bad_ext: + dout("mdsmap_decode m_enabled: %d, m_damaged: %d, m_num_laggy: %d\n", +diff --git a/include/linux/ceph/mdsmap.h b/include/linux/ceph/mdsmap.h +index 4c3e0648dc277..fcc95bff72a57 100644 +--- a/include/linux/ceph/mdsmap.h ++++ b/include/linux/ceph/mdsmap.h +@@ -25,7 +25,11 @@ struct ceph_mdsmap { + u32 m_session_timeout; /* seconds */ + u32 m_session_autoclose; /* seconds */ + u64 m_max_file_size; +- u64 m_max_xattr_size; /* maximum size for xattrs blob */ ++ /* ++ * maximum size for xattrs blob. ++ * Zeroed by default to force the usage of the (sync) SETXATTR Op. ++ */ ++ u64 m_max_xattr_size; + u32 m_max_mds; /* expected up:active mds number */ + u32 m_num_active_mds; /* actual up:active mds number */ + u32 possible_max_rank; /* possible max rank index */ +-- +2.43.0 + diff --git a/queue-6.6/dmaengine-fsl-edma-correct-max_segment_size-setting.patch b/queue-6.6/dmaengine-fsl-edma-correct-max_segment_size-setting.patch new file mode 100644 index 00000000000..20fcec6ce3b --- /dev/null +++ b/queue-6.6/dmaengine-fsl-edma-correct-max_segment_size-setting.patch @@ -0,0 +1,66 @@ +From 72948c318780e95ea55bf1cd9fd37a77fd0a0fcc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 7 Feb 2024 14:47:32 -0500 +Subject: dmaengine: fsl-edma: correct max_segment_size setting + +From: Frank Li + +[ 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 +Link: https://lore.kernel.org/r/20240207194733.2112870-1-Frank.Li@nxp.com +Signed-off-by: Vinod Koul +Signed-off-by: Sasha Levin +--- + 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 40d50cc3d75a3..92fe53faa53b1 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 a56c8a0f2663f..42a338cbe6143 100644 +--- a/drivers/dma/fsl-edma-main.c ++++ b/drivers/dma/fsl-edma-main.c +@@ -10,6 +10,7 @@ + */ + + #include ++#include + #include + #include + #include +@@ -589,7 +590,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 + diff --git a/queue-6.6/dmaengine-fsl-edma-utilize-common-dt-binding-header-.patch b/queue-6.6/dmaengine-fsl-edma-utilize-common-dt-binding-header-.patch new file mode 100644 index 00000000000..39cf5e4c9c2 --- /dev/null +++ b/queue-6.6/dmaengine-fsl-edma-utilize-common-dt-binding-header-.patch @@ -0,0 +1,69 @@ +From 148c0e7c08d6625c357dc8d7d19fd5cb19eee308 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Tue, 14 Nov 2023 10:48:23 -0500 +Subject: dmaengine: fsl-edma: utilize common dt-binding header file + +From: Frank Li + +[ 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 +Link: https://lore.kernel.org/r/20231114154824.3617255-4-Frank.Li@nxp.com +Signed-off-by: Vinod Koul +Stable-dep-of: a79f949a5ce1 ("dmaengine: fsl-edma: correct max_segment_size setting") +Signed-off-by: Sasha Levin +--- + 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 30df55da4dbb9..a56c8a0f2663f 100644 +--- a/drivers/dma/fsl-edma-main.c ++++ b/drivers/dma/fsl-edma-main.c +@@ -9,6 +9,7 @@ + * Vybrid and Layerscape SoCs. + */ + ++#include + #include + #include + #include +@@ -23,12 +24,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); +@@ -157,14 +152,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 + diff --git a/queue-6.6/drm-bridge-add-transparent-bridge-helper.patch b/queue-6.6/drm-bridge-add-transparent-bridge-helper.patch new file mode 100644 index 00000000000..367a1dcdd91 --- /dev/null +++ b/queue-6.6/drm-bridge-add-transparent-bridge-helper.patch @@ -0,0 +1,233 @@ +From 62aa603606683e56c0e967003e07e93b73d8e901 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Dec 2023 14:43:28 +0300 +Subject: drm/bridge: add transparent bridge helper + +From: Dmitry Baryshkov + +[ 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 +Signed-off-by: Dmitry Baryshkov +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 +--- + 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 ++ */ ++#include ++#include ++ ++#include ++#include ++ ++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 "); ++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 ++ */ ++#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 + diff --git a/queue-6.6/drm-bridge-aux-hpd-separate-allocation-and-registrat.patch b/queue-6.6/drm-bridge-aux-hpd-separate-allocation-and-registrat.patch new file mode 100644 index 00000000000..8cce175bd1d --- /dev/null +++ b/queue-6.6/drm-bridge-aux-hpd-separate-allocation-and-registrat.patch @@ -0,0 +1,175 @@ +From 5987955d65715e06a13a72c145058466f3cf587a Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 17 Feb 2024 16:02:24 +0100 +Subject: drm/bridge: aux-hpd: separate allocation and registration + +From: Johan Hovold + +[ 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 +Reviewed-by: Bjorn Andersson +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Dmitry Baryshkov +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 +--- + 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 + ++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 + diff --git a/queue-6.6/drm-bridge-implement-generic-dp-hpd-bridge.patch b/queue-6.6/drm-bridge-implement-generic-dp-hpd-bridge.patch new file mode 100644 index 00000000000..a1ed0c114c8 --- /dev/null +++ b/queue-6.6/drm-bridge-implement-generic-dp-hpd-bridge.patch @@ -0,0 +1,262 @@ +From 1ddace2b96caf41b5ed5d98e44326187059c8096 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Dec 2023 14:43:31 +0300 +Subject: drm/bridge: implement generic DP HPD bridge + +From: Dmitry Baryshkov + +[ 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 +Signed-off-by: Dmitry Baryshkov +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 +--- + 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 ++ */ ++#include ++#include ++#include ++ ++#include ++#include ++ ++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 "); ++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 ++ + #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 + diff --git a/queue-6.6/dt-bindings-dma-fsl-edma-add-fsl-edma.h-to-prevent-h.patch b/queue-6.6/dt-bindings-dma-fsl-edma-add-fsl-edma.h-to-prevent-h.patch new file mode 100644 index 00000000000..c04047ea337 --- /dev/null +++ b/queue-6.6/dt-bindings-dma-fsl-edma-add-fsl-edma.h-to-prevent-h.patch @@ -0,0 +1,57 @@ +From 8f41cc5863892f914017415a4843bcd9e3da7a5d Mon Sep 17 00:00:00 2001 +From: Sasha Levin +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 + +[ 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 +Reviewed-by: Rob Herring +Link: https://lore.kernel.org/r/20231114154824.3617255-3-Frank.Li@nxp.com +Signed-off-by: Vinod Koul +Stable-dep-of: a79f949a5ce1 ("dmaengine: fsl-edma: correct max_segment_size setting") +Signed-off-by: Sasha Levin +--- + 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 + diff --git a/queue-6.6/mm-migrate-convert-numamigrate_isolate_page-to-numam.patch b/queue-6.6/mm-migrate-convert-numamigrate_isolate_page-to-numam.patch new file mode 100644 index 00000000000..c5664ef3fc4 --- /dev/null +++ b/queue-6.6/mm-migrate-convert-numamigrate_isolate_page-to-numam.patch @@ -0,0 +1,87 @@ +From 4f2123962d79d1c209c30c367027ec1bdc474f1f Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Sep 2023 17:51:26 +0800 +Subject: mm: migrate: convert numamigrate_isolate_page() to + numamigrate_isolate_folio() + +From: Kefeng Wang + +[ Upstream commit 2ac9e99f3b21b2864305fbfba4bae5913274c409 ] + +Rename numamigrate_isolate_page() to numamigrate_isolate_folio(), then +make it takes a folio and use folio API to save compound_head() calls. + +Link: https://lkml.kernel.org/r/20230913095131.2426871-4-wangkefeng.wang@huawei.com +Signed-off-by: Kefeng Wang +Reviewed-by: Zi Yan +Cc: David Hildenbrand +Cc: "Huang, Ying" +Cc: Hugh Dickins +Cc: Matthew Wilcox (Oracle) +Cc: Mike Kravetz +Signed-off-by: Andrew Morton +Stable-dep-of: 2774f256e7c0 ("mm/vmscan: fix a bug calling wakeup_kswapd() with a wrong zone index") +Signed-off-by: Sasha Levin +--- + mm/migrate.c | 20 ++++++++++---------- + 1 file changed, 10 insertions(+), 10 deletions(-) + +diff --git a/mm/migrate.c b/mm/migrate.c +index c9fabb960996f..e5f2f7243a659 100644 +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -2501,10 +2501,9 @@ static struct folio *alloc_misplaced_dst_folio(struct folio *src, + return __folio_alloc_node(gfp, order, nid); + } + +-static int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page) ++static int numamigrate_isolate_folio(pg_data_t *pgdat, struct folio *folio) + { +- int nr_pages = thp_nr_pages(page); +- int order = compound_order(page); ++ int nr_pages = folio_nr_pages(folio); + + /* Avoid migrating to a node that is nearly full */ + if (!migrate_balanced_pgdat(pgdat, nr_pages)) { +@@ -2516,22 +2515,23 @@ static int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page) + if (managed_zone(pgdat->node_zones + z)) + break; + } +- wakeup_kswapd(pgdat->node_zones + z, 0, order, ZONE_MOVABLE); ++ wakeup_kswapd(pgdat->node_zones + z, 0, ++ folio_order(folio), ZONE_MOVABLE); + return 0; + } + +- if (!isolate_lru_page(page)) ++ if (!folio_isolate_lru(folio)) + return 0; + +- mod_node_page_state(page_pgdat(page), NR_ISOLATED_ANON + page_is_file_lru(page), ++ node_stat_mod_folio(folio, NR_ISOLATED_ANON + folio_is_file_lru(folio), + nr_pages); + + /* +- * Isolating the page has taken another reference, so the +- * caller's reference can be safely dropped without the page ++ * Isolating the folio has taken another reference, so the ++ * caller's reference can be safely dropped without the folio + * disappearing underneath us during migration. + */ +- put_page(page); ++ folio_put(folio); + return 1; + } + +@@ -2565,7 +2565,7 @@ int migrate_misplaced_page(struct page *page, struct vm_area_struct *vma, + if (page_is_file_lru(page) && PageDirty(page)) + goto out; + +- isolated = numamigrate_isolate_page(pgdat, page); ++ isolated = numamigrate_isolate_folio(pgdat, page_folio(page)); + if (!isolated) + goto out; + +-- +2.43.0 + diff --git a/queue-6.6/mm-migrate-remove-pagetranshuge-check-in-numamigrate.patch b/queue-6.6/mm-migrate-remove-pagetranshuge-check-in-numamigrate.patch new file mode 100644 index 00000000000..276dbcceefc --- /dev/null +++ b/queue-6.6/mm-migrate-remove-pagetranshuge-check-in-numamigrate.patch @@ -0,0 +1,63 @@ +From 33a638a72e8de7db8b0ae986a8c1b06728d757cc Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Sep 2023 17:51:24 +0800 +Subject: mm: migrate: remove PageTransHuge check in numamigrate_isolate_page() + +From: Kefeng Wang + +[ Upstream commit a8ac4a767dcd9d87d8229045904d9fe15ea5e0e8 ] + +Patch series "mm: migrate: more folio conversion and unification", v3. + +Convert more migrate functions to use a folio, it is also a preparation +for large folio migration support when balancing numa. + +This patch (of 8): + +The assert VM_BUG_ON_PAGE(order && !PageTransHuge(page), page) is not very +useful, + + 1) for a tail/base page, order = 0, for a head page, the order > 0 && + PageTransHuge() is true + 2) there is a PageCompound() check and only base page is handled in + do_numa_page(), and do_huge_pmd_numa_page() only handle PMD-mapped + THP + 3) even though the page is a tail page, isolate_lru_page() will post + a warning, and fail to isolate the page + 4) if large folio/pte-mapped THP migration supported in the future, + we could migrate the entire folio if numa fault on a tail page + +so just remove the check. + +Link: https://lkml.kernel.org/r/20230913095131.2426871-1-wangkefeng.wang@huawei.com +Link: https://lkml.kernel.org/r/20230913095131.2426871-2-wangkefeng.wang@huawei.com +Signed-off-by: Kefeng Wang +Suggested-by: Matthew Wilcox (Oracle) +Cc: David Hildenbrand +Cc: Huang Ying +Cc: Hugh Dickins +Cc: Mike Kravetz +Cc: Zi Yan +Signed-off-by: Andrew Morton +Stable-dep-of: 2774f256e7c0 ("mm/vmscan: fix a bug calling wakeup_kswapd() with a wrong zone index") +Signed-off-by: Sasha Levin +--- + mm/migrate.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/mm/migrate.c b/mm/migrate.c +index b4d972d80b10c..6f8ad6b64c9bc 100644 +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -2506,8 +2506,6 @@ static int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page) + int nr_pages = thp_nr_pages(page); + int order = compound_order(page); + +- VM_BUG_ON_PAGE(order && !PageTransHuge(page), page); +- + /* Do not migrate THP mapped by multiple processes */ + if (PageTransHuge(page) && total_mapcount(page) > 1) + return 0; +-- +2.43.0 + diff --git a/queue-6.6/mm-migrate-remove-thp-mapcount-check-in-numamigrate_.patch b/queue-6.6/mm-migrate-remove-thp-mapcount-check-in-numamigrate_.patch new file mode 100644 index 00000000000..ba414216891 --- /dev/null +++ b/queue-6.6/mm-migrate-remove-thp-mapcount-check-in-numamigrate_.patch @@ -0,0 +1,50 @@ +From 9429f944b65798873089ce0b50d6f44bddac674b Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Wed, 13 Sep 2023 17:51:25 +0800 +Subject: mm: migrate: remove THP mapcount check in numamigrate_isolate_page() + +From: Kefeng Wang + +[ Upstream commit 728be28fae8c838d52c91dce4867133798146357 ] + +The check of THP mapped by multiple processes was introduced by commit +04fa5d6a6547 ("mm: migrate: check page_count of THP before migrating") and +refactor by commit 340ef3902cf2 ("mm: numa: cleanup flow of transhuge page +migration"), which is out of date, since migrate_misplaced_page() is now +using the standard migrate_pages() for small pages and THPs, the reference +count checking is in folio_migrate_mapping(), so let's remove the special +check for THP. + +Link: https://lkml.kernel.org/r/20230913095131.2426871-3-wangkefeng.wang@huawei.com +Signed-off-by: Kefeng Wang +Suggested-by: Matthew Wilcox (Oracle) +Reviewed-by: "Huang, Ying" +Cc: David Hildenbrand +Cc: Hugh Dickins +Cc: Mike Kravetz +Cc: Zi Yan +Signed-off-by: Andrew Morton +Stable-dep-of: 2774f256e7c0 ("mm/vmscan: fix a bug calling wakeup_kswapd() with a wrong zone index") +Signed-off-by: Sasha Levin +--- + mm/migrate.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/mm/migrate.c b/mm/migrate.c +index 6f8ad6b64c9bc..c9fabb960996f 100644 +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -2506,10 +2506,6 @@ static int numamigrate_isolate_page(pg_data_t *pgdat, struct page *page) + int nr_pages = thp_nr_pages(page); + int order = compound_order(page); + +- /* Do not migrate THP mapped by multiple processes */ +- if (PageTransHuge(page) && total_mapcount(page) > 1) +- return 0; +- + /* Avoid migrating to a node that is nearly full */ + if (!migrate_balanced_pgdat(pgdat, nr_pages)) { + int z; +-- +2.43.0 + diff --git a/queue-6.6/mm-vmscan-fix-a-bug-calling-wakeup_kswapd-with-a-wro.patch b/queue-6.6/mm-vmscan-fix-a-bug-calling-wakeup_kswapd-with-a-wro.patch new file mode 100644 index 00000000000..2ba91111adb --- /dev/null +++ b/queue-6.6/mm-vmscan-fix-a-bug-calling-wakeup_kswapd-with-a-wro.patch @@ -0,0 +1,98 @@ +From 8b6bc15674905f185c644d93e48f6b7437c0d184 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Fri, 16 Feb 2024 20:15:02 +0900 +Subject: mm/vmscan: fix a bug calling wakeup_kswapd() with a wrong zone index + +From: Byungchul Park + +[ Upstream commit 2774f256e7c0219e2b0a0894af1c76bdabc4f974 ] + +With numa balancing on, when a numa system is running where a numa node +doesn't have its local memory so it has no managed zones, the following +oops has been observed. It's because wakeup_kswapd() is called with a +wrong zone index, -1. Fixed it by checking the index before calling +wakeup_kswapd(). + +> BUG: unable to handle page fault for address: 00000000000033f3 +> #PF: supervisor read access in kernel mode +> #PF: error_code(0x0000) - not-present page +> PGD 0 P4D 0 +> Oops: 0000 [#1] PREEMPT SMP NOPTI +> CPU: 2 PID: 895 Comm: masim Not tainted 6.6.0-dirty #255 +> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS +> rel-1.16.0-0-gd239552ce722-prebuilt.qemu.org 04/01/2014 +> RIP: 0010:wakeup_kswapd (./linux/mm/vmscan.c:7812) +> Code: (omitted) +> RSP: 0000:ffffc90004257d58 EFLAGS: 00010286 +> RAX: ffffffffffffffff RBX: ffff88883fff0480 RCX: 0000000000000003 +> RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff88883fff0480 +> RBP: ffffffffffffffff R08: ff0003ffffffffff R09: ffffffffffffffff +> R10: ffff888106c95540 R11: 0000000055555554 R12: 0000000000000003 +> R13: 0000000000000000 R14: 0000000000000000 R15: ffff88883fff0940 +> FS: 00007fc4b8124740(0000) GS:ffff888827c00000(0000) knlGS:0000000000000000 +> CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 +> CR2: 00000000000033f3 CR3: 000000026cc08004 CR4: 0000000000770ee0 +> DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 +> DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 +> PKRU: 55555554 +> Call Trace: +> +> ? __die +> ? page_fault_oops +> ? __pte_offset_map_lock +> ? exc_page_fault +> ? asm_exc_page_fault +> ? wakeup_kswapd +> migrate_misplaced_page +> __handle_mm_fault +> handle_mm_fault +> do_user_addr_fault +> exc_page_fault +> asm_exc_page_fault +> RIP: 0033:0x55b897ba0808 +> Code: (omitted) +> RSP: 002b:00007ffeefa821a0 EFLAGS: 00010287 +> RAX: 000055b89983acd0 RBX: 00007ffeefa823f8 RCX: 000055b89983acd0 +> RDX: 00007fc2f8122010 RSI: 0000000000020000 RDI: 000055b89983acd0 +> RBP: 00007ffeefa821a0 R08: 0000000000000037 R09: 0000000000000075 +> R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000000 +> R13: 00007ffeefa82410 R14: 000055b897ba5dd8 R15: 00007fc4b8340000 +> + +Link: https://lkml.kernel.org/r/20240216111502.79759-1-byungchul@sk.com +Signed-off-by: Byungchul Park +Reported-by: Hyeongtak Ji +Fixes: c574bbe917036 ("NUMA balancing: optimize page placement for memory tiering system") +Reviewed-by: Oscar Salvador +Cc: Baolin Wang +Cc: "Huang, Ying" +Cc: Johannes Weiner +Cc: +Signed-off-by: Andrew Morton +Signed-off-by: Sasha Levin +--- + mm/migrate.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/mm/migrate.c b/mm/migrate.c +index e5f2f7243a659..d69b4556cc15f 100644 +--- a/mm/migrate.c ++++ b/mm/migrate.c +@@ -2515,6 +2515,14 @@ static int numamigrate_isolate_folio(pg_data_t *pgdat, struct folio *folio) + if (managed_zone(pgdat->node_zones + z)) + break; + } ++ ++ /* ++ * If there are no managed zones, it should not proceed ++ * further. ++ */ ++ if (z < 0) ++ return 0; ++ + wakeup_kswapd(pgdat->node_zones + z, 0, + folio_order(folio), ZONE_MOVABLE); + return 0; +-- +2.43.0 + diff --git a/queue-6.6/series b/queue-6.6/series new file mode 100644 index 00000000000..d31c1da03c5 --- /dev/null +++ b/queue-6.6/series @@ -0,0 +1,13 @@ +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 +ceph-switch-to-corrected-encoding-of-max_xattr_size-.patch +mm-migrate-remove-pagetranshuge-check-in-numamigrate.patch +mm-migrate-remove-thp-mapcount-check-in-numamigrate_.patch +mm-migrate-convert-numamigrate_isolate_page-to-numam.patch +mm-vmscan-fix-a-bug-calling-wakeup_kswapd-with-a-wro.patch diff --git a/queue-6.6/soc-qcom-pmic-glink-switch-to-drm_aux_hpd_bridge.patch b/queue-6.6/soc-qcom-pmic-glink-switch-to-drm_aux_hpd_bridge.patch new file mode 100644 index 00000000000..cf425a162a9 --- /dev/null +++ b/queue-6.6/soc-qcom-pmic-glink-switch-to-drm_aux_hpd_bridge.patch @@ -0,0 +1,111 @@ +From bb14b6982fe054b9297263c12201143bc1732d73 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sun, 3 Dec 2023 14:43:32 +0300 +Subject: soc: qcom: pmic-glink: switch to DRM_AUX_HPD_BRIDGE + +From: Dmitry Baryshkov + +[ 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 +Acked-by: Bjorn Andersson +Signed-off-by: Dmitry Baryshkov +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 +--- + 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 715348869d048..a4a201404d09f 100644 +--- a/drivers/soc/qcom/Kconfig ++++ b/drivers/soc/qcom/Kconfig +@@ -102,6 +102,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 9b0000b5f064c..c07cddecc85e9 100644 +--- a/drivers/soc/qcom/pmic_glink_altmode.c ++++ b/drivers/soc/qcom/pmic_glink_altmode.c +@@ -11,7 +11,7 @@ + #include + #include + #include +-#include ++#include + + #include + #include +@@ -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 + diff --git a/queue-6.6/soc-qcom-pmic_glink_altmode-fix-drm-bridge-use-after.patch b/queue-6.6/soc-qcom-pmic_glink_altmode-fix-drm-bridge-use-after.patch new file mode 100644 index 00000000000..79c4b4e1a4a --- /dev/null +++ b/queue-6.6/soc-qcom-pmic_glink_altmode-fix-drm-bridge-use-after.patch @@ -0,0 +1,123 @@ +From 67a4099fba7bfae3544f7d85c0fb4e9e47c744b9 Mon Sep 17 00:00:00 2001 +From: Sasha Levin +Date: Sat, 17 Feb 2024 16:02:25 +0100 +Subject: soc: qcom: pmic_glink_altmode: fix drm bridge use-after-free + +From: Johan Hovold + +[ 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: # 6.3 +Cc: Bjorn Andersson +Cc: Dmitry Baryshkov +Signed-off-by: Johan Hovold +Reviewed-by: Bjorn Andersson +Reviewed-by: Dmitry Baryshkov +Signed-off-by: Dmitry Baryshkov +Link: https://patchwork.freedesktop.org/patch/msgid/20240217150228.5788-4-johan+linaro@kernel.org +Signed-off-by: Sasha Levin +--- + 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 c07cddecc85e9..0b869de665101 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 + -- 2.47.3