xref: /wlan-dirver/qca-wifi-host-cmn/wmi/src/wmi_unified_vdev_tlv.c (revision bea437e2293c3d4fb1b5704fcf633aedac996962)
1 /*
2  * Copyright (c) 2016-2019 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 			    wmi_host_vdev_start_resp *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 
209 	return QDF_STATUS_SUCCESS;
210 }
211 
212 static QDF_STATUS
213 extract_vdev_delete_resp_tlv(struct wmi_unified *wmi_handle, void *evt_buf,
214 			     struct wmi_host_vdev_delete_resp *delete_rsp)
215 {
216 	WMI_VDEV_DELETE_RESP_EVENTID_param_tlvs *param_buf;
217 	wmi_vdev_delete_resp_event_fixed_param *ev;
218 
219 	param_buf = (WMI_VDEV_DELETE_RESP_EVENTID_param_tlvs *)evt_buf;
220 	if (!param_buf) {
221 		WMI_LOGE("Invalid vdev delete response event buffer");
222 		return QDF_STATUS_E_INVAL;
223 	}
224 
225 	ev = param_buf->fixed_param;
226 	if (!ev) {
227 		WMI_LOGE("Invalid vdev delete response event");
228 		return QDF_STATUS_E_INVAL;
229 	}
230 
231 	qdf_mem_zero(delete_rsp, sizeof(*delete_rsp));
232 	delete_rsp->vdev_id = ev->vdev_id;
233 
234 	return QDF_STATUS_SUCCESS;
235 }
236 
237 static QDF_STATUS extract_vdev_peer_delete_all_response_event_tlv(
238 		wmi_unified_t wmi_hdl,
239 		void *evt_buf,
240 		struct wmi_host_vdev_peer_delete_all_response_event *param)
241 {
242 	WMI_VDEV_DELETE_ALL_PEER_RESP_EVENTID_param_tlvs *param_buf;
243 	wmi_vdev_delete_all_peer_resp_event_fixed_param *ev;
244 
245 	param_buf = (WMI_VDEV_DELETE_ALL_PEER_RESP_EVENTID_param_tlvs *)evt_buf;
246 
247 	ev = (wmi_vdev_delete_all_peer_resp_event_fixed_param *)
248 							param_buf->fixed_param;
249 	if (!ev) {
250 		WMI_LOGE("%s: Invalid peer_delete all response", __func__);
251 		return QDF_STATUS_E_FAILURE;
252 	}
253 
254 	param->vdev_id = ev->vdev_id;
255 	param->status = ev->status;
256 
257 	return QDF_STATUS_SUCCESS;
258 }
259 
260 static QDF_STATUS
261 extract_vdev_stopped_param_tlv(struct wmi_unified *wmi_handle,
262 			       void *evt_buf, uint32_t *vdev_id)
263 {
264 	WMI_VDEV_STOPPED_EVENTID_param_tlvs *param_buf;
265 	wmi_vdev_stopped_event_fixed_param *resp_event;
266 
267 	param_buf = (WMI_VDEV_STOPPED_EVENTID_param_tlvs *)evt_buf;
268 	if (!param_buf) {
269 		WMI_LOGE("Invalid event buffer");
270 		return QDF_STATUS_E_INVAL;
271 	}
272 	resp_event = param_buf->fixed_param;
273 	*vdev_id = resp_event->vdev_id;
274 
275 	return QDF_STATUS_SUCCESS;
276 }
277 
278 static QDF_STATUS extract_ext_tbttoffset_num_vdevs_tlv(
279 						wmi_unified_t wmi_hdl,
280 						void *evt_buf,
281 						uint32_t *num_vdevs)
282 {
283 	WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *param_buf;
284 	wmi_tbtt_offset_ext_event_fixed_param *tbtt_offset_ext_event;
285 
286 	param_buf = (WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *)evt_buf;
287 	if (!param_buf) {
288 		WMI_LOGE("%s Invalid tbtt update ext event buffer", __func__);
289 		return QDF_STATUS_E_INVAL;
290 	}
291 	tbtt_offset_ext_event = param_buf->fixed_param;
292 
293 	*num_vdevs = tbtt_offset_ext_event->num_vdevs;
294 
295 	return QDF_STATUS_SUCCESS;
296 }
297 
298 static QDF_STATUS extract_tbttoffset_update_params_tlv(
299 					wmi_unified_t wmi_hdl,
300 					void *evt_buf, uint8_t idx,
301 					struct tbttoffset_params *tbtt_param)
302 {
303 	WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *param_buf;
304 	wmi_tbtt_offset_event_fixed_param *tbtt_offset_event;
305 	uint32_t vdev_map;
306 
307 	param_buf = (WMI_TBTTOFFSET_UPDATE_EVENTID_param_tlvs *)evt_buf;
308 	if (!param_buf) {
309 		WMI_LOGE("%s: Invalid tbtt update event buffer", __func__);
310 		return QDF_STATUS_E_INVAL;
311 	}
312 
313 	tbtt_offset_event = param_buf->fixed_param;
314 	vdev_map = tbtt_offset_event->vdev_map;
315 	tbtt_param->vdev_id = wmi_vdev_map_to_vdev_id(vdev_map, idx);
316 	if (tbtt_param->vdev_id == WLAN_INVALID_VDEV_ID)
317 		return QDF_STATUS_E_INVAL;
318 	tbtt_param->tbttoffset =
319 		param_buf->tbttoffset_list[tbtt_param->vdev_id];
320 	tbtt_param->vdev_tbtt_qtime_lo =
321 		param_buf->tbtt_qtime_low_us_list[tbtt_param->vdev_id];
322 	tbtt_param->vdev_tbtt_qtime_hi =
323 		param_buf->tbtt_qtime_high_us_list[tbtt_param->vdev_id];
324 
325 	return QDF_STATUS_SUCCESS;
326 }
327 
328 static QDF_STATUS extract_ext_tbttoffset_update_params_tlv(
329 					wmi_unified_t wmi_hdl,
330 					void *evt_buf, uint8_t idx,
331 					struct tbttoffset_params *tbtt_param)
332 {
333 	WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *param_buf;
334 	wmi_tbtt_offset_info *tbtt_offset_info;
335 
336 	param_buf = (WMI_TBTTOFFSET_EXT_UPDATE_EVENTID_param_tlvs *)evt_buf;
337 	if (!param_buf) {
338 		WMI_LOGE("%s: Invalid tbtt update event buffer", __func__);
339 		return QDF_STATUS_E_INVAL;
340 	}
341 	tbtt_offset_info = &param_buf->tbtt_offset_info[idx];
342 
343 	tbtt_param->vdev_id = tbtt_offset_info->vdev_id;
344 	tbtt_param->tbttoffset = tbtt_offset_info->tbttoffset;
345 	tbtt_param->vdev_tbtt_qtime_lo = tbtt_offset_info->tbtt_qtime_low_us;
346 	tbtt_param->vdev_tbtt_qtime_hi = tbtt_offset_info->tbtt_qtime_high_us;
347 
348 	return QDF_STATUS_SUCCESS;
349 }
350 
351 void wmi_vdev_attach_tlv(struct wmi_unified *wmi_handle)
352 {
353 	struct wmi_ops *wmi_ops;
354 
355 	if (!wmi_handle) {
356 		WMI_LOGP("%s: null wmi handle", __func__);
357 		return;
358 	}
359 
360 	wmi_ops = wmi_handle->ops;
361 	wmi_ops->extract_vdev_delete_resp = extract_vdev_delete_resp_tlv;
362 	wmi_ops->extract_vdev_stopped_param = extract_vdev_stopped_param_tlv;
363 	wmi_ops->extract_vdev_start_resp = extract_vdev_start_resp_tlv;
364 	wmi_ops->extract_vdev_peer_delete_all_response_event =
365 				extract_vdev_peer_delete_all_response_event_tlv;
366 	wmi_ops->extract_tbttoffset_num_vdevs =
367 				extract_tbttoffset_num_vdevs_tlv;
368 	wmi_ops->extract_tbttoffset_update_params =
369 				extract_tbttoffset_update_params_tlv;
370 	wmi_ops->extract_ext_tbttoffset_update_params =
371 				extract_ext_tbttoffset_update_params_tlv;
372 	wmi_ops->extract_ext_tbttoffset_num_vdevs =
373 				extract_ext_tbttoffset_num_vdevs_tlv;
374 	wmi_ops->send_vdev_set_neighbour_rx_cmd =
375 				send_vdev_set_neighbour_rx_cmd_tlv;
376 	wmi_ops->send_beacon_send_cmd = send_beacon_send_cmd_tlv;
377 	wmi_ops->send_vdev_config_ratemask_cmd =
378 				send_vdev_config_ratemask_cmd_tlv;
379 }
380