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 <[email protected]> Reviewed-by: Thierry Reding <[email protected]> Fixes: 2a6d731a8f16 ("drm/simpledrm: Allow physical width and height configuration via panel node") Cc: Rayyan Ansari <[email protected]> Cc: <[email protected]> # v6.4+ --- drivers/gpu/drm/sysfb/simpledrm.c | 49 +++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/sysfb/simpledrm.c b/drivers/gpu/drm/sysfb/simpledrm.c index 15dcafa9d524..6bbe779ec870 100644 --- a/drivers/gpu/drm/sysfb/simpledrm.c +++ b/drivers/gpu/drm/sysfb/simpledrm.c @@ -193,6 +193,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 */ @@ -594,7 +627,7 @@ static struct simpledrm_device *simpledrm_device_create(struct drm_driver *drv, struct drm_sysfb_device *sysfb; 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; @@ -658,8 +691,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.54.0
