[PATCH ath-next v2] wifi: ath12k: add basic hwmon temperature reporting

Maharaja Kennadyrajan quic_mkenna at quicinc.com
Fri Feb 20 01:55:18 PST 2026


On 2/20/2026 3:14 AM, Jeff Johnson wrote:
> On 2/18/2026 11:34 PM, Maharaja Kennadyrajan wrote:
>> +int ath12k_thermal_register(struct ath12k_base *ab)
>> +{
>> +	struct ath12k *ar;
>> +	int i, j, ret;
>> +
>> +	if (!IS_REACHABLE(CONFIG_HWMON))
>> +		return 0;
>> +
>> +	for (i = 0; i < ab->num_radios; i++) {
>> +		ar = ab->pdevs[i].ar;
>> +		if (!ar)
>> +			continue;
>> +
>> +		ar->thermal.hwmon_dev =
>> +			hwmon_device_register_with_groups(&ar->ah->hw->wiphy->dev,
>> +							  "ath12k_hwmon", ar,
>> +							  ath12k_hwmon_groups);
> ath10k and ath11k use devm_hwmon_device_register_with_groups().
> why doesn't ath12k do the same?
> then the code below and in _unregister() that calls hwmon_device_unregister()
> would be unnecessary since the objects would be reclaimed when the dev is
> destroyed.


ath12k_thermal_register() loops all radios and devm-registers hwmon devices. If registration fails for radio N, it returns an error that bubbles up and 'ath12k_core_pdev_create()' unwinds only DP ('ath12k_dp_pdev_free()'),
while already-registered hwmon devices for earlier radios remain bound to `wiphy->dev` via devm. If bring-up aborts (pdev_create fails), those hwmon sysfs nodes may persist until the 'wiphy' device is finally destroyed,
which can be much later or never if the bring-up stops early. It will impact resource/sysfs leak window and possible user-visible stale hwmon entries in failure paths.

Given this, using hwmon_device_register_with_groups() plus explicit unregister keeps lifecycle handling predictable and aligned with ath12k’s recovery paths.


>> +		if (IS_ERR(ar->thermal.hwmon_dev)) {
>> +			ret = PTR_ERR(ar->thermal.hwmon_dev);
>> +			ar->thermal.hwmon_dev = NULL;
>> +			ath12k_err(ar->ab, "failed to register hwmon device: %d\n",
>> +				   ret);
>> +			for (j = i - 1; j >= 0; j--) {
>> +				ar = ab->pdevs[i].ar;
>> +				if (!ar)
>> +					continue;
>> +
>> +				hwmon_device_unregister(ar->thermal.hwmon_dev);
>> +				ar->thermal.hwmon_dev = NULL;
>> +			}
>> +			return ret;
>> +		}
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> +void ath12k_thermal_unregister(struct ath12k_base *ab)
>> +{
>> +	struct ath12k *ar;
>> +	int i;
>> +
>> +	if (!IS_REACHABLE(CONFIG_HWMON))
>> +		return;
>> +
>> +	for (i = 0; i < ab->num_radios; i++) {
>> +		ar = ab->pdevs[i].ar;
>> +		if (!ar)
>> +			continue;
>> +
>> +		if (ar->thermal.hwmon_dev) {
>> +			hwmon_device_unregister(ar->thermal.hwmon_dev);
>> +			ar->thermal.hwmon_dev = NULL;
>> +		}
>> +	}
>> +}



More information about the ath12k mailing list