Commit 2a0a3ae1 authored by Laurent Pinchart's avatar Laurent Pinchart Committed by Tomi Valkeinen

drm/omap: dss: Cleanup DSS ports on initialisation failure

When the DSS initialises its output DPI and SDI ports, failures don't
clean up previous successfully initialised ports. This can lead to
resource leak or memory corruption. Fix it.
Reported-by: default avatarHans Verkuil <hverkuil@xs4all.nl>
Signed-off-by: default avatarLaurent Pinchart <laurent.pinchart@ideasonboard.com>
Reviewed-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
Acked-by: default avatarSam Ravnborg <sam@ravnborg.org>
Tested-by: default avatarSebastian Reichel <sebastian.reichel@collabora.com>
Reviewed-by: default avatarSebastian Reichel <sebastian.reichel@collabora.com>
Signed-off-by: default avatarTomi Valkeinen <tomi.valkeinen@ti.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20200226112514.12455-22-laurent.pinchart@ideasonboard.com
parent 5e20bdf3
...@@ -1151,46 +1151,38 @@ static const struct dss_features dra7xx_dss_feats = { ...@@ -1151,46 +1151,38 @@ static const struct dss_features dra7xx_dss_feats = {
.has_lcd_clk_src = true, .has_lcd_clk_src = true,
}; };
static int dss_init_ports(struct dss_device *dss) static void __dss_uninit_ports(struct dss_device *dss, unsigned int num_ports)
{ {
struct platform_device *pdev = dss->pdev; struct platform_device *pdev = dss->pdev;
struct device_node *parent = pdev->dev.of_node; struct device_node *parent = pdev->dev.of_node;
struct device_node *port; struct device_node *port;
unsigned int i; unsigned int i;
int r;
for (i = 0; i < dss->feat->num_ports; i++) { for (i = 0; i < num_ports; i++) {
port = of_graph_get_port_by_id(parent, i); port = of_graph_get_port_by_id(parent, i);
if (!port) if (!port)
continue; continue;
switch (dss->feat->ports[i]) { switch (dss->feat->ports[i]) {
case OMAP_DISPLAY_TYPE_DPI: case OMAP_DISPLAY_TYPE_DPI:
r = dpi_init_port(dss, pdev, port, dss->feat->model); dpi_uninit_port(port);
if (r)
return r;
break; break;
case OMAP_DISPLAY_TYPE_SDI: case OMAP_DISPLAY_TYPE_SDI:
r = sdi_init_port(dss, pdev, port); sdi_uninit_port(port);
if (r)
return r;
break; break;
default: default:
break; break;
} }
} }
return 0;
} }
static void dss_uninit_ports(struct dss_device *dss) static int dss_init_ports(struct dss_device *dss)
{ {
struct platform_device *pdev = dss->pdev; struct platform_device *pdev = dss->pdev;
struct device_node *parent = pdev->dev.of_node; struct device_node *parent = pdev->dev.of_node;
struct device_node *port; struct device_node *port;
int i; unsigned int i;
int r;
for (i = 0; i < dss->feat->num_ports; i++) { for (i = 0; i < dss->feat->num_ports; i++) {
port = of_graph_get_port_by_id(parent, i); port = of_graph_get_port_by_id(parent, i);
...@@ -1199,15 +1191,32 @@ static void dss_uninit_ports(struct dss_device *dss) ...@@ -1199,15 +1191,32 @@ static void dss_uninit_ports(struct dss_device *dss)
switch (dss->feat->ports[i]) { switch (dss->feat->ports[i]) {
case OMAP_DISPLAY_TYPE_DPI: case OMAP_DISPLAY_TYPE_DPI:
dpi_uninit_port(port); r = dpi_init_port(dss, pdev, port, dss->feat->model);
if (r)
goto error;
break; break;
case OMAP_DISPLAY_TYPE_SDI: case OMAP_DISPLAY_TYPE_SDI:
sdi_uninit_port(port); r = sdi_init_port(dss, pdev, port);
if (r)
goto error;
break; break;
default: default:
break; break;
} }
} }
return 0;
error:
__dss_uninit_ports(dss, i);
return r;
}
static void dss_uninit_ports(struct dss_device *dss)
{
__dss_uninit_ports(dss, dss->feat->num_ports);
} }
static int dss_video_pll_probe(struct dss_device *dss) static int dss_video_pll_probe(struct dss_device *dss)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment