xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified_vdev_tlv.c (revision 97f44cd39e4ff816eaa1710279d28cf6b9e65ad9)
1 /*
2  * Copyright (c) 2016-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 #include <osdep.h>
20 #include <qdf_module.h>
21 #include <qdf_list.h>
22 #include <qdf_platform.h>
23 #include <wmi_unified_vdev_tlv.h>
24 #include <wlan_vdev_mgr_tgt_if_tx_defs.h>
25 
26 static QDF_STATUS
27 send_vdev_config_ratemask_cmd_tlv(struct wmi_unified *wmi_handle,
28 				  struct config_ratemask_params *param)
29 {
30 	wmi_vdev_config_ratemask_cmd_fixed_param *cmd;
31 	wmi_buf_t buf;
32 	int32_t len = sizeof(*cmd);
33 
34 	buf = wmi_buf_alloc(wmi_handle, len);
35 	if (!buf) {
36 		wmi_err("wmi_buf_alloc failed");
37 		return QDF_STATUS_E_FAILURE;
38 	}
39 	cmd = (wmi_vdev_config_ratemask_cmd_fixed_param *)wmi_buf_data(buf);
40 	WMITLV_SET_HDR(&cmd->tlv_header,
41 		       WMITLV_TAG_STRUC_wmi_vdev_config_ratemask_fixed_param,
42 		       WMITLV_GET_STRUCT_TLVLEN(
43 				wmi_vdev_config_ratemask_cmd_fixed_param));
44 	cmd->vdev_id = param->vdev_id;
45 	cmd->type = param->type;
46 	cmd->mask_lower32 = param->lower32;
47 	cmd->mask_higher32 = param->higher32;
48 	cmd->mask_lower32_2 = param->lower32_2;
49 	cmd->mask_higher32_2 = param->higher32_2;
50 
51 	wmi_mtrace(WMI_VDEV_RATEMASK_CMDID, cmd->vdev_id, 0);
52 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
53 				 WMI_VDEV_RATEMASK_CMDID)) {
54 		wmi_err("Setting vdev ratemask failed");
55 		wmi_buf_free(buf);
56 		return QDF_STATUS_E_FAILURE;
57 	}
58 
59 	return QDF_STATUS_SUCCESS;
60 }
61 
62 static QDF_STATUS
63 send_beacon_send_cmd_tlv(struct wmi_unified *wmi_handle,
64 			 struct beacon_params *param)
65 {
66 	QDF_STATUS ret;
67 	wmi_bcn_send_from_host_cmd_fixed_param *cmd;
68 	wmi_buf_t wmi_buf;
69 	qdf_dma_addr_t dma_addr;
70 	uint32_t dtim_flag = 0;
71 
72 	wmi_buf = wmi_buf_alloc(wmi_handle, sizeof(*cmd));
73 	if (!wmi_buf) {
74 		wmi_err("wmi_buf_alloc failed");
75 		return QDF_STATUS_E_NOMEM;
76 	}
77 	if (param->is_dtim_count_zero) {
78 		dtim_flag |= WMI_BCN_SEND_DTIM_ZERO;
79 		if (param->is_bitctl_reqd) {
80 			/* deliver CAB traffic in next DTIM beacon */
81 			dtim_flag |= WMI_BCN_SEND_DTIM_BITCTL_SET;
82 		}
83 	}
84 	cmd = (wmi_bcn_send_from_host_cmd_fixed_param *)wmi_buf_data(wmi_buf);
85 	WMITLV_SET_HDR(
86 		&cmd->tlv_header,
87 		WMITLV_TAG_STRUC_wmi_bcn_send_from_host_cmd_fixed_param,
88 		WMITLV_GET_STRUCT_TLVLEN
89 				(wmi_bcn_send_from_host_cmd_fixed_param));
90 	cmd->vdev_id = param->vdev_id;
91 	cmd->data_len = qdf_nbuf_len(param->wbuf);
92 	cmd->frame_ctrl = param->frame_ctrl;
93 	cmd->dtim_flag = dtim_flag;
94 	dma_addr = qdf_nbuf_get_frag_paddr(param->wbuf, 0);
95 	cmd->frag_ptr_lo = qdf_get_lower_32_bits(dma_addr);
96 #if defined(HTT_PADDR64)
97 	cmd->frag_ptr_hi = qdf_get_upper_32_bits(dma_addr) & 0x1F;
98 #endif
99 	cmd->bcn_antenna = param->bcn_txant;
100 
101 	wmi_mtrace(WMI_PDEV_SEND_BCN_CMDID, cmd->vdev_id, 0);
102 	ret = wmi_unified_cmd_send(wmi_handle, wmi_buf, sizeof(*cmd),
103 				   WMI_PDEV_SEND_BCN_CMDID);
104 	if (ret != QDF_STATUS_SUCCESS) {
105 		wmi_err("Failed to send bcn: %d", ret);
106 		wmi_buf_free(wmi_buf);
107 	}
108 
109 	return ret;
110 }
111 
112 static QDF_STATUS
113 extract_tbttoffset_num_vdevs_tlv(struct wmi_unified *wmi_handle, void *evt_buf,
114 				 uint32_t *num_vdevs)
115 {
116 	WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf;
117 	wmi_tbtt_offset_event_fixed_param *tbtt_offset_event;
118 	uint32_t vdev_map;
119 
120 	param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *)evt_buf;
121 	if (!param_buf) {
122 		wmi_err("Invalid tbtt update ext event buffer");
123 		return QDF_STATUS_E_INVAL;
124 	}
125 	tbtt_offset_event = param_buf->fixed_param;
126 	vdev_map = tbtt_offset_event->vdev_map;
127 	*num_vdevs = wmi_vdev_map_to_num_vdevs(vdev_map);
128 
129 	return QDF_STATUS_SUCCESS;
130 }
131 
132 static QDF_STATUS
133 send_vdev_set_neighbour_rx_cmd_tlv(struct wmi_unified *wmi_handle,
134 				   uint8_t macaddr[QDF_MAC_ADDR_SIZE],
135 				   struct set_neighbour_rx_params *param)
136 {
137 	wmi_vdev_filter_nrp_config_cmd_fixed_param *cmd;
138 	wmi_buf_t buf;
139 	int32_t len = sizeof(*cmd);
140 
141 	buf = wmi_buf_alloc(wmi_handle, len);
142 	if (!buf) {
143 		wmi_err("wmi_buf_alloc failed");
144 		return QDF_STATUS_E_FAILURE;
145 	}
146 	cmd = (wmi_vdev_filter_nrp_config_cmd_fixed_param *)wmi_buf_data(buf);
147 	WMITLV_SET_HDR(&cmd->tlv_header,
148 		       WMITLV_TAG_STRUC_wmi_vdev_filter_nrp_config_cmd_fixed_param,
149 		       WMITLV_GET_STRUCT_TLVLEN(
150 		       wmi_vdev_filter_nrp_config_cmd_fixed_param));
151 	cmd->vdev_id = param->vdev_id;
152 	cmd->bssid_idx = param->idx;
153 	cmd->action = param->action;
154 	cmd->type = param->type;
155 	WMI_CHAR_ARRAY_TO_MAC_ADDR(macaddr, &cmd->addr);
156 	cmd->flag = 0;
157 
158 	wmi_mtrace(WMI_VDEV_FILTER_NEIGHBOR_RX_PACKETS_CMDID, cmd->vdev_id, 0);
159 	if (wmi_unified_cmd_send(wmi_handle, buf, len,
160 				 WMI_VDEV_FILTER_NEIGHBOR_RX_PACKETS_CMDID)) {
161 		wmi_err("Failed to set neighbour rx param");
162 		wmi_buf_free(buf);
163 		return QDF_STATUS_E_FAILURE;
164 	}
165 
166 	return QDF_STATUS_SUCCESS;
167 }
168 
169 static QDF_STATUS
170 extract_vdev_start_resp_tlv(struct wmi_unified *wmi_handle, void *evt_buf,
171 			    struct vdev_start_response *vdev_rsp)
172 {
173 	WMI_VDEV_START_RESP_EVENTID_param_tlvs *param_buf;
174 	wmi_vdev_start_response_event_fixed_param *ev;
175 
176 	param_buf = (WMI_VDEV_START_RESP_EVENTID_param_tlvs *)evt_buf;
177 	if (!param_buf) {
178 		wmi_err("Invalid start response event buffer");
179 		return QDF_STATUS_E_INVAL;
180 	}
181 
182 	ev = param_buf->fixed_param;
183 	if (!ev) {
184 		wmi_err("Invalid start response event buffer");
185 		return QDF_STATUS_E_INVAL;
186 	}
187 
188 	qdf_mem_zero(vdev_rsp, sizeof(*vdev_rsp));
189 
190 	vdev_rsp->vdev_id = ev->vdev_id;
191 	vdev_rsp->requestor_id = ev->requestor_id;
192 	switch (ev->resp_type) {
193 	case WMI_VDEV_START_RESP_EVENT:
194 		vdev_rsp->resp_type = WMI_HOST_VDEV_START_RESP_EVENT;
195 		break;
196 	case WMI_VDEV_RESTART_RESP_EVENT:
197 		vdev_rsp->resp_type = WMI_HOST_VDEV_RESTART_RESP_EVENT;
198 		break;
199 	default:
200 		wmi_err("Invalid start response event buffer");
201 		break;
202 	};
203 	vdev_rsp->status = ev->status;
204 	vdev_rsp->chain_mask = ev->chain_mask;
205 	vdev_rsp->smps_mode = ev->smps_mode;
206 	vdev_rsp->mac_id = ev->mac_id;
207 	vdev_rsp->cfgd_tx_streams = ev->cfgd_tx_streams;
208 	vdev_rsp->cfgd_rx_streams = ev->cfgd_rx_streams;
209 	vdev_rsp->max_allowed_tx_power = ev->max_allowed_tx_power;
210 
211 	return QDF_STATUS_SUCCESS;
212 }
213 
214 static QDF_STATUS
215 extract_vdev_delete_resp_tlv(struct wmi_unified *wmi_handle, void *evt_buf,
216 			     struct vdev_delete_response *delete_rsp)
217 {
218 	WMI_VDEV_DELETE_RESP_EVENTID_param_tlvs *param_buf;
219 	wmi_vdev_delete_resp_event_fixed_param *ev;
220 
221 	param_buf = (WMI_VDEV_DELETE_RESP_EVENTID_param_tlvs *)evt_buf;
222 	if (!param_buf) {
223 		wmi_err("Invalid vdev delete response event buffer");
224 		return QDF_STATUS_E_INVAL;
225 	}
226 
227 	ev = param_buf->fixed_param;
228 	if (!ev) {
229 		wmi_err("Invalid vdev delete response event");
230 		return QDF_STATUS_E_INVAL;
231 	}
232 
233 	qdf_mem_zero(delete_rsp, sizeof(*delete_rsp));
234 	delete_rsp->vdev_id = ev->vdev_id;
235 
236 	return QDF_STATUS_SUCCESS;
237 }
238 
239 static QDF_STATUS extract_vdev_peer_delete_all_response_event_tlv(
240 		wmi_unified_t wmi_hdl,
241 		void *evt_buf,
242 		struct peer_delete_all_response *param)
243 {
244 	WMI_VDEV_DELETE_ALL_PEER_RESP_EVENTID_param_tlvs *param_buf;
245 	wmi_vdev_delete_all_peer_resp_event_fixed_param *ev;
246 
247 	param_buf = (WMI_VDEV_DELETE_ALL_PEER_RESP_EVENTID_param_tlvs *)evt_buf;
248 
249 	ev = (wmi_vdev_delete_all_peer_resp_event_fixed_param *)
250 							param_buf->fixed_param;
251 	if (!ev) {
252 		wmi_err("Invalid peer_delete all response");
253 		return QDF_STATUS_E_FAILURE;
254 	}
255 
256 	param->vdev_id = ev->vdev_id;
257 	param->status = ev->status;
258 
259 	return QDF_STATUS_SUCCESS;
260 }
261 
262 static QDF_STATUS
263 extract_vdev_stopped_param_tlv(struct wmi_unified *wmi_handle,
264 			       void *evt_buf, uint32_t *vdev_id)
265 {
266 	WMI_VDEV_STOPPED_EVENTID_param_tlvs *param_buf;
267 	wmi_vdev_stopped_event_fixed_param *resp_event;
268 
269 	param_buf = (WMI_VDEV_STOPPED_EVENTID_param_tlvs *)evt_buf;
270 	if (!param_buf) {
271 		wmi_err("Invalid event buffer");
272 		return QDF_STATUS_E_INVAL;
273 	}
274 	resp_event = param_buf->fixed_param;
275 	*vdev_id = resp_event->vdev_id;
276 
277 	return QDF_STATUS_SUCCESS;
278 }
279 
280 static QDF_STATUS extract_ext_tbttoffset_num_vdevs_tlv(
281 						wmi_unified_t wmi_hdl,
282 						void *evt_buf,
283 						uint32_t *num_vdevs)
284 {
285 	WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *param_buf;
286 	wmi_tbtt_offset_ext_event_fixed_param *tbtt_offset_ext_event;
287 
288 	param_buf = (WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *)evt_buf;
289 	if (!param_buf) {
290 		wmi_err("Invalid tbtt update ext event buffer");
291 		return QDF_STATUS_E_INVAL;
292 	}
293 	tbtt_offset_ext_event = param_buf->fixed_param;
294 
295 	*num_vdevs = tbtt_offset_ext_event->num_vdevs;
296 
297 	return QDF_STATUS_SUCCESS;
298 }
299 
300 static QDF_STATUS extract_tbttoffset_update_params_tlv(
301 					wmi_unified_t wmi_hdl,
302 					void *evt_buf, uint8_t idx,
303 					struct tbttoffset_params *tbtt_param)
304 {
305 	WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf;
306 	wmi_tbtt_offset_event_fixed_param *tbtt_offset_event;
307 	uint32_t vdev_map;
308 
309 	param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *)evt_buf;
310 	if (!param_buf) {
311 		wmi_err("Invalid tbtt update event buffer");
312 		return QDF_STATUS_E_INVAL;
313 	}
314 
315 	tbtt_offset_event = param_buf->fixed_param;
316 	vdev_map = tbtt_offset_event->vdev_map;
317 	tbtt_param->vdev_id = wmi_vdev_map_to_vdev_id(vdev_map, idx);
318 	if (tbtt_param->vdev_id == WLAN_INVALID_VDEV_ID)
319 		return QDF_STATUS_E_INVAL;
320 	tbtt_param->tbttoffset =
321 		param_buf->tbttoffset_list[tbtt_param->vdev_id];
322 	if (param_buf->tbtt_qtime_low_us_list)
323 		tbtt_param->vdev_tbtt_qtime_lo =
324 		    param_buf->tbtt_qtime_low_us_list[tbtt_param->vdev_id];
325 	if (param_buf->tbtt_qtime_high_us_list)
326 		tbtt_param->vdev_tbtt_qtime_hi =
327 		    param_buf->tbtt_qtime_high_us_list[tbtt_param->vdev_id];
328 
329 	return QDF_STATUS_SUCCESS;
330 }
331 
332 static QDF_STATUS extract_ext_tbttoffset_update_params_tlv(
333 					wmi_unified_t wmi_hdl,
334 					void *evt_buf, uint8_t idx,
335 					struct tbttoffset_params *tbtt_param)
336 {
337 	WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *param_buf;
338 	wmi_tbtt_offset_info *tbtt_offset_info;
339 
340 	param_buf = (WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *)evt_buf;
341 	if (!param_buf) {
342 		wmi_err("Invalid tbtt update event buffer");
343 		return QDF_STATUS_E_INVAL;
344 	}
345 	tbtt_offset_info = &param_buf->tbtt_offset_info[idx];
346 
347 	tbtt_param->vdev_id = tbtt_offset_info->vdev_id;
348 	tbtt_param->tbttoffset = tbtt_offset_info->tbttoffset;
349 	tbtt_param->vdev_tbtt_qtime_lo = tbtt_offset_info->tbtt_qtime_low_us;
350 	tbtt_param->vdev_tbtt_qtime_hi = tbtt_offset_info->tbtt_qtime_high_us;
351 
352 	return QDF_STATUS_SUCCESS;
353 }
354 
355 static QDF_STATUS extract_muedca_params_tlv(wmi_unified_t wmi_hdl,
356 					    void *evt_buf,
357 					    struct muedca_params *muedca_param_list)
358 {
359 	WMI_MUEDCA_PARAMS_CONFIG_EVENTID_param_tlvs *param_buf;
360 	wmi_muedca_params_config_event_fixed_param *muedca_param;
361 	int i;
362 
363 	param_buf = (WMI_MUEDCA_PARAMS_CONFIG_EVENTID_param_tlvs *)evt_buf;
364 	if (!param_buf) {
365 		wmi_err("Invalid muedca evt buffer");
366 		return QDF_STATUS_E_INVAL;
367 	}
368 	muedca_param = param_buf->fixed_param;
369 
370 	muedca_param_list->pdev_id = wmi_hdl->ops->
371 		convert_target_pdev_id_to_host(wmi_hdl,
372 					       muedca_param->pdev_id);
373 	for (i = 0; i < WMI_AC_MAX; i++) {
374 		muedca_param_list->muedca_aifsn[i] = muedca_param->aifsn[i] &
375 						      WMI_MUEDCA_PARAM_MASK;
376 		muedca_param_list->muedca_ecwmin[i] = muedca_param->ecwmin[i] &
377 						      WMI_MUEDCA_PARAM_MASK;
378 		muedca_param_list->muedca_ecwmax[i] = muedca_param->ecwmax[i] &
379 						      WMI_MUEDCA_PARAM_MASK;
380 		muedca_param_list->muedca_timer[i] = muedca_param->muedca_expiration_time[i] &
381 						      WMI_MUEDCA_PARAM_MASK;
382 	}
383 
384 	return QDF_STATUS_SUCCESS;
385 }
386 
387 void wmi_vdev_attach_tlv(struct wmi_unified *wmi_handle)
388 {
389 	struct wmi_ops *wmi_ops;
390 
391 	if (!wmi_handle) {
392 		wmi_err("null wmi handle");
393 		return;
394 	}
395 
396 	wmi_ops = wmi_handle->ops;
397 	wmi_ops->extract_vdev_delete_resp = extract_vdev_delete_resp_tlv;
398 	wmi_ops->extract_vdev_stopped_param = extract_vdev_stopped_param_tlv;
399 	wmi_ops->extract_vdev_start_resp = extract_vdev_start_resp_tlv;
400 	wmi_ops->extract_vdev_peer_delete_all_response_event =
401 				extract_vdev_peer_delete_all_response_event_tlv;
402 	wmi_ops->extract_tbttoffset_num_vdevs =
403 				extract_tbttoffset_num_vdevs_tlv;
404 	wmi_ops->extract_tbttoffset_update_params =
405 				extract_tbttoffset_update_params_tlv;
406 	wmi_ops->extract_ext_tbttoffset_update_params =
407 				extract_ext_tbttoffset_update_params_tlv;
408 	wmi_ops->extract_ext_tbttoffset_num_vdevs =
409 				extract_ext_tbttoffset_num_vdevs_tlv;
410 	wmi_ops->extract_muedca_params_handler =
411 				extract_muedca_params_tlv;
412 	wmi_ops->send_vdev_set_neighbour_rx_cmd =
413 				send_vdev_set_neighbour_rx_cmd_tlv;
414 	wmi_ops->send_beacon_send_cmd = send_beacon_send_cmd_tlv;
415 	wmi_ops->send_vdev_config_ratemask_cmd =
416 				send_vdev_config_ratemask_cmd_tlv;
417 }
418