Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

thermal/drivers/rcar_gen3_thermal: Fix device initialization

The thermal zone is registered before the device is register and the
thermal coefficients are calculated, providing a window for very
incorrect readings.

The reason why the zone was register before the device was fully
initialized was that the presence of the set_trips() callback is used to
determine if the driver supports interrupt or not, as it is not defined
if the device is incapable of interrupts.

Fix this by using the operations structure in the private data instead
of the zone to determine if interrupts are available or not, and
initialize the device before registering the zone.

Signed-off-by: Niklas Söderlund <niklas.soderlund+renesas@ragnatech.se>
Reviewed-by: Wolfram Sang <wsa+renesas@sang-engineering.com>
Link: https://lore.kernel.org/r/20230208190333.3159879-4-niklas.soderlund+renesas@ragnatech.se
Signed-off-by: Daniel Lezcano <daniel.lezcano@linaro.org>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Niklas Söderlund and committed by
Rafael J. Wysocki
47b2d3d2 aef43e04

+13 -10
+13 -10
drivers/thermal/rcar_gen3_thermal.c
··· 89 89 struct rcar_gen3_thermal_tsc *tscs[TSC_MAX_NUM]; 90 90 struct thermal_zone_device_ops ops; 91 91 unsigned int num_tscs; 92 - void (*thermal_init)(struct rcar_gen3_thermal_tsc *tsc); 92 + void (*thermal_init)(struct rcar_gen3_thermal_priv *priv, 93 + struct rcar_gen3_thermal_tsc *tsc); 93 94 int ptat[3]; 94 95 }; 95 96 ··· 241 240 for (i = 0; i < priv->num_tscs; i++) { 242 241 status = rcar_gen3_thermal_read(priv->tscs[i], REG_GEN3_IRQSTR); 243 242 rcar_gen3_thermal_write(priv->tscs[i], REG_GEN3_IRQSTR, 0); 244 - if (status) 243 + if (status && priv->tscs[i]->zone) 245 244 thermal_zone_device_update(priv->tscs[i]->zone, 246 245 THERMAL_EVENT_UNSPECIFIED); 247 246 } ··· 312 311 return true; 313 312 } 314 313 315 - static void rcar_gen3_thermal_init_r8a7795es1(struct rcar_gen3_thermal_tsc *tsc) 314 + static void rcar_gen3_thermal_init_r8a7795es1(struct rcar_gen3_thermal_priv *priv, 315 + struct rcar_gen3_thermal_tsc *tsc) 316 316 { 317 317 rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, CTSR_THBGR); 318 318 rcar_gen3_thermal_write(tsc, REG_GEN3_CTSR, 0x0); ··· 324 322 325 323 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0x3F); 326 324 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0); 327 - if (tsc->zone->ops->set_trips) 325 + if (priv->ops.set_trips) 328 326 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, 329 327 IRQ_TEMPD1 | IRQ_TEMP2); 330 328 ··· 340 338 usleep_range(1000, 2000); 341 339 } 342 340 343 - static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_tsc *tsc) 341 + static void rcar_gen3_thermal_init(struct rcar_gen3_thermal_priv *priv, 342 + struct rcar_gen3_thermal_tsc *tsc) 344 343 { 345 344 u32 reg_val; 346 345 ··· 353 350 354 351 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQCTL, 0); 355 352 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQMSK, 0); 356 - if (tsc->zone->ops->set_trips) 353 + if (priv->ops.set_trips) 357 354 rcar_gen3_thermal_write(tsc, REG_GEN3_IRQEN, 358 355 IRQ_TEMPD1 | IRQ_TEMP2); 359 356 ··· 517 514 for (i = 0; i < priv->num_tscs; i++) { 518 515 struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; 519 516 517 + priv->thermal_init(priv, tsc); 518 + rcar_gen3_thermal_calc_coefs(priv, tsc, *ths_tj_1); 519 + 520 520 zone = devm_thermal_of_zone_register(dev, i, tsc, &priv->ops); 521 521 if (IS_ERR(zone)) { 522 522 dev_err(dev, "Sensor %u: Can't register thermal zone\n", i); ··· 527 521 goto error_unregister; 528 522 } 529 523 tsc->zone = zone; 530 - 531 - priv->thermal_init(tsc); 532 - rcar_gen3_thermal_calc_coefs(priv, tsc, *ths_tj_1); 533 524 534 525 tsc->zone->tzp->no_hwmon = false; 535 526 ret = thermal_add_hwmon_sysfs(tsc->zone); ··· 565 562 for (i = 0; i < priv->num_tscs; i++) { 566 563 struct rcar_gen3_thermal_tsc *tsc = priv->tscs[i]; 567 564 568 - priv->thermal_init(tsc); 565 + priv->thermal_init(priv, tsc); 569 566 } 570 567 571 568 return 0;