From 39de6194131c155901f96686a063212656d80c2e Mon Sep 17 00:00:00 2001 From: Darren Etheridge Date: Fri, 21 Jun 2013 13:52:27 -0500 Subject: drm/tilcdc fixing i2c/slave initialization race In certain senarios drm will initialize before i2c this means that i2c slave devices like the nxp tda998x will fail to be probed. This patch detects this condition then defers the probe of the slave device and the tilcdc main driver. Signed-off-by: Darren Etheridge Acked-by: Rob Clark Signed-off-by: Dave Airlie --- drivers/gpu/drm/tilcdc/tilcdc_slave.c | 53 +++++++++++++++++++---------------- 1 file changed, 29 insertions(+), 24 deletions(-) (limited to 'drivers/gpu/drm/tilcdc/tilcdc_slave.c') diff --git a/drivers/gpu/drm/tilcdc/tilcdc_slave.c b/drivers/gpu/drm/tilcdc/tilcdc_slave.c index 8bf4fd19181..dfffaf01402 100644 --- a/drivers/gpu/drm/tilcdc/tilcdc_slave.c +++ b/drivers/gpu/drm/tilcdc/tilcdc_slave.c @@ -298,6 +298,7 @@ static int slave_probe(struct platform_device *pdev) struct tilcdc_module *mod; struct pinctrl *pinctrl; uint32_t i2c_phandle; + struct i2c_adapter *slavei2c; int ret = -EINVAL; /* bail out early if no DT data: */ @@ -306,44 +307,48 @@ static int slave_probe(struct platform_device *pdev) return -ENXIO; } - slave_mod = kzalloc(sizeof(*slave_mod), GFP_KERNEL); - if (!slave_mod) - return -ENOMEM; - - mod = &slave_mod->base; - - tilcdc_module_init(mod, "slave", &slave_module_ops); - - pinctrl = devm_pinctrl_get_select_default(&pdev->dev); - if (IS_ERR(pinctrl)) - dev_warn(&pdev->dev, "pins are not configured\n"); - + /* Bail out early if i2c not specified */ if (of_property_read_u32(node, "i2c", &i2c_phandle)) { dev_err(&pdev->dev, "could not get i2c bus phandle\n"); - goto fail; + return ret; } - mod->preferred_bpp = slave_info.bpp; - i2c_node = of_find_node_by_phandle(i2c_phandle); if (!i2c_node) { dev_err(&pdev->dev, "could not get i2c bus node\n"); - goto fail; + return ret; } - slave_mod->i2c = of_find_i2c_adapter_by_node(i2c_node); - if (!slave_mod->i2c) { + /* but defer the probe if it can't be initialized it might come later */ + slavei2c = of_find_i2c_adapter_by_node(i2c_node); + of_node_put(i2c_node); + + if (!slavei2c) { + ret = -EPROBE_DEFER; + tilcdc_slave_probedefer(true); dev_err(&pdev->dev, "could not get i2c\n"); - goto fail; + return ret; } - of_node_put(i2c_node); + slave_mod = kzalloc(sizeof(*slave_mod), GFP_KERNEL); + if (!slave_mod) + return -ENOMEM; - return 0; + mod = &slave_mod->base; -fail: - slave_destroy(mod); - return ret; + mod->preferred_bpp = slave_info.bpp; + + slave_mod->i2c = slavei2c; + + tilcdc_module_init(mod, "slave", &slave_module_ops); + + pinctrl = devm_pinctrl_get_select_default(&pdev->dev); + if (IS_ERR(pinctrl)) + dev_warn(&pdev->dev, "pins are not configured\n"); + + tilcdc_slave_probedefer(false); + + return 0; } static int slave_remove(struct platform_device *pdev) -- cgit v1.2.3-70-g09d2