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 any
5   * purpose with or without fee is hereby granted, provided that the above
6   * copyright notice and this permission notice appear in all copies.
7   *
8   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9   * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10   * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11   * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12   * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13   * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14   * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15   */
16  
17  /**
18   *  DOC: osif_dp_txrx.c
19   *  This file contains DP component's TX/RX osif API implementation
20   */
21  #include "os_if_dp.h"
22  #include "os_if_dp_lro.h"
23  #include <wlan_dp_public_struct.h>
24  #include <wlan_objmgr_vdev_obj.h>
25  #include "osif_sync.h"
26  #include <linux/netdevice.h>
27  #include <linux/skbuff.h>
28  #include <linux/etherdevice.h>
29  #include <linux/if_ether.h>
30  #include <linux/inetdevice.h>
31  #include <linux/wireless.h>
32  #include <linux/rtnetlink.h>
33  #include <net/cfg80211.h>
34  #include <cdp_txrx_cmn.h>
35  #include <cdp_txrx_peer_ops.h>
36  #include <cdp_txrx_misc.h>
37  #include <net/tcp.h>
38  #include <ol_defines.h>
39  #include <hif_napi.h>
40  #include <hif.h>
41  #include <wlan_hdd_main.h>
42  #include "wlan_hdd_wmm.h"
43  
44  /**
45   * osif_dp_classify_pkt() - classify packet
46   * @skb:  sk buff
47   *
48   * Return: none
49   */
osif_dp_classify_pkt(struct sk_buff * skb)50  void osif_dp_classify_pkt(struct sk_buff *skb)
51  {
52  	struct ethhdr *eh = (struct ethhdr *)skb->data;
53  
54  	qdf_mem_zero(skb->cb, sizeof(skb->cb));
55  
56  	/* check destination mac address is broadcast/multicast */
57  	if (is_broadcast_ether_addr((uint8_t *)eh))
58  		QDF_NBUF_CB_GET_IS_BCAST(skb) = true;
59  	else if (is_multicast_ether_addr((uint8_t *)eh))
60  		QDF_NBUF_CB_GET_IS_MCAST(skb) = true;
61  
62  	if (qdf_nbuf_is_ipv4_arp_pkt(skb))
63  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
64  			QDF_NBUF_CB_PACKET_TYPE_ARP;
65  	else if (qdf_nbuf_is_ipv4_dhcp_pkt(skb))
66  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
67  			QDF_NBUF_CB_PACKET_TYPE_DHCP;
68  	else if (qdf_nbuf_is_ipv4_eapol_pkt(skb))
69  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
70  			QDF_NBUF_CB_PACKET_TYPE_EAPOL;
71  	else if (qdf_nbuf_is_ipv4_wapi_pkt(skb))
72  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
73  			QDF_NBUF_CB_PACKET_TYPE_WAPI;
74  	else if (qdf_nbuf_is_icmp_pkt(skb))
75  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
76  			QDF_NBUF_CB_PACKET_TYPE_ICMP;
77  	else if (qdf_nbuf_is_icmpv6_pkt(skb))
78  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
79  			QDF_NBUF_CB_PACKET_TYPE_ICMPv6;
80  }
81  
82  /**
83   * osif_dp_mark_critical_pkt() - Identify and mark critical packets
84   * @skb: skb ptr
85   *
86   * Return: None
87   */
osif_dp_mark_critical_pkt(struct sk_buff * skb)88  static void osif_dp_mark_critical_pkt(struct sk_buff *skb)
89  {
90  	if (qdf_nbuf_is_ipv4_eapol_pkt(skb)) {
91  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
92  				QDF_NBUF_CB_PACKET_TYPE_EAPOL;
93  	} else if (qdf_nbuf_is_ipv4_arp_pkt(skb)) {
94  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
95  				QDF_NBUF_CB_PACKET_TYPE_ARP;
96  	} else if (qdf_nbuf_is_ipv4_dhcp_pkt(skb)) {
97  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
98  				QDF_NBUF_CB_PACKET_TYPE_DHCP;
99  	} else if (qdf_nbuf_is_ipv6_dhcp_pkt(skb)) {
100  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
101  				QDF_NBUF_CB_PACKET_TYPE_DHCPV6;
102  	} else if (qdf_nbuf_is_icmpv6_pkt(skb)) {
103  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
104  			QDF_NBUF_CB_PACKET_TYPE_ICMPv6;
105  	}
106  
107  	QDF_NBUF_CB_TX_EXTRA_IS_CRITICAL(skb) = true;
108  }
109  
110  #ifdef DP_TX_PACKET_INSPECT_FOR_ILP
111  /**
112   * osif_dp_mark_pkt_type_by_priority() - mark packet type to skb->cb
113   *                                       by type from priority of skb
114   * @skb: network buffer
115   *
116   * Return: true - packet type marked, false - not marked
117   */
118  static inline
osif_dp_mark_pkt_type_by_priority(struct sk_buff * skb)119  bool osif_dp_mark_pkt_type_by_priority(struct sk_buff *skb)
120  {
121  	bool type_marked = false;
122  	uint32_t pkt_type =
123  		qdf_nbuf_get_priority_pkt_type(skb);
124  
125  	if (qdf_unlikely(pkt_type == QDF_NBUF_PRIORITY_PKT_TCP_ACK)) {
126  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
127  					QDF_NBUF_CB_PACKET_TYPE_TCP_ACK;
128  		type_marked = true;
129  	}
130  	/* cleanup the packet type in priority */
131  	qdf_nbuf_remove_priority_pkt_type(skb);
132  
133  	return type_marked;
134  }
135  #else
136  static inline
osif_dp_mark_pkt_type_by_priority(struct sk_buff * skb)137  bool osif_dp_mark_pkt_type_by_priority(struct sk_buff *skb)
138  {
139  	return false;
140  }
141  #endif
142  
143  /**
144   * osif_dp_mark_non_critical_pkt() - Identify and mark non-critical packets
145   * @skb: skb ptr
146   *
147   * Return: None
148   */
osif_dp_mark_non_critical_pkt(struct sk_buff * skb)149  static void osif_dp_mark_non_critical_pkt(struct sk_buff *skb)
150  {
151  	/* check if packet type is marked from skb->priority already */
152  	if (osif_dp_mark_pkt_type_by_priority(skb))
153  		return;
154  
155  	if (qdf_nbuf_is_icmp_pkt(skb))
156  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
157  				QDF_NBUF_CB_PACKET_TYPE_ICMP;
158  	else if (qdf_nbuf_is_ipv4_wapi_pkt(skb))
159  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
160  			QDF_NBUF_CB_PACKET_TYPE_WAPI;
161  }
162  
osif_dp_mark_pkt_type(struct sk_buff * skb)163  void osif_dp_mark_pkt_type(struct sk_buff *skb)
164  {
165  	struct ethhdr *eh = (struct ethhdr *)skb->data;
166  
167  	/*
168  	 * Zero out CB before accessing it. Expectation is that cb is accessed
169  	 * for the first time here on TX path in hard_start_xmit.
170  	 */
171  	qdf_mem_zero(skb->cb, sizeof(skb->cb));
172  
173  	/* check destination mac address is broadcast/multicast */
174  	if (is_broadcast_ether_addr((uint8_t *)eh))
175  		QDF_NBUF_CB_GET_IS_BCAST(skb) = true;
176  	else if (is_multicast_ether_addr((uint8_t *)eh))
177  		QDF_NBUF_CB_GET_IS_MCAST(skb) = true;
178  
179  	/*
180  	 * TX Packets in the HI_PRIO queue are assumed to be critical and
181  	 * marked accordingly.
182  	 */
183  	if (skb->queue_mapping == TX_GET_QUEUE_IDX(HDD_LINUX_AC_HI_PRIO, 0))
184  		osif_dp_mark_critical_pkt(skb);
185  	else
186  		osif_dp_mark_non_critical_pkt(skb);
187  }
188  
189  /*
190   * When bus bandwidth is idle, if RX data is delivered with
191   * napi_gro_receive, to reduce RX delay related with GRO,
192   * check gro_result returned from napi_gro_receive to determine
193   * is extra GRO flush still necessary.
194   */
195  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 12, 0))
196  #define DP_IS_EXTRA_GRO_FLUSH_NECESSARY(_gro_ret) true
197  #define GRO_DROP_UPDATE_STATUS(gro_ret, status)
198  #else
199  #define GRO_DROP_UPDATE_STATUS(gro_ret, status) \
200  	if ((gro_ret) == GRO_DROP) ((status) = QDF_STATUS_E_GRO_DROP)
201  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
202  #define DP_IS_EXTRA_GRO_FLUSH_NECESSARY(_gro_ret) \
203  	((_gro_ret) != GRO_DROP)
204  #else
205  #define DP_IS_EXTRA_GRO_FLUSH_NECESSARY(_gro_ret) \
206  	((_gro_ret) != GRO_DROP && (_gro_ret) != GRO_NORMAL)
207  #endif
208  #endif
209  
210  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
211  /**
212   * osif_dp_rx_thread_napi_gro_flush() - do gro flush
213   * @napi: napi used to do gro flush
214   * @flush_code: flush_code differentiating low_tput_flush and normal_flush
215   *
216   * if there is RX GRO_NORMAL packets pending in napi
217   * rx_list, flush them manually right after napi_gro_flush.
218   *
219   * Return: none
220   */
221  static inline
osif_dp_rx_thread_napi_gro_flush(struct napi_struct * napi,enum dp_rx_gro_flush_code flush_code)222  void osif_dp_rx_thread_napi_gro_flush(struct napi_struct *napi,
223  				      enum dp_rx_gro_flush_code flush_code)
224  {
225  	if (napi->poll) {
226  		/* Skipping GRO flush in low TPUT */
227  		if (flush_code != DP_RX_GRO_LOW_TPUT_FLUSH)
228  			napi_gro_flush(napi, false);
229  
230  		if (napi->rx_count) {
231  			netif_receive_skb_list(&napi->rx_list);
232  			qdf_init_list_head(&napi->rx_list);
233  			napi->rx_count = 0;
234  		}
235  	}
236  }
237  #else
238  static inline
osif_dp_rx_thread_napi_gro_flush(struct napi_struct * napi,enum dp_rx_gro_flush_code flush_code)239  void osif_dp_rx_thread_napi_gro_flush(struct napi_struct *napi,
240  				      enum dp_rx_gro_flush_code flush_code)
241  {
242  	if (napi->poll) {
243  		/* Skipping GRO flush in low TPUT */
244  		if (flush_code != DP_RX_GRO_LOW_TPUT_FLUSH)
245  			napi_gro_flush(napi, false);
246  	}
247  }
248  #endif
249  
250  /**
251   * osif_dp_rx_napi_gro_flush() - GRO RX/flush function.
252   * @napi_to_use: napi to be used to give packets to the stack, gro flush
253   * @nbuf: pointer to n/w buff
254   * @low_tput_force_flush: Is force flush required in low tput
255   *
256   * Function calls napi_gro_receive for the skb. If the skb indicates that a
257   * flush needs to be done (set by the lower DP layer), the function also calls
258   * napi_gro_flush. Local softirqs are disabled (and later enabled) while making
259   * napi_gro__ calls.
260   *
261   * Return: QDF_STATUS_SUCCESS if not dropped by napi_gro_receive or
262   *	   QDF error code.
263   */
264  
265  static QDF_STATUS
osif_dp_rx_napi_gro_flush(qdf_napi_struct * napi_to_use,qdf_nbuf_t nbuf,uint8_t * low_tput_force_flush)266  osif_dp_rx_napi_gro_flush(qdf_napi_struct *napi_to_use,
267  			  qdf_nbuf_t nbuf,
268  			  uint8_t *low_tput_force_flush)
269  {
270  	QDF_STATUS status = QDF_STATUS_SUCCESS;
271  	gro_result_t gro_ret;
272  
273  	skb_set_hash(nbuf, QDF_NBUF_CB_RX_FLOW_ID(nbuf), PKT_HASH_TYPE_L4);
274  
275  	local_bh_disable();
276  	gro_ret = napi_gro_receive((struct napi_struct *)napi_to_use, nbuf);
277  
278  	if (DP_IS_EXTRA_GRO_FLUSH_NECESSARY(gro_ret)) {
279  		*low_tput_force_flush = 1;
280  		osif_dp_rx_thread_napi_gro_flush((struct napi_struct *)napi_to_use,
281  						 DP_RX_GRO_NORMAL_FLUSH);
282  	}
283  
284  	local_bh_enable();
285  	GRO_DROP_UPDATE_STATUS(gro_ret, status);
286  
287  	return status;
288  }
289  
290  /**
291   * osif_dp_rx_napi_gro_receive() - GRO RX receive function.
292   * @napi_to_use: napi to be used to give packets to the stack
293   * @nbuf: pointer to n/w buff
294   *
295   * Function calls napi_gro_receive for the skb.
296   * napi_gro_flush. Local softirqs are disabled (and later enabled) while making
297   * napi_gro__ calls.
298   *
299   * Return: QDF_STATUS_SUCCESS if not dropped by napi_gro_receive or
300   *	   QDF error code.
301   */
302  static QDF_STATUS
osif_dp_rx_napi_gro_receive(qdf_napi_struct * napi_to_use,qdf_nbuf_t nbuf)303  osif_dp_rx_napi_gro_receive(qdf_napi_struct *napi_to_use,
304  			    qdf_nbuf_t nbuf)
305  {
306  	QDF_STATUS status = QDF_STATUS_SUCCESS;
307  	gro_result_t gro_ret;
308  
309  	skb_set_hash(nbuf, QDF_NBUF_CB_RX_FLOW_ID(nbuf), PKT_HASH_TYPE_L4);
310  
311  	local_bh_disable();
312  	gro_ret = napi_gro_receive((struct napi_struct *)napi_to_use, nbuf);
313  
314  	local_bh_enable();
315  	GRO_DROP_UPDATE_STATUS(gro_ret, status);
316  
317  	return status;
318  }
319  
320  #ifdef RECEIVE_OFFLOAD
321  /**
322   * osif_dp_rxthread_napi_normal_gro_flush() - GRO flush cbk for NAPI+Rx_Thread
323   * Rx mode
324   * @data: hif NAPI context
325   *
326   * Return: none
327   */
osif_dp_rxthread_napi_normal_gro_flush(void * data)328  static void osif_dp_rxthread_napi_normal_gro_flush(void *data)
329  {
330  	struct qca_napi_info *qca_napi = (struct qca_napi_info *)data;
331  
332  	local_bh_disable();
333  	/*
334  	 * As we are breaking context in Rxthread mode, there is rx_thread NAPI
335  	 * corresponds each hif_napi.
336  	 */
337  	osif_dp_rx_thread_napi_gro_flush(&qca_napi->rx_thread_napi,
338  					 DP_RX_GRO_NORMAL_FLUSH);
339  	local_bh_enable();
340  }
341  
342  /**
343   * osif_dp_hif_napi_gro_flush() - GRO flush callback for NAPI Rx mode
344   * @data: hif NAPI context
345   *
346   * Return: none
347   */
osif_dp_hif_napi_gro_flush(void * data)348  static void osif_dp_hif_napi_gro_flush(void *data)
349  {
350  	struct qca_napi_info *qca_napi = (struct qca_napi_info *)data;
351  
352  	local_bh_disable();
353  	napi_gro_flush(&qca_napi->napi, false);
354  	local_bh_enable();
355  }
356  #endif
357  
358  #ifdef FEATURE_LRO
359  /**
360   * osif_dp_qdf_lro_flush() - LRO flush wrapper
361   * @data: hif NAPI context
362   *
363   * Return: none
364   */
osif_dp_qdf_lro_flush(void * data)365  static void osif_dp_qdf_lro_flush(void *data)
366  {
367  	struct qca_napi_info *qca_napii = (struct qca_napi_info *)data;
368  	qdf_lro_ctx_t qdf_lro_ctx = qca_napii->lro_ctx;
369  
370  	qdf_lro_flush(qdf_lro_ctx);
371  }
372  #elif defined(RECEIVE_OFFLOAD)
osif_dp_qdf_lro_flush(void * data)373  static void osif_dp_qdf_lro_flush(void *data)
374  {
375  }
376  #endif
377  
378  #ifdef WLAN_FEATURE_DYNAMIC_RX_AGGREGATION
379  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
380  static enum qdisc_filter_status
__osif_check_for_prio_filter_in_clsact_qdisc(struct tcf_block * block,uint32_t prio)381  __osif_check_for_prio_filter_in_clsact_qdisc(struct tcf_block *block,
382  					     uint32_t prio)
383  {
384  	struct tcf_chain *chain;
385  	struct tcf_proto *tp;
386  	struct tcf_proto *tp_next;
387  	enum qdisc_filter_status ret = QDISC_FILTER_PRIO_MISMATCH;
388  
389  	mutex_lock(&block->lock);
390  	list_for_each_entry(chain, &block->chain_list, list) {
391  		mutex_lock(&chain->filter_chain_lock);
392  		tp = tcf_chain_dereference(chain->filter_chain, chain);
393  		while (tp) {
394  			tp_next = rtnl_dereference(tp->next);
395  			if (tp->prio == (prio << 16)) {
396  				ret = QDISC_FILTER_PRIO_MATCH;
397  				break;
398  			}
399  			tp = tp_next;
400  		}
401  		mutex_unlock(&chain->filter_chain_lock);
402  
403  		if (ret == QDISC_FILTER_PRIO_MATCH)
404  			break;
405  	}
406  	mutex_unlock(&block->lock);
407  
408  	return ret;
409  }
410  #else
411  static enum qdisc_filter_status
__osif_check_for_prio_filter_in_clsact_qdisc(struct tcf_block * block,uint32_t prio)412  __osif_check_for_prio_filter_in_clsact_qdisc(struct tcf_block *block,
413  					     uint32_t prio)
414  {
415  	struct tcf_chain *chain;
416  	struct tcf_proto *tp;
417  	enum qdisc_filter_status ret = QDISC_FILTER_PRIO_MISMATCH;
418  
419  	if (!rtnl_trylock())
420  		return QDISC_FILTER_RTNL_LOCK_FAIL;
421  
422  	list_for_each_entry(chain, &block->chain_list, list) {
423  		for (tp = rtnl_dereference(chain->filter_chain); tp;
424  		     tp = rtnl_dereference(tp->next)) {
425  			if (tp->prio == (prio << 16))
426  				ret = QDISC_FILTER_PRIO_MATCH;
427  		}
428  	}
429  	rtnl_unlock();
430  
431  	return ret;
432  }
433  #endif
434  
435  /**
436   * osif_check_for_prio_filter_in_clsact_qdisc() - Check if priority 3 filter
437   *  is configured in the ingress clsact qdisc
438   * @qdisc: pointer to clsact qdisc
439   * @prio: traffic priority
440   *
441   * Return: qdisc filter status
442   */
443  static enum qdisc_filter_status
osif_check_for_prio_filter_in_clsact_qdisc(struct Qdisc * qdisc,uint32_t prio)444  osif_check_for_prio_filter_in_clsact_qdisc(struct Qdisc *qdisc, uint32_t prio)
445  {
446  	const struct Qdisc_class_ops *cops;
447  	struct tcf_block *ingress_block;
448  
449  	cops = qdisc->ops->cl_ops;
450  	if (qdf_unlikely(!cops || !cops->tcf_block))
451  		return QDISC_FILTER_PRIO_MISMATCH;
452  
453  	ingress_block = cops->tcf_block(qdisc, TC_H_MIN_INGRESS, NULL);
454  	if (qdf_unlikely(!ingress_block))
455  		return QDISC_FILTER_PRIO_MISMATCH;
456  
457  	return __osif_check_for_prio_filter_in_clsact_qdisc(ingress_block,
458  							    prio);
459  }
460  
461  /**
462   * osif_dp_rx_check_qdisc_configured() - Check if any ingress qdisc
463   * configured for given netdev
464   * @ndev: pointer to netdev
465   * @prio: traffic priority
466   *
467   * The function checks if ingress qdisc is registered for a given
468   * net device.
469   *
470   * Return: None
471   */
472  static QDF_STATUS
osif_dp_rx_check_qdisc_configured(qdf_netdev_t ndev,uint32_t prio)473  osif_dp_rx_check_qdisc_configured(qdf_netdev_t ndev, uint32_t prio)
474  {
475  	struct netdev_queue *ingress_q;
476  	struct Qdisc *ingress_qdisc;
477  	struct net_device *dev = (struct net_device *)ndev;
478  	bool disable_gro = false;
479  	enum qdisc_filter_status status;
480  
481  	if (!dev->ingress_queue)
482  		goto reset_wl;
483  
484  	if (!rtnl_trylock())
485  		return QDF_STATUS_E_AGAIN;
486  
487  	ingress_q = rtnl_dereference(dev->ingress_queue);
488  	if (qdf_unlikely(!ingress_q))
489  		goto reset;
490  
491  	ingress_qdisc = rtnl_dereference(ingress_q->qdisc);
492  	if (qdf_unlikely(!ingress_qdisc))
493  		goto reset;
494  
495  	if (qdf_str_eq(ingress_qdisc->ops->id, "ingress")) {
496  		disable_gro = true;
497  	} else if (qdf_str_eq(ingress_qdisc->ops->id, "clsact")) {
498  		status = osif_check_for_prio_filter_in_clsact_qdisc(
499  								  ingress_qdisc,
500  								  prio);
501  
502  		if (status == QDISC_FILTER_PRIO_MISMATCH)
503  			goto reset;
504  
505  		disable_gro = true;
506  	}
507  
508  	if (disable_gro) {
509  		rtnl_unlock();
510  		return QDF_STATUS_SUCCESS;
511  	}
512  
513  reset:
514  	rtnl_unlock();
515  
516  reset_wl:
517  	return QDF_STATUS_E_NOSUPPORT;
518  }
519  
520  #else
521  static QDF_STATUS
osif_dp_rx_check_qdisc_configured(qdf_netdev_t ndev,uint32_t prio)522  osif_dp_rx_check_qdisc_configured(qdf_netdev_t ndev, uint32_t prio)
523  {
524  	return QDF_STATUS_E_NOSUPPORT;
525  }
526  #endif
527  
528  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 6, 0))
529  static void
osif_dp_register_arp_unsolicited_cbk(struct wlan_dp_psoc_callbacks * cb_obj)530  osif_dp_register_arp_unsolicited_cbk(struct wlan_dp_psoc_callbacks *cb_obj)
531  {
532  	cb_obj->dp_is_gratuitous_arp_unsolicited_na = NULL;
533  }
534  #else
osif_dp_is_gratuitous_arp_unsolicited_na(qdf_nbuf_t nbuf)535  static bool osif_dp_is_gratuitous_arp_unsolicited_na(qdf_nbuf_t nbuf)
536  {
537  	return cfg80211_is_gratuitous_arp_unsolicited_na((struct sk_buff *)nbuf);
538  }
539  
540  static void
osif_dp_register_arp_unsolicited_cbk(struct wlan_dp_psoc_callbacks * cb_obj)541  osif_dp_register_arp_unsolicited_cbk(struct wlan_dp_psoc_callbacks *cb_obj)
542  {
543  	cb_obj->dp_is_gratuitous_arp_unsolicited_na =
544  		osif_dp_is_gratuitous_arp_unsolicited_na;
545  }
546  #endif
547  
548  #if defined(CFG80211_CTRL_FRAME_SRC_ADDR_TA_ADDR)
549  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 15, 41))
550  static
osif_dp_cfg80211_rx_control_port(qdf_netdev_t dev,u8 * ta_addr,qdf_nbuf_t nbuf,bool unencrypted)551  bool osif_dp_cfg80211_rx_control_port(qdf_netdev_t dev, u8 *ta_addr,
552  				      qdf_nbuf_t nbuf, bool unencrypted)
553  {
554  	return cfg80211_rx_control_port((struct net_device *)dev,
555  					(struct sk_buff *)nbuf,
556  					unencrypted, -1);
557  }
558  
559  #else
560  static
osif_dp_cfg80211_rx_control_port(qdf_netdev_t dev,u8 * ta_addr,qdf_nbuf_t nbuf,bool unencrypted)561  bool osif_dp_cfg80211_rx_control_port(qdf_netdev_t dev, u8 *ta_addr,
562  				      qdf_nbuf_t nbuf, bool unencrypted)
563  {
564  	return cfg80211_rx_control_port((struct net_device *)dev,
565  					ta_addr, (struct sk_buff *)nbuf,
566  					unencrypted);
567  }
568  #endif
569  
570  static void
osif_dp_register_send_rx_pkt_over_nl(struct wlan_dp_psoc_callbacks * cb_obj)571  osif_dp_register_send_rx_pkt_over_nl(struct wlan_dp_psoc_callbacks *cb_obj)
572  {
573  	cb_obj->dp_send_rx_pkt_over_nl = osif_dp_cfg80211_rx_control_port;
574  }
575  
576  #else
577  static void
osif_dp_register_send_rx_pkt_over_nl(struct wlan_dp_psoc_callbacks * cb_obj)578  osif_dp_register_send_rx_pkt_over_nl(struct wlan_dp_psoc_callbacks *cb_obj)
579  {
580  	cb_obj->dp_send_rx_pkt_over_nl = NULL;
581  }
582  #endif
583  
584  #ifdef RECEIVE_OFFLOAD
585  static
osif_dp_register_rx_offld_flush_cb(enum dp_rx_offld_flush_cb cb_type)586  void osif_dp_register_rx_offld_flush_cb(enum dp_rx_offld_flush_cb cb_type)
587  {
588  	void *soc = cds_get_context(QDF_MODULE_ID_SOC);
589  
590  	if (cb_type == DP_RX_FLUSH_LRO)
591  		cdp_register_rx_offld_flush_cb(soc, osif_dp_qdf_lro_flush);
592  	else if (cb_type == DP_RX_FLUSH_THREAD)
593  		cdp_register_rx_offld_flush_cb(soc,
594  					       osif_dp_rxthread_napi_normal_gro_flush);
595  	else if (cb_type == DP_RX_FLUSH_NAPI)
596  		cdp_register_rx_offld_flush_cb(soc,
597  					       osif_dp_hif_napi_gro_flush);
598  }
599  #else
600  
601  static
osif_dp_register_rx_offld_flush_cb(enum dp_rx_offld_flush_cb cb_type)602  void osif_dp_register_rx_offld_flush_cb(enum dp_rx_offld_flush_cb cb_type) { }
603  #endif
604  
605  static
osif_dp_rx_pkt_to_nw(qdf_nbuf_t nbuf,enum dp_nbuf_push_type type)606  QDF_STATUS osif_dp_rx_pkt_to_nw(qdf_nbuf_t nbuf, enum dp_nbuf_push_type type)
607  {
608  	int netif_status;
609  
610  	if (type == DP_NBUF_PUSH_BH_DISABLE) {
611  		local_bh_disable();
612  		netif_status = netif_receive_skb(nbuf);
613  		local_bh_enable();
614  	} else if (type == DP_NBUF_PUSH_NI) {
615  		netif_status = netif_rx_ni(nbuf);
616  	} else if (type == DP_NBUF_PUSH_NAPI) {
617  		netif_status = netif_receive_skb(nbuf);
618  	} else {
619  		netif_status = netif_rx(nbuf);
620  	}
621  
622  	if (qdf_likely(netif_status == NET_RX_SUCCESS))
623  		return QDF_STATUS_SUCCESS;
624  
625  	return QDF_STATUS_E_FAILURE;
626  }
627  
os_if_dp_register_txrx_callbacks(struct wlan_dp_psoc_callbacks * cb_obj)628  void os_if_dp_register_txrx_callbacks(struct wlan_dp_psoc_callbacks *cb_obj)
629  {
630  	cb_obj->dp_nbuf_push_pkt = osif_dp_rx_pkt_to_nw;
631  	cb_obj->dp_rx_napi_gro_flush = osif_dp_rx_napi_gro_flush;
632  	cb_obj->dp_rx_napi_gro_receive = osif_dp_rx_napi_gro_receive;
633  	cb_obj->dp_rx_thread_napi_gro_flush = osif_dp_rx_thread_napi_gro_flush;
634  	cb_obj->dp_lro_rx_cb = osif_dp_lro_rx;
635  	cb_obj->dp_register_rx_offld_flush_cb =
636  		osif_dp_register_rx_offld_flush_cb;
637  	cb_obj->dp_rx_check_qdisc_configured =
638  		osif_dp_rx_check_qdisc_configured;
639  
640  	osif_dp_register_arp_unsolicited_cbk(cb_obj);
641  
642  	osif_dp_register_send_rx_pkt_over_nl(cb_obj);
643  }
644