| From fdce891d362019055b6c8af7e855d30111b07a2a Mon Sep 17 00:00:00 2001 | |
| From: Sasha Levin <sashal@kernel.org> | |
| Date: Sat, 12 Sep 2026 11:20:12 -0400 | |
| Subject: drm/sysfb: simpledrm: Improve panel-size validation | |
| From: Thomas Zimmermann <tzimmermann@suse.de> | |
| [ Upstream commit 3a75a0761914d01c7362adf1f906cc1d1762c189 ] | |
| Validate the panel size from the device-tree node against the | |
| limitations of struct drm_display_mode. The type only stores sizes | |
| in 16-bit fields. Fail transparently on errors; do not warn. | |
| v3: | |
| - move comments to a more prominent place (Thierry) | |
| v2: | |
| - only use initialized values in debugging output (Sashiko) | |
| Signed-off-by: Thomas Zimmermann <tzimmermann@suse.de> | |
| Reviewed-by: Thierry Reding <treding@nvidia.com> | |
| Reviewed-by: Maxime Ripard <mripard@kernel.org> | |
| Reviewed-by: Javier Martinez Canillas <javierm@redhat.com> | |
| Fixes: 2a6d731a8f16 ("drm/simpledrm: Allow physical width and height configuration via panel node") | |
| Cc: Rayyan Ansari <rayyan@ansari.sh> | |
| Cc: <stable@vger.kernel.org> # v6.4+ | |
| Link: https://patch.msgid.link/20260625094509.157581-3-tzimmermann@suse.de | |
| Signed-off-by: Sasha Levin <sashal@kernel.org> | |
| --- | |
| drivers/gpu/drm/tiny/simpledrm.c | 49 ++++++++++++++++++++++++++++++-- | |
| 1 file changed, 46 insertions(+), 3 deletions(-) | |
| diff --git a/drivers/gpu/drm/tiny/simpledrm.c b/drivers/gpu/drm/tiny/simpledrm.c | |
| index 30676b1073034..2abe80eec793b 100644 | |
| --- a/drivers/gpu/drm/tiny/simpledrm.c | |
| +++ b/drivers/gpu/drm/tiny/simpledrm.c | |
| @@ -210,6 +210,39 @@ simplefb_get_memory_of(struct drm_device *dev, struct device_node *of_node) | |
| return res; | |
| } | |
| +static int __simplefb_get_panel_size_mm_of(struct drm_device *dev, | |
| + struct device_node *of_panel_node, | |
| + const char *name) | |
| +{ | |
| + int ret; | |
| + u32 value; | |
| + | |
| + ret = of_property_read_u32(of_panel_node, name, &value); | |
| + if (ret) { | |
| + drm_dbg(dev, "simplefb: cannot parse panel %s: error %d\n", | |
| + name, ret); | |
| + return ret; | |
| + } else if (value > U16_MAX) { | |
| + drm_dbg(dev, "simplefb: panel %s of %u exceeds maximum value\n", | |
| + name, value); | |
| + return -EINVAL; | |
| + } | |
| + | |
| + return value; | |
| +} | |
| + | |
| +static int simplefb_get_panel_width_mm_of(struct drm_device *dev, | |
| + struct device_node *of_panel_node) | |
| +{ | |
| + return __simplefb_get_panel_size_mm_of(dev, of_panel_node, "width-mm"); | |
| +} | |
| + | |
| +static int simplefb_get_panel_height_mm_of(struct drm_device *dev, | |
| + struct device_node *of_panel_node) | |
| +{ | |
| + return __simplefb_get_panel_size_mm_of(dev, of_panel_node, "height-mm"); | |
| +} | |
| + | |
| /* | |
| * Simple Framebuffer device | |
| */ | |
| @@ -625,7 +658,7 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, | |
| struct simpledrm_device *sdev; | |
| struct drm_device *dev; | |
| int width, height, stride; | |
| - int width_mm = 0, height_mm = 0; | |
| + u16 width_mm = 0, height_mm = 0; | |
| struct device_node *panel_node; | |
| const struct drm_format_info *format; | |
| struct resource *res, *mem = NULL; | |
| @@ -685,8 +718,18 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, | |
| return ERR_CAST(mem); | |
| panel_node = of_parse_phandle(of_node, "panel", 0); | |
| if (panel_node) { | |
| - simplefb_read_u32_of(dev, panel_node, "width-mm", &width_mm); | |
| - simplefb_read_u32_of(dev, panel_node, "height-mm", &height_mm); | |
| + /* | |
| + * Ignore errors from parsing the physical panel | |
| + * size. Using the pre-initialized sizes of 0 will | |
| + * make drm_sysfb_mode() calculate a default physical | |
| + * size based on a resolution of 96 dpi. | |
| + */ | |
| + ret = simplefb_get_panel_width_mm_of(dev, panel_node); | |
| + if (ret > 0) | |
| + width_mm = ret; | |
| + ret = simplefb_get_panel_height_mm_of(dev, panel_node); | |
| + if (ret > 0) | |
| + height_mm = ret; | |
| of_node_put(panel_node); | |
| } | |
| } else { | |
| -- | |
| 2.53.0 | |