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