1 /*
2 * Copyright (c) 2011-2020 The Linux Foundation. All rights reserved.
3 * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18 /**
19 * DOC: wlan_hdd_sysfs_thermal_cfg.c
20 *
21 * implementation for creating sysfs file thermal_cfg
22 */
23
24 #include <wlan_hdd_includes.h>
25 #include "osif_psoc_sync.h"
26 #include <wlan_hdd_sysfs.h>
27 #include <wlan_hdd_sysfs_thermal_cfg.h>
28 #include "qdf_trace.h"
29 #include "sme_api.h"
30 #include "qdf_status.h"
31 #include <wlan_fw_offload_main.h>
32 #include "wlan_hdd_thermal.h"
33 #include <wlan_fwol_ucfg_api.h>
34
35 #ifdef FW_THERMAL_THROTTLE_SUPPORT
36 #ifndef QCN7605_SUPPORT
hdd_send_thermal_mgmt_cmd(mac_handle_t mac_handle,uint16_t lower_thresh_deg,uint16_t higher_thresh_deg)37 static QDF_STATUS hdd_send_thermal_mgmt_cmd(mac_handle_t mac_handle,
38 uint16_t lower_thresh_deg,
39 uint16_t higher_thresh_deg)
40 {
41 return sme_set_thermal_mgmt(mac_handle, lower_thresh_deg,
42 higher_thresh_deg);
43 }
44 #else
hdd_send_thermal_mgmt_cmd(mac_handle_t mac_handle,uint16_t lower_thresh_deg,uint16_t higher_thresh_deg)45 static QDF_STATUS hdd_send_thermal_mgmt_cmd(mac_handle_t mac_handle,
46 uint16_t lower_thresh_deg,
47 uint16_t higher_thresh_deg)
48 {
49 return QDF_STATUS_SUCCESS;
50 }
51 #endif
52 #endif /* FW_THERMAL_THROTTLE_SUPPORT */
53
54 static ssize_t
__hdd_sysfs_thermal_cfg_store(struct hdd_context * hdd_ctx,struct kobj_attribute * attr,const char * buf,size_t count)55 __hdd_sysfs_thermal_cfg_store(struct hdd_context *hdd_ctx,
56 struct kobj_attribute *attr,
57 const char *buf,
58 size_t count)
59 {
60 char buf_local[MAX_SYSFS_USER_COMMAND_SIZE_LENGTH + 1];
61 char *sptr, *token;
62 uint32_t val1, val2, val3, val4, val7;
63 uint16_t val5, val6;
64 QDF_STATUS status;
65 int ret;
66 struct thermal_mitigation_params therm_cfg_params;
67 struct wlan_fwol_thermal_temp thermal_temp = {0};
68
69 status = ucfg_fwol_get_thermal_temp(hdd_ctx->psoc, &thermal_temp);
70 if (QDF_IS_STATUS_ERROR(status)) {
71 hdd_err_rl("Failed to get fwol thermal obj");
72 return status;
73 }
74
75 if (!wlan_hdd_validate_modules_state(hdd_ctx))
76 return -EINVAL;
77
78 ret = hdd_sysfs_validate_and_copy_buf(buf_local, sizeof(buf_local),
79 buf, count);
80
81 if (ret) {
82 hdd_err_rl("invalid input");
83 return ret;
84 }
85
86 sptr = buf_local;
87 hdd_debug("thermal_cfg: count %zu buf_local:(%s)",
88 count, buf_local);
89
90 /* Get val1 */
91 token = strsep(&sptr, " ");
92 if (!token)
93 return -EINVAL;
94 if (kstrtou32(token, 0, &val1))
95 return -EINVAL;
96
97 /* Get val2 */
98 token = strsep(&sptr, " ");
99 if (!token)
100 return -EINVAL;
101 if (kstrtou32(token, 0, &val2))
102 return -EINVAL;
103
104 /* Get val3 */
105 token = strsep(&sptr, " ");
106 if (!token)
107 return -EINVAL;
108 if (kstrtou32(token, 0, &val3))
109 return -EINVAL;
110
111 /* Get val4 */
112 token = strsep(&sptr, " ");
113 if (!token)
114 return -EINVAL;
115 if (kstrtou32(token, 0, &val4))
116 return -EINVAL;
117
118 /* Get val5 */
119 token = strsep(&sptr, " ");
120 if (!token)
121 return -EINVAL;
122 if (kstrtou16(token, 0, &val5))
123 return -EINVAL;
124
125 /* Get val6 */
126 token = strsep(&sptr, " ");
127 if (!token)
128 return -EINVAL;
129 if (kstrtou16(token, 0, &val6))
130 return -EINVAL;
131
132 /* Get val7 */
133 token = strsep(&sptr, " ");
134 if (!token)
135 return -EINVAL;
136 if (kstrtou32(token, 0, &val7))
137 return -EINVAL;
138
139 /* Check for valid inputs */
140 if (val1 < 0 || val1 > 1 || val2 < 0 || val3 < 0 || val3 > 100 ||
141 val4 < 0 || val4 > 3 || val5 < 0 || val6 < 0 || val7 < 0 ||
142 val6 <= val5)
143 return -EINVAL;
144
145 therm_cfg_params.enable = val1;
146 therm_cfg_params.dc = val2;
147 therm_cfg_params.levelconf[0].dcoffpercent = val3;
148 therm_cfg_params.levelconf[0].priority = val4;
149 therm_cfg_params.levelconf[0].tmplwm = val7;
150 hdd_thermal_fill_clientid_priority(hdd_ctx, THERMAL_MONITOR_APPS,
151 thermal_temp.priority_apps,
152 thermal_temp.priority_wpps,
153 &therm_cfg_params);
154
155 status = sme_set_thermal_throttle_cfg(hdd_ctx->mac_handle,
156 &therm_cfg_params);
157
158 if (QDF_IS_STATUS_ERROR(status))
159 return qdf_status_to_os_return(status);
160
161 if (!val7) {
162 status = hdd_send_thermal_mgmt_cmd(hdd_ctx->mac_handle,
163 val5, val6);
164
165 if (QDF_IS_STATUS_ERROR(status))
166 return qdf_status_to_os_return(status);
167 }
168
169 return count;
170 }
171
172 static ssize_t
hdd_sysfs_thermal_cfg_store(struct kobject * kobj,struct kobj_attribute * attr,const char * buf,size_t count)173 hdd_sysfs_thermal_cfg_store(struct kobject *kobj,
174 struct kobj_attribute *attr,
175 const char *buf,
176 size_t count)
177 {
178 struct osif_psoc_sync *psoc_sync;
179 struct hdd_context *hdd_ctx = cds_get_context(QDF_MODULE_ID_HDD);
180 ssize_t errno_size;
181 int ret;
182
183 ret = wlan_hdd_validate_context(hdd_ctx);
184 if (ret != 0)
185 return ret;
186
187 errno_size = osif_psoc_sync_op_start(wiphy_dev(hdd_ctx->wiphy),
188 &psoc_sync);
189 if (errno_size)
190 return errno_size;
191
192 errno_size = __hdd_sysfs_thermal_cfg_store(hdd_ctx, attr,
193 buf, count);
194
195 osif_psoc_sync_op_stop(psoc_sync);
196
197 return errno_size;
198 }
199
200 static struct kobj_attribute thermal_cfg_attribute =
201 __ATTR(thermal_cfg, 0220, NULL,
202 hdd_sysfs_thermal_cfg_store);
203
hdd_sysfs_thermal_cfg_create(struct kobject * driver_kobject)204 int hdd_sysfs_thermal_cfg_create(struct kobject *driver_kobject)
205 {
206 int error;
207
208 if (!driver_kobject) {
209 hdd_err("could not get driver kobject!");
210 return -EINVAL;
211 }
212
213 error = sysfs_create_file(driver_kobject,
214 &thermal_cfg_attribute.attr);
215 if (error)
216 hdd_err("could not create thermal_cfg sysfs file");
217
218 return error;
219 }
220
221 void
hdd_sysfs_thermal_cfg_destroy(struct kobject * driver_kobject)222 hdd_sysfs_thermal_cfg_destroy(struct kobject *driver_kobject)
223 {
224 if (!driver_kobject) {
225 hdd_err("could not get driver kobject!");
226 return;
227 }
228 sysfs_remove_file(driver_kobject, &thermal_cfg_attribute.attr);
229 }
230