On 5 July 2012 07:20, Linus Walleij <linus.wall...@linaro.org> wrote:

> On Wed, Jun 20, 2012 at 3:04 PM, hongbo.zhang <hongbo.zh...@linaro.org>
> wrote:
>
> >  /*
> > + * Thermal Sensor
> > + */
> > +
> > +#ifdef CONFIG_DB8500_THERMAL
>
> Please don't #ifdef the platform data like this, Documentation/CodingStyle
> dislikes #ifdefs unless needed and this just saves a very marginal piece of
> code in footprint, and will compile just as well even if the driver is not
> selected.
>
Yes I will remove #ifdef

>
> > +static struct resource db8500_thsens_resources[] = {
>
> > +#ifdef CONFIG_DB8500_CPUFREQ_COOLING
>
> Don't #ifdef this either.
>
> Then you will need to add device tree bindings for all this
> platform data sooner or later. Please check with Lee Jones if
> uncertain.
>
OK I will check device tree codes and check with him if any doubt.

>
> > @@ -607,6 +676,8 @@ static struct platform_device
> *snowball_platform_devs[] __initdata = {
> >         &snowball_key_dev,
> >         &snowball_sbnet_dev,
> >         &ab8500_device,
> > +       &u8500_thsens_device,
> > +       &u8500_cpufreq_cooling_device,
> >  };
>
> As you can see the above will break compilation when the drivers
> are not selected if you don't remove the #ifdefs.
>
This is a silly mistake I made :(

>
> > diff --git a/drivers/thermal/cpu_cooling.c
> b/drivers/thermal/cpu_cooling.c
> > index c40d9a0..a8aa10f 100644
> > --- a/drivers/thermal/cpu_cooling.c
> > +++ b/drivers/thermal/cpu_cooling.c
> > @@ -399,8 +399,7 @@ struct thermal_cooling_device
> *cpufreq_cooling_register(
> >         /*Verify that all the entries of freq_clip_table are present*/
> >         for (i = 0; i < tab_size; i++) {
> >                 clip_tab = ((struct freq_clip_table *)&tab_ptr[i]);
> > -               if (!clip_tab->freq_clip_max || !clip_tab->mask_val
> > -                                       || !clip_tab->temp_level) {
> > +               if (!clip_tab->freq_clip_max || !clip_tab->mask_val) {
> >                         kfree(cpufreq_dev);
> >                         return ERR_PTR(-EINVAL);
> >                 }
>
> This looks like a generic patch to cpu_cooling, please break it out
> and send this
> separately to the thermal maintainer and discuss it already today.
>
Yes this should be a separate patch.

>
> > +#include <linux/compiler.h>
>
> Why is this include needed?
> (Just curious.)
>
This is due to some obsolete debuging codes, I forgot to remove this header
file.

>
> > +/* Bind callback functions for thermal zone */
> > +static int db8500_cdev_bind(struct thermal_zone_device *thermal,
> > +                       struct thermal_cooling_device *cdev)
> > +{
> > +       struct db8500_thermal_zone *pzone;
> > +       struct db8500_thsens_platform_data *ptrips;
> > +       int i, j, ret;
> > +
> > +       pzone = (struct db8500_thermal_zone *)thermal->devdata;
> > +       ptrips = pzone->thsens_pdev->dev.platform_data;
> > +
> > +       for (i = 0; i < ptrips->num_trips; i++)
> > +               for (j = 0; j < COOLING_DEV_MAX; j++)
> > +                       if (ptrips->trip_points[i].cooling_dev_name[j]
> && cdev->type)
> > +                               if
> (strcmp(ptrips->trip_points[i].cooling_dev_name[j], cdev->type) == 0) {
> > +                                       ret =
> thermal_zone_bind_cooling_device(thermal, i, cdev);
> > +                                       if (ret)
> > +                                               pr_err("Error binding
> cooling device.\n");
> > +                                       else
> > +                                               pr_info("Cooling device
> %s binded to trip point %d.\n", cdev->type, i);
> > +                               }
> > +
> > +       schedule_work(&pzone->therm_work);
>
> So what happens if this work is scheduled and you suspend before
> it executes?
>
> I think you need a suspend/resume hook to clean that up?
> Probably also in remove().
>
Yes I will consider suspend/resume functions.

>
> > +static irqreturn_t prcmu_low_irq_handler(int irq, void *irq_data)
> > +{
> > +       struct db8500_thermal_zone *pzone = irq_data;
> > +       struct db8500_thsens_platform_data *ptrips;
> > +       unsigned long next_low, next_high;
> > +       int i;
> > +
> > +       ptrips = pzone->thsens_pdev->dev.platform_data;
> > +
> > +       for(i = 0; i < ptrips->num_trips; i++) {
> > +               if (pzone->cur_high == ptrips->trip_points[i].temp)
> > +                       break;
> > +       }
> > +
> > +       if (i <= 1) {
> > +               next_high = ptrips->trip_points[0].temp;
> > +               next_low = PRCMU_DEFAULT_LOW_TEMP;
> > +       } else {
> > +               next_high = ptrips->trip_points[i-1].temp;
> > +               next_low = ptrips->trip_points[i-2].temp;
> > +       }
> > +
> > +       (void) prcmu_stop_temp_sense();
> > +       (void) prcmu_config_hotmon((u8)(next_low/1000),
> (u8)(next_high/1000));
> > +       (void) prcmu_start_temp_sense(PRCMU_DEFAULT_MEASURE_TIME);
> > +
> > +       pzone->cur_high = next_high;
> > +       pzone->cur_low = next_low;
> > +       pr_debug("PRCMU set max %ld, set min %ld\n", next_high,
> next_low);
> > +
> > +       schedule_work(&pzone->therm_work);
> > +
> > +       return IRQ_HANDLED;
> > +}
>
> This also triggers a work that can be inhibited by suspend/resume
> or remove.
>
> > +       schedule_work(&pzone->therm_work);
>
> etc.
>
> > +static int __devinit db8500_thermal_probe(struct platform_device *pdev)
> > +{
> > +       struct db8500_thermal_zone *pzone = NULL;
> > +       struct db8500_thsens_platform_data *ptrips;
> > +       int low_irq, high_irq, ret = 0;
> > +       unsigned long dft_low, dft_high;
> > +
> > +       pr_info("Function db8500_thermal_probe.\n");
> > +
> > +       pzone = kzalloc(sizeof(struct db8500_thermal_zone), GFP_KERNEL);
>
> Use devm_kzalloc().
>
> > +       if (!pzone)
> > +               return ENOMEM;
> > +
> > +       pzone->thsens_pdev = pdev;
> > +
> > +       low_irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_LOW");
> > +       if (low_irq < 0) {
> > +               pr_err("Get IRQ_HOTMON_LOW failed.\n");
> > +               goto exit_irq;
> > +       }
> > +
> > +       ret = request_threaded_irq(low_irq, NULL, prcmu_low_irq_handler,
> > +                               IRQF_NO_SUSPEND, "dbx500_temp_low",
> pzone);
>
> Use devm_request_threaded_irq().
>
> > +       if (ret < 0) {
> > +               pr_err("Failed to allocate temp low irq.\n");
> > +               goto exit_irq;
> > +       }
> > +
> > +       high_irq = platform_get_irq_byname(pdev, "IRQ_HOTMON_HIGH");
> > +       if (high_irq < 0) {
> > +               pr_err("Get IRQ_HOTMON_HIGH failed.\n");
> > +               goto exit_irq;
> > +       }
> > +
> > +       ret = request_threaded_irq(high_irq, NULL,
>  prcmu_high_irq_handler,
> > +                               IRQF_NO_SUSPEND, "dbx500_temp_high",
> pzone);
>
> Use devm_request_threaded_irq()
>
> > +       if (ret < 0) {
> > +               pr_err("Failed to allocate temp high irq.\n");
> > +               goto exit_irq;
> > +       }
>
> (...)
> > +exit_irq:
> > +       if (pzone->low_irq > 0)
> > +               free_irq(pzone->low_irq, pzone);
> > +       if (pzone->low_irq > 0)
> > +               free_irq(pzone->high_irq, pzone);
> > +
> > +       kfree(pzone);
>
> None of this is needed if you use the devm_* functions, they
> are garbage collecting.
>
Good suggestion of using devm_* functions.

>
> > +static int __devexit db8500_thermal_remove(struct platform_device *pdev)
> > +{
> > +       struct db8500_thermal_zone *pzone = th_zone;
> > +
> > +       if (pzone && pzone->therm_dev)
> > +               thermal_zone_device_unregister(pzone->therm_dev);
>
> And...
>
> > +       if (pzone && pzone->low_irq)
> > +               free_irq(pzone->low_irq, pzone);
> > +       if (pzone && pzone->high_irq)
> > +               free_irq(pzone->high_irq, pzone);
> > +       if (pzone)
> > +               kfree(pzone);
>
> None of this either.
>
> > diff --git a/include/linux/platform_data/db8500_thermal.h
> b/include/linux/platform_data/db8500_thermal.h
>
> Thanks for using the proper platform data dir!
>
Thanks for all of you comments.

>
> Yours,
> Linus Walleij
>
_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to