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