xref: /wlan-driver/qcacld-3.0/components/dp/core/src/wlan_dp_softap_txrx.c (revision 5113495b16420b49004c444715d2daae2066e7dc)
1 /*
2  * Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. 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   * DOC: wlan_dp_softap_txrx.c
20   * DP Soft AP TX/RX path implementation
21   *
22   *
23   */
24 
25 #include <wlan_dp_priv.h>
26 #include <wlan_dp_main.h>
27 #include <wlan_dp_txrx.h>
28 #include "wlan_dp_public_struct.h"
29 #include <qdf_types.h>
30 #include <cdp_txrx_cmn.h>
31 #include <cdp_txrx_peer_ops.h>
32 #include <cdp_txrx_misc.h>
33 #include <cdp_txrx_flow_ctrl_v2.h>
34 #include "wlan_dp_rx_thread.h"
35 #include "nan_public_structs.h"
36 #include "nan_ucfg_api.h"
37 #include <wlan_cm_ucfg_api.h>
38 #include <enet.h>
39 #include <cds_utils.h>
40 #include <wlan_dp_bus_bandwidth.h>
41 #include <wlan_tdls_ucfg_api.h>
42 #include <qdf_trace.h>
43 #include <qdf_nbuf.h>
44 #include <qdf_net_stats.h>
45 
46 /* Preprocessor definitions and constants */
47 #undef QCA_DP_SAP_DUMP_SK_BUFF
48 
49 /* Type declarations */
50 
51 /* Function definitions and documentation */
52 #ifdef QCA_DP_SAP_DUMP_SK_BUFF
53 /**
54  * dp_softap_dump_nbuf() - Dump an nbuf
55  * @nbuf: nbuf to dump
56  *
57  * Return: None
58  */
dp_softap_dump_nbuf(qdf_nbuf_t nbuf)59 static void dp_softap_dump_nbuf(qdf_nbuf_t nbuf)
60 {
61 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
62 		  "%s: head = %pK ", __func__, nbuf->head);
63 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
64 		  "%s: tail = %pK ", __func__, nbuf->tail);
65 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
66 		  "%s: end = %pK ", __func__, nbuf->end);
67 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
68 		  "%s: len = %d ", __func__, nbuf->len);
69 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
70 		  "%s: data_len = %d ", __func__, nbuf->data_len);
71 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
72 		  "%s: mac_len = %d", __func__, nbuf->mac_len);
73 
74 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
75 		  "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x ", nbuf->data[0],
76 		  nbuf->data[1], nbuf->data[2], nbuf->data[3], nbuf->data[4],
77 		  nbuf->data[5], nbuf->data[6], nbuf->data[7]);
78 	QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
79 		  "0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x 0x%x", nbuf->data[8],
80 		  nbuf->data[9], nbuf->data[10], nbuf->data[11], nbuf->data[12],
81 		  nbuf->data[13], nbuf->data[14], nbuf->data[15]);
82 }
83 #else
dp_softap_dump_nbuf(qdf_nbuf_t nbuf)84 static inline void dp_softap_dump_nbuf(qdf_nbuf_t nbuf)
85 {
86 }
87 #endif
88 
89 #define IEEE8021X_AUTH_TYPE_EAP 0
90 #define EAP_CODE_OFFSET 18
91 #define EAP_CODE_FAILURE 4
92 
93 /* Wait EAP Failure frame timeout in (MS) */
94 #define EAP_FRM_TIME_OUT 80
95 
96 /**
97  * dp_softap_inspect_tx_eap_pkt() - Inspect eap pkt tx/tx-completion
98  * @dp_intf: pointer to DP interface
99  * @nbuf: pointer to n/w buffer
100  * @tx_comp: tx sending or tx completion
101  *
102  * Inspect the EAP-Failure pkt tx sending and tx completion.
103  *
104  * Return: void
105  */
dp_softap_inspect_tx_eap_pkt(struct wlan_dp_intf * dp_intf,qdf_nbuf_t nbuf,bool tx_comp)106 static void dp_softap_inspect_tx_eap_pkt(struct wlan_dp_intf *dp_intf,
107 					 qdf_nbuf_t nbuf,
108 					 bool tx_comp)
109 {
110 	struct qdf_mac_addr *mac_addr;
111 	uint8_t *data;
112 	uint8_t auth_type, eap_code;
113 	struct wlan_objmgr_peer *peer;
114 	struct wlan_dp_sta_info *sta_info;
115 
116 	if (qdf_likely(QDF_NBUF_CB_GET_PACKET_TYPE(nbuf) !=
117 	    QDF_NBUF_CB_PACKET_TYPE_EAPOL) ||
118 	    qdf_nbuf_len(nbuf) < (EAP_CODE_OFFSET + 1))
119 		return;
120 
121 	if (cds_is_driver_recovering() || cds_is_driver_in_bad_state() ||
122 	    cds_is_load_or_unload_in_progress()) {
123 		dp_debug("Recovery/(Un)load in Progress. Ignore!!!");
124 		return;
125 	}
126 
127 	if (dp_intf->device_mode != QDF_P2P_GO_MODE)
128 		return;
129 
130 	if (dp_intf->bss_state != BSS_INTF_START) {
131 		dp_debug("BSS intf state is not START");
132 		return;
133 	}
134 	data = qdf_nbuf_data(nbuf);
135 	auth_type = *(uint8_t *)(data + EAPOL_PACKET_TYPE_OFFSET);
136 	if (auth_type != IEEE8021X_AUTH_TYPE_EAP)
137 		return;
138 	eap_code = *(uint8_t *)(data + EAP_CODE_OFFSET);
139 	if (eap_code != EAP_CODE_FAILURE)
140 		return;
141 	mac_addr = (struct qdf_mac_addr *)qdf_nbuf_data(nbuf) +
142 		QDF_NBUF_DEST_MAC_OFFSET;
143 
144 	peer = wlan_objmgr_get_peer_by_mac(dp_intf->dp_ctx->psoc,
145 					   mac_addr->bytes,
146 					   WLAN_DP_ID);
147 	if (!peer) {
148 		dp_err("Peer object not found");
149 		return;
150 	}
151 	sta_info = dp_get_peer_priv_obj(peer);
152 	if (!sta_info) {
153 		wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID);
154 		return;
155 	}
156 
157 	if (tx_comp) {
158 		dp_info("eap_failure frm tx done" QDF_MAC_ADDR_FMT,
159 			QDF_MAC_ADDR_REF(mac_addr->bytes));
160 		qdf_atomic_clear_bit(DP_PENDING_TYPE_EAP_FAILURE,
161 				     &sta_info->pending_eap_frm_type);
162 		qdf_event_set(&dp_intf->qdf_sta_eap_frm_done_event);
163 	} else {
164 		dp_info("eap_failure frm tx pending" QDF_MAC_ADDR_FMT,
165 			QDF_MAC_ADDR_REF(mac_addr->bytes));
166 		qdf_event_reset(&dp_intf->qdf_sta_eap_frm_done_event);
167 		qdf_atomic_set_bit(DP_PENDING_TYPE_EAP_FAILURE,
168 				   &sta_info->pending_eap_frm_type);
169 		QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_NOTIFY_COMP(nbuf) = 1;
170 	}
171 	wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID);
172 }
173 
dp_softap_check_wait_for_tx_eap_pkt(struct wlan_dp_intf * dp_intf,struct qdf_mac_addr * mac_addr)174 void dp_softap_check_wait_for_tx_eap_pkt(struct wlan_dp_intf *dp_intf,
175 					 struct qdf_mac_addr *mac_addr)
176 {
177 	struct wlan_objmgr_peer *peer;
178 	struct wlan_dp_sta_info *sta_info;
179 	QDF_STATUS qdf_status;
180 
181 	if (dp_intf->device_mode != QDF_P2P_GO_MODE)
182 		return;
183 
184 	peer = wlan_objmgr_get_peer_by_mac(dp_intf->dp_ctx->psoc,
185 					   mac_addr->bytes,
186 					   WLAN_DP_ID);
187 	if (!peer) {
188 		dp_err("Peer object not found");
189 		return;
190 	}
191 
192 	sta_info = dp_get_peer_priv_obj(peer);
193 	if (qdf_atomic_test_bit(DP_PENDING_TYPE_EAP_FAILURE,
194 				&sta_info->pending_eap_frm_type)) {
195 		dp_info("eap_failure frm pending" QDF_MAC_ADDR_FMT,
196 			QDF_MAC_ADDR_REF(mac_addr->bytes));
197 		qdf_status = qdf_wait_for_event_completion(
198 				&dp_intf->qdf_sta_eap_frm_done_event,
199 				EAP_FRM_TIME_OUT);
200 		if (!QDF_IS_STATUS_SUCCESS(qdf_status))
201 			dp_debug("eap_failure tx timeout");
202 	}
203 	wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID);
204 }
205 
206 #ifdef SAP_DHCP_FW_IND
207 /**
208  * dp_post_dhcp_ind() - Send DHCP START/STOP indication to FW
209  * @dp_link: DP link handle
210  * @mac_addr: mac address
211  * @dhcp_start: dhcp start
212  *
213  * Return: error number
214  */
dp_post_dhcp_ind(struct wlan_dp_link * dp_link,uint8_t * mac_addr,bool dhcp_start)215 int dp_post_dhcp_ind(struct wlan_dp_link *dp_link, uint8_t *mac_addr,
216 		     bool dhcp_start)
217 {
218 	struct wlan_dp_intf *dp_intf;
219 	struct dp_dhcp_ind msg;
220 	struct wlan_dp_psoc_sb_ops *sb_ops;
221 	QDF_STATUS status = QDF_STATUS_SUCCESS;
222 
223 	dp_info("Post DHCP indication,sta_mac=" QDF_MAC_ADDR_FMT
224 		 " ,  start=%u", QDF_MAC_ADDR_REF(mac_addr), dhcp_start);
225 
226 	if (!is_dp_link_valid(dp_link)) {
227 		dp_err("NULL DP link");
228 		return QDF_STATUS_E_INVAL;
229 	}
230 
231 	dp_intf = dp_link->dp_intf;
232 	/*
233 	 * If DP RX thread is enabled, RX DHCP packets are enqueue into
234 	 * DP RX thread queue, defer DHCP inspection until host has
235 	 * resumed entirely, no issue to send DHCP indication MSG.
236 	 * If DP RX thread is disabled, DHCP inspection happens earlier,
237 	 * skip sending DHCP indication MSG if host has not resumed.
238 	 */
239 	if (qdf_unlikely(!dp_intf->dp_ctx->enable_dp_rx_threads &&
240 			 dp_intf->dp_ctx->is_suspend)) {
241 		dp_err_rl("Device is system suspended, skip DHCP Ind");
242 		return QDF_STATUS_E_INVAL;
243 	}
244 
245 	sb_ops = &dp_intf->dp_ctx->sb_ops;
246 	msg.dhcp_start = dhcp_start;
247 	msg.device_mode = dp_intf->device_mode;
248 	qdf_mem_copy(msg.intf_mac_addr.bytes,
249 		     dp_intf->mac_addr.bytes,
250 		     QDF_MAC_ADDR_SIZE);
251 	qdf_mem_copy(msg.peer_mac_addr.bytes,
252 		     mac_addr,
253 		     QDF_MAC_ADDR_SIZE);
254 
255 	status = sb_ops->dp_send_dhcp_ind(dp_link->link_id, &msg);
256 	if (!QDF_IS_STATUS_SUCCESS(status)) {
257 		dp_err("Post DHCP Ind MSG fail");
258 		return QDF_STATUS_E_FAULT;
259 	}
260 
261 	return 0;
262 }
263 
264 #define DHCP_CLIENT_MAC_ADDR_OFFSET 0x46
265 
266 /**
267  * dp_softap_notify_dhcp_ind() - Notify SAP for DHCP indication for tx desc
268  * @link_context: DP link context
269  * @nbuf: pointer to OS packet (sk_buff)
270  *
271  * Return: None
272  */
dp_softap_notify_dhcp_ind(void * link_context,qdf_nbuf_t nbuf)273 static void dp_softap_notify_dhcp_ind(void *link_context, qdf_nbuf_t nbuf)
274 {
275 	uint8_t *dest_mac_addr;
276 	struct wlan_dp_link *dp_link = link_context;
277 
278 	if (!is_dp_link_valid(dp_link))
279 		return;
280 
281 	dest_mac_addr = qdf_nbuf_data(nbuf) + DHCP_CLIENT_MAC_ADDR_OFFSET;
282 
283 	/*stop dhcp indication*/
284 	dp_post_dhcp_ind(dp_link, dest_mac_addr, false);
285 }
286 
dp_softap_inspect_dhcp_packet(struct wlan_dp_link * dp_link,qdf_nbuf_t nbuf,enum qdf_proto_dir dir)287 int dp_softap_inspect_dhcp_packet(struct wlan_dp_link *dp_link,
288 				  qdf_nbuf_t nbuf,
289 				  enum qdf_proto_dir dir)
290 {
291 	struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
292 	enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
293 	struct wlan_objmgr_peer *peer;
294 	struct wlan_dp_sta_info *sta_info;
295 	int errno = 0;
296 	struct qdf_mac_addr *src_mac;
297 
298 	if (((dp_intf->device_mode == QDF_SAP_MODE) ||
299 	     (dp_intf->device_mode == QDF_P2P_GO_MODE)) &&
300 	    ((dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_DHCP ==
301 				QDF_NBUF_CB_GET_PACKET_TYPE(nbuf)) ||
302 	     (dir == QDF_RX && qdf_nbuf_is_ipv4_dhcp_pkt(nbuf) == true))) {
303 		src_mac = (struct qdf_mac_addr *)(qdf_nbuf_data(nbuf) +
304 						  DHCP_CLIENT_MAC_ADDR_OFFSET);
305 
306 		subtype = qdf_nbuf_get_dhcp_subtype(nbuf);
307 
308 		peer = wlan_objmgr_get_peer_by_mac(dp_intf->dp_ctx->psoc,
309 						   src_mac->bytes,
310 						   WLAN_DP_ID);
311 		if (!peer) {
312 			dp_err("Peer object not found");
313 			return QDF_STATUS_E_INVAL;
314 		}
315 
316 		sta_info = dp_get_peer_priv_obj(peer);
317 		if (!sta_info) {
318 			dp_err("Station not found");
319 			wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID);
320 			return QDF_STATUS_E_INVAL;
321 		}
322 
323 		dp_info("ENTER: type=%d, phase=%d, nego_status=%d",
324 			subtype,
325 			sta_info->dhcp_phase,
326 			sta_info->dhcp_nego_status);
327 
328 		switch (subtype) {
329 		case QDF_PROTO_DHCP_DISCOVER:
330 			if (dir != QDF_RX)
331 				break;
332 			if (sta_info->dhcp_nego_status == DHCP_NEGO_STOP)
333 				errno =	dp_post_dhcp_ind(
334 						dp_link,
335 						sta_info->sta_mac.bytes,
336 						true);
337 			sta_info->dhcp_phase = DHCP_PHASE_DISCOVER;
338 			if (QDF_IS_STATUS_SUCCESS(errno))
339 				sta_info->dhcp_nego_status =
340 						DHCP_NEGO_IN_PROGRESS;
341 			break;
342 		case QDF_PROTO_DHCP_OFFER:
343 			sta_info->dhcp_phase = DHCP_PHASE_OFFER;
344 			break;
345 		case QDF_PROTO_DHCP_REQUEST:
346 			if (dir != QDF_RX)
347 				break;
348 			if (sta_info->dhcp_nego_status == DHCP_NEGO_STOP)
349 				errno = dp_post_dhcp_ind(
350 						dp_link,
351 						sta_info->sta_mac.bytes,
352 						true);
353 			if (QDF_IS_STATUS_SUCCESS(errno))
354 				sta_info->dhcp_nego_status =
355 						DHCP_NEGO_IN_PROGRESS;
356 			fallthrough;
357 		case QDF_PROTO_DHCP_DECLINE:
358 			if (dir == QDF_RX)
359 				sta_info->dhcp_phase = DHCP_PHASE_REQUEST;
360 			break;
361 		case QDF_PROTO_DHCP_ACK:
362 		case QDF_PROTO_DHCP_NACK:
363 			sta_info->dhcp_phase = DHCP_PHASE_ACK;
364 			if (sta_info->dhcp_nego_status ==
365 				DHCP_NEGO_IN_PROGRESS) {
366 				dp_debug("Setting NOTIFY_COMP Flag");
367 				QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_NOTIFY_COMP(nbuf) = 1;
368 			}
369 			sta_info->dhcp_nego_status = DHCP_NEGO_STOP;
370 			break;
371 		default:
372 			break;
373 		}
374 
375 		wlan_objmgr_peer_release_ref(peer, WLAN_DP_ID);
376 		dp_info("EXIT: phase=%d, nego_status=%d",
377 			sta_info->dhcp_phase,
378 			sta_info->dhcp_nego_status);
379 	}
380 
381 	return errno;
382 }
383 #else
dp_softap_notify_dhcp_ind(void * context,qdf_nbuf_t nbuf)384 static void dp_softap_notify_dhcp_ind(void *context, qdf_nbuf_t nbuf)
385 {
386 }
387 #endif /* SAP_DHCP_FW_IND */
388 
389 #if defined(IPA_OFFLOAD)
390 static
dp_sap_nbuf_orphan(struct wlan_dp_intf * dp_intf,qdf_nbuf_t nbuf)391 qdf_nbuf_t dp_sap_nbuf_orphan(struct wlan_dp_intf *dp_intf,
392 			      qdf_nbuf_t nbuf)
393 {
394 	if (!qdf_nbuf_ipa_owned_get(nbuf)) {
395 		nbuf = dp_nbuf_orphan(dp_intf, nbuf);
396 	} else {
397 		/*
398 		 * Clear the IPA ownership after check it to avoid ipa_free_skb
399 		 * is called when Tx completed for intra-BSS Tx packets
400 		 */
401 		qdf_nbuf_ipa_owned_clear(nbuf);
402 	}
403 	return nbuf;
404 }
405 #else
406 static inline
dp_sap_nbuf_orphan(struct wlan_dp_intf * dp_intf,qdf_nbuf_t nbuf)407 qdf_nbuf_t dp_sap_nbuf_orphan(struct wlan_dp_intf *dp_intf,
408 			      qdf_nbuf_t nbuf)
409 {
410 	return dp_nbuf_orphan(dp_intf, nbuf);
411 }
412 #endif /* IPA_OFFLOAD */
413 
414 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
415 static
dp_softap_get_tx_resource(struct wlan_dp_link * dp_link,qdf_nbuf_t nbuf)416 void dp_softap_get_tx_resource(struct wlan_dp_link *dp_link,
417 			       qdf_nbuf_t nbuf)
418 {
419 	struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
420 
421 	if (QDF_NBUF_CB_GET_IS_BCAST(nbuf) || QDF_NBUF_CB_GET_IS_MCAST(nbuf))
422 		dp_get_tx_resource(dp_link, &dp_intf->mac_addr);
423 	else
424 		dp_get_tx_resource(dp_link,
425 				   (struct qdf_mac_addr *)(qdf_nbuf_data(nbuf) +
426 							   QDF_NBUF_DEST_MAC_OFFSET));
427 }
428 #else
429 #define dp_softap_get_tx_resource(dp_intf, nbuf)
430 #endif
431 
432 #ifdef FEATURE_WDS
433 static void
dp_wds_replace_peer_mac(void * soc,struct wlan_dp_link * dp_link,uint8_t * mac_addr)434 dp_wds_replace_peer_mac(void *soc, struct wlan_dp_link *dp_link,
435 			uint8_t *mac_addr)
436 {
437 	struct cdp_ast_entry_info ast_entry_info = {0};
438 	cdp_config_param_type val;
439 	QDF_STATUS status;
440 
441 	if (!cdp_find_peer_exist(soc, OL_TXRX_PDEV_ID, mac_addr)) {
442 		status = cdp_txrx_get_vdev_param(soc, dp_link->link_id,
443 						 CDP_ENABLE_WDS, &val);
444 		if (!QDF_IS_STATUS_SUCCESS(status))
445 			return;
446 
447 		if (!val.cdp_vdev_param_wds)
448 			return;
449 
450 		if (!cdp_peer_get_ast_info_by_soc(soc,  mac_addr,
451 						  &ast_entry_info))
452 			return;
453 
454 		qdf_mem_copy(mac_addr, ast_entry_info.peer_mac_addr,
455 			     QDF_MAC_ADDR_SIZE);
456 	}
457 }
458 #else
459 static inline
dp_wds_replace_peer_mac(void * soc,struct wlan_dp_link * dp_link,uint8_t * mac_addr)460 void dp_wds_replace_peer_mac(void *soc, struct wlan_dp_link *dp_link,
461 			     uint8_t *mac_addr)
462 {
463 }
464 #endif /* FEATURE_WDS*/
465 
dp_softap_validate_peer_state(struct wlan_dp_link * dp_link,qdf_nbuf_t nbuf)466 static QDF_STATUS dp_softap_validate_peer_state(struct wlan_dp_link *dp_link,
467 						qdf_nbuf_t nbuf)
468 {
469 	struct qdf_mac_addr *dest_mac_addr;
470 	struct qdf_mac_addr mac_addr;
471 	enum ol_txrx_peer_state peer_state;
472 	void *soc;
473 
474 	dest_mac_addr = (struct qdf_mac_addr *)(qdf_nbuf_data(nbuf) +
475 						QDF_NBUF_DEST_MAC_OFFSET);
476 
477 	if (QDF_NBUF_CB_GET_IS_BCAST(nbuf) || QDF_NBUF_CB_GET_IS_MCAST(nbuf))
478 		return QDF_STATUS_SUCCESS;
479 
480 	/* for a unicast frame */
481 	qdf_copy_macaddr(&mac_addr, dest_mac_addr);
482 	soc = cds_get_context(QDF_MODULE_ID_SOC);
483 	QDF_BUG(soc);
484 	dp_wds_replace_peer_mac(soc, dp_link, mac_addr.bytes);
485 	peer_state = cdp_peer_state_get(soc, dp_link->link_id,
486 					mac_addr.bytes, false);
487 
488 	if (peer_state == OL_TXRX_PEER_STATE_INVALID) {
489 		dp_debug_rl("Failed to find right station");
490 		return QDF_STATUS_E_FAILURE;
491 	}
492 
493 	if (peer_state != OL_TXRX_PEER_STATE_CONN &&
494 	    peer_state != OL_TXRX_PEER_STATE_AUTH) {
495 		dp_debug_rl("Station not connected yet");
496 		return QDF_STATUS_E_FAILURE;
497 	}
498 
499 	if (peer_state == OL_TXRX_PEER_STATE_CONN) {
500 		if (qdf_ntohs(qdf_nbuf_get_protocol(nbuf)) != ETHERTYPE_PAE &&
501 		    qdf_ntohs(qdf_nbuf_get_protocol(nbuf)) != ETHERTYPE_WAI) {
502 			dp_debug_rl("NON-EAPOL/WAPI pkt in non-Auth state");
503 			return QDF_STATUS_E_FAILURE;
504 		}
505 	}
506 	return QDF_STATUS_SUCCESS;
507 }
508 
509 static
dp_softap_validate_driver_state(struct wlan_dp_intf * dp_intf)510 QDF_STATUS dp_softap_validate_driver_state(struct wlan_dp_intf *dp_intf)
511 {
512 	if (qdf_unlikely(cds_is_driver_transitioning())) {
513 		dp_err_rl("driver is transitioning, drop pkt");
514 		return QDF_STATUS_E_ABORTED;
515 	}
516 
517 	/*
518 	 * below unified mask will take care of SAP TX block
519 	 * WLAN suspend state check
520 	 * BSS start check and
521 	 * DP TX function register check
522 	 */
523 	if (qdf_unlikely(dp_intf->sap_tx_block_mask)) {
524 		dp_err_rl("Softap TX blocked mask: %u",
525 			  dp_intf->sap_tx_block_mask);
526 		return QDF_STATUS_E_ABORTED;
527 	}
528 
529 	return QDF_STATUS_SUCCESS;
530 }
531 
dp_softap_config_tx_pkt_tracing(struct wlan_dp_intf * dp_intf,qdf_nbuf_t nbuf)532 static void dp_softap_config_tx_pkt_tracing(struct wlan_dp_intf *dp_intf,
533 					    qdf_nbuf_t nbuf)
534 {
535 	if (dp_is_current_high_throughput(dp_intf->dp_ctx))
536 		return;
537 
538 	QDF_NBUF_CB_TX_PACKET_TRACK(nbuf) = QDF_NBUF_TX_PKT_DATA_TRACK;
539 	QDF_NBUF_UPDATE_TX_PKT_COUNT(nbuf, QDF_NBUF_TX_PKT_DP);
540 	qdf_dp_trace_set_track(nbuf, QDF_TX);
541 	DPTRACE(qdf_dp_trace(nbuf, QDF_DP_TRACE_TX_PACKET_PTR_RECORD,
542 			     QDF_TRACE_DEFAULT_PDEV_ID,
543 			     qdf_nbuf_data_addr(nbuf),
544 			     sizeof(qdf_nbuf_data(nbuf)),
545 			     QDF_TX));
546 }
547 
548 #ifdef DP_TRAFFIC_END_INDICATION
549 /**
550  * wlan_dp_traffic_end_indication_update_dscp() - Compare dscp derived from
551  *                                                provided tos value with
552  *                                                stored value and update if
553  *                                                it's equal to special dscp
554  * @dp_intf: pointer to DP interface
555  * @tos: pointer to tos
556  *
557  * Return: True if tos is updated else False
558  */
559 static inline bool
wlan_dp_traffic_end_indication_update_dscp(struct wlan_dp_intf * dp_intf,uint8_t * tos)560 wlan_dp_traffic_end_indication_update_dscp(struct wlan_dp_intf *dp_intf,
561 					   uint8_t *tos)
562 {
563 	bool update;
564 	uint8_t dscp, ecn;
565 
566 	ecn = (*tos & ~QDF_NBUF_PKT_IPV4_DSCP_MASK);
567 	dscp = (*tos & QDF_NBUF_PKT_IPV4_DSCP_MASK) >>
568 		QDF_NBUF_PKT_IPV4_DSCP_SHIFT;
569 	update = (dp_intf->traffic_end_ind.spl_dscp == dscp);
570 	if (update)
571 		*tos = ((dp_intf->traffic_end_ind.def_dscp <<
572 			 QDF_NBUF_PKT_IPV4_DSCP_SHIFT) | ecn);
573 	return update;
574 }
575 
576 /**
577  * dp_softap_inspect_traffic_end_indication_pkt() - Restore tos field for last
578  *                                                  packet in data stream
579  * @dp_intf: pointer to DP interface
580  * @nbuf: pointer to OS packet
581  *
582  * Return: None
583  */
584 static inline void
dp_softap_inspect_traffic_end_indication_pkt(struct wlan_dp_intf * dp_intf,qdf_nbuf_t nbuf)585 dp_softap_inspect_traffic_end_indication_pkt(struct wlan_dp_intf *dp_intf,
586 					     qdf_nbuf_t nbuf)
587 {
588 	uint8_t tos, tc;
589 	bool ret;
590 
591 	if (qdf_nbuf_data_is_ipv4_pkt(qdf_nbuf_data(nbuf))) {
592 		tos = qdf_nbuf_data_get_ipv4_tos(qdf_nbuf_data(nbuf));
593 		ret = wlan_dp_traffic_end_indication_update_dscp(dp_intf, &tos);
594 		if (ret) {
595 			qdf_nbuf_data_set_ipv4_tos(qdf_nbuf_data(nbuf), tos);
596 			if (qdf_nbuf_is_ipv4_last_fragment(nbuf))
597 				QDF_NBUF_CB_GET_PACKET_TYPE(nbuf) =
598 					QDF_NBUF_CB_PACKET_TYPE_END_INDICATION;
599 		}
600 	} else if (qdf_nbuf_is_ipv6_pkt(nbuf)) {
601 		tc = qdf_nbuf_data_get_ipv6_tc(qdf_nbuf_data(nbuf));
602 		ret = wlan_dp_traffic_end_indication_update_dscp(dp_intf, &tc);
603 		if (ret) {
604 			qdf_nbuf_data_set_ipv6_tc(qdf_nbuf_data(nbuf), tc);
605 			QDF_NBUF_CB_GET_PACKET_TYPE(nbuf) =
606 				QDF_NBUF_CB_PACKET_TYPE_END_INDICATION;
607 		}
608 	}
609 }
610 
611 /**
612  * dp_softap_traffic_end_indication_enabled() - Check if traffic end indication
613  *                                              is enabled or not
614  * @dp_intf: pointer to DP interface
615  *
616  * Return: True or False
617  */
618 static inline bool
dp_softap_traffic_end_indication_enabled(struct wlan_dp_intf * dp_intf)619 dp_softap_traffic_end_indication_enabled(struct wlan_dp_intf *dp_intf)
620 {
621 	return qdf_unlikely(dp_intf->traffic_end_ind.enabled);
622 }
623 #else
624 static inline bool
dp_softap_traffic_end_indication_enabled(struct wlan_dp_intf * dp_intf)625 dp_softap_traffic_end_indication_enabled(struct wlan_dp_intf *dp_intf)
626 {
627 	return false;
628 }
629 
630 static inline void
dp_softap_inspect_traffic_end_indication_pkt(struct wlan_dp_intf * dp_intf,qdf_nbuf_t nbuf)631 dp_softap_inspect_traffic_end_indication_pkt(struct wlan_dp_intf *dp_intf,
632 					     qdf_nbuf_t nbuf)
633 {}
634 #endif
635 
636 /**
637  * dp_softap_start_xmit() - Transmit a frame
638  * @nbuf: pointer to Network buffer
639  * @dp_link: DP link handle
640  *
641  * Return: QDF_STATUS_SUCCESS on successful transmission
642  */
dp_softap_start_xmit(qdf_nbuf_t nbuf,struct wlan_dp_link * dp_link)643 QDF_STATUS dp_softap_start_xmit(qdf_nbuf_t nbuf, struct wlan_dp_link *dp_link)
644 {
645 	struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
646 	struct wlan_dp_psoc_context *dp_ctx = dp_intf->dp_ctx;
647 	struct qdf_mac_addr *dest_mac_addr;
648 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
649 	uint32_t num_seg;
650 	struct dp_tx_rx_stats *stats = &dp_intf->dp_stats.tx_rx_stats;
651 	int cpu = qdf_get_smp_processor_id();
652 
653 	dest_mac_addr = (struct qdf_mac_addr *)(qdf_nbuf_data(nbuf) +
654 						QDF_NBUF_DEST_MAC_OFFSET);
655 	++stats->per_cpu[cpu].tx_called;
656 	stats->cont_txtimeout_cnt = 0;
657 
658 	if (QDF_IS_STATUS_ERROR(dp_softap_validate_driver_state(dp_intf)))
659 		goto drop_pkt;
660 
661 	wlan_dp_pkt_add_timestamp(dp_intf, QDF_PKT_TX_DRIVER_ENTRY, nbuf);
662 
663 	if (QDF_IS_STATUS_ERROR(dp_softap_validate_peer_state(dp_link, nbuf)))
664 		goto drop_pkt;
665 
666 	dp_softap_get_tx_resource(dp_link, nbuf);
667 
668 	nbuf = dp_sap_nbuf_orphan(dp_intf, nbuf);
669 	if (!nbuf)
670 		goto drop_pkt_accounting;
671 
672 	qdf_net_buf_debug_acquire_skb(nbuf, __FILE__, __LINE__);
673 
674 	qdf_net_stats_add_tx_bytes(&dp_intf->stats, qdf_nbuf_len(nbuf));
675 
676 	if (qdf_nbuf_is_tso(nbuf)) {
677 		num_seg = qdf_nbuf_get_tso_num_seg(nbuf);
678 		qdf_net_stats_add_tx_pkts(&dp_intf->stats, num_seg);
679 	} else {
680 		qdf_net_stats_add_tx_pkts(&dp_intf->stats, 1);
681 		dp_ctx->no_tx_offload_pkt_cnt++;
682 	}
683 
684 	QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_NOTIFY_COMP(nbuf) = 0;
685 
686 	if (qdf_unlikely(QDF_NBUF_CB_GET_PACKET_TYPE(nbuf) ==
687 			 QDF_NBUF_CB_PACKET_TYPE_DHCP))
688 		dp_softap_inspect_dhcp_packet(dp_link, nbuf, QDF_TX);
689 
690 	if (qdf_unlikely(QDF_NBUF_CB_GET_PACKET_TYPE(nbuf) ==
691 			 QDF_NBUF_CB_PACKET_TYPE_EAPOL)) {
692 		dp_softap_inspect_tx_eap_pkt(dp_intf, nbuf, false);
693 		dp_event_eapol_log(nbuf, QDF_TX);
694 	}
695 
696 	if (dp_softap_traffic_end_indication_enabled(dp_intf))
697 		dp_softap_inspect_traffic_end_indication_pkt(dp_intf, nbuf);
698 
699 	dp_softap_config_tx_pkt_tracing(dp_intf, nbuf);
700 
701 	/* check whether need to linearize skb, like non-linear udp data */
702 	if (dp_nbuf_nontso_linearize(nbuf) != QDF_STATUS_SUCCESS) {
703 		dp_debug_rl("nbuf %pK linearize failed. drop the pkt", nbuf);
704 		goto drop_pkt_and_release_skb;
705 	}
706 
707 	if (dp_intf->txrx_ops.tx.tx(soc, dp_link->link_id, nbuf)) {
708 		dp_debug("Failed to send packet to txrx for sta: "
709 			 QDF_MAC_ADDR_FMT,
710 			 QDF_MAC_ADDR_REF(dest_mac_addr->bytes));
711 		goto drop_pkt_and_release_skb;
712 	}
713 
714 	return QDF_STATUS_SUCCESS;
715 
716 drop_pkt_and_release_skb:
717 	qdf_net_buf_debug_release_skb(nbuf);
718 drop_pkt:
719 	qdf_dp_trace_data_pkt(nbuf, QDF_TRACE_DEFAULT_PDEV_ID,
720 			      QDF_DP_TRACE_DROP_PACKET_RECORD, 0,
721 			      QDF_TX);
722 	qdf_nbuf_kfree(nbuf);
723 drop_pkt_accounting:
724 	qdf_net_stats_inc_tx_dropped(&dp_intf->stats);
725 
726 	return QDF_STATUS_E_FAILURE;
727 }
728 
dp_softap_tx_timeout(struct wlan_dp_intf * dp_intf)729 void dp_softap_tx_timeout(struct wlan_dp_intf *dp_intf)
730 {
731 	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
732 
733 	cdp_dump_flow_pool_info(cds_get_context(QDF_MODULE_ID_SOC));
734 
735 	++dp_intf->dp_stats.tx_rx_stats.tx_timeout_cnt;
736 	++dp_intf->dp_stats.tx_rx_stats.cont_txtimeout_cnt;
737 
738 	if (dp_intf->dp_stats.tx_rx_stats.cont_txtimeout_cnt >
739 	    DP_TX_STALL_THRESHOLD) {
740 		dp_err("Detected data stall due to continuous TX timeouts");
741 		dp_intf->dp_stats.tx_rx_stats.cont_txtimeout_cnt = 0;
742 
743 		if (dp_is_data_stall_event_enabled(DP_HOST_SAP_TX_TIMEOUT))
744 			cdp_post_data_stall_event(soc,
745 					  DATA_STALL_LOG_INDICATOR_HOST_DRIVER,
746 					  DATA_STALL_LOG_HOST_SOFTAP_TX_TIMEOUT,
747 					  OL_TXRX_PDEV_ID, 0xFF,
748 					  DATA_STALL_LOG_RECOVERY_TRIGGER_PDR);
749 	}
750 }
751 
752 /**
753  * dp_softap_notify_tx_compl_cbk() - callback to notify tx completion
754  * @nbuf: pointer to n/w buffer
755  * @context: pointer to DP interface
756  * @flag: tx status flag
757  *
758  * Return: None
759  */
dp_softap_notify_tx_compl_cbk(qdf_nbuf_t nbuf,void * context,uint16_t flag)760 void dp_softap_notify_tx_compl_cbk(qdf_nbuf_t nbuf,
761 				   void *context, uint16_t flag)
762 {
763 	struct wlan_dp_link *dp_link = context;
764 	struct wlan_dp_intf *dp_intf;
765 
766 	if (!is_dp_link_valid(dp_link))
767 		return;
768 
769 	dp_intf = dp_link->dp_intf;
770 	if (QDF_NBUF_CB_PACKET_TYPE_DHCP == QDF_NBUF_CB_GET_PACKET_TYPE(nbuf)) {
771 		dp_debug("sending DHCP indication");
772 		dp_softap_notify_dhcp_ind(context, nbuf);
773 	} else if (QDF_NBUF_CB_GET_PACKET_TYPE(nbuf) ==
774 						QDF_NBUF_CB_PACKET_TYPE_EAPOL) {
775 		dp_softap_inspect_tx_eap_pkt(dp_intf, nbuf, true);
776 	}
777 }
778 
779 #ifdef WLAN_FEATURE_TSF_PLUS_SOCK_TS
780 static inline
dp_softap_tsf_timestamp_rx(struct wlan_dp_psoc_context * dp_ctx,qdf_nbuf_t netbuf)781 void dp_softap_tsf_timestamp_rx(struct wlan_dp_psoc_context *dp_ctx,
782 				qdf_nbuf_t netbuf)
783 {
784 	dp_ctx->dp_ops.dp_tsf_timestamp_rx(dp_ctx->dp_ops.callback_ctx,
785 					   netbuf);
786 }
787 #else
788 static inline
dp_softap_tsf_timestamp_rx(struct wlan_dp_psoc_context * dp_ctx,qdf_nbuf_t netbuf)789 void dp_softap_tsf_timestamp_rx(struct wlan_dp_psoc_context *dp_ctx,
790 				qdf_nbuf_t netbuf)
791 {
792 }
793 #endif
794 
795 #ifdef WLAN_FEATURE_11BE_MLO
dp_nbuf_dst_addr_is_mld_addr(struct wlan_dp_intf * dp_intf,qdf_nbuf_t nbuf)796 static inline bool dp_nbuf_dst_addr_is_mld_addr(struct wlan_dp_intf *dp_intf,
797 						qdf_nbuf_t nbuf)
798 {
799 	struct qdf_mac_addr *mld_addr;
800 
801 	mld_addr = (struct qdf_mac_addr *)&dp_intf->mac_addr;
802 
803 	if (!qdf_is_macaddr_zero(mld_addr) &&
804 	    !qdf_mem_cmp(mld_addr->bytes,
805 			 (qdf_nbuf_data(nbuf) +
806 			  QDF_NBUF_DEST_MAC_OFFSET),
807 			 QDF_MAC_ADDR_SIZE))
808 		return true;
809 
810 	return false;
811 }
812 #else
dp_nbuf_dst_addr_is_mld_addr(struct wlan_dp_intf * dp_intf,qdf_nbuf_t nbuf)813 static inline bool dp_nbuf_dst_addr_is_mld_addr(struct wlan_dp_intf *dp_intf,
814 						qdf_nbuf_t nbuf)
815 {
816 	return false;
817 }
818 #endif
819 
dp_softap_rx_packet_cbk(void * link_ctx,qdf_nbuf_t rx_buf)820 QDF_STATUS dp_softap_rx_packet_cbk(void *link_ctx, qdf_nbuf_t rx_buf)
821 {
822 	struct wlan_dp_intf *dp_intf = NULL;
823 	struct wlan_dp_link *dp_link = NULL;
824 	QDF_STATUS qdf_status;
825 	unsigned int cpu_index;
826 	qdf_nbuf_t nbuf = NULL;
827 	qdf_nbuf_t next = NULL;
828 	struct wlan_dp_psoc_context *dp_ctx = NULL;
829 	bool is_eapol = false;
830 	struct dp_tx_rx_stats *stats;
831 
832 	/* Sanity check on inputs */
833 	if (unlikely(!link_ctx || !rx_buf)) {
834 		dp_err("Null params being passed");
835 		return QDF_STATUS_E_FAILURE;
836 	}
837 
838 	dp_link = (struct wlan_dp_link *)link_ctx;
839 	dp_intf = dp_link->dp_intf;
840 	dp_ctx = dp_intf->dp_ctx;
841 
842 	stats = &dp_intf->dp_stats.tx_rx_stats;
843 	/* walk the chain until all are processed */
844 	next = rx_buf;
845 
846 	while (next) {
847 		nbuf = next;
848 		next = qdf_nbuf_next(nbuf);
849 		qdf_nbuf_set_next(nbuf, NULL);
850 
851 		dp_softap_dump_nbuf(nbuf);
852 
853 		qdf_nbuf_set_dev(nbuf, dp_intf->dev);
854 
855 		cpu_index = qdf_get_cpu();
856 		++stats->per_cpu[cpu_index].rx_packets;
857 		qdf_net_stats_add_rx_pkts(&dp_intf->stats, 1);
858 		/* count aggregated RX frame into stats */
859 		qdf_net_stats_add_rx_pkts(&dp_intf->stats,
860 					  qdf_nbuf_get_gso_segs(nbuf));
861 		qdf_net_stats_add_rx_bytes(&dp_intf->stats,
862 					   qdf_nbuf_len(nbuf));
863 
864 		dp_softap_inspect_dhcp_packet(dp_link, nbuf, QDF_RX);
865 
866 		if (qdf_nbuf_is_ipv4_eapol_pkt(nbuf))
867 			is_eapol = true;
868 
869 		if (qdf_unlikely(is_eapol &&
870 		    !(!qdf_mem_cmp(dp_link->mac_addr.bytes,
871 				   qdf_nbuf_data(nbuf) +
872 				   QDF_NBUF_DEST_MAC_OFFSET,
873 				   QDF_MAC_ADDR_SIZE) ||
874 		    dp_nbuf_dst_addr_is_mld_addr(dp_intf, nbuf)))) {
875 			qdf_nbuf_free(nbuf);
876 			continue;
877 		}
878 
879 		wlan_dp_pkt_add_timestamp(dp_intf,
880 					  QDF_PKT_RX_DRIVER_EXIT, nbuf);
881 
882 		dp_event_eapol_log(nbuf, QDF_RX);
883 		qdf_dp_trace_log_pkt(dp_link->link_id,
884 				     nbuf, QDF_RX, QDF_TRACE_DEFAULT_PDEV_ID,
885 				     dp_intf->device_mode);
886 		DPTRACE(qdf_dp_trace(nbuf,
887 				     QDF_DP_TRACE_RX_PACKET_PTR_RECORD,
888 				     QDF_TRACE_DEFAULT_PDEV_ID,
889 				     qdf_nbuf_data_addr(nbuf),
890 				     sizeof(qdf_nbuf_data(nbuf)), QDF_RX));
891 		DPTRACE(qdf_dp_trace_data_pkt(nbuf, QDF_TRACE_DEFAULT_PDEV_ID,
892 					      QDF_DP_TRACE_RX_PACKET_RECORD,
893 					      0, QDF_RX));
894 
895 		if (dp_rx_pkt_tracepoints_enabled())
896 			qdf_trace_dp_packet(nbuf, QDF_RX, NULL, 0);
897 
898 		qdf_nbuf_set_protocol_eth_tye_trans(nbuf);
899 
900 		/* hold configurable wakelock for unicast traffic */
901 		if (!dp_is_current_high_throughput(dp_ctx) &&
902 		    dp_ctx->dp_cfg.rx_wakelock_timeout &&
903 		    !qdf_nbuf_pkt_type_is_mcast(nbuf) &&
904 		    !qdf_nbuf_pkt_type_is_bcast(nbuf)) {
905 			cds_host_diag_log_work(&dp_ctx->rx_wake_lock,
906 					dp_ctx->dp_cfg.rx_wakelock_timeout,
907 					WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
908 			qdf_wake_lock_timeout_acquire(&dp_ctx->rx_wake_lock,
909 					dp_ctx->dp_cfg.rx_wakelock_timeout);
910 		}
911 
912 		/* Remove SKB from internal tracking table before submitting
913 		 * it to stack
914 		 */
915 		qdf_net_buf_debug_release_skb(nbuf);
916 
917 		dp_softap_tsf_timestamp_rx(dp_ctx, nbuf);
918 
919 		if (is_eapol && dp_ctx->dp_ops.dp_send_rx_pkt_over_nl) {
920 			if (dp_ctx->dp_ops.dp_send_rx_pkt_over_nl(dp_intf->dev,
921 					(u8 *)&dp_link->conn_info.peer_macaddr,
922 								  nbuf, false))
923 				qdf_status = QDF_STATUS_SUCCESS;
924 			else
925 				qdf_status = QDF_STATUS_E_INVAL;
926 			qdf_nbuf_dev_kfree(nbuf);
927 		} else {
928 			qdf_status = wlan_dp_rx_deliver_to_stack(dp_intf, nbuf);
929 		}
930 
931 		if (QDF_IS_STATUS_SUCCESS(qdf_status))
932 			++stats->per_cpu[cpu_index].rx_delivered;
933 		else
934 			++stats->per_cpu[cpu_index].rx_refused;
935 	}
936 
937 	return QDF_STATUS_SUCCESS;
938 }
939