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