diff mbox

[RFC] drm: adv7511/33: Fix adv7511_cec_init() failure handling

Message ID d4e6cae8-f0f7-8ecf-b556-3cb0fa8dc0cc@xs4all.nl (mailing list archive)
State New, archived
Headers show

Commit Message

Hans Verkuil Nov. 17, 2017, 8:43 a.m. UTC
If the device tree for a board did not specify a cec clock, then
adv7511_cec_init would return an error, which would cause adv7511_probe()
to fail and thus there is no HDMI output.

There is no need to have adv7511_probe() fail if the CEC initialization
fails, so just change adv7511_cec_init() to a void function. In addition,
adv7511_cec_init() should just return silently if the cec clock isn't
found and show a message for any other errors.

An otherwise correct cleanup patch from Dan Carpenter turned this broken
failure handling into a kernel Oops, so bisection points to commit
7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL") rather
than 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support").

Based on earlier patches from Arnd and John.

Reported-by: Naresh Kamboju <naresh.kamboju@linaro.org>
Cc: Xinliang Liu <xinliang.liu@linaro.org>
Cc: Dan Carpenter <dan.carpenter@oracle.com>
Cc: Sean Paul <seanpaul@chromium.org>
Cc: Hans Verkuil <hans.verkuil@cisco.com>
Cc: Archit Taneja <architt@codeaurora.org>
Cc: John Stultz <john.stultz@linaro.org>
Link: https://bugs.linaro.org/show_bug.cgi?id=3345
Link: https://lkft.validation.linaro.org/scheduler/job/48017#L3551
Fixes: 7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL")
Fixes: 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support")
Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
---
This rework of Arnd and John's patches goes a bit further and makes
cec_init a void function and just silently exits if there is no cec clock
defined in the dts. I'm sure that's the reason why the kirin board failed
on this. BTW: if the kirin board DOES support cec, then it would be nice
if it can be hooked up in the dts!

I'll test this with my two adv7511/33 boards on Monday.

Regards,

	Hans
---

Comments

Hans Verkuil Nov. 20, 2017, 3:05 p.m. UTC | #1
On 11/17/2017 09:43 AM, Hans Verkuil wrote:
> If the device tree for a board did not specify a cec clock, then
> adv7511_cec_init would return an error, which would cause adv7511_probe()
> to fail and thus there is no HDMI output.
> 
> There is no need to have adv7511_probe() fail if the CEC initialization
> fails, so just change adv7511_cec_init() to a void function. In addition,
> adv7511_cec_init() should just return silently if the cec clock isn't
> found and show a message for any other errors.
> 
> An otherwise correct cleanup patch from Dan Carpenter turned this broken
> failure handling into a kernel Oops, so bisection points to commit
> 7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL") rather
> than 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support").
> 
> Based on earlier patches from Arnd and John.
> 
> Reported-by: Naresh Kamboju <naresh.kamboju@linaro.org>
> Cc: Xinliang Liu <xinliang.liu@linaro.org>
> Cc: Dan Carpenter <dan.carpenter@oracle.com>
> Cc: Sean Paul <seanpaul@chromium.org>
> Cc: Hans Verkuil <hans.verkuil@cisco.com>
> Cc: Archit Taneja <architt@codeaurora.org>
> Cc: John Stultz <john.stultz@linaro.org>
> Link: https://bugs.linaro.org/show_bug.cgi?id=3345
> Link: https://lkft.validation.linaro.org/scheduler/job/48017#L3551
> Fixes: 7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL")
> Fixes: 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support")
> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>

I tested this patch on a Dragonboard and a Renesas Koelsch board. I also forced
errors in parsing the dts or registering the CEC adapter to test those failure
paths on both boards.

So:

Tested-by: Hans Verkuil <hans.verkuil@cisco.com>

Regards,

	Hans

