blob: fb09212f6080e8f3e7dc1a22dea7b5d29e7f7eb0 [file] [log] [blame]
Pankaj Singh50e40422020-01-09 15:29:35 +05301/*
2 * Copyright (c) 2020 The Linux Foundation. All rights reserved.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
19/**
20 * DOC: wlan_hdd_thermal.c
21 *
22 * WLAN Host Device Driver implementation for thermal mitigation handling
23 */
24
25#include <wlan_hdd_includes.h>
26#include <net/cfg80211.h>
27#include "wlan_osif_priv.h"
28#include "qdf_trace.h"
29#include "wlan_hdd_main.h"
30#include "osif_sync.h"
31#include <linux/limits.h>
32#include <wlan_hdd_object_manager.h>
33#include "sme_api.h"
34#include "wlan_hdd_thermal.h"
35#include "wlan_hdd_cfg80211.h"
36#include <qca_vendor.h>
37#include "wlan_fwol_ucfg_api.h"
38
39static const struct nla_policy
40 wlan_hdd_thermal_mitigation_policy
41 [QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_MAX + 1] = {
42 [QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE] = {.type = NLA_U32},
43 [QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL] = {
44 .type = NLA_U32},
45};
46
47/**
48 * __wlan_hdd_cfg80211_set_thermal_mitigation_policy() - Set the thermal policy
49 * @wiphy: Pointer to wireless phy
50 * @wdev: Pointer to wireless device
51 * @data: Pointer to data
52 * @data_len: Length of @data
53 *
54 * Return: 0 on success, negative errno on failure
55 */
56static int
57__wlan_hdd_cfg80211_set_thermal_mitigation_policy(struct wiphy *wiphy,
58 struct wireless_dev *wdev,
59 const void *data,
60 int data_len)
61{
62 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
63 struct nlattr *tb[QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_MAX + 1];
64 bool enable = true;
65 uint32_t dc, dc_off_percent, level, cmd_type;
66 uint32_t prio = 0, target_temp = 0;
67 struct wlan_fwol_thermal_temp thermal_temp = {0};
68 QDF_STATUS status;
69
70 hdd_enter();
71
72 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
73 hdd_err_rl("Command not allowed in FTM mode");
74 return -EPERM;
75 }
76
77 if (wlan_cfg80211_nla_parse(tb,
78 QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_MAX,
79 (struct nlattr *)data, data_len,
80 wlan_hdd_thermal_mitigation_policy)) {
81 hdd_err_rl("Invalid attribute");
82 return -EINVAL;
83 }
84
85 if (!tb[QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE]) {
86 hdd_err_rl("attr thermal cmd value failed");
87 return -EINVAL;
88 }
89
90 cmd_type = nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_VALUE]);
91 if (cmd_type != QCA_WLAN_VENDOR_ATTR_THERMAL_CMD_TYPE_SET_LEVEL) {
92 hdd_err_rl("invalid thermal cmd value");
93 return -EINVAL;
94 }
95
96 if (!tb[QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL]) {
97 hdd_err_rl("attr thermal throttle set failed");
98 return -EINVAL;
99 }
100 level =
101 nla_get_u32(tb[QCA_WLAN_VENDOR_ATTR_THERMAL_LEVEL]);
102
103 hdd_debug("thermal mitigation level %d", level);
104
105 status = ucfg_fwol_get_thermal_temp(hdd_ctx->psoc, &thermal_temp);
106 if (QDF_IS_STATUS_ERROR(status)) {
107 hdd_err_rl("Failed to get fwol thermal obj");
108 return qdf_status_to_os_return(status);
109 }
110
111 switch (level) {
112 case QCA_WLAN_VENDOR_THERMAL_LEVEL_EMERGENCY:
113 dc_off_percent = thermal_temp.throttle_dutycycle_level[5];
114 break;
115 case QCA_WLAN_VENDOR_THERMAL_LEVEL_CRITICAL:
116 dc_off_percent = thermal_temp.throttle_dutycycle_level[4];
117 break;
118 case QCA_WLAN_VENDOR_THERMAL_LEVEL_SEVERE:
119 dc_off_percent = thermal_temp.throttle_dutycycle_level[3];
120 break;
121 case QCA_WLAN_VENDOR_THERMAL_LEVEL_MODERATE:
122 dc_off_percent = thermal_temp.throttle_dutycycle_level[2];
123 break;
124 case QCA_WLAN_VENDOR_THERMAL_LEVEL_LIGHT:
125 dc_off_percent = thermal_temp.throttle_dutycycle_level[1];
126 break;
127 case QCA_WLAN_VENDOR_THERMAL_LEVEL_NONE:
128 enable = false;
129 dc_off_percent = thermal_temp.throttle_dutycycle_level[0];
130 break;
131 default:
132 hdd_debug("Invalid thermal state");
133 return -EINVAL;
134 }
135
136 dc = thermal_temp.thermal_sampling_time;
137 hdd_debug("dc %d dc_off_per %d", dc, dc_off_percent);
138
139 status = sme_set_thermal_throttle_cfg(hdd_ctx->mac_handle,
140 enable,
141 dc,
142 dc_off_percent,
143 prio,
144 target_temp);
145 if (QDF_IS_STATUS_ERROR(status))
146 hdd_err_rl("Failed to set throttle configuration %d", status);
147
148 return qdf_status_to_os_return(status);
149}
150
151/**
152 * wlan_hdd_cfg80211_set_thermal_mitigation_policy() - set thermal
153 * mitigation policy
154 * @wiphy: wiphy pointer
155 * @wdev: pointer to struct wireless_dev
156 * @data: pointer to incoming NL vendor data
157 * @data_len: length of @data
158 *
159 * Return: 0 on success; error number otherwise.
160 */
161int
162wlan_hdd_cfg80211_set_thermal_mitigation_policy(struct wiphy *wiphy,
163 struct wireless_dev *wdev,
164 const void *data, int data_len)
165{
166 struct osif_psoc_sync *psoc_sync;
167 int errno;
168
169 errno = osif_psoc_sync_op_start(wiphy_dev(wiphy), &psoc_sync);
170 if (errno)
171 return errno;
172
173 errno = __wlan_hdd_cfg80211_set_thermal_mitigation_policy(wiphy, wdev,
174 data,
175 data_len);
176
177 osif_psoc_sync_op_stop(psoc_sync);
178
179 return errno;
180}
181
182bool wlan_hdd_thermal_config_support(void)
183{
184 return true;
185}
186