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_txrx.c
20 * DP 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 <qdf_types.h>
29 #include <cdp_txrx_cmn.h>
30 #include <cdp_txrx_peer_ops.h>
31 #include <cdp_txrx_misc.h>
32 #include <cdp_txrx_flow_ctrl_v2.h>
33 #include "wlan_dp_rx_thread.h"
34 #if defined(WLAN_SUPPORT_RX_FISA)
35 #include "wlan_dp_fisa_rx.h"
36 #endif
37 #include "nan_public_structs.h"
38 #include "wlan_nan_api_i.h"
39 #include <wlan_cm_api.h>
40 #include <enet.h>
41 #include <cds_utils.h>
42 #include <wlan_dp_bus_bandwidth.h>
43 #include "wlan_tdls_api.h"
44 #include <qdf_trace.h>
45 #include <qdf_net_stats.h>
46
wlan_dp_intf_get_pkt_type_bitmap_value(void * intf_ctx)47 uint32_t wlan_dp_intf_get_pkt_type_bitmap_value(void *intf_ctx)
48 {
49 struct wlan_dp_intf *dp_intf = (struct wlan_dp_intf *)intf_ctx;
50
51 if (!dp_intf) {
52 dp_err_rl("DP Context is NULL");
53 return 0;
54 }
55
56 return dp_intf->pkt_type_bitmap;
57 }
58
59 #if defined(WLAN_SUPPORT_RX_FISA)
dp_rx_skip_fisa(struct wlan_dp_psoc_context * dp_ctx,uint32_t value)60 void dp_rx_skip_fisa(struct wlan_dp_psoc_context *dp_ctx, uint32_t value)
61 {
62 qdf_atomic_set(&dp_ctx->skip_fisa_param.skip_fisa, !value);
63 }
64 #endif
65
66 #ifdef QCA_LL_LEGACY_TX_FLOW_CONTROL
dp_get_tx_resource(struct wlan_dp_link * dp_link,struct qdf_mac_addr * mac_addr)67 void dp_get_tx_resource(struct wlan_dp_link *dp_link,
68 struct qdf_mac_addr *mac_addr)
69 {
70 struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
71 struct wlan_dp_psoc_callbacks *dp_ops = &dp_intf->dp_ctx->dp_ops;
72
73 dp_ops->dp_get_tx_resource(dp_link->link_id,
74 mac_addr);
75 }
76 #endif /* QCA_LL_LEGACY_TX_FLOW_CONTROL */
77
78 #ifdef FEATURE_WLAN_DIAG_SUPPORT
79 /**
80 * dp_event_eapol_log() - send event to wlan diag
81 * @nbuf: Network buffer ptr
82 * @dir: direction
83 *
84 * Return: None
85 */
dp_event_eapol_log(qdf_nbuf_t nbuf,enum qdf_proto_dir dir)86 void dp_event_eapol_log(qdf_nbuf_t nbuf, enum qdf_proto_dir dir)
87 {
88 int16_t eapol_key_info;
89
90 WLAN_HOST_DIAG_EVENT_DEF(wlan_diag_event, struct host_event_wlan_eapol);
91
92 if (dir == QDF_TX && QDF_NBUF_CB_PACKET_TYPE_EAPOL !=
93 QDF_NBUF_CB_GET_PACKET_TYPE(nbuf))
94 return;
95 else if (!qdf_nbuf_is_ipv4_eapol_pkt(nbuf))
96 return;
97
98 eapol_key_info = (uint16_t)(*(uint16_t *)
99 (nbuf->data + EAPOL_KEY_INFO_OFFSET));
100
101 wlan_diag_event.event_sub_type =
102 (dir == QDF_TX ?
103 WIFI_EVENT_DRIVER_EAPOL_FRAME_TRANSMIT_REQUESTED :
104 WIFI_EVENT_DRIVER_EAPOL_FRAME_RECEIVED);
105 wlan_diag_event.eapol_packet_type = (uint8_t)(*(uint8_t *)
106 (nbuf->data + EAPOL_PACKET_TYPE_OFFSET));
107 wlan_diag_event.eapol_key_info = eapol_key_info;
108 wlan_diag_event.eapol_rate = 0;
109 qdf_mem_copy(wlan_diag_event.dest_addr,
110 (nbuf->data + QDF_NBUF_DEST_MAC_OFFSET),
111 sizeof(wlan_diag_event.dest_addr));
112 qdf_mem_copy(wlan_diag_event.src_addr,
113 (nbuf->data + QDF_NBUF_SRC_MAC_OFFSET),
114 sizeof(wlan_diag_event.src_addr));
115
116 WLAN_HOST_DIAG_EVENT_REPORT(&wlan_diag_event, EVENT_WLAN_EAPOL);
117 }
118 #endif /* FEATURE_WLAN_DIAG_SUPPORT */
119
dp_intf_is_tx_allowed(qdf_nbuf_t nbuf,uint8_t intf_id,void * soc,uint8_t * peer_mac)120 static int dp_intf_is_tx_allowed(qdf_nbuf_t nbuf,
121 uint8_t intf_id, void *soc,
122 uint8_t *peer_mac)
123 {
124 enum ol_txrx_peer_state peer_state;
125
126 peer_state = cdp_peer_state_get(soc, intf_id, peer_mac, false);
127 if (qdf_likely(OL_TXRX_PEER_STATE_AUTH == peer_state))
128 return true;
129 if (OL_TXRX_PEER_STATE_CONN == peer_state &&
130 (qdf_ntohs(qdf_nbuf_get_protocol(nbuf)) == ETHERTYPE_PAE ||
131 IS_DP_ETHERTYPE_WAI(nbuf)))
132 return true;
133
134 dp_info("Invalid peer state for Tx: %d", peer_state);
135 return false;
136 }
137
138 /**
139 * dp_tx_rx_is_dns_domain_name_match() - function to check whether dns
140 * domain name in the received nbuf matches with the tracking dns domain
141 * name or not
142 *
143 * @nbuf: Network buffer pointer
144 * @dp_intf: DP interface pointer
145 *
146 * Returns: true if matches else false
147 */
dp_tx_rx_is_dns_domain_name_match(qdf_nbuf_t nbuf,struct wlan_dp_intf * dp_intf)148 static bool dp_tx_rx_is_dns_domain_name_match(qdf_nbuf_t nbuf,
149 struct wlan_dp_intf *dp_intf)
150 {
151 uint8_t *domain_name;
152
153 if (dp_intf->track_dns_domain_len == 0)
154 return false;
155
156 /* check OOB , is strncmp accessing data more than skb->len */
157 if ((dp_intf->track_dns_domain_len +
158 QDF_NBUF_PKT_DNS_NAME_OVER_UDP_OFFSET) > qdf_nbuf_len(nbuf))
159 return false;
160
161 domain_name = qdf_nbuf_get_dns_domain_name(nbuf,
162 dp_intf->track_dns_domain_len);
163 if (qdf_str_ncmp(domain_name, dp_intf->dns_payload,
164 dp_intf->track_dns_domain_len) == 0)
165 return true;
166 else
167 return false;
168 }
169
170 /**
171 * dp_clear_tx_rx_connectivity_stats() - clear connectivity stats
172 * @dp_intf: pointer to DP interface
173 *
174 * Return: None
175 */
dp_clear_tx_rx_connectivity_stats(struct wlan_dp_intf * dp_intf)176 static void dp_clear_tx_rx_connectivity_stats(struct wlan_dp_intf *dp_intf)
177 {
178 dp_debug("Clear txrx connectivity stats");
179 qdf_mem_zero(&dp_intf->dp_stats.arp_stats,
180 sizeof(dp_intf->dp_stats.arp_stats));
181 qdf_mem_zero(&dp_intf->dp_stats.dns_stats,
182 sizeof(dp_intf->dp_stats.dns_stats));
183 qdf_mem_zero(&dp_intf->dp_stats.tcp_stats,
184 sizeof(dp_intf->dp_stats.tcp_stats));
185 qdf_mem_zero(&dp_intf->dp_stats.icmpv4_stats,
186 sizeof(dp_intf->dp_stats.icmpv4_stats));
187 dp_intf->pkt_type_bitmap = 0;
188 dp_intf->track_arp_ip = 0;
189 qdf_mem_zero(dp_intf->dns_payload, dp_intf->track_dns_domain_len);
190 dp_intf->track_dns_domain_len = 0;
191 dp_intf->track_src_port = 0;
192 dp_intf->track_dest_port = 0;
193 dp_intf->track_dest_ipv4 = 0;
194 }
195
dp_reset_all_intfs_connectivity_stats(struct wlan_dp_psoc_context * dp_ctx)196 void dp_reset_all_intfs_connectivity_stats(struct wlan_dp_psoc_context *dp_ctx)
197 {
198 struct wlan_dp_intf *dp_intf = NULL;
199
200 qdf_spin_lock_bh(&dp_ctx->intf_list_lock);
201 for (dp_get_front_intf_no_lock(dp_ctx, &dp_intf); dp_intf;
202 dp_get_next_intf_no_lock(dp_ctx, dp_intf, &dp_intf)) {
203 dp_clear_tx_rx_connectivity_stats(dp_intf);
204 }
205 qdf_spin_unlock_bh(&dp_ctx->intf_list_lock);
206 }
207
208 void
dp_tx_rx_collect_connectivity_stats_info(qdf_nbuf_t nbuf,void * context,enum connectivity_stats_pkt_status action,uint8_t * pkt_type)209 dp_tx_rx_collect_connectivity_stats_info(qdf_nbuf_t nbuf, void *context,
210 enum connectivity_stats_pkt_status action, uint8_t *pkt_type)
211 {
212 uint32_t pkt_type_bitmap;
213 struct wlan_dp_link *dp_link = (struct wlan_dp_link *)context;
214 struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
215
216 /* ARP tracking is done already. */
217 pkt_type_bitmap = dp_intf->pkt_type_bitmap;
218
219 pkt_type_bitmap &= ~dp_intf->dp_ctx->arp_connectivity_map;
220
221 if (!pkt_type_bitmap)
222 return;
223
224 switch (action) {
225 case PKT_TYPE_REQ:
226 case PKT_TYPE_TX_HOST_FW_SENT:
227 if (qdf_nbuf_is_icmp_pkt(nbuf)) {
228 if (qdf_nbuf_data_is_icmpv4_req(nbuf) &&
229 dp_intf->track_dest_ipv4 ==
230 qdf_nbuf_get_icmpv4_tgt_ip(nbuf)) {
231 *pkt_type = DP_CONNECTIVITY_CHECK_SET_ICMPV4;
232 if (action == PKT_TYPE_REQ) {
233 ++dp_intf->dp_stats.icmpv4_stats.
234 tx_icmpv4_req_count;
235 dp_info("ICMPv4 Req packet");
236 } else
237 /* host receives tx completion */
238 ++dp_intf->dp_stats.icmpv4_stats.
239 tx_host_fw_sent;
240 }
241 } else if (qdf_nbuf_is_ipv4_tcp_pkt(nbuf)) {
242 if (qdf_nbuf_data_is_tcp_syn(nbuf) &&
243 dp_intf->track_dest_port ==
244 qdf_nbuf_data_get_tcp_dst_port(nbuf)) {
245 *pkt_type = DP_CONNECTIVITY_CHECK_SET_TCP_SYN;
246 if (action == PKT_TYPE_REQ) {
247 ++dp_intf->dp_stats.tcp_stats.
248 tx_tcp_syn_count;
249 dp_info("TCP Syn packet");
250 } else {
251 /* host receives tx completion */
252 ++dp_intf->dp_stats.tcp_stats.
253 tx_tcp_syn_host_fw_sent;
254 }
255 } else if ((dp_intf->dp_stats.tcp_stats.
256 is_tcp_syn_ack_rcv || dp_intf->dp_stats.
257 tcp_stats.is_tcp_ack_sent) &&
258 qdf_nbuf_data_is_tcp_ack(nbuf) &&
259 (dp_intf->track_dest_port ==
260 qdf_nbuf_data_get_tcp_dst_port(nbuf))) {
261 *pkt_type = DP_CONNECTIVITY_CHECK_SET_TCP_ACK;
262 if (action == PKT_TYPE_REQ &&
263 dp_intf->dp_stats.tcp_stats.
264 is_tcp_syn_ack_rcv) {
265 ++dp_intf->dp_stats.tcp_stats.
266 tx_tcp_ack_count;
267 dp_intf->dp_stats.tcp_stats.
268 is_tcp_syn_ack_rcv = false;
269 dp_intf->dp_stats.tcp_stats.
270 is_tcp_ack_sent = true;
271 dp_info("TCP Ack packet");
272 } else if (action == PKT_TYPE_TX_HOST_FW_SENT &&
273 dp_intf->dp_stats.tcp_stats.
274 is_tcp_ack_sent) {
275 /* host receives tx completion */
276 ++dp_intf->dp_stats.tcp_stats.
277 tx_tcp_ack_host_fw_sent;
278 dp_intf->dp_stats.tcp_stats.
279 is_tcp_ack_sent = false;
280 }
281 }
282 } else if (qdf_nbuf_is_ipv4_udp_pkt(nbuf)) {
283 if (qdf_nbuf_data_is_dns_query(nbuf) &&
284 dp_tx_rx_is_dns_domain_name_match(nbuf, dp_intf)) {
285 *pkt_type = DP_CONNECTIVITY_CHECK_SET_DNS;
286 if (action == PKT_TYPE_REQ) {
287 ++dp_intf->dp_stats.dns_stats.
288 tx_dns_req_count;
289 dp_info("DNS query packet");
290 } else
291 /* host receives tx completion */
292 ++dp_intf->dp_stats.dns_stats.
293 tx_host_fw_sent;
294 }
295 }
296 break;
297
298 case PKT_TYPE_RSP:
299 if (qdf_nbuf_is_icmp_pkt(nbuf)) {
300 if (qdf_nbuf_data_is_icmpv4_rsp(nbuf) &&
301 (dp_intf->track_dest_ipv4 ==
302 qdf_nbuf_get_icmpv4_src_ip(nbuf))) {
303 ++dp_intf->dp_stats.icmpv4_stats.
304 rx_icmpv4_rsp_count;
305 *pkt_type =
306 DP_CONNECTIVITY_CHECK_SET_ICMPV4;
307 dp_info("ICMPv4 resp packet");
308 }
309 } else if (qdf_nbuf_is_ipv4_tcp_pkt(nbuf)) {
310 if (qdf_nbuf_data_is_tcp_syn_ack(nbuf) &&
311 (dp_intf->track_dest_port ==
312 qdf_nbuf_data_get_tcp_src_port(nbuf))) {
313 ++dp_intf->dp_stats.tcp_stats.
314 rx_tcp_syn_ack_count;
315 dp_intf->dp_stats.tcp_stats.
316 is_tcp_syn_ack_rcv = true;
317 *pkt_type =
318 DP_CONNECTIVITY_CHECK_SET_TCP_SYN_ACK;
319 dp_info("TCP Syn ack packet");
320 }
321 } else if (qdf_nbuf_is_ipv4_udp_pkt(nbuf)) {
322 if (qdf_nbuf_data_is_dns_response(nbuf) &&
323 dp_tx_rx_is_dns_domain_name_match(nbuf, dp_intf)) {
324 ++dp_intf->dp_stats.dns_stats.
325 rx_dns_rsp_count;
326 *pkt_type = DP_CONNECTIVITY_CHECK_SET_DNS;
327 dp_info("DNS resp packet");
328 }
329 }
330 break;
331
332 case PKT_TYPE_TX_DROPPED:
333 switch (*pkt_type) {
334 case DP_CONNECTIVITY_CHECK_SET_ICMPV4:
335 ++dp_intf->dp_stats.icmpv4_stats.tx_dropped;
336 dp_info("ICMPv4 Req packet dropped");
337 break;
338 case DP_CONNECTIVITY_CHECK_SET_TCP_SYN:
339 ++dp_intf->dp_stats.tcp_stats.tx_tcp_syn_dropped;
340 dp_info("TCP syn packet dropped");
341 break;
342 case DP_CONNECTIVITY_CHECK_SET_TCP_ACK:
343 ++dp_intf->dp_stats.tcp_stats.tx_tcp_ack_dropped;
344 dp_info("TCP ack packet dropped");
345 break;
346 case DP_CONNECTIVITY_CHECK_SET_DNS:
347 ++dp_intf->dp_stats.dns_stats.tx_dropped;
348 dp_info("DNS query packet dropped");
349 break;
350 default:
351 break;
352 }
353 break;
354 case PKT_TYPE_RX_DELIVERED:
355 switch (*pkt_type) {
356 case DP_CONNECTIVITY_CHECK_SET_ICMPV4:
357 ++dp_intf->dp_stats.icmpv4_stats.rx_delivered;
358 break;
359 case DP_CONNECTIVITY_CHECK_SET_TCP_SYN_ACK:
360 ++dp_intf->dp_stats.tcp_stats.rx_delivered;
361 break;
362 case DP_CONNECTIVITY_CHECK_SET_DNS:
363 ++dp_intf->dp_stats.dns_stats.rx_delivered;
364 break;
365 default:
366 break;
367 }
368 break;
369 case PKT_TYPE_RX_REFUSED:
370 switch (*pkt_type) {
371 case DP_CONNECTIVITY_CHECK_SET_ICMPV4:
372 ++dp_intf->dp_stats.icmpv4_stats.rx_refused;
373 break;
374 case DP_CONNECTIVITY_CHECK_SET_TCP_SYN_ACK:
375 ++dp_intf->dp_stats.tcp_stats.rx_refused;
376 break;
377 case DP_CONNECTIVITY_CHECK_SET_DNS:
378 ++dp_intf->dp_stats.dns_stats.rx_refused;
379 break;
380 default:
381 break;
382 }
383 break;
384 case PKT_TYPE_TX_ACK_CNT:
385 switch (*pkt_type) {
386 case DP_CONNECTIVITY_CHECK_SET_ICMPV4:
387 ++dp_intf->dp_stats.icmpv4_stats.tx_ack_cnt;
388 break;
389 case DP_CONNECTIVITY_CHECK_SET_TCP_SYN:
390 ++dp_intf->dp_stats.tcp_stats.tx_tcp_syn_ack_cnt;
391 break;
392 case DP_CONNECTIVITY_CHECK_SET_TCP_ACK:
393 ++dp_intf->dp_stats.tcp_stats.tx_tcp_ack_ack_cnt;
394 break;
395 case DP_CONNECTIVITY_CHECK_SET_DNS:
396 ++dp_intf->dp_stats.dns_stats.tx_ack_cnt;
397 break;
398 default:
399 break;
400 }
401 break;
402 default:
403 break;
404 }
405 }
406
407 /**
408 * dp_get_transmit_mac_addr() - Get the mac address to validate the xmit
409 * @dp_link: DP link handle
410 * @nbuf: The network buffer
411 * @mac_addr_tx_allowed: The mac address to be filled
412 *
413 * Return: None
414 */
415 static
dp_get_transmit_mac_addr(struct wlan_dp_link * dp_link,qdf_nbuf_t nbuf,struct qdf_mac_addr * mac_addr_tx_allowed)416 void dp_get_transmit_mac_addr(struct wlan_dp_link *dp_link,
417 qdf_nbuf_t nbuf,
418 struct qdf_mac_addr *mac_addr_tx_allowed)
419 {
420 struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
421 bool is_mc_bc_addr = false;
422 enum nan_datapath_state state;
423
424 /* Check for VDEV validity before accessing it. Since VDEV references
425 * are not taken in the per packet path, there is a change for VDEV
426 * getting deleted in a parallel context. Because DP VDEV object is
427 * protected by dp_intf::num_active_task, the chance of VDEV object
428 * getting deleted while executing dp_start_xmit() is sparse. So, a
429 * simple VDEV NULL check should be sufficient to handle the case of
430 * VDEV getting destroyed first followed by dp_start_xmit().
431 */
432 if (!dp_link->vdev)
433 return;
434
435 switch (dp_intf->device_mode) {
436 case QDF_NDI_MODE:
437 state = wlan_nan_get_ndi_state(dp_link->vdev);
438 if (state == NAN_DATA_NDI_CREATED_STATE ||
439 state == NAN_DATA_CONNECTED_STATE ||
440 state == NAN_DATA_CONNECTING_STATE ||
441 state == NAN_DATA_PEER_CREATE_STATE) {
442 if (QDF_NBUF_CB_GET_IS_BCAST(nbuf) ||
443 QDF_NBUF_CB_GET_IS_MCAST(nbuf))
444 is_mc_bc_addr = true;
445 if (is_mc_bc_addr)
446 qdf_copy_macaddr(mac_addr_tx_allowed,
447 &dp_intf->mac_addr);
448 else
449 qdf_copy_macaddr(mac_addr_tx_allowed,
450 (struct qdf_mac_addr *)qdf_nbuf_data(nbuf));
451 }
452 break;
453 case QDF_STA_MODE:
454 case QDF_P2P_CLIENT_MODE:
455 if (wlan_cm_is_vdev_active(dp_link->vdev))
456 qdf_copy_macaddr(mac_addr_tx_allowed,
457 &dp_link->conn_info.bssid);
458 break;
459 default:
460 break;
461 }
462 }
463
464 #ifdef HANDLE_BROADCAST_EAPOL_TX_FRAME
465 /**
466 * dp_fix_broadcast_eapol() - Fix broadcast eapol
467 * @dp_link: pointer to dp link
468 * @nbuf: pointer to nbuf
469 *
470 * Override DA of broadcast eapol with bssid addr.
471 *
472 * Return: None
473 */
dp_fix_broadcast_eapol(struct wlan_dp_link * dp_link,qdf_nbuf_t nbuf)474 static void dp_fix_broadcast_eapol(struct wlan_dp_link *dp_link,
475 qdf_nbuf_t nbuf)
476 {
477 qdf_ether_header_t *eth_hdr = (qdf_ether_header_t *)qdf_nbuf_data(nbuf);
478 unsigned char *ap_mac_addr =
479 &dp_link->conn_info.bssid.bytes[0];
480
481 if (qdf_unlikely((QDF_NBUF_CB_GET_PACKET_TYPE(nbuf) ==
482 QDF_NBUF_CB_PACKET_TYPE_EAPOL) &&
483 QDF_NBUF_CB_GET_IS_BCAST(nbuf))) {
484 dp_debug("SA: "QDF_MAC_ADDR_FMT " override DA: "QDF_MAC_ADDR_FMT " with AP mac address "QDF_MAC_ADDR_FMT,
485 QDF_MAC_ADDR_REF(ð_hdr->ether_shost[0]),
486 QDF_MAC_ADDR_REF(ð_hdr->ether_dhost[0]),
487 QDF_MAC_ADDR_REF(ap_mac_addr));
488
489 qdf_mem_copy(ð_hdr->ether_dhost, ap_mac_addr,
490 QDF_MAC_ADDR_SIZE);
491 }
492 }
493 #else
dp_fix_broadcast_eapol(struct wlan_dp_link * dp_link,qdf_nbuf_t nbuf)494 static void dp_fix_broadcast_eapol(struct wlan_dp_link *dp_link,
495 qdf_nbuf_t nbuf)
496 {
497 }
498 #endif /* HANDLE_BROADCAST_EAPOL_TX_FRAME */
499
500 #ifdef WLAN_DP_FEATURE_MARK_ICMP_REQ_TO_FW
501 /**
502 * dp_mark_icmp_req_to_fw() - Mark the ICMP request at a certain time interval
503 * to be sent to the FW.
504 * @dp_ctx: Global dp context
505 * @nbuf: packet to be transmitted
506 *
507 * This func sets the "to_fw" flag in the packet context block, if the
508 * current packet is an ICMP request packet. This marking is done at a
509 * specific time interval, unless the INI value indicates to disable/enable
510 * this for all frames.
511 *
512 * Return: none
513 */
dp_mark_icmp_req_to_fw(struct wlan_dp_psoc_context * dp_ctx,qdf_nbuf_t nbuf)514 static void dp_mark_icmp_req_to_fw(struct wlan_dp_psoc_context *dp_ctx,
515 qdf_nbuf_t nbuf)
516 {
517 uint64_t curr_time, time_delta;
518 int time_interval_ms = dp_ctx->dp_cfg.icmp_req_to_fw_mark_interval;
519 static uint64_t prev_marked_icmp_time;
520
521 if (!dp_ctx->dp_cfg.icmp_req_to_fw_mark_interval)
522 return;
523
524 if ((qdf_nbuf_get_icmp_subtype(nbuf) != QDF_PROTO_ICMP_REQ) &&
525 (qdf_nbuf_get_icmpv6_subtype(nbuf) != QDF_PROTO_ICMPV6_REQ))
526 return;
527
528 /* Mark all ICMP request to be sent to FW */
529 if (time_interval_ms == WLAN_CFG_ICMP_REQ_TO_FW_MARK_ALL)
530 QDF_NBUF_CB_TX_PACKET_TO_FW(nbuf) = 1;
531
532 /* For fragment IPV4 ICMP frames
533 * only mark last segment once to FW
534 */
535 if (qdf_nbuf_is_ipv4_pkt(nbuf) &&
536 qdf_nbuf_is_ipv4_fragment(nbuf))
537 return;
538
539 curr_time = qdf_get_log_timestamp();
540 time_delta = curr_time - prev_marked_icmp_time;
541 if (time_delta >= (time_interval_ms *
542 QDF_LOG_TIMESTAMP_CYCLES_PER_10_US * 100)) {
543 QDF_NBUF_CB_TX_PACKET_TO_FW(nbuf) = 1;
544 prev_marked_icmp_time = curr_time;
545 }
546 }
547 #else
dp_mark_icmp_req_to_fw(struct wlan_dp_psoc_context * dp_ctx,qdf_nbuf_t nbuf)548 static void dp_mark_icmp_req_to_fw(struct wlan_dp_psoc_context *dp_ctx,
549 qdf_nbuf_t nbuf)
550 {
551 }
552 #endif
553
554 #ifdef CONFIG_DP_PKT_ADD_TIMESTAMP
wlan_dp_pkt_add_timestamp(struct wlan_dp_intf * dp_intf,enum qdf_pkt_timestamp_index index,qdf_nbuf_t nbuf)555 void wlan_dp_pkt_add_timestamp(struct wlan_dp_intf *dp_intf,
556 enum qdf_pkt_timestamp_index index,
557 qdf_nbuf_t nbuf)
558 {
559 struct wlan_dp_psoc_callbacks *dp_ops;
560
561 if (qdf_unlikely(qdf_is_dp_pkt_timestamp_enabled())) {
562 uint64_t tsf_time;
563
564 dp_ops = &dp_intf->dp_ctx->dp_ops;
565 dp_ops->dp_get_tsf_time(dp_intf->dev,
566 qdf_get_log_timestamp(),
567 &tsf_time);
568 qdf_add_dp_pkt_timestamp(nbuf, index, tsf_time);
569 }
570 }
571 #endif
572
573 QDF_STATUS
dp_start_xmit(struct wlan_dp_link * dp_link,qdf_nbuf_t nbuf)574 dp_start_xmit(struct wlan_dp_link *dp_link, qdf_nbuf_t nbuf)
575 {
576 struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
577 struct wlan_dp_psoc_context *dp_ctx = dp_intf->dp_ctx;
578 struct dp_tx_rx_stats *stats;
579 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
580 enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
581 bool is_arp = false;
582 bool is_eapol = false;
583 bool is_dhcp = false;
584 uint8_t pkt_type;
585 struct qdf_mac_addr mac_addr_tx_allowed = QDF_MAC_ADDR_ZERO_INIT;
586 int cpu = qdf_get_smp_processor_id();
587
588 stats = &dp_intf->dp_stats.tx_rx_stats;
589 ++stats->per_cpu[cpu].tx_called;
590 stats->cont_txtimeout_cnt = 0;
591
592 if (qdf_unlikely(cds_is_driver_transitioning())) {
593 dp_err_rl("driver is transitioning, drop pkt");
594 goto drop_pkt;
595 }
596
597 if (qdf_unlikely(dp_ctx->is_suspend)) {
598 dp_err_rl("Device is system suspended, drop pkt");
599 goto drop_pkt;
600 }
601
602 QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_NOTIFY_COMP(nbuf) = 1;
603
604 pkt_type = QDF_NBUF_CB_GET_PACKET_TYPE(nbuf);
605
606 if (pkt_type == QDF_NBUF_CB_PACKET_TYPE_ARP) {
607 if (qdf_nbuf_data_is_arp_req(nbuf) &&
608 (dp_intf->track_arp_ip == qdf_nbuf_get_arp_tgt_ip(nbuf))) {
609 is_arp = true;
610 ++dp_intf->dp_stats.arp_stats.tx_arp_req_count;
611 dp_info("ARP packet");
612 }
613 } else if (pkt_type == QDF_NBUF_CB_PACKET_TYPE_EAPOL) {
614 subtype = qdf_nbuf_get_eapol_subtype(nbuf);
615 if (subtype == QDF_PROTO_EAPOL_M2) {
616 ++dp_intf->dp_stats.eapol_stats.eapol_m2_count;
617 is_eapol = true;
618 } else if (subtype == QDF_PROTO_EAPOL_M4) {
619 ++dp_intf->dp_stats.eapol_stats.eapol_m4_count;
620 is_eapol = true;
621 }
622 } else if (pkt_type == QDF_NBUF_CB_PACKET_TYPE_DHCP) {
623 subtype = qdf_nbuf_get_dhcp_subtype(nbuf);
624 if (subtype == QDF_PROTO_DHCP_DISCOVER) {
625 ++dp_intf->dp_stats.dhcp_stats.dhcp_dis_count;
626 is_dhcp = true;
627 } else if (subtype == QDF_PROTO_DHCP_REQUEST) {
628 ++dp_intf->dp_stats.dhcp_stats.dhcp_req_count;
629 is_dhcp = true;
630 }
631 } else if ((pkt_type == QDF_NBUF_CB_PACKET_TYPE_ICMP) ||
632 (pkt_type == QDF_NBUF_CB_PACKET_TYPE_ICMPv6)) {
633 dp_mark_icmp_req_to_fw(dp_ctx, nbuf);
634 }
635
636 wlan_dp_pkt_add_timestamp(dp_intf, QDF_PKT_TX_DRIVER_ENTRY, nbuf);
637
638 /* track connectivity stats */
639 if (dp_intf->pkt_type_bitmap)
640 dp_tx_rx_collect_connectivity_stats_info(nbuf, dp_link,
641 PKT_TYPE_REQ,
642 &pkt_type);
643
644 dp_get_transmit_mac_addr(dp_link, nbuf, &mac_addr_tx_allowed);
645 if (qdf_is_macaddr_zero(&mac_addr_tx_allowed)) {
646 dp_info_rl("tx not allowed, transmit operation suspended");
647 goto drop_pkt;
648 }
649
650 dp_get_tx_resource(dp_link, &mac_addr_tx_allowed);
651
652 if (!qdf_nbuf_ipa_owned_get(nbuf)) {
653 nbuf = dp_nbuf_orphan(dp_intf, nbuf);
654 if (!nbuf)
655 goto drop_pkt_accounting;
656 }
657
658 /*
659 * Add SKB to internal tracking table before further processing
660 * in WLAN driver.
661 */
662 qdf_net_buf_debug_acquire_skb(nbuf, __FILE__, __LINE__);
663
664 qdf_net_stats_add_tx_bytes(&dp_intf->stats, qdf_nbuf_len(nbuf));
665
666 if (qdf_nbuf_is_tso(nbuf)) {
667 qdf_net_stats_add_tx_pkts(&dp_intf->stats,
668 qdf_nbuf_get_tso_num_seg(nbuf));
669 } else {
670 qdf_net_stats_add_tx_pkts(&dp_intf->stats, 1);
671 dp_ctx->no_tx_offload_pkt_cnt++;
672 }
673
674 dp_event_eapol_log(nbuf, QDF_TX);
675 QDF_NBUF_CB_TX_PACKET_TRACK(nbuf) = QDF_NBUF_TX_PKT_DATA_TRACK;
676 QDF_NBUF_UPDATE_TX_PKT_COUNT(nbuf, QDF_NBUF_TX_PKT_DP);
677
678 qdf_dp_trace_set_track(nbuf, QDF_TX);
679
680 DPTRACE(qdf_dp_trace(nbuf, QDF_DP_TRACE_TX_PACKET_PTR_RECORD,
681 QDF_TRACE_DEFAULT_PDEV_ID,
682 qdf_nbuf_data_addr(nbuf),
683 sizeof(qdf_nbuf_data(nbuf)),
684 QDF_TX));
685
686 if (!dp_intf_is_tx_allowed(nbuf, dp_link->link_id, soc,
687 mac_addr_tx_allowed.bytes)) {
688 dp_info("Tx not allowed for sta:" QDF_MAC_ADDR_FMT,
689 QDF_MAC_ADDR_REF(mac_addr_tx_allowed.bytes));
690 goto drop_pkt_and_release_nbuf;
691 }
692
693 /* check whether need to linearize nbuf, like non-linear udp data */
694 if (dp_nbuf_nontso_linearize(nbuf) != QDF_STATUS_SUCCESS) {
695 dp_err_rl(" nbuf %pK linearize failed. drop the pkt", nbuf);
696 goto drop_pkt_and_release_nbuf;
697 }
698
699 /*
700 * If a transmit function is not registered, drop packet
701 */
702 if (!dp_intf->txrx_ops.tx.tx) {
703 dp_err_rl("TX function not registered by the data path");
704 goto drop_pkt_and_release_nbuf;
705 }
706
707 dp_fix_broadcast_eapol(dp_link, nbuf);
708
709 if (dp_intf->txrx_ops.tx.tx(soc, dp_link->link_id, nbuf)) {
710 dp_debug_rl("Failed to send packet from adapter %u",
711 dp_link->link_id);
712 goto drop_pkt_and_release_nbuf;
713 }
714
715 return QDF_STATUS_SUCCESS;
716
717 drop_pkt_and_release_nbuf:
718 qdf_net_buf_debug_release_skb(nbuf);
719 drop_pkt:
720
721 /* track connectivity stats */
722 if (dp_intf->pkt_type_bitmap)
723 dp_tx_rx_collect_connectivity_stats_info(nbuf, dp_link,
724 PKT_TYPE_TX_DROPPED,
725 &pkt_type);
726 qdf_dp_trace_data_pkt(nbuf, QDF_TRACE_DEFAULT_PDEV_ID,
727 QDF_DP_TRACE_DROP_PACKET_RECORD, 0,
728 QDF_TX);
729 qdf_nbuf_kfree(nbuf);
730
731 drop_pkt_accounting:
732
733 qdf_net_stats_inc_tx_dropped(&dp_intf->stats);
734 ++stats->per_cpu[cpu].tx_dropped;
735 if (is_arp) {
736 ++dp_intf->dp_stats.arp_stats.tx_dropped;
737 dp_info_rl("ARP packet dropped");
738 } else if (is_eapol) {
739 ++dp_intf->dp_stats.eapol_stats.
740 tx_dropped[subtype - QDF_PROTO_EAPOL_M1];
741 } else if (is_dhcp) {
742 ++dp_intf->dp_stats.dhcp_stats.
743 tx_dropped[subtype - QDF_PROTO_DHCP_DISCOVER];
744 }
745
746 return QDF_STATUS_E_FAILURE;
747 }
748
dp_tx_timeout(struct wlan_dp_intf * dp_intf)749 void dp_tx_timeout(struct wlan_dp_intf *dp_intf)
750 {
751 void *soc = cds_get_context(QDF_MODULE_ID_SOC);
752 u64 diff_time;
753
754 cdp_dump_flow_pool_info(soc);
755
756 ++dp_intf->dp_stats.tx_rx_stats.tx_timeout_cnt;
757 ++dp_intf->dp_stats.tx_rx_stats.cont_txtimeout_cnt;
758
759 diff_time = qdf_system_ticks() -
760 dp_intf->dp_stats.tx_rx_stats.last_txtimeout;
761
762 if ((dp_intf->dp_stats.tx_rx_stats.cont_txtimeout_cnt > 1) &&
763 (diff_time > (DP_TX_TIMEOUT * 2))) {
764 /*
765 * In case when there is no traffic is running, it may
766 * possible tx time-out may once happen and later system
767 * recovered then continuous tx timeout count has to be
768 * reset as it is gets modified only when traffic is running.
769 * If over a period of time if this count reaches to threshold
770 * then host triggers a false subsystem restart. In genuine
771 * time out case OS will call the tx time-out back to back
772 * at interval of DP_TX_TIMEOUT. Here now check if previous
773 * TX TIME out has occurred more than twice of DP_TX_TIMEOUT
774 * back then host may recovered here from data stall.
775 */
776 dp_intf->dp_stats.tx_rx_stats.cont_txtimeout_cnt = 0;
777 dp_info("Reset continuous tx timeout stat");
778 }
779
780 dp_intf->dp_stats.tx_rx_stats.last_txtimeout = qdf_system_ticks();
781
782 if (dp_intf->dp_stats.tx_rx_stats.cont_txtimeout_cnt >
783 DP_TX_STALL_THRESHOLD) {
784 dp_err("Data stall due to continuous TX timeouts");
785 dp_intf->dp_stats.tx_rx_stats.cont_txtimeout_cnt = 0;
786
787 if (dp_is_data_stall_event_enabled(DP_HOST_STA_TX_TIMEOUT))
788 cdp_post_data_stall_event(soc,
789 DATA_STALL_LOG_INDICATOR_HOST_DRIVER,
790 DATA_STALL_LOG_HOST_STA_TX_TIMEOUT,
791 OL_TXRX_PDEV_ID, 0xFF,
792 DATA_STALL_LOG_RECOVERY_TRIGGER_PDR);
793 }
794 }
795
dp_sta_notify_tx_comp_cb(qdf_nbuf_t nbuf,void * ctx,uint16_t flag)796 void dp_sta_notify_tx_comp_cb(qdf_nbuf_t nbuf, void *ctx, uint16_t flag)
797 {
798 struct wlan_dp_link *dp_link = ctx;
799 struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
800 enum qdf_proto_subtype subtype;
801 struct qdf_mac_addr *dest_mac_addr;
802 QDF_STATUS status;
803
804 if (is_dp_intf_valid(dp_intf))
805 return;
806
807 dest_mac_addr = (struct qdf_mac_addr *)qdf_nbuf_data(nbuf);
808
809 switch (QDF_NBUF_CB_GET_PACKET_TYPE(nbuf)) {
810 case QDF_NBUF_CB_PACKET_TYPE_ARP:
811 if (flag & BIT(QDF_TX_RX_STATUS_DOWNLOAD_SUCC))
812 ++dp_intf->dp_stats.arp_stats.
813 tx_host_fw_sent;
814 if (flag & BIT(QDF_TX_RX_STATUS_OK))
815 ++dp_intf->dp_stats.arp_stats.tx_ack_cnt;
816 break;
817 case QDF_NBUF_CB_PACKET_TYPE_EAPOL:
818 subtype = qdf_nbuf_get_eapol_subtype(nbuf);
819 if (!(flag & BIT(QDF_TX_RX_STATUS_OK)) &&
820 subtype != QDF_PROTO_INVALID &&
821 subtype <= QDF_PROTO_EAPOL_M4)
822 ++dp_intf->dp_stats.eapol_stats.
823 tx_noack_cnt[subtype - QDF_PROTO_EAPOL_M1];
824 break;
825 case QDF_NBUF_CB_PACKET_TYPE_DHCP:
826 subtype = qdf_nbuf_get_dhcp_subtype(nbuf);
827 if (!(flag & BIT(QDF_TX_RX_STATUS_OK)) &&
828 subtype != QDF_PROTO_INVALID &&
829 subtype <= QDF_PROTO_DHCP_ACK)
830 ++dp_intf->dp_stats.dhcp_stats.
831 tx_noack_cnt[subtype - QDF_PROTO_DHCP_DISCOVER];
832 break;
833 default:
834 break;
835 }
836
837 /* Since it is TDLS call took TDLS vdev ref*/
838 status = wlan_objmgr_vdev_try_get_ref(dp_link->vdev, WLAN_TDLS_SB_ID);
839 if (QDF_IS_STATUS_SUCCESS(status)) {
840 wlan_tdls_update_tx_pkt_cnt(dp_link->vdev, dest_mac_addr);
841 wlan_objmgr_vdev_release_ref(dp_link->vdev, WLAN_TDLS_SB_ID);
842 }
843 }
844
845 #ifdef FEATURE_MONITOR_MODE_SUPPORT
dp_mon_rx_packet_cbk(void * context,qdf_nbuf_t rxbuf)846 QDF_STATUS dp_mon_rx_packet_cbk(void *context, qdf_nbuf_t rxbuf)
847 {
848 struct wlan_dp_intf *dp_intf;
849 struct wlan_dp_link *dp_link;
850 QDF_STATUS status;
851 qdf_nbuf_t nbuf;
852 qdf_nbuf_t nbuf_next;
853 unsigned int cpu_index;
854 struct dp_tx_rx_stats *stats;
855 enum dp_nbuf_push_type type;
856
857 /* Sanity check on inputs */
858 if ((!context) || (!rxbuf)) {
859 dp_err_rl("Null params being passed");
860 return QDF_STATUS_E_FAILURE;
861 }
862
863 dp_link = (struct wlan_dp_link *)context;
864 dp_intf = dp_link->dp_intf;
865 if (!dp_intf) {
866 dp_err_rl("dp_intf is NULL for dp_link %pK", dp_link);
867 return QDF_STATUS_E_FAILURE;
868 }
869
870 cpu_index = qdf_get_cpu();
871 stats = &dp_intf->dp_stats.tx_rx_stats;
872
873 /* walk the chain until all are processed */
874 nbuf = rxbuf;
875 while (nbuf) {
876 nbuf_next = qdf_nbuf_next(nbuf);
877 qdf_nbuf_set_dev(nbuf, dp_intf->dev);
878
879 ++stats->per_cpu[cpu_index].rx_packets;
880 qdf_net_stats_add_rx_pkts(&dp_intf->stats, 1);
881 qdf_net_stats_add_rx_bytes(&dp_intf->stats,
882 qdf_nbuf_len(nbuf));
883
884 /* Remove SKB from internal tracking table before submitting
885 * it to stack
886 */
887 qdf_net_buf_debug_release_skb(nbuf);
888
889 /*
890 * If this is not a last packet on the chain
891 * Just put packet into backlog queue, not scheduling RX sirq
892 */
893 if (qdf_nbuf_next(nbuf)) {
894 status = dp_intf->dp_ctx->dp_ops.dp_nbuf_push_pkt(nbuf,
895 DP_NBUF_PUSH_SIMPLE);
896 } else {
897 /*
898 * This is the last packet on the chain
899 * Scheduling rx sirq
900 */
901 type = qdf_in_atomic() ? DP_NBUF_PUSH_NAPI :
902 DP_NBUF_PUSH_BH_DISABLE;
903 status = dp_intf->dp_ctx->dp_ops.dp_nbuf_push_pkt(nbuf,
904 type);
905 }
906
907 if (QDF_IS_STATUS_SUCCESS(status))
908 ++stats->per_cpu[cpu_index].rx_delivered;
909 else
910 ++stats->per_cpu[cpu_index].rx_refused;
911
912 nbuf = nbuf_next;
913 }
914
915 return QDF_STATUS_SUCCESS;
916 }
917
dp_monitor_set_rx_monitor_cb(struct ol_txrx_ops * txrx,ol_txrx_rx_mon_fp rx_monitor_cb)918 void dp_monitor_set_rx_monitor_cb(struct ol_txrx_ops *txrx,
919 ol_txrx_rx_mon_fp rx_monitor_cb)
920 {
921 txrx->rx.mon = rx_monitor_cb;
922 }
923
dp_rx_monitor_callback(ol_osif_vdev_handle context,qdf_nbuf_t rxbuf,void * rx_status)924 void dp_rx_monitor_callback(ol_osif_vdev_handle context,
925 qdf_nbuf_t rxbuf,
926 void *rx_status)
927 {
928 dp_mon_rx_packet_cbk(context, rxbuf);
929 }
930 #endif
931
932 /**
933 * dp_is_rx_wake_lock_needed() - check if wake lock is needed
934 * @nbuf: pointer to sk_buff
935 *
936 * RX wake lock is needed for:
937 * 1) Unicast data packet OR
938 * 2) Local ARP data packet
939 *
940 * Return: true if wake lock is needed or false otherwise.
941 */
dp_is_rx_wake_lock_needed(qdf_nbuf_t nbuf)942 static bool dp_is_rx_wake_lock_needed(qdf_nbuf_t nbuf)
943 {
944 if ((!qdf_nbuf_pkt_type_is_mcast(nbuf) &&
945 !qdf_nbuf_pkt_type_is_bcast(nbuf)) ||
946 qdf_nbuf_is_arp_local(nbuf))
947 return true;
948
949 return false;
950 }
951
952 #ifdef RECEIVE_OFFLOAD
953 /**
954 * dp_resolve_rx_ol_mode() - Resolve Rx offload method, LRO or GRO
955 * @dp_ctx: pointer to DP psoc Context
956 *
957 * Return: None
958 */
dp_resolve_rx_ol_mode(struct wlan_dp_psoc_context * dp_ctx)959 static void dp_resolve_rx_ol_mode(struct wlan_dp_psoc_context *dp_ctx)
960 {
961 void *soc;
962
963 soc = cds_get_context(QDF_MODULE_ID_SOC);
964
965 if (!(cdp_cfg_get(soc, cfg_dp_lro_enable) ^
966 cdp_cfg_get(soc, cfg_dp_gro_enable))) {
967 cdp_cfg_get(soc, cfg_dp_lro_enable) &&
968 cdp_cfg_get(soc, cfg_dp_gro_enable) ?
969 dp_info("Can't enable both LRO and GRO, disabling Rx offload"):
970 dp_info("LRO and GRO both are disabled");
971 dp_ctx->ol_enable = 0;
972 } else if (cdp_cfg_get(soc, cfg_dp_lro_enable)) {
973 dp_info("Rx offload LRO is enabled");
974 dp_ctx->ol_enable = CFG_LRO_ENABLED;
975 } else {
976 dp_info("Rx offload: GRO is enabled");
977 dp_ctx->ol_enable = CFG_GRO_ENABLED;
978 }
979 }
980
981 #ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION
982 /**
983 * dp_gro_rx_bh_disable() - GRO RX/flush function.
984 * @dp_intf: DP interface pointer
985 * @napi_to_use: napi to be used to give packets to the stack, gro flush
986 * @nbuf: pointer to n/w buff
987 *
988 * Function calls napi_gro_receive for the skb. If the skb indicates that a
989 * flush needs to be done (set by the lower DP layer), the function also calls
990 * napi_gro_flush. Local softirqs are disabled (and later enabled) while making
991 * napi_gro__ calls.
992 *
993 * Return: QDF_STATUS_SUCCESS if not dropped by napi_gro_receive or
994 * QDF error code.
995 */
dp_gro_rx_bh_disable(struct wlan_dp_intf * dp_intf,qdf_napi_struct * napi_to_use,qdf_nbuf_t nbuf)996 static QDF_STATUS dp_gro_rx_bh_disable(struct wlan_dp_intf *dp_intf,
997 qdf_napi_struct *napi_to_use,
998 qdf_nbuf_t nbuf)
999 {
1000 QDF_STATUS status = QDF_STATUS_SUCCESS;
1001 struct wlan_dp_psoc_context *dp_ctx = dp_intf->dp_ctx;
1002 uint32_t rx_aggregation;
1003 uint8_t rx_ctx_id = QDF_NBUF_CB_RX_CTX_ID(nbuf);
1004 uint8_t low_tput_force_flush = 0;
1005 int32_t gro_disallowed;
1006
1007 rx_aggregation = qdf_atomic_read(&dp_ctx->dp_agg_param.rx_aggregation);
1008 gro_disallowed = qdf_atomic_read(&dp_intf->gro_disallowed);
1009
1010 if (dp_get_current_throughput_level(dp_ctx) == PLD_BUS_WIDTH_IDLE ||
1011 !rx_aggregation || gro_disallowed) {
1012 status = dp_ctx->dp_ops.dp_rx_napi_gro_flush(napi_to_use, nbuf,
1013 &low_tput_force_flush);
1014 if (!low_tput_force_flush)
1015 dp_intf->dp_stats.tx_rx_stats.
1016 rx_gro_low_tput_flush++;
1017 if (!rx_aggregation)
1018 dp_ctx->dp_agg_param.gro_force_flush[rx_ctx_id] = 1;
1019 if (gro_disallowed)
1020 dp_intf->gro_flushed[rx_ctx_id] = 1;
1021 } else {
1022 status = dp_ctx->dp_ops.dp_rx_napi_gro_receive(napi_to_use,
1023 nbuf);
1024 }
1025
1026 return status;
1027 }
1028
1029 #else /* WLAN_FEATURE_DYNAMIC_RX_AGGREGATION */
1030
1031 /**
1032 * dp_gro_rx_bh_disable() - GRO RX/flush function.
1033 * @dp_intf: DP interface pointer
1034 * @napi_to_use: napi to be used to give packets to the stack, gro flush
1035 * @nbuf: pointer to nbuff
1036 *
1037 * Function calls napi_gro_receive for the skb. If the skb indicates that a
1038 * flush needs to be done (set by the lower DP layer), the function also calls
1039 * napi_gro_flush. Local softirqs are disabled (and later enabled) while making
1040 * napi_gro__ calls.
1041 *
1042 * Return: QDF_STATUS_SUCCESS if not dropped by napi_gro_receive or
1043 * QDF error code.
1044 */
1045
dp_gro_rx_bh_disable(struct wlan_dp_intf * dp_intf,qdf_napi_struct * napi_to_use,qdf_nbuf_t nbuf)1046 static QDF_STATUS dp_gro_rx_bh_disable(struct wlan_dp_intf *dp_intf,
1047 qdf_napi_struct *napi_to_use,
1048 qdf_nbuf_t nbuf)
1049 {
1050 QDF_STATUS status = QDF_STATUS_SUCCESS;
1051 struct wlan_dp_psoc_context *dp_ctx = dp_intf->dp_ctx;
1052 uint8_t low_tput_force_flush = 0;
1053
1054 if (dp_get_current_throughput_level(dp_ctx) == PLD_BUS_WIDTH_IDLE) {
1055 status = dp_ctx->dp_ops.dp_rx_napi_gro_flush(napi_to_use, nbuf,
1056 &low_tput_force_flush);
1057 if (!low_tput_force_flush)
1058 dp_intf->dp_stats.tx_rx_stats.
1059 rx_gro_low_tput_flush++;
1060 } else {
1061 status = dp_ctx->dp_ops.dp_rx_napi_gro_receive(napi_to_use,
1062 nbuf);
1063 }
1064
1065 return status;
1066 }
1067 #endif /* WLAN_FEATURE_DYNAMIC_RX_AGGREGATION */
1068
1069 #if defined(FEATURE_LRO)
1070 /**
1071 * dp_lro_rx() - Handle Rx processing via LRO
1072 * @dp_intf: pointer to DP interface
1073 * @nbuf: pointer to n/w buff
1074 *
1075 * Return: QDF_STATUS_SUCCESS if processed via LRO or non zero return code
1076 */
1077 static inline QDF_STATUS
dp_lro_rx(struct wlan_dp_intf * dp_intf,qdf_nbuf_t nbuf)1078 dp_lro_rx(struct wlan_dp_intf *dp_intf, qdf_nbuf_t nbuf)
1079 {
1080 struct wlan_dp_psoc_context *dp_ctx = dp_intf->dp_ctx;
1081
1082 return dp_ctx->dp_ops.dp_lro_rx_cb(dp_intf->dev, nbuf);
1083 }
1084
1085 /**
1086 * dp_is_lro_enabled() - Is LRO enabled
1087 * @dp_ctx: DP interface
1088 *
1089 * This function checks if LRO is enabled in DP context.
1090 *
1091 * Return: 0 - success, < 0 - failure
1092 */
1093 static inline QDF_STATUS
dp_is_lro_enabled(struct wlan_dp_psoc_context * dp_ctx)1094 dp_is_lro_enabled(struct wlan_dp_psoc_context *dp_ctx)
1095 {
1096 if (dp_ctx->ol_enable != CFG_LRO_ENABLED)
1097 return QDF_STATUS_E_NOSUPPORT;
1098 }
1099
dp_lro_set_reset(struct wlan_dp_intf * dp_intf,uint8_t enable_flag)1100 QDF_STATUS dp_lro_set_reset(struct wlan_dp_intf *dp_intf, uint8_t enable_flag)
1101 {
1102 struct wlan_dp_psoc_context *dp_ctx = dp_intf->dp_ctx;
1103
1104 if ((dp_ctx->ol_enable != CFG_LRO_ENABLED) ||
1105 (dp_intf->device_mode != QDF_STA_MODE)) {
1106 dp_info("LRO is already Disabled");
1107 return QDF_STATUS_E_INVAL;
1108 }
1109
1110 if (enable_flag) {
1111 qdf_atomic_set(&dp_ctx->vendor_disable_lro_flag, 0);
1112 } else {
1113 /* Disable LRO, Enable tcpdelack*/
1114 qdf_atomic_set(&dp_ctx->vendor_disable_lro_flag, 1);
1115 dp_info("LRO Disabled");
1116
1117 if (dp_ctx->dp_cfg.enable_tcp_delack) {
1118 struct wlan_rx_tp_data rx_tp_data;
1119
1120 dp_info("Enable TCP delack as LRO is disabled");
1121 rx_tp_data.rx_tp_flags = TCP_DEL_ACK_IND;
1122 rx_tp_data.level =
1123 DP_BUS_BW_CFG(dp_ctx->dp_cfg.cur_rx_level);
1124 wlan_dp_update_tcp_rx_param(dp_ctx, &rx_tp_data);
1125 dp_ctx->en_tcp_delack_no_lro = 1;
1126 }
1127 }
1128
1129 return QDF_STATUS_SUCCESS;
1130 }
1131 #else
1132 static inline
dp_lro_rx(struct wlan_dp_intf * dp_intf,qdf_nbuf_t nbuf)1133 QDF_STATUS dp_lro_rx(struct wlan_dp_intf *dp_intf,
1134 qdf_nbuf_t nbuf)
1135 {
1136 return QDF_STATUS_E_NOSUPPORT;
1137 }
1138
1139 static inline
dp_is_lro_enabled(struct wlan_dp_psoc_context * dp_ctx)1140 int dp_is_lro_enabled(struct wlan_dp_psoc_context *dp_ctx)
1141 {
1142 return QDF_STATUS_E_NOSUPPORT;
1143 }
1144 #endif /* FEATURE_LRO */
1145
1146 /**
1147 * dp_gro_rx_thread() - Handle Rx processing via GRO for DP thread
1148 * @dp_intf: pointer to DP interface
1149 * @nbuf: pointer to n/w buff
1150 *
1151 * Return: QDF_STATUS_SUCCESS if processed via GRO or non zero return code
1152 */
1153 static
dp_gro_rx_thread(struct wlan_dp_intf * dp_intf,qdf_nbuf_t nbuf)1154 QDF_STATUS dp_gro_rx_thread(struct wlan_dp_intf *dp_intf,
1155 qdf_nbuf_t nbuf)
1156 {
1157 qdf_napi_struct *napi_to_use = NULL;
1158 QDF_STATUS status = QDF_STATUS_E_FAILURE;
1159
1160 if (!dp_intf->dp_ctx->enable_dp_rx_threads) {
1161 dp_err_rl("gro not supported without DP RX thread!");
1162 return status;
1163 }
1164
1165 napi_to_use =
1166 (qdf_napi_struct *)dp_rx_get_napi_context(cds_get_context(QDF_MODULE_ID_SOC),
1167 QDF_NBUF_CB_RX_CTX_ID(nbuf));
1168
1169 if (!napi_to_use) {
1170 dp_err_rl("no napi to use for GRO!");
1171 return status;
1172 }
1173
1174 return dp_gro_rx_bh_disable(dp_intf, napi_to_use, nbuf);
1175 }
1176
1177 /**
1178 * dp_gro_rx_legacy() - Handle Rx processing via GRO for ihelium based targets
1179 * @dp_intf: pointer to DP interface
1180 * @nbuf: pointer to n/w buf
1181 *
1182 * Supports GRO for only station mode
1183 *
1184 * Return: QDF_STATUS_SUCCESS if processed via GRO or non zero return code
1185 */
1186 static
dp_gro_rx_legacy(struct wlan_dp_intf * dp_intf,qdf_nbuf_t nbuf)1187 QDF_STATUS dp_gro_rx_legacy(struct wlan_dp_intf *dp_intf, qdf_nbuf_t nbuf)
1188 {
1189 qdf_napi_struct *napi_to_use;
1190 QDF_STATUS status = QDF_STATUS_E_FAILURE;
1191 struct wlan_dp_psoc_context *dp_ctx = dp_intf->dp_ctx;
1192
1193 /* Only enabling it for STA mode like LRO today */
1194 if (QDF_STA_MODE != dp_intf->device_mode)
1195 return QDF_STATUS_E_NOSUPPORT;
1196
1197 if (qdf_atomic_read(&dp_ctx->disable_rx_ol_in_low_tput) ||
1198 qdf_atomic_read(&dp_ctx->disable_rx_ol_in_concurrency))
1199 return QDF_STATUS_E_NOSUPPORT;
1200
1201 napi_to_use = dp_ctx->dp_ops.dp_gro_rx_legacy_get_napi(nbuf,
1202 dp_ctx->enable_rxthread);
1203 if (!napi_to_use)
1204 goto out;
1205
1206 status = dp_gro_rx_bh_disable(dp_intf, napi_to_use, nbuf);
1207 out:
1208
1209 return status;
1210 }
1211
1212 /**
1213 * dp_register_rx_ol_cb() - Register LRO/GRO rx processing callbacks
1214 * @dp_ctx: pointer to dp_ctx
1215 * @wifi3_0_target: whether its a lithium/beryllium arch based target or not
1216 *
1217 * Return: none
1218 */
dp_register_rx_ol_cb(struct wlan_dp_psoc_context * dp_ctx,bool wifi3_0_target)1219 static void dp_register_rx_ol_cb(struct wlan_dp_psoc_context *dp_ctx,
1220 bool wifi3_0_target)
1221 {
1222 if (!dp_ctx) {
1223 dp_err("DP context is NULL");
1224 return;
1225 }
1226
1227 dp_ctx->en_tcp_delack_no_lro = 0;
1228
1229 if (!dp_is_lro_enabled(dp_ctx)) {
1230 dp_ctx->dp_ops.dp_register_rx_offld_flush_cb(DP_RX_FLUSH_LRO);
1231 dp_ctx->receive_offload_cb = dp_lro_rx;
1232 dp_info("LRO is enabled");
1233 } else if (dp_ctx->ol_enable == CFG_GRO_ENABLED) {
1234 qdf_atomic_set(&dp_ctx->dp_agg_param.rx_aggregation, 1);
1235 if (wifi3_0_target) {
1236 /* no flush registration needed, it happens in DP thread */
1237 dp_ctx->receive_offload_cb = dp_gro_rx_thread;
1238 } else {
1239 /*ihelium based targets */
1240 if (dp_ctx->enable_rxthread)
1241 dp_ctx->dp_ops.dp_register_rx_offld_flush_cb(
1242 DP_RX_FLUSH_THREAD);
1243 else
1244 dp_ctx->dp_ops.dp_register_rx_offld_flush_cb(
1245 DP_RX_FLUSH_NAPI);
1246 dp_ctx->receive_offload_cb = dp_gro_rx_legacy;
1247 }
1248 dp_info("GRO is enabled");
1249 } else if (DP_BUS_BW_CFG(dp_ctx->dp_cfg.enable_tcp_delack)) {
1250 dp_ctx->en_tcp_delack_no_lro = 1;
1251 dp_info("TCP Del ACK is enabled");
1252 }
1253 }
1254
1255 /**
1256 * dp_rx_ol_send_config() - Send RX offload configuration to FW
1257 * @dp_ctx: pointer to DP_ctx
1258 *
1259 * This function is only used for non lithium targets. Lithium based targets are
1260 * sending LRO config to FW in vdev attach implemented in cmn DP layer.
1261 *
1262 * Return: 0 on success, non zero on failure
1263 */
dp_rx_ol_send_config(struct wlan_dp_psoc_context * dp_ctx)1264 static QDF_STATUS dp_rx_ol_send_config(struct wlan_dp_psoc_context *dp_ctx)
1265 {
1266 struct cdp_lro_hash_config lro_config = {0};
1267 QDF_STATUS status = QDF_STATUS_SUCCESS;
1268
1269 /*
1270 * This will enable flow steering and Toeplitz hash
1271 * So enable it for LRO or GRO processing.
1272 */
1273 if (dp_ctx->dp_cfg.gro_enable ||
1274 dp_ctx->dp_cfg.lro_enable) {
1275 lro_config.lro_enable = 1;
1276 lro_config.tcp_flag = QDF_TCPHDR_ACK;
1277 lro_config.tcp_flag_mask = QDF_TCPHDR_FIN | QDF_TCPHDR_SYN |
1278 QDF_TCPHDR_RST | QDF_TCPHDR_ACK |
1279 QDF_TCPHDR_URG | QDF_TCPHDR_ECE |
1280 QDF_TCPHDR_CWR;
1281 }
1282
1283 qdf_get_random_bytes(lro_config.toeplitz_hash_ipv4,
1284 (sizeof(lro_config.toeplitz_hash_ipv4[0]) *
1285 LRO_IPV4_SEED_ARR_SZ));
1286
1287 qdf_get_random_bytes(lro_config.toeplitz_hash_ipv6,
1288 (sizeof(lro_config.toeplitz_hash_ipv6[0]) *
1289 LRO_IPV6_SEED_ARR_SZ));
1290
1291 status = dp_ctx->sb_ops.dp_lro_config_cmd(dp_ctx->psoc, &lro_config);
1292 dp_info("LRO Config: lro_enable: 0x%x tcp_flag 0x%x tcp_flag_mask 0x%x",
1293 lro_config.lro_enable, lro_config.tcp_flag,
1294 lro_config.tcp_flag_mask);
1295
1296 return status;
1297 }
1298
dp_rx_ol_init(struct wlan_dp_psoc_context * dp_ctx,bool is_wifi3_0_target)1299 QDF_STATUS dp_rx_ol_init(struct wlan_dp_psoc_context *dp_ctx,
1300 bool is_wifi3_0_target)
1301 {
1302 QDF_STATUS status = QDF_STATUS_SUCCESS;
1303
1304 dp_resolve_rx_ol_mode(dp_ctx);
1305 dp_register_rx_ol_cb(dp_ctx, is_wifi3_0_target);
1306
1307 dp_info("ol init");
1308 if (!is_wifi3_0_target) {
1309 status = dp_rx_ol_send_config(dp_ctx);
1310 if (status) {
1311 dp_ctx->ol_enable = 0;
1312 dp_err("Failed to send LRO/GRO configuration! %u", status);
1313 return status;
1314 }
1315 }
1316
1317 return 0;
1318 }
1319
dp_disable_rx_ol_for_low_tput(struct wlan_dp_psoc_context * dp_ctx,bool disable)1320 void dp_disable_rx_ol_for_low_tput(struct wlan_dp_psoc_context *dp_ctx,
1321 bool disable)
1322 {
1323 if (disable)
1324 qdf_atomic_set(&dp_ctx->disable_rx_ol_in_low_tput, 1);
1325 else
1326 qdf_atomic_set(&dp_ctx->disable_rx_ol_in_low_tput, 0);
1327 }
1328
1329 #else /* RECEIVE_OFFLOAD */
dp_disable_rx_ol_for_low_tput(struct wlan_dp_psoc_context * dp_ctx,bool disable)1330 void dp_disable_rx_ol_for_low_tput(struct wlan_dp_psoc_context *dp_ctx,
1331 bool disable)
1332 {
1333 }
1334 #endif /* RECEIVE_OFFLOAD */
1335
1336 #ifdef WLAN_FEATURE_TSF_PLUS_SOCK_TS
dp_tsf_timestamp_rx(struct wlan_dp_psoc_context * dp_ctx,qdf_nbuf_t netbuf)1337 static inline void dp_tsf_timestamp_rx(struct wlan_dp_psoc_context *dp_ctx,
1338 qdf_nbuf_t netbuf)
1339 {
1340 dp_ctx->dp_ops.dp_tsf_timestamp_rx(dp_ctx->dp_ops.callback_ctx,
1341 netbuf);
1342 }
1343 #else
dp_tsf_timestamp_rx(struct wlan_dp_psoc_context * dp_ctx,qdf_nbuf_t netbuf)1344 static inline void dp_tsf_timestamp_rx(struct wlan_dp_psoc_context *dp_ctx,
1345 qdf_nbuf_t netbuf)
1346 {
1347 }
1348 #endif
1349
1350 QDF_STATUS
dp_rx_thread_gro_flush_ind_cbk(void * link_ctx,int rx_ctx_id)1351 dp_rx_thread_gro_flush_ind_cbk(void *link_ctx, int rx_ctx_id)
1352 {
1353 struct wlan_dp_link *dp_link = link_ctx;
1354 struct wlan_dp_intf *dp_intf;
1355 enum dp_rx_gro_flush_code gro_flush_code = DP_RX_GRO_NORMAL_FLUSH;
1356
1357 if (qdf_unlikely((!dp_link) || (!dp_link->dp_intf) ||
1358 (!dp_link->dp_intf->dp_ctx))) {
1359 dp_err("Null params being passed");
1360 return QDF_STATUS_E_FAILURE;
1361 }
1362
1363 dp_intf = dp_link->dp_intf;
1364 if (dp_intf->runtime_disable_rx_thread)
1365 return QDF_STATUS_SUCCESS;
1366
1367 if (dp_is_low_tput_gro_enable(dp_intf->dp_ctx)) {
1368 dp_intf->dp_stats.tx_rx_stats.rx_gro_flush_skip++;
1369 gro_flush_code = DP_RX_GRO_LOW_TPUT_FLUSH;
1370 }
1371
1372 return dp_rx_gro_flush_ind(cds_get_context(QDF_MODULE_ID_SOC),
1373 rx_ctx_id, gro_flush_code);
1374 }
1375
dp_rx_pkt_thread_enqueue_cbk(void * link_ctx,qdf_nbuf_t nbuf_list)1376 QDF_STATUS dp_rx_pkt_thread_enqueue_cbk(void *link_ctx,
1377 qdf_nbuf_t nbuf_list)
1378 {
1379 struct wlan_dp_intf *dp_intf;
1380 struct wlan_dp_link *dp_link;
1381 uint8_t link_id;
1382 qdf_nbuf_t head_ptr;
1383
1384 if (qdf_unlikely(!link_ctx || !nbuf_list)) {
1385 dp_err_rl("Null params being passed");
1386 return QDF_STATUS_E_FAILURE;
1387 }
1388
1389 dp_link = (struct wlan_dp_link *)link_ctx;
1390 if (!is_dp_link_valid(dp_link))
1391 return QDF_STATUS_E_FAILURE;
1392
1393 dp_intf = dp_link->dp_intf;
1394 if (dp_intf->runtime_disable_rx_thread &&
1395 dp_intf->txrx_ops.rx.rx_stack)
1396 return dp_intf->txrx_ops.rx.rx_stack(dp_link, nbuf_list);
1397
1398 link_id = dp_link->link_id;
1399
1400 head_ptr = nbuf_list;
1401 while (head_ptr) {
1402 qdf_nbuf_cb_update_vdev_id(head_ptr,
1403 link_id);
1404 head_ptr = qdf_nbuf_next(head_ptr);
1405 }
1406
1407 return dp_rx_enqueue_pkt(cds_get_context(QDF_MODULE_ID_SOC), nbuf_list);
1408 }
1409
1410 #ifdef CONFIG_HL_SUPPORT
wlan_dp_rx_deliver_to_stack(struct wlan_dp_intf * dp_intf,qdf_nbuf_t nbuf)1411 QDF_STATUS wlan_dp_rx_deliver_to_stack(struct wlan_dp_intf *dp_intf,
1412 qdf_nbuf_t nbuf)
1413 {
1414 struct wlan_dp_psoc_context *dp_ctx = dp_intf->dp_ctx;
1415
1416 dp_intf->dp_stats.tx_rx_stats.rx_non_aggregated++;
1417 dp_ctx->no_rx_offload_pkt_cnt++;
1418
1419 return dp_ctx->dp_ops.dp_nbuf_push_pkt(nbuf, DP_NBUF_PUSH_NI);
1420 }
1421 #else
1422
1423 #if defined(WLAN_SUPPORT_RX_FISA)
1424 /**
1425 * wlan_dp_set_fisa_disallowed_for_intf() - Set fisa disallowed bit for an intf
1426 * @soc: DP soc handle
1427 * @dp_intf: DP interface handle
1428 * @rx_ctx_id: rx context id
1429 * @val: Enable or disable
1430 *
1431 * The function sets the fisa disallowed flag for a given vdev
1432 *
1433 * Return: None
1434 */
1435 static inline
wlan_dp_set_fisa_disallowed_for_intf(ol_txrx_soc_handle soc,struct wlan_dp_intf * dp_intf,uint8_t rx_ctx_id,uint8_t val)1436 void wlan_dp_set_fisa_disallowed_for_intf(ol_txrx_soc_handle soc,
1437 struct wlan_dp_intf *dp_intf,
1438 uint8_t rx_ctx_id, uint8_t val)
1439 {
1440 dp_intf->fisa_disallowed[rx_ctx_id] = val;
1441 }
1442 #else
1443 static inline
wlan_dp_set_fisa_disallowed_for_intf(ol_txrx_soc_handle soc,struct wlan_dp_intf * dp_intf,uint8_t rx_ctx_id,uint8_t val)1444 void wlan_dp_set_fisa_disallowed_for_intf(ol_txrx_soc_handle soc,
1445 struct wlan_dp_intf *dp_intf,
1446 uint8_t rx_ctx_id, uint8_t val)
1447 {
1448 }
1449 #endif
1450
1451 #ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION
wlan_dp_rx_deliver_to_stack(struct wlan_dp_intf * dp_intf,qdf_nbuf_t nbuf)1452 QDF_STATUS wlan_dp_rx_deliver_to_stack(struct wlan_dp_intf *dp_intf,
1453 qdf_nbuf_t nbuf)
1454 {
1455 struct wlan_dp_psoc_context *dp_ctx = dp_intf->dp_ctx;
1456 struct wlan_dp_psoc_callbacks *dp_ops = &dp_ctx->dp_ops;
1457 int status = QDF_STATUS_E_FAILURE;
1458 bool nbuf_receive_offload_ok = false;
1459 enum dp_nbuf_push_type push_type;
1460 uint8_t rx_ctx_id = QDF_NBUF_CB_RX_CTX_ID(nbuf);
1461 ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
1462 int32_t gro_disallowed;
1463
1464 if (QDF_NBUF_CB_RX_TCP_PROTO(nbuf) &&
1465 !QDF_NBUF_CB_RX_PEER_CACHED_FRM(nbuf))
1466 nbuf_receive_offload_ok = true;
1467
1468 gro_disallowed = qdf_atomic_read(&dp_intf->gro_disallowed);
1469 if (gro_disallowed == 0 &&
1470 dp_intf->gro_flushed[rx_ctx_id] != 0) {
1471 if (qdf_likely(soc))
1472 wlan_dp_set_fisa_disallowed_for_intf(soc, dp_intf,
1473 rx_ctx_id, 0);
1474 dp_intf->gro_flushed[rx_ctx_id] = 0;
1475 } else if (gro_disallowed &&
1476 dp_intf->gro_flushed[rx_ctx_id] == 0) {
1477 if (qdf_likely(soc))
1478 wlan_dp_set_fisa_disallowed_for_intf(soc, dp_intf,
1479 rx_ctx_id, 1);
1480 }
1481
1482 if (nbuf_receive_offload_ok && dp_ctx->receive_offload_cb &&
1483 !dp_ctx->dp_agg_param.gro_force_flush[rx_ctx_id] &&
1484 !dp_intf->gro_flushed[rx_ctx_id] &&
1485 !dp_intf->runtime_disable_rx_thread) {
1486 status = dp_ctx->receive_offload_cb(dp_intf, nbuf);
1487
1488 if (QDF_IS_STATUS_SUCCESS(status)) {
1489 dp_intf->dp_stats.tx_rx_stats.rx_aggregated++;
1490 return status;
1491 }
1492
1493 if (status == QDF_STATUS_E_GRO_DROP) {
1494 dp_intf->dp_stats.tx_rx_stats.rx_gro_dropped++;
1495 return status;
1496 }
1497 }
1498
1499 /*
1500 * The below case handles the scenario when rx_aggregation is
1501 * re-enabled dynamically, in which case gro_force_flush needs
1502 * to be reset to 0 to allow GRO.
1503 */
1504 if (qdf_atomic_read(&dp_ctx->dp_agg_param.rx_aggregation) &&
1505 dp_ctx->dp_agg_param.gro_force_flush[rx_ctx_id])
1506 dp_ctx->dp_agg_param.gro_force_flush[rx_ctx_id] = 0;
1507
1508 dp_intf->dp_stats.tx_rx_stats.rx_non_aggregated++;
1509
1510 /* Account for GRO/LRO ineligible packets, mostly UDP */
1511 if (qdf_nbuf_get_gso_segs(nbuf) == 0)
1512 dp_ctx->no_rx_offload_pkt_cnt++;
1513
1514 if (qdf_likely((dp_ctx->enable_dp_rx_threads ||
1515 dp_ctx->enable_rxthread) &&
1516 !dp_intf->runtime_disable_rx_thread)) {
1517 push_type = DP_NBUF_PUSH_BH_DISABLE;
1518 } else if (qdf_unlikely(QDF_NBUF_CB_RX_PEER_CACHED_FRM(nbuf))) {
1519 /*
1520 * Frames before peer is registered to avoid contention with
1521 * NAPI softirq.
1522 * Refer fix:
1523 * qcacld-3.0: Do netif_rx_ni() for frames received before
1524 * peer assoc
1525 */
1526 push_type = DP_NBUF_PUSH_NI;
1527 } else { /* NAPI Context */
1528 push_type = DP_NBUF_PUSH_NAPI;
1529 }
1530
1531 return dp_ops->dp_nbuf_push_pkt(nbuf, push_type);
1532 }
1533
1534 #else /* WLAN_FEATURE_DYNAMIC_RX_AGGREGATION */
1535
wlan_dp_rx_deliver_to_stack(struct wlan_dp_intf * dp_intf,qdf_nbuf_t nbuf)1536 QDF_STATUS wlan_dp_rx_deliver_to_stack(struct wlan_dp_intf *dp_intf,
1537 qdf_nbuf_t nbuf)
1538 {
1539 struct wlan_dp_psoc_context *dp_ctx = dp_intf->dp_ctx;
1540 struct wlan_dp_psoc_callbacks *dp_ops = &dp_ctx->dp_ops;
1541 int status = QDF_STATUS_E_FAILURE;
1542 bool nbuf_receive_offload_ok = false;
1543 enum dp_nbuf_push_type push_type;
1544
1545 if (QDF_NBUF_CB_RX_TCP_PROTO(nbuf) &&
1546 !QDF_NBUF_CB_RX_PEER_CACHED_FRM(nbuf))
1547 nbuf_receive_offload_ok = true;
1548
1549 if (nbuf_receive_offload_ok && dp_ctx->receive_offload_cb) {
1550 status = dp_ctx->receive_offload_cb(dp_intf, nbuf);
1551
1552 if (QDF_IS_STATUS_SUCCESS(status)) {
1553 dp_intf->dp_stats.tx_rx_stats.rx_aggregated++;
1554 return status;
1555 }
1556
1557 if (status == QDF_STATUS_E_GRO_DROP) {
1558 dp_intf->dp_stats.tx_rx_stats.rx_gro_dropped++;
1559 return status;
1560 }
1561 }
1562
1563 dp_intf->dp_stats.tx_rx_stats.rx_non_aggregated++;
1564
1565 /* Account for GRO/LRO ineligible packets, mostly UDP */
1566 if (qdf_nbuf_get_gso_segs(nbuf) == 0)
1567 dp_ctx->no_rx_offload_pkt_cnt++;
1568
1569 if (qdf_likely((dp_ctx->enable_dp_rx_threads ||
1570 dp_ctx->enable_rxthread) &&
1571 !dp_intf->runtime_disable_rx_thread)) {
1572 push_type = DP_NBUF_PUSH_BH_DISABLE;
1573 } else if (qdf_unlikely(QDF_NBUF_CB_RX_PEER_CACHED_FRM(nbuf))) {
1574 /*
1575 * Frames before peer is registered to avoid contention with
1576 * NAPI softirq.
1577 * Refer fix:
1578 * qcacld-3.0: Do netif_rx_ni() for frames received before
1579 * peer assoc
1580 */
1581 push_type = DP_NBUF_PUSH_NI;
1582 } else { /* NAPI Context */
1583 push_type = DP_NBUF_PUSH_NAPI;
1584 }
1585
1586 return dp_ops->dp_nbuf_push_pkt(nbuf, push_type);
1587 }
1588 #endif /* WLAN_FEATURE_DYNAMIC_RX_AGGREGATION */
1589 #endif
1590
1591 static inline bool
dp_is_gratuitous_arp_unsolicited_na(struct wlan_dp_psoc_context * dp_ctx,qdf_nbuf_t nbuf)1592 dp_is_gratuitous_arp_unsolicited_na(struct wlan_dp_psoc_context *dp_ctx,
1593 qdf_nbuf_t nbuf)
1594 {
1595 if (qdf_unlikely(dp_ctx->dp_ops.dp_is_gratuitous_arp_unsolicited_na))
1596 return dp_ctx->dp_ops.dp_is_gratuitous_arp_unsolicited_na(nbuf);
1597
1598 return false;
1599 }
1600
dp_rx_flush_packet_cbk(void * dp_link_context,uint8_t link_id)1601 QDF_STATUS dp_rx_flush_packet_cbk(void *dp_link_context, uint8_t link_id)
1602 {
1603 struct wlan_dp_link *dp_link = (struct wlan_dp_link *)dp_link_context;
1604 struct wlan_dp_intf *dp_intf = dp_link->dp_intf;
1605 struct wlan_dp_psoc_context *dp_ctx;
1606 ol_txrx_soc_handle soc = cds_get_context(QDF_MODULE_ID_SOC);
1607
1608 if (qdf_unlikely(!soc))
1609 return QDF_STATUS_E_FAILURE;
1610
1611 dp_ctx = dp_intf->dp_ctx;
1612 if (qdf_unlikely(!dp_ctx))
1613 return QDF_STATUS_E_FAILURE;
1614
1615 qdf_atomic_inc(&dp_intf->num_active_task);
1616
1617 /* do fisa flush for this vdev */
1618 if (wlan_dp_cfg_is_rx_fisa_enabled(&dp_ctx->dp_cfg))
1619 wlan_dp_rx_fisa_flush_by_vdev_id((struct dp_soc *)soc, link_id);
1620
1621 if (dp_ctx->enable_dp_rx_threads)
1622 dp_txrx_flush_pkts_by_vdev_id(soc, link_id);
1623
1624 qdf_atomic_dec(&dp_intf->num_active_task);
1625
1626 return QDF_STATUS_SUCCESS;
1627 }
1628
1629 #if defined(WLAN_SUPPORT_RX_FISA)
wlan_dp_rx_fisa_cbk(void * dp_soc,void * dp_vdev,qdf_nbuf_t nbuf_list)1630 QDF_STATUS wlan_dp_rx_fisa_cbk(void *dp_soc,
1631 void *dp_vdev, qdf_nbuf_t nbuf_list)
1632 {
1633 struct wlan_dp_psoc_context *dp_ctx = dp_get_context();
1634
1635 return dp_fisa_rx(dp_ctx, dp_vdev, nbuf_list);
1636 }
1637
wlan_dp_rx_fisa_flush_by_ctx_id(void * dp_soc,int ring_num)1638 QDF_STATUS wlan_dp_rx_fisa_flush_by_ctx_id(void *dp_soc, int ring_num)
1639 {
1640 return dp_rx_fisa_flush_by_ctx_id((struct dp_soc *)dp_soc, ring_num);
1641 }
1642
wlan_dp_rx_fisa_flush_by_vdev_id(void * dp_soc,uint8_t vdev_id)1643 QDF_STATUS wlan_dp_rx_fisa_flush_by_vdev_id(void *dp_soc, uint8_t vdev_id)
1644 {
1645 return dp_rx_fisa_flush_by_vdev_id((struct dp_soc *)dp_soc, vdev_id);
1646 }
1647 #endif
1648
dp_rx_packet_cbk(void * dp_link_context,qdf_nbuf_t rxBuf)1649 QDF_STATUS dp_rx_packet_cbk(void *dp_link_context,
1650 qdf_nbuf_t rxBuf)
1651 {
1652 struct wlan_dp_intf *dp_intf = NULL;
1653 struct wlan_dp_link *dp_link = NULL;
1654 struct wlan_dp_psoc_context *dp_ctx = NULL;
1655 QDF_STATUS qdf_status = QDF_STATUS_E_FAILURE;
1656 qdf_nbuf_t nbuf = NULL;
1657 qdf_nbuf_t next = NULL;
1658 unsigned int cpu_index;
1659 struct qdf_mac_addr *mac_addr, *dest_mac_addr;
1660 bool wake_lock = false;
1661 bool track_arp = false;
1662 enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
1663 bool is_eapol, send_over_nl;
1664 bool is_dhcp;
1665 struct dp_tx_rx_stats *stats;
1666 QDF_STATUS status;
1667 uint8_t pkt_type;
1668
1669 /* Sanity check on inputs */
1670 if (qdf_unlikely((!dp_link_context) || (!rxBuf))) {
1671 dp_err_rl("Null params being passed");
1672 return QDF_STATUS_E_FAILURE;
1673 }
1674
1675 dp_link = (struct wlan_dp_link *)dp_link_context;
1676 dp_intf = dp_link->dp_intf;
1677 dp_ctx = dp_intf->dp_ctx;
1678
1679 cpu_index = qdf_get_cpu();
1680 stats = &dp_intf->dp_stats.tx_rx_stats;
1681
1682 next = rxBuf;
1683
1684 while (next) {
1685 nbuf = next;
1686 next = qdf_nbuf_next(nbuf);
1687 qdf_nbuf_set_next(nbuf, NULL);
1688 is_eapol = false;
1689 is_dhcp = false;
1690 send_over_nl = false;
1691
1692 if (qdf_nbuf_is_ipv4_arp_pkt(nbuf)) {
1693 if (qdf_nbuf_data_is_arp_rsp(nbuf) &&
1694 (dp_intf->track_arp_ip ==
1695 qdf_nbuf_get_arp_src_ip(nbuf))) {
1696 ++dp_intf->dp_stats.arp_stats.
1697 rx_arp_rsp_count;
1698 dp_debug("ARP packet received");
1699 track_arp = true;
1700 }
1701 } else if (qdf_nbuf_is_ipv4_eapol_pkt(nbuf)) {
1702 subtype = qdf_nbuf_get_eapol_subtype(nbuf);
1703 send_over_nl = true;
1704
1705 /* Mac address check between RX packet DA and dp_intf's */
1706 dp_rx_pkt_da_check(dp_intf, nbuf);
1707 if (subtype == QDF_PROTO_EAPOL_M1) {
1708 ++dp_intf->dp_stats.eapol_stats.
1709 eapol_m1_count;
1710 is_eapol = true;
1711 } else if (subtype == QDF_PROTO_EAPOL_M3) {
1712 ++dp_intf->dp_stats.eapol_stats.
1713 eapol_m3_count;
1714 is_eapol = true;
1715 }
1716 } else if (qdf_nbuf_is_ipv4_dhcp_pkt(nbuf)) {
1717 subtype = qdf_nbuf_get_dhcp_subtype(nbuf);
1718 if (subtype == QDF_PROTO_DHCP_OFFER) {
1719 ++dp_intf->dp_stats.dhcp_stats.
1720 dhcp_off_count;
1721 is_dhcp = true;
1722 } else if (subtype == QDF_PROTO_DHCP_ACK) {
1723 ++dp_intf->dp_stats.dhcp_stats.
1724 dhcp_ack_count;
1725 is_dhcp = true;
1726 }
1727 }
1728
1729 wlan_dp_pkt_add_timestamp(dp_intf, QDF_PKT_RX_DRIVER_EXIT,
1730 nbuf);
1731
1732 /* track connectivity stats */
1733 if (dp_intf->pkt_type_bitmap)
1734 dp_tx_rx_collect_connectivity_stats_info(nbuf, dp_link,
1735 PKT_TYPE_RSP,
1736 &pkt_type);
1737
1738 if ((dp_link->conn_info.proxy_arp_service) &&
1739 dp_is_gratuitous_arp_unsolicited_na(dp_ctx, nbuf)) {
1740 qdf_atomic_inc(&stats->rx_usolict_arp_n_mcast_drp);
1741 /* Remove SKB from internal tracking table before
1742 * submitting it to stack.
1743 */
1744 qdf_nbuf_free(nbuf);
1745 continue;
1746 }
1747
1748 dp_event_eapol_log(nbuf, QDF_RX);
1749 qdf_dp_trace_log_pkt(dp_link->link_id, nbuf, QDF_RX,
1750 QDF_TRACE_DEFAULT_PDEV_ID,
1751 dp_intf->device_mode);
1752
1753 DPTRACE(qdf_dp_trace(nbuf,
1754 QDF_DP_TRACE_RX_PACKET_PTR_RECORD,
1755 QDF_TRACE_DEFAULT_PDEV_ID,
1756 qdf_nbuf_data_addr(nbuf),
1757 sizeof(qdf_nbuf_data(nbuf)), QDF_RX));
1758
1759 DPTRACE(qdf_dp_trace_data_pkt(nbuf, QDF_TRACE_DEFAULT_PDEV_ID,
1760 QDF_DP_TRACE_RX_PACKET_RECORD,
1761 0, QDF_RX));
1762
1763 dest_mac_addr = (struct qdf_mac_addr *)(qdf_nbuf_data(nbuf) +
1764 QDF_NBUF_DEST_MAC_OFFSET);
1765 mac_addr = (struct qdf_mac_addr *)(qdf_nbuf_data(nbuf) +
1766 QDF_NBUF_SRC_MAC_OFFSET);
1767
1768 status = wlan_objmgr_vdev_try_get_ref(dp_link->vdev,
1769 WLAN_TDLS_SB_ID);
1770 if (QDF_IS_STATUS_SUCCESS(status)) {
1771 wlan_tdls_update_rx_pkt_cnt(dp_link->vdev, mac_addr,
1772 dest_mac_addr);
1773 wlan_objmgr_vdev_release_ref(dp_link->vdev,
1774 WLAN_TDLS_SB_ID);
1775 }
1776
1777 if (dp_rx_pkt_tracepoints_enabled())
1778 qdf_trace_dp_packet(nbuf, QDF_RX, NULL, 0);
1779
1780 qdf_nbuf_set_dev(nbuf, dp_intf->dev);
1781 qdf_nbuf_set_protocol_eth_tye_trans(nbuf);
1782 ++stats->per_cpu[cpu_index].rx_packets;
1783 qdf_net_stats_add_rx_pkts(&dp_intf->stats, 1);
1784 /* count aggregated RX frame into stats */
1785 qdf_net_stats_add_rx_pkts(&dp_intf->stats,
1786 qdf_nbuf_get_gso_segs(nbuf));
1787 qdf_net_stats_add_rx_bytes(&dp_intf->stats,
1788 qdf_nbuf_len(nbuf));
1789
1790 /* Incr GW Rx count for NUD tracking based on GW mac addr */
1791 dp_nud_incr_gw_rx_pkt_cnt(dp_intf, mac_addr);
1792
1793 /* Check & drop replayed mcast packets (for IPV6) */
1794 if (dp_ctx->dp_cfg.multicast_replay_filter &&
1795 qdf_nbuf_is_mcast_replay(nbuf)) {
1796 qdf_atomic_inc(&stats->rx_usolict_arp_n_mcast_drp);
1797 qdf_nbuf_free(nbuf);
1798 continue;
1799 }
1800
1801 /* hold configurable wakelock for unicast traffic */
1802 if (!dp_is_current_high_throughput(dp_ctx) &&
1803 dp_ctx->dp_cfg.rx_wakelock_timeout &&
1804 dp_link->conn_info.is_authenticated)
1805 wake_lock = dp_is_rx_wake_lock_needed(nbuf);
1806
1807 if (wake_lock) {
1808 cds_host_diag_log_work(&dp_ctx->rx_wake_lock,
1809 dp_ctx->dp_cfg.rx_wakelock_timeout,
1810 WIFI_POWER_EVENT_WAKELOCK_HOLD_RX);
1811 qdf_wake_lock_timeout_acquire(&dp_ctx->rx_wake_lock,
1812 dp_ctx->dp_cfg.rx_wakelock_timeout);
1813 }
1814
1815 /* Remove SKB from internal tracking table before submitting
1816 * it to stack
1817 */
1818 qdf_net_buf_debug_release_skb(nbuf);
1819
1820 dp_tsf_timestamp_rx(dp_ctx, nbuf);
1821
1822 if (send_over_nl && dp_ctx->dp_ops.dp_send_rx_pkt_over_nl) {
1823 if (dp_ctx->dp_ops.dp_send_rx_pkt_over_nl(dp_intf->dev,
1824 (u8 *)&dp_link->conn_info.peer_macaddr,
1825 nbuf, false))
1826 qdf_status = QDF_STATUS_SUCCESS;
1827 else
1828 qdf_status = QDF_STATUS_E_INVAL;
1829 qdf_nbuf_dev_kfree(nbuf);
1830 } else {
1831 qdf_status = wlan_dp_rx_deliver_to_stack(dp_intf, nbuf);
1832 }
1833
1834 if (QDF_IS_STATUS_SUCCESS(qdf_status)) {
1835 ++stats->per_cpu[cpu_index].rx_delivered;
1836 if (track_arp)
1837 ++dp_intf->dp_stats.arp_stats.rx_delivered;
1838 if (is_eapol)
1839 ++dp_intf->dp_stats.eapol_stats.
1840 rx_delivered[subtype - QDF_PROTO_EAPOL_M1];
1841 else if (is_dhcp)
1842 ++dp_intf->dp_stats.dhcp_stats.
1843 rx_delivered[subtype - QDF_PROTO_DHCP_DISCOVER];
1844
1845 /* track connectivity stats */
1846 if (dp_intf->pkt_type_bitmap)
1847 dp_tx_rx_collect_connectivity_stats_info(
1848 nbuf, dp_link,
1849 PKT_TYPE_RX_DELIVERED,
1850 &pkt_type);
1851 } else {
1852 ++stats->per_cpu[cpu_index].rx_refused;
1853 if (track_arp)
1854 ++dp_intf->dp_stats.arp_stats.rx_refused;
1855
1856 if (is_eapol)
1857 ++dp_intf->dp_stats.eapol_stats.
1858 rx_refused[subtype - QDF_PROTO_EAPOL_M1];
1859 else if (is_dhcp)
1860 ++dp_intf->dp_stats.dhcp_stats.
1861 rx_refused[subtype - QDF_PROTO_DHCP_DISCOVER];
1862
1863 /* track connectivity stats */
1864 if (dp_intf->pkt_type_bitmap)
1865 dp_tx_rx_collect_connectivity_stats_info(
1866 nbuf, dp_link,
1867 PKT_TYPE_RX_REFUSED,
1868 &pkt_type);
1869 }
1870 }
1871
1872 return QDF_STATUS_SUCCESS;
1873 }
1874
1875