> ---
> This rework of Arnd and John's patches goes a bit further and makes
> cec_init a void function and just silently exits if there is no cec clock
> defined in the dts. I'm sure that's the reason why the kirin board failed
> on this. BTW: if the kirin board DOES support cec, then it would be nice
> if it can be hooked up in the dts!
> 
> I'll test this with my two adv7511/33 boards on Monday.
> 
> Regards,
> 
> 	Hans
> ---
> diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h
> index 543a5eb91624..bc17aa965e58 100644
> --- a/drivers/gpu/drm/bridge/adv7511/adv7511.h
> +++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h
> @@ -374,8 +374,8 @@ struct adv7511 {
>  };
> 
>  #ifdef CONFIG_DRM_I2C_ADV7511_CEC
> -int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
> -		     unsigned int offset);
> +void adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
> +		      unsigned int offset);
>  void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1);
>  #endif
> 
> diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
> index b33d730e4d73..c1cd471d31fa 100644
> --- a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
> +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
> @@ -300,18 +300,20 @@ static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511)
>  	return 0;
>  }
> 
> -int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
> -		     unsigned int offset)
> +void adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
> +		      unsigned int offset)
>  {
>  	int ret = adv7511_cec_parse_dt(dev, adv7511);
> 
>  	if (ret)
> -		return ret;
> +		goto disable_cec;
> 
>  	adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
>  		adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS);
> -	if (IS_ERR(adv7511->cec_adap))
> -		return PTR_ERR(adv7511->cec_adap);
> +	if (IS_ERR(adv7511->cec_adap)) {
> +		ret = PTR_ERR(adv7511->cec_adap);
> +		goto fail;
> +	}
> 
>  	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0);
>  	/* cec soft reset */
> @@ -329,9 +331,15 @@ int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
>  		     ((adv7511->cec_clk_freq / 750000) - 1) << 2);
> 
>  	ret = cec_register_adapter(adv7511->cec_adap, dev);
> -	if (ret) {
> -		cec_delete_adapter(adv7511->cec_adap);
> -		adv7511->cec_adap = NULL;
> -	}
> -	return ret;
> +	if (!ret)
> +		return;
> +	cec_delete_adapter(adv7511->cec_adap);
> +	adv7511->cec_adap = NULL;
> +
> +fail:
> +	dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
> +		 ret);
> +disable_cec:
> +	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
> +		     ADV7511_CEC_CTRL_POWER_DOWN);
>  }
> diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
> index 3a33075dbb22..56eeeea6a1fa 100644
> --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
> +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
> @@ -1202,9 +1202,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
>  	offset = adv7511->type == ADV7533 ? ADV7533_REG_CEC_OFFSET : 0;
> 
>  #ifdef CONFIG_DRM_I2C_ADV7511_CEC
> -	ret = adv7511_cec_init(dev, adv7511, offset);
> -	if (ret)
> -		goto err_unregister_cec;
> +	adv7511_cec_init(dev, adv7511, offset);
>  #else
>  	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
>  		     ADV7511_CEC_CTRL_POWER_DOWN);
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/dri-devel
>
Hans Verkuil Nov. 20, 2017, 3:06 p.m. UTC | #2
On 11/20/2017 04:05 PM, Hans Verkuil wrote:
> On 11/17/2017 09:43 AM, Hans Verkuil wrote:
>> If the device tree for a board did not specify a cec clock, then
>> adv7511_cec_init would return an error, which would cause adv7511_probe()
>> to fail and thus there is no HDMI output.
>>
>> There is no need to have adv7511_probe() fail if the CEC initialization
>> fails, so just change adv7511_cec_init() to a void function. In addition,
>> adv7511_cec_init() should just return silently if the cec clock isn't
>> found and show a message for any other errors.
>>
>> An otherwise correct cleanup patch from Dan Carpenter turned this broken
>> failure handling into a kernel Oops, so bisection points to commit
>> 7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL") rather
>> than 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support").
>>
>> Based on earlier patches from Arnd and John.
>>
>> Reported-by: Naresh Kamboju <naresh.kamboju@linaro.org>
>> Cc: Xinliang Liu <xinliang.liu@linaro.org>
>> Cc: Dan Carpenter <dan.carpenter@oracle.com>
>> Cc: Sean Paul <seanpaul@chromium.org>
>> Cc: Hans Verkuil <hans.verkuil@cisco.com>
>> Cc: Archit Taneja <architt@codeaurora.org>
>> Cc: John Stultz <john.stultz@linaro.org>
>> Link: https://bugs.linaro.org/show_bug.cgi?id=3345
>> Link: https://lkft.validation.linaro.org/scheduler/job/48017#L3551
>> Fixes: 7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL")
>> Fixes: 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support")
>> Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com>
> 
> I tested this patch on a Dragonboard and a Renesas Koelsch board. I also forced
> errors in parsing the dts or registering the CEC adapter to test those failure
> paths on both boards.
> 
> So:
> 
> Tested-by: Hans Verkuil <hans.verkuil@cisco.com>

