From nobody Thu Sep 24 12:53:51 2026 Received: from canpmsgout03.his.huawei.com (canpmsgout03.his.huawei.com [113.46.200.218]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 3639325B091 for ; Thu, 24 Sep 2026 08:17:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.218 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790237877; cv=none; b=N5MsgNQ6sEbvKuaRa2gPnIm73eP7VCC2J3OTW1itC3sP5kczkA9ljfA3+lUKCRFRmeGmRexnFVZxBS22aTbr2ueiz7ewuiQhzxgMxg3SVcSEXGAOddfU+P/og8hMlm8LLRm6R7jOgLjz9eEH2kcdRHvBm2qh47xLFXgoCEVw/9g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790237877; c=relaxed/simple; bh=akLwqcWyfkLhvblu+5XiG000Nrcm0BUAJnPKOXmq8Ik=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=Lb288s2Wa/oEVNIVnh2PL5GF2qWIcHs7wJsSDoL0Pl1J8FILuJLUBWwUJnbW6WrNuPQ5wFXlQAQEM7O/s2e2zqvqreJ1HCw1VeociIi9wrVpeV86bkL84m1qa2kld1eNzJEtbuHwxYWmDaQxoG0p16G6JHJmUCUhbu/7EtZ5hjQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=dR4oXyQ3; arc=none smtp.client-ip=113.46.200.218 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="dR4oXyQ3" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=AoKsN4mo7UqzgL6Fe5eCByZqucD8tS9yp1hZ5L7IS5Q=; b=dR4oXyQ3ZGcgEi9+k4kHOllp9IyIpBZEImGNauhPQbYzAdG+lE1q0UsL/tSCJC1LwvittckCX GqmsmyiM7Wq7yMrDe9F2NLQ7Nb9FlSYHQWT72bY5vQZH0DJED/E3qrACEbd7hseVdKRC8ovAsM5 RI3rD1w6Z2CnBv8z5t5X0xU= Received: from mail.maildlp.com (unknown [172.19.163.104]) by canpmsgout03.his.huawei.com (SkyGuard) with ESMTPS id 4hr5xV6vhfzpSyD; Thu, 24 Sep 2026 16:05:50 +0800 (CST) Received: from kwepemk200005.china.huawei.com (unknown [7.202.194.71]) by mail.maildlp.com (Postfix) with ESMTPS id A51814057F; Thu, 24 Sep 2026 16:17:50 +0800 (CST) Received: from localhost.huawei.com (10.169.71.169) by kwepemk200005.china.huawei.com (7.202.194.71) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Thu, 24 Sep 2026 16:17:50 +0800 From: Yongbang Shi To: , , , , , , , CC: , , , , , , , , , Subject: [PATCH for drm-misc-fixes v3 1/2] drm/hisilicon/hibmc: Modify the method of obtaining the hpd_status Date: Thu, 24 Sep 2026 16:06:08 +0800 Message-ID: <20260924080609.3681795-2-shiyongbang@huawei.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260924080609.3681795-1-shiyongbang@huawei.com> References: <20260924080609.3681795-1-shiyongbang@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemk200005.china.huawei.com (7.202.194.71) Content-Type: text/plain; charset="utf-8" From: Lin He To more accurately determine whether the current HPD status matches the interrupt status, the polling mechanism in the lower half of the HPD interrupt (via hibmc_dp_check_hpd_status) has been replaced with directly retrieving the interrupt status in the upper half of the interrupt (via hibmc_dp_get_hpd_status). * Detection and training are not performed if hpd_status is not HPD_IN. * Set the initial status of hpd_status to HPD_OUT. Fixes: 3906e7a3b26d ("drm/hisilicon/hibmc: fix dp probabilistical detect er= rors after HPD irq") Signed-off-by: Lin He Signed-off-by: Yongbang Shi --- ChangeLog: v2 -> v3: - Delete irq_status and use hpd_status directly for hotplug detection. (sashiko-bot) - Add debug logs when hpd_status is not HPD_IN in detect and encoder_enable. v1 -> v2: - More states in HIBMC_DP_HPD_STATUS are added to the 'hibmc_dp_get_hpd_status'. --- drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h | 1 - drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c | 32 +++++++++++------ drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h | 5 +-- .../gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c | 34 +++++++++++-------- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 2 +- 5 files changed, 45 insertions(+), 29 deletions(-) diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h b/drivers/gpu/drm= /hisilicon/hibmc/dp/dp_comm.h index f53dac256ee0..b0e258b9265e 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h +++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_comm.h @@ -43,7 +43,6 @@ struct hibmc_dp_dev { u8 downstream_ports[DP_MAX_DOWNSTREAM_PORTS]; struct drm_dp_desc desc; bool is_branch; - int hpd_status; void __iomem *serdes_base; }; =20 diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c b/drivers/gpu/drm/h= isilicon/hibmc/dp/dp_hw.c index d5bd3c45649b..a4cd4cd8cc75 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c +++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.c @@ -191,6 +191,10 @@ int hibmc_dp_hw_init(struct hibmc_dp *dp) 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); + /* To latch the HPD interrupt, ensuring that DP can support more modes + * within the fbcon framework when connected alone. + */ + msleep(100); =20 return 0; } @@ -322,20 +326,26 @@ void hibmc_dp_set_cbar(struct hibmc_dp *dp, const str= uct hibmc_dp_cbar_cfg *cfg) writel(HIBMC_DP_SYNC_EN_MASK, dp_dev->base + HIBMC_DP_TIMING_SYNC_CTRL); } =20 -bool hibmc_dp_check_hpd_status(struct hibmc_dp *dp, int exp_status) +int hibmc_dp_get_hpd_status(struct hibmc_dp *dp) { + int hpd_status =3D HIBMC_HPD_UNKNOWN; u32 status; - int ret; =20 - ret =3D readl_poll_timeout(dp->dp_dev->base + HIBMC_DP_HPD_STATUS, status, - FIELD_GET(HIBMC_DP_HPD_CUR_STATE, status) =3D=3D exp_status, - 1000, 100000); /* DP spec says 100ms */ - if (ret) { - drm_dbg_dp(dp->drm_dev, "wait hpd status timeout"); - return false; + status =3D FIELD_GET(HIBMC_DP_HPD_CUR_STATE, + readl(dp->dp_dev->base + HIBMC_DP_HPD_STATUS)); + switch (status) { + case 0: /* idle */ + case 3: /* unplug */ + case 4: /* unplug intermediate */ + hpd_status =3D HIBMC_HPD_OUT; + break; + case 1: /* plug */ + case 2: /* plug intermediate */ + hpd_status =3D HIBMC_HPD_IN; + break; + default: + break; } =20 - dp->dp_dev->hpd_status =3D exp_status; - - return true; + return hpd_status; } diff --git a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h b/drivers/gpu/drm/h= isilicon/hibmc/dp/dp_hw.h index 0f3662d8737e..959bf95f6fe5 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h +++ b/drivers/gpu/drm/hisilicon/hibmc/dp/dp_hw.h @@ -15,6 +15,7 @@ struct hibmc_dp_dev; =20 enum hibmc_hpd_status { + HIBMC_HPD_UNKNOWN, HIBMC_HPD_OUT, HIBMC_HPD_IN, }; @@ -54,7 +55,7 @@ struct hibmc_dp { void __iomem *mmio; struct drm_dp_aux aux; struct hibmc_dp_cbar_cfg cfg; - u32 irq_status; + int hpd_status; int phys_status; }; =20 @@ -66,7 +67,7 @@ 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); -bool hibmc_dp_check_hpd_status(struct hibmc_dp *dp, int exp_status); +int hibmc_dp_get_hpd_status(struct hibmc_dp *dp); u8 hibmc_dp_get_link_rate(struct hibmc_dp *dp); u8 hibmc_dp_get_lanes(struct hibmc_dp *dp); =20 diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c b/drivers/gpu/d= rm/hisilicon/hibmc/hibmc_drm_dp.c index 2e9403b8bf3c..1f8ea0b09253 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_dp.c @@ -15,8 +15,6 @@ #include "dp/dp_comm.h" #include "dp/dp_config.h" =20 -#define DP_MASKED_SINK_HPD_PLUG_INT BIT(2) - static int hibmc_dp_connector_get_modes(struct drm_connector *connector) { const struct drm_edid *drm_edid; @@ -63,11 +61,10 @@ static int hibmc_dp_detect(struct drm_connector *connec= tor, struct hibmc_dp_dev *dp_dev =3D dp->dp_dev; int ret =3D connector_status_disconnected; =20 - if (dp->irq_status) { - if (dp_dev->hpd_status !=3D HIBMC_HPD_IN) { - ret =3D connector_status_disconnected; - goto exit; - } + if (dp->hpd_status !=3D HIBMC_HPD_IN) { + drm_dbg_dp(dp->drm_dev, "dp detect skipped, hpd (%d)\n", + dp->hpd_status); + goto exit; } =20 if (!hibmc_dp_get_dpcd(dp_dev)) { @@ -166,6 +163,12 @@ static void hibmc_dp_encoder_enable(struct drm_encoder= *drm_encoder, struct hibmc_dp *dp =3D container_of(drm_encoder, struct hibmc_dp, encode= r); struct drm_display_mode *mode =3D &drm_encoder->crtc->state->mode; =20 + if (dp->hpd_status !=3D HIBMC_HPD_IN) { + drm_dbg_dp(dp->drm_dev, "dp encoder enable skipped, hpd (%d)\n", + dp->hpd_status); + return; + } + if (hibmc_dp_prepare(dp, mode)) return; =20 @@ -189,24 +192,26 @@ irqreturn_t hibmc_dp_hpd_isr(int irq, void *arg) { struct drm_device *dev =3D (struct drm_device *)arg; struct hibmc_drm_private *priv =3D to_hibmc_drm_private(dev); - int idx, exp_status; + int status =3D priv->dp.hpd_status; + int idx; =20 if (!drm_dev_enter(dev, &idx)) return -ENODEV; =20 - if (priv->dp.irq_status & DP_MASKED_SINK_HPD_PLUG_INT) { + if (status =3D=3D HIBMC_HPD_IN) { drm_dbg_dp(&priv->dev, "HPD IN isr occur!\n"); hibmc_dp_hpd_cfg(&priv->dp); - exp_status =3D HIBMC_HPD_IN; - } else { + } else if (status =3D=3D HIBMC_HPD_OUT) { drm_dbg_dp(&priv->dev, "HPD OUT isr occur!\n"); hibmc_dp_reset_link(&priv->dp); - exp_status =3D HIBMC_HPD_OUT; + } else { + drm_err(&priv->dev, "HPD status (%d) error\n", status); + goto exit; } =20 - if (hibmc_dp_check_hpd_status(&priv->dp, exp_status)) - drm_connector_helper_hpd_irq_event(&priv->dp.connector); + drm_connector_helper_hpd_irq_event(&priv->dp.connector); =20 +exit: drm_dev_exit(idx); =20 return IRQ_HANDLED; @@ -223,6 +228,7 @@ int hibmc_dp_init(struct hibmc_drm_private *priv) =20 dp->mmio =3D priv->mmio; dp->drm_dev =3D dev; + dp->hpd_status =3D HIBMC_HPD_OUT; =20 ret =3D hibmc_dp_hw_init(&priv->dp); if (ret) { diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/= drm/hisilicon/hibmc/hibmc_drm_drv.c index 4d85c89f3f88..4ab0e565cb13 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -62,7 +62,7 @@ static irqreturn_t hibmc_dp_interrupt(int irq, void *arg) =20 status =3D readl(priv->mmio + HIBMC_DP_INTSTAT); if (status) { - priv->dp.irq_status =3D status; + priv->dp.hpd_status =3D hibmc_dp_get_hpd_status(&priv->dp); writel(status, priv->mmio + HIBMC_DP_INTCLR); return IRQ_WAKE_THREAD; } --=20 2.43.0 From nobody Thu Sep 24 12:53:51 2026 Received: from canpmsgout05.his.huawei.com (canpmsgout05.his.huawei.com [113.46.200.220]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 7F7EE43DEDF for ; Thu, 24 Sep 2026 08:17:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=113.46.200.220 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790237884; cv=none; b=dHAaKwn8Y9nMq4o+FDETXcx85xo7Wcs4jAQl488D0iGOCSt8AD9P8tkIiViq3//rtLagI6nlrE55otUBjyQCHrV+nOzrvdz19BMNyx40EWjvyfhPLYF/Dswu1MWNQQCHhw24s1KGF3nubtpABHkNasFIfSQso0usIA+JuUoeqvE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1790237884; c=relaxed/simple; bh=7NRzBcjvIhTIEW+WOJjmu7XiLjMyaWq9SmOlrjJ8JhY=; h=From:To:CC:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version:Content-Type; b=AfrSK2OEgpfmVDrRtJsDY5xKvPAv0/B5kHYAH22V8szIBXN0rLizrtanj9P+ot8RF8pzgdcZFuaH0ttNsn/AaHvh6M3/uIQnKvDVvC+2leK4k0gpPLq7rUWxvLUAtHW8plALNWRR+cuEAzFRbbIf7DahhMlyHMEpLEjKpO4PS/o= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com; spf=pass smtp.mailfrom=huawei.com; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b=Bg/YesFj; arc=none smtp.client-ip=113.46.200.220 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=quarantine dis=none) header.from=huawei.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=huawei.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=huawei.com header.i=@huawei.com header.b="Bg/YesFj" dkim-signature: v=1; a=rsa-sha256; d=huawei.com; s=dkim; c=relaxed/relaxed; q=dns/txt; h=From; bh=6kjXznkOnXGtV+t4t+Sino0ktTMNsnonA1JZVorFzVc=; b=Bg/YesFjrCeY4YYqSRTL3qpsM4zkBYiiYhdKfu8kmoap8FzGQsToKq4C0iJjoesz/4IuVajQt 3JWSCPlubz4q7CzKXL84AcpJOkTEFzCsRhCfaR5cGzq0fQObnWbSY0I8tydbMldKh8mUcm2nTJ3 az3YheAWjP+ISJkZeugY5Ys= Received: from mail.maildlp.com (unknown [172.19.163.104]) by canpmsgout05.his.huawei.com (SkyGuard) with ESMTPS id 4hr5xP3N5pz12LHt; Thu, 24 Sep 2026 16:05:45 +0800 (CST) Received: from kwepemk200005.china.huawei.com (unknown [7.202.194.71]) by mail.maildlp.com (Postfix) with ESMTPS id 1E4074057F; Thu, 24 Sep 2026 16:17:51 +0800 (CST) Received: from localhost.huawei.com (10.169.71.169) by kwepemk200005.china.huawei.com (7.202.194.71) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.2.2562.45; Thu, 24 Sep 2026 16:17:50 +0800 From: Yongbang Shi To: , , , , , , , CC: , , , , , , , , , Subject: [PATCH for drm-misc-fixes v3 2/2] drm/hisilicon/hibmc: Add a flag to indicate whether the OS-side driver has been loaded Date: Thu, 24 Sep 2026 16:06:09 +0800 Message-ID: <20260924080609.3681795-3-shiyongbang@huawei.com> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260924080609.3681795-1-shiyongbang@huawei.com> References: <20260924080609.3681795-1-shiyongbang@huawei.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-ClientProxiedBy: kwepems200002.china.huawei.com (7.221.188.68) To kwepemk200005.china.huawei.com (7.202.194.71) Content-Type: text/plain; charset="utf-8" From: Lin He Add a flag to indicate whether the OS-side driver has been loaded to prevent the BMC from enabling DP if the driver is not loaded, which could lead to system failure in handling interrupts and generate error messages like: irq xx: nobody cared (try booting with the "irqpoll" option) ... Call Trace: ... Fixes: 0ab6ea261c1f ("drm/hisilicon/hibmc: add dp module in hibmc") Signed-off-by: Lin He Signed-off-by: Yongbang Shi --- ChangeLog: v2 -> v3: - Move hibmc_set_enable_flag() before drm_dev_register() and hibmc_set_disable_flag() after drm_dev_unregister() to narrow the race window. (sashiko-bot) - Add spinlock_t gpio_lock to hibmc_drm_private to protect all operations on 0x0802A4. (sashiko-bot) v1 -> v2: - The call to `hibmc_set_enable_flag()` has been moved before `drm_client_setup()`, specifically before the connector detection triggers the I2C bit operation. (sashiko-bot) - A read-modify-write operation has been implemented instead of directly writing to prevent clearing the I2C mask bits. (sashiko-bot) --- .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c | 30 +++++++++++++++++++ .../gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h | 2 ++ .../gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c | 19 ++++++++++-- .../gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h | 3 ++ 4 files changed, 51 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c b/drivers/gpu/= drm/hisilicon/hibmc/hibmc_drm_drv.c index 4ab0e565cb13..9859492da5fa 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.c @@ -167,6 +167,8 @@ static int hibmc_kms_init(struct hibmc_drm_private *pri= v) if (ret) return ret; =20 + spin_lock_init(&priv->gpio_lock); + dev->mode_config.min_width =3D 0; dev->mode_config.min_height =3D 0; dev->mode_config.max_width =3D 1920; @@ -423,6 +425,30 @@ static int hibmc_load(struct drm_device *dev) return ret; } =20 +static inline void hibmc_set_enable_flag(struct hibmc_drm_private *priv) +{ + unsigned long flags; + u32 value; + + spin_lock_irqsave(&priv->gpio_lock, flags); + value =3D readl(priv->mmio + HIBMC_ENABLE_FLAG); + value |=3D HIBMC_ENABLE_STATE; + writel(value, priv->mmio + HIBMC_ENABLE_FLAG); + spin_unlock_irqrestore(&priv->gpio_lock, flags); +} + +static inline void hibmc_set_disable_flag(struct hibmc_drm_private *priv) +{ + unsigned long flags; + u32 value; + + spin_lock_irqsave(&priv->gpio_lock, flags); + value =3D readl(priv->mmio + HIBMC_ENABLE_FLAG); + value &=3D ~HIBMC_ENABLE_STATE; + writel(value, priv->mmio + HIBMC_ENABLE_FLAG); + spin_unlock_irqrestore(&priv->gpio_lock, flags); +} + static int hibmc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) { @@ -458,6 +484,8 @@ static int hibmc_pci_probe(struct pci_dev *pdev, goto err_return; } =20 + hibmc_set_enable_flag(priv); + ret =3D drm_dev_register(dev, 0); if (ret) { drm_err(dev, "failed to register drv for userspace access: %d\n", @@ -470,6 +498,7 @@ static int hibmc_pci_probe(struct pci_dev *pdev, return 0; =20 err_unload: + hibmc_set_disable_flag(to_hibmc_drm_private(dev)); hibmc_unload(dev); err_return: return ret; @@ -480,6 +509,7 @@ static void hibmc_pci_remove(struct pci_dev *pdev) struct drm_device *dev =3D pci_get_drvdata(pdev); =20 drm_dev_unregister(dev); + hibmc_set_disable_flag(to_hibmc_drm_private(dev)); hibmc_unload(dev); } =20 diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h b/drivers/gpu/= drm/hisilicon/hibmc/hibmc_drm_drv.h index dce8572bf63e..c2a82000ea7f 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_drv.h @@ -49,6 +49,8 @@ struct hibmc_drm_private { struct drm_crtc crtc; struct hibmc_vdac vdac; struct hibmc_dp dp; + + spinlock_t gpio_lock; /* protects RMW on I2C/ENABLE_FLAG (0x0802A4) */ }; =20 static inline struct hibmc_vdac *to_hibmc_vdac(struct drm_connector *conne= ctor) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c b/drivers/gpu/= drm/hisilicon/hibmc/hibmc_drm_i2c.c index 44860011855e..4ceb87efec05 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_i2c.c @@ -27,7 +27,11 @@ static void hibmc_set_i2c_signal(void *data, u32 mask, i= nt value) { struct hibmc_vdac *vdac =3D data; struct hibmc_drm_private *priv =3D to_hibmc_drm_private(vdac->connector.d= ev); - u32 tmp_dir =3D readl(priv->mmio + GPIO_DATA_DIRECTION); + unsigned long flags; + u32 tmp_dir; + + spin_lock_irqsave(&priv->gpio_lock, flags); + tmp_dir =3D readl(priv->mmio + GPIO_DATA_DIRECTION); =20 if (value) { tmp_dir &=3D ~mask; @@ -41,20 +45,29 @@ static void hibmc_set_i2c_signal(void *data, u32 mask, = int value) tmp_dir |=3D mask; writel(tmp_dir, priv->mmio + GPIO_DATA_DIRECTION); } + spin_unlock_irqrestore(&priv->gpio_lock, flags); } =20 static int hibmc_get_i2c_signal(void *data, u32 mask) { struct hibmc_vdac *vdac =3D data; struct hibmc_drm_private *priv =3D to_hibmc_drm_private(vdac->connector.d= ev); - u32 tmp_dir =3D readl(priv->mmio + GPIO_DATA_DIRECTION); + unsigned long flags; + u32 tmp_dir; + int ret; + + spin_lock_irqsave(&priv->gpio_lock, flags); + tmp_dir =3D readl(priv->mmio + GPIO_DATA_DIRECTION); =20 if ((tmp_dir & mask) !=3D mask) { tmp_dir &=3D ~mask; writel(tmp_dir, priv->mmio + GPIO_DATA_DIRECTION); } =20 - return (readl(priv->mmio + GPIO_DATA) & mask) ? 1 : 0; + ret =3D (readl(priv->mmio + GPIO_DATA) & mask) ? 1 : 0; + spin_unlock_irqrestore(&priv->gpio_lock, flags); + + return ret; } =20 static void hibmc_ddc_setsda(void *data, int state) diff --git a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h b/drivers/gpu= /drm/hisilicon/hibmc/hibmc_drm_regs.h index 17b30c393b10..b95add5b253c 100644 --- a/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h +++ b/drivers/gpu/drm/hisilicon/hibmc/hibmc_drm_regs.h @@ -200,5 +200,8 @@ =20 #define HIBMC_CRT_PALETTE 0x80C00 =20 +#define HIBMC_ENABLE_FLAG 0x802A4 +#define HIBMC_ENABLE_STATE BIT(2) + #define HIBMC_FIELD(field, value) (field(value) & field##_MASK) #endif --=20 2.43.0