The commit 53bdcf5f026c ("drm: sti: fix sub-components bind") moves i2c adapter search and locking from .bind() to .probe(), however proper error path in the modified .probe() is not implemented and leftover of the related error path in .bind() remains. This change fixes these issues.
Fixes: 53bdcf5f026c ("drm: sti: fix sub-components bind") Signed-off-by: Vladimir Zapolskiy vladimir_zapolskiy@mentor.com --- drivers/gpu/drm/sti/sti_hdmi.c | 49 ++++++++++++++++++++++++++---------------- 1 file changed, 31 insertions(+), 18 deletions(-)
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index 09e29e4..c23b580 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -700,18 +700,17 @@ static int sti_hdmi_bind(struct device *dev, struct device *master, void *data)
encoder = sti_hdmi_find_encoder(drm_dev); if (!encoder) - goto err_adapt; + return -EINVAL;
connector = devm_kzalloc(dev, sizeof(*connector), GFP_KERNEL); if (!connector) - goto err_adapt; - + return -EINVAL;
connector->hdmi = hdmi;
bridge = devm_kzalloc(dev, sizeof(*bridge), GFP_KERNEL); if (!bridge) - goto err_adapt; + return -EINVAL;
bridge->driver_private = hdmi; bridge->funcs = &sti_hdmi_bridge_funcs; @@ -748,8 +747,7 @@ err_sysfs: drm_connector_unregister(drm_connector); err_connector: drm_connector_cleanup(drm_connector); -err_adapt: - put_device(&hdmi->ddc_adapt->dev); + return -EINVAL; }
@@ -809,24 +807,29 @@ static int sti_hdmi_probe(struct platform_device *pdev) res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "hdmi-reg"); if (!res) { DRM_ERROR("Invalid hdmi resource\n"); - return -ENOMEM; + ret = -ENOMEM; + goto release_adapter; } hdmi->regs = devm_ioremap_nocache(dev, res->start, resource_size(res)); - if (!hdmi->regs) - return -ENOMEM; + if (!hdmi->regs) { + ret = -ENOMEM; + goto release_adapter; + }
if (of_device_is_compatible(np, "st,stih416-hdmi")) { res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "syscfg"); if (!res) { DRM_ERROR("Invalid syscfg resource\n"); - return -ENOMEM; + ret = -ENOMEM; + goto release_adapter; } hdmi->syscfg = devm_ioremap_nocache(dev, res->start, resource_size(res)); - if (!hdmi->syscfg) - return -ENOMEM; - + if (!hdmi->syscfg) { + ret = -ENOMEM; + goto release_adapter; + } }
hdmi->phy_ops = (struct hdmi_phy_ops *) @@ -836,25 +839,29 @@ static int sti_hdmi_probe(struct platform_device *pdev) hdmi->clk_pix = devm_clk_get(dev, "pix"); if (IS_ERR(hdmi->clk_pix)) { DRM_ERROR("Cannot get hdmi_pix clock\n"); - return PTR_ERR(hdmi->clk_pix); + ret = PTR_ERR(hdmi->clk_pix); + goto release_adapter; }
hdmi->clk_tmds = devm_clk_get(dev, "tmds"); if (IS_ERR(hdmi->clk_tmds)) { DRM_ERROR("Cannot get hdmi_tmds clock\n"); - return PTR_ERR(hdmi->clk_tmds); + ret = PTR_ERR(hdmi->clk_tmds); + goto release_adapter; }
hdmi->clk_phy = devm_clk_get(dev, "phy"); if (IS_ERR(hdmi->clk_phy)) { DRM_ERROR("Cannot get hdmi_phy clock\n"); - return PTR_ERR(hdmi->clk_phy); + ret = PTR_ERR(hdmi->clk_phy); + goto release_adapter; }
hdmi->clk_audio = devm_clk_get(dev, "audio"); if (IS_ERR(hdmi->clk_audio)) { DRM_ERROR("Cannot get hdmi_audio clock\n"); - return PTR_ERR(hdmi->clk_audio); + ret = PTR_ERR(hdmi->clk_audio); + goto release_adapter; }
hdmi->hpd = readl(hdmi->regs + HDMI_STA) & HDMI_STA_HOT_PLUG; @@ -867,7 +874,7 @@ static int sti_hdmi_probe(struct platform_device *pdev) hdmi_irq_thread, IRQF_ONESHOT, dev_name(dev), hdmi); if (ret) { DRM_ERROR("Failed to register HDMI interrupt\n"); - return ret; + goto release_adapter; }
hdmi->reset = devm_reset_control_get(dev, "hdmi"); @@ -878,6 +885,12 @@ static int sti_hdmi_probe(struct platform_device *pdev) platform_set_drvdata(pdev, hdmi);
return component_add(&pdev->dev, &sti_hdmi_ops); + + release_adapter: + if (hdmi->ddc_adapt) + put_device(&hdmi->ddc_adapt->dev); + + return ret; }
static int sti_hdmi_remove(struct platform_device *pdev)
This change is needed to properly lock I2C bus device and driver, which serve DDC lines. Without this change I2C bus driver module may gone in runtime and this won't be noticed by the driver.
Signed-off-by: Vladimir Zapolskiy vladimir_zapolskiy@mentor.com --- drivers/gpu/drm/sti/sti_hdmi.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index c23b580..b892f29a 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -792,13 +792,10 @@ static int sti_hdmi_probe(struct platform_device *pdev)
ddc = of_parse_phandle(pdev->dev.of_node, "ddc", 0); if (ddc) { - hdmi->ddc_adapt = of_find_i2c_adapter_by_node(ddc); - if (!hdmi->ddc_adapt) { - of_node_put(ddc); - return -EPROBE_DEFER; - } - + hdmi->ddc_adapt = of_get_i2c_adapter_by_node(ddc); of_node_put(ddc); + if (!hdmi->ddc_adapt) + return -EPROBE_DEFER; }
hdmi->dev = pdev->dev; @@ -887,8 +884,7 @@ static int sti_hdmi_probe(struct platform_device *pdev) return component_add(&pdev->dev, &sti_hdmi_ops);
release_adapter: - if (hdmi->ddc_adapt) - put_device(&hdmi->ddc_adapt->dev); + i2c_put_adapter(hdmi->ddc_adapt);
return ret; } @@ -897,10 +893,9 @@ static int sti_hdmi_remove(struct platform_device *pdev) { struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev);
- if (hdmi->ddc_adapt) - put_device(&hdmi->ddc_adapt->dev); - + i2c_put_adapter(hdmi->ddc_adapt); component_del(&pdev->dev, &sti_hdmi_ops); + return 0; }
Hi Vladimir,
Thank you for the patches. I will integrate them in the next drm/sti pull request that should be sent by next week.
BR Vincent
-----Original Message----- From: Vladimir Zapolskiy [mailto:vladimir_zapolskiy@mentor.com] Sent: lundi 21 septembre 2015 17:51 To: Benjamin Gaignard; Vincent ABRIOU Cc: David Airlie; dri-devel@lists.freedesktop.org Subject: [PATCH 2/2] drm: sti_hdmi: use of_get_i2c_adapter_by_node interface
This change is needed to properly lock I2C bus device and driver, which serve DDC lines. Without this change I2C bus driver module may gone in runtime and this won't be noticed by the driver.
Signed-off-by: Vladimir Zapolskiy vladimir_zapolskiy@mentor.com
drivers/gpu/drm/sti/sti_hdmi.c | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/sti/sti_hdmi.c b/drivers/gpu/drm/sti/sti_hdmi.c index c23b580..b892f29a 100644 --- a/drivers/gpu/drm/sti/sti_hdmi.c +++ b/drivers/gpu/drm/sti/sti_hdmi.c @@ -792,13 +792,10 @@ static int sti_hdmi_probe(struct platform_device *pdev)
ddc = of_parse_phandle(pdev->dev.of_node, "ddc", 0); if (ddc) {
hdmi->ddc_adapt = of_find_i2c_adapter_by_node(ddc);
if (!hdmi->ddc_adapt) {
of_node_put(ddc);
return -EPROBE_DEFER;
}
hdmi->ddc_adapt = of_get_i2c_adapter_by_node(ddc);
of_node_put(ddc);
if (!hdmi->ddc_adapt)
return -EPROBE_DEFER;
}
hdmi->dev = pdev->dev;
@@ -887,8 +884,7 @@ static int sti_hdmi_probe(struct platform_device *pdev) return component_add(&pdev->dev, &sti_hdmi_ops);
release_adapter:
- if (hdmi->ddc_adapt)
put_device(&hdmi->ddc_adapt->dev);
i2c_put_adapter(hdmi->ddc_adapt);
return ret;
} @@ -897,10 +893,9 @@ static int sti_hdmi_remove(struct platform_device *pdev) { struct sti_hdmi *hdmi = dev_get_drvdata(&pdev->dev);
- if (hdmi->ddc_adapt)
put_device(&hdmi->ddc_adapt->dev);
- i2c_put_adapter(hdmi->ddc_adapt); component_del(&pdev->dev, &sti_hdmi_ops);
- return 0;
}
-- 2.5.0
dri-devel@lists.freedesktop.org