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

thermal: fix multiple disbalanced device node counters

Here on function return all temporarily used device nodes shall
decrement their usage counter. The problems are found with device
nodes allocated by for_each_child_of_node(), of_parse_phandle()
and of_find_node_by_name(), fix all problems at once.

Signed-off-by: Vladimir Zapolskiy <vz@mleia.com>
Cc: devicetree@vger.kernel.org
Cc: Zhang Rui <rui.zhang@intel.com>
Cc: Eduardo Valentin <edubezval@gmail.com>
Signed-off-by: Eduardo Valentin <edubezval@gmail.com>

authored by

Vladimir Zapolskiy and committed by
Eduardo Valentin
c2aad93c 689bd24c

+32 -8
+32 -8
drivers/thermal/of-thermal.c
··· 387 387 int (*get_trend)(void *, long *)) 388 388 { 389 389 struct device_node *np, *child, *sensor_np; 390 + struct thermal_zone_device *tzd = ERR_PTR(-ENODEV); 390 391 391 392 np = of_find_node_by_name(NULL, "thermal-zones"); 392 393 if (!np) 393 394 return ERR_PTR(-ENODEV); 394 395 395 - if (!dev || !dev->of_node) 396 + if (!dev || !dev->of_node) { 397 + of_node_put(np); 396 398 return ERR_PTR(-EINVAL); 399 + } 397 400 398 - sensor_np = dev->of_node; 401 + sensor_np = of_node_get(dev->of_node); 399 402 400 403 for_each_child_of_node(np, child) { 401 404 struct of_phandle_args sensor_specs; ··· 425 422 } 426 423 427 424 if (sensor_specs.np == sensor_np && id == sensor_id) { 428 - of_node_put(np); 429 - return thermal_zone_of_add_sensor(child, sensor_np, 430 - data, 431 - get_temp, 432 - get_trend); 425 + tzd = thermal_zone_of_add_sensor(child, sensor_np, 426 + data, 427 + get_temp, 428 + get_trend); 429 + of_node_put(sensor_specs.np); 430 + of_node_put(child); 431 + goto exit; 433 432 } 433 + of_node_put(sensor_specs.np); 434 434 } 435 + exit: 436 + of_node_put(sensor_np); 435 437 of_node_put(np); 436 438 437 - return ERR_PTR(-ENODEV); 439 + return tzd; 438 440 } 439 441 EXPORT_SYMBOL_GPL(thermal_zone_of_sensor_register); 440 442 ··· 631 623 632 624 /* Required for cooling map matching */ 633 625 trip->np = np; 626 + of_node_get(np); 634 627 635 628 return 0; 636 629 } ··· 739 730 return tz; 740 731 741 732 free_tbps: 733 + for (i = 0; i < tz->num_tbps; i++) 734 + of_node_put(tz->tbps[i].cooling_device); 742 735 kfree(tz->tbps); 743 736 free_trips: 737 + for (i = 0; i < tz->ntrips; i++) 738 + of_node_put(tz->trips[i].np); 744 739 kfree(tz->trips); 740 + of_node_put(gchild); 745 741 free_tz: 746 742 kfree(tz); 747 743 of_node_put(child); ··· 756 742 757 743 static inline void of_thermal_free_zone(struct __thermal_zone *tz) 758 744 { 745 + int i; 746 + 747 + for (i = 0; i < tz->num_tbps; i++) 748 + of_node_put(tz->tbps[i].cooling_device); 759 749 kfree(tz->tbps); 750 + for (i = 0; i < tz->ntrips; i++) 751 + of_node_put(tz->trips[i].np); 760 752 kfree(tz->trips); 761 753 kfree(tz); 762 754 } ··· 834 814 /* attempting to build remaining zones still */ 835 815 } 836 816 } 817 + of_node_put(np); 837 818 838 819 return 0; 839 820 840 821 exit_free: 822 + of_node_put(child); 823 + of_node_put(np); 841 824 of_thermal_free_zone(tz); 842 825 843 826 /* no memory available, so free what we have built */ ··· 882 859 kfree(zone->ops); 883 860 of_thermal_free_zone(zone->devdata); 884 861 } 862 + of_node_put(np); 885 863 }