1 /*
2  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
3  *
4  * Permission to use, copy, modify, and/or distribute this software for any
5  * purpose with or without fee is hereby granted, provided that the above
6  * copyright notice and this permission notice appear in all copies.
7  *
8  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9  * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10  * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11  * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12  * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13  * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14  * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15  */
16 
17 /**
18  * DOC: target_if_dp_comp.c
19  */
20 
21 #include "target_if_dp_comp.h"
22 #include "target_if.h"
23 #include "qdf_status.h"
24 #include "wmi.h"
25 #include "wmi_unified_api.h"
26 #include "wmi_unified_priv.h"
27 #include "wmi_unified_param.h"
28 #include "wlan_objmgr_psoc_obj.h"
29 #include "wlan_dp_public_struct.h"
30 #include "cdp_txrx_cmn.h"
31 #include "cdp_txrx_ops.h"
32 #include "wlan_dp_main.h"
33 #include <wlan_cm_api.h>
34 
35 /**
36  * target_if_dp_get_arp_stats_event_handler() - arp stats event handler
37  * @scn: scn
38  * @data: buffer with event
39  * @datalen: buffer length
40  *
41  * Return: Return: 0 on success, failure code otherwise.
42  */
43 static int
target_if_dp_get_arp_stats_event_handler(ol_scn_t scn,uint8_t * data,uint32_t datalen)44 target_if_dp_get_arp_stats_event_handler(ol_scn_t scn, uint8_t *data,
45 					 uint32_t datalen)
46 {
47 	WMI_VDEV_GET_ARP_STAT_EVENTID_param_tlvs *param_buf;
48 	wmi_vdev_get_arp_stats_event_fixed_param *data_event;
49 	wmi_vdev_get_connectivity_check_stats *connect_stats_event;
50 	struct wlan_objmgr_psoc *psoc;
51 	struct wlan_dp_psoc_nb_ops *nb_ops;
52 	uint8_t *buf_ptr;
53 	struct dp_rsp_stats rsp = {0};
54 
55 	if (!scn || !data) {
56 		dp_err("scn: 0x%pK, data: 0x%pK", scn, data);
57 		return -EINVAL;
58 	}
59 	param_buf = (WMI_VDEV_GET_ARP_STAT_EVENTID_param_tlvs *)data;
60 	if (!param_buf) {
61 		dp_err("Invalid get arp stats event");
62 		return -EINVAL;
63 	}
64 	data_event = param_buf->fixed_param;
65 	if (!data_event) {
66 		dp_err("Invalid get arp stats data event");
67 		return -EINVAL;
68 	}
69 
70 	psoc = target_if_get_psoc_from_scn_hdl(scn);
71 	if (!psoc) {
72 		dp_err("null psoc");
73 		return -EINVAL;
74 	}
75 
76 	nb_ops = dp_intf_get_rx_ops(psoc);
77 	if (!nb_ops) {
78 		dp_err("null tx ops");
79 		return -EINVAL;
80 	}
81 
82 	rsp.arp_req_enqueue = data_event->arp_req_enqueue;
83 	rsp.vdev_id = data_event->vdev_id;
84 	rsp.arp_req_tx_success = data_event->arp_req_tx_success;
85 	rsp.arp_req_tx_failure = data_event->arp_req_tx_failure;
86 	rsp.arp_rsp_recvd = data_event->arp_rsp_recvd;
87 	rsp.out_of_order_arp_rsp_drop_cnt =
88 		data_event->out_of_order_arp_rsp_drop_cnt;
89 	rsp.dad_detected = data_event->dad_detected;
90 	rsp.connect_status = data_event->connect_status;
91 	rsp.ba_session_establishment_status =
92 		data_event->ba_session_establishment_status;
93 
94 	buf_ptr = (uint8_t *)data_event;
95 	buf_ptr = buf_ptr + sizeof(wmi_vdev_get_arp_stats_event_fixed_param) +
96 		  WMI_TLV_HDR_SIZE;
97 	connect_stats_event = (wmi_vdev_get_connectivity_check_stats *)buf_ptr;
98 
99 	if (((connect_stats_event->tlv_header & 0xFFFF0000) >> 16 ==
100 	      WMITLV_TAG_STRUC_wmi_vdev_get_connectivity_check_stats)) {
101 		rsp.connect_stats_present = true;
102 		rsp.tcp_ack_recvd = connect_stats_event->tcp_ack_recvd;
103 		rsp.icmpv4_rsp_recvd = connect_stats_event->icmpv4_rsp_recvd;
104 		dp_debug("tcp_ack_recvd %d icmpv4_rsp_recvd %d",
105 			 connect_stats_event->tcp_ack_recvd,
106 			 connect_stats_event->icmpv4_rsp_recvd);
107 	}
108 
109 	nb_ops->osif_dp_get_arp_stats_evt(psoc, &rsp);
110 
111 	return QDF_STATUS_SUCCESS;
112 }
113 
114 /**
115  * target_if_dp_arp_stats_register_event_handler() - register event handler
116  * @psoc: psoc handle
117  *
118  * Return: Return: 0 on success, failure code otherwise.
119  */
120 static QDF_STATUS
target_if_dp_arp_stats_register_event_handler(struct wlan_objmgr_psoc * psoc)121 target_if_dp_arp_stats_register_event_handler(struct wlan_objmgr_psoc *psoc)
122 {
123 	struct wmi_unified *wmi_handle;
124 	QDF_STATUS ret_val;
125 
126 	if (!psoc) {
127 		dp_err("PSOC is NULL!");
128 		return QDF_STATUS_E_INVAL;
129 	}
130 
131 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
132 	if (!wmi_handle) {
133 		dp_err("wmi_handle is null");
134 		return QDF_STATUS_E_INVAL;
135 	}
136 
137 	ret_val = wmi_unified_register_event_handler(wmi_handle,
138 				wmi_get_arp_stats_req_id,
139 				target_if_dp_get_arp_stats_event_handler,
140 				WMI_RX_WORK_CTX);
141 	if (QDF_IS_STATUS_ERROR(ret_val))
142 		dp_err("Failed to register event_handler");
143 
144 	return QDF_STATUS_SUCCESS;
145 }
146 
147 /**
148  * target_if_dp_arp_stats_unregister_event_handler() - unregister event handler
149  * @psoc: psoc handle
150  *
151  * Return: Return: 0 on success, failure code otherwise.
152  */
153 static QDF_STATUS
target_if_dp_arp_stats_unregister_event_handler(struct wlan_objmgr_psoc * psoc)154 target_if_dp_arp_stats_unregister_event_handler(struct wlan_objmgr_psoc *psoc)
155 {
156 	struct wmi_unified *wmi_handle;
157 
158 	if (!psoc) {
159 		dp_err("PSOC is NULL!");
160 		return QDF_STATUS_E_INVAL;
161 	}
162 
163 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
164 	if (!wmi_handle) {
165 		dp_err("wmi_handle is null");
166 		return QDF_STATUS_E_INVAL;
167 	}
168 
169 	wmi_unified_unregister_event_handler(wmi_handle,
170 					     wmi_get_arp_stats_req_id);
171 	return QDF_STATUS_SUCCESS;
172 }
173 
174 /**
175  * target_if_dp_get_arp_req_stats() - send get arp stats request command to fw
176  * @psoc: psoc handle
177  * @req_buf: get arp stats request buffer
178  *
179  * Return: Return: 0 on success, failure code otherwise.
180  */
181 static QDF_STATUS
target_if_dp_get_arp_req_stats(struct wlan_objmgr_psoc * psoc,struct dp_get_arp_stats_params * req_buf)182 target_if_dp_get_arp_req_stats(struct wlan_objmgr_psoc *psoc,
183 			       struct dp_get_arp_stats_params *req_buf)
184 {
185 	QDF_STATUS status;
186 	struct get_arp_stats *arp_stats;
187 	struct wmi_unified *wmi_handle;
188 	struct wlan_objmgr_vdev *vdev;
189 
190 	if (!psoc) {
191 		dp_err("PSOC is NULL!");
192 		return QDF_STATUS_E_INVAL;
193 	}
194 
195 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
196 	if (!wmi_handle) {
197 		dp_err("wmi_handle is null");
198 		return QDF_STATUS_E_INVAL;
199 	}
200 
201 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
202 						    req_buf->vdev_id,
203 						    WLAN_DP_ID);
204 	if (!vdev) {
205 		dp_err("Can't get vdev by vdev_id:%d", req_buf->vdev_id);
206 		return QDF_STATUS_E_INVAL;
207 	}
208 	if (!wlan_cm_is_vdev_active(vdev)) {
209 		dp_debug("vdev id:%d is not started", req_buf->vdev_id);
210 		status = QDF_STATUS_E_INVAL;
211 		goto release_ref;
212 	}
213 
214 	arp_stats = (struct get_arp_stats *)req_buf;
215 	status = wmi_unified_get_arp_stats_req(wmi_handle, arp_stats);
216 	if (QDF_IS_STATUS_ERROR(status))
217 		dp_err("failed to send get arp stats to FW");
218 release_ref:
219 	wlan_objmgr_vdev_release_ref(vdev, WLAN_DP_ID);
220 	return status;
221 }
222 
223 /**
224  * target_if_dp_set_arp_req_stats() - send set arp stats request command to fw
225  * @psoc: psoc handle
226  * @req_buf: set srp stats request buffer
227  *
228  * Return: Return: 0 on success, failure code otherwise.
229  */
230 static QDF_STATUS
target_if_dp_set_arp_req_stats(struct wlan_objmgr_psoc * psoc,struct dp_set_arp_stats_params * req_buf)231 target_if_dp_set_arp_req_stats(struct wlan_objmgr_psoc *psoc,
232 			       struct dp_set_arp_stats_params *req_buf)
233 {
234 	QDF_STATUS status;
235 	struct set_arp_stats *arp_stats;
236 	struct wmi_unified *wmi_handle;
237 	struct wlan_objmgr_vdev *vdev;
238 
239 	if (!psoc) {
240 		dp_err("PSOC is NULL!");
241 		return QDF_STATUS_E_INVAL;
242 	}
243 
244 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
245 	if (!wmi_handle) {
246 		dp_err("wmi_handle is null");
247 		return QDF_STATUS_E_INVAL;
248 	}
249 
250 	vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc,
251 						    req_buf->vdev_id,
252 						    WLAN_DP_ID);
253 	if (!vdev) {
254 		dp_err("Can't get vdev by vdev_id:%d", req_buf->vdev_id);
255 		return QDF_STATUS_E_INVAL;
256 	}
257 
258 	status = wlan_vdev_is_up(vdev);
259 	if (QDF_IS_STATUS_ERROR(status)) {
260 		dp_err("vdev id:%d is not started", req_buf->vdev_id);
261 		status = QDF_STATUS_E_INVAL;
262 		goto release_ref;
263 	}
264 	arp_stats = (struct set_arp_stats *)req_buf;
265 	status = wmi_unified_set_arp_stats_req(wmi_handle, arp_stats);
266 	if (QDF_IS_STATUS_ERROR(status))
267 		dp_err("failed to set arp stats to FW");
268 
269 release_ref:
270 	wlan_objmgr_vdev_release_ref(vdev, WLAN_DP_ID);
271 	return status;
272 }
273 
274 /**
275  * target_if_dp_lro_config_cmd() - process the LRO config command
276  * @psoc: Pointer to psoc handle
277  * @dp_lro_cmd: Pointer to LRO configuration parameters
278  *
279  * This function sends down the LRO configuration parameters to
280  * the firmware to enable LRO, sets the TCP flags and sets the
281  * seed values for the toeplitz hash generation
282  *
283  * Return: QDF_STATUS_SUCCESS for success otherwise failure
284  */
285 static QDF_STATUS
target_if_dp_lro_config_cmd(struct wlan_objmgr_psoc * psoc,struct cdp_lro_hash_config * dp_lro_cmd)286 target_if_dp_lro_config_cmd(struct wlan_objmgr_psoc *psoc,
287 			    struct cdp_lro_hash_config *dp_lro_cmd)
288 {
289 	struct wmi_lro_config_cmd_t wmi_lro_cmd = {0};
290 	struct wmi_unified *wmi_handle;
291 
292 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
293 	if (!dp_lro_cmd || !wmi_handle) {
294 		dp_err("wmi_handle or dp_lro_cmd is null");
295 		return QDF_STATUS_E_FAILURE;
296 	}
297 
298 	wmi_lro_cmd.lro_enable = dp_lro_cmd->lro_enable;
299 	wmi_lro_cmd.tcp_flag = dp_lro_cmd->tcp_flag;
300 	wmi_lro_cmd.tcp_flag_mask = dp_lro_cmd->tcp_flag_mask;
301 	qdf_mem_copy(wmi_lro_cmd.toeplitz_hash_ipv4,
302 		     dp_lro_cmd->toeplitz_hash_ipv4,
303 		     LRO_IPV4_SEED_ARR_SZ * sizeof(uint32_t));
304 	qdf_mem_copy(wmi_lro_cmd.toeplitz_hash_ipv6,
305 		     dp_lro_cmd->toeplitz_hash_ipv6,
306 		     LRO_IPV6_SEED_ARR_SZ * sizeof(uint32_t));
307 
308 	return wmi_unified_lro_config_cmd(wmi_handle, &wmi_lro_cmd);
309 }
310 
311 /**
312  * target_if_dp_send_dhcp_ind() - process set arp stats request command to fw
313  * @vdev_id: vdev id
314  * @dhcp_ind: DHCP indication.
315  *
316  * Return: 0 on success, failure code otherwise.
317  */
318 static QDF_STATUS
target_if_dp_send_dhcp_ind(uint16_t vdev_id,struct dp_dhcp_ind * dhcp_ind)319 target_if_dp_send_dhcp_ind(uint16_t vdev_id,
320 			   struct dp_dhcp_ind *dhcp_ind)
321 {
322 	struct wmi_unified *wmi_handle;
323 	struct wlan_objmgr_psoc *psoc;
324 	wmi_peer_set_param_cmd_fixed_param peer_set_param_fp = {0};
325 	QDF_STATUS status;
326 
327 	psoc = wlan_objmgr_get_psoc_by_id(0, WLAN_PSOC_TARGET_IF_ID);
328 	if (!psoc) {
329 		dp_err("psoc null");
330 		return QDF_STATUS_E_INVAL;
331 	}
332 
333 	wmi_handle = get_wmi_unified_hdl_from_psoc(psoc);
334 	if (!wmi_handle) {
335 		dp_err("Unable to get wmi handle");
336 		return QDF_STATUS_E_NULL_VALUE;
337 	}
338 
339 	/* fill in values */
340 	peer_set_param_fp.vdev_id = vdev_id;
341 	peer_set_param_fp.param_id = WMI_HOST_PEER_CRIT_PROTO_HINT_ENABLED;
342 
343 	if (dhcp_ind->dhcp_start)
344 		peer_set_param_fp.param_value = 1;
345 	else
346 		peer_set_param_fp.param_value = 0;
347 
348 	WMI_CHAR_ARRAY_TO_MAC_ADDR(dhcp_ind->peer_mac_addr.bytes,
349 				   &peer_set_param_fp.peer_macaddr);
350 
351 	status = wmi_unified_process_dhcp_ind(wmi_handle,
352 					      &peer_set_param_fp);
353 	wlan_objmgr_psoc_release_ref(psoc, WLAN_PSOC_TARGET_IF_ID);
354 
355 	return status;
356 }
357 
target_if_dp_register_tx_ops(struct wlan_dp_psoc_sb_ops * sb_ops)358 void target_if_dp_register_tx_ops(struct wlan_dp_psoc_sb_ops *sb_ops)
359 {
360 	sb_ops->dp_arp_stats_register_event_handler =
361 		target_if_dp_arp_stats_register_event_handler;
362 	sb_ops->dp_arp_stats_unregister_event_handler =
363 		target_if_dp_arp_stats_unregister_event_handler;
364 	sb_ops->dp_get_arp_req_stats =
365 		target_if_dp_get_arp_req_stats;
366 	sb_ops->dp_set_arp_req_stats =
367 		target_if_dp_set_arp_req_stats;
368 	sb_ops->dp_lro_config_cmd = target_if_dp_lro_config_cmd;
369 	sb_ops->dp_send_dhcp_ind =
370 		target_if_dp_send_dhcp_ind;
371 }
372 
target_if_dp_register_rx_ops(struct wlan_dp_psoc_nb_ops * nb_ops)373 void target_if_dp_register_rx_ops(struct wlan_dp_psoc_nb_ops *nb_ops)
374 {
375 }
376