hulk inclusion category: bugfix bugzilla: https://atomgit.com/src-openeuler/kernel/issues/13655 ------------------------------------------ This reverts commit c59efc9ba374c1da3591874351c379cf356649b1, reversing changes made to 99312afdcddfa53db7c2da2022ace2768c6fb8ba. 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 Commit c59efc9ba37 attempted to fix the issue, but the problem still persists on Kunpeng 920. Therefore, temporarily revert it. Fixes: 70dcc68078ac ("drm/hisilicon/hibmc: hibmc-drm bugfix for DP") Signed-off-by: Tengda Wu <wutengda2@huawei.com> --- .../gpu/drm/hisilicon/hibmc/hibmc_drm_de.c | 24 ++++---- .../drm/hisilicon/hibmc/hibmc_drm_debugfs.c | 4 +- .../gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c | 4 +- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 59 +++++++++++-------- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 4 +- .../gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c | 4 +- drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c | 8 +-- 7 files changed, 56 insertions(+), 51 deletions(-) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c index 60263bb5ce8f..4d57ec688f82 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_de.c @@ -105,7 +105,7 @@ static void hibmc_plane_atomic_update(struct drm_plane *plane, u32 reg; s64 gpu_addr = 0; unsigned int line_l; - struct hibmc_drm_private *priv = to_hibmc_drm_private(plane->dev); + struct hibmc_drm_private *priv = plane->dev->dev_private; struct drm_gem_vram_object *gbo; if (!state->fb) @@ -159,7 +159,7 @@ static const struct drm_plane_helper_funcs hibmc_plane_helper_funcs = { static void hibmc_crtc_dpms(struct drm_crtc *crtc, int dpms) { - struct hibmc_drm_private *priv = to_hibmc_drm_private(crtc->dev); + struct hibmc_drm_private *priv = crtc->dev->dev_private; unsigned int reg; reg = readl(priv->mmio + HIBMC_CRT_DISP_CTL); @@ -175,7 +175,7 @@ static void hibmc_crtc_atomic_enable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { unsigned int reg; - struct hibmc_drm_private *priv = to_hibmc_drm_private(crtc->dev); + struct hibmc_drm_private *priv = crtc->dev->dev_private; hibmc_set_power_mode(priv, HIBMC_PW_MODE_CTL_MODE_MODE0); @@ -194,7 +194,7 @@ static void hibmc_crtc_atomic_disable(struct drm_crtc *crtc, struct drm_crtc_state *old_state) { unsigned int reg; - struct hibmc_drm_private *priv = to_hibmc_drm_private(crtc->dev); + struct hibmc_drm_private *priv = crtc->dev->dev_private; hibmc_crtc_dpms(crtc, HIBMC_CRT_DPMS_OFF); drm_crtc_vblank_off(crtc); @@ -254,7 +254,7 @@ static unsigned int format_pll_reg(void) static void set_vclock_hisilicon(struct drm_device *dev, unsigned long pll) { u32 val; - struct hibmc_drm_private *priv = to_hibmc_drm_private(dev); + struct hibmc_drm_private *priv = dev->dev_private; val = readl(priv->mmio + CRT_PLL1_HS); val &= ~(CRT_PLL1_HS_OUTER_BYPASS(1)); @@ -315,7 +315,7 @@ static unsigned int display_ctrl_adjust(struct drm_device *dev, unsigned long x, y; u32 pll1; /* bit[31:0] of PLL */ u32 pll2; /* bit[63:32] of PLL */ - struct hibmc_drm_private *priv = to_hibmc_drm_private(dev); + struct hibmc_drm_private *priv = dev->dev_private; x = mode->hdisplay; y = mode->vdisplay; @@ -363,7 +363,7 @@ static void hibmc_crtc_mode_set_nofb(struct drm_crtc *crtc) unsigned int val; struct drm_display_mode *mode = &crtc->state->mode; struct drm_device *dev = crtc->dev; - struct hibmc_drm_private *priv = to_hibmc_drm_private(dev); + struct hibmc_drm_private *priv = dev->dev_private; int width = mode->hsync_end - mode->hsync_start; int height = mode->vsync_end - mode->vsync_start; @@ -397,7 +397,7 @@ static void hibmc_crtc_atomic_begin(struct drm_crtc *crtc, { unsigned int reg; struct drm_device *dev = crtc->dev; - struct hibmc_drm_private *priv = to_hibmc_drm_private(dev); + struct hibmc_drm_private *priv = dev->dev_private; hibmc_set_power_mode(priv, HIBMC_PW_MODE_CTL_MODE_MODE0); @@ -427,7 +427,7 @@ static void hibmc_crtc_atomic_flush(struct drm_crtc *crtc, static int hibmc_crtc_enable_vblank(struct drm_crtc *crtc) { - struct hibmc_drm_private *priv = to_hibmc_drm_private(crtc->dev); + struct hibmc_drm_private *priv = crtc->dev->dev_private; writel(HIBMC_RAW_INTERRUPT_EN_VBLANK(1), priv->mmio + HIBMC_RAW_INTERRUPT_EN); @@ -437,7 +437,7 @@ static int hibmc_crtc_enable_vblank(struct drm_crtc *crtc) static void hibmc_crtc_disable_vblank(struct drm_crtc *crtc) { - struct hibmc_drm_private *priv = to_hibmc_drm_private(crtc->dev); + struct hibmc_drm_private *priv = crtc->dev->dev_private; writel(HIBMC_RAW_INTERRUPT_EN_VBLANK(0), priv->mmio + HIBMC_RAW_INTERRUPT_EN); @@ -445,7 +445,7 @@ static void hibmc_crtc_disable_vblank(struct drm_crtc *crtc) static void hibmc_crtc_load_lut(struct drm_crtc *crtc) { - struct hibmc_drm_private *priv = to_hibmc_drm_private(crtc->dev); + struct hibmc_drm_private *priv = crtc->dev->dev_private; void __iomem *mmio = priv->mmio; u16 *r, *g, *b; unsigned int reg; @@ -502,7 +502,7 @@ static const struct drm_crtc_helper_funcs hibmc_crtc_helper_funcs = { int hibmc_de_init(struct hibmc_drm_private *priv) { - struct drm_device *dev = &priv->dev; + struct drm_device *dev = priv->dev; struct drm_crtc *crtc = &priv->crtc; struct drm_plane *plane = &priv->primary_plane; int ret; diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_debugfs.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_debugfs.c index 840ef38c8c22..6c6ff3255d15 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_debugfs.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_debugfs.c @@ -89,7 +89,7 @@ static ssize_t hibmc_control_write(struct file *file, const char __user *user_bu if (cfg->pattern > 9 || cfg->enable > 1 || cfg->self_timing > 1) return -EINVAL; - ret = drm_dev_enter(&priv->dev, &idx); + ret = drm_dev_enter(priv->dev, &idx); if (!ret) return -ENODEV; @@ -106,7 +106,7 @@ static int hibmc_dp_dbgfs_show(struct seq_file *m, void *arg) struct hibmc_dp_cbar_cfg *cfg = &priv->dp.cfg; int idx; - if (!drm_dev_enter(&priv->dev, &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, diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c index ce4e7ed9825b..ae6f5c235e02 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c @@ -196,7 +196,7 @@ irqreturn_t hibmc_dp_hpd_isr(int irq, void *arg) } } else { if (dp->irq_status & HIBMC_DP_MASKED_SINK_HPD_PLUG_INT) { - drm_dbg_dp(&priv->dev, "HPD IN isr occur!\n"); + drm_dbg_dp(priv->dev, "HPD IN isr occur!\n"); hibmc_dp_hpd_cfg(dp); dp->hpd_status = 1; if (dev->registered) @@ -213,7 +213,7 @@ irqreturn_t hibmc_dp_hpd_isr(int irq, void *arg) int hibmc_dp_init(struct hibmc_drm_private *priv) { - struct drm_device *dev = &priv->dev; + struct drm_device *dev = priv->dev; struct drm_crtc *crtc = &priv->crtc; struct hibmc_dp *dp = &priv->dp; struct drm_connector *connector = &dp->connector; diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c index a0997f439e7b..b9398a78c26c 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -34,7 +34,8 @@ static const char *g_irqs_names_map[HIBMC_MAX_VECTORS] = { "hibmc-vblank", "hibm static irqreturn_t hibmc_drm_interrupt(int irq, void *arg) { struct drm_device *dev = (struct drm_device *)arg; - struct hibmc_drm_private *priv = to_hibmc_drm_private(dev); + struct hibmc_drm_private *priv = + (struct hibmc_drm_private *)dev->dev_private; u32 status; status = readl(priv->mmio + HIBMC_RAW_INTERRUPT); @@ -100,26 +101,25 @@ static const struct dev_pm_ops hibmc_pm_ops = { static int hibmc_kms_init(struct hibmc_drm_private *priv) { - struct drm_device *dev = &priv->dev; int ret; - drm_mode_config_init(dev); + drm_mode_config_init(priv->dev); priv->mode_config_initialized = true; - dev->mode_config.min_width = 0; - dev->mode_config.min_height = 0; - dev->mode_config.max_width = 1920; - dev->mode_config.max_height = 1200; + priv->dev->mode_config.min_width = 0; + priv->dev->mode_config.min_height = 0; + priv->dev->mode_config.max_width = 1920; + priv->dev->mode_config.max_height = 1200; - dev->mode_config.fb_base = priv->fb_base; - dev->mode_config.preferred_depth = 32; - dev->mode_config.prefer_shadow = 1; + priv->dev->mode_config.fb_base = priv->fb_base; + priv->dev->mode_config.preferred_depth = 32; + priv->dev->mode_config.prefer_shadow = 1; - dev->mode_config.funcs = (void *)&hibmc_mode_funcs; + priv->dev->mode_config.funcs = (void *)&hibmc_mode_funcs; ret = hibmc_de_init(priv); if (ret) { - drm_err(dev, "failed to init de: %d\n", ret); + drm_err(priv->dev, "failed to init de: %d\n", ret); goto err; } @@ -131,22 +131,22 @@ static int hibmc_kms_init(struct hibmc_drm_private *priv) if (ret) { ret = hibmc_dp_init(priv); if (ret) { - drm_err(&priv->dev, "failed to init dp: %d\n", ret); + drm_err(priv->dev, "failed to init dp: %d\n", ret); goto err; } } ret = hibmc_vdac_init(priv); if (ret) { - drm_err(dev, "failed to init vdac: %d\n", ret); + drm_err(priv->dev, "failed to init vdac: %d\n", ret); goto err; } - drm_kms_helper_poll_init(&priv->dev); + drm_kms_helper_poll_init(priv->dev); return 0; err: - drm_atomic_helper_shutdown(&priv->dev); + drm_atomic_helper_shutdown(priv->dev); return ret; } @@ -154,7 +154,7 @@ static int hibmc_kms_init(struct hibmc_drm_private *priv) static void hibmc_kms_fini(struct hibmc_drm_private *priv) { if (priv->mode_config_initialized) { - drm_mode_config_cleanup(&priv->dev); + drm_mode_config_cleanup(priv->dev); priv->mode_config_initialized = false; } } @@ -244,7 +244,7 @@ static void hibmc_hw_config(struct hibmc_drm_private *priv) static int hibmc_hw_map(struct hibmc_drm_private *priv) { - struct drm_device *dev = &priv->dev; + struct drm_device *dev = priv->dev; struct pci_dev *pdev = dev->pdev; resource_size_t addr, size, ioaddr, iosize; @@ -271,7 +271,7 @@ static int hibmc_hw_map(struct hibmc_drm_private *priv) static void hibmc_hw_unmap(struct hibmc_drm_private *priv) { - struct drm_device *dev = &priv->dev; + struct drm_device *dev = priv->dev; if (priv->fb_map) { devm_iounmap(dev->dev, priv->fb_map); @@ -343,9 +343,17 @@ static int hibmc_msi_init(struct drm_device *dev) static int hibmc_load(struct drm_device *dev) { - struct hibmc_drm_private *priv = to_hibmc_drm_private(dev); + struct hibmc_drm_private *priv; int ret; + priv = drmm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); + if (!priv) { + drm_err(dev, "no memory to allocate for hibmc_drm_private\n"); + return -ENOMEM; + } + dev->dev_private = priv; + priv->dev = dev; + ret = hibmc_hw_init(priv); if (ret) return ret; @@ -391,8 +399,8 @@ static int hibmc_load(struct drm_device *dev) static int hibmc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { - struct hibmc_drm_private *priv; struct drm_device *dev; + struct hibmc_drm_private *priv; int ret; ret = drm_fb_helper_remove_conflicting_pci_framebuffers(pdev, @@ -400,14 +408,12 @@ static int hibmc_pci_probe(struct pci_dev *pdev, if (ret) return ret; - priv = devm_drm_dev_alloc(&pdev->dev, &hibmc_driver, - struct hibmc_drm_private, dev); - if (IS_ERR(priv)) { + dev = drm_dev_alloc(&hibmc_driver, &pdev->dev); + if (IS_ERR(dev)) { DRM_ERROR("failed to allocate drm_device\n"); - return PTR_ERR(priv); + return PTR_ERR(dev); } - dev = &priv->dev; dev->pdev = pdev; pci_set_drvdata(pdev, dev); @@ -434,6 +440,7 @@ 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; diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h index ab92f4688ecb..617585268009 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h @@ -43,7 +43,7 @@ struct hibmc_drm_private { unsigned long fb_size; /* drm */ - struct drm_device dev; + struct drm_device *dev; struct drm_plane primary_plane; struct drm_crtc crtc; bool mode_config_initialized; @@ -63,7 +63,7 @@ static inline struct hibmc_dp *to_hibmc_dp(struct drm_connector *connector) static inline struct hibmc_drm_private *to_hibmc_drm_private(struct drm_device *dev) { - return container_of(dev, struct hibmc_drm_private, dev); + return dev->dev_private; } void hibmc_set_power_mode(struct hibmc_drm_private *priv, diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c index 5f1b88a59aa9..9c0ec6e54df0 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_vdac.c @@ -143,7 +143,7 @@ static void hibmc_encoder_mode_set(struct drm_encoder *encoder, { u32 reg; struct drm_device *dev = encoder->dev; - struct hibmc_drm_private *priv = to_hibmc_drm_private(dev); + struct hibmc_drm_private *priv = dev->dev_private; reg = readl(priv->mmio + HIBMC_DISPLAY_CONTROL_HISILE); reg |= HIBMC_DISPLAY_CONTROL_FPVDDEN(1); @@ -163,7 +163,7 @@ 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 drm_device *dev = priv->dev; struct hibmc_vdac *vdac = &priv->vdac; struct drm_encoder *encoder = &vdac->encoder; struct drm_connector *connector = &vdac->connector; diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c index e84fb81849a7..602ece11bb4a 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_ttm.c @@ -25,7 +25,7 @@ int hibmc_mm_init(struct hibmc_drm_private *hibmc) { struct drm_vram_mm *vmm; int ret; - struct drm_device *dev = &hibmc->dev; + struct drm_device *dev = hibmc->dev; vmm = drm_vram_helper_alloc_mm(dev, pci_resource_start(dev->pdev, 0), @@ -41,12 +41,10 @@ int hibmc_mm_init(struct hibmc_drm_private *hibmc) void hibmc_mm_fini(struct hibmc_drm_private *hibmc) { - struct drm_device *dev = &hibmc->dev; - - if (!dev->vram_mm) + if (!hibmc->dev->vram_mm) return; - drm_vram_helper_release_mm(dev); + drm_vram_helper_release_mm(hibmc->dev); } int hibmc_dumb_create(struct drm_file *file, struct drm_device *dev, -- 2.34.1