1 /*
2 * Copyright (c) 2019-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_mpta_helper.c
21 *
22 * The implementation of mpta helper configuration
23 */
24
25 #include "wlan_hdd_main.h"
26 #include "wmi_unified_param.h"
27 #include "wlan_hdd_mpta_helper.h"
28 #include "qca_vendor.h"
29 #include "wlan_osif_request_manager.h"
30 #include "osif_sync.h"
31
32 const struct nla_policy
33 qca_wlan_vendor_mpta_helper_attr[QCA_MPTA_HELPER_VENDOR_ATTR_MAX + 1] = {
34 [QCA_MPTA_HELPER_VENDOR_ATTR_ZIGBEE_STATE] = {.type = NLA_U32 },
35 [QCA_MPTA_HELPER_VENDOR_ATTR_INT_WLAN_DURATION] = {.type = NLA_U32 },
36 [QCA_MPTA_HELPER_VENDOR_ATTR_INT_NON_WLAN_DURATION] = {
37 .type = NLA_U32 },
38 [QCA_MPTA_HELPER_VENDOR_ATTR_MON_WLAN_DURATION] = {.type = NLA_U32 },
39 [QCA_MPTA_HELPER_VENDOR_ATTR_MON_NON_WLAN_DURATION] = {
40 .type = NLA_U32 },
41 [QCA_MPTA_HELPER_VENDOR_ATTR_INT_OCS_DURATION] = {.type = NLA_U32 },
42 [QCA_MPTA_HELPER_VENDOR_ATTR_MON_OCS_DURATION] = {.type = NLA_U32 },
43 [QCA_MPTA_HELPER_VENDOR_ATTR_ZIGBEE_CHAN] = {.type = NLA_U32 },
44 [QCA_MPTA_HELPER_VENDOR_ATTR_WLAN_MUTE_DURATION] = {.type = NLA_U32 },
45 };
46
47 /**
48 * __wlan_hdd_cfg80211_mpta_helper_config() - update
49 * tri-radio coex status by mpta helper
50 * @wiphy: wiphy device pointer
51 * @wdev: wireless device pointer
52 * @data: Vendor command data buffer
53 * @data_len: Buffer length
54 *
55 * Return: 0 on success; error number otherwise.
56 *
57 */
58 static int
__wlan_hdd_cfg80211_mpta_helper_config(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)59 __wlan_hdd_cfg80211_mpta_helper_config(struct wiphy *wiphy,
60 struct wireless_dev *wdev,
61 const void *data,
62 int data_len)
63 {
64 struct hdd_context *hdd_ctx = wiphy_priv(wiphy);
65 struct nlattr *tb[QCA_MPTA_HELPER_VENDOR_ATTR_MAX + 1];
66 struct coex_config_params coex_cfg_params = {0};
67 int errno;
68 QDF_STATUS status;
69
70 hdd_enter_dev(wdev->netdev);
71
72 if (QDF_GLOBAL_FTM_MODE == hdd_get_conparam()) {
73 hdd_err("Command not allowed in FTM mode");
74 return -EPERM;
75 }
76
77 errno = wlan_hdd_validate_context(hdd_ctx);
78 if (errno)
79 return errno;
80
81 if (wlan_cfg80211_nla_parse(tb, QCA_MPTA_HELPER_VENDOR_ATTR_MAX, data,
82 data_len,
83 qca_wlan_vendor_mpta_helper_attr)) {
84 hdd_err("invalid attr");
85 return -EINVAL;
86 }
87
88 /* if no attributes specified, return -EINVAL */
89 errno = -EINVAL;
90
91 if (tb[QCA_MPTA_HELPER_VENDOR_ATTR_ZIGBEE_STATE]) {
92 coex_cfg_params.config_type =
93 WMI_COEX_CONFIG_MPTA_HELPER_ZIGBEE_STATE;
94 coex_cfg_params.config_arg1 = nla_get_u32
95 (tb[QCA_MPTA_HELPER_VENDOR_ATTR_ZIGBEE_STATE]);
96
97 status = sme_send_coex_config_cmd(&coex_cfg_params);
98
99 if (QDF_IS_STATUS_ERROR(status)) {
100 hdd_err("Failed to set zigbee STATE");
101 return -EINVAL;
102 }
103
104 errno = 0;
105 }
106
107 if ((tb[QCA_MPTA_HELPER_VENDOR_ATTR_INT_WLAN_DURATION]) &&
108 (tb[QCA_MPTA_HELPER_VENDOR_ATTR_INT_NON_WLAN_DURATION])) {
109 coex_cfg_params.config_type =
110 WMI_COEX_CONFIG_MPTA_HELPER_INT_OCS_PARAMS;
111 coex_cfg_params.config_arg1 = nla_get_u32
112 (tb[QCA_MPTA_HELPER_VENDOR_ATTR_INT_WLAN_DURATION]);
113 coex_cfg_params.config_arg2 = nla_get_u32
114 (tb[QCA_MPTA_HELPER_VENDOR_ATTR_INT_NON_WLAN_DURATION]);
115
116 status = sme_send_coex_config_cmd(&coex_cfg_params);
117
118 if (QDF_IS_STATUS_ERROR(status)) {
119 hdd_err("Failed to set int OCS duration");
120 return -EINVAL;
121 }
122
123 errno = 0;
124 }
125
126 if ((tb[QCA_MPTA_HELPER_VENDOR_ATTR_MON_WLAN_DURATION]) &&
127 (tb[QCA_MPTA_HELPER_VENDOR_ATTR_MON_NON_WLAN_DURATION])) {
128 coex_cfg_params.config_type =
129 WMI_COEX_CONFIG_MPTA_HELPER_MON_OCS_PARAMS;
130 coex_cfg_params.config_arg1 = nla_get_u32
131 (tb[QCA_MPTA_HELPER_VENDOR_ATTR_MON_WLAN_DURATION]);
132 coex_cfg_params.config_arg2 = nla_get_u32
133 (tb[QCA_MPTA_HELPER_VENDOR_ATTR_MON_NON_WLAN_DURATION]);
134
135 status = sme_send_coex_config_cmd(&coex_cfg_params);
136
137 if (QDF_IS_STATUS_ERROR(status)) {
138 hdd_err("Failed to set mon OCS duration");
139 return -EINVAL;
140 }
141
142 errno = 0;
143 }
144
145 if ((tb[QCA_MPTA_HELPER_VENDOR_ATTR_INT_OCS_DURATION]) &&
146 (tb[QCA_MPTA_HELPER_VENDOR_ATTR_MON_OCS_DURATION])) {
147 coex_cfg_params.config_type =
148 WMI_COEX_CONFIG_MPTA_HELPER_INT_MON_DURATION;
149 coex_cfg_params.config_arg1 = nla_get_u32
150 (tb[QCA_MPTA_HELPER_VENDOR_ATTR_INT_OCS_DURATION]);
151 coex_cfg_params.config_arg2 = nla_get_u32
152 (tb[QCA_MPTA_HELPER_VENDOR_ATTR_MON_OCS_DURATION]);
153
154 status = sme_send_coex_config_cmd(&coex_cfg_params);
155
156 if (QDF_IS_STATUS_ERROR(status)) {
157 hdd_err("Failed to set int mon duration");
158 return -EINVAL;
159 }
160
161 errno = 0;
162 }
163
164 if (tb[QCA_MPTA_HELPER_VENDOR_ATTR_ZIGBEE_CHAN]) {
165 coex_cfg_params.config_type =
166 WMI_COEX_CONFIG_MPTA_HELPER_ZIGBEE_CHANNEL;
167 coex_cfg_params.config_arg1 = nla_get_u32
168 (tb[QCA_MPTA_HELPER_VENDOR_ATTR_ZIGBEE_CHAN]);
169
170 status = sme_send_coex_config_cmd(&coex_cfg_params);
171
172 if (QDF_IS_STATUS_ERROR(status)) {
173 hdd_err("Failed to set zigbee chan");
174 return -EINVAL;
175 }
176
177 errno = 0;
178 }
179
180 if (tb[QCA_MPTA_HELPER_VENDOR_ATTR_WLAN_MUTE_DURATION]) {
181 coex_cfg_params.config_type =
182 WMI_COEX_CONFIG_MPTA_HELPER_WLAN_MUTE_DURATION;
183 coex_cfg_params.config_arg1 = nla_get_u32
184 (tb[QCA_MPTA_HELPER_VENDOR_ATTR_WLAN_MUTE_DURATION]);
185
186 status = sme_send_coex_config_cmd(&coex_cfg_params);
187
188 if (QDF_IS_STATUS_ERROR(status)) {
189 hdd_err("Failed to set wlan mute duration");
190 return -EINVAL;
191 }
192
193 errno = 0;
194 }
195
196 return errno;
197 }
198
199 /**
200 * wlan_hdd_cfg80211_mpta_helper_config() - update
201 * tri-radio coex status by mpta helper
202 * @wiphy: wiphy device pointer
203 * @wdev: wireless device pointer
204 * @data: Vendor command data buffer
205 * @data_len: Buffer length
206 *
207 * Return: 0 on success; error number otherwise.
208 *
209 */
210 int
wlan_hdd_cfg80211_mpta_helper_config(struct wiphy * wiphy,struct wireless_dev * wdev,const void * data,int data_len)211 wlan_hdd_cfg80211_mpta_helper_config(struct wiphy *wiphy,
212 struct wireless_dev *wdev,
213 const void *data,
214 int data_len)
215 {
216 int errno;
217 struct osif_vdev_sync *vdev_sync;
218
219 errno = osif_vdev_sync_op_start(wdev->netdev, &vdev_sync);
220 if (errno)
221 return errno;
222
223 errno = __wlan_hdd_cfg80211_mpta_helper_config(
224 wiphy, wdev, data, data_len);
225
226 osif_vdev_sync_op_stop(vdev_sync);
227
228 return errno;
229 }
230
231 /**
232 * wlan_hdd_mpta_helper_enable() - enable/disable mpta helper
233 * according to cfg from INI
234 * @coex_cfg_params: pointer of coex config command params
235 * @config: pointer of BTC config items
236 *
237 * Return: 0 on success; error number otherwise.
238 *
239 */
240 int
wlan_hdd_mpta_helper_enable(struct coex_config_params * coex_cfg_params,struct wlan_fwol_coex_config * config)241 wlan_hdd_mpta_helper_enable(struct coex_config_params *coex_cfg_params,
242 struct wlan_fwol_coex_config *config)
243 {
244 QDF_STATUS status;
245
246 coex_cfg_params->config_type = WMI_COEX_CONFIG_MPTA_HELPER_ENABLE;
247 coex_cfg_params->config_arg1 = config->btc_mpta_helper_enable;
248
249 status = sme_send_coex_config_cmd(coex_cfg_params);
250 if (QDF_IS_STATUS_ERROR(status)) {
251 hdd_err("Failed to send coex MPTA Helper Enable");
252 return -EINVAL;
253 }
254
255 return 0;
256 }
257
258