As far as I am concerned the [RFC] part can be dropped from this patch.

Regards,

	Hans
John Stultz Nov. 20, 2017, 8:13 p.m. UTC | #3
On Fri, Nov 17, 2017 at 12:43 AM, Hans Verkuil <hverkuil@xs4all.nl> wrote:
> diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
> index 3a33075dbb22..56eeeea6a1fa 100644
> --- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
> +++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
> @@ -1202,9 +1202,7 @@ static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
>         offset = adv7511->type == ADV7533 ? ADV7533_REG_CEC_OFFSET : 0;
>
>  #ifdef CONFIG_DRM_I2C_ADV7511_CEC
> -       ret = adv7511_cec_init(dev, adv7511, offset);
> -       if (ret)
> -               goto err_unregister_cec;
> +       adv7511_cec_init(dev, adv7511, offset);
>  #else
>         regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
>                      ADV7511_CEC_CTRL_POWER_DOWN);


One tiny nit-pick I realized I should have made in my patch...

In the !CONFIG_DRM_I2C_ADV7511_CEC, can you just define adv7511_cec_init() as
{
    regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
ADV7511_CEC_CTRL_POWER_DOWN);
}

Then we can call it either way, and don't need to have the ufly
#ifdefs in the adv7511_probe function?

thanks
-john
diff mbox

Patch

diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511.h b/drivers/gpu/drm/bridge/adv7511/adv7511.h
index 543a5eb91624..bc17aa965e58 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511.h
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511.h
@@ -374,8 +374,8 @@  struct adv7511 {
 };

 #ifdef CONFIG_DRM_I2C_ADV7511_CEC
-int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
-		     unsigned int offset);
+void adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
+		      unsigned int offset);
 void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1);
 #endif

diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
index b33d730e4d73..c1cd471d31fa 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c
@@ -300,18 +300,20 @@  static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511)
 	return 0;
 }

-int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
-		     unsigned int offset)
+void adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
+		      unsigned int offset)
 {
 	int ret = adv7511_cec_parse_dt(dev, adv7511);

 	if (ret)
-		return ret;
+		goto disable_cec;

 	adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
 		adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS);
-	if (IS_ERR(adv7511->cec_adap))
-		return PTR_ERR(adv7511->cec_adap);
+	if (IS_ERR(adv7511->cec_adap)) {
+		ret = PTR_ERR(adv7511->cec_adap);
+		goto fail;
+	}

 	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0);
 	/* cec soft reset */
@@ -329,9 +331,15 @@  int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511,
 		     ((adv7511->cec_clk_freq / 750000) - 1) << 2);

 	ret = cec_register_adapter(adv7511->cec_adap, dev);
-	if (ret) {
-		cec_delete_adapter(adv7511->cec_adap);
-		adv7511->cec_adap = NULL;
-	}
-	return ret;
+	if (!ret)
+		return;
+	cec_delete_adapter(adv7511->cec_adap);
+	adv7511->cec_adap = NULL;
+
+fail:
+	dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
+		 ret);
+disable_cec:
+	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
+		     ADV7511_CEC_CTRL_POWER_DOWN);
 }
diff --git a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
index 3a33075dbb22..56eeeea6a1fa 100644
--- a/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
+++ b/drivers/gpu/drm/bridge/adv7511/adv7511_drv.c
@@ -1202,9 +1202,7 @@  static int adv7511_probe(struct i2c_client *i2c, const struct i2c_device_id *id)
 	offset = adv7511->type == ADV7533 ? ADV7533_REG_CEC_OFFSET : 0;

 #ifdef CONFIG_DRM_I2C_ADV7511_CEC
-	ret = adv7511_cec_init(dev, adv7511, offset);
-	if (ret)
-		goto err_unregister_cec;
+	adv7511_cec_init(dev, adv7511, offset);
 #else
 	regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
 		     ADV7511_CEC_CTRL_POWER_DOWN);