Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause-Clear
0002 /*
0003  * Copyright (c) 2020 The Linux Foundation. All rights reserved.
0004  */
0005 
0006 #include <linux/device.h>
0007 #include <linux/sysfs.h>
0008 #include <linux/thermal.h>
0009 #include <linux/hwmon.h>
0010 #include <linux/hwmon-sysfs.h>
0011 #include "core.h"
0012 #include "debug.h"
0013 
0014 static int
0015 ath11k_thermal_get_max_throttle_state(struct thermal_cooling_device *cdev,
0016                       unsigned long *state)
0017 {
0018     *state = ATH11K_THERMAL_THROTTLE_MAX;
0019 
0020     return 0;
0021 }
0022 
0023 static int
0024 ath11k_thermal_get_cur_throttle_state(struct thermal_cooling_device *cdev,
0025                       unsigned long *state)
0026 {
0027     struct ath11k *ar = cdev->devdata;
0028 
0029     mutex_lock(&ar->conf_mutex);
0030     *state = ar->thermal.throttle_state;
0031     mutex_unlock(&ar->conf_mutex);
0032 
0033     return 0;
0034 }
0035 
0036 static int
0037 ath11k_thermal_set_cur_throttle_state(struct thermal_cooling_device *cdev,
0038                       unsigned long throttle_state)
0039 {
0040     struct ath11k *ar = cdev->devdata;
0041     int ret;
0042 
0043     if (throttle_state > ATH11K_THERMAL_THROTTLE_MAX) {
0044         ath11k_warn(ar->ab, "throttle state %ld is exceeding the limit %d\n",
0045                 throttle_state, ATH11K_THERMAL_THROTTLE_MAX);
0046         return -EINVAL;
0047     }
0048     mutex_lock(&ar->conf_mutex);
0049     ret = ath11k_thermal_set_throttling(ar, throttle_state);
0050     if (ret == 0)
0051         ar->thermal.throttle_state = throttle_state;
0052     mutex_unlock(&ar->conf_mutex);
0053     return ret;
0054 }
0055 
0056 static const struct thermal_cooling_device_ops ath11k_thermal_ops = {
0057     .get_max_state = ath11k_thermal_get_max_throttle_state,
0058     .get_cur_state = ath11k_thermal_get_cur_throttle_state,
0059     .set_cur_state = ath11k_thermal_set_cur_throttle_state,
0060 };
0061 
0062 static ssize_t ath11k_thermal_show_temp(struct device *dev,
0063                     struct device_attribute *attr,
0064                     char *buf)
0065 {
0066     struct ath11k *ar = dev_get_drvdata(dev);
0067     int ret, temperature;
0068     unsigned long time_left;
0069 
0070     mutex_lock(&ar->conf_mutex);
0071 
0072     /* Can't get temperature when the card is off */
0073     if (ar->state != ATH11K_STATE_ON) {
0074         ret = -ENETDOWN;
0075         goto out;
0076     }
0077 
0078     reinit_completion(&ar->thermal.wmi_sync);
0079     ret = ath11k_wmi_send_pdev_temperature_cmd(ar);
0080     if (ret) {
0081         ath11k_warn(ar->ab, "failed to read temperature %d\n", ret);
0082         goto out;
0083     }
0084 
0085     if (test_bit(ATH11K_FLAG_CRASH_FLUSH, &ar->ab->dev_flags)) {
0086         ret = -ESHUTDOWN;
0087         goto out;
0088     }
0089 
0090     time_left = wait_for_completion_timeout(&ar->thermal.wmi_sync,
0091                         ATH11K_THERMAL_SYNC_TIMEOUT_HZ);
0092     if (!time_left) {
0093         ath11k_warn(ar->ab, "failed to synchronize thermal read\n");
0094         ret = -ETIMEDOUT;
0095         goto out;
0096     }
0097 
0098     spin_lock_bh(&ar->data_lock);
0099     temperature = ar->thermal.temperature;
0100     spin_unlock_bh(&ar->data_lock);
0101 
0102     /* display in millidegree celcius */
0103     ret = snprintf(buf, PAGE_SIZE, "%d\n", temperature * 1000);
0104 out:
0105     mutex_unlock(&ar->conf_mutex);
0106     return ret;
0107 }
0108 
0109 void ath11k_thermal_event_temperature(struct ath11k *ar, int temperature)
0110 {
0111     spin_lock_bh(&ar->data_lock);
0112     ar->thermal.temperature = temperature;
0113     spin_unlock_bh(&ar->data_lock);
0114     complete(&ar->thermal.wmi_sync);
0115 }
0116 
0117 static SENSOR_DEVICE_ATTR(temp1_input, 0444, ath11k_thermal_show_temp,
0118               NULL, 0);
0119 
0120 static struct attribute *ath11k_hwmon_attrs[] = {
0121     &sensor_dev_attr_temp1_input.dev_attr.attr,
0122     NULL,
0123 };
0124 ATTRIBUTE_GROUPS(ath11k_hwmon);
0125 
0126 int ath11k_thermal_set_throttling(struct ath11k *ar, u32 throttle_state)
0127 {
0128     struct ath11k_base *sc = ar->ab;
0129     struct thermal_mitigation_params param;
0130     int ret = 0;
0131 
0132     lockdep_assert_held(&ar->conf_mutex);
0133 
0134     if (ar->state != ATH11K_STATE_ON)
0135         return 0;
0136 
0137     memset(&param, 0, sizeof(param));
0138     param.pdev_id = ar->pdev->pdev_id;
0139     param.enable = throttle_state ? 1 : 0;
0140     param.dc = ATH11K_THERMAL_DEFAULT_DUTY_CYCLE;
0141     param.dc_per_event = 0xFFFFFFFF;
0142 
0143     param.levelconf[0].tmplwm = ATH11K_THERMAL_TEMP_LOW_MARK;
0144     param.levelconf[0].tmphwm = ATH11K_THERMAL_TEMP_HIGH_MARK;
0145     param.levelconf[0].dcoffpercent = throttle_state;
0146     param.levelconf[0].priority = 0; /* disable all data tx queues */
0147 
0148     ret = ath11k_wmi_send_thermal_mitigation_param_cmd(ar, &param);
0149     if (ret) {
0150         ath11k_warn(sc, "failed to send thermal mitigation duty cycle %u ret %d\n",
0151                 throttle_state, ret);
0152     }
0153 
0154     return ret;
0155 }
0156 
0157 int ath11k_thermal_register(struct ath11k_base *sc)
0158 {
0159     struct thermal_cooling_device *cdev;
0160     struct device *hwmon_dev;
0161     struct ath11k *ar;
0162     struct ath11k_pdev *pdev;
0163     int i, ret;
0164 
0165     for (i = 0; i < sc->num_radios; i++) {
0166         pdev = &sc->pdevs[i];
0167         ar = pdev->ar;
0168         if (!ar)
0169             continue;
0170 
0171         cdev = thermal_cooling_device_register("ath11k_thermal", ar,
0172                                &ath11k_thermal_ops);
0173 
0174         if (IS_ERR(cdev)) {
0175             ath11k_err(sc, "failed to setup thermal device result: %ld\n",
0176                    PTR_ERR(cdev));
0177             ret = -EINVAL;
0178             goto err_thermal_destroy;
0179         }
0180 
0181         ar->thermal.cdev = cdev;
0182 
0183         ret = sysfs_create_link(&ar->hw->wiphy->dev.kobj, &cdev->device.kobj,
0184                     "cooling_device");
0185         if (ret) {
0186             ath11k_err(sc, "failed to create cooling device symlink\n");
0187             goto err_thermal_destroy;
0188         }
0189 
0190         if (!IS_REACHABLE(CONFIG_HWMON))
0191             return 0;
0192 
0193         hwmon_dev = devm_hwmon_device_register_with_groups(&ar->hw->wiphy->dev,
0194                                    "ath11k_hwmon", ar,
0195                                    ath11k_hwmon_groups);
0196         if (IS_ERR(hwmon_dev)) {
0197             ath11k_err(ar->ab, "failed to register hwmon device: %ld\n",
0198                    PTR_ERR(hwmon_dev));
0199             ret = -EINVAL;
0200             goto err_thermal_destroy;
0201         }
0202     }
0203 
0204     return 0;
0205 
0206 err_thermal_destroy:
0207     ath11k_thermal_unregister(sc);
0208     return ret;
0209 }
0210 
0211 void ath11k_thermal_unregister(struct ath11k_base *sc)
0212 {
0213     struct ath11k *ar;
0214     struct ath11k_pdev *pdev;
0215     int i;
0216 
0217     for (i = 0; i < sc->num_radios; i++) {
0218         pdev = &sc->pdevs[i];
0219         ar = pdev->ar;
0220         if (!ar)
0221             continue;
0222 
0223         sysfs_remove_link(&ar->hw->wiphy->dev.kobj, "cooling_device");
0224         thermal_cooling_device_unregister(ar->thermal.cdev);
0225     }
0226 }