From nobody Mon May 25 06:40:25 2026 Received: from mail-01.1984.is (mail-01.1984.is [185.112.145.69]) (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 A3AD03603FB for ; Sun, 17 May 2026 13:03:50 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.112.145.69 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779023034; cv=none; b=LFsdMkWH686bahZJs/KA145jCe6iN1VF9tfuxYowqS1YeTR3cOqj78CAD3LW+WMNFx0pl9bxlbXe3dHMisAyuXMJYqO8fNzj/VS1LfAIxe5pFzLXMjGtc3CC5pBtN3wtFQKWK8SxQA2kiA9JswVGMROc0btYadn2KtMIq3/BCCM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1779023034; c=relaxed/simple; bh=6ckILtZv9sY+vKdKLniRwzFkP0Ddi17YLXHBOO1N5IY=; h=Date:Message-ID:From:To:Cc:Subject; b=FodvQyobycdy5oP50c98x+MjjvY9gqqKoHYvbjKJOsSdF5jftovTLP8LOxcscUNqeH8i+7NKv5Esnn6NgmaglnNvbPT+xIht7RaqDF8/YrQhYXWwjmtW9mo784nMJLslpa3Ga21RSR76PFhBKDrbkvqyPIjYAanFFjiK+DV0hCw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=berkoc.com; spf=pass smtp.mailfrom=berkoc.com; dkim=pass (2048-bit key) header.d=berkoc.com header.i=@berkoc.com header.b=KhR5E3Lh; arc=none smtp.client-ip=185.112.145.69 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=berkoc.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=berkoc.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=berkoc.com header.i=@berkoc.com header.b="KhR5E3Lh" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=berkoc.com; s=1984; h=Subject:Cc:To:From:Message-ID:Date:Sender:Reply-To:MIME-Version: Content-Type:Content-Transfer-Encoding:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: In-Reply-To:References:List-Id:List-Help:List-Unsubscribe:List-Subscribe: List-Post:List-Owner:List-Archive; bh=D9kECFUMtuKh0TE7iHonFkqbM5K+lBf35nG9AQ8cfUI=; b=KhR5E3LhqCJewlgXOx6eBv3ByC QDm/vd+N7NB9IxWiSkrQluzZKyxuvdHvf3LbrYEgjLbqJmtamfZ0933twJSyx9Q65FlDCtxLi54r1 VPkV0vLnFJmX40/1K0wRUZ/NIrFx/CFyLp61nCmdfPhlkloUcRVgLDrf4WKNv0mQK1fn3dC3lM/yq XCSYYfP11otwHj0gv01sekNqSC+Jk2tOCJpvkZTWakS90x7HyaIrMfBxtZLiBooDi5gV6ewhPeYsV LbROp7LmgYQQH0pTnntLMpqOH/1OIuoqVRwxMaqCOrbrhCyoLSZyBmDw+7gKZHc4R96zGrukkMIBh 7EcrVIsQ==; Received: from localhost by mail-01.1984.is with utf8esmtp (Exim 4.96) (envelope-from ) id 1wOb9H-00FziQ-2K; Sun, 17 May 2026 13:03:23 +0000 Date: Sun, 17 May 2026 15:03:09 +0200 Message-ID: <28e476e896dafdd31518dc5360ab7766@berkoc.com> From: Berkant Koc To: dri-devel@lists.freedesktop.org Cc: Thomas Zimmermann , Jocelyn Falempe , Dave Airlie , Maarten Lankhorst , Maxime Ripard , Simona Vetter , Sam Ravnborg , linux-kernel@vger.kernel.org Subject: [PATCH] drm/mgag200: reject pixel clocks outside PLL range X-Spam-Score: 0.0 (/) X-Authenticated-User: me@berkoc.com X-Sender-Address: me@berkoc.com Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Content-Transfer-Encoding: quoted-printable MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Commit 877507bb954e ("drm/mgag200: Provide per-device callbacks for PIXPLLC") split the PLL compute code into per-model source files. The g200se variant kept the existing permitteddelta sanity check and returns -EINVAL when no register combination matches the requested pixel clock within tolerance, which lets atomic_check reject the mode. The matching helpers in g200wb, g200eh, g200er, g200ev, g200eh3 and g200ew3 omit that check. When the search loop finds no candidate, m, n, p and s stay at their initial zero values and the function still returns success. atomic_update then programs those zero values into the PIXPLLCM/N/P registers, which yields a corrupted output clock on the affected models. Apply the same permitteddelta test (clock * 5 / 1000, matching the g200se reference) in all six helpers so that out-of-range modes are rejected during atomic_check instead of producing garbage register writes during atomic_update. Fixes: 877507bb954e ("drm/mgag200: Provide per-device callbacks for PIXPLLC= ") Cc: stable@vger.kernel.org # v6.1+ Signed-off-by: Berkant Koc --- Build-tested with CONFIG_DRM_MGAG200=3Dm, allmodconfig defaults; no new warnings. checkpatch.pl --no-tree clean (0 errors, 0 warnings). drivers/gpu/drm/mgag200/mgag200_g200eh.c | 8 +++++++- drivers/gpu/drm/mgag200/mgag200_g200eh3.c | 8 +++++++- drivers/gpu/drm/mgag200/mgag200_g200er.c | 8 +++++++- drivers/gpu/drm/mgag200/mgag200_g200ev.c | 8 +++++++- drivers/gpu/drm/mgag200/mgag200_g200ew3.c | 8 +++++++- drivers/gpu/drm/mgag200/mgag200_g200wb.c | 8 +++++++- 6 files changed, 42 insertions(+), 6 deletions(-) diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh.c b/drivers/gpu/drm/mga= g200/mgag200_g200eh.c index d2aa931f579d..2387ff87550a 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200eh.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh.c @@ -51,13 +51,14 @@ static int mgag200_g200eh_pixpllc_atomic_check(struct d= rm_crtc *crtc, struct mgag200_crtc_state *new_mgag200_crtc_state =3D to_mgag200_crtc_sta= te(new_crtc_state); long clock =3D new_crtc_state->mode.clock; struct mgag200_pll_values *pixpllc =3D &new_mgag200_crtc_state->pixpllc; - unsigned int delta, tmpdelta; + unsigned int delta, tmpdelta, permitteddelta; unsigned int testp, testm, testn; unsigned int p, m, n, s; unsigned int computed; =20 m =3D n =3D p =3D s =3D 0; delta =3D 0xffffffff; + permitteddelta =3D clock * 5 / 1000; =20 for (testp =3D 16; testp > 0; testp >>=3D 1) { if (clock * testp > vcomax) @@ -82,6 +83,11 @@ static int mgag200_g200eh_pixpllc_atomic_check(struct dr= m_crtc *crtc, } } =20 + if (delta > permitteddelta) { + pr_warn("PLL delta too large\n"); + return -EINVAL; + } + pixpllc->m =3D m; pixpllc->n =3D n; pixpllc->p =3D p; diff --git a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c b/drivers/gpu/drm/mg= ag200/mgag200_g200eh3.c index 7bea7a728f56..322e93982ea2 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200eh3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200eh3.c @@ -26,13 +26,14 @@ static int mgag200_g200eh3_pixpllc_atomic_check(struct = drm_crtc *crtc, struct mgag200_crtc_state *new_mgag200_crtc_state =3D to_mgag200_crtc_sta= te(new_crtc_state); long clock =3D new_crtc_state->mode.clock; struct mgag200_pll_values *pixpllc =3D &new_mgag200_crtc_state->pixpllc; - unsigned int delta, tmpdelta; + unsigned int delta, tmpdelta, permitteddelta; unsigned int testp, testm, testn; unsigned int p, m, n, s; unsigned int computed; =20 m =3D n =3D p =3D s =3D 0; delta =3D 0xffffffff; + permitteddelta =3D clock * 5 / 1000; testp =3D 0; =20 for (testm =3D 150; testm >=3D 6; testm--) { @@ -59,6 +60,11 @@ static int mgag200_g200eh3_pixpllc_atomic_check(struct d= rm_crtc *crtc, break; } =20 + if (delta > permitteddelta) { + pr_warn("PLL delta too large\n"); + return -EINVAL; + } + pixpllc->m =3D m; pixpllc->n =3D n; pixpllc->p =3D p; diff --git a/drivers/gpu/drm/mgag200/mgag200_g200er.c b/drivers/gpu/drm/mga= g200/mgag200_g200er.c index 8fa8fe943abf..e180db21902b 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200er.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200er.c @@ -69,13 +69,14 @@ static int mgag200_g200er_pixpllc_atomic_check(struct d= rm_crtc *crtc, struct mgag200_crtc_state *new_mgag200_crtc_state =3D to_mgag200_crtc_sta= te(new_crtc_state); long clock =3D new_crtc_state->mode.clock; struct mgag200_pll_values *pixpllc =3D &new_mgag200_crtc_state->pixpllc; - unsigned int delta, tmpdelta; + unsigned int delta, tmpdelta, permitteddelta; int testr, testn, testm, testo; unsigned int p, m, n, s; unsigned int computed, vco; =20 m =3D n =3D p =3D s =3D 0; delta =3D 0xffffffff; + permitteddelta =3D clock * 5 / 1000; =20 for (testr =3D 0; testr < 4; testr++) { if (delta =3D=3D 0) @@ -110,6 +111,11 @@ static int mgag200_g200er_pixpllc_atomic_check(struct = drm_crtc *crtc, } } =20 + if (delta > permitteddelta) { + pr_warn("PLL delta too large\n"); + return -EINVAL; + } + pixpllc->m =3D m; pixpllc->n =3D n; pixpllc->p =3D p; diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ev.c b/drivers/gpu/drm/mga= g200/mgag200_g200ev.c index 3fadbeb10af9..0e882872e968 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ev.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ev.c @@ -57,13 +57,14 @@ static int mgag200_g200ev_pixpllc_atomic_check(struct d= rm_crtc *crtc, struct mgag200_crtc_state *new_mgag200_crtc_state =3D to_mgag200_crtc_sta= te(new_crtc_state); long clock =3D new_crtc_state->mode.clock; struct mgag200_pll_values *pixpllc =3D &new_mgag200_crtc_state->pixpllc; - unsigned int delta, tmpdelta; + unsigned int delta, tmpdelta, permitteddelta; unsigned int testp, testm, testn; unsigned int p, m, n, s; unsigned int computed; =20 m =3D n =3D p =3D s =3D 0; delta =3D 0xffffffff; + permitteddelta =3D clock * 5 / 1000; =20 for (testp =3D 16; testp > 0; testp--) { if (clock * testp > vcomax) @@ -89,6 +90,11 @@ static int mgag200_g200ev_pixpllc_atomic_check(struct dr= m_crtc *crtc, } } =20 + if (delta > permitteddelta) { + pr_warn("PLL delta too large\n"); + return -EINVAL; + } + pixpllc->m =3D m; pixpllc->n =3D n; pixpllc->p =3D p; diff --git a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c b/drivers/gpu/drm/mg= ag200/mgag200_g200ew3.c index e387a455eae5..da8f2a66cde3 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200ew3.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200ew3.c @@ -33,13 +33,14 @@ static int mgag200_g200ew3_pixpllc_atomic_check(struct = drm_crtc *crtc, struct mgag200_crtc_state *new_mgag200_crtc_state =3D to_mgag200_crtc_sta= te(new_crtc_state); long clock =3D new_crtc_state->mode.clock; struct mgag200_pll_values *pixpllc =3D &new_mgag200_crtc_state->pixpllc; - unsigned int delta, tmpdelta; + unsigned int delta, tmpdelta, permitteddelta; unsigned int testp, testm, testn, testp2; unsigned int p, m, n, s; unsigned int computed; =20 m =3D n =3D p =3D s =3D 0; delta =3D 0xffffffff; + permitteddelta =3D clock * 5 / 1000; =20 for (testp =3D 1; testp < 8; testp++) { for (testp2 =3D 1; testp2 < 8; testp2++) { @@ -68,6 +69,11 @@ static int mgag200_g200ew3_pixpllc_atomic_check(struct d= rm_crtc *crtc, } } =20 + if (delta > permitteddelta) { + pr_warn("PLL delta too large\n"); + return -EINVAL; + } + pixpllc->m =3D m; pixpllc->n =3D n; pixpllc->p =3D p; diff --git a/drivers/gpu/drm/mgag200/mgag200_g200wb.c b/drivers/gpu/drm/mga= g200/mgag200_g200wb.c index d847fa8ded8c..ca4775173ff0 100644 --- a/drivers/gpu/drm/mgag200/mgag200_g200wb.c +++ b/drivers/gpu/drm/mgag200/mgag200_g200wb.c @@ -49,13 +49,14 @@ static int mgag200_g200wb_pixpllc_atomic_check(struct d= rm_crtc *crtc, struct mgag200_crtc_state *new_mgag200_crtc_state =3D to_mgag200_crtc_sta= te(new_crtc_state); long clock =3D new_crtc_state->mode.clock; struct mgag200_pll_values *pixpllc =3D &new_mgag200_crtc_state->pixpllc; - unsigned int delta, tmpdelta; + unsigned int delta, tmpdelta, permitteddelta; unsigned int testp, testm, testn; unsigned int p, m, n, s; unsigned int computed; =20 m =3D n =3D p =3D s =3D 0; delta =3D 0xffffffff; + permitteddelta =3D clock * 5 / 1000; =20 for (testp =3D 1; testp < 9; testp++) { if (clock * testp > vcomax) @@ -81,6 +82,11 @@ static int mgag200_g200wb_pixpllc_atomic_check(struct dr= m_crtc *crtc, } } =20 + if (delta > permitteddelta) { + pr_warn("PLL delta too large\n"); + return -EINVAL; + } + pixpllc->m =3D m; pixpllc->n =3D n; pixpllc->p =3D p; --