Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > linux.kernel > #1641451
| From | Maxime Ripard <maxime.ripard@free-electrons.com> |
|---|---|
| Newsgroups | linux.kernel |
| Subject | Re: [PATCH] iio: adc: sun4i-gpadc-iio: fix parent device being used in devm function |
| Date | 2017-05-15 11:20 +0200 |
| Message-ID | <tHkky-6aZ-17@gated-at.bofh.it> (permalink) |
| References | <tHiVs-57h-5@gated-at.bofh.it> |
| Organization | linux.* mail to news gateway |
[Multipart message — attachments visible in raw view] - view raw
On Mon, May 15, 2017 at 09:39:02AM +0200, Quentin Schulz wrote:
> For the sake of DT binding stability, this IIO driver is a child of an
> MFD driver for Allwinner A10, A13 and A31 because there already exists a
> DT binding for this IP. The MFD driver has a DT node but the IIO driver
> does not.
>
> The IIO device registers the temperature sensor in the thermal framework
> using the DT node of the parent, the MFD device, so the thermal
> framework could match the phandle to the MFD device in the DT and the
> struct device used to register in the thermal framework.
>
> devm_thermal_zone_of_sensor_register was previously used to register the
> thermal sensor with the parent struct device of the IIO device,
> representing the MFD device. By doing so, we registered actually the
> parent in the devm routine and not the actual IIO device.
>
> This lead to the devm unregister function not being called when the IIO
> module driver is removed. It resulted in the thermal framework still
> polling the get_temp function of the IIO module while the device doesn't
> exist anymore, thus generated a kernel panic.
>
> Use the non-devm function instead and do the unregister manually in the
> remove function.
>
> Fixes: d1caa9905538 ("iio: adc: add support for Allwinner SoCs ADC")
>
> Signed-off-by: Quentin Schulz <quentin.schulz@free-electrons.com>
> Reported-by: Corentin Labbe <clabbe.montjoie@gmail.com>
> ---
> drivers/iio/adc/sun4i-gpadc-iio.c | 31 ++++++++++++++++++-------------
> 1 file changed, 18 insertions(+), 13 deletions(-)
>
> diff --git a/drivers/iio/adc/sun4i-gpadc-iio.c b/drivers/iio/adc/sun4i-gpadc-iio.c
> index b23527309088..0d3df17be405 100644
> --- a/drivers/iio/adc/sun4i-gpadc-iio.c
> +++ b/drivers/iio/adc/sun4i-gpadc-iio.c
> @@ -105,6 +105,7 @@ struct sun4i_gpadc_iio {
> bool no_irq;
> /* prevents concurrent reads of temperature and ADC */
> struct mutex mutex;
> + struct thermal_zone_device *tzd;
> };
>
> #define SUN4I_GPADC_ADC_CHANNEL(_channel, _name) { \
> @@ -502,7 +503,6 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
> {
> struct sun4i_gpadc_iio *info = iio_priv(indio_dev);
> const struct of_device_id *of_dev;
> - struct thermal_zone_device *tzd;
> struct resource *mem;
> void __iomem *base;
> int ret;
> @@ -532,13 +532,13 @@ static int sun4i_gpadc_probe_dt(struct platform_device *pdev,
> if (!IS_ENABLED(CONFIG_THERMAL_OF))
> return 0;
>
> - tzd = devm_thermal_zone_of_sensor_register(&pdev->dev, 0, info,
> - &sun4i_ts_tz_ops);
> - if (IS_ERR(tzd))
> + info->tzd = thermal_zone_of_sensor_register(&pdev->dev, 0, info,
> + &sun4i_ts_tz_ops);
> + if (IS_ERR(info->tzd))
> dev_err(&pdev->dev, "could not register thermal sensor: %ld\n",
> - PTR_ERR(tzd));
> + PTR_ERR(info->tzd));
>
> - return PTR_ERR_OR_ZERO(tzd);
> + return PTR_ERR_OR_ZERO(info->tzd);
> }
>
> static int sun4i_gpadc_probe_mfd(struct platform_device *pdev,
> @@ -584,15 +584,14 @@ static int sun4i_gpadc_probe_mfd(struct platform_device *pdev,
> * of_node, and the device from this driver as third argument to
> * return the temperature.
> */
> - struct thermal_zone_device *tzd;
> - tzd = devm_thermal_zone_of_sensor_register(pdev->dev.parent, 0,
> - info,
> - &sun4i_ts_tz_ops);
> - if (IS_ERR(tzd)) {
> + info->tzd = thermal_zone_of_sensor_register(pdev->dev.parent, 0,
> + info,
> + &sun4i_ts_tz_ops);
> + if (IS_ERR(info->tzd)) {
> dev_err(&pdev->dev,
> "could not register thermal sensor: %ld\n",
> - PTR_ERR(tzd));
> - return PTR_ERR(tzd);
> + PTR_ERR(info->tzd));
> + return PTR_ERR(info->tzd);
> }
> } else {
> indio_dev->num_channels =
> @@ -688,6 +687,12 @@ static int sun4i_gpadc_remove(struct platform_device *pdev)
>
> pm_runtime_put(&pdev->dev);
> pm_runtime_disable(&pdev->dev);
> +
> + if (pdev->dev.of_node)
> + thermal_zone_of_sensor_unregister(&pdev->dev, info->tzd);
> + else
> + thermal_zone_of_sensor_unregister(pdev->dev.parent, info->tzd);
> +
Can't we just store the device used to create the zone in the
structure as well, that would avoid that non-trivial logic.
Maxime
--
Maxime Ripard, Free Electrons
Embedded Linux and Kernel engineering
http://free-electrons.com
Back to linux.kernel | Previous | Next — Previous in thread | Next in thread | Find similar | Unroll thread
[PATCH] iio: adc: sun4i-gpadc-iio: fix parent device being used in devm function Quentin Schulz <quentin.schulz@free-electrons.com> - 2017-05-15 09:50 +0200
Re: [PATCH] iio: adc: sun4i-gpadc-iio: fix parent device being used in devm function Maxime Ripard <maxime.ripard@free-electrons.com> - 2017-05-15 11:20 +0200
Re: [PATCH] iio: adc: sun4i-gpadc-iio: fix parent device being used in devm function Quentin Schulz <quentin.schulz@free-electrons.com> - 2017-05-15 11:20 +0200
Re: [PATCH] iio: adc: sun4i-gpadc-iio: fix parent device being used in devm function Maxime Ripard <maxime.ripard@free-electrons.com> - 2017-05-16 11:40 +0200
csiph-web