Kernel
Threads by month
- ----- 2026 -----
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- 34 participants
- 22793 discussions
From: Gregory Price <gourry(a)gourry.net>
stable inclusion
from stable-v6.12.57
commit e980de2ff109dacb6d9d3a77f01b27c467115ecb
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/11500
CVE: CVE-2025-68313
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
commit 607b9fb2ce248cc5b633c5949e0153838992c152 upstream.
There's an issue with RDSEED's 16-bit and 32-bit register output
variants on Zen5 which return a random value of 0 "at a rate inconsistent
with randomness while incorrectly signaling success (CF=1)". Search the
web for AMD-SB-7055 for more detail.
Add a fix glue which checks microcode revisions.
[ bp: Add microcode revisions checking, rewrite. ]
Cc: stable(a)vger.kernel.org
Signed-off-by: Gregory Price <gourry(a)gourry.net>
Signed-off-by: Borislav Petkov (AMD) <bp(a)alien8.de>
Link: https://lore.kernel.org/r/20251018024010.4112396-1-gourry@gourry.net
[ bp: 6.12 backport: use the alternative microcode version checking. ]
Signed-off-by: Borislav Petkov (AMD) <bp(a)alien8.de>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Conflicts:
arch/x86/include/asm/cpu.h
arch/x86/kernel/cpu/microcode/amd.c
[move the definition of zen_patch_rev]
Signed-off-by: Bowen You <youbowen2(a)huawei.com>
---
arch/x86/include/asm/cpu.h | 12 ++++++++++
arch/x86/kernel/cpu/amd.c | 35 +++++++++++++++++++++++++++++
arch/x86/kernel/cpu/microcode/amd.c | 12 ----------
3 files changed, 47 insertions(+), 12 deletions(-)
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index 43a228e11209..d252aa7f04fb 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -84,4 +84,16 @@ int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type);
extern struct cpumask cpus_stop_mask;
+union zen_patch_rev {
+ struct {
+ __u32 rev : 8,
+ stepping : 4,
+ model : 4,
+ __reserved : 4,
+ ext_model : 4,
+ ext_fam : 8;
+ };
+ __u32 ucode_rev;
+};
+
#endif /* _ASM_X86_CPU_H */
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index f89dbe6f48e6..5a46bf0cce5d 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -1135,8 +1135,43 @@ static void init_amd_zen4(struct cpuinfo_x86 *c)
}
}
+static bool check_rdseed_microcode(void)
+{
+ struct cpuinfo_x86 *c = &boot_cpu_data;
+ union zen_patch_rev p;
+ u32 min_rev = 0;
+
+ p.ext_fam = c->x86 - 0xf;
+ p.model = c->x86_model;
+ p.ext_model = c->x86_model >> 4;
+ p.stepping = c->x86_stepping;
+ /* reserved bits are expected to be 0 in test below */
+ p.__reserved = 0;
+
+ if (cpu_has(c, X86_FEATURE_ZEN5)) {
+ switch (p.ucode_rev >> 8) {
+ case 0xb0021: min_rev = 0xb00215a; break;
+ case 0xb1010: min_rev = 0xb101054; break;
+ default:
+ pr_debug("%s: ucode_rev: 0x%x, current revision: 0x%x\n",
+ __func__, p.ucode_rev, c->microcode);
+ return false;
+ }
+ }
+
+ if (!min_rev)
+ return false;
+
+ return c->microcode >= min_rev;
+}
+
static void init_amd_zen5(struct cpuinfo_x86 *c)
{
+ if (!check_rdseed_microcode()) {
+ clear_cpu_cap(c, X86_FEATURE_RDSEED);
+ msr_clear_bit(MSR_AMD64_CPUID_FN_7, 18);
+ pr_emerg_once("RDSEED32 is broken. Disabling the corresponding CPUID bit.\n");
+ }
}
static void init_amd(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index b6990dc26274..75746a991f8e 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -96,18 +96,6 @@ static struct equiv_cpu_table {
struct equiv_cpu_entry *entry;
} equiv_table;
-union zen_patch_rev {
- struct {
- __u32 rev : 8,
- stepping : 4,
- model : 4,
- __reserved : 4,
- ext_model : 4,
- ext_fam : 8;
- };
- __u32 ucode_rev;
-};
-
union cpuid_1_eax {
struct {
__u32 stepping : 4,
--
2.34.1
2
1
06 Feb '26
From: Sravan Kumar Gundu <sravankumarlpu(a)gmail.com>
mainline inclusion
from mainline-v6.17-rc1
commit af0db3c1f898144846d4c172531a199bb3ca375d
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/9085
CVE: CVE-2025-38685
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?…
--------------------------------
This issue triggers when a userspace program does an ioctl
FBIOPUT_CON2FBMAP by passing console number and frame buffer number.
Ideally this maps console to frame buffer and updates the screen if
console is visible.
As part of mapping it has to do resize of console according to frame
buffer info. if this resize fails and returns from vc_do_resize() and
continues further. At this point console and new frame buffer are mapped
and sets display vars. Despite failure still it continue to proceed
updating the screen at later stages where vc_data is related to previous
frame buffer and frame buffer info and display vars are mapped to new
frame buffer and eventully leading to out-of-bounds write in
fast_imageblit(). This bheviour is excepted only when fg_console is
equal to requested console which is a visible console and updates screen
with invalid struct references in fbcon_putcs().
Reported-and-tested-by: syzbot+c4b7aa0513823e2ea880(a)syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=c4b7aa0513823e2ea880
Signed-off-by: Sravan Kumar Gundu <sravankumarlpu(a)gmail.com>
Cc: stable(a)vger.kernel.org
Signed-off-by: Helge Deller <deller(a)gmx.de>
Conflicts:
drivers/video/fbdev/core/fbcon.c
[Context conflicts.]
Signed-off-by: Jiacheng Yu <yujiacheng3(a)huawei.com>
---
drivers/video/fbdev/core/fbcon.c | 9 +++++----
1 file changed, 5 insertions(+), 4 deletions(-)
diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c
index 81bf4f7bd9e8..66ecb2a044c6 100644
--- a/drivers/video/fbdev/core/fbcon.c
+++ b/drivers/video/fbdev/core/fbcon.c
@@ -827,7 +827,8 @@ static void con2fb_init_display(struct vc_data *vc, struct fb_info *info,
fg_vc->vc_rows);
}
- update_screen(vc_cons[fg_console].d);
+ if (fg_console != unit)
+ update_screen(vc_cons[fg_console].d);
}
/**
@@ -1366,6 +1367,7 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
struct vc_data *svc;
struct fbcon_ops *ops = info->fbcon_par;
int rows, cols, charcnt = 256;
+ unsigned long ret = 0;
p = &fb_display[unit];
@@ -1417,11 +1419,10 @@ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var,
rows = FBCON_SWAP(ops->rotate, info->var.yres, info->var.xres);
cols /= vc->vc_font.width;
rows /= vc->vc_font.height;
- vc_resize(vc, cols, rows);
+ ret = vc_resize(vc, cols, rows);
- if (con_is_visible(vc)) {
+ if (con_is_visible(vc) && !ret)
update_screen(vc);
- }
}
static __inline__ void ywrap_up(struct vc_data *vc, int count)
--
2.43.0
2
1
06 Feb '26
This reverts commit 84c1c0818c45cdfbbaa4b5ba4b8a552a52f5760e, reversing
changes made to 67fd5a0f7d0f1baceab00f0d3901a94803f0aee1.
Commit 70dcc68078ac introduced a null-pointer dereference exception,
causing kernel boot failure:
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000048
Call trace:
hibmc_debugfs_init+0x38/0x68 [hibmc_drm]
hibmc_pci_probe+0xdc/0x1ac [hibmc_drm]
local_pci_probe+0x48/0xb0
work_for_cpu_fn+0x24/0x50
process_one_work+0x1d8/0x4c0
worker_thread+0x25c/0x470
kthread+0x108/0x150
Temporarily revert the entire associated patch series as a precautionary
measure to circumvent the issue.
Fixes: 70dcc68078ac ("drm/hisilicon/hibmc: hibmc-drm bugfix for DP")
Signed-off-by: Tengda Wu <wutengda2(a)huawei.com>
---
drivers/gpu/drm/drm_connector.c | 9 -
drivers/gpu/drm/drm_internal.h | 2 -
drivers/gpu/drm/drm_probe_helper.c | 29 --
drivers/gpu/drm/drm_sysfs.c | 17 +-
drivers/gpu/drm/hisilicon/hibmc/Kconfig | 2 -
drivers/gpu/drm/hisilicon/hibmc/Makefile | 4 +-
drivers/gpu/drm/hisilicon/hibmc/dp/dp_aux.c | 167 -------
drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h | 73 ---
.../gpu/drm/hisilicon/hibmc/dp/dp_config.h | 21 -
drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c | 338 --------------
drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h | 74 ----
drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c | 415 ------------------
drivers/gpu/drm/hisilicon/hibmc/dp/dp_reg.h | 140 ------
.../gpu/drm/hisilicon/hibmc/dp/dp_serdes.c | 59 ---
.../drm/hisilicon/hibmc/hibmc_drm_debugfs.c | 149 -------
.../gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c | 257 -----------
.../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 127 ++----
.../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 31 +-
.../gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c | 48 +-
.../gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 60 +--
include/drm/drm_probe_helper.h | 3 -
21 files changed, 79 insertions(+), 1946 deletions(-)
delete mode 100644 drivers/gpu/drm/hisilicon/hibmc/dp/dp_aux.c
delete mode 100644 drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h
delete mode 100644 drivers/gpu/drm/hisilicon/hibmc/dp/dp_config.h
delete mode 100644 drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c
delete mode 100644 drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h
delete mode 100644 drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c
delete mode 100644 drivers/gpu/drm/hisilicon/hibmc/dp/dp_reg.h
delete mode 100644 drivers/gpu/drm/hisilicon/hibmc/dp/dp_serdes.c
delete mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_debugfs.c
delete mode 100644 drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c
diff --git a/drivers/gpu/drm/drm_connector.c b/drivers/gpu/drm/drm_connector.c
index fa9675396287..9c3bbe2c3e6f 100644
--- a/drivers/gpu/drm/drm_connector.c
+++ b/drivers/gpu/drm/drm_connector.c
@@ -525,10 +525,6 @@ int drm_connector_register(struct drm_connector *connector)
goto err_debugfs;
}
- ret = drm_sysfs_connector_add_late(connector);
- if (ret)
- goto err_late_register;
-
drm_mode_object_register(connector->dev, &connector->base);
connector->registration_state = DRM_CONNECTOR_REGISTERED;
@@ -538,9 +534,6 @@ int drm_connector_register(struct drm_connector *connector)
goto unlock;
-err_late_register:
- if (connector->funcs->early_unregister)
- connector->funcs->early_unregister(connector);
err_debugfs:
drm_debugfs_connector_remove(connector);
drm_sysfs_connector_remove(connector);
@@ -567,8 +560,6 @@ void drm_connector_unregister(struct drm_connector *connector)
return;
}
- drm_sysfs_connector_remove_early(connector);
-
if (connector->funcs->early_unregister)
connector->funcs->early_unregister(connector);
diff --git a/drivers/gpu/drm/drm_internal.h b/drivers/gpu/drm/drm_internal.h
index fbad756446a2..41efe40bc70f 100644
--- a/drivers/gpu/drm/drm_internal.h
+++ b/drivers/gpu/drm/drm_internal.h
@@ -165,8 +165,6 @@ int drm_sysfs_init(void);
void drm_sysfs_destroy(void);
struct device *drm_sysfs_minor_alloc(struct drm_minor *minor);
int drm_sysfs_connector_add(struct drm_connector *connector);
-int drm_sysfs_connector_add_late(struct drm_connector *connector);
-void drm_sysfs_connector_remove_early(struct drm_connector *connector);
void drm_sysfs_connector_remove(struct drm_connector *connector);
void drm_sysfs_lease_event(struct drm_device *dev);
diff --git a/drivers/gpu/drm/drm_probe_helper.c b/drivers/gpu/drm/drm_probe_helper.c
index ef4eb87fa599..d3f0d048594e 100644
--- a/drivers/gpu/drm/drm_probe_helper.c
+++ b/drivers/gpu/drm/drm_probe_helper.c
@@ -875,32 +875,3 @@ bool drm_helper_hpd_irq_event(struct drm_device *dev)
return changed;
}
EXPORT_SYMBOL(drm_helper_hpd_irq_event);
-
-/**
- * drm_connector_helper_detect_from_ddc - Read EDID and detect connector status.
- * @connector: The connector
- * @ctx: Acquire context
- * @force: Perform screen-destructive operations, if necessary
- *
- * Detects the connector status by reading the EDID using drm_probe_ddc(),
- * which requires connector->ddc to be set. Returns connector_status_connected
- * on success or connector_status_disconnected on failure.
- *
- * Returns:
- * The connector status as defined by enum drm_connector_status.
- */
-int drm_connector_helper_detect_from_ddc(struct drm_connector *connector,
- struct drm_modeset_acquire_ctx *ctx,
- bool force)
-{
- struct i2c_adapter *ddc = connector->ddc;
-
- if (!ddc)
- return connector_status_unknown;
-
- if (drm_probe_ddc(ddc))
- return connector_status_connected;
-
- return connector_status_disconnected;
-}
-EXPORT_SYMBOL(drm_connector_helper_detect_from_ddc);
diff --git a/drivers/gpu/drm/drm_sysfs.c b/drivers/gpu/drm/drm_sysfs.c
index 5f65981bdaf4..f0336c804639 100644
--- a/drivers/gpu/drm/drm_sysfs.c
+++ b/drivers/gpu/drm/drm_sysfs.c
@@ -291,29 +291,20 @@ int drm_sysfs_connector_add(struct drm_connector *connector)
return PTR_ERR(connector->kdev);
}
- return 0;
-}
-
-int drm_sysfs_connector_add_late(struct drm_connector *connector)
-{
if (connector->ddc)
return sysfs_create_link(&connector->kdev->kobj,
- &connector->ddc->dev.kobj, "ddc");
-
+ &connector->ddc->dev.kobj, "ddc");
return 0;
}
-void drm_sysfs_connector_remove_early(struct drm_connector *connector)
-{
- if (connector->ddc)
- sysfs_remove_link(&connector->kdev->kobj, "ddc");
-}
-
void drm_sysfs_connector_remove(struct drm_connector *connector)
{
if (!connector->kdev)
return;
+ if (connector->ddc)
+ sysfs_remove_link(&connector->kdev->kobj, "ddc");
+
DRM_DEBUG("removing \"%s\" from sysfs\n",
connector->name);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Kconfig b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
index 44c83c80aa68..4e41c144a290 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Kconfig
+++ b/drivers/gpu/drm/hisilicon/hibmc/Kconfig
@@ -3,8 +3,6 @@ config DRM_HISI_HIBMC
tristate "DRM Support for Hisilicon Hibmc"
depends on DRM && PCI && (ARM64 || COMPILE_TEST)
depends on MMU
- select DRM_DISPLAY_HELPER
- select DRM_DISPLAY_DP_HELPER
select DRM_KMS_HELPER
select DRM_VRAM_HELPER
select DRM_TTM
diff --git a/drivers/gpu/drm/hisilicon/hibmc/Makefile b/drivers/gpu/drm/hisilicon/hibmc/Makefile
index 43fe471caee3..684ef794eb7c 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/Makefile
+++ b/drivers/gpu/drm/hisilicon/hibmc/Makefile
@@ -1,6 +1,4 @@
# SPDX-License-Identifier: GPL-2.0-only
-hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_ttm.o hibmc_drm_i2c.o \
- dp/dp_aux.o dp/dp_link.o dp/dp_hw.o dp/dp_serdes.o hibmc_drm_dp.o \
- hibmc_drm_debugfs.o
+hibmc-drm-y := hibmc_drm_drv.o hibmc_drm_de.o hibmc_drm_vdac.o hibmc_ttm.o hibmc_drm_i2c.o
obj-$(CONFIG_DRM_HISI_HIBMC) += hibmc-drm.o
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_aux.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_aux.c
deleted file mode 100644
index 533611a211ad..000000000000
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_aux.c
+++ /dev/null
@@ -1,167 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// Copyright (c) 2024 Hisilicon Limited.
-
-#include <linux/io.h>
-#include <linux/iopoll.h>
-#include <linux/minmax.h>
-#include <drm/drm_device.h>
-#include <drm/drm_print.h>
-#include "dp_comm.h"
-#include "dp_reg.h"
-#include "dp_hw.h"
-
-#define HIBMC_AUX_CMD_REQ_LEN GENMASK(7, 4)
-#define HIBMC_AUX_CMD_ADDR GENMASK(27, 8)
-#define HIBMC_AUX_CMD_I2C_ADDR_ONLY BIT(28)
-#define HIBMC_BYTES_IN_U32 4
-#define HIBMC_AUX_I2C_WRITE_SUCCESS 0x1
-#define HIBMC_DP_MIN_PULSE_NUM 0x9
-#define BITS_IN_U8 8
-
-static inline void hibmc_dp_aux_reset(struct hibmc_dp_dev *dp)
-{
- hibmc_dp_reg_write_field(dp, HIBMC_DP_DPTX_RST_CTRL, HIBMC_DP_CFG_AUX_RST_N, 0x0);
- usleep_range(10, 15);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_DPTX_RST_CTRL, HIBMC_DP_CFG_AUX_RST_N, 0x1);
-}
-
-static void hibmc_dp_aux_read_data(struct hibmc_dp_dev *dp, u8 *buf, u8 size)
-{
- u32 reg_num;
- u32 value;
- u32 num;
- u8 i, j;
-
- reg_num = DIV_ROUND_UP(size, HIBMC_BYTES_IN_U32);
- for (i = 0; i < reg_num; i++) {
- /* number of bytes read from a single register */
- num = min(size - i * HIBMC_BYTES_IN_U32, HIBMC_BYTES_IN_U32);
- value = readl(dp->base + HIBMC_DP_AUX_RD_DATA0 + i * HIBMC_BYTES_IN_U32);
- /* convert the 32-bit value of the register to the buffer. */
- for (j = 0; j < num; j++)
- buf[i * HIBMC_BYTES_IN_U32 + j] = value >> (j * BITS_IN_U8);
- }
-}
-
-static void hibmc_dp_aux_write_data(struct hibmc_dp_dev *dp, u8 *buf, u8 size)
-{
- u32 reg_num;
- u32 value;
- u32 num;
- u8 i, j;
-
- reg_num = DIV_ROUND_UP(size, HIBMC_BYTES_IN_U32);
- for (i = 0; i < reg_num; i++) {
- /* number of bytes written to a single register */
- num = min_t(u8, size - i * HIBMC_BYTES_IN_U32, HIBMC_BYTES_IN_U32);
- value = 0;
- /* obtain the 32-bit value written to a single register. */
- for (j = 0; j < num; j++)
- value |= buf[i * HIBMC_BYTES_IN_U32 + j] << (j * BITS_IN_U8);
- /* writing data to a single register */
- writel(value, dp->base + HIBMC_DP_AUX_WR_DATA0 + i * HIBMC_BYTES_IN_U32);
- }
-}
-
-static u32 hibmc_dp_aux_build_cmd(const struct drm_dp_aux_msg *msg)
-{
- u32 aux_cmd = msg->request;
-
- if (msg->size)
- aux_cmd |= FIELD_PREP(HIBMC_AUX_CMD_REQ_LEN, (msg->size - 1));
- else
- aux_cmd |= FIELD_PREP(HIBMC_AUX_CMD_I2C_ADDR_ONLY, 1);
-
- aux_cmd |= FIELD_PREP(HIBMC_AUX_CMD_ADDR, msg->address);
-
- return aux_cmd;
-}
-
-/* ret >= 0, ret is size; ret < 0, ret is err code */
-static int hibmc_dp_aux_parse_xfer(struct hibmc_dp_dev *dp, struct drm_dp_aux_msg *msg)
-{
- u32 buf_data_cnt;
- u32 aux_status;
-
- aux_status = readl(dp->base + HIBMC_DP_AUX_STATUS);
- msg->reply = FIELD_GET(HIBMC_DP_CFG_AUX_STATUS, aux_status);
-
- if (aux_status & HIBMC_DP_CFG_AUX_TIMEOUT)
- return -ETIMEDOUT;
-
- /* only address */
- if (!msg->size)
- return 0;
-
- if (msg->reply != DP_AUX_NATIVE_REPLY_ACK)
- return -EIO;
-
- buf_data_cnt = FIELD_GET(HIBMC_DP_CFG_AUX_READY_DATA_BYTE, aux_status);
-
- switch (msg->request) {
- case DP_AUX_NATIVE_WRITE:
- return msg->size;
- case DP_AUX_I2C_WRITE | DP_AUX_I2C_MOT:
- if (buf_data_cnt == HIBMC_AUX_I2C_WRITE_SUCCESS)
- return msg->size;
- else
- return FIELD_GET(HIBMC_DP_CFG_AUX, aux_status);
- case DP_AUX_NATIVE_READ:
- case DP_AUX_I2C_READ | DP_AUX_I2C_MOT:
- buf_data_cnt--;
- if (buf_data_cnt != msg->size) {
- /* only the successful part of data is read */
- return -EBUSY;
- }
-
- /* all data is successfully read */
- hibmc_dp_aux_read_data(dp, msg->buffer, msg->size);
- return msg->size;
- default:
- return -EINVAL;
- }
-}
-
-/* ret >= 0 ,ret is size; ret < 0, ret is err code */
-static ssize_t hibmc_dp_aux_xfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
-{
- struct hibmc_dp *dp_priv = container_of(aux, struct hibmc_dp, aux);
- struct hibmc_dp_dev *dp = dp_priv->dp_dev;
- u32 aux_cmd;
- int ret;
- u32 val; /* val will be assigned at the beginning of readl_poll_timeout function */
-
- writel(0, dp->base + HIBMC_DP_AUX_WR_DATA0);
- writel(0, dp->base + HIBMC_DP_AUX_WR_DATA1);
- writel(0, dp->base + HIBMC_DP_AUX_WR_DATA2);
- writel(0, dp->base + HIBMC_DP_AUX_WR_DATA3);
-
- hibmc_dp_aux_write_data(dp, msg->buffer, msg->size);
-
- aux_cmd = hibmc_dp_aux_build_cmd(msg);
- writel(aux_cmd, dp->base + HIBMC_DP_AUX_CMD_ADDR);
-
- /* enable aux transfer */
- hibmc_dp_reg_write_field(dp, HIBMC_DP_AUX_REQ, HIBMC_DP_CFG_AUX_REQ, 0x1);
- ret = readl_poll_timeout(dp->base + HIBMC_DP_AUX_REQ, val,
- !(val & HIBMC_DP_CFG_AUX_REQ), 50, 5000);
- if (ret) {
- hibmc_dp_aux_reset(dp);
- return ret;
- }
-
- return hibmc_dp_aux_parse_xfer(dp, msg);
-}
-
-void hibmc_dp_aux_init(struct hibmc_dp *dp)
-{
- hibmc_dp_reg_write_field(dp->dp_dev, HIBMC_DP_AUX_REQ, HIBMC_DP_CFG_AUX_SYNC_LEN_SEL, 0x0);
- hibmc_dp_reg_write_field(dp->dp_dev, HIBMC_DP_AUX_REQ, HIBMC_DP_CFG_AUX_TIMER_TIMEOUT, 0x1);
- hibmc_dp_reg_write_field(dp->dp_dev, HIBMC_DP_AUX_REQ, HIBMC_DP_CFG_AUX_MIN_PULSE_NUM,
- HIBMC_DP_MIN_PULSE_NUM);
-
- dp->aux.transfer = hibmc_dp_aux_xfer;
- dp->aux.name = "HIBMC DRM dp aux";
- drm_dp_aux_init(&dp->aux);
- dp->dp_dev->aux = &dp->aux;
-}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h
deleted file mode 100644
index 1107e10b2047..000000000000
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (c) 2024 Hisilicon Limited. */
-
-#ifndef DP_COMM_H
-#define DP_COMM_H
-
-#include <linux/types.h>
-#include <linux/bitops.h>
-#include <linux/errno.h>
-#include <linux/mutex.h>
-#include <linux/kernel.h>
-#include <linux/bitfield.h>
-#include <linux/io.h>
-#include <drm/drm_dp_helper.h>
-
-#include "dp_hw.h"
-
-#define HIBMC_DP_LINK_RATE_CAL 27
-#define HIBMC_DP_LANE_NUM_MAX 2
-
-struct hibmc_link_status {
- bool clock_recovered;
- bool channel_equalized;
-};
-
-struct hibmc_link_cap {
- u8 link_rate;
- u8 lanes;
- int rx_dpcd_revision;
- bool is_tps3;
- bool is_tps4;
-};
-
-struct hibmc_dp_link {
- struct hibmc_link_status status;
- u8 train_set[HIBMC_DP_LANE_NUM_MAX];
- struct hibmc_link_cap cap;
-};
-
-struct hibmc_dp_dev {
- struct drm_dp_aux *aux;
- struct drm_device *dev;
- void __iomem *base;
- struct mutex lock; /* protects concurrent RW in hibmc_dp_reg_write_field() */
- struct hibmc_dp_link link;
- u8 dpcd[DP_RECEIVER_CAP_SIZE];
- void __iomem *serdes_base;
-};
-
-#define dp_field_modify(reg_value, mask, val) \
- do { \
- (reg_value) &= ~(mask); \
- (reg_value) |= FIELD_PREP(mask, val); \
- } while (0) \
-
-#define hibmc_dp_reg_write_field(dp, offset, mask, val) \
- do { \
- u32 reg_value; \
- typeof(dp) _dp = dp; \
- typeof(_dp->base) addr = (_dp->base + (offset)); \
- mutex_lock(&_dp->lock); \
- reg_value = readl(addr); \
- dp_field_modify(reg_value, mask, val); \
- writel(reg_value, addr); \
- mutex_unlock(&_dp->lock); \
- } while (0)
-
-void hibmc_dp_aux_init(struct hibmc_dp *dp);
-int hibmc_dp_link_training(struct hibmc_dp_dev *dp);
-int hibmc_dp_serdes_rate_switch(u8 rate, struct hibmc_dp_dev *dp);
-int hibmc_dp_serdes_set_tx_cfg(struct hibmc_dp_dev *dp, u8 train_set[HIBMC_DP_LANE_NUM_MAX]);
-
-#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_config.h b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_config.h
deleted file mode 100644
index 08f9e1caf7fc..000000000000
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_config.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (c) 2024 Hisilicon Limited. */
-
-#ifndef DP_CONFIG_H
-#define DP_CONFIG_H
-
-#define HIBMC_DP_BPP 24
-#define HIBMC_DP_SYMBOL_PER_FCLK 4
-#define HIBMC_DP_MSA1 0x20
-#define HIBMC_DP_MSA2 0x845c00
-#define HIBMC_DP_OFFSET 0x1e0000
-#define HIBMC_DP_HDCP 0x2
-#define HIBMC_DP_INT_RST 0xffff
-#define HIBMC_DP_DPTX_RST 0x3ff
-#define HIBMC_DP_CLK_EN 0x7
-#define HIBMC_DP_SYNC_EN_MASK 0x3
-#define HIBMC_DP_LINK_RATE_CAL 27
-#define HIBMC_DP_SYNC_DELAY(lanes) ((lanes) == 0x2 ? 86 : 46)
-#define HIBMC_DP_INT_ENABLE 0xc
-
-#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c
deleted file mode 100644
index 9e8f95d957f2..000000000000
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c
+++ /dev/null
@@ -1,338 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// Copyright (c) 2024 Hisilicon Limited.
-
-#include <linux/io.h>
-#include <linux/delay.h>
-#include "dp_config.h"
-#include "dp_comm.h"
-#include "dp_reg.h"
-#include "dp_hw.h"
-
-static void hibmc_dp_set_tu(struct hibmc_dp_dev *dp, struct drm_display_mode *mode)
-{
- u32 tu_symbol_frac_size;
- u32 tu_symbol_size;
- u32 rate_ks;
- u8 lane_num;
- u32 value;
- u32 bpp;
-
- lane_num = dp->link.cap.lanes;
- if (lane_num == 0) {
- drm_err(dp->dev, "set tu failed, lane num cannot be 0!\n");
- return;
- }
-
- bpp = HIBMC_DP_BPP;
- rate_ks = dp->link.cap.link_rate * HIBMC_DP_LINK_RATE_CAL;
- value = (mode->clock * bpp * 5) / (61 * lane_num * rate_ks);
-
- if (value % 10 == 9) { /* 9 carry */
- tu_symbol_size = value / 10 + 1;
- tu_symbol_frac_size = 0;
- } else {
- tu_symbol_size = value / 10;
- tu_symbol_frac_size = value % 10 + 1;
- }
-
- drm_dbg_dp(dp->dev, "tu value: %u.%u value: %u\n",
- tu_symbol_size, tu_symbol_frac_size, value);
-
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_PACKET,
- HIBMC_DP_CFG_STREAM_TU_SYMBOL_SIZE, tu_symbol_size);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_PACKET,
- HIBMC_DP_CFG_STREAM_TU_SYMBOL_FRAC_SIZE, tu_symbol_frac_size);
-}
-
-static void hibmc_dp_set_sst(struct hibmc_dp_dev *dp, struct drm_display_mode *mode)
-{
- u32 hblank_size;
- u32 htotal_size;
- u32 htotal_int;
- u32 hblank_int;
- u32 fclk; /* flink_clock */
-
- fclk = dp->link.cap.link_rate * HIBMC_DP_LINK_RATE_CAL;
-
- /* Considering the effect of spread spectrum, the value may be deviated.
- * The coefficient (0.9947) is used to offset the deviation.
- */
- htotal_int = mode->htotal * 9947 / 10000;
- htotal_size = htotal_int * fclk / (HIBMC_DP_SYMBOL_PER_FCLK * (mode->clock / 1000));
-
- hblank_int = mode->htotal - mode->hdisplay - mode->hdisplay * 53 / 10000;
- hblank_size = hblank_int * fclk * 9947 /
- (mode->clock * 10 * HIBMC_DP_SYMBOL_PER_FCLK);
-
- drm_dbg_dp(dp->dev, "h_active %u v_active %u htotal_size %u hblank_size %u",
- mode->hdisplay, mode->vdisplay, htotal_size, hblank_size);
- drm_dbg_dp(dp->dev, "flink_clock %u pixel_clock %d", fclk, mode->clock / 1000);
-
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_HORIZONTAL_SIZE,
- HIBMC_DP_CFG_STREAM_HTOTAL_SIZE, htotal_size);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_HORIZONTAL_SIZE,
- HIBMC_DP_CFG_STREAM_HBLANK_SIZE, hblank_size);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_PACKET,
- HIBMC_DP_CFG_STREAM_SYNC_CALIBRATION,
- HIBMC_DP_SYNC_DELAY(dp->link.cap.lanes));
-}
-
-static void hibmc_dp_link_cfg(struct hibmc_dp_dev *dp, struct drm_display_mode *mode)
-{
- u32 timing_delay;
- u32 vblank;
- u32 hstart;
- u32 vstart;
-
- vblank = mode->vtotal - mode->vdisplay;
- timing_delay = mode->htotal - mode->hsync_start;
- hstart = mode->htotal - mode->hsync_start;
- vstart = mode->vtotal - mode->vsync_start;
-
- hibmc_dp_reg_write_field(dp, HIBMC_DP_TIMING_GEN_CONFIG0,
- HIBMC_DP_CFG_TIMING_GEN0_HBLANK, mode->htotal - mode->hdisplay);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_TIMING_GEN_CONFIG0,
- HIBMC_DP_CFG_TIMING_GEN0_HACTIVE, mode->hdisplay);
-
- hibmc_dp_reg_write_field(dp, HIBMC_DP_TIMING_GEN_CONFIG2,
- HIBMC_DP_CFG_TIMING_GEN0_VBLANK, vblank);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_TIMING_GEN_CONFIG2,
- HIBMC_DP_CFG_TIMING_GEN0_VACTIVE, mode->vdisplay);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_TIMING_GEN_CONFIG3,
- HIBMC_DP_CFG_TIMING_GEN0_VFRONT_PORCH,
- mode->vsync_start - mode->vdisplay);
-
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CONFIG0,
- HIBMC_DP_CFG_STREAM_HACTIVE, mode->hdisplay);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CONFIG0,
- HIBMC_DP_CFG_STREAM_HBLANK, mode->htotal - mode->hdisplay);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CONFIG2,
- HIBMC_DP_CFG_STREAM_HSYNC_WIDTH,
- mode->hsync_end - mode->hsync_start);
-
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CONFIG1,
- HIBMC_DP_CFG_STREAM_VACTIVE, mode->vdisplay);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CONFIG1,
- HIBMC_DP_CFG_STREAM_VBLANK, vblank);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CONFIG3,
- HIBMC_DP_CFG_STREAM_VFRONT_PORCH,
- mode->vsync_start - mode->vdisplay);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CONFIG3,
- HIBMC_DP_CFG_STREAM_VSYNC_WIDTH,
- mode->vsync_end - mode->vsync_start);
-
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_MSA0,
- HIBMC_DP_CFG_STREAM_VSTART, vstart);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_MSA0,
- HIBMC_DP_CFG_STREAM_HSTART, hstart);
-
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CTRL, HIBMC_DP_CFG_STREAM_VSYNC_POLARITY,
- mode->flags & DRM_MODE_FLAG_PVSYNC ? 1 : 0);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CTRL, HIBMC_DP_CFG_STREAM_HSYNC_POLARITY,
- mode->flags & DRM_MODE_FLAG_PHSYNC ? 1 : 0);
-
- /* MSA mic 0 and 1 */
- writel(HIBMC_DP_MSA1, dp->base + HIBMC_DP_VIDEO_MSA1);
- writel(HIBMC_DP_MSA2, dp->base + HIBMC_DP_VIDEO_MSA2);
-
- hibmc_dp_set_tu(dp, mode);
-
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CTRL, HIBMC_DP_CFG_STREAM_RGB_ENABLE, 0x1);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CTRL, HIBMC_DP_CFG_STREAM_VIDEO_MAPPING, 0);
-
- /* divide 2: up even */
- if (timing_delay % 2)
- timing_delay++;
-
- hibmc_dp_reg_write_field(dp, HIBMC_DP_TIMING_MODEL_CTRL,
- HIBMC_DP_CFG_PIXEL_NUM_TIMING_MODE_SEL1, timing_delay);
-
- hibmc_dp_set_sst(dp, mode);
-}
-
-int hibmc_dp_hw_init(struct hibmc_dp *dp)
-{
- struct drm_device *drm_dev = dp->drm_dev;
- struct hibmc_dp_dev *dp_dev;
-
- dp_dev = devm_kzalloc(drm_dev->dev, sizeof(struct hibmc_dp_dev), GFP_KERNEL);
- if (!dp_dev)
- return -ENOMEM;
-
- mutex_init(&dp_dev->lock);
-
- dp->dp_dev = dp_dev;
-
- dp_dev->dev = drm_dev;
- dp_dev->base = dp->mmio + HIBMC_DP_OFFSET;
- dp_dev->serdes_base = dp_dev->base + HIBMC_DP_HOST_OFFSET;
-
- hibmc_dp_aux_init(dp);
-
- dp_dev->link.cap.lanes = 0x2;
- dp_dev->link.cap.link_rate = DP_LINK_BW_8_1;
-
- /* int init */
- writel(0, dp_dev->base + HIBMC_DP_INTR_ENABLE);
- writel(HIBMC_DP_INT_RST, dp_dev->base + HIBMC_DP_INTR_ORIGINAL_STATUS);
- /* rst */
- writel(0, dp_dev->base + HIBMC_DP_DPTX_RST_CTRL);
- usleep_range(30, 50);
- writel(HIBMC_DP_DPTX_RST, dp_dev->base + HIBMC_DP_DPTX_RST_CTRL);
- /* hdcp data */
- writel(HIBMC_DP_HDCP, dp_dev->base + HIBMC_DP_HDCP_CFG);
- /* clock enable */
- writel(HIBMC_DP_CLK_EN, dp_dev->base + HIBMC_DP_DPTX_CLK_CTRL);
-
- return 0;
-}
-
-void hibmc_dp_enable_int(struct hibmc_dp *dp)
-{
- struct hibmc_dp_dev *dp_dev = dp->dp_dev;
-
- writel(HIBMC_DP_INT_ENABLE, dp_dev->base + HIBMC_DP_INTR_ENABLE);
-}
-
-void hibmc_dp_disable_int(struct hibmc_dp *dp)
-{
- struct hibmc_dp_dev *dp_dev = dp->dp_dev;
-
- writel(0, dp_dev->base + HIBMC_DP_INTR_ENABLE);
- writel(HIBMC_DP_INT_RST, dp_dev->base + HIBMC_DP_INTR_ORIGINAL_STATUS);
-}
-
-void hibmc_dp_hpd_cfg(struct hibmc_dp *dp)
-{
- struct hibmc_dp_dev *dp_dev = dp->dp_dev;
-
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_AUX_REQ, HIBMC_DP_CFG_AUX_SYNC_LEN_SEL, 0x0);
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_AUX_REQ, HIBMC_DP_CFG_AUX_TIMER_TIMEOUT, 0x1);
- hibmc_dp_reg_write_field(dp->dp_dev, HIBMC_DP_AUX_REQ, HIBMC_DP_CFG_AUX_MIN_PULSE_NUM, 0x9);
- writel(HIBMC_DP_HDCP, dp_dev->base + HIBMC_DP_HDCP_CFG);
- writel(0, dp_dev->base + HIBMC_DP_INTR_ENABLE);
- writel(HIBMC_DP_INT_RST, dp_dev->base + HIBMC_DP_INTR_ORIGINAL_STATUS);
- writel(HIBMC_DP_INT_ENABLE, dp_dev->base + HIBMC_DP_INTR_ENABLE);
- writel(HIBMC_DP_DPTX_RST, dp_dev->base + HIBMC_DP_DPTX_RST_CTRL);
- writel(HIBMC_DP_CLK_EN, dp_dev->base + HIBMC_DP_DPTX_CLK_CTRL);
-}
-
-void hibmc_dp_display_en(struct hibmc_dp *dp, bool enable)
-{
- struct hibmc_dp_dev *dp_dev = dp->dp_dev;
-
- if (enable) {
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_VIDEO_CTRL,
- HIBMC_DP_CFG_MST_ENABLE, 0x1);
- writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL);
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_DPTX_GCTL0,
- HIBMC_DP_CFG_TIMING_GEN_ENABLE, 0x1);
- writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL);
- } else {
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_DPTX_GCTL0,
- HIBMC_DP_CFG_TIMING_GEN_ENABLE, 0);
- writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL);
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_VIDEO_CTRL, HIBMC_DP_CFG_MST_ENABLE, 0);
- writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL);
- }
-
- msleep(50);
-}
-
-int hibmc_dp_mode_set(struct hibmc_dp *dp, struct drm_display_mode *mode)
-{
- struct hibmc_dp_dev *dp_dev = dp->dp_dev;
- int ret;
-
- if (!dp_dev->link.status.channel_equalized) {
- ret = hibmc_dp_link_training(dp_dev);
- if (ret) {
- drm_err(dp->drm_dev, "dp link training failed, ret: %d\n", ret);
- return ret;
- }
- }
-
- hibmc_dp_display_en(dp, false);
- hibmc_dp_link_cfg(dp_dev, mode);
-
- return 0;
-}
-
-u8 hibmc_dp_get_link_rate(struct hibmc_dp *dp)
-{
- if (!dp->dp_dev)
- return 0;
-
- return dp->dp_dev->link.cap.link_rate;
-}
-
-u8 hibmc_dp_get_lanes(struct hibmc_dp *dp)
-{
- if (!dp->dp_dev)
- return 0;
-
- return dp->dp_dev->link.cap.lanes;
-}
-
-int hibmc_dp_get_dpcd(struct hibmc_dp *dp)
-{
- if (!dp->dp_dev)
- return 0;
-
- return dp->dp_dev->link.cap.rx_dpcd_revision;
-}
-
-void hibmc_dp_reset_link(struct hibmc_dp *dp)
-{
- if (dp->dp_dev) {
- dp->dp_dev->link.status.clock_recovered = false;
- dp->dp_dev->link.status.channel_equalized = false;
- }
-}
-
-static const struct hibmc_dp_color_raw g_rgb_raw[] = {
- {CBAR_COLOR_BAR, 0x000, 0x000, 0x000},
- {CBAR_WHITE, 0xfff, 0xfff, 0xfff},
- {CBAR_RED, 0xfff, 0x000, 0x000},
- {CBAR_ORANGE, 0xfff, 0x800, 0x000},
- {CBAR_YELLOW, 0xfff, 0xfff, 0x000},
- {CBAR_GREEN, 0x000, 0xfff, 0x000},
- {CBAR_CYAN, 0x000, 0x800, 0x800},
- {CBAR_BLUE, 0x000, 0x000, 0xfff},
- {CBAR_PURPLE, 0x800, 0x000, 0x800},
- {CBAR_BLACK, 0x000, 0x000, 0x000},
-};
-
-void hibmc_dp_set_cbar(struct hibmc_dp *dp, const struct hibmc_dp_cbar_cfg *cfg)
-{
- struct hibmc_dp_dev *dp_dev = dp->dp_dev;
- struct hibmc_dp_color_raw raw_data;
-
- if (cfg->enable) {
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL,
- HIBMC_DP_COLOR_BAR_TIMING_SEL_M, cfg->self_timing);
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL,
- HIBMC_DP_COLOR_BAR_CTRL_M, cfg->dynamic_rate);
- if (cfg->pattern == CBAR_COLOR_BAR) {
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL,
- HIBMC_DP_COLOR_BAR_PATTERN_SEL_M, 0);
- } else {
- raw_data = g_rgb_raw[cfg->pattern];
- drm_dbg_dp(dp->drm_dev, "r:%x g:%x b:%x\n", raw_data.r_value,
- raw_data.g_value, raw_data.b_value);
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL,
- HIBMC_DP_COLOR_BAR_PATTERN_SEL_M, 1);
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL,
- HIBMC_DP_COLOR_BAR_DATA_R_M, raw_data.r_value);
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL1,
- HIBMC_DP_COLOR_BAR_DATA_G_M, raw_data.g_value);
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL1,
- HIBMC_DP_COLOR_BAR_DATA_B_M, raw_data.b_value);
- }
- }
-
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL,
- HIBMC_DP_COLOR_BAR_ENABLE_M, cfg->enable);
- writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL);
-}
-
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h
deleted file mode 100644
index 4740db06e1b0..000000000000
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h
+++ /dev/null
@@ -1,74 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (c) 2024 Hisilicon Limited. */
-
-#ifndef DP_KAPI_H
-#define DP_KAPI_H
-
-#include <linux/types.h>
-#include <linux/delay.h>
-#include <drm/drm_device.h>
-#include <drm/drm_encoder.h>
-#include <drm/drm_connector.h>
-#include <drm/drm_print.h>
-#include <drm/drm_dp_helper.h>
-
-// 27 * 10000000 * 80% = 216000000
-#define DP_MODE_VALI_CAL 216000000
-#define BPP_24 24
-
-struct hibmc_dp_dev;
-
-enum hibmc_dp_cbar_pattern {
- CBAR_COLOR_BAR,
- CBAR_WHITE,
- CBAR_RED,
- CBAR_ORANGE,
- CBAR_YELLOW,
- CBAR_GREEN,
- CBAR_CYAN,
- CBAR_BLUE,
- CBAR_PURPLE,
- CBAR_BLACK,
-};
-
-struct hibmc_dp_color_raw {
- enum hibmc_dp_cbar_pattern pattern;
- u32 r_value;
- u32 g_value;
- u32 b_value;
-};
-
-struct hibmc_dp_cbar_cfg {
- u8 enable;
- u8 self_timing;
- u8 dynamic_rate; /* 0:static, 1-255(frame):dynamic */
- enum hibmc_dp_cbar_pattern pattern;
-};
-
-struct hibmc_dp {
- struct hibmc_dp_dev *dp_dev;
- struct drm_device *drm_dev;
- struct drm_encoder encoder;
- struct drm_connector connector;
- void __iomem *mmio;
- struct drm_dp_aux aux;
- struct hibmc_dp_cbar_cfg cfg;
- u32 irq_status;
- int hpd_status;
- bool is_connected;
-};
-
-int hibmc_dp_hw_init(struct hibmc_dp *dp);
-int hibmc_dp_mode_set(struct hibmc_dp *dp, struct drm_display_mode *mode);
-void hibmc_dp_display_en(struct hibmc_dp *dp, bool enable);
-struct edid *hibmc_dp_get_edid(struct hibmc_dp *dp);
-int hibmc_dp_get_dpcd(struct hibmc_dp *dp);
-u8 hibmc_dp_get_link_rate(struct hibmc_dp *dp);
-u8 hibmc_dp_get_lanes(struct hibmc_dp *dp);
-void hibmc_dp_set_cbar(struct hibmc_dp *dp, const struct hibmc_dp_cbar_cfg *cfg);
-void hibmc_dp_reset_link(struct hibmc_dp *dp);
-void hibmc_dp_hpd_cfg(struct hibmc_dp *dp);
-void hibmc_dp_enable_int(struct hibmc_dp *dp);
-void hibmc_dp_disable_int(struct hibmc_dp *dp);
-
-#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c
deleted file mode 100644
index 9b632428fec6..000000000000
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c
+++ /dev/null
@@ -1,415 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// Copyright (c) 2024 Hisilicon Limited.
-
-#include <linux/delay.h>
-#include <drm/drm_device.h>
-#include <drm/drm_print.h>
-#include "dp_comm.h"
-#include "dp_reg.h"
-
-#define HIBMC_EQ_MAX_RETRY 5
-
-static inline int hibmc_dp_get_serdes_rate_cfg(struct hibmc_dp_dev *dp)
-{
- switch (dp->link.cap.link_rate) {
- case DP_LINK_BW_1_62:
- return DP_SERDES_BW_1_62;
- case DP_LINK_BW_2_7:
- return DP_SERDES_BW_2_7;
- case DP_LINK_BW_5_4:
- return DP_SERDES_BW_5_4;
- case DP_LINK_BW_8_1:
- return DP_SERDES_BW_8_1;
- default:
- return -EINVAL;
- }
-}
-
-static int hibmc_dp_link_training_configure(struct hibmc_dp_dev *dp)
-{
- u8 buf[2];
- int ret;
-
- /* DP 2 lane */
- hibmc_dp_reg_write_field(dp, HIBMC_DP_PHYIF_CTRL0, HIBMC_DP_CFG_LANE_DATA_EN,
- dp->link.cap.lanes == 0x2 ? 0x3 : 0x1);
- hibmc_dp_reg_write_field(dp, HIBMC_DP_DPTX_GCTL0, HIBMC_DP_CFG_PHY_LANE_NUM,
- dp->link.cap.lanes == 0x2 ? 0x1 : 0);
-
- /* enhanced frame */
- hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CTRL, HIBMC_DP_CFG_STREAM_FRAME_MODE, 0x1);
-
- ret = hibmc_dp_get_serdes_rate_cfg(dp);
- if (ret < 0)
- return ret;
-
- ret = hibmc_dp_serdes_rate_switch(ret, dp);
- if (ret)
- return ret;
-
- /* set rate and lane count */
- buf[0] = dp->link.cap.link_rate;
- buf[1] = DP_LANE_COUNT_ENHANCED_FRAME_EN | dp->link.cap.lanes;
- ret = drm_dp_dpcd_write(dp->aux, DP_LINK_BW_SET, buf, sizeof(buf));
- if (ret != sizeof(buf)) {
- drm_dbg_dp(dp->dev, "dp aux write link rate and lanes failed, ret: %d\n", ret);
- return ret >= 0 ? -EIO : ret;
- }
-
- /* set 8b/10b and downspread */
- buf[0] = DP_SPREAD_AMP_0_5;
- buf[1] = DP_SET_ANSI_8B10B;
- ret = drm_dp_dpcd_write(dp->aux, DP_DOWNSPREAD_CTRL, buf, sizeof(buf));
- if (ret != sizeof(buf)) {
- drm_dbg_dp(dp->dev, "dp aux write 8b/10b and downspread failed, ret: %d\n", ret);
- return ret >= 0 ? -EIO : ret;
- }
-
- return 0;
-}
-
-static int hibmc_dp_link_set_pattern(struct hibmc_dp_dev *dp, int pattern)
-{
- int ret;
- u8 val;
- u8 buf;
-
- buf = (u8)pattern;
- if (pattern != DP_TRAINING_PATTERN_DISABLE && pattern != DP_TRAINING_PATTERN_4) {
- buf |= DP_LINK_SCRAMBLING_DISABLE;
- hibmc_dp_reg_write_field(dp, HIBMC_DP_PHYIF_CTRL0, HIBMC_DP_CFG_SCRAMBLE_EN, 0x1);
- } else {
- hibmc_dp_reg_write_field(dp, HIBMC_DP_PHYIF_CTRL0, HIBMC_DP_CFG_SCRAMBLE_EN, 0);
- }
-
- switch (pattern) {
- case DP_TRAINING_PATTERN_DISABLE:
- val = 0;
- break;
- case DP_TRAINING_PATTERN_1:
- val = 1;
- break;
- case DP_TRAINING_PATTERN_2:
- val = 2;
- break;
- case DP_TRAINING_PATTERN_3:
- val = 3;
- break;
- case DP_TRAINING_PATTERN_4:
- val = 4;
- break;
- default:
- return -EINVAL;
- }
-
- hibmc_dp_reg_write_field(dp, HIBMC_DP_PHYIF_CTRL0, HIBMC_DP_CFG_PAT_SEL, val);
-
- ret = drm_dp_dpcd_write(dp->aux, DP_TRAINING_PATTERN_SET, &buf, sizeof(buf));
- if (ret != sizeof(buf)) {
- drm_dbg_dp(dp->dev, "dp aux write training pattern set failed\n");
- return ret >= 0 ? -EIO : ret;
- }
-
- return 0;
-}
-
-static int hibmc_dp_link_training_cr_pre(struct hibmc_dp_dev *dp)
-{
- u8 *train_set = dp->link.train_set;
- int ret;
- u8 i;
-
- ret = hibmc_dp_link_training_configure(dp);
- if (ret)
- return ret;
-
- ret = hibmc_dp_link_set_pattern(dp, DP_TRAINING_PATTERN_1);
- if (ret)
- return ret;
-
- for (i = 0; i < dp->link.cap.lanes; i++)
- train_set[i] = DP_TRAIN_VOLTAGE_SWING_LEVEL_0;
-
- ret = hibmc_dp_serdes_set_tx_cfg(dp, dp->link.train_set);
- if (ret)
- return ret;
-
- ret = drm_dp_dpcd_write(dp->aux, DP_TRAINING_LANE0_SET, train_set, dp->link.cap.lanes);
- if (ret != dp->link.cap.lanes) {
- drm_dbg_dp(dp->dev, "dp aux write training lane set failed\n");
- return ret >= 0 ? -EIO : ret;
- }
-
- return 0;
-}
-
-static bool hibmc_dp_link_get_adjust_train(struct hibmc_dp_dev *dp,
- u8 lane_status[DP_LINK_STATUS_SIZE])
-{
- u8 train_set[HIBMC_DP_LANE_NUM_MAX] = {0};
- u8 lane;
-
- for (lane = 0; lane < dp->link.cap.lanes; lane++)
- train_set[lane] = drm_dp_get_adjust_request_voltage(lane_status, lane) |
- drm_dp_get_adjust_request_pre_emphasis(lane_status, lane);
-
- if (memcmp(dp->link.train_set, train_set, HIBMC_DP_LANE_NUM_MAX)) {
- memcpy(dp->link.train_set, train_set, HIBMC_DP_LANE_NUM_MAX);
- return true;
- }
-
- return false;
-}
-
-static int hibmc_dp_link_reduce_rate(struct hibmc_dp_dev *dp)
-{
- int ret;
-
- switch (dp->link.cap.link_rate) {
- case DP_LINK_BW_2_7:
- dp->link.cap.link_rate = DP_LINK_BW_1_62;
- break;
- case DP_LINK_BW_5_4:
- dp->link.cap.link_rate = DP_LINK_BW_2_7;
- break;
- case DP_LINK_BW_8_1:
- dp->link.cap.link_rate = DP_LINK_BW_5_4;
- break;
- default:
- return -EINVAL;
- }
-
- ret = hibmc_dp_get_serdes_rate_cfg(dp);
- if (ret < 0)
- return ret;
-
- return hibmc_dp_serdes_rate_switch(ret, dp);
-}
-
-static inline int hibmc_dp_link_reduce_lane(struct hibmc_dp_dev *dp)
-{
- switch (dp->link.cap.lanes) {
- case 0x2:
- dp->link.cap.lanes--;
- drm_dbg_dp(dp->dev, "dp link training reduce to 1 lane\n");
- break;
- case 0x1:
- drm_err(dp->dev, "dp link training reduce lane failed, already reach minimum\n");
- return -EIO;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int hibmc_dp_link_training_cr(struct hibmc_dp_dev *dp)
-{
- u8 lane_status[DP_LINK_STATUS_SIZE] = {0};
- bool level_changed;
- u32 voltage_tries;
- u32 cr_tries;
- u32 max_cr;
- int ret;
-
- /*
- * DP 1.4 spec define 10 for maxtries value, for pre DP 1.4 version set a limit of 80
- * (4 voltage levels x 4 preemphasis levels x 5 identical voltage retries)
- */
- max_cr = dp->link.cap.rx_dpcd_revision >= DP_DPCD_REV_14 ? 10 : 80;
-
- voltage_tries = 1;
- for (cr_tries = 0; cr_tries < max_cr; cr_tries++) {
- drm_dp_link_train_clock_recovery_delay(dp->dpcd);
-
- ret = drm_dp_dpcd_read_link_status(dp->aux, lane_status);
- if (ret != DP_LINK_STATUS_SIZE) {
- drm_err(dp->dev, "Get lane status failed, ret: %d\n", ret);
- return ret >= 0 ? -EIO : ret;
- }
-
- if (drm_dp_clock_recovery_ok(lane_status, dp->link.cap.lanes)) {
- drm_dbg_dp(dp->dev, "dp link training cr done\n");
- dp->link.status.clock_recovered = true;
- return 0;
- }
-
- if (voltage_tries == 5) {
- drm_dbg_dp(dp->dev, "same voltage tries 5 times\n");
- dp->link.status.clock_recovered = false;
- return 0;
- }
-
- level_changed = hibmc_dp_link_get_adjust_train(dp, lane_status);
-
- ret = hibmc_dp_serdes_set_tx_cfg(dp, dp->link.train_set);
- if (ret)
- return ret;
-
- ret = drm_dp_dpcd_write(dp->aux, DP_TRAINING_LANE0_SET, dp->link.train_set,
- dp->link.cap.lanes);
- if (ret != dp->link.cap.lanes) {
- drm_dbg_dp(dp->dev, "Update link training failed\n");
- return ret >= 0 ? -EIO : ret;
- }
-
- voltage_tries = level_changed ? 1 : voltage_tries + 1;
- }
-
- drm_err(dp->dev, "dp link training clock recovery %u timers failed\n", max_cr);
- dp->link.status.clock_recovered = false;
-
- return 0;
-}
-
-static int hibmc_dp_link_training_channel_eq(struct hibmc_dp_dev *dp)
-{
- u8 lane_status[DP_LINK_STATUS_SIZE] = {0};
- u8 eq_tries;
- int tps;
- int ret;
-
- if (dp->link.cap.is_tps4)
- tps = DP_TRAINING_PATTERN_4;
- else if (dp->link.cap.is_tps3)
- tps = DP_TRAINING_PATTERN_3;
- else
- tps = DP_TRAINING_PATTERN_2;
-
- ret = hibmc_dp_link_set_pattern(dp, tps);
- if (ret)
- return ret;
-
- for (eq_tries = 0; eq_tries < HIBMC_EQ_MAX_RETRY; eq_tries++) {
- drm_dp_link_train_channel_eq_delay(dp->dpcd);
-
- ret = drm_dp_dpcd_read_link_status(dp->aux, lane_status);
- if (ret != DP_LINK_STATUS_SIZE) {
- drm_err(dp->dev, "get lane status failed\n");
- break;
- }
-
- if (!drm_dp_clock_recovery_ok(lane_status, dp->link.cap.lanes)) {
- drm_dbg_dp(dp->dev, "clock recovery check failed\n");
- drm_dbg_dp(dp->dev, "cannot continue channel equalization\n");
- dp->link.status.clock_recovered = false;
- break;
- }
-
- if (drm_dp_channel_eq_ok(lane_status, dp->link.cap.lanes)) {
- dp->link.status.channel_equalized = true;
- drm_dbg_dp(dp->dev, "dp link training eq done\n");
- break;
- }
-
- hibmc_dp_link_get_adjust_train(dp, lane_status);
-
- ret = hibmc_dp_serdes_set_tx_cfg(dp, dp->link.train_set);
- if (ret)
- break;
-
- ret = drm_dp_dpcd_write(dp->aux, DP_TRAINING_LANE0_SET,
- dp->link.train_set, dp->link.cap.lanes);
- if (ret != dp->link.cap.lanes) {
- drm_dbg_dp(dp->dev, "Update link training failed\n");
- ret = (ret >= 0) ? -EIO : ret;
- break;
- }
- }
-
- if (eq_tries == HIBMC_EQ_MAX_RETRY)
- drm_err(dp->dev, "channel equalization failed %u times\n", eq_tries);
-
- hibmc_dp_link_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE);
-
- return ret < 0 ? ret : 0;
-}
-
-static int hibmc_dp_link_downgrade_training_cr(struct hibmc_dp_dev *dp)
-{
- if (hibmc_dp_link_reduce_rate(dp))
- return hibmc_dp_link_reduce_lane(dp);
-
- return 0;
-}
-
-static int hibmc_dp_link_downgrade_training_eq(struct hibmc_dp_dev *dp)
-{
- u8 status[DP_LINK_STATUS_SIZE] = {0};
- int ret;
-
- ret = drm_dp_dpcd_read_link_status(dp->aux, status);
- if (ret != DP_LINK_STATUS_SIZE) {
- drm_err(dp->dev, "get lane status failed\n");
- return ret >= 0 ? -EIO : ret;
- }
-
- if ((dp->link.status.clock_recovered && !dp->link.status.channel_equalized) ||
- (status[0] != 0 && !dp->link.status.clock_recovered)) { // at least one cr_done
- if (!hibmc_dp_link_reduce_lane(dp))
- return 0;
- }
-
- return hibmc_dp_link_reduce_rate(dp);
-}
-
-static void hibmc_dp_update_caps(struct hibmc_dp_dev *dp)
-{
- dp->link.cap.rx_dpcd_revision = dp->dpcd[DP_DPCD_REV];
-
- dp->link.cap.is_tps3 = (dp->dpcd[DP_DPCD_REV] >= DP_DPCD_REV_13) &&
- (dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED);
- dp->link.cap.is_tps4 = (dp->dpcd[DP_DPCD_REV] >= DP_DPCD_REV_14) &&
- (dp->dpcd[DP_MAX_DOWNSPREAD] & DP_TPS4_SUPPORTED);
- dp->link.cap.link_rate = dp->dpcd[DP_MAX_LINK_RATE];
- dp->link.cap.lanes = dp->dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;
- if (dp->link.cap.lanes > HIBMC_DP_LANE_NUM_MAX)
- dp->link.cap.lanes = HIBMC_DP_LANE_NUM_MAX;
-}
-
-int hibmc_dp_link_training(struct hibmc_dp_dev *dp)
-{
- struct hibmc_dp_link *link = &dp->link;
- int ret;
-
- ret = drm_dp_read_dpcd_caps(dp->aux, dp->dpcd);
- if (ret)
- drm_err(dp->dev, "dp aux read dpcd failed, ret: %d\n", ret);
-
- hibmc_dp_update_caps(dp);
-
- while (true) {
- ret = hibmc_dp_link_training_cr_pre(dp);
- if (ret)
- goto err;
-
- ret = hibmc_dp_link_training_cr(dp);
- if (ret)
- goto err;
-
- if (!link->status.clock_recovered) {
- ret = hibmc_dp_link_downgrade_training_cr(dp);
- if (ret)
- goto err;
- continue;
- }
-
- ret = hibmc_dp_link_training_channel_eq(dp);
- if (ret)
- goto err;
-
- if (!link->status.channel_equalized) {
- ret = hibmc_dp_link_downgrade_training_eq(dp);
- if (ret)
- goto err;
- continue;
- }
-
- return 0;
- }
-
-err:
- hibmc_dp_link_set_pattern(dp, DP_TRAINING_PATTERN_DISABLE);
-
- return ret;
-}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_reg.h b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_reg.h
deleted file mode 100644
index 156e5d63c47f..000000000000
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_reg.h
+++ /dev/null
@@ -1,140 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/* Copyright (c) 2024 Hisilicon Limited. */
-
-#ifndef DP_REG_H
-#define DP_REG_H
-
-#define HIBMC_DP_AUX_CMD_ADDR 0x50
-
-#define HIBMC_DP_AUX_WR_DATA0 0x54
-#define HIBMC_DP_AUX_WR_DATA1 0x58
-#define HIBMC_DP_AUX_WR_DATA2 0x5c
-#define HIBMC_DP_AUX_WR_DATA3 0x60
-#define HIBMC_DP_AUX_RD_DATA0 0x64
-
-#define HIBMC_DP_AUX_REQ 0x74
-#define HIBMC_DP_CFG_AUX_REQ BIT(0)
-#define HIBMC_DP_CFG_AUX_SYNC_LEN_SEL BIT(1)
-#define HIBMC_DP_CFG_AUX_TIMER_TIMEOUT BIT(2)
-#define HIBMC_DP_CFG_AUX_MIN_PULSE_NUM GENMASK(13, 9)
-
-#define HIBMC_DP_AUX_STATUS 0x78
-#define HIBMC_DP_CFG_AUX_TIMEOUT BIT(0)
-#define HIBMC_DP_CFG_AUX_STATUS GENMASK(11, 4)
-#define HIBMC_DP_CFG_AUX_READY_DATA_BYTE GENMASK(16, 12)
-#define HIBMC_DP_CFG_AUX GENMASK(24, 17)
-
-#define HIBMC_DP_PHYIF_CTRL0 0xa0
-#define HIBMC_DP_CFG_SCRAMBLE_EN BIT(0)
-#define HIBMC_DP_CFG_PAT_SEL GENMASK(7, 4)
-#define HIBMC_DP_CFG_LANE_DATA_EN GENMASK(11, 8)
-
-#define HIBMC_DP_VIDEO_CTRL 0x100
-#define HIBMC_DP_CFG_STREAM_RGB_ENABLE BIT(1)
-#define HIBMC_DP_CFG_STREAM_VIDEO_MAPPING GENMASK(5, 2)
-#define HIBMC_DP_CFG_STREAM_FRAME_MODE BIT(6)
-#define HIBMC_DP_CFG_STREAM_HSYNC_POLARITY BIT(7)
-#define HIBMC_DP_CFG_STREAM_VSYNC_POLARITY BIT(8)
-
-#define HIBMC_DP_VIDEO_CONFIG0 0x104
-#define HIBMC_DP_CFG_STREAM_HACTIVE GENMASK(31, 16)
-#define HIBMC_DP_CFG_STREAM_HBLANK GENMASK(15, 0)
-
-#define HIBMC_DP_VIDEO_CONFIG1 0x108
-#define HIBMC_DP_CFG_STREAM_VACTIVE GENMASK(31, 16)
-#define HIBMC_DP_CFG_STREAM_VBLANK GENMASK(15, 0)
-
-#define HIBMC_DP_VIDEO_CONFIG2 0x10c
-#define HIBMC_DP_CFG_STREAM_HSYNC_WIDTH GENMASK(15, 0)
-
-#define HIBMC_DP_VIDEO_CONFIG3 0x110
-#define HIBMC_DP_CFG_STREAM_VSYNC_WIDTH GENMASK(15, 0)
-#define HIBMC_DP_CFG_STREAM_VFRONT_PORCH GENMASK(31, 16)
-
-#define HIBMC_DP_VIDEO_PACKET 0x114
-#define HIBMC_DP_CFG_STREAM_TU_SYMBOL_SIZE GENMASK(5, 0)
-#define HIBMC_DP_CFG_STREAM_TU_SYMBOL_FRAC_SIZE GENMASK(9, 6)
-#define HIBMC_DP_CFG_STREAM_SYNC_CALIBRATION GENMASK(31, 20)
-
-#define HIBMC_DP_VIDEO_MSA0 0x118
-#define HIBMC_DP_CFG_STREAM_VSTART GENMASK(31, 16)
-#define HIBMC_DP_CFG_STREAM_HSTART GENMASK(15, 0)
-
-#define HIBMC_DP_VIDEO_MSA1 0x11c
-#define HIBMC_DP_VIDEO_MSA2 0x120
-
-#define HIBMC_DP_VIDEO_HORIZONTAL_SIZE 0X124
-#define HIBMC_DP_CFG_STREAM_HTOTAL_SIZE GENMASK(31, 16)
-#define HIBMC_DP_CFG_STREAM_HBLANK_SIZE GENMASK(15, 0)
-
-#define HIBMC_DP_COLOR_BAR_CTRL 0x260
-#define HIBMC_DP_COLOR_BAR_ENABLE_M BIT(0)
-#define HIBMC_DP_COLOR_BAR_CTRL_M GENMASK(8, 1)
-#define HIBMC_DP_COLOR_BAR_TIMING_SEL_M BIT(9)
-#define HIBMC_DP_COLOR_BAR_PATTERN_SEL_M BIT(10)
-#define HIBMC_DP_COLOR_BAR_DATA_R_M GENMASK(23, 12)
-#define HIBMC_DP_COLOR_BAR_CTRL1 0x264
-#define HIBMC_DP_COLOR_BAR_DATA_B_M GENMASK(11, 0)
-#define HIBMC_DP_COLOR_BAR_DATA_G_M GENMASK(23, 12)
-#define HIBMC_DP_TIMING_GEN_CONFIG0 0x26c
-#define HIBMC_DP_CFG_TIMING_GEN0_HACTIVE GENMASK(31, 16)
-#define HIBMC_DP_CFG_TIMING_GEN0_HBLANK GENMASK(15, 0)
-
-#define HIBMC_DP_TIMING_GEN_CONFIG2 0x274
-#define HIBMC_DP_CFG_TIMING_GEN0_VACTIVE GENMASK(31, 16)
-#define HIBMC_DP_CFG_TIMING_GEN0_VBLANK GENMASK(15, 0)
-
-#define HIBMC_DP_TIMING_GEN_CONFIG3 0x278
-#define HIBMC_DP_CFG_TIMING_GEN0_VFRONT_PORCH GENMASK(31, 16)
-
-#define HIBMC_DP_HDCP_CFG 0x600
-
-#define HIBMC_DP_DPTX_RST_CTRL 0x700
-#define HIBMC_DP_CFG_AUX_RST_N BIT(4)
-
-#define HIBMC_DP_DPTX_CLK_CTRL 0x704
-
-#define HIBMC_DP_DPTX_GCTL0 0x708
-#define HIBMC_DP_CFG_PHY_LANE_NUM GENMASK(2, 1)
-#define HIBMC_DP_CFG_TIMING_GEN_ENABLE BIT(10)
-#define HIBMC_DP_CFG_MST_ENABLE BIT(0)
-
-#define HIBMC_DP_INTR_ENABLE 0x720
-#define HIBMC_DP_INTR_ORIGINAL_STATUS 0x728
-
-#define HIBMC_DP_TIMING_MODEL_CTRL 0x884
-#define HIBMC_DP_CFG_PIXEL_NUM_TIMING_MODE_SEL1 GENMASK(31, 16)
-
-#define HIBMC_DP_TIMING_SYNC_CTRL 0xFF0
-
-#define HIBMC_DP_INTSTAT 0x1e0724
-#define HIBMC_DP_INTCLR 0x1e0728
-
-/* dp serdes reg */
-#define HIBMC_DP_HOST_OFFSET 0x10000
-#define HIBMC_DP_LANE0_RATE_OFFSET 0x4
-#define HIBMC_DP_LANE1_RATE_OFFSET 0xc
-#define HIBMC_DP_LANE_STATUS_OFFSET 0x10
-#define HIBMC_DP_PMA_LANE0_OFFSET 0x18
-#define HIBMC_DP_PMA_LANE1_OFFSET 0x1c
-#define HIBMC_DP_HOST_SERDES_CTRL 0x1f001c
-#define HIBMC_DP_PMA_TXDEEMPH GENMASK(18, 1)
-#define DP_SERDES_DONE 0x3
-
-/* dp serdes TX-Deempth Configuration */
-#define DP_SERDES_VOL0_PRE0 0x280
-#define DP_SERDES_VOL0_PRE1 0x2300
-#define DP_SERDES_VOL0_PRE2 0x53c0
-#define DP_SERDES_VOL0_PRE3 0x8400
-#define DP_SERDES_VOL1_PRE0 0x380
-#define DP_SERDES_VOL1_PRE1 0x3440
-#define DP_SERDES_VOL1_PRE2 0x6480
-#define DP_SERDES_VOL2_PRE0 0x4c1
-#define DP_SERDES_VOL2_PRE1 0x4500
-#define DP_SERDES_VOL3_PRE0 0x600
-#define DP_SERDES_BW_8_1 0x3
-#define DP_SERDES_BW_5_4 0x2
-#define DP_SERDES_BW_2_7 0x1
-#define DP_SERDES_BW_1_62 0x0
-
-#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_serdes.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_serdes.c
deleted file mode 100644
index 8191233aa965..000000000000
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_serdes.c
+++ /dev/null
@@ -1,59 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// Copyright (c) 2025 Hisilicon Limited.
-
-#include <linux/delay.h>
-#include <drm/drm_device.h>
-#include <drm/drm_print.h>
-#include "dp_comm.h"
-#include "dp_config.h"
-#include "dp_reg.h"
-
-int hibmc_dp_serdes_set_tx_cfg(struct hibmc_dp_dev *dp, u8 train_set[HIBMC_DP_LANE_NUM_MAX])
-{
- static const u32 serdes_tx_cfg[4][4] = { {DP_SERDES_VOL0_PRE0, DP_SERDES_VOL0_PRE1,
- DP_SERDES_VOL0_PRE2, DP_SERDES_VOL0_PRE3},
- {DP_SERDES_VOL1_PRE0, DP_SERDES_VOL1_PRE1,
- DP_SERDES_VOL1_PRE2}, {DP_SERDES_VOL2_PRE0,
- DP_SERDES_VOL2_PRE1}, {DP_SERDES_VOL3_PRE0}};
- int cfg[2];
- int i;
-
- for (i = 0; i < HIBMC_DP_LANE_NUM_MAX; i++) {
- cfg[i] = serdes_tx_cfg[FIELD_GET(DP_TRAIN_VOLTAGE_SWING_MASK, train_set[i])]
- [FIELD_GET(DP_TRAIN_PRE_EMPHASIS_MASK, train_set[i])];
- if (!cfg[i])
- return -EINVAL;
-
- /* lane1 offset is 4 */
- writel(FIELD_PREP(HIBMC_DP_PMA_TXDEEMPH, cfg[i]),
- dp->serdes_base + HIBMC_DP_PMA_LANE0_OFFSET + i * 4);
- }
-
- usleep_range(300, 500);
-
- if (readl(dp->serdes_base + HIBMC_DP_LANE_STATUS_OFFSET) != DP_SERDES_DONE) {
- drm_dbg_dp(dp->dev, "dp serdes cfg failed\n");
- return -EAGAIN;
- }
-
- return 0;
-}
-
-int hibmc_dp_serdes_rate_switch(u8 rate, struct hibmc_dp_dev *dp)
-{
- writel(rate, dp->serdes_base + HIBMC_DP_LANE0_RATE_OFFSET);
- writel(rate, dp->serdes_base + HIBMC_DP_LANE1_RATE_OFFSET);
-
- usleep_range(300, 500);
-
- if (readl(dp->serdes_base + HIBMC_DP_LANE_STATUS_OFFSET) != DP_SERDES_DONE) {
- drm_dbg_dp(dp->dev, "dp serdes rate switching failed\n");
- return -EAGAIN;
- }
-
- if (rate < DP_SERDES_BW_8_1)
- drm_dbg_dp(dp->dev, "reducing serdes rate to :%d\n",
- rate ? rate * HIBMC_DP_LINK_RATE_CAL * 10 : 162);
-
- return 0;
-}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_debugfs.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_debugfs.c
deleted file mode 100644
index 6c6ff3255d15..000000000000
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_debugfs.c
+++ /dev/null
@@ -1,149 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// Copyright (c) 2024 Hisilicon Limited.
-
-#include <linux/debugfs.h>
-#include <linux/device.h>
-#include <linux/seq_file.h>
-#include <linux/pci.h>
-
-#include <drm/drm_drv.h>
-#include <drm/drm_file.h>
-#include <drm/drm_debugfs.h>
-#include <drm/drm_edid.h>
-
-#include "hibmc_drm_drv.h"
-
-#define MAX_BUF_SIZE 12
-
-static int hibmc_dp_show(struct seq_file *m, void *arg)
-{
- struct drm_info_node *node = m->private;
- struct drm_device *dev = node->minor->dev;
- struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
- int idx, rate;
-
- if (!drm_dev_enter(dev, &idx))
- return -ENODEV;
-
- switch (hibmc_dp_get_link_rate(&priv->dp)) {
- case 0x1e:
- rate = 810; // 8.1Gbps
- break;
- case 0x14:
- rate = 540; // 5.4Gbps
- break;
- case 0xA:
- rate = 270; // 2.7Gbps
- break;
- case 0x6:
- rate = 162; // 1.62Gbps
- break;
- default:
- rate = 0;
- }
-
- seq_printf(m, "enable lanes: %u\n", hibmc_dp_get_lanes(&priv->dp));
- seq_printf(m, "link rate: %d\n", rate);
- seq_printf(m, "vfresh: %d\n", drm_mode_vrefresh(&priv->crtc.mode));
- seq_printf(m, "dpcd version: 0x%x\n", hibmc_dp_get_dpcd(&priv->dp));
- seq_printf(m, "hpd status: %d\n", priv->dp.hpd_status);
-
- drm_dev_exit(idx);
-
- return 0;
-}
-
-static ssize_t hibmc_control_write(struct file *file, const char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct hibmc_drm_private *priv = file_inode(file)->i_private;
- struct hibmc_dp_cbar_cfg *cfg = &priv->dp.cfg;
- int ret, idx;
- u8 buf[MAX_BUF_SIZE];
-
- if (count >= MAX_BUF_SIZE)
- return -EINVAL;
-
- if (copy_from_user(buf, user_buf, count))
- return -EFAULT;
-
- buf[count] = '\0';
-
- /* Only 4 parameters is allowed, the ranger are as follow:
- * [0] enable/disable colorbar feature
- 0: enable colorbar, 1: disable colorbar
- * [1] the timing source of colorbar displaying
- 0: timing follows XDP, 1: internal self timing
- * [2] the movment of colorbar displaying
- 0: static colorbar image,
- * 1~255: right shifting a type of color per (1~255)frames
- * [3] the color type of colorbar displaying
- 0~9: color bar, white, red, orange,
- * yellow, green, cyan, bule, pupper, black
- */
- if (sscanf(buf, "%hhu %hhu %hhu %u", &cfg->enable, &cfg->self_timing,
- &cfg->dynamic_rate, &cfg->pattern) != 4) {
- return -EINVAL;
- }
-
- if (cfg->pattern > 9 || cfg->enable > 1 || cfg->self_timing > 1)
- return -EINVAL;
-
- ret = drm_dev_enter(priv->dev, &idx);
- if (!ret)
- return -ENODEV;
-
- hibmc_dp_set_cbar(&priv->dp, cfg);
-
- drm_dev_exit(idx);
-
- return count;
-}
-
-static int hibmc_dp_dbgfs_show(struct seq_file *m, void *arg)
-{
- struct hibmc_drm_private *priv = m->private;
- struct hibmc_dp_cbar_cfg *cfg = &priv->dp.cfg;
- int idx;
-
- if (!drm_dev_enter(priv->dev, &idx))
- return -ENODEV;
-
- seq_printf(m, "hibmc dp colorbar cfg: %u %u %u %u\n", cfg->enable, cfg->self_timing,
- cfg->dynamic_rate, cfg->pattern);
-
- drm_dev_exit(idx);
-
- return 0;
-}
-
-static int hibmc_open(struct inode *inode, struct file *filp)
-{
- return single_open(filp, hibmc_dp_dbgfs_show, inode->i_private);
-}
-
-static const struct file_operations hibmc_dbg_fops = {
- .owner = THIS_MODULE,
- .write = hibmc_control_write,
- .read = seq_read,
- .open = hibmc_open,
- .llseek = seq_lseek,
- .release = single_release,
-};
-
-static struct drm_info_list hibmc_debugfs_list[] = {
- { "hibmc-dp", hibmc_dp_show },
-};
-
-void hibmc_debugfs_init(struct drm_connector *connector, struct dentry *root)
-{
- struct drm_device *dev = connector->dev;
- struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
- struct drm_minor *minor = dev->primary;
-
- /* create the file in drm directory, so we don't need to remove manually */
- debugfs_create_file("colorbar-cfg", 0200, root, priv, &hibmc_dbg_fops);
-
- drm_debugfs_create_files(hibmc_debugfs_list, ARRAY_SIZE(hibmc_debugfs_list),
- minor->debugfs_root, minor);
-}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c
deleted file mode 100644
index ae6f5c235e02..000000000000
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c
+++ /dev/null
@@ -1,257 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-// Copyright (c) 2024 Hisilicon Limited.
-
-#include <linux/io.h>
-
-#include <drm/drm_probe_helper.h>
-#include <drm/drm_simple_kms_helper.h>
-#include <drm/drm_atomic_helper.h>
-#include <drm/drm_modes.h>
-#include <drm/drm_drv.h>
-#include <drm/drm_edid.h>
-
-#include "hibmc_drm_drv.h"
-#include "hibmc_drm_regs.h"
-#include "dp/dp_hw.h"
-
-#define HIBMC_DP_MASKED_SINK_HPD_PLUG_INT BIT(2)
-#define HIBMC_DP_MASKED_SINK_HPD_UNPLUG_INT BIT(3)
-
-static int hibmc_dp_connector_get_modes(struct drm_connector *connector)
-{
- int count;
- struct hibmc_dp *dp = to_hibmc_dp(connector);
- struct edid *edid;
-
-
- edid = drm_get_edid(connector, &dp->aux.ddc);
- if (edid) {
- drm_connector_update_edid_property(connector, edid);
- count = drm_add_edid_modes(connector, edid);
- if (count) {
- dp->is_connected = true;
- goto out;
- }
- }
-
-
- dp->is_connected = false;
-
- count = drm_add_modes_noedid(connector, connector->dev->mode_config.max_width,
- connector->dev->mode_config.max_height);
- drm_set_preferred_mode(connector, 1024, 768); // temporary implementation
-
-out:
- kfree(edid);
-
- return count;
-}
-
-static int hibmc_dp_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode,
- struct drm_modeset_acquire_ctx *ctx,
- enum drm_mode_status *status)
-{
- struct hibmc_dp *dp = to_hibmc_dp(connector);
- u64 cur_val, max_val;
-
- if (!dp->is_connected) {
- *status = MODE_OK;
- return 0;
- }
-
- cur_val = (u64)mode->htotal * mode->vtotal * drm_mode_vrefresh(mode) * BPP_24;
- max_val = (u64)hibmc_dp_get_link_rate(dp) * DP_MODE_VALI_CAL * hibmc_dp_get_lanes(dp);
- if (cur_val > max_val)
- *status = MODE_CLOCK_HIGH;
- else
- *status = MODE_OK;
-
- return 0;
-}
-
-static int hibmc_dp_detect(struct drm_connector *connector,
- struct drm_modeset_acquire_ctx *ctx, bool force)
-{
- struct hibmc_dp *dp = to_hibmc_dp(connector);
-
- if (dp->hpd_status)
- return connector_status_connected;
- else
- return connector_status_disconnected;
-}
-
-static const struct drm_connector_helper_funcs hibmc_dp_conn_helper_funcs = {
- .get_modes = hibmc_dp_connector_get_modes,
- .mode_valid_ctx = hibmc_dp_mode_valid,
- .detect_ctx = hibmc_dp_detect,
-};
-
-static int hibmc_dp_late_register(struct drm_connector *connector)
-{
- struct hibmc_dp *dp = to_hibmc_dp(connector);
-
- hibmc_dp_enable_int(dp);
-
- return drm_dp_aux_register(&dp->aux);
-}
-
-static void hibmc_dp_early_unregister(struct drm_connector *connector)
-{
- struct hibmc_dp *dp = to_hibmc_dp(connector);
-
- drm_dp_aux_unregister(&dp->aux);
-
- hibmc_dp_disable_int(dp);
-}
-
-static const struct drm_connector_funcs hibmc_dp_conn_funcs = {
- .reset = drm_atomic_helper_connector_reset,
- .fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = drm_connector_cleanup,
- .atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
- .atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
- .late_register = hibmc_dp_late_register,
- .early_unregister = hibmc_dp_early_unregister,
-};
-
-static inline int hibmc_dp_prepare(struct hibmc_dp *dp, struct drm_display_mode *mode)
-{
- int ret;
-
- hibmc_dp_display_en(dp, false);
-
- ret = hibmc_dp_mode_set(dp, mode);
- if (ret)
- drm_err(dp->drm_dev, "hibmc dp mode set failed: %d\n", ret);
-
- return ret;
-}
-
-static void hibmc_dp_encoder_enable(struct drm_encoder *drm_encoder,
- struct drm_atomic_state *state)
-{
- struct hibmc_dp *dp = container_of(drm_encoder, struct hibmc_dp, encoder);
- struct drm_display_mode *mode = &drm_encoder->crtc->state->mode;
-
- if (hibmc_dp_prepare(dp, mode))
- return;
-
- hibmc_dp_display_en(dp, true);
-}
-
-static void hibmc_dp_encoder_disable(struct drm_encoder *drm_encoder,
- struct drm_atomic_state *state)
-{
- struct hibmc_dp *dp = container_of(drm_encoder, struct hibmc_dp, encoder);
-
- hibmc_dp_display_en(dp, false);
-}
-
-static void hibmc_dp_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state)
-{
- u32 reg;
- struct drm_device *dev = encoder->dev;
- struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
-
- reg = readl(priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
- reg |= HIBMC_DISPLAY_CONTROL_FPVDDEN(1);
- reg |= HIBMC_DISPLAY_CONTROL_PANELDATE(1);
- reg |= HIBMC_DISPLAY_CONTROL_FPEN(1);
- reg |= HIBMC_DISPLAY_CONTROL_VBIASEN(1);
- writel(reg, priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
-}
-
-static const struct drm_encoder_helper_funcs hibmc_dp_encoder_helper_funcs = {
- .atomic_enable = hibmc_dp_encoder_enable,
- .atomic_disable = hibmc_dp_encoder_disable,
- .atomic_mode_set = hibmc_dp_encoder_mode_set,
-};
-
-static const struct drm_encoder_funcs hibmc_encoder_funcs = {
- .destroy = drm_encoder_cleanup,
-};
-
-irqreturn_t hibmc_dp_hpd_isr(int irq, void *arg)
-{
- struct drm_device *dev = (struct drm_device *)arg;
- struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
- struct hibmc_dp *dp = &priv->dp;
- int idx;
-
- if (!drm_dev_enter(dev, &idx))
- return -ENODEV;
-
- if (dp->hpd_status) { /* only check unplug int when the last status is HPD in */
- if ((dp->irq_status & HIBMC_DP_MASKED_SINK_HPD_UNPLUG_INT)) {
- drm_dbg_dp(dev, "HPD OUT isr occur!\n");
- hibmc_dp_reset_link(dp);
- dp->hpd_status = 0;
- if (dev->registered)
- drm_helper_hpd_irq_event(dev);
- } else {
- drm_dbg_dp(dev, "HPD OUT occur but err!\n");
- }
- } else {
- if (dp->irq_status & HIBMC_DP_MASKED_SINK_HPD_PLUG_INT) {
- drm_dbg_dp(priv->dev, "HPD IN isr occur!\n");
- hibmc_dp_hpd_cfg(dp);
- dp->hpd_status = 1;
- if (dev->registered)
- drm_helper_hpd_irq_event(dev);
- } else {
- drm_dbg_dp(dev, "HPD IN occur but err!\n");
- }
- }
-
- drm_dev_exit(idx);
-
- return IRQ_HANDLED;
-}
-
-int hibmc_dp_init(struct hibmc_drm_private *priv)
-{
- struct drm_device *dev = priv->dev;
- struct drm_crtc *crtc = &priv->crtc;
- struct hibmc_dp *dp = &priv->dp;
- struct drm_connector *connector = &dp->connector;
- struct drm_encoder *encoder = &dp->encoder;
- int ret;
-
- dp->mmio = priv->mmio;
- dp->drm_dev = dev;
-
- ret = hibmc_dp_hw_init(&priv->dp);
- if (ret) {
- drm_err(dev, "hibmc dp hw init failed: %d\n", ret);
- return ret;
- }
-
- hibmc_dp_display_en(&priv->dp, false);
-
- encoder->possible_crtcs = drm_crtc_mask(crtc);
- ret = drm_encoder_init(dev, encoder, &hibmc_encoder_funcs, DRM_MODE_ENCODER_TMDS, NULL);
- if (ret) {
- drm_err(dev, "init dp encoder failed: %d\n", ret);
- return ret;
- }
-
- drm_encoder_helper_add(encoder, &hibmc_dp_encoder_helper_funcs);
-
- ret = drm_connector_init_with_ddc(dev, connector, &hibmc_dp_conn_funcs,
- DRM_MODE_CONNECTOR_DisplayPort, &dp->aux.ddc);
- if (ret) {
- drm_err(dev, "init dp connector failed: %d\n", ret);
- return ret;
- }
-
- drm_connector_helper_add(connector, &hibmc_dp_conn_helper_funcs);
-
- drm_connector_attach_encoder(connector, encoder);
-
- connector->polled = DRM_CONNECTOR_POLL_HPD;
-
- return 0;
-}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index b9398a78c26c..2723b4ae9856 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -20,17 +20,12 @@
#include <drm/drm_irq.h>
#include <drm/drm_managed.h>
#include <drm/drm_vblank.h>
-#include <drm/drm_probe_helper.h>
#include "hibmc_drm_drv.h"
#include "hibmc_drm_regs.h"
-#include "dp/dp_reg.h"
-
DEFINE_DRM_GEM_FOPS(hibmc_fops);
-static const char *g_irqs_names_map[HIBMC_MAX_VECTORS] = { "hibmc-vblank", "hibmc-hpd" };
-
static irqreturn_t hibmc_drm_interrupt(int irq, void *arg)
{
struct drm_device *dev = (struct drm_device *)arg;
@@ -49,22 +44,6 @@ static irqreturn_t hibmc_drm_interrupt(int irq, void *arg)
return IRQ_HANDLED;
}
-static irqreturn_t hibmc_dp_interrupt(int irq, void *arg)
-{
- struct drm_device *dev = (struct drm_device *)arg;
- struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
- u32 status;
-
- status = readl(priv->mmio + HIBMC_DP_INTSTAT);
- if (status) {
- priv->dp.irq_status = status;
- writel(status, priv->mmio + HIBMC_DP_INTCLR);
- return IRQ_WAKE_THREAD;
- }
-
- return IRQ_HANDLED;
-}
-
static struct drm_driver hibmc_driver = {
.driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
.fops = &hibmc_fops,
@@ -120,35 +99,16 @@ static int hibmc_kms_init(struct hibmc_drm_private *priv)
ret = hibmc_de_init(priv);
if (ret) {
drm_err(priv->dev, "failed to init de: %d\n", ret);
- goto err;
- }
-
- /*
- * If the serdes reg is readable and is not equal to 0,
- * DP block exists and initializes it.
- */
- ret = readl(priv->mmio + HIBMC_DP_HOST_SERDES_CTRL);
- if (ret) {
- ret = hibmc_dp_init(priv);
- if (ret) {
- drm_err(priv->dev, "failed to init dp: %d\n", ret);
- goto err;
- }
+ return ret;
}
ret = hibmc_vdac_init(priv);
if (ret) {
drm_err(priv->dev, "failed to init vdac: %d\n", ret);
- goto err;
+ return ret;
}
- drm_kms_helper_poll_init(priv->dev);
return 0;
-
-err:
- drm_atomic_helper_shutdown(priv->dev);
-
- return ret;
}
static void hibmc_kms_fini(struct hibmc_drm_private *priv)
@@ -297,47 +257,20 @@ static int hibmc_hw_init(struct hibmc_drm_private *priv)
return 0;
}
-static void hibmc_unload(struct drm_device *dev)
-{
- drm_atomic_helper_shutdown(dev);
- drm_kms_helper_poll_fini(dev);
-}
-
-static int hibmc_msi_init(struct drm_device *dev)
+static int hibmc_unload(struct drm_device *dev)
{
- struct pci_dev *pdev = to_pci_dev(dev->dev);
- int valid_irq_num;
- int irq;
- int ret;
- int i;
+ struct hibmc_drm_private *priv = dev->dev_private;
- ret = pci_alloc_irq_vectors(pdev, HIBMC_MIN_VECTORS,
- HIBMC_MAX_VECTORS, PCI_IRQ_MSI);
- if (ret < 0) {
- drm_err(dev, "enabling MSI failed: %d\n", ret);
- return ret;
- }
+ drm_atomic_helper_shutdown(dev);
- valid_irq_num = ret;
-
- for (i = 0; i < valid_irq_num; i++) {
- irq = pci_irq_vector(pdev, i);
-
- if (i)
- /* PCI devices require shared interrupts. */
- ret = devm_request_threaded_irq(&pdev->dev, irq,
- hibmc_dp_interrupt,
- hibmc_dp_hpd_isr,
- IRQF_SHARED, g_irqs_names_map[i], dev);
- else
- ret = devm_request_irq(&pdev->dev, irq, hibmc_drm_interrupt,
- IRQF_SHARED, g_irqs_names_map[i], dev);
- if (ret) {
- drm_err(dev, "install irq failed: %d\n", ret);
- return ret;
- }
- }
+ if (dev->irq_enabled)
+ drm_irq_uninstall(dev);
+ pci_disable_msi(dev->pdev);
+ hibmc_kms_fini(priv);
+ hibmc_mm_fini(priv);
+ hibmc_hw_unmap(priv);
+ dev->dev_private = NULL;
return 0;
}
@@ -355,19 +288,21 @@ static int hibmc_load(struct drm_device *dev)
priv->dev = dev;
ret = hibmc_hw_init(priv);
- if (ret)
- return ret;
+ if (ret) {
+ drm_err(dev, "failed to initialize hardware: %d\n", ret);
+ goto err_alloc;
+ }
ret = hibmc_mm_init(priv);
if (ret) {
- drm_err(dev, "Error initializing VRAM MM; %d\n", ret);
- return ret;
+ drm_err(dev, "failed to initialize mm: %d\n", ret);
+ goto err_hw;
}
ret = hibmc_kms_init(priv);
if (ret) {
- drm_err(dev, "hibmc kms init failed, ret:%d\n", ret);
- return ret;
+ drm_err(dev, "failed to initialize kms: %d\n", ret);
+ goto err_mm;
}
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
@@ -376,10 +311,13 @@ static int hibmc_load(struct drm_device *dev)
goto err_kms;
}
- ret = hibmc_msi_init(dev);
+ ret = pci_enable_msi(dev->pdev);
if (ret) {
- drm_err(dev, "hibmc msi init failed, ret:%d\n", ret);
- goto err_kms;
+ drm_warn(dev, "enabling MSI failed: %d\n", ret);
+ } else {
+ ret = drm_irq_install(dev, dev->pdev->irq);
+ if (ret)
+ drm_warn(dev, "install irq failed: %d\n", ret);
}
/* reset all the states of crtc/plane/encoder/connector */
@@ -389,8 +327,11 @@ static int hibmc_load(struct drm_device *dev)
err_kms:
hibmc_kms_fini(priv);
+err_mm:
hibmc_mm_fini(priv);
+err_hw:
hibmc_hw_unmap(priv);
+err_alloc:
dev->dev_private = NULL;
return ret;
@@ -400,7 +341,6 @@ static int hibmc_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct drm_device *dev;
- struct hibmc_drm_private *priv;
int ret;
ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev,
@@ -423,8 +363,6 @@ static int hibmc_pci_probe(struct pci_dev *pdev,
goto err_free;
}
- pci_set_master(pdev);
-
ret = hibmc_load(dev);
if (ret) {
drm_err(dev, "failed to load hibmc: %d\n", ret);
@@ -440,9 +378,6 @@ static int hibmc_pci_probe(struct pci_dev *pdev,
drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth);
- priv = to_hibmc_drm_private(dev);
- hibmc_debugfs_init(&priv->dp.connector, dev->primary->debugfs_root);
-
return 0;
err_unload:
@@ -480,8 +415,8 @@ static struct pci_driver hibmc_pci_driver = {
.id_table = hibmc_pci_table,
.probe = hibmc_pci_probe,
.remove = hibmc_pci_remove,
- .shutdown = hibmc_pci_shutdown,
- .driver.pm = &hibmc_pm_ops,
+ .shutdown = hibmc_pci_shutdown,
+ .driver.pm = &hibmc_pm_ops,
};
module_pci_driver(hibmc_pci_driver);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index 617585268009..87d2aad0bb5e 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -21,16 +21,12 @@
#include <drm/drm_edid.h>
#include <drm/drm_fb_helper.h>
#include <drm/drm_framebuffer.h>
-#include "dp/dp_hw.h"
struct drm_device;
-#define HIBMC_MIN_VECTORS 1
-#define HIBMC_MAX_VECTORS 2
-struct hibmc_vdac {
- struct drm_device *dev;
- struct drm_encoder encoder;
- struct drm_connector connector;
+struct hibmc_connector {
+ struct drm_connector base;
+
struct i2c_adapter adapter;
struct i2c_algo_bit_data bit_data;
};
@@ -46,19 +42,14 @@ struct hibmc_drm_private {
struct drm_device *dev;
struct drm_plane primary_plane;
struct drm_crtc crtc;
+ struct drm_encoder encoder;
+ struct hibmc_connector connector;
bool mode_config_initialized;
- struct hibmc_vdac vdac;
- struct hibmc_dp dp;
};
-static inline struct hibmc_vdac *to_hibmc_vdac(struct drm_connector *connector)
-{
- return container_of(connector, struct hibmc_vdac, connector);
-}
-
-static inline struct hibmc_dp *to_hibmc_dp(struct drm_connector *connector)
+static inline struct hibmc_connector *to_hibmc_connector(struct drm_connector *connector)
{
- return container_of(connector, struct hibmc_dp, connector);
+ return container_of(connector, struct hibmc_connector, base);
}
static inline struct hibmc_drm_private *to_hibmc_drm_private(struct drm_device *dev)
@@ -78,14 +69,8 @@ int hibmc_mm_init(struct hibmc_drm_private *hibmc);
void hibmc_mm_fini(struct hibmc_drm_private *hibmc);
int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
struct drm_mode_create_dumb *args);
-int hibmc_ddc_create(struct drm_device *drm_dev, struct hibmc_vdac *connector);
-void hibmc_ddc_del(struct hibmc_vdac *vdac);
-int hibmc_dp_init(struct hibmc_drm_private *priv);
+int hibmc_ddc_create(struct drm_device *drm_dev, struct hibmc_connector *connector);
extern const struct drm_mode_config_funcs hibmc_mode_funcs;
-void hibmc_debugfs_init(struct drm_connector *connector, struct dentry *root);
-
-irqreturn_t hibmc_dp_hpd_isr(int irq, void *arg);
-
#endif
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c
index 2e0fcd2b3bc1..86d712090d87 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c
@@ -25,8 +25,8 @@
static void hibmc_set_i2c_signal(void *data, u32 mask, int value)
{
- struct hibmc_vdac *vdac = data;
- struct hibmc_drm_private *priv = to_hibmc_drm_private(vdac->connector.dev);
+ struct hibmc_connector *hibmc_connector = data;
+ struct hibmc_drm_private *priv = to_hibmc_drm_private(hibmc_connector->base.dev);
u32 tmp_dir = readl(priv->mmio + GPIO_DATA_DIRECTION);
if (value) {
@@ -45,8 +45,8 @@ static void hibmc_set_i2c_signal(void *data, u32 mask, int value)
static int hibmc_get_i2c_signal(void *data, u32 mask)
{
- struct hibmc_vdac *vdac = data;
- struct hibmc_drm_private *priv = to_hibmc_drm_private(vdac->connector.dev);
+ struct hibmc_connector *hibmc_connector = data;
+ struct hibmc_drm_private *priv = to_hibmc_drm_private(hibmc_connector->base.dev);
u32 tmp_dir = readl(priv->mmio + GPIO_DATA_DIRECTION);
if ((tmp_dir & mask) != mask) {
@@ -77,27 +77,23 @@ static int hibmc_ddc_getscl(void *data)
return hibmc_get_i2c_signal(data, I2C_SCL_MASK);
}
-int hibmc_ddc_create(struct drm_device *drm_dev, struct hibmc_vdac *vdac)
+int hibmc_ddc_create(struct drm_device *drm_dev,
+ struct hibmc_connector *connector)
{
- vdac->adapter.owner = THIS_MODULE;
- vdac->adapter.class = I2C_CLASS_DDC;
- snprintf(vdac->adapter.name, I2C_NAME_SIZE, "HIS i2c bit bus");
- vdac->adapter.dev.parent = drm_dev->dev;
- i2c_set_adapdata(&vdac->adapter, vdac);
- vdac->adapter.algo_data = &vdac->bit_data;
-
- vdac->bit_data.udelay = 20;
- vdac->bit_data.timeout = usecs_to_jiffies(2000);
- vdac->bit_data.data = vdac;
- vdac->bit_data.setsda = hibmc_ddc_setsda;
- vdac->bit_data.setscl = hibmc_ddc_setscl;
- vdac->bit_data.getsda = hibmc_ddc_getsda;
- vdac->bit_data.getscl = hibmc_ddc_getscl;
-
- return i2c_bit_add_bus(&vdac->adapter);
-}
-
-void hibmc_ddc_del(struct hibmc_vdac *vdac)
-{
- i2c_del_adapter(&vdac->adapter);
+ connector->adapter.owner = THIS_MODULE;
+ connector->adapter.class = I2C_CLASS_DDC;
+ snprintf(connector->adapter.name, I2C_NAME_SIZE, "HIS i2c bit bus");
+ connector->adapter.dev.parent = &drm_dev->pdev->dev;
+ i2c_set_adapdata(&connector->adapter, connector);
+ connector->adapter.algo_data = &connector->bit_data;
+
+ connector->bit_data.udelay = 20;
+ connector->bit_data.timeout = usecs_to_jiffies(2000);
+ connector->bit_data.data = connector;
+ connector->bit_data.setsda = hibmc_ddc_setsda;
+ connector->bit_data.setscl = hibmc_ddc_setscl;
+ connector->bit_data.getsda = hibmc_ddc_getsda;
+ connector->bit_data.getscl = hibmc_ddc_getscl;
+
+ return i2c_bit_add_bus(&connector->adapter);
}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
index 9c0ec6e54df0..fb761853289c 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -42,9 +42,9 @@ static int hibmc_connector_get_modes(struct drm_connector *connector)
{
int count;
void *edid;
- struct hibmc_vdac *vdac = to_hibmc_vdac(connector);
+ struct hibmc_connector *hibmc_connector = to_hibmc_connector(connector);
- edid = drm_get_edid(connector, &vdac->adapter);
+ edid = drm_get_edid(connector, &hibmc_connector->adapter);
if (edid) {
drm_connector_update_edid_property(connector, edid);
count = drm_add_edid_modes(connector, edid);
@@ -88,53 +88,26 @@ static enum drm_mode_status hibmc_connector_mode_valid(
return hibmc_valid_mode(mode->hdisplay, mode->vdisplay);
}
-static void hibmc_vdac_connector_destroy(struct drm_connector *connector)
+static void hibmc_connector_destroy(struct drm_connector *connector)
{
- struct hibmc_vdac *vdac = to_hibmc_vdac(connector);
+ struct hibmc_connector *hibmc_connector = to_hibmc_connector(connector);
- i2c_del_adapter(&vdac->adapter);
+ i2c_del_adapter(&hibmc_connector->adapter);
drm_connector_cleanup(connector);
}
-static int hibmc_vdac_detect(struct drm_connector *connector, struct drm_modeset_acquire_ctx *ctx,
- bool force)
-{
- struct hibmc_drm_private *priv = to_hibmc_drm_private(connector->dev);
- struct hibmc_dp *dp = &priv->dp;
-
- if (dp->hpd_status)
- return connector_status_disconnected;
-
- return connector_status_connected;
-}
-
static const struct drm_connector_helper_funcs
hibmc_connector_helper_funcs = {
.get_modes = hibmc_connector_get_modes,
.mode_valid = hibmc_connector_mode_valid,
- .detect_ctx = hibmc_vdac_detect,
};
-static void hibmc_vdac_force(struct drm_connector *connector)
-{
- struct hibmc_drm_private *priv = to_hibmc_drm_private(connector->dev);
- struct hibmc_dp *dp = &priv->dp;
-
- if (dp->hpd_status) {
- connector->status = connector_status_disconnected;
- return;
- }
-
- connector->status = connector_status_connected;
-}
-
static const struct drm_connector_funcs hibmc_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = hibmc_vdac_connector_destroy,
+ .destroy = hibmc_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
- .force = hibmc_vdac_force,
};
static void hibmc_encoder_mode_set(struct drm_encoder *encoder,
@@ -164,12 +137,12 @@ static const struct drm_encoder_funcs hibmc_encoder_funcs = {
int hibmc_vdac_init(struct hibmc_drm_private *priv)
{
struct drm_device *dev = priv->dev;
- struct hibmc_vdac *vdac = &priv->vdac;
- struct drm_encoder *encoder = &vdac->encoder;
- struct drm_connector *connector = &vdac->connector;
+ struct hibmc_connector *hibmc_connector = &priv->connector;
+ struct drm_encoder *encoder = &priv->encoder;
+ struct drm_connector *connector = &hibmc_connector->base;
int ret;
- ret = hibmc_ddc_create(dev, vdac);
+ ret = hibmc_ddc_create(dev, hibmc_connector);
if (ret) {
drm_err(dev, "failed to create ddc: %d\n", ret);
return ret;
@@ -180,7 +153,7 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv)
DRM_MODE_ENCODER_DAC, NULL);
if (ret) {
drm_err(dev, "failed to init encoder: %d\n", ret);
- goto err;
+ return ret;
}
drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs);
@@ -188,21 +161,14 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv)
ret = drm_connector_init_with_ddc(dev, connector,
&hibmc_connector_funcs,
DRM_MODE_CONNECTOR_VGA,
- &vdac->adapter);
+ &hibmc_connector->adapter);
if (ret) {
drm_err(dev, "failed to init connector: %d\n", ret);
- goto err;
+ return ret;
}
drm_connector_helper_add(connector, &hibmc_connector_helper_funcs);
drm_connector_attach_encoder(connector, encoder);
- connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
-
return 0;
-
-err:
- hibmc_ddc_del(vdac);
-
- return ret;
}
diff --git a/include/drm/drm_probe_helper.h b/include/drm/drm_probe_helper.h
index 621885d5de84..8d3ed2834d34 100644
--- a/include/drm/drm_probe_helper.h
+++ b/include/drm/drm_probe_helper.h
@@ -24,7 +24,4 @@ void drm_kms_helper_poll_disable(struct drm_device *dev);
void drm_kms_helper_poll_enable(struct drm_device *dev);
bool drm_kms_helper_is_poll_worker(void);
-int drm_connector_helper_detect_from_ddc(struct drm_connector *connector,
- struct drm_modeset_acquire_ctx *ctx,
- bool force);
#endif
--
2.34.1
2
1
From: Gregory Price <gourry(a)gourry.net>
stable inclusion
from stable-v6.12.57
commit e980de2ff109dacb6d9d3a77f01b27c467115ecb
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/11500
CVE: CVE-2025-68313
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
commit 607b9fb2ce248cc5b633c5949e0153838992c152 upstream.
There's an issue with RDSEED's 16-bit and 32-bit register output
variants on Zen5 which return a random value of 0 "at a rate inconsistent
with randomness while incorrectly signaling success (CF=1)". Search the
web for AMD-SB-7055 for more detail.
Add a fix glue which checks microcode revisions.
[ bp: Add microcode revisions checking, rewrite. ]
Cc: stable(a)vger.kernel.org
Signed-off-by: Gregory Price <gourry(a)gourry.net>
Signed-off-by: Borislav Petkov (AMD) <bp(a)alien8.de>
Link: https://lore.kernel.org/r/20251018024010.4112396-1-gourry@gourry.net
[ bp: 6.12 backport: use the alternative microcode version checking. ]
Signed-off-by: Borislav Petkov (AMD) <bp(a)alien8.de>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Conflicts:
arch/x86/include/asm/cpu.h
arch/x86/kernel/cpu/microcode/amd.c
[move the definition of zen_patch_rev]
Signed-off-by: Bowen You <youbowen2(a)huawei.com>
---
arch/x86/include/asm/cpu.h | 12 ++++++++++
arch/x86/kernel/cpu/amd.c | 35 +++++++++++++++++++++++++++++
arch/x86/kernel/cpu/microcode/amd.c | 12 ----------
3 files changed, 47 insertions(+), 12 deletions(-)
diff --git a/arch/x86/include/asm/cpu.h b/arch/x86/include/asm/cpu.h
index 43a228e11209..d252aa7f04fb 100644
--- a/arch/x86/include/asm/cpu.h
+++ b/arch/x86/include/asm/cpu.h
@@ -84,4 +84,16 @@ int intel_microcode_sanity_check(void *mc, bool print_err, int hdr_type);
extern struct cpumask cpus_stop_mask;
+union zen_patch_rev {
+ struct {
+ __u32 rev : 8,
+ stepping : 4,
+ model : 4,
+ __reserved : 4,
+ ext_model : 4,
+ ext_fam : 8;
+ };
+ __u32 ucode_rev;
+};
+
#endif /* _ASM_X86_CPU_H */
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index f89dbe6f48e6..5a46bf0cce5d 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -1135,8 +1135,43 @@ static void init_amd_zen4(struct cpuinfo_x86 *c)
}
}
+static bool check_rdseed_microcode(void)
+{
+ struct cpuinfo_x86 *c = &boot_cpu_data;
+ union zen_patch_rev p;
+ u32 min_rev = 0;
+
+ p.ext_fam = c->x86 - 0xf;
+ p.model = c->x86_model;
+ p.ext_model = c->x86_model >> 4;
+ p.stepping = c->x86_stepping;
+ /* reserved bits are expected to be 0 in test below */
+ p.__reserved = 0;
+
+ if (cpu_has(c, X86_FEATURE_ZEN5)) {
+ switch (p.ucode_rev >> 8) {
+ case 0xb0021: min_rev = 0xb00215a; break;
+ case 0xb1010: min_rev = 0xb101054; break;
+ default:
+ pr_debug("%s: ucode_rev: 0x%x, current revision: 0x%x\n",
+ __func__, p.ucode_rev, c->microcode);
+ return false;
+ }
+ }
+
+ if (!min_rev)
+ return false;
+
+ return c->microcode >= min_rev;
+}
+
static void init_amd_zen5(struct cpuinfo_x86 *c)
{
+ if (!check_rdseed_microcode()) {
+ clear_cpu_cap(c, X86_FEATURE_RDSEED);
+ msr_clear_bit(MSR_AMD64_CPUID_FN_7, 18);
+ pr_emerg_once("RDSEED32 is broken. Disabling the corresponding CPUID bit.\n");
+ }
}
static void init_amd(struct cpuinfo_x86 *c)
diff --git a/arch/x86/kernel/cpu/microcode/amd.c b/arch/x86/kernel/cpu/microcode/amd.c
index b6990dc26274..75746a991f8e 100644
--- a/arch/x86/kernel/cpu/microcode/amd.c
+++ b/arch/x86/kernel/cpu/microcode/amd.c
@@ -96,18 +96,6 @@ static struct equiv_cpu_table {
struct equiv_cpu_entry *entry;
} equiv_table;
-union zen_patch_rev {
- struct {
- __u32 rev : 8,
- stepping : 4,
- model : 4,
- __reserved : 4,
- ext_model : 4,
- ext_fam : 8;
- };
- __u32 ucode_rev;
-};
-
union cpuid_1_eax {
struct {
__u32 stepping : 4,
--
2.34.1
2
1
06 Feb '26
hulk inclusion
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/13655
------------------------------------------
This reverts commit 70dcc68078ac0303c412b9dedfddcc0a850e29f1.
Commit 70dcc68078ac introduced a null-pointer dereference exception,
causing kernel boot failure:
Unable to handle kernel NULL pointer dereference at virtual address 0000000000000048
Call trace:
hibmc_debugfs_init+0x38/0x68 [hibmc_drm]
hibmc_pci_probe+0xdc/0x1ac [hibmc_drm]
local_pci_probe+0x48/0xb0
work_for_cpu_fn+0x24/0x50
process_one_work+0x1d8/0x4c0
worker_thread+0x25c/0x470
kthread+0x108/0x150
Temporarily revert this patch to circumvent the issue.
Fixes: 70dcc68078ac ("drm/hisilicon/hibmc: hibmc-drm bugfix for DP")
Signed-off-by: Tengda Wu <wutengda2(a)huawei.com>
---
drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h | 5 +-
drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c | 83 ++++++-------------
drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h | 9 --
drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c | 67 ++++-----------
drivers/gpu/drm/hisilicon/hibmc/dp/dp_reg.h | 10 +--
.../gpu/drm/hisilicon/hibmc/dp/dp_serdes.c | 12 +++
.../drm/hisilicon/hibmc/hibmc_drm_debugfs.c | 49 +----------
.../gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c | 65 ---------------
.../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 37 ++++-----
.../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 1 -
.../gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c | 5 --
.../gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 13 +--
12 files changed, 77 insertions(+), 279 deletions(-)
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h
index 1107e10b2047..4bbe6b567056 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h
@@ -15,7 +15,6 @@
#include "dp_hw.h"
-#define HIBMC_DP_LINK_RATE_CAL 27
#define HIBMC_DP_LANE_NUM_MAX 2
struct hibmc_link_status {
@@ -26,9 +25,6 @@ struct hibmc_link_status {
struct hibmc_link_cap {
u8 link_rate;
u8 lanes;
- int rx_dpcd_revision;
- bool is_tps3;
- bool is_tps4;
};
struct hibmc_dp_link {
@@ -67,6 +63,7 @@ struct hibmc_dp_dev {
void hibmc_dp_aux_init(struct hibmc_dp *dp);
int hibmc_dp_link_training(struct hibmc_dp_dev *dp);
+int hibmc_dp_serdes_init(struct hibmc_dp_dev *dp);
int hibmc_dp_serdes_rate_switch(u8 rate, struct hibmc_dp_dev *dp);
int hibmc_dp_serdes_set_tx_cfg(struct hibmc_dp_dev *dp, u8 train_set[HIBMC_DP_LANE_NUM_MAX]);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c
index 9e8f95d957f2..8f0daec7d174 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c
@@ -154,6 +154,7 @@ int hibmc_dp_hw_init(struct hibmc_dp *dp)
{
struct drm_device *drm_dev = dp->drm_dev;
struct hibmc_dp_dev *dp_dev;
+ int ret;
dp_dev = devm_kzalloc(drm_dev->dev, sizeof(struct hibmc_dp_dev), GFP_KERNEL);
if (!dp_dev)
@@ -165,22 +166,23 @@ int hibmc_dp_hw_init(struct hibmc_dp *dp)
dp_dev->dev = drm_dev;
dp_dev->base = dp->mmio + HIBMC_DP_OFFSET;
- dp_dev->serdes_base = dp_dev->base + HIBMC_DP_HOST_OFFSET;
hibmc_dp_aux_init(dp);
+ ret = hibmc_dp_serdes_init(dp_dev);
+ if (ret)
+ return ret;
+
dp_dev->link.cap.lanes = 0x2;
dp_dev->link.cap.link_rate = DP_LINK_BW_8_1;
+ /* hdcp data */
+ writel(HIBMC_DP_HDCP, dp_dev->base + HIBMC_DP_HDCP_CFG);
/* int init */
writel(0, dp_dev->base + HIBMC_DP_INTR_ENABLE);
writel(HIBMC_DP_INT_RST, dp_dev->base + HIBMC_DP_INTR_ORIGINAL_STATUS);
/* rst */
- writel(0, dp_dev->base + HIBMC_DP_DPTX_RST_CTRL);
- usleep_range(30, 50);
writel(HIBMC_DP_DPTX_RST, dp_dev->base + HIBMC_DP_DPTX_RST_CTRL);
- /* hdcp data */
- writel(HIBMC_DP_HDCP, dp_dev->base + HIBMC_DP_HDCP_CFG);
/* clock enable */
writel(HIBMC_DP_CLK_EN, dp_dev->base + HIBMC_DP_DPTX_CLK_CTRL);
@@ -222,17 +224,14 @@ void hibmc_dp_display_en(struct hibmc_dp *dp, bool enable)
struct hibmc_dp_dev *dp_dev = dp->dp_dev;
if (enable) {
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_VIDEO_CTRL,
- HIBMC_DP_CFG_MST_ENABLE, 0x1);
+ hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_VIDEO_CTRL, BIT(0), 0x1);
writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL);
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_DPTX_GCTL0,
- HIBMC_DP_CFG_TIMING_GEN_ENABLE, 0x1);
+ hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_DPTX_GCTL0, BIT(10), 0x1);
writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL);
} else {
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_DPTX_GCTL0,
- HIBMC_DP_CFG_TIMING_GEN_ENABLE, 0);
+ hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_DPTX_GCTL0, BIT(10), 0);
writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL);
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_VIDEO_CTRL, HIBMC_DP_CFG_MST_ENABLE, 0);
+ hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_VIDEO_CTRL, BIT(0), 0);
writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL);
}
@@ -258,36 +257,10 @@ int hibmc_dp_mode_set(struct hibmc_dp *dp, struct drm_display_mode *mode)
return 0;
}
-u8 hibmc_dp_get_link_rate(struct hibmc_dp *dp)
-{
- if (!dp->dp_dev)
- return 0;
-
- return dp->dp_dev->link.cap.link_rate;
-}
-
-u8 hibmc_dp_get_lanes(struct hibmc_dp *dp)
-{
- if (!dp->dp_dev)
- return 0;
-
- return dp->dp_dev->link.cap.lanes;
-}
-
-int hibmc_dp_get_dpcd(struct hibmc_dp *dp)
-{
- if (!dp->dp_dev)
- return 0;
-
- return dp->dp_dev->link.cap.rx_dpcd_revision;
-}
-
void hibmc_dp_reset_link(struct hibmc_dp *dp)
{
- if (dp->dp_dev) {
- dp->dp_dev->link.status.clock_recovered = false;
- dp->dp_dev->link.status.channel_equalized = false;
- }
+ dp->dp_dev->link.status.clock_recovered = false;
+ dp->dp_dev->link.status.channel_equalized = false;
}
static const struct hibmc_dp_color_raw g_rgb_raw[] = {
@@ -309,30 +282,26 @@ void hibmc_dp_set_cbar(struct hibmc_dp *dp, const struct hibmc_dp_cbar_cfg *cfg)
struct hibmc_dp_color_raw raw_data;
if (cfg->enable) {
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL,
- HIBMC_DP_COLOR_BAR_TIMING_SEL_M, cfg->self_timing);
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL,
- HIBMC_DP_COLOR_BAR_CTRL_M, cfg->dynamic_rate);
+ hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL, BIT(9),
+ cfg->self_timing);
+ hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL, GENMASK(8, 1),
+ cfg->dynamic_rate);
if (cfg->pattern == CBAR_COLOR_BAR) {
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL,
- HIBMC_DP_COLOR_BAR_PATTERN_SEL_M, 0);
+ hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL, BIT(10), 0);
} else {
raw_data = g_rgb_raw[cfg->pattern];
drm_dbg_dp(dp->drm_dev, "r:%x g:%x b:%x\n", raw_data.r_value,
raw_data.g_value, raw_data.b_value);
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL,
- HIBMC_DP_COLOR_BAR_PATTERN_SEL_M, 1);
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL,
- HIBMC_DP_COLOR_BAR_DATA_R_M, raw_data.r_value);
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL1,
- HIBMC_DP_COLOR_BAR_DATA_G_M, raw_data.g_value);
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL1,
- HIBMC_DP_COLOR_BAR_DATA_B_M, raw_data.b_value);
+ hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL, BIT(10), 1);
+ hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL, GENMASK(23, 12),
+ raw_data.r_value);
+ hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL1, GENMASK(23, 12),
+ raw_data.g_value);
+ hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL1, GENMASK(11, 0),
+ raw_data.b_value);
}
}
- hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL,
- HIBMC_DP_COLOR_BAR_ENABLE_M, cfg->enable);
+ hibmc_dp_reg_write_field(dp_dev, HIBMC_DP_COLOR_BAR_CTRL, BIT(0), cfg->enable);
writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL);
}
-
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h
index 4740db06e1b0..f55d78d266f2 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h
@@ -12,10 +12,6 @@
#include <drm/drm_print.h>
#include <drm/drm_dp_helper.h>
-// 27 * 10000000 * 80% = 216000000
-#define DP_MODE_VALI_CAL 216000000
-#define BPP_24 24
-
struct hibmc_dp_dev;
enum hibmc_dp_cbar_pattern {
@@ -55,16 +51,11 @@ struct hibmc_dp {
struct hibmc_dp_cbar_cfg cfg;
u32 irq_status;
int hpd_status;
- bool is_connected;
};
int hibmc_dp_hw_init(struct hibmc_dp *dp);
int hibmc_dp_mode_set(struct hibmc_dp *dp, struct drm_display_mode *mode);
void hibmc_dp_display_en(struct hibmc_dp *dp, bool enable);
-struct edid *hibmc_dp_get_edid(struct hibmc_dp *dp);
-int hibmc_dp_get_dpcd(struct hibmc_dp *dp);
-u8 hibmc_dp_get_link_rate(struct hibmc_dp *dp);
-u8 hibmc_dp_get_lanes(struct hibmc_dp *dp);
void hibmc_dp_set_cbar(struct hibmc_dp *dp, const struct hibmc_dp_cbar_cfg *cfg);
void hibmc_dp_reset_link(struct hibmc_dp *dp);
void hibmc_dp_hpd_cfg(struct hibmc_dp *dp);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c
index 9b632428fec6..c3e648e2f1a8 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_link.c
@@ -39,14 +39,6 @@ static int hibmc_dp_link_training_configure(struct hibmc_dp_dev *dp)
/* enhanced frame */
hibmc_dp_reg_write_field(dp, HIBMC_DP_VIDEO_CTRL, HIBMC_DP_CFG_STREAM_FRAME_MODE, 0x1);
- ret = hibmc_dp_get_serdes_rate_cfg(dp);
- if (ret < 0)
- return ret;
-
- ret = hibmc_dp_serdes_rate_switch(ret, dp);
- if (ret)
- return ret;
-
/* set rate and lane count */
buf[0] = dp->link.cap.link_rate;
buf[1] = DP_LANE_COUNT_ENHANCED_FRAME_EN | dp->link.cap.lanes;
@@ -209,23 +201,21 @@ static int hibmc_dp_link_training_cr(struct hibmc_dp_dev *dp)
bool level_changed;
u32 voltage_tries;
u32 cr_tries;
- u32 max_cr;
int ret;
/*
* DP 1.4 spec define 10 for maxtries value, for pre DP 1.4 version set a limit of 80
* (4 voltage levels x 4 preemphasis levels x 5 identical voltage retries)
*/
- max_cr = dp->link.cap.rx_dpcd_revision >= DP_DPCD_REV_14 ? 10 : 80;
voltage_tries = 1;
- for (cr_tries = 0; cr_tries < max_cr; cr_tries++) {
+ for (cr_tries = 0; cr_tries < 80; cr_tries++) {
drm_dp_link_train_clock_recovery_delay(dp->dpcd);
ret = drm_dp_dpcd_read_link_status(dp->aux, lane_status);
if (ret != DP_LINK_STATUS_SIZE) {
- drm_err(dp->dev, "Get lane status failed, ret: %d\n", ret);
- return ret >= 0 ? -EIO : ret;
+ drm_err(dp->dev, "Get lane status failed\n");
+ return ret;
}
if (drm_dp_clock_recovery_ok(lane_status, dp->link.cap.lanes)) {
@@ -256,7 +246,7 @@ static int hibmc_dp_link_training_cr(struct hibmc_dp_dev *dp)
voltage_tries = level_changed ? 1 : voltage_tries + 1;
}
- drm_err(dp->dev, "dp link training clock recovery %u timers failed\n", max_cr);
+ drm_err(dp->dev, "dp link training clock recovery 80 times failed\n");
dp->link.status.clock_recovered = false;
return 0;
@@ -266,17 +256,9 @@ static int hibmc_dp_link_training_channel_eq(struct hibmc_dp_dev *dp)
{
u8 lane_status[DP_LINK_STATUS_SIZE] = {0};
u8 eq_tries;
- int tps;
int ret;
- if (dp->link.cap.is_tps4)
- tps = DP_TRAINING_PATTERN_4;
- else if (dp->link.cap.is_tps3)
- tps = DP_TRAINING_PATTERN_3;
- else
- tps = DP_TRAINING_PATTERN_2;
-
- ret = hibmc_dp_link_set_pattern(dp, tps);
+ ret = hibmc_dp_link_set_pattern(dp, DP_TRAINING_PATTERN_2);
if (ret)
return ret;
@@ -306,7 +288,7 @@ static int hibmc_dp_link_training_channel_eq(struct hibmc_dp_dev *dp)
ret = hibmc_dp_serdes_set_tx_cfg(dp, dp->link.train_set);
if (ret)
- break;
+ return ret;
ret = drm_dp_dpcd_write(dp->aux, DP_TRAINING_LANE0_SET,
dp->link.train_set, dp->link.cap.lanes);
@@ -335,17 +317,7 @@ static int hibmc_dp_link_downgrade_training_cr(struct hibmc_dp_dev *dp)
static int hibmc_dp_link_downgrade_training_eq(struct hibmc_dp_dev *dp)
{
- u8 status[DP_LINK_STATUS_SIZE] = {0};
- int ret;
-
- ret = drm_dp_dpcd_read_link_status(dp->aux, status);
- if (ret != DP_LINK_STATUS_SIZE) {
- drm_err(dp->dev, "get lane status failed\n");
- return ret >= 0 ? -EIO : ret;
- }
-
- if ((dp->link.status.clock_recovered && !dp->link.status.channel_equalized) ||
- (status[0] != 0 && !dp->link.status.clock_recovered)) { // at least one cr_done
+ if ((dp->link.status.clock_recovered && !dp->link.status.channel_equalized)) {
if (!hibmc_dp_link_reduce_lane(dp))
return 0;
}
@@ -353,20 +325,6 @@ static int hibmc_dp_link_downgrade_training_eq(struct hibmc_dp_dev *dp)
return hibmc_dp_link_reduce_rate(dp);
}
-static void hibmc_dp_update_caps(struct hibmc_dp_dev *dp)
-{
- dp->link.cap.rx_dpcd_revision = dp->dpcd[DP_DPCD_REV];
-
- dp->link.cap.is_tps3 = (dp->dpcd[DP_DPCD_REV] >= DP_DPCD_REV_13) &&
- (dp->dpcd[DP_MAX_LANE_COUNT] & DP_TPS3_SUPPORTED);
- dp->link.cap.is_tps4 = (dp->dpcd[DP_DPCD_REV] >= DP_DPCD_REV_14) &&
- (dp->dpcd[DP_MAX_DOWNSPREAD] & DP_TPS4_SUPPORTED);
- dp->link.cap.link_rate = dp->dpcd[DP_MAX_LINK_RATE];
- dp->link.cap.lanes = dp->dpcd[DP_MAX_LANE_COUNT] & DP_MAX_LANE_COUNT_MASK;
- if (dp->link.cap.lanes > HIBMC_DP_LANE_NUM_MAX)
- dp->link.cap.lanes = HIBMC_DP_LANE_NUM_MAX;
-}
-
int hibmc_dp_link_training(struct hibmc_dp_dev *dp)
{
struct hibmc_dp_link *link = &dp->link;
@@ -376,7 +334,16 @@ int hibmc_dp_link_training(struct hibmc_dp_dev *dp)
if (ret)
drm_err(dp->dev, "dp aux read dpcd failed, ret: %d\n", ret);
- hibmc_dp_update_caps(dp);
+ dp->link.cap.link_rate = dp->dpcd[DP_MAX_LINK_RATE];
+ dp->link.cap.lanes = 0x2;
+
+ ret = hibmc_dp_get_serdes_rate_cfg(dp);
+ if (ret < 0)
+ return ret;
+
+ ret = hibmc_dp_serdes_rate_switch(ret, dp);
+ if (ret)
+ return ret;
while (true) {
ret = hibmc_dp_link_training_cr_pre(dp);
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_reg.h b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_reg.h
index 156e5d63c47f..394b1e933c3a 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_reg.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_reg.h
@@ -68,14 +68,8 @@
#define HIBMC_DP_CFG_STREAM_HBLANK_SIZE GENMASK(15, 0)
#define HIBMC_DP_COLOR_BAR_CTRL 0x260
-#define HIBMC_DP_COLOR_BAR_ENABLE_M BIT(0)
-#define HIBMC_DP_COLOR_BAR_CTRL_M GENMASK(8, 1)
-#define HIBMC_DP_COLOR_BAR_TIMING_SEL_M BIT(9)
-#define HIBMC_DP_COLOR_BAR_PATTERN_SEL_M BIT(10)
-#define HIBMC_DP_COLOR_BAR_DATA_R_M GENMASK(23, 12)
#define HIBMC_DP_COLOR_BAR_CTRL1 0x264
-#define HIBMC_DP_COLOR_BAR_DATA_B_M GENMASK(11, 0)
-#define HIBMC_DP_COLOR_BAR_DATA_G_M GENMASK(23, 12)
+
#define HIBMC_DP_TIMING_GEN_CONFIG0 0x26c
#define HIBMC_DP_CFG_TIMING_GEN0_HACTIVE GENMASK(31, 16)
#define HIBMC_DP_CFG_TIMING_GEN0_HBLANK GENMASK(15, 0)
@@ -96,8 +90,6 @@
#define HIBMC_DP_DPTX_GCTL0 0x708
#define HIBMC_DP_CFG_PHY_LANE_NUM GENMASK(2, 1)
-#define HIBMC_DP_CFG_TIMING_GEN_ENABLE BIT(10)
-#define HIBMC_DP_CFG_MST_ENABLE BIT(0)
#define HIBMC_DP_INTR_ENABLE 0x720
#define HIBMC_DP_INTR_ORIGINAL_STATUS 0x728
diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_serdes.c b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_serdes.c
index 8191233aa965..676059d4c1e6 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_serdes.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_serdes.c
@@ -57,3 +57,15 @@ int hibmc_dp_serdes_rate_switch(u8 rate, struct hibmc_dp_dev *dp)
return 0;
}
+
+int hibmc_dp_serdes_init(struct hibmc_dp_dev *dp)
+{
+ dp->serdes_base = dp->base + HIBMC_DP_HOST_OFFSET;
+
+ writel(FIELD_PREP(HIBMC_DP_PMA_TXDEEMPH, DP_SERDES_VOL0_PRE0),
+ dp->serdes_base + HIBMC_DP_PMA_LANE0_OFFSET);
+ writel(FIELD_PREP(HIBMC_DP_PMA_TXDEEMPH, DP_SERDES_VOL0_PRE0),
+ dp->serdes_base + HIBMC_DP_PMA_LANE1_OFFSET);
+
+ return hibmc_dp_serdes_rate_switch(DP_SERDES_BW_8_1, dp);
+}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_debugfs.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_debugfs.c
index 6c6ff3255d15..83d2cd48f81c 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_debugfs.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_debugfs.c
@@ -15,44 +15,6 @@
#define MAX_BUF_SIZE 12
-static int hibmc_dp_show(struct seq_file *m, void *arg)
-{
- struct drm_info_node *node = m->private;
- struct drm_device *dev = node->minor->dev;
- struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
- int idx, rate;
-
- if (!drm_dev_enter(dev, &idx))
- return -ENODEV;
-
- switch (hibmc_dp_get_link_rate(&priv->dp)) {
- case 0x1e:
- rate = 810; // 8.1Gbps
- break;
- case 0x14:
- rate = 540; // 5.4Gbps
- break;
- case 0xA:
- rate = 270; // 2.7Gbps
- break;
- case 0x6:
- rate = 162; // 1.62Gbps
- break;
- default:
- rate = 0;
- }
-
- seq_printf(m, "enable lanes: %u\n", hibmc_dp_get_lanes(&priv->dp));
- seq_printf(m, "link rate: %d\n", rate);
- seq_printf(m, "vfresh: %d\n", drm_mode_vrefresh(&priv->crtc.mode));
- seq_printf(m, "dpcd version: 0x%x\n", hibmc_dp_get_dpcd(&priv->dp));
- seq_printf(m, "hpd status: %d\n", priv->dp.hpd_status);
-
- drm_dev_exit(idx);
-
- return 0;
-}
-
static ssize_t hibmc_control_write(struct file *file, const char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -131,19 +93,12 @@ static const struct file_operations hibmc_dbg_fops = {
.release = single_release,
};
-static struct drm_info_list hibmc_debugfs_list[] = {
- { "hibmc-dp", hibmc_dp_show },
-};
-
void hibmc_debugfs_init(struct drm_connector *connector, struct dentry *root)
{
struct drm_device *dev = connector->dev;
struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
- struct drm_minor *minor = dev->primary;
/* create the file in drm directory, so we don't need to remove manually */
- debugfs_create_file("colorbar-cfg", 0200, root, priv, &hibmc_dbg_fops);
-
- drm_debugfs_create_files(hibmc_debugfs_list, ARRAY_SIZE(hibmc_debugfs_list),
- minor->debugfs_root, minor);
+ debugfs_create_file("colorbar-cfg", 0200,
+ root, priv, &hibmc_dbg_fops);
}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c
index ae6f5c235e02..c2cda042c736 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c
@@ -11,7 +11,6 @@
#include <drm/drm_edid.h>
#include "hibmc_drm_drv.h"
-#include "hibmc_drm_regs.h"
#include "dp/dp_hw.h"
#define HIBMC_DP_MASKED_SINK_HPD_PLUG_INT BIT(2)
@@ -20,56 +19,14 @@
static int hibmc_dp_connector_get_modes(struct drm_connector *connector)
{
int count;
- struct hibmc_dp *dp = to_hibmc_dp(connector);
- struct edid *edid;
-
-
- edid = drm_get_edid(connector, &dp->aux.ddc);
- if (edid) {
- drm_connector_update_edid_property(connector, edid);
- count = drm_add_edid_modes(connector, edid);
- if (count) {
- dp->is_connected = true;
- goto out;
- }
- }
-
-
- dp->is_connected = false;
count = drm_add_modes_noedid(connector, connector->dev->mode_config.max_width,
connector->dev->mode_config.max_height);
drm_set_preferred_mode(connector, 1024, 768); // temporary implementation
-out:
- kfree(edid);
-
return count;
}
-static int hibmc_dp_mode_valid(struct drm_connector *connector,
- struct drm_display_mode *mode,
- struct drm_modeset_acquire_ctx *ctx,
- enum drm_mode_status *status)
-{
- struct hibmc_dp *dp = to_hibmc_dp(connector);
- u64 cur_val, max_val;
-
- if (!dp->is_connected) {
- *status = MODE_OK;
- return 0;
- }
-
- cur_val = (u64)mode->htotal * mode->vtotal * drm_mode_vrefresh(mode) * BPP_24;
- max_val = (u64)hibmc_dp_get_link_rate(dp) * DP_MODE_VALI_CAL * hibmc_dp_get_lanes(dp);
- if (cur_val > max_val)
- *status = MODE_CLOCK_HIGH;
- else
- *status = MODE_OK;
-
- return 0;
-}
-
static int hibmc_dp_detect(struct drm_connector *connector,
struct drm_modeset_acquire_ctx *ctx, bool force)
{
@@ -83,7 +40,6 @@ static int hibmc_dp_detect(struct drm_connector *connector,
static const struct drm_connector_helper_funcs hibmc_dp_conn_helper_funcs = {
.get_modes = hibmc_dp_connector_get_modes,
- .mode_valid_ctx = hibmc_dp_mode_valid,
.detect_ctx = hibmc_dp_detect,
};
@@ -148,26 +104,9 @@ static void hibmc_dp_encoder_disable(struct drm_encoder *drm_encoder,
hibmc_dp_display_en(dp, false);
}
-static void hibmc_dp_encoder_mode_set(struct drm_encoder *encoder,
- struct drm_crtc_state *crtc_state,
- struct drm_connector_state *conn_state)
-{
- u32 reg;
- struct drm_device *dev = encoder->dev;
- struct hibmc_drm_private *priv = to_hibmc_drm_private(dev);
-
- reg = readl(priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
- reg |= HIBMC_DISPLAY_CONTROL_FPVDDEN(1);
- reg |= HIBMC_DISPLAY_CONTROL_PANELDATE(1);
- reg |= HIBMC_DISPLAY_CONTROL_FPEN(1);
- reg |= HIBMC_DISPLAY_CONTROL_VBIASEN(1);
- writel(reg, priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE);
-}
-
static const struct drm_encoder_helper_funcs hibmc_dp_encoder_helper_funcs = {
.atomic_enable = hibmc_dp_encoder_enable,
.atomic_disable = hibmc_dp_encoder_disable,
- .atomic_mode_set = hibmc_dp_encoder_mode_set,
};
static const struct drm_encoder_funcs hibmc_encoder_funcs = {
@@ -191,8 +130,6 @@ irqreturn_t hibmc_dp_hpd_isr(int irq, void *arg)
dp->hpd_status = 0;
if (dev->registered)
drm_helper_hpd_irq_event(dev);
- } else {
- drm_dbg_dp(dev, "HPD OUT occur but err!\n");
}
} else {
if (dp->irq_status & HIBMC_DP_MASKED_SINK_HPD_PLUG_INT) {
@@ -201,8 +138,6 @@ irqreturn_t hibmc_dp_hpd_isr(int irq, void *arg)
dp->hpd_status = 1;
if (dev->registered)
drm_helper_hpd_irq_event(dev);
- } else {
- drm_dbg_dp(dev, "HPD IN occur but err!\n");
}
}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
index b9398a78c26c..147354daed84 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c
@@ -20,7 +20,6 @@
#include <drm/drm_irq.h>
#include <drm/drm_managed.h>
#include <drm/drm_vblank.h>
-#include <drm/drm_probe_helper.h>
#include "hibmc_drm_drv.h"
#include "hibmc_drm_regs.h"
@@ -120,7 +119,7 @@ static int hibmc_kms_init(struct hibmc_drm_private *priv)
ret = hibmc_de_init(priv);
if (ret) {
drm_err(priv->dev, "failed to init de: %d\n", ret);
- goto err;
+ return ret;
}
/*
@@ -130,25 +129,17 @@ static int hibmc_kms_init(struct hibmc_drm_private *priv)
ret = readl(priv->mmio + HIBMC_DP_HOST_SERDES_CTRL);
if (ret) {
ret = hibmc_dp_init(priv);
- if (ret) {
+ if (ret)
drm_err(priv->dev, "failed to init dp: %d\n", ret);
- goto err;
- }
}
ret = hibmc_vdac_init(priv);
if (ret) {
drm_err(priv->dev, "failed to init vdac: %d\n", ret);
- goto err;
+ return ret;
}
- drm_kms_helper_poll_init(priv->dev);
return 0;
-
-err:
- drm_atomic_helper_shutdown(priv->dev);
-
- return ret;
}
static void hibmc_kms_fini(struct hibmc_drm_private *priv)
@@ -300,7 +291,6 @@ static int hibmc_hw_init(struct hibmc_drm_private *priv)
static void hibmc_unload(struct drm_device *dev)
{
drm_atomic_helper_shutdown(dev);
- drm_kms_helper_poll_fini(dev);
}
static int hibmc_msi_init(struct drm_device *dev)
@@ -355,19 +345,21 @@ static int hibmc_load(struct drm_device *dev)
priv->dev = dev;
ret = hibmc_hw_init(priv);
- if (ret)
- return ret;
+ if (ret) {
+ drm_err(dev, "failed to initialize hardware: %d\n", ret);
+ goto err_alloc;
+ }
ret = hibmc_mm_init(priv);
if (ret) {
- drm_err(dev, "Error initializing VRAM MM; %d\n", ret);
- return ret;
+ drm_err(dev, "failed to initialize mm: %d\n", ret);
+ goto err_hw;
}
ret = hibmc_kms_init(priv);
if (ret) {
- drm_err(dev, "hibmc kms init failed, ret:%d\n", ret);
- return ret;
+ drm_err(dev, "failed to initialize kms: %d\n", ret);
+ goto err_mm;
}
ret = drm_vblank_init(dev, dev->mode_config.num_crtc);
@@ -389,8 +381,11 @@ static int hibmc_load(struct drm_device *dev)
err_kms:
hibmc_kms_fini(priv);
+err_mm:
hibmc_mm_fini(priv);
+err_hw:
hibmc_hw_unmap(priv);
+err_alloc:
dev->dev_private = NULL;
return ret;
@@ -400,7 +395,6 @@ static int hibmc_pci_probe(struct pci_dev *pdev,
const struct pci_device_id *ent)
{
struct drm_device *dev;
- struct hibmc_drm_private *priv;
int ret;
ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev,
@@ -440,9 +434,6 @@ static int hibmc_pci_probe(struct pci_dev *pdev,
drm_fbdev_generic_setup(dev, dev->mode_config.preferred_depth);
- priv = to_hibmc_drm_private(dev);
- hibmc_debugfs_init(&priv->dp.connector, dev->primary->debugfs_root);
-
return 0;
err_unload:
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
index 617585268009..0b0addca37f9 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h
@@ -79,7 +79,6 @@ void hibmc_mm_fini(struct hibmc_drm_private *hibmc);
int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev,
struct drm_mode_create_dumb *args);
int hibmc_ddc_create(struct drm_device *drm_dev, struct hibmc_vdac *connector);
-void hibmc_ddc_del(struct hibmc_vdac *vdac);
int hibmc_dp_init(struct hibmc_drm_private *priv);
extern const struct drm_mode_config_funcs hibmc_mode_funcs;
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c
index 2e0fcd2b3bc1..4f801c0fbd96 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c
@@ -96,8 +96,3 @@ int hibmc_ddc_create(struct drm_device *drm_dev, struct hibmc_vdac *vdac)
return i2c_bit_add_bus(&vdac->adapter);
}
-
-void hibmc_ddc_del(struct hibmc_vdac *vdac)
-{
- i2c_del_adapter(&vdac->adapter);
-}
diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
index 9c0ec6e54df0..f183dd819daf 100644
--- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
+++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c
@@ -88,7 +88,7 @@ static enum drm_mode_status hibmc_connector_mode_valid(
return hibmc_valid_mode(mode->hdisplay, mode->vdisplay);
}
-static void hibmc_vdac_connector_destroy(struct drm_connector *connector)
+static void hibmc_connector_destroy(struct drm_connector *connector)
{
struct hibmc_vdac *vdac = to_hibmc_vdac(connector);
@@ -130,7 +130,7 @@ static void hibmc_vdac_force(struct drm_connector *connector)
static const struct drm_connector_funcs hibmc_connector_funcs = {
.fill_modes = drm_helper_probe_single_connector_modes,
- .destroy = hibmc_vdac_connector_destroy,
+ .destroy = hibmc_connector_destroy,
.reset = drm_atomic_helper_connector_reset,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
@@ -180,7 +180,7 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv)
DRM_MODE_ENCODER_DAC, NULL);
if (ret) {
drm_err(dev, "failed to init encoder: %d\n", ret);
- goto err;
+ return ret;
}
drm_encoder_helper_add(encoder, &hibmc_encoder_helper_funcs);
@@ -191,7 +191,7 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv)
&vdac->adapter);
if (ret) {
drm_err(dev, "failed to init connector: %d\n", ret);
- goto err;
+ return ret;
}
drm_connector_helper_add(connector, &hibmc_connector_helper_funcs);
@@ -200,9 +200,4 @@ int hibmc_vdac_init(struct hibmc_drm_private *priv)
connector->polled = DRM_CONNECTOR_POLL_CONNECT | DRM_CONNECTOR_POLL_DISCONNECT;
return 0;
-
-err:
- hibmc_ddc_del(vdac);
-
- return ret;
}
--
2.34.1
2
1
Fix CVE-2025-21696.
change since v1:
- fix kabi breakage due to first patch.
Lokesh Gidra (1):
userfaultfd: move userfaultfd_ctx struct to header file
Ryan Roberts (1):
mm: clear uffd-wp PTE/PMD state on mremap()
Ze Zuo (1):
userfaultfd: fix kabi breakage due to struct userfaultfd_ctx
fs/userfaultfd.c | 39 --------------------------
include/linux/userfaultfd_k.h | 53 +++++++++++++++++++++++++++++++++++
mm/huge_memory.c | 12 ++++++++
mm/hugetlb.c | 14 ++++++++-
mm/mremap.c | 32 ++++++++++++++++++++-
5 files changed, 109 insertions(+), 41 deletions(-)
--
2.25.1
2
4
From: Gregory Price <gourry(a)gourry.net>
stable inclusion
from stable-v6.12.57
commit e980de2ff109dacb6d9d3a77f01b27c467115ecb
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/11500
CVE: CVE-2025-68313
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
commit 607b9fb2ce248cc5b633c5949e0153838992c152 upstream.
There's an issue with RDSEED's 16-bit and 32-bit register output
variants on Zen5 which return a random value of 0 "at a rate inconsistent
with randomness while incorrectly signaling success (CF=1)". Search the
web for AMD-SB-7055 for more detail.
Add a fix glue which checks microcode revisions.
[ bp: Add microcode revisions checking, rewrite. ]
Cc: stable(a)vger.kernel.org
Signed-off-by: Gregory Price <gourry(a)gourry.net>
Signed-off-by: Borislav Petkov (AMD) <bp(a)alien8.de>
Link: https://lore.kernel.org/r/20251018024010.4112396-1-gourry@gourry.net
[ bp: 6.12 backport: use the alternative microcode version checking. ]
Signed-off-by: Borislav Petkov (AMD) <bp(a)alien8.de>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Conflicts:
arch/x86/include/asm/cpu.h
[Add the definition of zen_patch_rev]
Signed-off-by: Bowen You <youbowen2(a)huawei.com>
---
arch/x86/kernel/cpu/amd.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index f89dbe6f48e6..5a46bf0cce5d 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -1135,8 +1135,43 @@ static void init_amd_zen4(struct cpuinfo_x86 *c)
}
}
+static bool check_rdseed_microcode(void)
+{
+ struct cpuinfo_x86 *c = &boot_cpu_data;
+ union zen_patch_rev p;
+ u32 min_rev = 0;
+
+ p.ext_fam = c->x86 - 0xf;
+ p.model = c->x86_model;
+ p.ext_model = c->x86_model >> 4;
+ p.stepping = c->x86_stepping;
+ /* reserved bits are expected to be 0 in test below */
+ p.__reserved = 0;
+
+ if (cpu_has(c, X86_FEATURE_ZEN5)) {
+ switch (p.ucode_rev >> 8) {
+ case 0xb0021: min_rev = 0xb00215a; break;
+ case 0xb1010: min_rev = 0xb101054; break;
+ default:
+ pr_debug("%s: ucode_rev: 0x%x, current revision: 0x%x\n",
+ __func__, p.ucode_rev, c->microcode);
+ return false;
+ }
+ }
+
+ if (!min_rev)
+ return false;
+
+ return c->microcode >= min_rev;
+}
+
static void init_amd_zen5(struct cpuinfo_x86 *c)
{
+ if (!check_rdseed_microcode()) {
+ clear_cpu_cap(c, X86_FEATURE_RDSEED);
+ msr_clear_bit(MSR_AMD64_CPUID_FN_7, 18);
+ pr_emerg_once("RDSEED32 is broken. Disabling the corresponding CPUID bit.\n");
+ }
}
static void init_amd(struct cpuinfo_x86 *c)
--
2.34.1
2
1
[PATCH OLK-5.10] arm64/fpsimd: signal: Allocate SSVE storage when restoring ZA
by Jinjie Ruan 06 Feb '26
by Jinjie Ruan 06 Feb '26
06 Feb '26
From: Mark Rutland <mark.rutland(a)arm.com>
stable inclusion
from stable-v6.6.122
commit 19b2c3f3ca1b4b6dccd2a42aca2692d8c79c4214
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/13639
CVE: CVE-2026-23107
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
commit ea8ccfddbce0bee6310da4f3fc560ad520f5e6b4 upstream.
The code to restore a ZA context doesn't attempt to allocate the task's
sve_state before setting TIF_SME. Consequently, restoring a ZA context
can place a task into an invalid state where TIF_SME is set but the
task's sve_state is NULL.
In legitimate but uncommon cases where the ZA signal context was NOT
created by the kernel in the context of the same task (e.g. if the task
is saved/restored with something like CRIU), we have no guarantee that
sve_state had been allocated previously. In these cases, userspace can
enter streaming mode without trapping while sve_state is NULL, causing a
later NULL pointer dereference when the kernel attempts to store the
register state:
| # ./sigreturn-za
| Unable to handle kernel NULL pointer dereference at virtual address 0000000000000000
| Mem abort info:
| ESR = 0x0000000096000046
| EC = 0x25: DABT (current EL), IL = 32 bits
| SET = 0, FnV = 0
| EA = 0, S1PTW = 0
| FSC = 0x06: level 2 translation fault
| Data abort info:
| ISV = 0, ISS = 0x00000046, ISS2 = 0x00000000
| CM = 0, WnR = 1, TnD = 0, TagAccess = 0
| GCS = 0, Overlay = 0, DirtyBit = 0, Xs = 0
| user pgtable: 4k pages, 52-bit VAs, pgdp=0000000101f47c00
| [0000000000000000] pgd=08000001021d8403, p4d=0800000102274403, pud=0800000102275403, pmd=0000000000000000
| Internal error: Oops: 0000000096000046 [#1] SMP
| Modules linked in:
| CPU: 0 UID: 0 PID: 153 Comm: sigreturn-za Not tainted 6.19.0-rc1 #1 PREEMPT
| Hardware name: linux,dummy-virt (DT)
| pstate: 214000c9 (nzCv daIF +PAN -UAO -TCO +DIT -SSBS BTYPE=--)
| pc : sve_save_state+0x4/0xf0
| lr : fpsimd_save_user_state+0xb0/0x1c0
| sp : ffff80008070bcc0
| x29: ffff80008070bcc0 x28: fff00000c1ca4c40 x27: 63cfa172fb5cf658
| x26: fff00000c1ca5228 x25: 0000000000000000 x24: 0000000000000000
| x23: 0000000000000000 x22: fff00000c1ca4c40 x21: fff00000c1ca4c40
| x20: 0000000000000020 x19: fff00000ff6900f0 x18: 0000000000000000
| x17: fff05e8e0311f000 x16: 0000000000000000 x15: 028fca8f3bdaf21c
| x14: 0000000000000212 x13: fff00000c0209f10 x12: 0000000000000020
| x11: 0000000000200b20 x10: 0000000000000000 x9 : fff00000ff69dcc0
| x8 : 00000000000003f2 x7 : 0000000000000001 x6 : fff00000c1ca5b48
| x5 : fff05e8e0311f000 x4 : 0000000008000000 x3 : 0000000000000000
| x2 : 0000000000000001 x1 : fff00000c1ca5970 x0 : 0000000000000440
| Call trace:
| sve_save_state+0x4/0xf0 (P)
| fpsimd_thread_switch+0x48/0x198
| __switch_to+0x20/0x1c0
| __schedule+0x36c/0xce0
| schedule+0x34/0x11c
| exit_to_user_mode_loop+0x124/0x188
| el0_interrupt+0xc8/0xd8
| __el0_irq_handler_common+0x18/0x24
| el0t_64_irq_handler+0x10/0x1c
| el0t_64_irq+0x198/0x19c
| Code: 54000040 d51b4408 d65f03c0 d503245f (e5bb5800)
| ---[ end trace 0000000000000000 ]---
Fix this by having restore_za_context() ensure that the task's sve_state
is allocated, matching what we do when taking an SME trap. Any live
SVE/SSVE state (which is restored earlier from a separate signal
context) must be preserved, and hence this is not zeroed.
Fixes: 39782210eb7e ("arm64/sme: Implement ZA signal handling")
Signed-off-by: Mark Rutland <mark.rutland(a)arm.com>
Cc: <stable(a)vger.kernel.org>
Cc: Mark Brown <broonie(a)kernel.org>
Cc: Will Deacon <will(a)kernel.org>
Reviewed-by: Mark Brown <broonie(a)kernel.org>
Signed-off-by: Catalin Marinas <catalin.marinas(a)arm.com>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Conflicts:
arch/arm64/kernel/signal.c
[conflict because ce514000da4f ("arm64/sme: Rename za_state to sme_state")]
Signed-off-by: Jinjie Ruan <ruanjinjie(a)huawei.com>
---
arch/arm64/kernel/signal.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c
index a0c85bb01751..d8c9434f975e 100644
--- a/arch/arm64/kernel/signal.c
+++ b/arch/arm64/kernel/signal.c
@@ -363,6 +363,10 @@ int restore_za_context(struct user_ctxs *user)
fpsimd_flush_task_state(current);
/* From now, fpsimd_thread_switch() won't touch thread.sve_state */
+ sve_alloc(current, false);
+ if (!current->thread.sve_state)
+ return -ENOMEM;
+
sme_alloc(current, true);
if (!current->thread.za_state) {
current->thread.svcr &= ~SVCR_ZA_MASK;
--
2.34.1
2
1
From: Gregory Price <gourry(a)gourry.net>
stable inclusion
from stable-v6.12.57
commit e980de2ff109dacb6d9d3a77f01b27c467115ecb
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/11500
CVE: CVE-2025-68313
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
commit 607b9fb2ce248cc5b633c5949e0153838992c152 upstream.
There's an issue with RDSEED's 16-bit and 32-bit register output
variants on Zen5 which return a random value of 0 "at a rate inconsistent
with randomness while incorrectly signaling success (CF=1)". Search the
web for AMD-SB-7055 for more detail.
Add a fix glue which checks microcode revisions.
[ bp: Add microcode revisions checking, rewrite. ]
Cc: stable(a)vger.kernel.org
Signed-off-by: Gregory Price <gourry(a)gourry.net>
Signed-off-by: Borislav Petkov (AMD) <bp(a)alien8.de>
Link: https://lore.kernel.org/r/20251018024010.4112396-1-gourry@gourry.net
[ bp: 6.12 backport: use the alternative microcode version checking. ]
Signed-off-by: Borislav Petkov (AMD) <bp(a)alien8.de>
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Conflicts:
arch/x86/include/asm/cpu.h
[Add the definition of zen_patch_rev]
Signed-off-by: Bowen You <youbowen2(a)huawei.com>
---
arch/x86/kernel/cpu/amd.c | 35 +++++++++++++++++++++++++++++++++++
1 file changed, 35 insertions(+)
diff --git a/arch/x86/kernel/cpu/amd.c b/arch/x86/kernel/cpu/amd.c
index f89dbe6f48e6..5a46bf0cce5d 100644
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -1135,8 +1135,43 @@ static void init_amd_zen4(struct cpuinfo_x86 *c)
}
}
+static bool check_rdseed_microcode(void)
+{
+ struct cpuinfo_x86 *c = &boot_cpu_data;
+ union zen_patch_rev p;
+ u32 min_rev = 0;
+
+ p.ext_fam = c->x86 - 0xf;
+ p.model = c->x86_model;
+ p.ext_model = c->x86_model >> 4;
+ p.stepping = c->x86_stepping;
+ /* reserved bits are expected to be 0 in test below */
+ p.__reserved = 0;
+
+ if (cpu_has(c, X86_FEATURE_ZEN5)) {
+ switch (p.ucode_rev >> 8) {
+ case 0xb0021: min_rev = 0xb00215a; break;
+ case 0xb1010: min_rev = 0xb101054; break;
+ default:
+ pr_debug("%s: ucode_rev: 0x%x, current revision: 0x%x\n",
+ __func__, p.ucode_rev, c->microcode);
+ return false;
+ }
+ }
+
+ if (!min_rev)
+ return false;
+
+ return c->microcode >= min_rev;
+}
+
static void init_amd_zen5(struct cpuinfo_x86 *c)
{
+ if (!check_rdseed_microcode()) {
+ clear_cpu_cap(c, X86_FEATURE_RDSEED);
+ msr_clear_bit(MSR_AMD64_CPUID_FN_7, 18);
+ pr_emerg_once("RDSEED32 is broken. Disabling the corresponding CPUID bit.\n");
+ }
}
static void init_amd(struct cpuinfo_x86 *c)
--
2.34.1
2
1
06 Feb '26
From: Arnd Bergmann <arnd(a)arndb.de>
stable inclusion
from stable-v6.6.122
commit 1b323391560354d8c515de8658b057a1daa82adb
category: bugfix
bugzilla: https://atomgit.com/src-openeuler/kernel/issues/13618
CVE: CVE-2026-23085
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id…
--------------------------------
commit 8d76a7d89c12d08382b66e2f21f20d0627d14859 upstream.
On 32-bit machines with CONFIG_ARM_LPAE, it is possible for lowmem
allocations to be backed by addresses physical memory above the 32-bit
address limit, as found while experimenting with larger VMSPLIT
configurations.
This caused the qemu virt model to crash in the GICv3 driver, which
allocates the 'itt' object using GFP_KERNEL. Since all memory below
the 4GB physical address limit is in ZONE_DMA in this configuration,
kmalloc() defaults to higher addresses for ZONE_NORMAL, and the
ITS driver stores the physical address in a 32-bit 'unsigned long'
variable.
Change the itt_addr variable to the correct phys_addr_t type instead,
along with all other variables in this driver that hold a physical
address.
The gicv5 driver correctly uses u64 variables, while all other irqchip
drivers don't call virt_to_phys or similar interfaces. It's expected that
other device drivers have similar issues, but fixing this one is
sufficient for booting a virtio based guest.
Fixes: cc2d3216f53c ("irqchip: GICv3: ITS command queue")
Signed-off-by: Arnd Bergmann <arnd(a)arndb.de>
Signed-off-by: Thomas Gleixner <tglx(a)kernel.org>
Reviewed-by: Marc Zyngier <maz(a)kernel.org>
Cc: stable(a)vger.kernel.org
Link: https://patch.msgid.link/20260119201603.2713066-1-arnd@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh(a)linuxfoundation.org>
Conflicts:
drivers/irqchip/irq-gic-v3-its.c
[ conflict becasue 5ddbc909f82a ("[Backport] irqchip/gic-v3-its: Fix VSYNC
referencing an unmapped VPE on GIC v4.1") not merged. ]
Signed-off-by: Jinjie Ruan <ruanjinjie(a)huawei.com>
---
drivers/irqchip/irq-gic-v3-its.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index fbe83b657dcc..8cac29a0996c 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -954,7 +954,7 @@ static struct its_collection *its_build_mapd_cmd(struct its_node *its,
struct its_cmd_block *cmd,
struct its_cmd_desc *desc)
{
- unsigned long itt_addr;
+ phys_addr_t itt_addr;
u8 size = ilog2(desc->its_mapd_cmd.dev->nr_ites);
itt_addr = virt_to_phys(desc->its_mapd_cmd.dev->itt);
@@ -1184,7 +1184,7 @@ static struct its_vpe *its_build_vmapp_cmd(struct its_node *its,
struct its_cmd_block *cmd,
struct its_cmd_desc *desc)
{
- unsigned long vpt_addr, vconf_addr;
+ phys_addr_t vpt_addr, vconf_addr;
u64 target;
bool alloc;
@@ -2891,10 +2891,10 @@ static int its_setup_baser(struct its_node *its, struct its_baser *baser,
baser->psz = psz;
tmp = indirect ? GITS_LVL1_ENTRY_SIZE : esz;
- pr_info("ITS@%pa: allocated %d %s @%lx (%s, esz %d, psz %dK, shr %d)\n",
+ pr_info("ITS@%pa: allocated %d %s @%llx (%s, esz %d, psz %dK, shr %d)\n",
&its->phys_base, (int)(PAGE_ORDER_TO_SIZE(order) / (int)tmp),
its_base_type_string[type],
- (unsigned long)virt_to_phys(base),
+ (u64)virt_to_phys(base),
indirect ? "indirect" : "flat", (int)esz,
psz / SZ_1K, (int)shr >> GITS_BASER_SHAREABILITY_SHIFT);
--
2.34.1
2
1