xref: /wlan-driver/qcacld-3.0/os_if/dp/src/os_if_dp.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1*5113495bSYour Name /*
2*5113495bSYour Name  * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
3*5113495bSYour Name  *
4*5113495bSYour Name  * Permission to use, copy, modify, and/or distribute this software for
5*5113495bSYour Name  * any purpose with or without fee is hereby granted, provided that the
6*5113495bSYour Name  * above copyright notice and this permission notice appear in all
7*5113495bSYour Name  * copies.
8*5113495bSYour Name  *
9*5113495bSYour Name  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10*5113495bSYour Name  * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11*5113495bSYour Name  * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12*5113495bSYour Name  * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13*5113495bSYour Name  * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14*5113495bSYour Name  * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15*5113495bSYour Name  * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16*5113495bSYour Name  * PERFORMANCE OF THIS SOFTWARE.
17*5113495bSYour Name  */
18*5113495bSYour Name  /**
19*5113495bSYour Name   * DOC: os_if_dp.c
20*5113495bSYour Name   *
21*5113495bSYour Name   *
22*5113495bSYour Name   */
23*5113495bSYour Name #include "os_if_dp.h"
24*5113495bSYour Name #include "wlan_nlink_srv.h"
25*5113495bSYour Name #include <wlan_cfg80211.h>
26*5113495bSYour Name #include <wlan_osif_priv.h>
27*5113495bSYour Name #include <cdp_txrx_cmn.h>
28*5113495bSYour Name #include "qca_vendor.h"
29*5113495bSYour Name #include "wlan_dp_ucfg_api.h"
30*5113495bSYour Name #include "osif_vdev_sync.h"
31*5113495bSYour Name #include "osif_sync.h"
32*5113495bSYour Name #include <net/netevent.h>
33*5113495bSYour Name #include "wlan_osif_request_manager.h"
34*5113495bSYour Name #include <ol_defines.h>
35*5113495bSYour Name 
36*5113495bSYour Name /*
37*5113495bSYour Name  * define short names for the global vendor params
38*5113495bSYour Name  * used by wlan_hdd_cfg80211_setarp_stats_cmd()
39*5113495bSYour Name  */
40*5113495bSYour Name #define STATS_GET_INVALID \
41*5113495bSYour Name 	QCA_ATTR_NUD_STATS_SET_INVALID
42*5113495bSYour Name #define COUNT_FROM_NETDEV \
43*5113495bSYour Name 	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_FROM_NETDEV
44*5113495bSYour Name #define COUNT_TO_LOWER_MAC \
45*5113495bSYour Name 	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TO_LOWER_MAC
46*5113495bSYour Name #define RX_COUNT_BY_LOWER_MAC \
47*5113495bSYour Name 	QCA_ATTR_NUD_STATS_ARP_REQ_RX_COUNT_BY_LOWER_MAC
48*5113495bSYour Name #define COUNT_TX_SUCCESS \
49*5113495bSYour Name 	QCA_ATTR_NUD_STATS_ARP_REQ_COUNT_TX_SUCCESS
50*5113495bSYour Name #define RSP_RX_COUNT_BY_LOWER_MAC \
51*5113495bSYour Name 	QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_LOWER_MAC
52*5113495bSYour Name #define RSP_RX_COUNT_BY_UPPER_MAC \
53*5113495bSYour Name 	QCA_ATTR_NUD_STATS_ARP_RSP_RX_COUNT_BY_UPPER_MAC
54*5113495bSYour Name #define RSP_COUNT_TO_NETDEV \
55*5113495bSYour Name 	QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_TO_NETDEV
56*5113495bSYour Name #define RSP_COUNT_OUT_OF_ORDER_DROP \
57*5113495bSYour Name 	QCA_ATTR_NUD_STATS_ARP_RSP_COUNT_OUT_OF_ORDER_DROP
58*5113495bSYour Name #define AP_LINK_ACTIVE \
59*5113495bSYour Name 	QCA_ATTR_NUD_STATS_AP_LINK_ACTIVE
60*5113495bSYour Name #define AP_LINK_DAD \
61*5113495bSYour Name 	QCA_ATTR_NUD_STATS_IS_DAD
62*5113495bSYour Name #define DATA_PKT_STATS \
63*5113495bSYour Name 	QCA_ATTR_NUD_STATS_DATA_PKT_STATS
64*5113495bSYour Name #define STATS_GET_MAX \
65*5113495bSYour Name 	QCA_ATTR_NUD_STATS_GET_MAX
66*5113495bSYour Name 
67*5113495bSYour Name #define CHECK_STATS_INVALID \
68*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_INVALID
69*5113495bSYour Name #define CHECK_STATS_PKT_TYPE \
70*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_TYPE
71*5113495bSYour Name #define CHECK_STATS_PKT_DNS_DOMAIN_NAME \
72*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DNS_DOMAIN_NAME
73*5113495bSYour Name #define CHECK_STATS_PKT_SRC_PORT \
74*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_SRC_PORT
75*5113495bSYour Name #define CHECK_STATS_PKT_DEST_PORT \
76*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_PORT
77*5113495bSYour Name #define CHECK_STATS_PKT_DEST_IPV4 \
78*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV4
79*5113495bSYour Name #define CHECK_STATS_PKT_DEST_IPV6 \
80*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_DEST_IPV6
81*5113495bSYour Name #define CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV \
82*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV
83*5113495bSYour Name #define CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC \
84*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC
85*5113495bSYour Name #define CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC \
86*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC
87*5113495bSYour Name #define CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS \
88*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS
89*5113495bSYour Name #define CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC \
90*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC
91*5113495bSYour Name #define CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC \
92*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC
93*5113495bSYour Name #define CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV \
94*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV
95*5113495bSYour Name #define CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP \
96*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP
97*5113495bSYour Name #define CHECK_DATA_STATS_MAX \
98*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_DATA_STATS_MAX
99*5113495bSYour Name 
100*5113495bSYour Name #define STATS_SET_INVALID \
101*5113495bSYour Name 	QCA_ATTR_NUD_STATS_SET_INVALID
102*5113495bSYour Name #define STATS_SET_START \
103*5113495bSYour Name 	QCA_ATTR_NUD_STATS_SET_START
104*5113495bSYour Name #define STATS_GW_IPV4 \
105*5113495bSYour Name 	QCA_ATTR_NUD_STATS_GW_IPV4
106*5113495bSYour Name #define STATS_SET_DATA_PKT_INFO \
107*5113495bSYour Name 		QCA_ATTR_NUD_STATS_SET_DATA_PKT_INFO
108*5113495bSYour Name #define STATS_SET_MAX \
109*5113495bSYour Name 	QCA_ATTR_NUD_STATS_SET_MAX
110*5113495bSYour Name 
111*5113495bSYour Name const struct nla_policy
112*5113495bSYour Name dp_set_nud_stats_policy[STATS_SET_MAX + 1] = {
113*5113495bSYour Name 	[STATS_SET_START] = {.type = NLA_FLAG },
114*5113495bSYour Name 	[STATS_GW_IPV4] = {.type = NLA_U32 },
115*5113495bSYour Name 	[STATS_SET_DATA_PKT_INFO] = {.type = NLA_NESTED },
116*5113495bSYour Name };
117*5113495bSYour Name 
118*5113495bSYour Name /* define short names for the global vendor params */
119*5113495bSYour Name #define CONNECTIVITY_STATS_SET_INVALID \
120*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_INVALID
121*5113495bSYour Name #define STATS_PKT_INFO_TYPE \
122*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_STATS_PKT_INFO_TYPE
123*5113495bSYour Name #define STATS_DNS_DOMAIN_NAME \
124*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DNS_DOMAIN_NAME
125*5113495bSYour Name #define STATS_SRC_PORT \
126*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_SRC_PORT
127*5113495bSYour Name #define STATS_DEST_PORT \
128*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_PORT
129*5113495bSYour Name #define STATS_DEST_IPV4 \
130*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV4
131*5113495bSYour Name #define STATS_DEST_IPV6 \
132*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_DEST_IPV6
133*5113495bSYour Name #define CONNECTIVITY_STATS_SET_MAX \
134*5113495bSYour Name 	QCA_ATTR_CONNECTIVITY_CHECK_STATS_SET_MAX
135*5113495bSYour Name 
136*5113495bSYour Name const struct nla_policy
137*5113495bSYour Name dp_set_connectivity_check_stats[CONNECTIVITY_STATS_SET_MAX + 1] = {
138*5113495bSYour Name 	[STATS_PKT_INFO_TYPE] = {.type = NLA_U32 },
139*5113495bSYour Name 	[STATS_DNS_DOMAIN_NAME] = {.type = NLA_NUL_STRING,
140*5113495bSYour Name 					.len = DNS_DOMAIN_NAME_MAX_LEN },
141*5113495bSYour Name 	[STATS_SRC_PORT] = {.type = NLA_U32 },
142*5113495bSYour Name 	[STATS_DEST_PORT] = {.type = NLA_U32 },
143*5113495bSYour Name 	[STATS_DEST_IPV4] = {.type = NLA_U32 },
144*5113495bSYour Name 	[STATS_DEST_IPV6] = {.type = NLA_BINARY,
145*5113495bSYour Name 			.len = ICMPV6_ADDR_LEN },
146*5113495bSYour Name };
147*5113495bSYour Name 
148*5113495bSYour Name #ifdef WLAN_FEATURE_DP_BUS_BANDWIDTH
149*5113495bSYour Name /**
150*5113495bSYour Name  * osif_dp_send_tcp_param_update_event() - Send vendor event to update
151*5113495bSYour Name  * TCP parameter through Wi-Fi HAL
152*5113495bSYour Name  * @psoc: Pointer to psoc context
153*5113495bSYour Name  * @data: Parameters to update
154*5113495bSYour Name  * @dir: Direction(tx/rx) to update
155*5113495bSYour Name  *
156*5113495bSYour Name  * Return: None
157*5113495bSYour Name  */
158*5113495bSYour Name static
osif_dp_send_tcp_param_update_event(struct wlan_objmgr_psoc * psoc,union wlan_tp_data * data,uint8_t dir)159*5113495bSYour Name void osif_dp_send_tcp_param_update_event(struct wlan_objmgr_psoc *psoc,
160*5113495bSYour Name 					 union wlan_tp_data *data,
161*5113495bSYour Name 					 uint8_t dir)
162*5113495bSYour Name {
163*5113495bSYour Name 	struct sk_buff *vendor_event;
164*5113495bSYour Name 	struct wlan_objmgr_pdev *pdev;
165*5113495bSYour Name 	struct pdev_osif_priv *os_priv;
166*5113495bSYour Name 	uint32_t event_len;
167*5113495bSYour Name 	bool tcp_limit_output = false;
168*5113495bSYour Name 	bool tcp_del_ack_ind_enabled = false;
169*5113495bSYour Name 	bool tcp_adv_win_scl_enabled = false;
170*5113495bSYour Name 	enum wlan_tp_level next_tp_level = WLAN_SVC_TP_NONE;
171*5113495bSYour Name 	enum qca_nl80211_vendor_subcmds_index index =
172*5113495bSYour Name 		QCA_NL80211_VENDOR_SUBCMD_THROUGHPUT_CHANGE_EVENT_INDEX;
173*5113495bSYour Name 
174*5113495bSYour Name 	event_len = sizeof(uint8_t) + sizeof(uint8_t) + NLMSG_HDRLEN;
175*5113495bSYour Name 	pdev = wlan_objmgr_get_pdev_by_id(psoc, 0, WLAN_DP_ID);
176*5113495bSYour Name 	if (!pdev)
177*5113495bSYour Name 		return;
178*5113495bSYour Name 
179*5113495bSYour Name 	os_priv = wlan_pdev_get_ospriv(pdev);
180*5113495bSYour Name 
181*5113495bSYour Name 	if (dir == 0) /*TX Flow */ {
182*5113495bSYour Name 		struct wlan_tx_tp_data *tx_tp_data =
183*5113495bSYour Name 				(struct wlan_tx_tp_data *)data;
184*5113495bSYour Name 
185*5113495bSYour Name 		next_tp_level = tx_tp_data->level;
186*5113495bSYour Name 
187*5113495bSYour Name 		if (tx_tp_data->tcp_limit_output) {
188*5113495bSYour Name 			/* TCP_LIMIT_OUTPUT_BYTES */
189*5113495bSYour Name 			event_len += sizeof(uint32_t);
190*5113495bSYour Name 			tcp_limit_output = true;
191*5113495bSYour Name 		}
192*5113495bSYour Name 	} else if (dir == 1) /* RX Flow */ {
193*5113495bSYour Name 		struct wlan_rx_tp_data *rx_tp_data =
194*5113495bSYour Name 				(struct wlan_rx_tp_data *)data;
195*5113495bSYour Name 
196*5113495bSYour Name 		next_tp_level = rx_tp_data->level;
197*5113495bSYour Name 
198*5113495bSYour Name 		if (rx_tp_data->rx_tp_flags & TCP_DEL_ACK_IND_MASK) {
199*5113495bSYour Name 			event_len += sizeof(uint32_t); /* TCP_DELACK_SEG */
200*5113495bSYour Name 			tcp_del_ack_ind_enabled = true;
201*5113495bSYour Name 		}
202*5113495bSYour Name 		if (rx_tp_data->rx_tp_flags & TCP_ADV_WIN_SCL_MASK) {
203*5113495bSYour Name 			event_len += sizeof(uint32_t); /* TCP_ADV_WIN_SCALE */
204*5113495bSYour Name 			tcp_adv_win_scl_enabled = true;
205*5113495bSYour Name 		}
206*5113495bSYour Name 	} else {
207*5113495bSYour Name 		dp_err("Invalid Direction [%d]", dir);
208*5113495bSYour Name 		wlan_objmgr_pdev_release_ref(pdev, WLAN_DP_ID);
209*5113495bSYour Name 		return;
210*5113495bSYour Name 	}
211*5113495bSYour Name 
212*5113495bSYour Name 	vendor_event = wlan_cfg80211_vendor_event_alloc(os_priv->wiphy,
213*5113495bSYour Name 							NULL, event_len,
214*5113495bSYour Name 							index, GFP_KERNEL);
215*5113495bSYour Name 
216*5113495bSYour Name 	if (!vendor_event) {
217*5113495bSYour Name 		dp_err("wlan_cfg80211_vendor_event_alloc failed");
218*5113495bSYour Name 		wlan_objmgr_pdev_release_ref(pdev, WLAN_DP_ID);
219*5113495bSYour Name 		return;
220*5113495bSYour Name 	}
221*5113495bSYour Name 
222*5113495bSYour Name 	if (nla_put_u8(
223*5113495bSYour Name 		vendor_event,
224*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_DIRECTION,
225*5113495bSYour Name 		dir))
226*5113495bSYour Name 		goto tcp_param_change_nla_failed;
227*5113495bSYour Name 
228*5113495bSYour Name 	if (nla_put_u8(
229*5113495bSYour Name 		vendor_event,
230*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_THROUGHPUT_LEVEL,
231*5113495bSYour Name 		(next_tp_level == WLAN_SVC_TP_LOW ?
232*5113495bSYour Name 		QCA_WLAN_THROUGHPUT_LEVEL_LOW :
233*5113495bSYour Name 		QCA_WLAN_THROUGHPUT_LEVEL_HIGH)))
234*5113495bSYour Name 		goto tcp_param_change_nla_failed;
235*5113495bSYour Name 
236*5113495bSYour Name 	if (tcp_limit_output &&
237*5113495bSYour Name 	    nla_put_u32(
238*5113495bSYour Name 		vendor_event,
239*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_LIMIT_OUTPUT_BYTES,
240*5113495bSYour Name 		(next_tp_level == WLAN_SVC_TP_LOW ?
241*5113495bSYour Name 		 TCP_LIMIT_OUTPUT_BYTES_LOW :
242*5113495bSYour Name 		 TCP_LIMIT_OUTPUT_BYTES_HI)))
243*5113495bSYour Name 		goto tcp_param_change_nla_failed;
244*5113495bSYour Name 
245*5113495bSYour Name 	if (tcp_del_ack_ind_enabled &&
246*5113495bSYour Name 	    (nla_put_u32(
247*5113495bSYour Name 		vendor_event,
248*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_DELACK_SEG,
249*5113495bSYour Name 		(next_tp_level == WLAN_SVC_TP_LOW ?
250*5113495bSYour Name 		 TCP_DEL_ACK_LOW : TCP_DEL_ACK_HI))))
251*5113495bSYour Name 		goto tcp_param_change_nla_failed;
252*5113495bSYour Name 
253*5113495bSYour Name 	if (tcp_adv_win_scl_enabled &&
254*5113495bSYour Name 	    (nla_put_u32(
255*5113495bSYour Name 		vendor_event,
256*5113495bSYour Name 		QCA_WLAN_VENDOR_ATTR_THROUGHPUT_CHANGE_TCP_ADV_WIN_SCALE,
257*5113495bSYour Name 		(next_tp_level == WLAN_SVC_TP_LOW ?
258*5113495bSYour Name 		 WIN_SCALE_LOW : WIN_SCALE_HI))))
259*5113495bSYour Name 		goto tcp_param_change_nla_failed;
260*5113495bSYour Name 
261*5113495bSYour Name 	wlan_cfg80211_vendor_event(vendor_event, GFP_KERNEL);
262*5113495bSYour Name 	wlan_objmgr_pdev_release_ref(pdev, WLAN_DP_ID);
263*5113495bSYour Name 	return;
264*5113495bSYour Name 
265*5113495bSYour Name tcp_param_change_nla_failed:
266*5113495bSYour Name 	wlan_objmgr_pdev_release_ref(pdev, WLAN_DP_ID);
267*5113495bSYour Name 	dp_err("nla_put api failed");
268*5113495bSYour Name 	wlan_cfg80211_vendor_free_skb(vendor_event);
269*5113495bSYour Name }
270*5113495bSYour Name #else
271*5113495bSYour Name static
osif_dp_send_tcp_param_update_event(struct wlan_objmgr_psoc * psoc,union wlan_tp_data * data,uint8_t dir)272*5113495bSYour Name void osif_dp_send_tcp_param_update_event(struct wlan_objmgr_psoc *psoc,
273*5113495bSYour Name 					 union wlan_tp_data *data,
274*5113495bSYour Name 					 uint8_t dir)
275*5113495bSYour Name {
276*5113495bSYour Name }
277*5113495bSYour Name #endif /*WLAN_FEATURE_DP_BUS_BANDWIDTH*/
278*5113495bSYour Name 
279*5113495bSYour Name /**
280*5113495bSYour Name  * osif_dp_get_net_dev_from_vdev() - Get netdev object from vdev
281*5113495bSYour Name  * @vdev: Pointer to vdev manager
282*5113495bSYour Name  * @out_net_dev: Pointer to output netdev
283*5113495bSYour Name  *
284*5113495bSYour Name  * Return: 0 on success, error code on failure
285*5113495bSYour Name  */
osif_dp_get_net_dev_from_vdev(struct wlan_objmgr_vdev * vdev,struct net_device ** out_net_dev)286*5113495bSYour Name static int osif_dp_get_net_dev_from_vdev(struct wlan_objmgr_vdev *vdev,
287*5113495bSYour Name 					 struct net_device **out_net_dev)
288*5113495bSYour Name {
289*5113495bSYour Name 	struct vdev_osif_priv *priv;
290*5113495bSYour Name 
291*5113495bSYour Name 	if (!vdev)
292*5113495bSYour Name 		return -EINVAL;
293*5113495bSYour Name 
294*5113495bSYour Name 	priv = wlan_vdev_get_ospriv(vdev);
295*5113495bSYour Name 	if (!priv || !priv->wdev || !priv->wdev->netdev)
296*5113495bSYour Name 		return -EINVAL;
297*5113495bSYour Name 
298*5113495bSYour Name 	*out_net_dev = priv->wdev->netdev;
299*5113495bSYour Name 
300*5113495bSYour Name 	return 0;
301*5113495bSYour Name }
302*5113495bSYour Name 
303*5113495bSYour Name /**
304*5113495bSYour Name  * osif_dp_process_mic_error() - Indicate mic error to supplicant
305*5113495bSYour Name  * @info: MIC error information
306*5113495bSYour Name  * @vdev: vdev handle
307*5113495bSYour Name  *
308*5113495bSYour Name  * Return: None
309*5113495bSYour Name  */
310*5113495bSYour Name static void
osif_dp_process_mic_error(struct dp_mic_error_info * info,struct wlan_objmgr_vdev * vdev)311*5113495bSYour Name osif_dp_process_mic_error(struct dp_mic_error_info *info,
312*5113495bSYour Name 			  struct wlan_objmgr_vdev *vdev)
313*5113495bSYour Name {
314*5113495bSYour Name 	struct net_device *dev;
315*5113495bSYour Name 	struct osif_vdev_sync *vdev_sync;
316*5113495bSYour Name 	int errno;
317*5113495bSYour Name 
318*5113495bSYour Name 	errno = osif_dp_get_net_dev_from_vdev(vdev, &dev);
319*5113495bSYour Name 	if (errno) {
320*5113495bSYour Name 		dp_err("failed to get netdev");
321*5113495bSYour Name 		return;
322*5113495bSYour Name 	}
323*5113495bSYour Name 	if (osif_vdev_sync_op_start(dev, &vdev_sync))
324*5113495bSYour Name 		return;
325*5113495bSYour Name 
326*5113495bSYour Name 	/* inform mic failure to nl80211 */
327*5113495bSYour Name 	cfg80211_michael_mic_failure(dev,
328*5113495bSYour Name 				     (uint8_t *)&info->ta_mac_addr,
329*5113495bSYour Name 				     info->multicast ?
330*5113495bSYour Name 				     NL80211_KEYTYPE_GROUP :
331*5113495bSYour Name 				     NL80211_KEYTYPE_PAIRWISE,
332*5113495bSYour Name 				     info->key_id,
333*5113495bSYour Name 				     info->tsc,
334*5113495bSYour Name 				     GFP_KERNEL);
335*5113495bSYour Name 	osif_vdev_sync_op_stop(vdev_sync);
336*5113495bSYour Name }
337*5113495bSYour Name 
338*5113495bSYour Name 
339*5113495bSYour Name /**
340*5113495bSYour Name  * osif_dp_get_arp_stats_event_handler() - ARP get stats event handler
341*5113495bSYour Name  * @psoc: psoc handle
342*5113495bSYour Name  * @rsp: Get ARP stats response
343*5113495bSYour Name  *
344*5113495bSYour Name  * Return: None
345*5113495bSYour Name  */
osif_dp_get_arp_stats_event_handler(struct wlan_objmgr_psoc * psoc,struct dp_rsp_stats * rsp)346*5113495bSYour Name static void osif_dp_get_arp_stats_event_handler(struct wlan_objmgr_psoc *psoc,
347*5113495bSYour Name 						struct dp_rsp_stats *rsp)
348*5113495bSYour Name {
349*5113495bSYour Name 	struct osif_request *request = NULL;
350*5113495bSYour Name 	void *context;
351*5113495bSYour Name 
352*5113495bSYour Name 	context = ucfg_dp_get_arp_request_ctx(psoc);
353*5113495bSYour Name 	if (!context)
354*5113495bSYour Name 		return;
355*5113495bSYour Name 
356*5113495bSYour Name 	request = osif_request_get(context);
357*5113495bSYour Name 	if (!request)
358*5113495bSYour Name 		return;
359*5113495bSYour Name 
360*5113495bSYour Name 	ucfg_dp_get_arp_stats_event_handler(psoc, rsp);
361*5113495bSYour Name 
362*5113495bSYour Name 	osif_request_complete(request);
363*5113495bSYour Name 	osif_request_put(request);
364*5113495bSYour Name }
365*5113495bSYour Name 
366*5113495bSYour Name #ifdef WLAN_NUD_TRACKING
367*5113495bSYour Name /**
368*5113495bSYour Name  * nud_state_osif_to_dp() - convert os_if to enum
369*5113495bSYour Name  * @curr_state: Current NUD state
370*5113495bSYour Name  *
371*5113495bSYour Name  * Return: DP enum equivalent to NUD state
372*5113495bSYour Name  */
nud_state_osif_to_dp(uint8_t curr_state)373*5113495bSYour Name static inline enum dp_nud_state nud_state_osif_to_dp(uint8_t curr_state)
374*5113495bSYour Name {
375*5113495bSYour Name 	switch (curr_state) {
376*5113495bSYour Name 	case NUD_NONE:
377*5113495bSYour Name 		return DP_NUD_NONE;
378*5113495bSYour Name 	case NUD_INCOMPLETE:
379*5113495bSYour Name 		return DP_NUD_INCOMPLETE;
380*5113495bSYour Name 	case NUD_REACHABLE:
381*5113495bSYour Name 		return DP_NUD_REACHABLE;
382*5113495bSYour Name 	case NUD_STALE:
383*5113495bSYour Name 		return DP_NUD_STALE;
384*5113495bSYour Name 	case NUD_DELAY:
385*5113495bSYour Name 		return DP_NUD_DELAY;
386*5113495bSYour Name 	case NUD_PROBE:
387*5113495bSYour Name 		return DP_NUD_PROBE;
388*5113495bSYour Name 	case NUD_FAILED:
389*5113495bSYour Name 		return DP_NUD_FAILED;
390*5113495bSYour Name 	case NUD_NOARP:
391*5113495bSYour Name 		return DP_NUD_NOARP;
392*5113495bSYour Name 	case NUD_PERMANENT:
393*5113495bSYour Name 		return DP_NUD_PERMANENT;
394*5113495bSYour Name 	default:
395*5113495bSYour Name 		return DP_NUD_STATE_INVALID;
396*5113495bSYour Name 	}
397*5113495bSYour Name }
398*5113495bSYour Name 
399*5113495bSYour Name /**
400*5113495bSYour Name  * os_if_dp_nud_stats_info() - print NUD stats info
401*5113495bSYour Name  * @vdev: vdev handle
402*5113495bSYour Name  *
403*5113495bSYour Name  * Return: None
404*5113495bSYour Name  */
os_if_dp_nud_stats_info(struct wlan_objmgr_vdev * vdev)405*5113495bSYour Name static void os_if_dp_nud_stats_info(struct wlan_objmgr_vdev *vdev)
406*5113495bSYour Name {
407*5113495bSYour Name 	struct netdev_queue *txq;
408*5113495bSYour Name 	struct net_device *net_dev;
409*5113495bSYour Name 	int i = 0, errno;
410*5113495bSYour Name 
411*5113495bSYour Name 	errno = osif_dp_get_net_dev_from_vdev(vdev, &net_dev);
412*5113495bSYour Name 	if (errno) {
413*5113495bSYour Name 		dp_err("failed to get netdev");
414*5113495bSYour Name 		return;
415*5113495bSYour Name 	}
416*5113495bSYour Name 	dp_info("carrier state: %d", netif_carrier_ok(net_dev));
417*5113495bSYour Name 
418*5113495bSYour Name 	for (i = 0; i < NUM_TX_QUEUES; i++) {
419*5113495bSYour Name 		txq = netdev_get_tx_queue(net_dev, i);
420*5113495bSYour Name 		dp_info("Queue: %d status: %d txq->trans_start: %lu",
421*5113495bSYour Name 			i, netif_tx_queue_stopped(txq), txq->trans_start);
422*5113495bSYour Name 	}
423*5113495bSYour Name }
424*5113495bSYour Name 
425*5113495bSYour Name /**
426*5113495bSYour Name  * os_if_dp_nud_netevent_cb() - netevent callback
427*5113495bSYour Name  * @nb: Pointer to notifier block
428*5113495bSYour Name  * @event: Net Event triggered
429*5113495bSYour Name  * @data: Pointer to neighbour struct
430*5113495bSYour Name  *
431*5113495bSYour Name  * Callback for netevent
432*5113495bSYour Name  *
433*5113495bSYour Name  * Return: 0 on success
434*5113495bSYour Name  */
os_if_dp_nud_netevent_cb(struct notifier_block * nb,unsigned long event,void * data)435*5113495bSYour Name static int os_if_dp_nud_netevent_cb(struct notifier_block *nb,
436*5113495bSYour Name 				    unsigned long event,
437*5113495bSYour Name 				    void *data)
438*5113495bSYour Name {
439*5113495bSYour Name 	struct neighbour *neighbor = data;
440*5113495bSYour Name 	struct osif_vdev_sync *vdev_sync;
441*5113495bSYour Name 	const struct net_device *netdev = neighbor->dev;
442*5113495bSYour Name 	int errno;
443*5113495bSYour Name 
444*5113495bSYour Name 	errno = osif_vdev_sync_op_start(neighbor->dev, &vdev_sync);
445*5113495bSYour Name 	if (errno)
446*5113495bSYour Name 		return errno;
447*5113495bSYour Name 
448*5113495bSYour Name 	switch (event) {
449*5113495bSYour Name 	case NETEVENT_NEIGH_UPDATE:
450*5113495bSYour Name 		ucfg_dp_nud_event((struct qdf_mac_addr *)netdev->dev_addr,
451*5113495bSYour Name 				  (struct qdf_mac_addr *)&neighbor->ha[0],
452*5113495bSYour Name 				  nud_state_osif_to_dp(neighbor->nud_state));
453*5113495bSYour Name 		break;
454*5113495bSYour Name 	default:
455*5113495bSYour Name 		break;
456*5113495bSYour Name 	}
457*5113495bSYour Name 
458*5113495bSYour Name 	osif_vdev_sync_op_stop(vdev_sync);
459*5113495bSYour Name 
460*5113495bSYour Name 	return 0;
461*5113495bSYour Name }
462*5113495bSYour Name 
463*5113495bSYour Name static struct notifier_block wlan_netevent_nb = {
464*5113495bSYour Name 	.notifier_call = os_if_dp_nud_netevent_cb
465*5113495bSYour Name };
466*5113495bSYour Name 
osif_dp_nud_register_netevent_notifier(struct wlan_objmgr_psoc * psoc)467*5113495bSYour Name int osif_dp_nud_register_netevent_notifier(struct wlan_objmgr_psoc *psoc)
468*5113495bSYour Name {
469*5113495bSYour Name 	int ret = 0;
470*5113495bSYour Name 
471*5113495bSYour Name 	if (ucfg_dp_nud_tracking_enabled(psoc)) {
472*5113495bSYour Name 		ret = register_netevent_notifier(&wlan_netevent_nb);
473*5113495bSYour Name 		if (!ret)
474*5113495bSYour Name 			dp_info("Registered netevent notifier");
475*5113495bSYour Name 	}
476*5113495bSYour Name 	return ret;
477*5113495bSYour Name }
478*5113495bSYour Name 
osif_dp_nud_unregister_netevent_notifier(struct wlan_objmgr_psoc * psoc)479*5113495bSYour Name void osif_dp_nud_unregister_netevent_notifier(struct wlan_objmgr_psoc *psoc)
480*5113495bSYour Name {
481*5113495bSYour Name 	int ret = 0;
482*5113495bSYour Name 
483*5113495bSYour Name 	if (ucfg_dp_nud_tracking_enabled(psoc)) {
484*5113495bSYour Name 		ret = unregister_netevent_notifier(&wlan_netevent_nb);
485*5113495bSYour Name 		if (!ret)
486*5113495bSYour Name 			dp_info("Unregistered netevent notifier");
487*5113495bSYour Name 	}
488*5113495bSYour Name }
489*5113495bSYour Name #else
os_if_dp_nud_stats_info(struct wlan_objmgr_vdev * vdev)490*5113495bSYour Name static void os_if_dp_nud_stats_info(struct wlan_objmgr_vdev *vdev)
491*5113495bSYour Name {
492*5113495bSYour Name }
493*5113495bSYour Name 
osif_dp_nud_register_netevent_notifier(struct wlan_objmgr_psoc * psoc)494*5113495bSYour Name int osif_dp_nud_register_netevent_notifier(struct wlan_objmgr_psoc *psoc)
495*5113495bSYour Name {
496*5113495bSYour Name 	return 0;
497*5113495bSYour Name }
498*5113495bSYour Name 
osif_dp_nud_unregister_netevent_notifier(struct wlan_objmgr_psoc * psoc)499*5113495bSYour Name void osif_dp_nud_unregister_netevent_notifier(struct wlan_objmgr_psoc *psoc)
500*5113495bSYour Name {
501*5113495bSYour Name }
502*5113495bSYour Name #endif
503*5113495bSYour Name 
504*5113495bSYour Name /**
505*5113495bSYour Name  * dp_dns_unmake_name_query() - Convert an uncompressed DNS name to a
506*5113495bSYour Name  *			     NUL-terminated string
507*5113495bSYour Name  * @name: DNS name
508*5113495bSYour Name  *
509*5113495bSYour Name  * Return: Produce a printable version of a DNS name.
510*5113495bSYour Name  */
dp_dns_unmake_name_query(uint8_t * name)511*5113495bSYour Name static inline uint8_t *dp_dns_unmake_name_query(uint8_t *name)
512*5113495bSYour Name {
513*5113495bSYour Name 	uint8_t *p;
514*5113495bSYour Name 	unsigned int len;
515*5113495bSYour Name 
516*5113495bSYour Name 	p = name;
517*5113495bSYour Name 	while ((len = *p)) {
518*5113495bSYour Name 		*(p++) = '.';
519*5113495bSYour Name 		p += len;
520*5113495bSYour Name 	}
521*5113495bSYour Name 
522*5113495bSYour Name 	return name + 1;
523*5113495bSYour Name }
524*5113495bSYour Name 
525*5113495bSYour Name /**
526*5113495bSYour Name  * dp_dns_make_name_query() - Convert a standard NUL-terminated string
527*5113495bSYour Name  *				to DNS name
528*5113495bSYour Name  * @string: Name as a NUL-terminated string
529*5113495bSYour Name  * @buf: Buffer in which to place DNS name
530*5113495bSYour Name  * @len: BUffer length
531*5113495bSYour Name  *
532*5113495bSYour Name  * DNS names consist of "<length>element" pairs.
533*5113495bSYour Name  *
534*5113495bSYour Name  * Return: Byte following constructed DNS name
535*5113495bSYour Name  */
dp_dns_make_name_query(const uint8_t * string,uint8_t * buf,uint8_t len)536*5113495bSYour Name static uint8_t *dp_dns_make_name_query(const uint8_t *string,
537*5113495bSYour Name 				       uint8_t *buf, uint8_t len)
538*5113495bSYour Name {
539*5113495bSYour Name 	uint8_t *length_byte = buf++;
540*5113495bSYour Name 	uint8_t c;
541*5113495bSYour Name 
542*5113495bSYour Name 	if (string[len - 1]) {
543*5113495bSYour Name 		dp_err("DNS name is not null terminated");
544*5113495bSYour Name 		return NULL;
545*5113495bSYour Name 	}
546*5113495bSYour Name 
547*5113495bSYour Name 	while ((c = *(string++))) {
548*5113495bSYour Name 		if (c == '.') {
549*5113495bSYour Name 			*length_byte = buf - length_byte - 1;
550*5113495bSYour Name 			length_byte = buf;
551*5113495bSYour Name 		}
552*5113495bSYour Name 		*(buf++) = c;
553*5113495bSYour Name 	}
554*5113495bSYour Name 	*length_byte = buf - length_byte - 1;
555*5113495bSYour Name 	*(buf++) = '\0';
556*5113495bSYour Name 	return buf;
557*5113495bSYour Name }
558*5113495bSYour Name 
559*5113495bSYour Name /**
560*5113495bSYour Name  * osif_dp_set_clear_connectivity_check_stats_info() - set/clear stats info
561*5113495bSYour Name  * @vdev: vdev context
562*5113495bSYour Name  * @arp_stats_params: arp stats structure to be sent to FW
563*5113495bSYour Name  * @tb: nl attribute
564*5113495bSYour Name  * @is_set_stats: set/clear stats
565*5113495bSYour Name  *
566*5113495bSYour Name  *
567*5113495bSYour Name  * Return: 0 on success, negative errno on failure
568*5113495bSYour Name  */
osif_dp_set_clear_connectivity_check_stats_info(struct wlan_objmgr_vdev * vdev,struct dp_set_arp_stats_params * arp_stats_params,struct nlattr ** tb,bool is_set_stats)569*5113495bSYour Name static int osif_dp_set_clear_connectivity_check_stats_info(
570*5113495bSYour Name 		struct wlan_objmgr_vdev *vdev,
571*5113495bSYour Name 		struct dp_set_arp_stats_params *arp_stats_params,
572*5113495bSYour Name 		struct nlattr **tb, bool is_set_stats)
573*5113495bSYour Name {
574*5113495bSYour Name 	struct nlattr *tb2[CONNECTIVITY_STATS_SET_MAX + 1];
575*5113495bSYour Name 	struct nlattr *curr_attr = NULL;
576*5113495bSYour Name 	int err = 0;
577*5113495bSYour Name 	uint32_t pkt_bitmap;
578*5113495bSYour Name 	int rem;
579*5113495bSYour Name 	uint8_t dns_payload[256];
580*5113495bSYour Name 	uint32_t pkt_type_bitmap = ucfg_dp_get_pkt_type_bitmap_value(vdev);
581*5113495bSYour Name 
582*5113495bSYour Name 	/* Set NUD command for start tracking is received. */
583*5113495bSYour Name 	nla_for_each_nested(curr_attr,
584*5113495bSYour Name 			    tb[STATS_SET_DATA_PKT_INFO],
585*5113495bSYour Name 			    rem) {
586*5113495bSYour Name 		if (wlan_cfg80211_nla_parse(tb2,
587*5113495bSYour Name 				CONNECTIVITY_STATS_SET_MAX,
588*5113495bSYour Name 				nla_data(curr_attr), nla_len(curr_attr),
589*5113495bSYour Name 				dp_set_connectivity_check_stats)) {
590*5113495bSYour Name 			dp_err("nla_parse failed");
591*5113495bSYour Name 			err = -EINVAL;
592*5113495bSYour Name 			goto end;
593*5113495bSYour Name 		}
594*5113495bSYour Name 
595*5113495bSYour Name 		if (tb2[STATS_PKT_INFO_TYPE]) {
596*5113495bSYour Name 			pkt_bitmap = nla_get_u32(tb2[STATS_PKT_INFO_TYPE]);
597*5113495bSYour Name 			if (!pkt_bitmap) {
598*5113495bSYour Name 				dp_err("pkt tracking bitmap is empty");
599*5113495bSYour Name 				err = -EINVAL;
600*5113495bSYour Name 				goto end;
601*5113495bSYour Name 			}
602*5113495bSYour Name 
603*5113495bSYour Name 			if (is_set_stats) {
604*5113495bSYour Name 				arp_stats_params->pkt_type_bitmap = pkt_bitmap;
605*5113495bSYour Name 				arp_stats_params->flag = true;
606*5113495bSYour Name 				pkt_type_bitmap |=
607*5113495bSYour Name 					arp_stats_params->pkt_type_bitmap;
608*5113495bSYour Name 				ucfg_dp_set_pkt_type_bitmap_value(vdev,
609*5113495bSYour Name 								  pkt_type_bitmap);
610*5113495bSYour Name 
611*5113495bSYour Name 				if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
612*5113495bSYour Name 					if (!tb[STATS_GW_IPV4]) {
613*5113495bSYour Name 						dp_err("GW ipv4 address is not present");
614*5113495bSYour Name 						err = -EINVAL;
615*5113495bSYour Name 						goto end;
616*5113495bSYour Name 					}
617*5113495bSYour Name 					arp_stats_params->ip_addr =
618*5113495bSYour Name 						nla_get_u32(tb[STATS_GW_IPV4]);
619*5113495bSYour Name 					arp_stats_params->pkt_type =
620*5113495bSYour Name 						WLAN_NUD_STATS_ARP_PKT_TYPE;
621*5113495bSYour Name 					ucfg_dp_set_track_arp_ip_value(vdev,
622*5113495bSYour Name 								arp_stats_params->ip_addr);
623*5113495bSYour Name 				}
624*5113495bSYour Name 
625*5113495bSYour Name 				if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
626*5113495bSYour Name 					uint8_t *domain_name;
627*5113495bSYour Name 
628*5113495bSYour Name 					if (!tb2[STATS_DNS_DOMAIN_NAME]) {
629*5113495bSYour Name 						dp_err("DNS domain id is not present");
630*5113495bSYour Name 						err = -EINVAL;
631*5113495bSYour Name 						goto end;
632*5113495bSYour Name 					}
633*5113495bSYour Name 					domain_name = nla_data(
634*5113495bSYour Name 						tb2[STATS_DNS_DOMAIN_NAME]);
635*5113495bSYour Name 					ucfg_dp_set_track_dns_domain_len_value(vdev,
636*5113495bSYour Name 						nla_len(tb2[STATS_DNS_DOMAIN_NAME]));
637*5113495bSYour Name 					ucfg_dp_get_dns_payload_value(vdev, dns_payload);
638*5113495bSYour Name 					if (!dp_dns_make_name_query(
639*5113495bSYour Name 						domain_name,
640*5113495bSYour Name 						dns_payload,
641*5113495bSYour Name 						ucfg_dp_get_track_dns_domain_len_value(vdev)))
642*5113495bSYour Name 						ucfg_dp_set_track_dns_domain_len_value(vdev, 0);
643*5113495bSYour Name 					/* DNStracking isn't supported in FW. */
644*5113495bSYour Name 					arp_stats_params->pkt_type_bitmap &=
645*5113495bSYour Name 						~CONNECTIVITY_CHECK_SET_DNS;
646*5113495bSYour Name 				}
647*5113495bSYour Name 
648*5113495bSYour Name 				if (pkt_bitmap &
649*5113495bSYour Name 				    CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
650*5113495bSYour Name 					if (!tb2[STATS_SRC_PORT] ||
651*5113495bSYour Name 					    !tb2[STATS_DEST_PORT]) {
652*5113495bSYour Name 						dp_err("Source/Dest port is not present");
653*5113495bSYour Name 						err = -EINVAL;
654*5113495bSYour Name 						goto end;
655*5113495bSYour Name 					}
656*5113495bSYour Name 					arp_stats_params->tcp_src_port =
657*5113495bSYour Name 						nla_get_u32(
658*5113495bSYour Name 							tb2[STATS_SRC_PORT]);
659*5113495bSYour Name 					arp_stats_params->tcp_dst_port =
660*5113495bSYour Name 						nla_get_u32(
661*5113495bSYour Name 							tb2[STATS_DEST_PORT]);
662*5113495bSYour Name 					ucfg_dp_set_track_src_port_value(vdev,
663*5113495bSYour Name 						arp_stats_params->tcp_src_port);
664*5113495bSYour Name 					ucfg_dp_set_track_dest_port_value(vdev,
665*5113495bSYour Name 						arp_stats_params->tcp_dst_port);
666*5113495bSYour Name 				}
667*5113495bSYour Name 
668*5113495bSYour Name 				if (pkt_bitmap &
669*5113495bSYour Name 				    CONNECTIVITY_CHECK_SET_ICMPV4) {
670*5113495bSYour Name 					if (!tb2[STATS_DEST_IPV4]) {
671*5113495bSYour Name 						dp_err("destination ipv4 address to track ping packets is not present");
672*5113495bSYour Name 						err = -EINVAL;
673*5113495bSYour Name 						goto end;
674*5113495bSYour Name 					}
675*5113495bSYour Name 					arp_stats_params->icmp_ipv4 =
676*5113495bSYour Name 						nla_get_u32(
677*5113495bSYour Name 							tb2[STATS_DEST_IPV4]);
678*5113495bSYour Name 					ucfg_dp_set_track_dest_ipv4_value(vdev,
679*5113495bSYour Name 						arp_stats_params->icmp_ipv4);
680*5113495bSYour Name 				}
681*5113495bSYour Name 			} else {
682*5113495bSYour Name 				/* clear stats command received */
683*5113495bSYour Name 				arp_stats_params->pkt_type_bitmap = pkt_bitmap;
684*5113495bSYour Name 				arp_stats_params->flag = false;
685*5113495bSYour Name 				pkt_type_bitmap &=
686*5113495bSYour Name 					(~arp_stats_params->pkt_type_bitmap);
687*5113495bSYour Name 				ucfg_dp_set_pkt_type_bitmap_value(vdev, pkt_type_bitmap);
688*5113495bSYour Name 
689*5113495bSYour Name 				if (pkt_bitmap & CONNECTIVITY_CHECK_SET_ARP) {
690*5113495bSYour Name 					arp_stats_params->pkt_type =
691*5113495bSYour Name 						WLAN_NUD_STATS_ARP_PKT_TYPE;
692*5113495bSYour Name 					ucfg_dp_clear_arp_stats(vdev);
693*5113495bSYour Name 					ucfg_dp_set_track_arp_ip_value(vdev, 0);
694*5113495bSYour Name 				}
695*5113495bSYour Name 
696*5113495bSYour Name 				if (pkt_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
697*5113495bSYour Name 					/* DNStracking isn't supported in FW. */
698*5113495bSYour Name 					arp_stats_params->pkt_type_bitmap &=
699*5113495bSYour Name 						~CONNECTIVITY_CHECK_SET_DNS;
700*5113495bSYour Name 					ucfg_dp_clear_dns_stats(vdev);
701*5113495bSYour Name 					ucfg_dp_clear_dns_payload_value(vdev);
702*5113495bSYour Name 					ucfg_dp_set_track_dns_domain_len_value(vdev, 0);
703*5113495bSYour Name 				}
704*5113495bSYour Name 
705*5113495bSYour Name 				if (pkt_bitmap &
706*5113495bSYour Name 				    CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
707*5113495bSYour Name 					ucfg_dp_clear_tcp_stats(vdev);
708*5113495bSYour Name 					ucfg_dp_set_track_src_port_value(vdev,
709*5113495bSYour Name 									 0);
710*5113495bSYour Name 					ucfg_dp_set_track_dest_port_value(vdev,
711*5113495bSYour Name 									  0);
712*5113495bSYour Name 				}
713*5113495bSYour Name 
714*5113495bSYour Name 				if (pkt_bitmap &
715*5113495bSYour Name 				    CONNECTIVITY_CHECK_SET_ICMPV4) {
716*5113495bSYour Name 					ucfg_dp_clear_icmpv4_stats(vdev);
717*5113495bSYour Name 					ucfg_dp_set_track_dest_ipv4_value(vdev,
718*5113495bSYour Name 									  0);
719*5113495bSYour Name 				}
720*5113495bSYour Name 			}
721*5113495bSYour Name 		} else {
722*5113495bSYour Name 			dp_err("stats list empty");
723*5113495bSYour Name 			err = -EINVAL;
724*5113495bSYour Name 			goto end;
725*5113495bSYour Name 		}
726*5113495bSYour Name 	}
727*5113495bSYour Name 
728*5113495bSYour Name end:
729*5113495bSYour Name 	return err;
730*5113495bSYour Name }
731*5113495bSYour Name 
732*5113495bSYour Name /**
733*5113495bSYour Name  * osif_dp_populate_dns_stats_info() - populate dns stats info
734*5113495bSYour Name  * @vdev: vdev context
735*5113495bSYour Name  * @skb: pointer to skb
736*5113495bSYour Name  *
737*5113495bSYour Name  *
738*5113495bSYour Name  * Return: An error code or 0 on success.
739*5113495bSYour Name  */
osif_dp_populate_dns_stats_info(struct wlan_objmgr_vdev * vdev,struct sk_buff * skb)740*5113495bSYour Name static int osif_dp_populate_dns_stats_info(struct wlan_objmgr_vdev *vdev,
741*5113495bSYour Name 					   struct sk_buff *skb)
742*5113495bSYour Name {
743*5113495bSYour Name 	uint8_t *dns_query;
744*5113495bSYour Name 	uint32_t track_dns_domain_len;
745*5113495bSYour Name 	struct dp_dns_stats *dns_stats = ucfg_dp_get_dns_stats(vdev);
746*5113495bSYour Name 
747*5113495bSYour Name 	if (!dns_stats) {
748*5113495bSYour Name 		dp_err("Unable to get DNS stats");
749*5113495bSYour Name 		return -EINVAL;
750*5113495bSYour Name 	}
751*5113495bSYour Name 
752*5113495bSYour Name 	track_dns_domain_len = ucfg_dp_get_track_dns_domain_len_value(vdev);
753*5113495bSYour Name 	dns_query = qdf_mem_malloc(track_dns_domain_len + 1);
754*5113495bSYour Name 	if (!dns_query)
755*5113495bSYour Name 		return -EINVAL;
756*5113495bSYour Name 
757*5113495bSYour Name 	ucfg_dp_get_dns_payload_value(vdev, dns_query);
758*5113495bSYour Name 
759*5113495bSYour Name 	if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
760*5113495bSYour Name 			CONNECTIVITY_CHECK_SET_DNS) ||
761*5113495bSYour Name 	    nla_put(skb, CHECK_STATS_PKT_DNS_DOMAIN_NAME,
762*5113495bSYour Name 		    track_dns_domain_len,
763*5113495bSYour Name 		    dp_dns_unmake_name_query(dns_query)) ||
764*5113495bSYour Name 	    nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
765*5113495bSYour Name 			dns_stats->tx_dns_req_count) ||
766*5113495bSYour Name 	    nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
767*5113495bSYour Name 			dns_stats->tx_host_fw_sent) ||
768*5113495bSYour Name 	    nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
769*5113495bSYour Name 			dns_stats->tx_host_fw_sent) ||
770*5113495bSYour Name 	    nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
771*5113495bSYour Name 			dns_stats->tx_ack_cnt) ||
772*5113495bSYour Name 	    nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
773*5113495bSYour Name 			dns_stats->rx_dns_rsp_count) ||
774*5113495bSYour Name 	    nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
775*5113495bSYour Name 			dns_stats->rx_delivered) ||
776*5113495bSYour Name 	    nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
777*5113495bSYour Name 			dns_stats->rx_host_drop)) {
778*5113495bSYour Name 		dp_err("nla put fail");
779*5113495bSYour Name 		qdf_mem_free(dns_query);
780*5113495bSYour Name 		kfree_skb(skb);
781*5113495bSYour Name 		return -EINVAL;
782*5113495bSYour Name 	}
783*5113495bSYour Name 	qdf_mem_free(dns_query);
784*5113495bSYour Name 	return 0;
785*5113495bSYour Name }
786*5113495bSYour Name 
787*5113495bSYour Name /**
788*5113495bSYour Name  * osif_dp_populate_tcp_stats_info() - populate tcp stats info
789*5113495bSYour Name  * @vdev: pointer to vdev context
790*5113495bSYour Name  * @skb: pointer to skb
791*5113495bSYour Name  * @pkt_type: tcp pkt type
792*5113495bSYour Name  *
793*5113495bSYour Name  * Return: An error code or 0 on success.
794*5113495bSYour Name  */
osif_dp_populate_tcp_stats_info(struct wlan_objmgr_vdev * vdev,struct sk_buff * skb,uint8_t pkt_type)795*5113495bSYour Name static int osif_dp_populate_tcp_stats_info(struct wlan_objmgr_vdev *vdev,
796*5113495bSYour Name 					   struct sk_buff *skb,
797*5113495bSYour Name 					   uint8_t pkt_type)
798*5113495bSYour Name {
799*5113495bSYour Name 	uint32_t track_src_port = ucfg_dp_get_track_src_port_value(vdev);
800*5113495bSYour Name 	uint32_t track_dest_port = ucfg_dp_get_track_dest_port_value(vdev);
801*5113495bSYour Name 	struct dp_tcp_stats *tcp_stats = ucfg_dp_get_tcp_stats(vdev);
802*5113495bSYour Name 
803*5113495bSYour Name 	if (!tcp_stats) {
804*5113495bSYour Name 		dp_err("Unable to get TCP stats");
805*5113495bSYour Name 		return -EINVAL;
806*5113495bSYour Name 	}
807*5113495bSYour Name 
808*5113495bSYour Name 	switch (pkt_type) {
809*5113495bSYour Name 	case CONNECTIVITY_CHECK_SET_TCP_SYN:
810*5113495bSYour Name 		/* Fill info for tcp syn packets (tx packet) */
811*5113495bSYour Name 		if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
812*5113495bSYour Name 				CONNECTIVITY_CHECK_SET_TCP_SYN) ||
813*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
814*5113495bSYour Name 				track_src_port) ||
815*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
816*5113495bSYour Name 				track_dest_port) ||
817*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
818*5113495bSYour Name 				tcp_stats->tx_tcp_syn_count) ||
819*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
820*5113495bSYour Name 				tcp_stats->tx_tcp_syn_host_fw_sent) ||
821*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
822*5113495bSYour Name 				tcp_stats->tx_tcp_syn_host_fw_sent) ||
823*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
824*5113495bSYour Name 				tcp_stats->tx_tcp_syn_ack_cnt)) {
825*5113495bSYour Name 			dp_err("nla put fail");
826*5113495bSYour Name 			kfree_skb(skb);
827*5113495bSYour Name 			return -EINVAL;
828*5113495bSYour Name 		}
829*5113495bSYour Name 		break;
830*5113495bSYour Name 	case CONNECTIVITY_CHECK_SET_TCP_SYN_ACK:
831*5113495bSYour Name 		/* Fill info for tcp syn-ack packets (rx packet) */
832*5113495bSYour Name 		if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
833*5113495bSYour Name 				CONNECTIVITY_CHECK_SET_TCP_SYN_ACK) ||
834*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
835*5113495bSYour Name 				track_src_port) ||
836*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
837*5113495bSYour Name 				track_dest_port) ||
838*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
839*5113495bSYour Name 				tcp_stats->rx_fw_cnt) ||
840*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
841*5113495bSYour Name 				tcp_stats->rx_tcp_syn_ack_count) ||
842*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
843*5113495bSYour Name 				tcp_stats->rx_delivered) ||
844*5113495bSYour Name 		    nla_put_u16(skb,
845*5113495bSYour Name 				CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
846*5113495bSYour Name 				tcp_stats->rx_host_drop)) {
847*5113495bSYour Name 			dp_err("nla put fail");
848*5113495bSYour Name 			kfree_skb(skb);
849*5113495bSYour Name 			return -EINVAL;
850*5113495bSYour Name 		}
851*5113495bSYour Name 		break;
852*5113495bSYour Name 	case CONNECTIVITY_CHECK_SET_TCP_ACK:
853*5113495bSYour Name 		/* Fill info for tcp ack packets (tx packet) */
854*5113495bSYour Name 		if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
855*5113495bSYour Name 				CONNECTIVITY_CHECK_SET_TCP_ACK) ||
856*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_SRC_PORT,
857*5113495bSYour Name 				track_src_port) ||
858*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_DEST_PORT,
859*5113495bSYour Name 				track_dest_port) ||
860*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
861*5113495bSYour Name 				tcp_stats->tx_tcp_ack_count) ||
862*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
863*5113495bSYour Name 				tcp_stats->tx_tcp_ack_host_fw_sent) ||
864*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
865*5113495bSYour Name 				tcp_stats->tx_tcp_ack_host_fw_sent) ||
866*5113495bSYour Name 		    nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
867*5113495bSYour Name 				tcp_stats->tx_tcp_ack_ack_cnt)) {
868*5113495bSYour Name 			dp_err("nla put fail");
869*5113495bSYour Name 			kfree_skb(skb);
870*5113495bSYour Name 			return -EINVAL;
871*5113495bSYour Name 		}
872*5113495bSYour Name 		break;
873*5113495bSYour Name 	default:
874*5113495bSYour Name 		break;
875*5113495bSYour Name 	}
876*5113495bSYour Name 	return 0;
877*5113495bSYour Name }
878*5113495bSYour Name 
879*5113495bSYour Name /**
880*5113495bSYour Name  * osif_dp_populate_icmpv4_stats_info() - populate icmpv4 stats
881*5113495bSYour Name  * @vdev: pointer to vdev context
882*5113495bSYour Name  * @skb: pointer to skb
883*5113495bSYour Name  *
884*5113495bSYour Name  *
885*5113495bSYour Name  * Return: An error code or 0 on success.
886*5113495bSYour Name  */
osif_dp_populate_icmpv4_stats_info(struct wlan_objmgr_vdev * vdev,struct sk_buff * skb)887*5113495bSYour Name static int osif_dp_populate_icmpv4_stats_info(struct wlan_objmgr_vdev *vdev,
888*5113495bSYour Name 					      struct sk_buff *skb)
889*5113495bSYour Name {
890*5113495bSYour Name 	struct dp_icmpv4_stats *icmpv4_stats = ucfg_dp_get_icmpv4_stats(vdev);
891*5113495bSYour Name 	uint32_t track_dest_ipv4 = ucfg_dp_get_track_dest_ipv4_value(vdev);
892*5113495bSYour Name 
893*5113495bSYour Name 	if (!icmpv4_stats) {
894*5113495bSYour Name 		dp_err("Unable to get ICMP stats");
895*5113495bSYour Name 		return -EINVAL;
896*5113495bSYour Name 	}
897*5113495bSYour Name 
898*5113495bSYour Name 	if (nla_put_u16(skb, CHECK_STATS_PKT_TYPE,
899*5113495bSYour Name 			CONNECTIVITY_CHECK_SET_ICMPV4) ||
900*5113495bSYour Name 	    nla_put_u32(skb, CHECK_STATS_PKT_DEST_IPV4,
901*5113495bSYour Name 			track_dest_ipv4) ||
902*5113495bSYour Name 	    nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_FROM_NETDEV,
903*5113495bSYour Name 			icmpv4_stats->tx_icmpv4_req_count) ||
904*5113495bSYour Name 	    nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TO_LOWER_MAC,
905*5113495bSYour Name 			icmpv4_stats->tx_host_fw_sent) ||
906*5113495bSYour Name 	    nla_put_u16(skb, CHECK_STATS_PKT_REQ_RX_COUNT_BY_LOWER_MAC,
907*5113495bSYour Name 			icmpv4_stats->tx_host_fw_sent) ||
908*5113495bSYour Name 	    nla_put_u16(skb, CHECK_STATS_PKT_REQ_COUNT_TX_SUCCESS,
909*5113495bSYour Name 			icmpv4_stats->tx_ack_cnt) ||
910*5113495bSYour Name 	    nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_LOWER_MAC,
911*5113495bSYour Name 			icmpv4_stats->rx_fw_cnt) ||
912*5113495bSYour Name 	    nla_put_u16(skb, CHECK_STATS_PKT_RSP_RX_COUNT_BY_UPPER_MAC,
913*5113495bSYour Name 			icmpv4_stats->rx_icmpv4_rsp_count) ||
914*5113495bSYour Name 	    nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_TO_NETDEV,
915*5113495bSYour Name 			icmpv4_stats->rx_delivered) ||
916*5113495bSYour Name 	    nla_put_u16(skb, CHECK_STATS_PKT_RSP_COUNT_OUT_OF_ORDER_DROP,
917*5113495bSYour Name 			icmpv4_stats->rx_host_drop)) {
918*5113495bSYour Name 		dp_err("nla put fail");
919*5113495bSYour Name 		kfree_skb(skb);
920*5113495bSYour Name 		return -EINVAL;
921*5113495bSYour Name 	}
922*5113495bSYour Name 	return 0;
923*5113495bSYour Name }
924*5113495bSYour Name 
925*5113495bSYour Name /**
926*5113495bSYour Name  * osif_dp_populate_connectivity_check_stats_info() - Poplulate connectivity
927*5113495bSYour Name  * stats info
928*5113495bSYour Name  * @vdev: pointer to vdev context
929*5113495bSYour Name  * @skb: pointer to skb
930*5113495bSYour Name  *
931*5113495bSYour Name  *
932*5113495bSYour Name  * Return: An error code or 0 on success.
933*5113495bSYour Name  */
934*5113495bSYour Name static int
osif_dp_populate_connectivity_check_stats_info(struct wlan_objmgr_vdev * vdev,struct sk_buff * skb)935*5113495bSYour Name osif_dp_populate_connectivity_check_stats_info(struct wlan_objmgr_vdev *vdev,
936*5113495bSYour Name 					       struct sk_buff *skb)
937*5113495bSYour Name {
938*5113495bSYour Name 	struct nlattr *connect_stats, *connect_info;
939*5113495bSYour Name 	uint32_t count = 0;
940*5113495bSYour Name 	uint32_t pkt_type_bitmap = ucfg_dp_get_pkt_type_bitmap_value(vdev);
941*5113495bSYour Name 
942*5113495bSYour Name 	connect_stats = nla_nest_start(skb, DATA_PKT_STATS);
943*5113495bSYour Name 	if (!connect_stats) {
944*5113495bSYour Name 		dp_err("nla_nest_start failed");
945*5113495bSYour Name 		return -EINVAL;
946*5113495bSYour Name 	}
947*5113495bSYour Name 
948*5113495bSYour Name 	if (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_DNS) {
949*5113495bSYour Name 		connect_info = nla_nest_start(skb, count);
950*5113495bSYour Name 		if (!connect_info) {
951*5113495bSYour Name 			dp_err("nla_nest_start failed count %u", count);
952*5113495bSYour Name 			return -EINVAL;
953*5113495bSYour Name 		}
954*5113495bSYour Name 
955*5113495bSYour Name 		if (osif_dp_populate_dns_stats_info(vdev, skb))
956*5113495bSYour Name 			goto put_attr_fail;
957*5113495bSYour Name 		nla_nest_end(skb, connect_info);
958*5113495bSYour Name 		count++;
959*5113495bSYour Name 	}
960*5113495bSYour Name 
961*5113495bSYour Name 	if (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_TCP_HANDSHAKE) {
962*5113495bSYour Name 		connect_info = nla_nest_start(skb, count);
963*5113495bSYour Name 		if (!connect_info) {
964*5113495bSYour Name 			dp_err("nla_nest_start failed count %u", count);
965*5113495bSYour Name 			return -EINVAL;
966*5113495bSYour Name 		}
967*5113495bSYour Name 		if (osif_dp_populate_tcp_stats_info(vdev, skb,
968*5113495bSYour Name 					CONNECTIVITY_CHECK_SET_TCP_SYN))
969*5113495bSYour Name 			goto put_attr_fail;
970*5113495bSYour Name 		nla_nest_end(skb, connect_info);
971*5113495bSYour Name 		count++;
972*5113495bSYour Name 
973*5113495bSYour Name 		connect_info = nla_nest_start(skb, count);
974*5113495bSYour Name 		if (!connect_info) {
975*5113495bSYour Name 			dp_err("nla_nest_start failed count %u", count);
976*5113495bSYour Name 			return -EINVAL;
977*5113495bSYour Name 		}
978*5113495bSYour Name 		if (osif_dp_populate_tcp_stats_info(vdev, skb,
979*5113495bSYour Name 					CONNECTIVITY_CHECK_SET_TCP_SYN_ACK))
980*5113495bSYour Name 			goto put_attr_fail;
981*5113495bSYour Name 		nla_nest_end(skb, connect_info);
982*5113495bSYour Name 		count++;
983*5113495bSYour Name 
984*5113495bSYour Name 		connect_info = nla_nest_start(skb, count);
985*5113495bSYour Name 		if (!connect_info) {
986*5113495bSYour Name 			dp_err("nla_nest_start failed count %u", count);
987*5113495bSYour Name 			return -EINVAL;
988*5113495bSYour Name 		}
989*5113495bSYour Name 		if (osif_dp_populate_tcp_stats_info(vdev, skb,
990*5113495bSYour Name 					CONNECTIVITY_CHECK_SET_TCP_ACK))
991*5113495bSYour Name 			goto put_attr_fail;
992*5113495bSYour Name 		nla_nest_end(skb, connect_info);
993*5113495bSYour Name 		count++;
994*5113495bSYour Name 	}
995*5113495bSYour Name 
996*5113495bSYour Name 	if (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ICMPV4) {
997*5113495bSYour Name 		connect_info = nla_nest_start(skb, count);
998*5113495bSYour Name 		if (!connect_info) {
999*5113495bSYour Name 			dp_err("nla_nest_start failed count %u", count);
1000*5113495bSYour Name 			return -EINVAL;
1001*5113495bSYour Name 		}
1002*5113495bSYour Name 
1003*5113495bSYour Name 		if (osif_dp_populate_icmpv4_stats_info(vdev, skb))
1004*5113495bSYour Name 			goto put_attr_fail;
1005*5113495bSYour Name 		nla_nest_end(skb, connect_info);
1006*5113495bSYour Name 		count++;
1007*5113495bSYour Name 	}
1008*5113495bSYour Name 
1009*5113495bSYour Name 	nla_nest_end(skb, connect_stats);
1010*5113495bSYour Name 	return 0;
1011*5113495bSYour Name 
1012*5113495bSYour Name put_attr_fail:
1013*5113495bSYour Name 	dp_err("QCA_WLAN_VENDOR_ATTR put fail. count %u", count);
1014*5113495bSYour Name 	return -EINVAL;
1015*5113495bSYour Name }
1016*5113495bSYour Name 
osif_dp_get_nud_stats(struct wiphy * wiphy,struct wlan_objmgr_vdev * vdev,const void * data,int data_len)1017*5113495bSYour Name int osif_dp_get_nud_stats(struct wiphy *wiphy,
1018*5113495bSYour Name 			  struct wlan_objmgr_vdev *vdev,
1019*5113495bSYour Name 			  const void *data, int data_len)
1020*5113495bSYour Name {
1021*5113495bSYour Name 	int err = 0;
1022*5113495bSYour Name 	struct dp_get_arp_stats_params arp_stats_params;
1023*5113495bSYour Name 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
1024*5113495bSYour Name 	uint32_t pkt_type_bitmap = ucfg_dp_get_pkt_type_bitmap_value(vdev);
1025*5113495bSYour Name 	struct sk_buff *skb;
1026*5113495bSYour Name 	struct osif_request *request = NULL;
1027*5113495bSYour Name 	struct dp_arp_stats *arp_stats;
1028*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
1029*5113495bSYour Name 	static const struct osif_request_params params = {
1030*5113495bSYour Name 		.priv_size = 0,
1031*5113495bSYour Name 		.timeout_ms = WLAN_WAIT_TIME_NUD_STATS,
1032*5113495bSYour Name 	};
1033*5113495bSYour Name 
1034*5113495bSYour Name 	request = osif_request_alloc(&params);
1035*5113495bSYour Name 	if (!request) {
1036*5113495bSYour Name 		dp_err("Request allocation failure");
1037*5113495bSYour Name 		return -ENOMEM;
1038*5113495bSYour Name 	}
1039*5113495bSYour Name 
1040*5113495bSYour Name 	ucfg_dp_set_nud_stats_cb(psoc, osif_request_cookie(request));
1041*5113495bSYour Name 
1042*5113495bSYour Name 	arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
1043*5113495bSYour Name 	arp_stats_params.vdev_id = ucfg_dp_get_link_id(vdev);
1044*5113495bSYour Name 
1045*5113495bSYour Name 	/* send NUD failure event only when ARP tracking is enabled. */
1046*5113495bSYour Name 	if (ucfg_dp_nud_fail_data_stall_evt_enabled() &&
1047*5113495bSYour Name 	    !ucfg_dp_nud_tracking_enabled(psoc) &&
1048*5113495bSYour Name 	    (pkt_type_bitmap & CONNECTIVITY_CHECK_SET_ARP)) {
1049*5113495bSYour Name 		QDF_TRACE(QDF_MODULE_ID_HDD_DATA, QDF_TRACE_LEVEL_ERROR,
1050*5113495bSYour Name 			  "Data stall due to NUD failure");
1051*5113495bSYour Name 		cdp_post_data_stall_event(soc,
1052*5113495bSYour Name 					  DATA_STALL_LOG_INDICATOR_FRAMEWORK,
1053*5113495bSYour Name 					  DATA_STALL_LOG_NUD_FAILURE,
1054*5113495bSYour Name 					  OL_TXRX_PDEV_ID, 0XFF,
1055*5113495bSYour Name 					  DATA_STALL_LOG_RECOVERY_TRIGGER_PDR);
1056*5113495bSYour Name 	}
1057*5113495bSYour Name 
1058*5113495bSYour Name 	if (QDF_STATUS_SUCCESS !=
1059*5113495bSYour Name 	    ucfg_dp_req_get_arp_stats(psoc, &arp_stats_params)) {
1060*5113495bSYour Name 		dp_err("Unable to sent ARP stats request");
1061*5113495bSYour Name 		err = -EINVAL;
1062*5113495bSYour Name 		goto exit;
1063*5113495bSYour Name 	}
1064*5113495bSYour Name 
1065*5113495bSYour Name 	err = osif_request_wait_for_response(request);
1066*5113495bSYour Name 	if (err) {
1067*5113495bSYour Name 		dp_err("timedout while retrieving NUD stats");
1068*5113495bSYour Name 		err = -ETIMEDOUT;
1069*5113495bSYour Name 		goto exit;
1070*5113495bSYour Name 	}
1071*5113495bSYour Name 
1072*5113495bSYour Name 	arp_stats = ucfg_dp_get_arp_stats(vdev);
1073*5113495bSYour Name 	if (!arp_stats) {
1074*5113495bSYour Name 		dp_err("Unable to get ARP stats");
1075*5113495bSYour Name 		err = -EINVAL;
1076*5113495bSYour Name 		goto exit;
1077*5113495bSYour Name 	}
1078*5113495bSYour Name 
1079*5113495bSYour Name 	skb = wlan_cfg80211_vendor_cmd_alloc_reply_skb(wiphy,
1080*5113495bSYour Name 						       WLAN_NUD_STATS_LEN);
1081*5113495bSYour Name 	if (!skb) {
1082*5113495bSYour Name 		dp_err("wlan_cfg80211_vendor_cmd_alloc_reply_skb failed");
1083*5113495bSYour Name 		err = -ENOMEM;
1084*5113495bSYour Name 		goto exit;
1085*5113495bSYour Name 	}
1086*5113495bSYour Name 
1087*5113495bSYour Name 	if (nla_put_u16(skb, COUNT_FROM_NETDEV,
1088*5113495bSYour Name 			arp_stats->tx_arp_req_count) ||
1089*5113495bSYour Name 	    nla_put_u16(skb, COUNT_TO_LOWER_MAC,
1090*5113495bSYour Name 			arp_stats->tx_host_fw_sent) ||
1091*5113495bSYour Name 	    nla_put_u16(skb, RX_COUNT_BY_LOWER_MAC,
1092*5113495bSYour Name 			arp_stats->tx_host_fw_sent) ||
1093*5113495bSYour Name 	    nla_put_u16(skb, COUNT_TX_SUCCESS,
1094*5113495bSYour Name 			arp_stats->tx_ack_cnt) ||
1095*5113495bSYour Name 	    nla_put_u16(skb, RSP_RX_COUNT_BY_LOWER_MAC,
1096*5113495bSYour Name 			arp_stats->rx_fw_cnt) ||
1097*5113495bSYour Name 	    nla_put_u16(skb, RSP_RX_COUNT_BY_UPPER_MAC,
1098*5113495bSYour Name 			arp_stats->rx_arp_rsp_count) ||
1099*5113495bSYour Name 	    nla_put_u16(skb, RSP_COUNT_TO_NETDEV,
1100*5113495bSYour Name 			arp_stats->rx_delivered) ||
1101*5113495bSYour Name 	    nla_put_u16(skb, RSP_COUNT_OUT_OF_ORDER_DROP,
1102*5113495bSYour Name 			arp_stats->rx_host_drop_reorder)) {
1103*5113495bSYour Name 		dp_err("nla put fail");
1104*5113495bSYour Name 		wlan_cfg80211_vendor_free_skb(skb);
1105*5113495bSYour Name 		err = -EINVAL;
1106*5113495bSYour Name 		goto exit;
1107*5113495bSYour Name 	}
1108*5113495bSYour Name 	if (ucfg_dp_get_con_status_value(vdev))
1109*5113495bSYour Name 		nla_put_flag(skb, AP_LINK_ACTIVE);
1110*5113495bSYour Name 	if (ucfg_dp_get_dad_value(vdev))
1111*5113495bSYour Name 		nla_put_flag(skb, AP_LINK_DAD);
1112*5113495bSYour Name 
1113*5113495bSYour Name 	/* ARP tracking is done above. */
1114*5113495bSYour Name 	pkt_type_bitmap &= ~CONNECTIVITY_CHECK_SET_ARP;
1115*5113495bSYour Name 
1116*5113495bSYour Name 	if (pkt_type_bitmap) {
1117*5113495bSYour Name 		if (osif_dp_populate_connectivity_check_stats_info(vdev, skb)) {
1118*5113495bSYour Name 			err = -EINVAL;
1119*5113495bSYour Name 			goto exit;
1120*5113495bSYour Name 		}
1121*5113495bSYour Name 	}
1122*5113495bSYour Name 
1123*5113495bSYour Name 	wlan_cfg80211_vendor_cmd_reply(skb);
1124*5113495bSYour Name exit:
1125*5113495bSYour Name 	ucfg_dp_clear_nud_stats_cb(psoc);
1126*5113495bSYour Name 	osif_request_put(request);
1127*5113495bSYour Name 	return err;
1128*5113495bSYour Name }
1129*5113495bSYour Name 
osif_dp_set_nud_stats(struct wiphy * wiphy,struct wlan_objmgr_vdev * vdev,const void * data,int data_len)1130*5113495bSYour Name int osif_dp_set_nud_stats(struct wiphy *wiphy,
1131*5113495bSYour Name 			  struct wlan_objmgr_vdev *vdev,
1132*5113495bSYour Name 			  const void *data, int data_len)
1133*5113495bSYour Name {
1134*5113495bSYour Name 	struct nlattr *tb[STATS_SET_MAX + 1];
1135*5113495bSYour Name 	struct wlan_objmgr_psoc *psoc = wlan_vdev_get_psoc(vdev);
1136*5113495bSYour Name 	struct dp_set_arp_stats_params arp_stats_params = {0};
1137*5113495bSYour Name 	uint32_t pkt_type_bitmap = ucfg_dp_get_pkt_type_bitmap_value(vdev);
1138*5113495bSYour Name 	int err = 0;
1139*5113495bSYour Name 
1140*5113495bSYour Name 	err = wlan_cfg80211_nla_parse(tb, STATS_SET_MAX, data, data_len,
1141*5113495bSYour Name 				      dp_set_nud_stats_policy);
1142*5113495bSYour Name 	if (err) {
1143*5113495bSYour Name 		dp_err("STATS_SET_START ATTR");
1144*5113495bSYour Name 		return err;
1145*5113495bSYour Name 	}
1146*5113495bSYour Name 
1147*5113495bSYour Name 	if (tb[STATS_SET_START]) {
1148*5113495bSYour Name 		/* tracking is enabled for stats other than arp. */
1149*5113495bSYour Name 		if (tb[STATS_SET_DATA_PKT_INFO]) {
1150*5113495bSYour Name 			err = osif_dp_set_clear_connectivity_check_stats_info(
1151*5113495bSYour Name 						vdev,
1152*5113495bSYour Name 						&arp_stats_params, tb, true);
1153*5113495bSYour Name 			if (err)
1154*5113495bSYour Name 				return -EINVAL;
1155*5113495bSYour Name 
1156*5113495bSYour Name 			/*
1157*5113495bSYour Name 			 * if only tracking dns, then don't send
1158*5113495bSYour Name 			 * wmi command to FW.
1159*5113495bSYour Name 			 */
1160*5113495bSYour Name 			if (!arp_stats_params.pkt_type_bitmap)
1161*5113495bSYour Name 				return err;
1162*5113495bSYour Name 		} else {
1163*5113495bSYour Name 			if (!tb[STATS_GW_IPV4]) {
1164*5113495bSYour Name 				dp_err("STATS_SET_START CMD");
1165*5113495bSYour Name 				return -EINVAL;
1166*5113495bSYour Name 			}
1167*5113495bSYour Name 
1168*5113495bSYour Name 			arp_stats_params.pkt_type_bitmap =
1169*5113495bSYour Name 						CONNECTIVITY_CHECK_SET_ARP;
1170*5113495bSYour Name 			pkt_type_bitmap |=
1171*5113495bSYour Name 					arp_stats_params.pkt_type_bitmap;
1172*5113495bSYour Name 			ucfg_dp_set_pkt_type_bitmap_value(vdev,
1173*5113495bSYour Name 							  pkt_type_bitmap);
1174*5113495bSYour Name 			arp_stats_params.flag = true;
1175*5113495bSYour Name 			arp_stats_params.ip_addr =
1176*5113495bSYour Name 					nla_get_u32(tb[STATS_GW_IPV4]);
1177*5113495bSYour Name 			ucfg_dp_set_track_arp_ip_value(vdev,
1178*5113495bSYour Name 						       arp_stats_params.ip_addr);
1179*5113495bSYour Name 			arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
1180*5113495bSYour Name 		}
1181*5113495bSYour Name 	} else {
1182*5113495bSYour Name 		/* clear stats command received. */
1183*5113495bSYour Name 		if (tb[STATS_SET_DATA_PKT_INFO]) {
1184*5113495bSYour Name 			err = osif_dp_set_clear_connectivity_check_stats_info(
1185*5113495bSYour Name 						vdev,
1186*5113495bSYour Name 						&arp_stats_params, tb, false);
1187*5113495bSYour Name 			if (err)
1188*5113495bSYour Name 				return -EINVAL;
1189*5113495bSYour Name 
1190*5113495bSYour Name 			/*
1191*5113495bSYour Name 			 * if only tracking dns, then don't send
1192*5113495bSYour Name 			 * wmi command to FW.
1193*5113495bSYour Name 			 */
1194*5113495bSYour Name 			if (!arp_stats_params.pkt_type_bitmap)
1195*5113495bSYour Name 				return err;
1196*5113495bSYour Name 		} else {
1197*5113495bSYour Name 			arp_stats_params.pkt_type_bitmap =
1198*5113495bSYour Name 						CONNECTIVITY_CHECK_SET_ARP;
1199*5113495bSYour Name 			pkt_type_bitmap &= (~arp_stats_params.pkt_type_bitmap);
1200*5113495bSYour Name 			ucfg_dp_set_pkt_type_bitmap_value(vdev,
1201*5113495bSYour Name 							  pkt_type_bitmap);
1202*5113495bSYour Name 			arp_stats_params.flag = false;
1203*5113495bSYour Name 			ucfg_dp_clear_arp_stats(vdev);
1204*5113495bSYour Name 			arp_stats_params.pkt_type = WLAN_NUD_STATS_ARP_PKT_TYPE;
1205*5113495bSYour Name 		}
1206*5113495bSYour Name 	}
1207*5113495bSYour Name 
1208*5113495bSYour Name 	dp_info("STATS_SET_START Received flag %d!", arp_stats_params.flag);
1209*5113495bSYour Name 
1210*5113495bSYour Name 	arp_stats_params.vdev_id = ucfg_dp_get_link_id(vdev);
1211*5113495bSYour Name 
1212*5113495bSYour Name 	if (QDF_STATUS_SUCCESS !=
1213*5113495bSYour Name 	    ucfg_dp_req_set_arp_stats(psoc, &arp_stats_params)) {
1214*5113495bSYour Name 		dp_err("Unable to set ARP stats!");
1215*5113495bSYour Name 		return -EINVAL;
1216*5113495bSYour Name 	}
1217*5113495bSYour Name 	return err;
1218*5113495bSYour Name }
1219*5113495bSYour Name 
1220*5113495bSYour Name /*
1221*5113495bSYour Name  * os_if_dp_register_event_handler() - Register osif event handler
1222*5113495bSYour Name  * @psoc: psoc handle
1223*5113495bSYour Name  *
1224*5113495bSYour Name  * Return: None
1225*5113495bSYour Name  */
os_if_dp_register_event_handler(struct wlan_objmgr_psoc * psoc)1226*5113495bSYour Name static void os_if_dp_register_event_handler(struct wlan_objmgr_psoc *psoc)
1227*5113495bSYour Name {
1228*5113495bSYour Name 	struct wlan_dp_psoc_nb_ops cb_obj = {0};
1229*5113495bSYour Name 
1230*5113495bSYour Name 	cb_obj.osif_dp_get_arp_stats_evt =
1231*5113495bSYour Name 		osif_dp_get_arp_stats_event_handler;
1232*5113495bSYour Name 
1233*5113495bSYour Name 	ucfg_dp_register_event_handler(psoc, &cb_obj);
1234*5113495bSYour Name }
1235*5113495bSYour Name 
os_if_dp_register_hdd_callbacks(struct wlan_objmgr_psoc * psoc,struct wlan_dp_psoc_callbacks * cb_obj)1236*5113495bSYour Name void os_if_dp_register_hdd_callbacks(struct wlan_objmgr_psoc *psoc,
1237*5113495bSYour Name 				     struct wlan_dp_psoc_callbacks *cb_obj)
1238*5113495bSYour Name {
1239*5113495bSYour Name 	cb_obj->osif_dp_send_tcp_param_update_event =
1240*5113495bSYour Name 		osif_dp_send_tcp_param_update_event;
1241*5113495bSYour Name 	cb_obj->os_if_dp_nud_stats_info = os_if_dp_nud_stats_info;
1242*5113495bSYour Name 	cb_obj->osif_dp_process_mic_error = osif_dp_process_mic_error;
1243*5113495bSYour Name 	os_if_dp_register_txrx_callbacks(cb_obj);
1244*5113495bSYour Name 
1245*5113495bSYour Name 	ucfg_dp_register_hdd_callbacks(psoc, cb_obj);
1246*5113495bSYour Name 	os_if_dp_register_event_handler(psoc);
1247*5113495bSYour Name }
1248