thermal: tango: add resume support
PATCH RESEND v2 1/1 thermal: tango: add resume support
From: Marc Gonzalez <[email protected]>
When this platform is suspended, firmware powers the entire SoC down, except a few hardware blocks waiting for wakeup events. And there is no context to save for this particular block.
Therefore, there is nothing useful for the driver to do on suspend; so we define a NULL suspend hook. On resume, the driver initializes the block exactly as is done in the probe callback.
---
Add Kevin's Reviewed-by tag. Eduardo/Zhang, can you pick this patch up for 4.8?
--- drivers/thermal/tango_thermal.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-)
drivers/thermal/tango_thermal.c +25 -2
@@ -64,6 +64,12 @@ static const struct thermal_zone_of_device_ops ops = { .get_temp = tango_get_temp, }; +static void tango_thermal_init (struct tango_thermal_priv *priv) +{ +writel (0 , priv->base +TEMPSI_CFG ); +writel (CMD_ON , priv->base +TEMPSI_CMD ); +} +static int tango_thermal_probe (struct platform_device *pdev) {struct resource *res;
@@ -79,14 +85,30 @@ static int tango_thermal_probe(struct platform_device *pdev)if (IS_ERR (priv->base))return PTR_ERR (priv->base); +platform_set_drvdata (pdev, priv); priv->thresh_idx =IDX_MIN ; -writel (0 , priv->base +TEMPSI_CFG ); -writel (CMD_ON , priv->base +TEMPSI_CMD ); +tango_thermal_init (priv); tzdev =devm_thermal_zone_of_sensor_register (&pdev->dev,0 , priv, &ops);return PTR_ERR_OR_ZERO (tzdev); } +#ifdef CONFIG_PM_SLEEP +static int tango_thermal_resume (struct device *dev) +{ +struct tango_thermal_priv *priv =dev_get_drvdata (dev); +tango_thermal_init (priv); + +return 0 ; +} + +static SIMPLE_DEV_PM_OPS(tango_thermal_pm, NULL, tango_thermal_resume); + +#define DEV_PM_OPS &tango_thermal_pm +#else +#define DEV_PM_OPS NULL +#endif +static const struct of_device_id tango_sensor_ids[] = { { .compatible ="sigma,smp8758-thermal" ,
@@ -99,6 +121,7 @@ static struct platform_driver tango_thermal_driver = { .driver = { .name = "tango-thermal", .of_match_table = tango_sensor_ids, + .pm = DEV_PM_OPS, }, };
Signature · 1 line
2.8.2
PATCH RESEND v2 1/1 thermal: tango: add resume support
Quoted 45 lines · Mason
From: Marc Gonzalez <[email protected]>
When this platform is suspended, firmware powers the entire SoC down, except a few hardware blocks waiting for wakeup events. And there is no context to save for this particular block.
Therefore, there is nothing useful for the driver to do on suspend; so we define a NULL suspend hook. On resume, the driver initializes the block exactly as is done in the probe callback.
Reviewed-by Kevin Hilman <[email protected]>Signed-off-by Marc Gonzalez <[email protected]>---
Add Kevin's Reviewed-by tag. Eduardo/Zhang, can you pick this patch up for 4.8?--- drivers/thermal/tango_thermal.c | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-)drivers/thermal/tango_thermal.c +8
-2@@ -64,6 +64,12 @@ static const struct thermal_zone_of_device_ops ops = { .get_temp = tango_get_temp, }; +static void tango_thermal_init (struct tango_thermal_priv *priv) +{ +writel (0 , priv->base +TEMPSI_CFG ); +writel (CMD_ON , priv->base +TEMPSI_CMD ); +} +static int tango_thermal_probe (struct platform_device *pdev) {struct resource *res;@@ -79,14 +85,30 @@ static int tango_thermal_probe(struct platform_device *pdev)if (IS_ERR (priv->base))return PTR_ERR (priv->base); +platform_set_drvdata (pdev, priv); priv->thresh_idx =IDX_MIN ; -writel (0 , priv->base +TEMPSI_CFG ); -writel (CMD_ON , priv->base +TEMPSI_CMD ); +tango_thermal_init (priv);
drivers/thermal/tango_thermal.c static int tango_thermal_probe(struct platform_device *pdev) · line 100
Quoted 10 lines
drivers/thermal/tango_thermal.c +5
-0tzdev =devm_thermal_zone_of_sensor_register (&pdev->dev,0 , priv, &ops);return PTR_ERR_OR_ZERO (tzdev); } +#ifdef CONFIG_PM_SLEEP +static int tango_thermal_resume (struct device *dev) +{ +struct tango_thermal_priv *priv =dev_get_drvdata (dev); +tango_thermal_init (priv);
checkpatch will warn about this. You're supposed to separate the local variable declarations and code by a single blank line.
drivers/thermal/tango_thermal.c static int tango_thermal_probe(struct platform_device *pdev) · line 110
Quoted 10 lines
drivers/thermal/tango_thermal.c +10
-0+ +return 0 ; +} + +static SIMPLE_DEV_PM_OPS(tango_thermal_pm, NULL, tango_thermal_resume); + +#define DEV_PM_OPS &tango_thermal_pm +#else +#define DEV_PM_OPS NULL +#endif
In my experience it's often not useful to #ifdef the struct pm_ops. These days you almost certainly want PM enabled, and the conditional doesn't save you all that much in the first place, because it's not unlikely for this to fit into some of the space that would be padded out anyway.
As a side-note, I've noticed that this driver has the following dependencies:
depends on ARCH_TANGO || COMPILE_TEST
which, last I checked, is probably going to fail on some architectures because you need at least another one on HAS_IOMEM (for readl() and writel()). That's a pre-existing problem, of course, so should be fixed in a separate patch.
Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160718/b630d14e/attachment.sig>
PATCH RESEND v2 1/1 thermal: tango: add resume support
Quoted 8 lines · CEST Thierry Reding
Quoted 8 lines
drivers/thermal/tango_thermal.c +8
-0+ +return 0 ; +} + +static SIMPLE_DEV_PM_OPS(tango_thermal_pm, NULL, tango_thermal_resume); + +#define DEV_PM_OPS &tango_thermal_pm +#else
Quoted 8 lines
drivers/thermal/tango_thermal.c static int tango_thermal_probe(struct platform_device *pdev) · line 110
Quoted 2 lines
drivers/thermal/tango_thermal.c +2
-0+#define DEV_PM_OPS NULL +#endif In my experience it's often not useful to #ifdef the struct
pm_ops. These days you almost certainly want PM enabled, and the conditional doesn't save you all that much in the first place, because it's not unlikely for this to fit into some of the space that would be padded out anyway.
This will also generate a warning when CONFIG_PM_SLEEP is not set. Better write this as
#define DEV_PM_OPS (IS_ENABLED(CONFIG_PM_SLEEP) ? &tango_thermal_pm : NULL)
so the compiler can drop the variable definition when it's not needed.
Quoted 9 lines
As a side-note, I've noticed that this driver has the following dependencies:
depends on ARCH_TANGO || COMPILE_TESTwhich, last I checked, is probably going to fail on some architectures because you need at least another one on
HAS_IOMEM(forreadl()andwritel()). That's a pre-existing problem, of course, so should be fixed in a separate patch.
No need, we just merged a patch to no longer allow COMPILE_TEST on arch/um/, so we can safely rely on MMIO to be available for COMPILE_TEST.
Arnd
PATCH RESEND v2 1/1 thermal: tango: add resume support
Quoted 19 lines · Arnd Bergmann
Quoted 8 lines · CEST Thierry Reding
Quoted 8 lines
drivers/thermal/tango_thermal.c +8
-0+ +return 0 ; +} + +static SIMPLE_DEV_PM_OPS(tango_thermal_pm, NULL, tango_thermal_resume); + +#define DEV_PM_OPS &tango_thermal_pm +#else Quoted 8 lines
drivers/thermal/tango_thermal.c static int tango_thermal_probe(struct platform_device *pdev) · line 110
Quoted 2 lines
drivers/thermal/tango_thermal.c +2
-0+#define DEV_PM_OPS NULL +#endif In my experience it's often not useful to #ifdef the struct
pm_ops. These days you almost certainly want PM enabled, and the conditional doesn't save you all that much in the first place, because it's not unlikely for this to fit into some of the space that would be padded out anyway.
Quoted 7 lines
This will also generate a warning when
CONFIG_PM_SLEEPis not set. Better write this as#define
DEV_PM_OPS(IS_ENABLED(CONFIG_PM_SLEEP)?&tango_thermal_pm: NULL)so the compiler can drop the variable definition when it's not needed.
My suggestion was to define tango_thermal_pm unconditionally to avoid any of these tricks. For any real use-case in which the 92 bytes for the struct dev_pm_ops would matter you most likely want PM_SLEEP anyway, so I don't really see why we would even want to make it optional.
Quoted 5 lines
Quoted 5 lines
As a side-note, I've noticed that this driver has the following dependencies:
depends on ARCH_TANGO || COMPILE_TEST
Quoted 7 lines
Quoted 4 lines
which, last I checked, is probably going to fail on some architectures because you need at least another one on
HAS_IOMEM(forreadl()andwritel()). That's a pre-existing problem, of course, so should be fixed in a separate patch.No need, we just merged a patch to no longer allow
COMPILE_TESTonarch/um/, so we can safely rely on MMIO to be available forCOMPILE_TEST.
I thought at least S390 didn't have readl() and writel() either, at least when PCI wasn't enabled, or some such.
Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160718/dca40322/attachment.sig>
PATCH RESEND v2 1/1 thermal: tango: add resume support
Quoted 25 lines · CEST Thierry Reding
Quoted 24 lines · Arnd Bergmann
Quoted 8 lines · CEST Thierry Reding
Quoted 8 lines
drivers/thermal/tango_thermal.c +8
-0+ +return 0 ; +} + +static SIMPLE_DEV_PM_OPS(tango_thermal_pm, NULL, tango_thermal_resume); + +#define DEV_PM_OPS &tango_thermal_pm +#else Quoted 8 lines
drivers/thermal/tango_thermal.c static int tango_thermal_probe(struct platform_device *pdev) · line 110
Quoted 2 lines
drivers/thermal/tango_thermal.c +2
-0+#define DEV_PM_OPS NULL +#endif In my experience it's often not useful to #ifdef the struct
pm_ops. These days you almost certainly want PM enabled, and the conditional doesn't save you all that much in the first place, because it's not unlikely for this to fit into some of the space that would be padded out anyway.This will also generate a warning when
CONFIG_PM_SLEEPis not set. Better write this as#define
DEV_PM_OPS(IS_ENABLED(CONFIG_PM_SLEEP)?&tango_thermal_pm: NULL)
Quoted 7 lines
Quoted 2 lines
so the compiler can drop the variable definition when it's not needed.
My suggestion was to define
tango_thermal_pmunconditionally to avoid any of these tricks. For any real use-case in which the 92 bytes for the structdev_pm_opswould matter you most likely wantPM_SLEEPanyway, so I don't really see why we would even want to make it optional.
Sure, leaving it unconditional works too.
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
As a side-note, I've noticed that this driver has the following dependencies:
depends on ARCH_TANGO || COMPILE_TESTwhich, last I checked, is probably going to fail on some architectures because you need at least another one on
HAS_IOMEM(forreadl()andwritel()). That's a pre-existing problem, of course, so should be fixed in a separate patch.
Quoted 5 lines
Quoted 2 lines
No need, we just merged a patch to no longer allow
COMPILE_TESTonarch/um/, so we can safely rely on MMIO to be available forCOMPILE_TEST.I thought at least S390 didn't have
readl()andwritel()either, at least when PCI wasn't enabled, or some such.
Yes, but they've never complained about COMPILE_TEST breakage because of that. Tile is in the same boat too in some configurations.
Arnd
PATCH RESEND v2 1/1 thermal: tango: add resume support
Quoted 46 lines · Arnd Bergmann
Quoted 25 lines · CEST Thierry Reding
Quoted 24 lines · Arnd Bergmann
Quoted 8 lines · CEST Thierry Reding
Quoted 8 lines
drivers/thermal/tango_thermal.c +8
-0+ +return 0 ; +} + +static SIMPLE_DEV_PM_OPS(tango_thermal_pm, NULL, tango_thermal_resume); + +#define DEV_PM_OPS &tango_thermal_pm +#else Quoted 8 lines
drivers/thermal/tango_thermal.c static int tango_thermal_probe(struct platform_device *pdev) · line 110
Quoted 2 lines
drivers/thermal/tango_thermal.c +2
-0+#define DEV_PM_OPS NULL +#endif In my experience it's often not useful to #ifdef the struct
pm_ops. These days you almost certainly want PM enabled, and the conditional doesn't save you all that much in the first place, because it's not unlikely for this to fit into some of the space that would be padded out anyway.This will also generate a warning when
CONFIG_PM_SLEEPis not set. Better write this as#define
DEV_PM_OPS(IS_ENABLED(CONFIG_PM_SLEEP)?&tango_thermal_pm: NULL)Quoted 7 lines
Quoted 2 lines
so the compiler can drop the variable definition when it's not needed.
My suggestion was to define
tango_thermal_pmunconditionally to avoid any of these tricks. For any real use-case in which the 92 bytes for the structdev_pm_opswould matter you most likely wantPM_SLEEPanyway, so I don't really see why we would even want to make it optional.Sure, leaving it unconditional works too.
Quoted 10 lines
Quoted 10 lines
Quoted 9 lines
As a side-note, I've noticed that this driver has the following dependencies:
depends on ARCH_TANGO || COMPILE_TESTwhich, last I checked, is probably going to fail on some architectures because you need at least another one on
HAS_IOMEM(forreadl()andwritel()). That's a pre-existing problem, of course, so should be fixed in a separate patch.
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
No need, we just merged a patch to no longer allow
COMPILE_TESTonarch/um/, so we can safely rely on MMIO to be available forCOMPILE_TEST.I thought at least S390 didn't have
readl()andwritel()either, at least when PCI wasn't enabled, or some such.Yes, but they've never complained about
COMPILE_TESTbreakage because of that. Tile is in the same boat too in some configurations.
Ah, okay. I remember running into this occasionally when doing randconfig builds on S390. That was many moons ago, so perhaps it's not an issue anymore, and maybe I've become overly cautious about the COMPILE_TEST dependency.
Thierry
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160718/a8f6b2c4/attachment.sig>
PATCH v3 1/1 thermal: tango: add resume support
In reply to MasonFrom: Marc Gonzalez <[email protected]>
When this platform is suspended, firmware powers the entire SoC down, except a few hardware blocks waiting for wakeup events. And there is no context to save for this particular block.
Therefore, there is nothing useful for the driver to do on suspend; so we define a NULL suspend hook. On resume, the driver initializes the block exactly as is done in the probe callback.
---
Changes in v3
Drop the DEV_PM_OPS macro, which caused some confusion.
Note: tango_thermal_pm struct only exists when CONFIG_PM_SLEEP is defined @Kevin, can I add your Reviewed-by tag back?
--- drivers/thermal/tango_thermal.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)
drivers/thermal/tango_thermal.c +21 -2
@@ -64,6 +64,12 @@ static const struct thermal_zone_of_device_ops ops = { .get_temp = tango_get_temp, }; +static void tango_thermal_init (struct tango_thermal_priv *priv) +{ +writel (0 , priv->base +TEMPSI_CFG ); +writel (CMD_ON , priv->base +TEMPSI_CMD ); +} +static int tango_thermal_probe (struct platform_device *pdev) {struct resource *res;
@@ -79,14 +85,24 @@ static int tango_thermal_probe(struct platform_device *pdev)if (IS_ERR (priv->base))return PTR_ERR (priv->base); +platform_set_drvdata (pdev, priv); priv->thresh_idx =IDX_MIN ; -writel (0 , priv->base +TEMPSI_CFG ); -writel (CMD_ON , priv->base +TEMPSI_CMD ); +tango_thermal_init (priv); tzdev =devm_thermal_zone_of_sensor_register (&pdev->dev,0 , priv, &ops);return PTR_ERR_OR_ZERO (tzdev); } +#ifdef CONFIG_PM_SLEEP +static int tango_thermal_resume (struct device *dev) +{ +tango_thermal_init (dev_get_drvdata (dev)); +return 0 ; +} + +static SIMPLE_DEV_PM_OPS(tango_thermal_pm, NULL, tango_thermal_resume); +#endif +static const struct of_device_id tango_sensor_ids[] = { { .compatible ="sigma,smp8758-thermal" ,
@@ -99,6 +115,9 @@ static struct platform_driver tango_thermal_driver = { .driver = { .name = "tango-thermal", .of_match_table = tango_sensor_ids, +#ifdef CONFIG_PM_SLEEP + .pm = &tango_thermal_pm, +#endif }, };
Signature · 1 line
2.9.0
PATCH v3 1/1 thermal: tango: add resume support
Quoted 11 lines · Mason
From: Marc Gonzalez <[email protected]>
When this platform is suspended, firmware powers the entire SoC down, except a few hardware blocks waiting for wakeup events. And there is no context to save for this particular block.
Therefore, there is nothing useful for the driver to do on suspend; so we define a NULL suspend hook. On resume, the driver initializes the block exactly as is done in the probe callback.
Signed-off-by Marc Gonzalez <[email protected]>
Quoted 8 lines
---
Changes in v3
Drop theDEV_PM_OPSmacro, which caused some confusion.
Note:tango_thermal_pmstruct only exists whenCONFIG_PM_SLEEPis defined @Kevin, can I add your Reviewed-by tag back?--- drivers/thermal/tango_thermal.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.infradead.org/pipermail/linux-arm-kernel/attachments/20160720/37477eea/attachment.sig>
PATCH v3 1/1 thermal: tango: add resume support
In reply to MasonQuoted 50 lines · Mason
From: Marc Gonzalez <[email protected]>
When this platform is suspended, firmware powers the entire SoC down, except a few hardware blocks waiting for wakeup events. And there is no context to save for this particular block.
Therefore, there is nothing useful for the driver to do on suspend; so we define a NULL suspend hook. On resume, the driver initializes the block exactly as is done in the probe callback.
Signed-off-by Marc Gonzalez <[email protected]>---
Changes in v3
Drop theDEV_PM_OPSmacro, which caused some confusion.
Note:tango_thermal_pmstruct only exists whenCONFIG_PM_SLEEPis defined @Kevin, can I add your Reviewed-by tag back?--- drivers/thermal/tango_thermal.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)drivers/thermal/tango_thermal.c +8
-2@@ -64,6 +64,12 @@ static const struct thermal_zone_of_device_ops ops = { .get_temp = tango_get_temp, }; +static void tango_thermal_init (struct tango_thermal_priv *priv) +{ +writel (0 , priv->base +TEMPSI_CFG ); +writel (CMD_ON , priv->base +TEMPSI_CMD ); +} +static int tango_thermal_probe (struct platform_device *pdev) {struct resource *res;@@ -79,14 +85,24 @@ static int tango_thermal_probe(struct platform_device *pdev)if (IS_ERR (priv->base))return PTR_ERR (priv->base); +platform_set_drvdata (pdev, priv); priv->thresh_idx =IDX_MIN ; -writel (0 , priv->base +TEMPSI_CFG ); -writel (CMD_ON , priv->base +TEMPSI_CMD ); +tango_thermal_init (priv); tzdev =devm_thermal_zone_of_sensor_register (&pdev->dev,0 , priv, &ops);return PTR_ERR_OR_ZERO (tzdev); }
drivers/thermal/tango_thermal.c static int tango_thermal_probe(struct platform_device *pdev) · line 104
Quoted 10 lines
drivers/thermal/tango_thermal.c +9
-0+#ifdef CONFIG_PM_SLEEP +static int tango_thermal_resume (struct device *dev) +{ +tango_thermal_init (dev_get_drvdata (dev)); +return 0 ; +} + +static SIMPLE_DEV_PM_OPS(tango_thermal_pm, NULL, tango_thermal_resume); +#endif
#else
#define tango_thermal_resume NULL
#endif
And then move the SIMPLE_DEV_PM_OPS here...
drivers/thermal/tango_thermal.c static struct platform_driver tango_thermal_driver = { · line 120
Quoted 11 lines
drivers/thermal/tango_thermal.c +4
-0+static const struct of_device_id tango_sensor_ids[] = { { .compatible ="sigma,smp8758-thermal" ,@@ -99,6 +115,9 @@ static struct platform_driver tango_thermal_driver = { .driver = { .name = "tango-thermal", .of_match_table = tango_sensor_ids, +#ifdef CONFIG_PM_SLEEP + .pm = &tango_thermal_pm, +#endif
... which allows you to get rid of the ugly ifdef here. (c.f. CodingStyle, Chapter 20,)
Kevin
PATCH v3 1/1 thermal: tango: add resume support
Quoted 16 lines · Kevin Hilman
drivers/thermal/tango_thermal.c static int tango_thermal_probe(struct platform_device *pdev) · line 104
Quoted 9 lines · Mason
drivers/thermal/tango_thermal.c +9
-0+#ifdef CONFIG_PM_SLEEP +static int tango_thermal_resume (struct device *dev) +{ +tango_thermal_init (dev_get_drvdata (dev)); +return 0 ; +} + +static SIMPLE_DEV_PM_OPS(tango_thermal_pm, NULL, tango_thermal_resume); +#endif #else
#definetango_thermal_resumeNULL
#endif
Quoted 1 line
And then move the
SIMPLE_DEV_PM_OPShere...
Moving the SIMPLE_DEV_PM_OPS macro outside the CONFIG_PM_SLEEP guard would unconditionally define a struct dev_pm_ops, which just wastes space when CONFIG_PM_SLEEP is undefined (if I'm not mistaken).
That's why I put SIMPLE_DEV_PM_OPS inside the CONFIG_PM_SLEEP guard.
Quoted 6 lines
Quoted 6 lines
drivers/thermal/tango_thermal.c +1
-0+static const struct of_device_id tango_sensor_ids[] = { { .compatible ="sigma,smp8758-thermal" ,@@ -99,6 +115,9 @@ static struct platform_driver tango_thermal_driver = { .driver = {
Quoted 8 lines
drivers/thermal/tango_thermal.c static struct platform_driver tango_thermal_driver = { · line 120
Quoted 5 lines
drivers/thermal/tango_thermal.c +3
-0.name = "tango-thermal", .of_match_table = tango_sensor_ids, +#ifdef CONFIG_PM_SLEEP + .pm = &tango_thermal_pm, +#endif ... which allows you to get rid of the ugly ifdef here. (c.f. CodingStyle, Chapter 20,)
The previous solution (v2) avoided duplicating the ifdef block, but Arnd and Thierry objected to the code. Later, they agreed that it should work; but if they didn't catch the code's intent at a glance, maybe there is a problem with it anyway.
What do you think?
I copied the DEV_PM_OPS "trick" from drivers/thermal/ti-soc-thermal/ti-bandgap.c (which was done by Eduardo, a thermal maintainer, so maybe he prefers that solution after all? commit 8feaf0ce1a043)
Regards.
PATCH v3 1/1 thermal: tango: add resume support
Quoted 4 lines · CEST Mason
Quoted 2 lines · Kevin Hilman
Mason wrote:
Quoted 13 lines
Quoted 5 lines
Quoted 5 lines
drivers/thermal/tango_thermal.c +5
-0+#ifdef CONFIG_PM_SLEEP +static int tango_thermal_resume (struct device *dev) +{ +tango_thermal_init (dev_get_drvdata (dev)); +return 0 ;Quoted 8 lines
drivers/thermal/tango_thermal.c static int tango_thermal_probe(struct platform_device *pdev) · line 104
Quoted 4 lines
drivers/thermal/tango_thermal.c +4
-0+} + +static SIMPLE_DEV_PM_OPS(tango_thermal_pm, NULL, tango_thermal_resume); +#endif #else
#definetango_thermal_resumeNULL
#endif
That's what SIMPLE_DEV_PM_OPS does internally already.
Quoted 7 lines
Quoted 1 line
And then move the
SIMPLE_DEV_PM_OPShere...Moving the
SIMPLE_DEV_PM_OPSmacro outside theCONFIG_PM_SLEEPguard would unconditionally define a structdev_pm_ops, which just wastes space whenCONFIG_PM_SLEEPis undefined (if I'm not mistaken).That's why I put
SIMPLE_DEV_PM_OPSinside theCONFIG_PM_SLEEPguard.
If you want to avoid the extra few bytes, just use the trick I suggested:
.pm = IS_ENABLED(CONFIG_PM_SLEEP) ? &tango_thermal_pm : NULL,
Quoted 20 lines
Quoted 6 lines
Quoted 6 lines
drivers/thermal/tango_thermal.c +1
-0+static const struct of_device_id tango_sensor_ids[] = { { .compatible ="sigma,smp8758-thermal" ,@@ -99,6 +115,9 @@ static struct platform_driver tango_thermal_driver = { .driver = {Quoted 8 lines
drivers/thermal/tango_thermal.c static struct platform_driver tango_thermal_driver = { · line 120
Quoted 5 lines
drivers/thermal/tango_thermal.c +3
-0.name = "tango-thermal", .of_match_table = tango_sensor_ids, +#ifdef CONFIG_PM_SLEEP + .pm = &tango_thermal_pm, +#endif ... which allows you to get rid of the ugly ifdef here. (c.f. CodingStyle, Chapter 20,)
The previous solution (v2) avoided duplicating the ifdef block, but Arnd and Thierry objected to the code. Later, they agreed that it should work; but if they didn't catch the code's intent at a glance, maybe there is a problem with it anyway.
Quoted 5 lines
What do you think?
I copied the
DEV_PM_OPS"trick" fromdrivers/thermal/ti-soc-thermal/ti-bandgap.c(which was done by Eduardo, a thermal maintainer, so maybe he prefers that solution after all? commit8feaf0ce1a043)
You should basically never have that #ifdef inside of the platform_driver definition. The normal way to do it is to have __maybe_unused markers for the functions so gcc can silently drop them when they are unused, or to have (slightly uglier and easier to get wrong) #ifdef around the function, but not around the references, but nowhere else.
The SIMPLE_DEV_PM_OPS macro is suboptimal because it requires the __maybe_unused tags and because it leaves more data around than necessary. Feel free to suggest improvements for those macros (others have tried before and failed because of the hundreds or thousands of users that exist), just don't try to be extra clever in your one driver, it would only make it harder for readers to understand.
Arnd
PATCH v3 1/1 thermal: tango: add resume support
Quoted 6 lines · Arnd Bergmann
Quoted 4 lines · CEST Mason
Moving the
SIMPLE_DEV_PM_OPSmacro outside theCONFIG_PM_SLEEPguard would unconditionally define a structdev_pm_ops, which just wastes space whenCONFIG_PM_SLEEPis undefined (if I'm not mistaken).
Quoted 6 lines
Quoted 1 line
That's why I put
SIMPLE_DEV_PM_OPSinside theCONFIG_PM_SLEEPguard.If you want to avoid the extra few bytes, just use the trick I suggested:
.pm =
IS_ENABLED(CONFIG_PM_SLEEP)?&tango_thermal_pm: NULL,
This would achieve the same result as the solution I proposed in my v2 patch, right?
So you're saying you prefer the IS_ENABLED macro over using #ifdef ... #else define stuff as NULL #endif
Did I get that right?
Eduardo, Zhang, what do thermal maintainers prefer?
Quoted 2 lines
You should basically never have that #ifdef inside of the
platform_driverdefinition.
Except when the fields don't exist, like the bug I introduced in struct smp_operations (which you fixed).
Regards.
PATCH v3 1/1 thermal: tango: add resume support
Quoted 15 lines · CEST Mason
Quoted 6 lines · Arnd Bergmann
Quoted 4 lines · CEST Mason
Moving the
SIMPLE_DEV_PM_OPSmacro outside theCONFIG_PM_SLEEPguard would unconditionally define a structdev_pm_ops, which just wastes space whenCONFIG_PM_SLEEPis undefined (if I'm not mistaken).Quoted 6 lines
Quoted 1 line
That's why I put
SIMPLE_DEV_PM_OPSinside theCONFIG_PM_SLEEPguard.If you want to avoid the extra few bytes, just use the trick I suggested:
.pm =
IS_ENABLED(CONFIG_PM_SLEEP)?&tango_thermal_pm: NULL,
Quoted 7 lines
This would achieve the same result as the solution I proposed in my v2 patch, right?
So you're saying you prefer the
IS_ENABLEDmacro over using #ifdef ... #else define stuff as NULL #endifDid I get that right?
Yes, but I'd also prefer not to hide the operations structure at all and just rely on the __maybe_unused (ideally) or #ifdef (not as good, but commonly used) to leave out the functions.
Quoted 7 lines
Eduardo, Zhang, what do thermal maintainers prefer?
Quoted 2 lines
You should basically never have that #ifdef inside of the
platform_driverdefinition.Except when the fields don't exist, like the bug I introduced in struct
smp_operations(which you fixed).
Right.
Arnd
Zhang Rui
reviewerPATCH v3 1/1 thermal: tango: add resume support
Quoted 24 lines · Arnd Bergmann
Quoted 23 lines · CEST Mason
Quoted 10 lines · Arnd Bergmann
Quoted 7 lines · CEST Mason
Moving the
SIMPLE_DEV_PM_OPSmacro outside theCONFIG_PM_SLEEPguard
would unconditionally define a structdev_pm_ops, which just wastes
space whenCONFIG_PM_SLEEPis undefined (if I'm not mistaken).Quoted 7 lines
Quoted 2 lines
That's why I put
SIMPLE_DEV_PM_OPSinside theCONFIG_PM_SLEEPguard.If you want to avoid the extra few bytes, just use the trick I suggested:
??????.pm =
IS_ENABLED(CONFIG_PM_SLEEP)?&tango_thermal_pm:
NULL,This would achieve the same result as the solution I proposed in my v2 patch, right?
Quoted 9 lines
Quoted 4 lines
So you're saying you prefer the
IS_ENABLEDmacro over using #ifdef ... #else define stuff as NULL #endifDid I get that right?
Yes, but I'd also prefer not to hide the operations structure at all and just rely on the
__maybe_unused(ideally) or #ifdef (not as good, but commonly used) to leave out the functions.
IMO, the typical way is to use #ifdef for the pm callbacks, and leave SIMPLE_DEV_PM_OPS outside the #ifdef.
For example,?drivers/ata/ahci_imx.c.
thanks,
rui
Quoted 11 lines
Quoted 8 lines
Eduardo, Zhang, what do thermal maintainers prefer?
Quoted 3 lines
You should basically never have that #ifdef inside of the
platform_driverdefinition.Except when the fields don't exist, like the bug I introduced in struct
smp_operations(which you fixed).Right.
Arnd
PATCH v3 1/1 thermal: tango: add resume support
Quoted 29 lines · CEST Zhang Rui
Quoted 28 lines · Arnd Bergmann
Quoted 27 lines · CEST Mason
Quoted 10 lines · Arnd Bergmann
Quoted 7 lines · CEST Mason
Moving the
SIMPLE_DEV_PM_OPSmacro outside theCONFIG_PM_SLEEPguard
would unconditionally define a structdev_pm_ops, which just wastes
space whenCONFIG_PM_SLEEPis undefined (if I'm not mistaken).Quoted 7 lines
Quoted 2 lines
That's why I put
SIMPLE_DEV_PM_OPSinside theCONFIG_PM_SLEEPguard.If you want to avoid the extra few bytes, just use the trick I suggested:
.pm =
IS_ENABLED(CONFIG_PM_SLEEP)?&tango_thermal_pm:
NULL,This would achieve the same result as the solution I proposed in my v2 patch, right?
So you're saying you prefer the
IS_ENABLEDmacro over using #ifdef ... #else define stuff as NULL #endifDid I get that right?
Quoted 9 lines
Quoted 5 lines
Yes, but I'd also prefer not to hide the operations structure at all and just rely on the
__maybe_unused(ideally) or #ifdef (not as good, but commonly used) to leave out the functions.IMO, the typical way is to use #ifdef for the pm callbacks, and leave
SIMPLE_DEV_PM_OPSoutside the #ifdef.
For example,drivers/ata/ahci_imx.c.
Lots of drivers do it like that, the main downside I see is that a lot of them also get it wrong and use incorrect #ifdef guards, either checking the wrong Kconfig symbol, or hiding the wrong subset of functions.
Arnd
Zhang Rui
reviewerPATCH v3 1/1 thermal: tango: add resume support
Quoted 45 lines · Arnd Bergmann
Quoted 44 lines · CEST Zhang Rui
Quoted 42 lines · Arnd Bergmann
Quoted 28 lines · CEST Mason
Quoted 18 lines · Arnd Bergmann
Quoted 11 lines · CEST Mason
Moving the
SIMPLE_DEV_PM_OPSmacro outside theCONFIG_PM_SLEEP
guard
would unconditionally define a structdev_pm_ops, which just
wastes
space whenCONFIG_PM_SLEEPis undefined (if I'm not mistaken).Quoted 3 lines
That's why I put
SIMPLE_DEV_PM_OPSinside theCONFIG_PM_SLEEP
guard.Quoted 6 lines
If you want to avoid the extra few bytes, just use the trick I
suggested:??????.pm =
IS_ENABLED(CONFIG_PM_SLEEP)?&tango_thermal_pm:
NULL,Quoted 7 lines
This would achieve the same result as the solution I proposed in my v2 patch, right?
So you're saying you prefer the
IS_ENABLEDmacro over using #ifdef ... #else define stuff as NULL #endifDid I get that right?
Yes, but I'd also prefer not to hide the operations structure at all and just rely on the
__maybe_unused(ideally) or #ifdef (not as good, but commonly used) to leave out the functions.
Quoted 8 lines
Quoted 5 lines
IMO, the typical way is to use #ifdef for the pm callbacks, and leave
SIMPLE_DEV_PM_OPSoutside the #ifdef.
For example,drivers/ata/ahci_imx.c.Lots of drivers do it like that, the main downside I see is that a lot of them also get it wrong and use incorrect #ifdef guards, either checking the wrong
Kconfigsymbol,
This also happens when IS_ENABLED macro is used.
Quoted 3 lines
or hiding the wrong
subset of functions.
This also sounds a driver bug to me, and the driver should get fixed. For us, it's not a problem if we do it right here, right? :)
thanks,
rui
PATCH v3 1/1 thermal: tango: add resume support
Quoted 51 lines · CEST Zhang Rui
Quoted 50 lines · Arnd Bergmann
Quoted 49 lines · CEST Zhang Rui
Quoted 33 lines · Arnd Bergmann
Quoted 31 lines · CEST Mason
Quoted 18 lines · Arnd Bergmann
Quoted 11 lines · CEST Mason
Moving the
SIMPLE_DEV_PM_OPSmacro outside theCONFIG_PM_SLEEP
guard
would unconditionally define a structdev_pm_ops, which just
wastes
space whenCONFIG_PM_SLEEPis undefined (if I'm not mistaken).Quoted 3 lines
That's why I put
SIMPLE_DEV_PM_OPSinside theCONFIG_PM_SLEEP
guard.Quoted 6 lines
If you want to avoid the extra few bytes, just use the trick I
suggested:.pm =
IS_ENABLED(CONFIG_PM_SLEEP)?&tango_thermal_pm:
NULL,This would achieve the same result as the solution I proposed in my v2 patch, right?
Quoted 9 lines
Quoted 4 lines
So you're saying you prefer the
IS_ENABLEDmacro over using #ifdef ... #else define stuff as NULL #endifDid I get that right?
Yes, but I'd also prefer not to hide the operations structure at all and just rely on the
__maybe_unused(ideally) or #ifdef (not as good, but commonly used) to leave out the functions.IMO, the typical way is to use #ifdef for the pm callbacks, and leave
SIMPLE_DEV_PM_OPSoutside the #ifdef.
For example,drivers/ata/ahci_imx.c.
Quoted 5 lines
Quoted 3 lines
Lots of drivers do it like that, the main downside I see is that a lot of them also get it wrong and use incorrect #ifdef guards, either checking the wrong
Kconfigsymbol,This also happens when
IS_ENABLEDmacro is used.
Right, but not with the __maybe_unused annotations.
Quoted 5 lines
Quoted 3 lines
or hiding the wrong
subset of functions.This also sounds a driver bug to me, and the driver should get fixed. For us, it's not a problem if we do it right here, right? :)
I think the ideal is to have only one set of conditionals in each driver, so at least you don't get a mismatch between them.
SIMPLE_DEV_PM_OPS uses conditional evaluation (but does not show the reference to the compiler). Annotating the functions as __maybe_unused lets the compiler decide for itself if they should be dropped or not, which means we use only the conditional inside of SIMPLE_DEV_PM_OPS.
Ideally, SIMPLE_DEV_PM_OPS itself should have used an IS_ENABLED() check instead of the #ifdef, that would have made it possible to just leave the function always defined with no __maybe_unused, but still have it dropped from the object code without a warning when there is no runtime reference.
Arnd
PATCH v3 1/1 thermal: tango: add resume support
Quoted 9 lines · Arnd Bergmann
I think the ideal is to have only one set of conditionals in each driver, so at least you don't get a mismatch between them.
SIMPLE_DEV_PM_OPSuses conditional evaluation (but does not show the reference to the compiler). Annotating the functions as__maybe_unusedlets the compiler decide for itself if they should be dropped or not, which means we use only the conditional inside ofSIMPLE_DEV_PM_OPS.
Quoted 5 lines
Ideally,
SIMPLE_DEV_PM_OPSitself should have used anIS_ENABLED()check instead of the #ifdef, that would have made it possible to just leave the function always defined with no__maybe_unused, but still have it dropped from the object code without a warning when there is no runtime reference.
I'm not sure my trivial issue deserves this much discussion. I just want the patch to be upstream in some form.
I'll submit one more patch, with SIMPLE_DEV_PM_OPS used unconditionally, and annotate the resume function with __maybe_unused.
This will waste the space of the struct on systems where S3 is disabled, but it seems to be the preferred solution, IIUC.
Regards.
PATCH v4 1/1 thermal: tango: add resume support
In reply to MasonWhen this platform is suspended, firmware powers the entire SoC down, except a few hardware blocks waiting for wakeup events. There is no context to save for this particular block.
Therefore, there is nothing useful for the driver to do on suspend; so we define a NULL suspend hook. On resume, the driver initializes the block exactly as is done in the probe callback.
---
Earlier versions of this patch were reviewed by Kevin and Thierry. The current form is preferred by Arnd.
--- drivers/thermal/tango_thermal.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)
drivers/thermal/tango_thermal.c +17 -2
@@ -64,6 +64,12 @@ static const struct thermal_zone_of_device_ops ops = { .get_temp = tango_get_temp, }; +static void tango_thermal_init (struct tango_thermal_priv *priv) +{ +writel (0 , priv->base +TEMPSI_CFG ); +writel (CMD_ON , priv->base +TEMPSI_CMD ); +} +static int tango_thermal_probe (struct platform_device *pdev) {struct resource *res;
@@ -79,14 +85,22 @@ static int tango_thermal_probe(struct platform_device *pdev)if (IS_ERR (priv->base))return PTR_ERR (priv->base); +platform_set_drvdata (pdev, priv); priv->thresh_idx =IDX_MIN ; -writel (0 , priv->base +TEMPSI_CFG ); -writel (CMD_ON , priv->base +TEMPSI_CMD ); +tango_thermal_init (priv); tzdev =devm_thermal_zone_of_sensor_register (&pdev->dev,0 , priv, &ops);return PTR_ERR_OR_ZERO (tzdev); } +static int __maybe_unused tango_thermal_resume (struct device *dev) +{ +tango_thermal_init (dev_get_drvdata (dev)); +return 0 ; +} + +static SIMPLE_DEV_PM_OPS(tango_thermal_pm, NULL, tango_thermal_resume); +static const struct of_device_id tango_sensor_ids[] = { { .compatible ="sigma,smp8758-thermal" ,
@@ -99,6 +113,7 @@ static struct platform_driver tango_thermal_driver = { .driver = { .name = "tango-thermal", .of_match_table = tango_sensor_ids, + .pm = &tango_thermal_pm, }, };
Signature · 1 line
2.9.0
PATCH v4 1/1 thermal: tango: add resume support
Quoted 9 lines · Marc Gonzalez
When this platform is suspended, firmware powers the entire SoC down, except a few hardware blocks waiting for wakeup events. There is no context to save for this particular block.
Therefore, there is nothing useful for the driver to do on suspend; so we define a NULL suspend hook. On resume, the driver initializes the block exactly as is done in the probe callback.
Signed-off-by Marc Gonzalez <[email protected]>
Quoted 56 lines
---
Earlier versions of this patch were reviewed by Kevin and Thierry. The current form is preferred by Arnd.--- drivers/thermal/tango_thermal.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-)drivers/thermal/tango_thermal.c +17
-2@@ -64,6 +64,12 @@ static const struct thermal_zone_of_device_ops ops = { .get_temp = tango_get_temp, }; +static void tango_thermal_init (struct tango_thermal_priv *priv) +{ +writel (0 , priv->base +TEMPSI_CFG ); +writel (CMD_ON , priv->base +TEMPSI_CMD ); +} +static int tango_thermal_probe (struct platform_device *pdev) {struct resource *res;@@ -79,14 +85,22 @@ static int tango_thermal_probe(struct platform_device *pdev)if (IS_ERR (priv->base))return PTR_ERR (priv->base); +platform_set_drvdata (pdev, priv); priv->thresh_idx =IDX_MIN ; -writel (0 , priv->base +TEMPSI_CFG ); -writel (CMD_ON , priv->base +TEMPSI_CMD ); +tango_thermal_init (priv); tzdev =devm_thermal_zone_of_sensor_register (&pdev->dev,0 , priv, &ops);return PTR_ERR_OR_ZERO (tzdev); } +static int __maybe_unused tango_thermal_resume (struct device *dev) +{ +tango_thermal_init (dev_get_drvdata (dev)); +return 0 ; +} + +static SIMPLE_DEV_PM_OPS(tango_thermal_pm, NULL, tango_thermal_resume); +static const struct of_device_id tango_sensor_ids[] = { { .compatible ="sigma,smp8758-thermal" ,@@ -99,6 +113,7 @@ static struct platform_driver tango_thermal_driver = { .driver = { .name = "tango-thermal", .of_match_table = tango_sensor_ids, + .pm = &tango_thermal_pm, }, };