1  /*
2   * Copyright (c) 2014-2021 The Linux Foundation. All rights reserved.
3   * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4   *
5   * Permission to use, copy, modify, and/or distribute this software for
6   * any purpose with or without fee is hereby granted, provided that the
7   * above copyright notice and this permission notice appear in all
8   * copies.
9   *
10   * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11   * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12   * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
13   * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
14   * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
15   * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
16   * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
17   * PERFORMANCE OF THIS SOFTWARE.
18   */
19  
20  /**
21   * DOC: qdf_nbuf.c
22   * QCA driver framework(QDF) network buffer management APIs
23   */
24  #include <linux/hashtable.h>
25  #include <linux/kernel.h>
26  #include <linux/version.h>
27  #include <linux/skbuff.h>
28  #include <linux/module.h>
29  #include <linux/proc_fs.h>
30  #include <linux/inetdevice.h>
31  #include <qdf_atomic.h>
32  #include <qdf_debugfs.h>
33  #include <qdf_lock.h>
34  #include <qdf_mem.h>
35  #include <qdf_module.h>
36  #include <qdf_nbuf.h>
37  #include <qdf_status.h>
38  #include "qdf_str.h"
39  #include <qdf_trace.h>
40  #include "qdf_tracker.h"
41  #include <qdf_types.h>
42  #include <net/ieee80211_radiotap.h>
43  #include <pld_common.h>
44  #include <qdf_crypto.h>
45  #include <linux/igmp.h>
46  #include <net/mld.h>
47  
48  #if defined(FEATURE_TSO)
49  #include <net/ipv6.h>
50  #include <linux/ipv6.h>
51  #include <linux/tcp.h>
52  #include <linux/if_vlan.h>
53  #include <linux/ip.h>
54  #endif /* FEATURE_TSO */
55  
56  #ifdef IPA_OFFLOAD
57  #include <i_qdf_ipa_wdi3.h>
58  #endif /* IPA_OFFLOAD */
59  #include "qdf_ssr_driver_dump.h"
60  
61  #if LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0)
62  
63  #define qdf_nbuf_users_inc atomic_inc
64  #define qdf_nbuf_users_dec atomic_dec
65  #define qdf_nbuf_users_set atomic_set
66  #define qdf_nbuf_users_read atomic_read
67  #else
68  #define qdf_nbuf_users_inc refcount_inc
69  #define qdf_nbuf_users_dec refcount_dec
70  #define qdf_nbuf_users_set refcount_set
71  #define qdf_nbuf_users_read refcount_read
72  #endif /* KERNEL_VERSION(4, 13, 0) */
73  
74  #define IEEE80211_RADIOTAP_VHT_BW_20	0
75  #define IEEE80211_RADIOTAP_VHT_BW_40	1
76  #define IEEE80211_RADIOTAP_VHT_BW_80	2
77  #define IEEE80211_RADIOTAP_VHT_BW_160	3
78  
79  #define RADIOTAP_VHT_BW_20	0
80  #define RADIOTAP_VHT_BW_40	1
81  #define RADIOTAP_VHT_BW_80	4
82  #define RADIOTAP_VHT_BW_160	11
83  
84  /* tx status */
85  #define RADIOTAP_TX_STATUS_FAIL		1
86  #define RADIOTAP_TX_STATUS_NOACK	2
87  
88  /* channel number to freq conversion */
89  #define CHANNEL_NUM_14 14
90  #define CHANNEL_NUM_15 15
91  #define CHANNEL_NUM_27 27
92  #define CHANNEL_NUM_35 35
93  #define CHANNEL_NUM_182 182
94  #define CHANNEL_NUM_197 197
95  #define CHANNEL_FREQ_2484 2484
96  #define CHANNEL_FREQ_2407 2407
97  #define CHANNEL_FREQ_2512 2512
98  #define CHANNEL_FREQ_5000 5000
99  #define CHANNEL_FREQ_4000 4000
100  #define CHANNEL_FREQ_5150 5150
101  #define FREQ_MULTIPLIER_CONST_5MHZ 5
102  #define FREQ_MULTIPLIER_CONST_20MHZ 20
103  #define RADIOTAP_5G_SPECTRUM_CHANNEL 0x0100
104  #define RADIOTAP_2G_SPECTRUM_CHANNEL 0x0080
105  #define RADIOTAP_CCK_CHANNEL 0x0020
106  #define RADIOTAP_OFDM_CHANNEL 0x0040
107  
108  #ifdef FEATURE_NBUFF_REPLENISH_TIMER
109  #include <qdf_mc_timer.h>
110  
111  struct qdf_track_timer {
112  	qdf_mc_timer_t track_timer;
113  	qdf_atomic_t alloc_fail_cnt;
114  };
115  
116  static struct qdf_track_timer alloc_track_timer;
117  
118  #define QDF_NBUF_ALLOC_EXPIRE_TIMER_MS  5000
119  #define QDF_NBUF_ALLOC_EXPIRE_CNT_THRESHOLD  50
120  #endif
121  
122  #ifdef NBUF_MEMORY_DEBUG
123  /* SMMU crash indication*/
124  static qdf_atomic_t smmu_crashed;
125  /* Number of nbuf not added to history*/
126  unsigned long g_histroy_add_drop;
127  #endif
128  
129  /* Packet Counter */
130  static uint32_t nbuf_tx_mgmt[QDF_NBUF_TX_PKT_STATE_MAX];
131  static uint32_t nbuf_tx_data[QDF_NBUF_TX_PKT_STATE_MAX];
132  #ifdef QDF_NBUF_GLOBAL_COUNT
133  #define NBUF_DEBUGFS_NAME      "nbuf_counters"
134  static qdf_atomic_t nbuf_count;
135  #endif
136  
137  #if defined(NBUF_MEMORY_DEBUG) || defined(QDF_NBUF_GLOBAL_COUNT)
138  static bool is_initial_mem_debug_disabled;
139  #endif
140  
141  /**
142   *  __qdf_nbuf_get_ip_offset() - Get IPV4/V6 header offset
143   * @data: Pointer to network data buffer
144   *
145   * Get the IP header offset in case of 8021Q and 8021AD
146   * tag is present in L2 header.
147   *
148   * Return: IP header offset
149   */
__qdf_nbuf_get_ip_offset(uint8_t * data)150  static inline uint8_t __qdf_nbuf_get_ip_offset(uint8_t *data)
151  {
152  	uint16_t ether_type;
153  
154  	ether_type = *(uint16_t *)(data +
155  				   QDF_NBUF_TRAC_ETH_TYPE_OFFSET);
156  
157  	if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021Q)))
158  		return QDF_NBUF_TRAC_VLAN_IP_OFFSET;
159  	else if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021AD)))
160  		return QDF_NBUF_TRAC_DOUBLE_VLAN_IP_OFFSET;
161  
162  	return QDF_NBUF_TRAC_IP_OFFSET;
163  }
164  
165  /**
166   *  __qdf_nbuf_get_ether_type() - Get the ether type
167   * @data: Pointer to network data buffer
168   *
169   * Get the ether type in case of 8021Q and 8021AD tag
170   * is present in L2 header, e.g for the returned ether type
171   * value, if IPV4 data ether type 0x0800, return 0x0008.
172   *
173   * Return ether type.
174   */
__qdf_nbuf_get_ether_type(uint8_t * data)175  static inline uint16_t __qdf_nbuf_get_ether_type(uint8_t *data)
176  {
177  	uint16_t ether_type;
178  
179  	ether_type = *(uint16_t *)(data +
180  				   QDF_NBUF_TRAC_ETH_TYPE_OFFSET);
181  
182  	if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021Q)))
183  		ether_type = *(uint16_t *)(data +
184  				QDF_NBUF_TRAC_VLAN_ETH_TYPE_OFFSET);
185  	else if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021AD)))
186  		ether_type = *(uint16_t *)(data +
187  				QDF_NBUF_TRAC_DOUBLE_VLAN_ETH_TYPE_OFFSET);
188  
189  	return ether_type;
190  }
191  
qdf_nbuf_tx_desc_count_display(void)192  void qdf_nbuf_tx_desc_count_display(void)
193  {
194  	qdf_debug("Current Snapshot of the Driver:");
195  	qdf_debug("Data Packets:");
196  	qdf_debug("HDD %d TXRX_Q %d TXRX %d HTT %d",
197  		  nbuf_tx_data[QDF_NBUF_TX_PKT_HDD] -
198  		  (nbuf_tx_data[QDF_NBUF_TX_PKT_TXRX] +
199  		  nbuf_tx_data[QDF_NBUF_TX_PKT_TXRX_ENQUEUE] -
200  		  nbuf_tx_data[QDF_NBUF_TX_PKT_TXRX_DEQUEUE]),
201  		  nbuf_tx_data[QDF_NBUF_TX_PKT_TXRX_ENQUEUE] -
202  		  nbuf_tx_data[QDF_NBUF_TX_PKT_TXRX_DEQUEUE],
203  		  nbuf_tx_data[QDF_NBUF_TX_PKT_TXRX] -
204  		  nbuf_tx_data[QDF_NBUF_TX_PKT_HTT],
205  		  nbuf_tx_data[QDF_NBUF_TX_PKT_HTT]  -
206  		  nbuf_tx_data[QDF_NBUF_TX_PKT_HTC]);
207  	qdf_debug(" HTC %d  HIF %d CE %d TX_COMP %d",
208  		  nbuf_tx_data[QDF_NBUF_TX_PKT_HTC] -
209  		  nbuf_tx_data[QDF_NBUF_TX_PKT_HIF],
210  		  nbuf_tx_data[QDF_NBUF_TX_PKT_HIF] -
211  		  nbuf_tx_data[QDF_NBUF_TX_PKT_CE],
212  		  nbuf_tx_data[QDF_NBUF_TX_PKT_CE] -
213  		  nbuf_tx_data[QDF_NBUF_TX_PKT_FREE],
214  		  nbuf_tx_data[QDF_NBUF_TX_PKT_FREE]);
215  	qdf_debug("Mgmt Packets:");
216  	qdf_debug("TXRX_Q %d TXRX %d HTT %d HTC %d HIF %d CE %d TX_COMP %d",
217  		  nbuf_tx_mgmt[QDF_NBUF_TX_PKT_TXRX_ENQUEUE] -
218  		  nbuf_tx_mgmt[QDF_NBUF_TX_PKT_TXRX_DEQUEUE],
219  		  nbuf_tx_mgmt[QDF_NBUF_TX_PKT_TXRX] -
220  		  nbuf_tx_mgmt[QDF_NBUF_TX_PKT_HTT],
221  		  nbuf_tx_mgmt[QDF_NBUF_TX_PKT_HTT] -
222  		  nbuf_tx_mgmt[QDF_NBUF_TX_PKT_HTC],
223  		  nbuf_tx_mgmt[QDF_NBUF_TX_PKT_HTC] -
224  		  nbuf_tx_mgmt[QDF_NBUF_TX_PKT_HIF],
225  		  nbuf_tx_mgmt[QDF_NBUF_TX_PKT_HIF] -
226  		  nbuf_tx_mgmt[QDF_NBUF_TX_PKT_CE],
227  		  nbuf_tx_mgmt[QDF_NBUF_TX_PKT_CE] -
228  		  nbuf_tx_mgmt[QDF_NBUF_TX_PKT_FREE],
229  		  nbuf_tx_mgmt[QDF_NBUF_TX_PKT_FREE]);
230  }
231  qdf_export_symbol(qdf_nbuf_tx_desc_count_display);
232  
233  /**
234   * qdf_nbuf_tx_desc_count_update() - Updates the layer packet counter
235   * @packet_type   : packet type either mgmt/data
236   * @current_state : layer at which the packet currently present
237   *
238   * Return: none
239   */
qdf_nbuf_tx_desc_count_update(uint8_t packet_type,uint8_t current_state)240  static inline void qdf_nbuf_tx_desc_count_update(uint8_t packet_type,
241  			uint8_t current_state)
242  {
243  	switch (packet_type) {
244  	case QDF_NBUF_TX_PKT_MGMT_TRACK:
245  		nbuf_tx_mgmt[current_state]++;
246  		break;
247  	case QDF_NBUF_TX_PKT_DATA_TRACK:
248  		nbuf_tx_data[current_state]++;
249  		break;
250  	default:
251  		break;
252  	}
253  }
254  
qdf_nbuf_tx_desc_count_clear(void)255  void qdf_nbuf_tx_desc_count_clear(void)
256  {
257  	memset(nbuf_tx_mgmt, 0, sizeof(nbuf_tx_mgmt));
258  	memset(nbuf_tx_data, 0, sizeof(nbuf_tx_data));
259  }
260  qdf_export_symbol(qdf_nbuf_tx_desc_count_clear);
261  
qdf_nbuf_set_state(qdf_nbuf_t nbuf,uint8_t current_state)262  void qdf_nbuf_set_state(qdf_nbuf_t nbuf, uint8_t current_state)
263  {
264  	/*
265  	 * Only Mgmt, Data Packets are tracked. WMI messages
266  	 * such as scan commands are not tracked
267  	 */
268  	uint8_t packet_type;
269  
270  	packet_type = QDF_NBUF_CB_TX_PACKET_TRACK(nbuf);
271  
272  	if ((packet_type != QDF_NBUF_TX_PKT_DATA_TRACK) &&
273  		(packet_type != QDF_NBUF_TX_PKT_MGMT_TRACK)) {
274  		return;
275  	}
276  	QDF_NBUF_CB_TX_PACKET_STATE(nbuf) = current_state;
277  	qdf_nbuf_tx_desc_count_update(packet_type,
278  					current_state);
279  }
280  qdf_export_symbol(qdf_nbuf_set_state);
281  
282  #ifdef FEATURE_NBUFF_REPLENISH_TIMER
283  /**
284   * __qdf_nbuf_start_replenish_timer() - Start alloc fail replenish timer
285   *
286   * This function starts the alloc fail replenish timer.
287   *
288   * Return: void
289   */
__qdf_nbuf_start_replenish_timer(void)290  static inline void __qdf_nbuf_start_replenish_timer(void)
291  {
292  	qdf_atomic_inc(&alloc_track_timer.alloc_fail_cnt);
293  	if (qdf_mc_timer_get_current_state(&alloc_track_timer.track_timer) !=
294  	    QDF_TIMER_STATE_RUNNING)
295  		qdf_mc_timer_start(&alloc_track_timer.track_timer,
296  				   QDF_NBUF_ALLOC_EXPIRE_TIMER_MS);
297  }
298  
299  /**
300   * __qdf_nbuf_stop_replenish_timer() - Stop alloc fail replenish timer
301   *
302   * This function stops the alloc fail replenish timer.
303   *
304   * Return: void
305   */
__qdf_nbuf_stop_replenish_timer(void)306  static inline void __qdf_nbuf_stop_replenish_timer(void)
307  {
308  	if (qdf_atomic_read(&alloc_track_timer.alloc_fail_cnt) == 0)
309  		return;
310  
311  	qdf_atomic_set(&alloc_track_timer.alloc_fail_cnt, 0);
312  	if (qdf_mc_timer_get_current_state(&alloc_track_timer.track_timer) ==
313  	    QDF_TIMER_STATE_RUNNING)
314  		qdf_mc_timer_stop(&alloc_track_timer.track_timer);
315  }
316  
317  /**
318   * qdf_replenish_expire_handler() - Replenish expire handler
319   * @arg: unused callback argument
320   *
321   * This function triggers when the alloc fail replenish timer expires.
322   *
323   * Return: void
324   */
qdf_replenish_expire_handler(void * arg)325  static void qdf_replenish_expire_handler(void *arg)
326  {
327  	if (qdf_atomic_read(&alloc_track_timer.alloc_fail_cnt) >
328  	    QDF_NBUF_ALLOC_EXPIRE_CNT_THRESHOLD) {
329  		qdf_print("ERROR: NBUF allocation timer expired Fail count %d",
330  			  qdf_atomic_read(&alloc_track_timer.alloc_fail_cnt));
331  
332  		/* Error handling here */
333  	}
334  }
335  
__qdf_nbuf_init_replenish_timer(void)336  void __qdf_nbuf_init_replenish_timer(void)
337  {
338  	qdf_mc_timer_init(&alloc_track_timer.track_timer, QDF_TIMER_TYPE_SW,
339  			  qdf_replenish_expire_handler, NULL);
340  }
341  
__qdf_nbuf_deinit_replenish_timer(void)342  void __qdf_nbuf_deinit_replenish_timer(void)
343  {
344  	__qdf_nbuf_stop_replenish_timer();
345  	qdf_mc_timer_destroy(&alloc_track_timer.track_timer);
346  }
347  
qdf_nbuf_stop_replenish_timer(void)348  void qdf_nbuf_stop_replenish_timer(void)
349  {
350  	__qdf_nbuf_stop_replenish_timer();
351  }
352  #else
353  
__qdf_nbuf_start_replenish_timer(void)354  static inline void __qdf_nbuf_start_replenish_timer(void) {}
__qdf_nbuf_stop_replenish_timer(void)355  static inline void __qdf_nbuf_stop_replenish_timer(void) {}
qdf_nbuf_stop_replenish_timer(void)356  void qdf_nbuf_stop_replenish_timer(void)
357  {
358  }
359  #endif
360  
361  /* globals do not need to be initialized to NULL/0 */
362  qdf_nbuf_trace_update_t qdf_trace_update_cb;
363  qdf_nbuf_free_t nbuf_free_cb;
364  
365  #ifdef QDF_NBUF_GLOBAL_COUNT
366  
__qdf_nbuf_count_get(void)367  int __qdf_nbuf_count_get(void)
368  {
369  	return qdf_atomic_read(&nbuf_count);
370  }
371  qdf_export_symbol(__qdf_nbuf_count_get);
372  
__qdf_nbuf_count_inc(qdf_nbuf_t nbuf)373  void __qdf_nbuf_count_inc(qdf_nbuf_t nbuf)
374  {
375  	int num_nbuf = 1;
376  	qdf_nbuf_t ext_list;
377  
378  	if (qdf_likely(is_initial_mem_debug_disabled))
379  		return;
380  
381  	ext_list = qdf_nbuf_get_ext_list(nbuf);
382  
383  	/* Take care to account for frag_list */
384  	while (ext_list) {
385  		++num_nbuf;
386  		ext_list = qdf_nbuf_queue_next(ext_list);
387  	}
388  
389  	qdf_atomic_add(num_nbuf, &nbuf_count);
390  }
391  qdf_export_symbol(__qdf_nbuf_count_inc);
392  
__qdf_nbuf_count_dec(__qdf_nbuf_t nbuf)393  void __qdf_nbuf_count_dec(__qdf_nbuf_t nbuf)
394  {
395  	qdf_nbuf_t ext_list;
396  	int num_nbuf;
397  
398  	if (qdf_likely(is_initial_mem_debug_disabled))
399  		return;
400  
401  	if (qdf_nbuf_get_users(nbuf) > 1)
402  		return;
403  
404  	num_nbuf = 1;
405  
406  	/* Take care to account for frag_list */
407  	ext_list = qdf_nbuf_get_ext_list(nbuf);
408  	while (ext_list) {
409  		if (qdf_nbuf_get_users(ext_list) == 1)
410  			++num_nbuf;
411  		ext_list = qdf_nbuf_queue_next(ext_list);
412  	}
413  
414  	qdf_atomic_sub(num_nbuf, &nbuf_count);
415  }
416  qdf_export_symbol(__qdf_nbuf_count_dec);
417  #endif
418  
419  #ifdef NBUF_FRAG_MEMORY_DEBUG
qdf_nbuf_frag_count_inc(qdf_nbuf_t nbuf)420  void qdf_nbuf_frag_count_inc(qdf_nbuf_t nbuf)
421  {
422  	qdf_nbuf_t ext_list;
423  	uint32_t num_nr_frags;
424  	uint32_t total_num_nr_frags;
425  
426  	if (qdf_likely(is_initial_mem_debug_disabled))
427  		return;
428  
429  	num_nr_frags = qdf_nbuf_get_nr_frags(nbuf);
430  	qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
431  
432  	total_num_nr_frags = num_nr_frags;
433  
434  	/* Take into account the frags attached to frag_list */
435  	ext_list = qdf_nbuf_get_ext_list(nbuf);
436  	while (ext_list) {
437  		num_nr_frags = qdf_nbuf_get_nr_frags(ext_list);
438  		qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
439  		total_num_nr_frags += num_nr_frags;
440  		ext_list = qdf_nbuf_queue_next(ext_list);
441  	}
442  
443  	qdf_frag_count_inc(total_num_nr_frags);
444  }
445  
446  qdf_export_symbol(qdf_nbuf_frag_count_inc);
447  
qdf_nbuf_frag_count_dec(qdf_nbuf_t nbuf)448  void  qdf_nbuf_frag_count_dec(qdf_nbuf_t nbuf)
449  {
450  	qdf_nbuf_t ext_list;
451  	uint32_t num_nr_frags;
452  	uint32_t total_num_nr_frags;
453  
454  	if (qdf_likely(is_initial_mem_debug_disabled))
455  		return;
456  
457  	if (qdf_nbuf_get_users(nbuf) > 1)
458  		return;
459  
460  	num_nr_frags = qdf_nbuf_get_nr_frags(nbuf);
461  	qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
462  
463  	total_num_nr_frags = num_nr_frags;
464  
465  	/* Take into account the frags attached to frag_list */
466  	ext_list = qdf_nbuf_get_ext_list(nbuf);
467  	while (ext_list) {
468  		if (qdf_nbuf_get_users(ext_list) == 1) {
469  			num_nr_frags = qdf_nbuf_get_nr_frags(ext_list);
470  			qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
471  			total_num_nr_frags += num_nr_frags;
472  		}
473  		ext_list = qdf_nbuf_queue_next(ext_list);
474  	}
475  
476  	qdf_frag_count_dec(total_num_nr_frags);
477  }
478  
479  qdf_export_symbol(qdf_nbuf_frag_count_dec);
480  
481  #endif
482  
483  static inline void
qdf_nbuf_set_defaults(struct sk_buff * skb,int align,int reserve)484  qdf_nbuf_set_defaults(struct sk_buff *skb, int align, int reserve)
485  {
486  	unsigned long offset;
487  
488  	memset(skb->cb, 0x0, sizeof(skb->cb));
489  	skb->dev = NULL;
490  
491  	/*
492  	 * The default is for netbuf fragments to be interpreted
493  	 * as wordstreams rather than bytestreams.
494  	 */
495  	QDF_NBUF_CB_TX_EXTRA_FRAG_WORDSTR_EFRAG(skb) = 1;
496  	QDF_NBUF_CB_TX_EXTRA_FRAG_WORDSTR_NBUF(skb) = 1;
497  
498  	/*
499  	 * XXX:how about we reserve first then align
500  	 * Align & make sure that the tail & data are adjusted properly
501  	 */
502  
503  	if (align) {
504  		offset = ((unsigned long)skb->data) % align;
505  		if (offset)
506  			skb_reserve(skb, align - offset);
507  	}
508  
509  	/*
510  	 * NOTE:alloc doesn't take responsibility if reserve unaligns the data
511  	 * pointer
512  	 */
513  	skb_reserve(skb, reserve);
514  	qdf_nbuf_count_inc(skb);
515  }
516  
517  #if defined(CONFIG_WIFI_EMULATION_WIFI_3_0) && defined(BUILD_X86) && \
518  	!defined(QCA_WIFI_QCN9000)
__qdf_nbuf_alloc(qdf_device_t osdev,size_t size,int reserve,int align,int prio,const char * func,uint32_t line)519  struct sk_buff *__qdf_nbuf_alloc(qdf_device_t osdev, size_t size, int reserve,
520  				 int align, int prio, const char *func,
521  				 uint32_t line)
522  {
523  	struct sk_buff *skb;
524  	uint32_t lowmem_alloc_tries = 0;
525  
526  	if (align)
527  		size += (align - 1);
528  
529  realloc:
530  	skb = dev_alloc_skb(size);
531  
532  	if (skb)
533  		goto skb_alloc;
534  
535  	skb = pld_nbuf_pre_alloc(size);
536  
537  	if (!skb) {
538  		qdf_rl_nofl_err("NBUF alloc failed %zuB @ %s:%d",
539  				size, func, line);
540  		return NULL;
541  	}
542  
543  skb_alloc:
544  	/* Hawkeye M2M emulation cannot handle memory addresses below 0x50000040
545  	 * Though we are trying to reserve low memory upfront to prevent this,
546  	 * we sometimes see SKBs allocated from low memory.
547  	 */
548  	if (virt_to_phys(qdf_nbuf_data(skb)) < 0x50000040) {
549  		lowmem_alloc_tries++;
550  		if (lowmem_alloc_tries > 100) {
551  			qdf_nofl_err("NBUF alloc failed %zuB @ %s:%d",
552  				     size, func, line);
553  			return NULL;
554  		} else {
555  			/* Not freeing to make sure it
556  			 * will not get allocated again
557  			 */
558  			goto realloc;
559  		}
560  	}
561  
562  	qdf_nbuf_set_defaults(skb, align, reserve);
563  
564  	return skb;
565  }
566  #else
567  
568  #ifdef QCA_DP_NBUF_FAST_RECYCLE_CHECK
__qdf_nbuf_alloc(qdf_device_t osdev,size_t size,int reserve,int align,int prio,const char * func,uint32_t line)569  struct sk_buff *__qdf_nbuf_alloc(qdf_device_t osdev, size_t size, int reserve,
570  				 int align, int prio, const char *func,
571  				 uint32_t line)
572  {
573  	return __qdf_nbuf_frag_alloc(osdev, size, reserve, align, prio, func,
574  				     line);
575  }
576  
577  #else
__qdf_nbuf_alloc(qdf_device_t osdev,size_t size,int reserve,int align,int prio,const char * func,uint32_t line)578  struct sk_buff *__qdf_nbuf_alloc(qdf_device_t osdev, size_t size, int reserve,
579  				 int align, int prio, const char *func,
580  				 uint32_t line)
581  {
582  	struct sk_buff *skb;
583  	int flags = GFP_KERNEL;
584  
585  	if (align)
586  		size += (align - 1);
587  
588  	if (in_interrupt() || irqs_disabled() || in_atomic())
589  		flags = GFP_ATOMIC;
590  
591  	skb =  alloc_skb(size, flags);
592  
593  	if (skb)
594  		goto skb_alloc;
595  
596  	skb = pld_nbuf_pre_alloc(size);
597  
598  	if (!skb) {
599  		qdf_rl_nofl_err("NBUF alloc failed %zuB @ %s:%d",
600  				size, func, line);
601  		__qdf_nbuf_start_replenish_timer();
602  		return NULL;
603  	}
604  
605  	__qdf_nbuf_stop_replenish_timer();
606  
607  skb_alloc:
608  	qdf_nbuf_set_defaults(skb, align, reserve);
609  
610  	return skb;
611  }
612  #endif
613  
614  #endif
615  qdf_export_symbol(__qdf_nbuf_alloc);
616  
__qdf_nbuf_frag_alloc(qdf_device_t osdev,size_t size,int reserve,int align,int prio,const char * func,uint32_t line)617  struct sk_buff *__qdf_nbuf_frag_alloc(qdf_device_t osdev, size_t size,
618  				      int reserve, int align, int prio,
619  				      const char *func, uint32_t line)
620  {
621  	struct sk_buff *skb;
622  	int flags = GFP_KERNEL & ~__GFP_DIRECT_RECLAIM;
623  	bool atomic = false;
624  
625  	if (align)
626  		size += (align - 1);
627  
628  	if (in_interrupt() || irqs_disabled() || in_atomic()) {
629  		atomic = true;
630  		flags = GFP_ATOMIC;
631  #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
632  		/*
633  		 * Observed that kcompactd burns out CPU to make order-3 page.
634  		 *__netdev_alloc_skb has 4k page fallback option just in case of
635  		 * failing high order page allocation so we don't need to be
636  		 * hard. Make kcompactd rest in piece.
637  		 */
638  		flags = flags & ~__GFP_KSWAPD_RECLAIM;
639  #endif
640  	}
641  
642  	skb = __netdev_alloc_skb(NULL, size, flags);
643  	if (skb)
644  		goto skb_alloc;
645  
646  	/* 32k page frag alloc failed, try page slab allocation */
647  	if (likely(!atomic))
648  		flags |= __GFP_DIRECT_RECLAIM;
649  
650  	skb = alloc_skb(size, flags);
651  	if (skb)
652  		goto skb_alloc;
653  
654  	skb = pld_nbuf_pre_alloc(size);
655  
656  	if (!skb) {
657  		qdf_rl_nofl_err("NBUF alloc failed %zuB @ %s:%d",
658  				size, func, line);
659  		__qdf_nbuf_start_replenish_timer();
660  		return NULL;
661  	}
662  
663  	__qdf_nbuf_stop_replenish_timer();
664  
665  skb_alloc:
666  	qdf_nbuf_set_defaults(skb, align, reserve);
667  
668  	return skb;
669  }
670  
671  qdf_export_symbol(__qdf_nbuf_frag_alloc);
672  
__qdf_nbuf_alloc_no_recycler(size_t size,int reserve,int align,const char * func,uint32_t line)673  __qdf_nbuf_t __qdf_nbuf_alloc_no_recycler(size_t size, int reserve, int align,
674  					  const char *func, uint32_t line)
675  {
676  	qdf_nbuf_t nbuf;
677  	unsigned long offset;
678  
679  	if (align)
680  		size += (align - 1);
681  
682  	nbuf = alloc_skb(size, GFP_ATOMIC);
683  	if (!nbuf)
684  		goto ret_nbuf;
685  
686  	memset(nbuf->cb, 0x0, sizeof(nbuf->cb));
687  
688  	skb_reserve(nbuf, reserve);
689  
690  	if (align) {
691  		offset = ((unsigned long)nbuf->data) % align;
692  		if (offset)
693  			skb_reserve(nbuf, align - offset);
694  	}
695  
696  	qdf_nbuf_count_inc(nbuf);
697  
698  ret_nbuf:
699  	return nbuf;
700  }
701  
702  qdf_export_symbol(__qdf_nbuf_alloc_no_recycler);
703  
__qdf_nbuf_free(struct sk_buff * skb)704  void __qdf_nbuf_free(struct sk_buff *skb)
705  {
706  	if (pld_nbuf_pre_alloc_free(skb))
707  		return;
708  
709  	qdf_nbuf_frag_count_dec(skb);
710  
711  	qdf_nbuf_count_dec(skb);
712  	if (nbuf_free_cb)
713  		nbuf_free_cb(skb);
714  	else
715  		dev_kfree_skb_any(skb);
716  }
717  
718  qdf_export_symbol(__qdf_nbuf_free);
719  
__qdf_nbuf_clone(__qdf_nbuf_t skb)720  __qdf_nbuf_t __qdf_nbuf_clone(__qdf_nbuf_t skb)
721  {
722  	qdf_nbuf_t skb_new = NULL;
723  
724  	skb_new = skb_clone(skb, GFP_ATOMIC);
725  	if (skb_new) {
726  		qdf_nbuf_frag_count_inc(skb_new);
727  		qdf_nbuf_count_inc(skb_new);
728  	}
729  	return skb_new;
730  }
731  
732  qdf_export_symbol(__qdf_nbuf_clone);
733  
734  struct sk_buff *
__qdf_nbuf_page_frag_alloc(qdf_device_t osdev,size_t size,int reserve,int align,__qdf_frag_cache_t * pf_cache,const char * func,uint32_t line)735  __qdf_nbuf_page_frag_alloc(qdf_device_t osdev, size_t size, int reserve,
736  			   int align, __qdf_frag_cache_t *pf_cache,
737  			   const char *func, uint32_t line)
738  {
739  	struct sk_buff *skb;
740  	qdf_frag_t frag_data;
741  	size_t orig_size = size;
742  	int flags = GFP_KERNEL;
743  
744  	if (align)
745  		size += (align - 1);
746  
747  	size += NET_SKB_PAD;
748  	size += SKB_DATA_ALIGN(sizeof(struct skb_shared_info));
749  	size = SKB_DATA_ALIGN(size);
750  
751  	if (in_interrupt() || irqs_disabled() || in_atomic())
752  		flags = GFP_ATOMIC;
753  
754  	frag_data = page_frag_alloc(pf_cache, size, flags);
755  	if (!frag_data) {
756  		qdf_rl_nofl_err("page frag alloc failed %zuB @ %s:%d",
757  				size, func, line);
758  		return __qdf_nbuf_alloc(osdev, orig_size, reserve, align, 0,
759  					func, line);
760  	}
761  
762  	skb = build_skb(frag_data, size);
763  	if (skb) {
764  		skb_reserve(skb, NET_SKB_PAD);
765  		goto skb_alloc;
766  	}
767  
768  	/* Free the data allocated from pf_cache */
769  	page_frag_free(frag_data);
770  
771  	size = orig_size + align - 1;
772  
773  	skb = pld_nbuf_pre_alloc(size);
774  	if (!skb) {
775  		qdf_rl_nofl_err("NBUF alloc failed %zuB @ %s:%d",
776  				size, func, line);
777  		__qdf_nbuf_start_replenish_timer();
778  		return NULL;
779  	}
780  
781  	__qdf_nbuf_stop_replenish_timer();
782  
783  skb_alloc:
784  	qdf_nbuf_set_defaults(skb, align, reserve);
785  
786  	return skb;
787  }
788  
789  qdf_export_symbol(__qdf_nbuf_page_frag_alloc);
790  
791  #ifdef QCA_DP_TX_NBUF_LIST_FREE
792  void
__qdf_nbuf_dev_kfree_list(__qdf_nbuf_queue_head_t * nbuf_queue_head)793  __qdf_nbuf_dev_kfree_list(__qdf_nbuf_queue_head_t *nbuf_queue_head)
794  {
795  	dev_kfree_skb_list_fast(nbuf_queue_head);
796  }
797  #else
798  void
__qdf_nbuf_dev_kfree_list(__qdf_nbuf_queue_head_t * nbuf_queue_head)799  __qdf_nbuf_dev_kfree_list(__qdf_nbuf_queue_head_t *nbuf_queue_head)
800  {
801  }
802  #endif
803  
804  qdf_export_symbol(__qdf_nbuf_dev_kfree_list);
805  
806  #ifdef NBUF_MEMORY_DEBUG
807  struct qdf_nbuf_event {
808  	qdf_nbuf_t nbuf;
809  	char func[QDF_MEM_FUNC_NAME_SIZE];
810  	uint32_t line;
811  	enum qdf_nbuf_event_type type;
812  	uint64_t timestamp;
813  	qdf_dma_addr_t iova;
814  };
815  
816  #ifndef QDF_NBUF_HISTORY_SIZE
817  #define QDF_NBUF_HISTORY_SIZE 4096
818  #endif
819  static qdf_atomic_t qdf_nbuf_history_index;
820  static struct qdf_nbuf_event qdf_nbuf_history[QDF_NBUF_HISTORY_SIZE];
821  
qdf_nbuf_ssr_register_region(void)822  void qdf_nbuf_ssr_register_region(void)
823  {
824  	qdf_ssr_driver_dump_register_region("qdf_nbuf_history",
825  					    qdf_nbuf_history,
826  					    sizeof(qdf_nbuf_history));
827  }
828  
829  qdf_export_symbol(qdf_nbuf_ssr_register_region);
830  
qdf_nbuf_ssr_unregister_region(void)831  void qdf_nbuf_ssr_unregister_region(void)
832  {
833  	qdf_ssr_driver_dump_unregister_region("qdf_nbuf_history");
834  }
835  
836  qdf_export_symbol(qdf_nbuf_ssr_unregister_region);
837  
qdf_nbuf_circular_index_next(qdf_atomic_t * index,int size)838  static int32_t qdf_nbuf_circular_index_next(qdf_atomic_t *index, int size)
839  {
840  	int32_t next = qdf_atomic_inc_return(index);
841  
842  	if (next == size)
843  		qdf_atomic_sub(size, index);
844  
845  	return next % size;
846  }
847  
848  void
qdf_nbuf_history_add(qdf_nbuf_t nbuf,const char * func,uint32_t line,enum qdf_nbuf_event_type type)849  qdf_nbuf_history_add(qdf_nbuf_t nbuf, const char *func, uint32_t line,
850  		     enum qdf_nbuf_event_type type)
851  {
852  	int32_t idx = qdf_nbuf_circular_index_next(&qdf_nbuf_history_index,
853  						   QDF_NBUF_HISTORY_SIZE);
854  	struct qdf_nbuf_event *event = &qdf_nbuf_history[idx];
855  
856  	if (qdf_atomic_read(&smmu_crashed)) {
857  		g_histroy_add_drop++;
858  		return;
859  	}
860  
861  	event->nbuf = nbuf;
862  	qdf_str_lcopy(event->func, func, QDF_MEM_FUNC_NAME_SIZE);
863  	event->line = line;
864  	event->type = type;
865  	event->timestamp = qdf_get_log_timestamp();
866  	if (type == QDF_NBUF_MAP || type == QDF_NBUF_UNMAP ||
867  	    type == QDF_NBUF_SMMU_MAP || type == QDF_NBUF_SMMU_UNMAP)
868  		event->iova = QDF_NBUF_CB_PADDR(nbuf);
869  	else
870  		event->iova = 0;
871  }
872  
qdf_set_smmu_fault_state(bool smmu_fault_state)873  void qdf_set_smmu_fault_state(bool smmu_fault_state)
874  {
875  	qdf_atomic_set(&smmu_crashed, smmu_fault_state);
876  	if (!smmu_fault_state)
877  		g_histroy_add_drop = 0;
878  }
879  qdf_export_symbol(qdf_set_smmu_fault_state);
880  #endif /* NBUF_MEMORY_DEBUG */
881  
882  #ifdef NBUF_SMMU_MAP_UNMAP_DEBUG
883  #define qdf_nbuf_smmu_map_tracker_bits 11 /* 2048 buckets */
884  qdf_tracker_declare(qdf_nbuf_smmu_map_tracker, qdf_nbuf_smmu_map_tracker_bits,
885  		    "nbuf map-no-unmap events", "nbuf map", "nbuf unmap");
886  
qdf_nbuf_smmu_map_tracking_init(void)887  static void qdf_nbuf_smmu_map_tracking_init(void)
888  {
889  	qdf_tracker_init(&qdf_nbuf_smmu_map_tracker);
890  }
891  
qdf_nbuf_smmu_map_tracking_deinit(void)892  static void qdf_nbuf_smmu_map_tracking_deinit(void)
893  {
894  	qdf_tracker_deinit(&qdf_nbuf_smmu_map_tracker);
895  }
896  
897  static QDF_STATUS
qdf_nbuf_track_smmu_map(qdf_nbuf_t nbuf,const char * func,uint32_t line)898  qdf_nbuf_track_smmu_map(qdf_nbuf_t nbuf, const char *func, uint32_t line)
899  {
900  	if (is_initial_mem_debug_disabled)
901  		return QDF_STATUS_SUCCESS;
902  
903  	return qdf_tracker_track(&qdf_nbuf_smmu_map_tracker, nbuf, func, line);
904  }
905  
906  static void
qdf_nbuf_untrack_smmu_map(qdf_nbuf_t nbuf,const char * func,uint32_t line)907  qdf_nbuf_untrack_smmu_map(qdf_nbuf_t nbuf, const char *func, uint32_t line)
908  {
909  	if (is_initial_mem_debug_disabled)
910  		return;
911  
912  	qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_SMMU_UNMAP);
913  	qdf_tracker_untrack(&qdf_nbuf_smmu_map_tracker, nbuf, func, line);
914  }
915  
qdf_nbuf_map_check_for_smmu_leaks(void)916  void qdf_nbuf_map_check_for_smmu_leaks(void)
917  {
918  	qdf_tracker_check_for_leaks(&qdf_nbuf_smmu_map_tracker);
919  }
920  
921  #ifdef IPA_OFFLOAD
qdf_nbuf_smmu_map_debug(qdf_nbuf_t nbuf,uint8_t hdl,uint8_t num_buffers,qdf_mem_info_t * info,const char * func,uint32_t line)922  QDF_STATUS qdf_nbuf_smmu_map_debug(qdf_nbuf_t nbuf,
923  				   uint8_t hdl,
924  				   uint8_t num_buffers,
925  				   qdf_mem_info_t *info,
926  				   const char *func,
927  				   uint32_t line)
928  {
929  	QDF_STATUS status;
930  
931  	status = qdf_nbuf_track_smmu_map(nbuf, func, line);
932  	if (QDF_IS_STATUS_ERROR(status))
933  		return status;
934  
935  	status = __qdf_ipa_wdi_create_smmu_mapping(hdl, num_buffers, info);
936  
937  	if (QDF_IS_STATUS_ERROR(status)) {
938  		qdf_nbuf_untrack_smmu_map(nbuf, func, line);
939  	} else {
940  		if (!is_initial_mem_debug_disabled)
941  			qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_MAP);
942  		qdf_net_buf_debug_update_smmu_map_node(nbuf, info->iova,
943  						       info->pa, func, line);
944  	}
945  
946  	return status;
947  }
948  
949  qdf_export_symbol(qdf_nbuf_smmu_map_debug);
950  
qdf_nbuf_smmu_unmap_debug(qdf_nbuf_t nbuf,uint8_t hdl,uint8_t num_buffers,qdf_mem_info_t * info,const char * func,uint32_t line)951  QDF_STATUS qdf_nbuf_smmu_unmap_debug(qdf_nbuf_t nbuf,
952  				     uint8_t hdl,
953  				     uint8_t num_buffers,
954  				     qdf_mem_info_t *info,
955  				     const char *func,
956  				     uint32_t line)
957  {
958  	QDF_STATUS status;
959  
960  	qdf_nbuf_untrack_smmu_map(nbuf, func, line);
961  	status = __qdf_ipa_wdi_release_smmu_mapping(hdl, num_buffers, info);
962  	qdf_net_buf_debug_update_smmu_unmap_node(nbuf, info->iova,
963  						 info->pa, func, line);
964  	return status;
965  }
966  
967  qdf_export_symbol(qdf_nbuf_smmu_unmap_debug);
968  #endif /* IPA_OFFLOAD */
969  
qdf_nbuf_panic_on_free_if_smmu_mapped(qdf_nbuf_t nbuf,const char * func,uint32_t line)970  static void qdf_nbuf_panic_on_free_if_smmu_mapped(qdf_nbuf_t nbuf,
971  						  const char *func,
972  						  uint32_t line)
973  {
974  	char map_func[QDF_TRACKER_FUNC_SIZE];
975  	uint32_t map_line;
976  
977  	if (!qdf_tracker_lookup(&qdf_nbuf_smmu_map_tracker, nbuf,
978  				&map_func, &map_line))
979  		return;
980  
981  	QDF_MEMDEBUG_PANIC("Nbuf freed @ %s:%u while mapped from %s:%u",
982  			   func, line, map_func, map_line);
983  }
984  
qdf_net_buf_update_smmu_params(QDF_NBUF_TRACK * p_node)985  static inline void qdf_net_buf_update_smmu_params(QDF_NBUF_TRACK *p_node)
986  {
987  	p_node->smmu_unmap_line_num = 0;
988  	p_node->is_nbuf_smmu_mapped = false;
989  	p_node->smmu_map_line_num = 0;
990  	p_node->smmu_map_func_name[0] = '\0';
991  	p_node->smmu_unmap_func_name[0] = '\0';
992  	p_node->smmu_unmap_iova_addr = 0;
993  	p_node->smmu_unmap_pa_addr = 0;
994  	p_node->smmu_map_iova_addr = 0;
995  	p_node->smmu_map_pa_addr = 0;
996  }
997  #else /* !NBUF_SMMU_MAP_UNMAP_DEBUG */
998  #ifdef NBUF_MEMORY_DEBUG
qdf_nbuf_smmu_map_tracking_init(void)999  static void qdf_nbuf_smmu_map_tracking_init(void)
1000  {
1001  }
1002  
qdf_nbuf_smmu_map_tracking_deinit(void)1003  static void qdf_nbuf_smmu_map_tracking_deinit(void)
1004  {
1005  }
1006  
qdf_nbuf_panic_on_free_if_smmu_mapped(qdf_nbuf_t nbuf,const char * func,uint32_t line)1007  static void qdf_nbuf_panic_on_free_if_smmu_mapped(qdf_nbuf_t nbuf,
1008  						  const char *func,
1009  						  uint32_t line)
1010  {
1011  }
1012  
qdf_net_buf_update_smmu_params(QDF_NBUF_TRACK * p_node)1013  static inline void qdf_net_buf_update_smmu_params(QDF_NBUF_TRACK *p_node)
1014  {
1015  }
1016  #endif /* NBUF_MEMORY_DEBUG */
1017  
1018  #ifdef IPA_OFFLOAD
qdf_nbuf_smmu_map_debug(qdf_nbuf_t nbuf,uint8_t hdl,uint8_t num_buffers,qdf_mem_info_t * info,const char * func,uint32_t line)1019  QDF_STATUS qdf_nbuf_smmu_map_debug(qdf_nbuf_t nbuf,
1020  				   uint8_t hdl,
1021  				   uint8_t num_buffers,
1022  				   qdf_mem_info_t *info,
1023  				   const char *func,
1024  				   uint32_t line)
1025  {
1026  	return  __qdf_ipa_wdi_create_smmu_mapping(hdl, num_buffers, info);
1027  }
1028  
1029  qdf_export_symbol(qdf_nbuf_smmu_map_debug);
1030  
qdf_nbuf_smmu_unmap_debug(qdf_nbuf_t nbuf,uint8_t hdl,uint8_t num_buffers,qdf_mem_info_t * info,const char * func,uint32_t line)1031  QDF_STATUS qdf_nbuf_smmu_unmap_debug(qdf_nbuf_t nbuf,
1032  				     uint8_t hdl,
1033  				     uint8_t num_buffers,
1034  				     qdf_mem_info_t *info,
1035  				     const char *func,
1036  				     uint32_t line)
1037  {
1038  	return __qdf_ipa_wdi_release_smmu_mapping(hdl, num_buffers, info);
1039  }
1040  
1041  qdf_export_symbol(qdf_nbuf_smmu_unmap_debug);
1042  #endif /* IPA_OFFLOAD */
1043  #endif /* NBUF_SMMU_MAP_UNMAP_DEBUG */
1044  
1045  #ifdef NBUF_MAP_UNMAP_DEBUG
1046  #define qdf_nbuf_map_tracker_bits 11 /* 2048 buckets */
1047  qdf_tracker_declare(qdf_nbuf_map_tracker, qdf_nbuf_map_tracker_bits,
1048  		    "nbuf map-no-unmap events", "nbuf map", "nbuf unmap");
1049  
qdf_nbuf_map_tracking_init(void)1050  static void qdf_nbuf_map_tracking_init(void)
1051  {
1052  	qdf_tracker_init(&qdf_nbuf_map_tracker);
1053  }
1054  
qdf_nbuf_map_tracking_deinit(void)1055  static void qdf_nbuf_map_tracking_deinit(void)
1056  {
1057  	qdf_tracker_deinit(&qdf_nbuf_map_tracker);
1058  }
1059  
1060  static QDF_STATUS
qdf_nbuf_track_map(qdf_nbuf_t nbuf,const char * func,uint32_t line)1061  qdf_nbuf_track_map(qdf_nbuf_t nbuf, const char *func, uint32_t line)
1062  {
1063  	if (is_initial_mem_debug_disabled)
1064  		return QDF_STATUS_SUCCESS;
1065  
1066  	return qdf_tracker_track(&qdf_nbuf_map_tracker, nbuf, func, line);
1067  }
1068  
1069  static void
qdf_nbuf_untrack_map(qdf_nbuf_t nbuf,const char * func,uint32_t line)1070  qdf_nbuf_untrack_map(qdf_nbuf_t nbuf, const char *func, uint32_t line)
1071  {
1072  	if (is_initial_mem_debug_disabled)
1073  		return;
1074  
1075  	qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_UNMAP);
1076  	qdf_tracker_untrack(&qdf_nbuf_map_tracker, nbuf, func, line);
1077  }
1078  
qdf_nbuf_map_check_for_leaks(void)1079  void qdf_nbuf_map_check_for_leaks(void)
1080  {
1081  	qdf_tracker_check_for_leaks(&qdf_nbuf_map_tracker);
1082  }
1083  
qdf_nbuf_map_debug(qdf_device_t osdev,qdf_nbuf_t buf,qdf_dma_dir_t dir,const char * func,uint32_t line)1084  QDF_STATUS qdf_nbuf_map_debug(qdf_device_t osdev,
1085  			      qdf_nbuf_t buf,
1086  			      qdf_dma_dir_t dir,
1087  			      const char *func,
1088  			      uint32_t line)
1089  {
1090  	QDF_STATUS status;
1091  
1092  	status = qdf_nbuf_track_map(buf, func, line);
1093  	if (QDF_IS_STATUS_ERROR(status))
1094  		return status;
1095  
1096  	status = __qdf_nbuf_map(osdev, buf, dir);
1097  	if (QDF_IS_STATUS_ERROR(status)) {
1098  		qdf_nbuf_untrack_map(buf, func, line);
1099  	} else {
1100  		if (!is_initial_mem_debug_disabled)
1101  			qdf_nbuf_history_add(buf, func, line, QDF_NBUF_MAP);
1102  		qdf_net_buf_debug_update_map_node(buf, func, line);
1103  	}
1104  
1105  	return status;
1106  }
1107  
1108  qdf_export_symbol(qdf_nbuf_map_debug);
1109  
qdf_nbuf_unmap_debug(qdf_device_t osdev,qdf_nbuf_t buf,qdf_dma_dir_t dir,const char * func,uint32_t line)1110  void qdf_nbuf_unmap_debug(qdf_device_t osdev,
1111  			  qdf_nbuf_t buf,
1112  			  qdf_dma_dir_t dir,
1113  			  const char *func,
1114  			  uint32_t line)
1115  {
1116  	qdf_nbuf_untrack_map(buf, func, line);
1117  	__qdf_nbuf_unmap_single(osdev, buf, dir);
1118  	qdf_net_buf_debug_update_unmap_node(buf, func, line);
1119  }
1120  
1121  qdf_export_symbol(qdf_nbuf_unmap_debug);
1122  
qdf_nbuf_map_single_debug(qdf_device_t osdev,qdf_nbuf_t buf,qdf_dma_dir_t dir,const char * func,uint32_t line)1123  QDF_STATUS qdf_nbuf_map_single_debug(qdf_device_t osdev,
1124  				     qdf_nbuf_t buf,
1125  				     qdf_dma_dir_t dir,
1126  				     const char *func,
1127  				     uint32_t line)
1128  {
1129  	QDF_STATUS status;
1130  
1131  	status = qdf_nbuf_track_map(buf, func, line);
1132  	if (QDF_IS_STATUS_ERROR(status))
1133  		return status;
1134  
1135  	status = __qdf_nbuf_map_single(osdev, buf, dir);
1136  	if (QDF_IS_STATUS_ERROR(status)) {
1137  		qdf_nbuf_untrack_map(buf, func, line);
1138  	} else {
1139  		if (!is_initial_mem_debug_disabled)
1140  			qdf_nbuf_history_add(buf, func, line, QDF_NBUF_MAP);
1141  		qdf_net_buf_debug_update_map_node(buf, func, line);
1142  	}
1143  
1144  	return status;
1145  }
1146  
1147  qdf_export_symbol(qdf_nbuf_map_single_debug);
1148  
qdf_nbuf_unmap_single_debug(qdf_device_t osdev,qdf_nbuf_t buf,qdf_dma_dir_t dir,const char * func,uint32_t line)1149  void qdf_nbuf_unmap_single_debug(qdf_device_t osdev,
1150  				 qdf_nbuf_t buf,
1151  				 qdf_dma_dir_t dir,
1152  				 const char *func,
1153  				 uint32_t line)
1154  {
1155  	qdf_nbuf_untrack_map(buf, func, line);
1156  	__qdf_nbuf_unmap_single(osdev, buf, dir);
1157  	qdf_net_buf_debug_update_unmap_node(buf, func, line);
1158  }
1159  
1160  qdf_export_symbol(qdf_nbuf_unmap_single_debug);
1161  
qdf_nbuf_map_nbytes_debug(qdf_device_t osdev,qdf_nbuf_t buf,qdf_dma_dir_t dir,int nbytes,const char * func,uint32_t line)1162  QDF_STATUS qdf_nbuf_map_nbytes_debug(qdf_device_t osdev,
1163  				     qdf_nbuf_t buf,
1164  				     qdf_dma_dir_t dir,
1165  				     int nbytes,
1166  				     const char *func,
1167  				     uint32_t line)
1168  {
1169  	QDF_STATUS status;
1170  
1171  	status = qdf_nbuf_track_map(buf, func, line);
1172  	if (QDF_IS_STATUS_ERROR(status))
1173  		return status;
1174  
1175  	status = __qdf_nbuf_map_nbytes(osdev, buf, dir, nbytes);
1176  	if (QDF_IS_STATUS_ERROR(status)) {
1177  		qdf_nbuf_untrack_map(buf, func, line);
1178  	} else {
1179  		if (!is_initial_mem_debug_disabled)
1180  			qdf_nbuf_history_add(buf, func, line, QDF_NBUF_MAP);
1181  		qdf_net_buf_debug_update_map_node(buf, func, line);
1182  	}
1183  
1184  	return status;
1185  }
1186  
1187  qdf_export_symbol(qdf_nbuf_map_nbytes_debug);
1188  
qdf_nbuf_unmap_nbytes_debug(qdf_device_t osdev,qdf_nbuf_t buf,qdf_dma_dir_t dir,int nbytes,const char * func,uint32_t line)1189  void qdf_nbuf_unmap_nbytes_debug(qdf_device_t osdev,
1190  				 qdf_nbuf_t buf,
1191  				 qdf_dma_dir_t dir,
1192  				 int nbytes,
1193  				 const char *func,
1194  				 uint32_t line)
1195  {
1196  	qdf_nbuf_untrack_map(buf, func, line);
1197  	__qdf_nbuf_unmap_nbytes(osdev, buf, dir, nbytes);
1198  	qdf_net_buf_debug_update_unmap_node(buf, func, line);
1199  }
1200  
1201  qdf_export_symbol(qdf_nbuf_unmap_nbytes_debug);
1202  
qdf_nbuf_map_nbytes_single_debug(qdf_device_t osdev,qdf_nbuf_t buf,qdf_dma_dir_t dir,int nbytes,const char * func,uint32_t line)1203  QDF_STATUS qdf_nbuf_map_nbytes_single_debug(qdf_device_t osdev,
1204  					    qdf_nbuf_t buf,
1205  					    qdf_dma_dir_t dir,
1206  					    int nbytes,
1207  					    const char *func,
1208  					    uint32_t line)
1209  {
1210  	QDF_STATUS status;
1211  
1212  	status = qdf_nbuf_track_map(buf, func, line);
1213  	if (QDF_IS_STATUS_ERROR(status))
1214  		return status;
1215  
1216  	status = __qdf_nbuf_map_nbytes_single(osdev, buf, dir, nbytes);
1217  	if (QDF_IS_STATUS_ERROR(status)) {
1218  		qdf_nbuf_untrack_map(buf, func, line);
1219  	} else {
1220  		if (!is_initial_mem_debug_disabled)
1221  			qdf_nbuf_history_add(buf, func, line, QDF_NBUF_MAP);
1222  		qdf_net_buf_debug_update_map_node(buf, func, line);
1223  	}
1224  
1225  	return status;
1226  }
1227  
1228  qdf_export_symbol(qdf_nbuf_map_nbytes_single_debug);
1229  
qdf_nbuf_unmap_nbytes_single_debug(qdf_device_t osdev,qdf_nbuf_t buf,qdf_dma_dir_t dir,int nbytes,const char * func,uint32_t line)1230  void qdf_nbuf_unmap_nbytes_single_debug(qdf_device_t osdev,
1231  					qdf_nbuf_t buf,
1232  					qdf_dma_dir_t dir,
1233  					int nbytes,
1234  					const char *func,
1235  					uint32_t line)
1236  {
1237  	qdf_nbuf_untrack_map(buf, func, line);
1238  	__qdf_nbuf_unmap_nbytes_single(osdev, buf, dir, nbytes);
1239  	qdf_net_buf_debug_update_unmap_node(buf, func, line);
1240  }
1241  
1242  qdf_export_symbol(qdf_nbuf_unmap_nbytes_single_debug);
1243  
qdf_nbuf_unmap_nbytes_single_paddr_debug(qdf_device_t osdev,qdf_nbuf_t buf,qdf_dma_addr_t phy_addr,qdf_dma_dir_t dir,int nbytes,const char * func,uint32_t line)1244  void qdf_nbuf_unmap_nbytes_single_paddr_debug(qdf_device_t osdev,
1245  					      qdf_nbuf_t buf,
1246  					      qdf_dma_addr_t phy_addr,
1247  					      qdf_dma_dir_t dir, int nbytes,
1248  					      const char *func, uint32_t line)
1249  {
1250  	qdf_nbuf_untrack_map(buf, func, line);
1251  	__qdf_record_nbuf_nbytes(__qdf_nbuf_get_end_offset(buf), dir, false);
1252  	__qdf_mem_unmap_nbytes_single(osdev, phy_addr, dir, nbytes);
1253  	qdf_net_buf_debug_update_unmap_node(buf, func, line);
1254  }
1255  
1256  qdf_export_symbol(qdf_nbuf_unmap_nbytes_single_paddr_debug);
1257  
qdf_nbuf_panic_on_free_if_mapped(qdf_nbuf_t nbuf,const char * func,uint32_t line)1258  static void qdf_nbuf_panic_on_free_if_mapped(qdf_nbuf_t nbuf,
1259  					     const char *func,
1260  					     uint32_t line)
1261  {
1262  	char map_func[QDF_TRACKER_FUNC_SIZE];
1263  	uint32_t map_line;
1264  
1265  	if (!qdf_tracker_lookup(&qdf_nbuf_map_tracker, nbuf,
1266  				&map_func, &map_line))
1267  		return;
1268  
1269  	QDF_MEMDEBUG_PANIC("Nbuf freed @ %s:%u while mapped from %s:%u",
1270  			   func, line, map_func, map_line);
1271  }
1272  #else
qdf_nbuf_map_tracking_init(void)1273  static inline void qdf_nbuf_map_tracking_init(void)
1274  {
1275  }
1276  
qdf_nbuf_map_tracking_deinit(void)1277  static inline void qdf_nbuf_map_tracking_deinit(void)
1278  {
1279  }
1280  
qdf_nbuf_panic_on_free_if_mapped(qdf_nbuf_t nbuf,const char * func,uint32_t line)1281  static inline void qdf_nbuf_panic_on_free_if_mapped(qdf_nbuf_t nbuf,
1282  						    const char *func,
1283  						    uint32_t line)
1284  {
1285  }
1286  #endif /* NBUF_MAP_UNMAP_DEBUG */
1287  
1288  #ifdef QDF_OS_DEBUG
1289  QDF_STATUS
__qdf_nbuf_map(qdf_device_t osdev,struct sk_buff * skb,qdf_dma_dir_t dir)1290  __qdf_nbuf_map(qdf_device_t osdev, struct sk_buff *skb, qdf_dma_dir_t dir)
1291  {
1292  	struct skb_shared_info *sh = skb_shinfo(skb);
1293  
1294  	qdf_assert((dir == QDF_DMA_TO_DEVICE)
1295  			|| (dir == QDF_DMA_FROM_DEVICE));
1296  
1297  	/*
1298  	 * Assume there's only a single fragment.
1299  	 * To support multiple fragments, it would be necessary to change
1300  	 * qdf_nbuf_t to be a separate object that stores meta-info
1301  	 * (including the bus address for each fragment) and a pointer
1302  	 * to the underlying sk_buff.
1303  	 */
1304  	qdf_assert(sh->nr_frags == 0);
1305  
1306  	return __qdf_nbuf_map_single(osdev, skb, dir);
1307  }
1308  qdf_export_symbol(__qdf_nbuf_map);
1309  
1310  #else
1311  QDF_STATUS
__qdf_nbuf_map(qdf_device_t osdev,struct sk_buff * skb,qdf_dma_dir_t dir)1312  __qdf_nbuf_map(qdf_device_t osdev, struct sk_buff *skb, qdf_dma_dir_t dir)
1313  {
1314  	return __qdf_nbuf_map_single(osdev, skb, dir);
1315  }
1316  qdf_export_symbol(__qdf_nbuf_map);
1317  #endif
1318  
1319  void
__qdf_nbuf_unmap(qdf_device_t osdev,struct sk_buff * skb,qdf_dma_dir_t dir)1320  __qdf_nbuf_unmap(qdf_device_t osdev, struct sk_buff *skb,
1321  			qdf_dma_dir_t dir)
1322  {
1323  	qdf_assert((dir == QDF_DMA_TO_DEVICE)
1324  		   || (dir == QDF_DMA_FROM_DEVICE));
1325  
1326  	/*
1327  	 * Assume there's a single fragment.
1328  	 * If this is not true, the assertion in __qdf_nbuf_map will catch it.
1329  	 */
1330  	__qdf_nbuf_unmap_single(osdev, skb, dir);
1331  }
1332  qdf_export_symbol(__qdf_nbuf_unmap);
1333  
1334  #if defined(A_SIMOS_DEVHOST) || defined(HIF_USB) || defined(HIF_SDIO)
1335  QDF_STATUS
__qdf_nbuf_map_single(qdf_device_t osdev,qdf_nbuf_t buf,qdf_dma_dir_t dir)1336  __qdf_nbuf_map_single(qdf_device_t osdev, qdf_nbuf_t buf, qdf_dma_dir_t dir)
1337  {
1338  	qdf_dma_addr_t paddr;
1339  
1340  	QDF_NBUF_CB_PADDR(buf) = paddr = (uintptr_t)buf->data;
1341  	BUILD_BUG_ON(sizeof(paddr) < sizeof(buf->data));
1342  	BUILD_BUG_ON(sizeof(QDF_NBUF_CB_PADDR(buf)) < sizeof(buf->data));
1343  	return QDF_STATUS_SUCCESS;
1344  }
1345  qdf_export_symbol(__qdf_nbuf_map_single);
1346  #else
1347  QDF_STATUS
__qdf_nbuf_map_single(qdf_device_t osdev,qdf_nbuf_t buf,qdf_dma_dir_t dir)1348  __qdf_nbuf_map_single(qdf_device_t osdev, qdf_nbuf_t buf, qdf_dma_dir_t dir)
1349  {
1350  	qdf_dma_addr_t paddr;
1351  
1352  	/* assume that the OS only provides a single fragment */
1353  	QDF_NBUF_CB_PADDR(buf) = paddr =
1354  		dma_map_single(osdev->dev, buf->data,
1355  				skb_end_pointer(buf) - buf->data,
1356  				__qdf_dma_dir_to_os(dir));
1357  	__qdf_record_nbuf_nbytes(
1358  		__qdf_nbuf_get_end_offset(buf), dir, true);
1359  	return dma_mapping_error(osdev->dev, paddr)
1360  		? QDF_STATUS_E_FAILURE
1361  		: QDF_STATUS_SUCCESS;
1362  }
1363  qdf_export_symbol(__qdf_nbuf_map_single);
1364  #endif
1365  
1366  #if defined(A_SIMOS_DEVHOST) || defined(HIF_USB) || defined(HIF_SDIO)
__qdf_nbuf_unmap_single(qdf_device_t osdev,qdf_nbuf_t buf,qdf_dma_dir_t dir)1367  void __qdf_nbuf_unmap_single(qdf_device_t osdev, qdf_nbuf_t buf,
1368  				qdf_dma_dir_t dir)
1369  {
1370  }
1371  #else
__qdf_nbuf_unmap_single(qdf_device_t osdev,qdf_nbuf_t buf,qdf_dma_dir_t dir)1372  void __qdf_nbuf_unmap_single(qdf_device_t osdev, qdf_nbuf_t buf,
1373  					qdf_dma_dir_t dir)
1374  {
1375  	if (QDF_NBUF_CB_PADDR(buf)) {
1376  		__qdf_record_nbuf_nbytes(
1377  			__qdf_nbuf_get_end_offset(buf), dir, false);
1378  		dma_unmap_single(osdev->dev, QDF_NBUF_CB_PADDR(buf),
1379  			skb_end_pointer(buf) - buf->data,
1380  			__qdf_dma_dir_to_os(dir));
1381  	}
1382  }
1383  #endif
1384  qdf_export_symbol(__qdf_nbuf_unmap_single);
1385  
1386  QDF_STATUS
__qdf_nbuf_set_rx_cksum(struct sk_buff * skb,qdf_nbuf_rx_cksum_t * cksum)1387  __qdf_nbuf_set_rx_cksum(struct sk_buff *skb, qdf_nbuf_rx_cksum_t *cksum)
1388  {
1389  	switch (cksum->l4_result) {
1390  	case QDF_NBUF_RX_CKSUM_NONE:
1391  		skb->ip_summed = CHECKSUM_NONE;
1392  		break;
1393  	case QDF_NBUF_RX_CKSUM_TCP_UDP_UNNECESSARY:
1394  		skb->ip_summed = CHECKSUM_UNNECESSARY;
1395  		skb->csum_level = cksum->csum_level;
1396  		break;
1397  	case QDF_NBUF_RX_CKSUM_TCP_UDP_HW:
1398  		skb->ip_summed = CHECKSUM_PARTIAL;
1399  		skb->csum = cksum->val;
1400  		break;
1401  	default:
1402  		pr_err("Unknown checksum type\n");
1403  		qdf_assert(0);
1404  		return QDF_STATUS_E_NOSUPPORT;
1405  	}
1406  	return QDF_STATUS_SUCCESS;
1407  }
1408  qdf_export_symbol(__qdf_nbuf_set_rx_cksum);
1409  
__qdf_nbuf_get_tx_cksum(struct sk_buff * skb)1410  qdf_nbuf_tx_cksum_t __qdf_nbuf_get_tx_cksum(struct sk_buff *skb)
1411  {
1412  	switch (skb->ip_summed) {
1413  	case CHECKSUM_NONE:
1414  		return QDF_NBUF_TX_CKSUM_NONE;
1415  	case CHECKSUM_PARTIAL:
1416  		return QDF_NBUF_TX_CKSUM_TCP_UDP;
1417  	case CHECKSUM_COMPLETE:
1418  		return QDF_NBUF_TX_CKSUM_TCP_UDP_IP;
1419  	default:
1420  		return QDF_NBUF_TX_CKSUM_NONE;
1421  	}
1422  }
1423  qdf_export_symbol(__qdf_nbuf_get_tx_cksum);
1424  
__qdf_nbuf_get_tid(struct sk_buff * skb)1425  uint8_t __qdf_nbuf_get_tid(struct sk_buff *skb)
1426  {
1427  	return skb->priority;
1428  }
1429  qdf_export_symbol(__qdf_nbuf_get_tid);
1430  
__qdf_nbuf_set_tid(struct sk_buff * skb,uint8_t tid)1431  void __qdf_nbuf_set_tid(struct sk_buff *skb, uint8_t tid)
1432  {
1433  	skb->priority = tid;
1434  }
1435  qdf_export_symbol(__qdf_nbuf_set_tid);
1436  
__qdf_nbuf_get_exemption_type(struct sk_buff * skb)1437  uint8_t __qdf_nbuf_get_exemption_type(struct sk_buff *skb)
1438  {
1439  	return QDF_NBUF_EXEMPT_NO_EXEMPTION;
1440  }
1441  qdf_export_symbol(__qdf_nbuf_get_exemption_type);
1442  
__qdf_nbuf_reg_trace_cb(qdf_nbuf_trace_update_t cb_func_ptr)1443  void __qdf_nbuf_reg_trace_cb(qdf_nbuf_trace_update_t cb_func_ptr)
1444  {
1445  	qdf_trace_update_cb = cb_func_ptr;
1446  }
1447  qdf_export_symbol(__qdf_nbuf_reg_trace_cb);
1448  
1449  enum qdf_proto_subtype
__qdf_nbuf_data_get_dhcp_subtype(uint8_t * data)1450  __qdf_nbuf_data_get_dhcp_subtype(uint8_t *data)
1451  {
1452  	enum qdf_proto_subtype subtype = QDF_PROTO_INVALID;
1453  
1454  	if ((data[QDF_DHCP_OPTION53_OFFSET] == QDF_DHCP_OPTION53) &&
1455  		(data[QDF_DHCP_OPTION53_LENGTH_OFFSET] ==
1456  					QDF_DHCP_OPTION53_LENGTH)) {
1457  
1458  		switch (data[QDF_DHCP_OPTION53_STATUS_OFFSET]) {
1459  		case QDF_DHCP_DISCOVER:
1460  			subtype = QDF_PROTO_DHCP_DISCOVER;
1461  			break;
1462  		case QDF_DHCP_REQUEST:
1463  			subtype = QDF_PROTO_DHCP_REQUEST;
1464  			break;
1465  		case QDF_DHCP_OFFER:
1466  			subtype = QDF_PROTO_DHCP_OFFER;
1467  			break;
1468  		case QDF_DHCP_ACK:
1469  			subtype = QDF_PROTO_DHCP_ACK;
1470  			break;
1471  		case QDF_DHCP_NAK:
1472  			subtype = QDF_PROTO_DHCP_NACK;
1473  			break;
1474  		case QDF_DHCP_RELEASE:
1475  			subtype = QDF_PROTO_DHCP_RELEASE;
1476  			break;
1477  		case QDF_DHCP_INFORM:
1478  			subtype = QDF_PROTO_DHCP_INFORM;
1479  			break;
1480  		case QDF_DHCP_DECLINE:
1481  			subtype = QDF_PROTO_DHCP_DECLINE;
1482  			break;
1483  		default:
1484  			break;
1485  		}
1486  	}
1487  
1488  	return subtype;
1489  }
1490  
1491  #define EAPOL_WPA_KEY_INFO_ACK BIT(7)
1492  #define EAPOL_WPA_KEY_INFO_MIC BIT(8)
1493  #define EAPOL_WPA_KEY_INFO_ENCR_KEY_DATA BIT(12) /* IEEE 802.11i/RSN only */
1494  
1495  /**
1496   * __qdf_nbuf_data_get_eapol_key() - Get EAPOL key
1497   * @data: Pointer to EAPOL packet data buffer
1498   *
1499   * We can distinguish M1/M3 from M2/M4 by the ack bit in the keyinfo field
1500   * The ralationship between the ack bit and EAPOL type is as follows:
1501   *
1502   *  EAPOL type  |   M1    M2   M3  M4
1503   * --------------------------------------
1504   *     Ack      |   1     0    1   0
1505   * --------------------------------------
1506   *
1507   * Then, we can differentiate M1 from M3, M2 from M4 by below methods:
1508   * M2/M4: by keyDataLength or Nonce value being 0 for M4.
1509   * M1/M3: by the mic/encrKeyData bit in the keyinfo field.
1510   *
1511   * Return: subtype of the EAPOL packet.
1512   */
1513  static inline enum qdf_proto_subtype
__qdf_nbuf_data_get_eapol_key(uint8_t * data)1514  __qdf_nbuf_data_get_eapol_key(uint8_t *data)
1515  {
1516  	uint16_t key_info, key_data_length;
1517  	enum qdf_proto_subtype subtype;
1518  	uint64_t *key_nonce;
1519  
1520  	key_info = qdf_ntohs((uint16_t)(*(uint16_t *)
1521  			(data + EAPOL_KEY_INFO_OFFSET)));
1522  
1523  	key_data_length = qdf_ntohs((uint16_t)(*(uint16_t *)
1524  				(data + EAPOL_KEY_DATA_LENGTH_OFFSET)));
1525  	key_nonce = (uint64_t *)(data + EAPOL_WPA_KEY_NONCE_OFFSET);
1526  
1527  	if (key_info & EAPOL_WPA_KEY_INFO_ACK)
1528  		if (key_info &
1529  		    (EAPOL_WPA_KEY_INFO_MIC | EAPOL_WPA_KEY_INFO_ENCR_KEY_DATA))
1530  			subtype = QDF_PROTO_EAPOL_M3;
1531  		else
1532  			subtype = QDF_PROTO_EAPOL_M1;
1533  	else
1534  		if (key_data_length == 0 ||
1535  		    !((*key_nonce) || (*(key_nonce + 1)) ||
1536  		      (*(key_nonce + 2)) || (*(key_nonce + 3))))
1537  			subtype = QDF_PROTO_EAPOL_M4;
1538  		else
1539  			subtype = QDF_PROTO_EAPOL_M2;
1540  
1541  	return subtype;
1542  }
1543  
1544  /**
1545   * __qdf_nbuf_data_get_exp_msg_type() - Get EAP expanded msg type
1546   * @data: Pointer to EAPOL packet data buffer
1547   * @code: EAP code
1548   *
1549   * Return: subtype of the EAPOL packet.
1550   */
1551  static inline enum qdf_proto_subtype
__qdf_nbuf_data_get_exp_msg_type(uint8_t * data,uint8_t code)1552  __qdf_nbuf_data_get_exp_msg_type(uint8_t *data, uint8_t code)
1553  {
1554  	uint8_t msg_type;
1555  	uint8_t opcode = *(data + EAP_EXP_MSG_OPCODE_OFFSET);
1556  
1557  	switch (opcode) {
1558  	case WSC_START:
1559  		return QDF_PROTO_EAP_WSC_START;
1560  	case WSC_ACK:
1561  		return QDF_PROTO_EAP_WSC_ACK;
1562  	case WSC_NACK:
1563  		return QDF_PROTO_EAP_WSC_NACK;
1564  	case WSC_MSG:
1565  		msg_type = *(data + EAP_EXP_MSG_TYPE_OFFSET);
1566  		switch (msg_type) {
1567  		case EAP_EXP_TYPE_M1:
1568  			return QDF_PROTO_EAP_M1;
1569  		case EAP_EXP_TYPE_M2:
1570  			return QDF_PROTO_EAP_M2;
1571  		case EAP_EXP_TYPE_M3:
1572  			return QDF_PROTO_EAP_M3;
1573  		case EAP_EXP_TYPE_M4:
1574  			return QDF_PROTO_EAP_M4;
1575  		case EAP_EXP_TYPE_M5:
1576  			return QDF_PROTO_EAP_M5;
1577  		case EAP_EXP_TYPE_M6:
1578  			return QDF_PROTO_EAP_M6;
1579  		case EAP_EXP_TYPE_M7:
1580  			return QDF_PROTO_EAP_M7;
1581  		case EAP_EXP_TYPE_M8:
1582  			return QDF_PROTO_EAP_M8;
1583  		default:
1584  			break;
1585  		}
1586  		break;
1587  	case WSC_DONE:
1588  		return QDF_PROTO_EAP_WSC_DONE;
1589  	case WSC_FRAG_ACK:
1590  		return QDF_PROTO_EAP_WSC_FRAG_ACK;
1591  	default:
1592  		break;
1593  	}
1594  	switch (code) {
1595  	case QDF_EAP_REQUEST:
1596  		return QDF_PROTO_EAP_REQUEST;
1597  	case QDF_EAP_RESPONSE:
1598  		return QDF_PROTO_EAP_RESPONSE;
1599  	default:
1600  		return QDF_PROTO_INVALID;
1601  	}
1602  }
1603  
1604  /**
1605   * __qdf_nbuf_data_get_eap_type() - Get EAP type
1606   * @data: Pointer to EAPOL packet data buffer
1607   * @code: EAP code
1608   *
1609   * Return: subtype of the EAPOL packet.
1610   */
1611  static inline enum qdf_proto_subtype
__qdf_nbuf_data_get_eap_type(uint8_t * data,uint8_t code)1612  __qdf_nbuf_data_get_eap_type(uint8_t *data, uint8_t code)
1613  {
1614  	uint8_t type = *(data + EAP_TYPE_OFFSET);
1615  
1616  	switch (type) {
1617  	case EAP_PACKET_TYPE_EXP:
1618  		return __qdf_nbuf_data_get_exp_msg_type(data, code);
1619  	case EAP_PACKET_TYPE_ID:
1620  		switch (code) {
1621  		case QDF_EAP_REQUEST:
1622  			return QDF_PROTO_EAP_REQ_ID;
1623  		case QDF_EAP_RESPONSE:
1624  			return QDF_PROTO_EAP_RSP_ID;
1625  		default:
1626  			return QDF_PROTO_INVALID;
1627  		}
1628  	default:
1629  		switch (code) {
1630  		case QDF_EAP_REQUEST:
1631  			return QDF_PROTO_EAP_REQUEST;
1632  		case QDF_EAP_RESPONSE:
1633  			return QDF_PROTO_EAP_RESPONSE;
1634  		default:
1635  			return QDF_PROTO_INVALID;
1636  		}
1637  	}
1638  }
1639  
1640  /**
1641   * __qdf_nbuf_data_get_eap_code() - Get EAPOL code
1642   * @data: Pointer to EAPOL packet data buffer
1643   *
1644   * Return: subtype of the EAPOL packet.
1645   */
1646  static inline enum qdf_proto_subtype
__qdf_nbuf_data_get_eap_code(uint8_t * data)1647  __qdf_nbuf_data_get_eap_code(uint8_t *data)
1648  {
1649  	uint8_t code = *(data + EAP_CODE_OFFSET);
1650  
1651  	switch (code) {
1652  	case QDF_EAP_REQUEST:
1653  	case QDF_EAP_RESPONSE:
1654  		return __qdf_nbuf_data_get_eap_type(data, code);
1655  	case QDF_EAP_SUCCESS:
1656  		return QDF_PROTO_EAP_SUCCESS;
1657  	case QDF_EAP_FAILURE:
1658  		return QDF_PROTO_EAP_FAILURE;
1659  	case QDF_EAP_INITIATE:
1660  		return QDF_PROTO_EAP_INITIATE;
1661  	case QDF_EAP_FINISH:
1662  		return QDF_PROTO_EAP_FINISH;
1663  	default:
1664  		return QDF_PROTO_INVALID;
1665  	}
1666  }
1667  
1668  enum qdf_proto_subtype
__qdf_nbuf_data_get_eapol_subtype(uint8_t * data)1669  __qdf_nbuf_data_get_eapol_subtype(uint8_t *data)
1670  {
1671  	uint8_t pkt_type = *(data + EAPOL_PACKET_TYPE_OFFSET);
1672  
1673  	switch (pkt_type) {
1674  	case EAPOL_PACKET_TYPE_EAP:
1675  		return __qdf_nbuf_data_get_eap_code(data);
1676  	case EAPOL_PACKET_TYPE_START:
1677  		return QDF_PROTO_EAPOL_START;
1678  	case EAPOL_PACKET_TYPE_LOGOFF:
1679  		return QDF_PROTO_EAPOL_LOGOFF;
1680  	case EAPOL_PACKET_TYPE_KEY:
1681  		return __qdf_nbuf_data_get_eapol_key(data);
1682  	case EAPOL_PACKET_TYPE_ASF:
1683  		return QDF_PROTO_EAPOL_ASF;
1684  	default:
1685  		return QDF_PROTO_INVALID;
1686  	}
1687  }
1688  
1689  qdf_export_symbol(__qdf_nbuf_data_get_eapol_subtype);
1690  
1691  enum qdf_proto_subtype
__qdf_nbuf_data_get_arp_subtype(uint8_t * data)1692  __qdf_nbuf_data_get_arp_subtype(uint8_t *data)
1693  {
1694  	uint16_t subtype;
1695  	enum qdf_proto_subtype proto_subtype = QDF_PROTO_INVALID;
1696  
1697  	subtype = (uint16_t)(*(uint16_t *)
1698  			(data + ARP_SUB_TYPE_OFFSET));
1699  
1700  	switch (QDF_SWAP_U16(subtype)) {
1701  	case ARP_REQUEST:
1702  		proto_subtype = QDF_PROTO_ARP_REQ;
1703  		break;
1704  	case ARP_RESPONSE:
1705  		proto_subtype = QDF_PROTO_ARP_RES;
1706  		break;
1707  	default:
1708  		break;
1709  	}
1710  
1711  	return proto_subtype;
1712  }
1713  
1714  enum qdf_proto_subtype
__qdf_nbuf_data_get_icmp_subtype(uint8_t * data)1715  __qdf_nbuf_data_get_icmp_subtype(uint8_t *data)
1716  {
1717  	uint8_t subtype;
1718  	enum qdf_proto_subtype proto_subtype = QDF_PROTO_INVALID;
1719  
1720  	subtype = (uint8_t)(*(uint8_t *)
1721  			(data + ICMP_SUBTYPE_OFFSET));
1722  
1723  	switch (subtype) {
1724  	case ICMP_REQUEST:
1725  		proto_subtype = QDF_PROTO_ICMP_REQ;
1726  		break;
1727  	case ICMP_RESPONSE:
1728  		proto_subtype = QDF_PROTO_ICMP_RES;
1729  		break;
1730  	default:
1731  		break;
1732  	}
1733  
1734  	return proto_subtype;
1735  }
1736  
1737  enum qdf_proto_subtype
__qdf_nbuf_data_get_icmpv6_subtype(uint8_t * data)1738  __qdf_nbuf_data_get_icmpv6_subtype(uint8_t *data)
1739  {
1740  	uint8_t subtype;
1741  	enum qdf_proto_subtype proto_subtype = QDF_PROTO_INVALID;
1742  
1743  	subtype = (uint8_t)(*(uint8_t *)
1744  			(data + ICMPV6_SUBTYPE_OFFSET));
1745  
1746  	switch (subtype) {
1747  	case ICMPV6_REQUEST:
1748  		proto_subtype = QDF_PROTO_ICMPV6_REQ;
1749  		break;
1750  	case ICMPV6_RESPONSE:
1751  		proto_subtype = QDF_PROTO_ICMPV6_RES;
1752  		break;
1753  	case ICMPV6_RS:
1754  		proto_subtype = QDF_PROTO_ICMPV6_RS;
1755  		break;
1756  	case ICMPV6_RA:
1757  		proto_subtype = QDF_PROTO_ICMPV6_RA;
1758  		break;
1759  	case ICMPV6_NS:
1760  		proto_subtype = QDF_PROTO_ICMPV6_NS;
1761  		break;
1762  	case ICMPV6_NA:
1763  		proto_subtype = QDF_PROTO_ICMPV6_NA;
1764  		break;
1765  	default:
1766  		break;
1767  	}
1768  
1769  	return proto_subtype;
1770  }
1771  
1772  bool
__qdf_nbuf_is_ipv4_last_fragment(struct sk_buff * skb)1773  __qdf_nbuf_is_ipv4_last_fragment(struct sk_buff *skb)
1774  {
1775  	if (((ntohs(ip_hdr(skb)->frag_off) & ~IP_OFFSET) & IP_MF) == 0)
1776  		return true;
1777  
1778  	return false;
1779  }
1780  
1781  bool
__qdf_nbuf_is_ipv4_fragment(struct sk_buff * skb)1782  __qdf_nbuf_is_ipv4_fragment(struct sk_buff *skb)
1783  {
1784  	if (ntohs(ip_hdr(skb)->frag_off) & IP_MF)
1785  		return true;
1786  
1787  	return false;
1788  }
1789  
1790  void
__qdf_nbuf_data_set_ipv4_tos(uint8_t * data,uint8_t tos)1791  __qdf_nbuf_data_set_ipv4_tos(uint8_t *data, uint8_t tos)
1792  {
1793  	*(uint8_t *)(data + QDF_NBUF_TRAC_IPV4_TOS_OFFSET) = tos;
1794  }
1795  
1796  uint8_t
__qdf_nbuf_data_get_ipv4_tos(uint8_t * data)1797  __qdf_nbuf_data_get_ipv4_tos(uint8_t *data)
1798  {
1799  	uint8_t tos;
1800  
1801  	tos = (uint8_t)(*(uint8_t *)(data +
1802  			QDF_NBUF_TRAC_IPV4_TOS_OFFSET));
1803  	return tos;
1804  }
1805  
1806  uint8_t
__qdf_nbuf_data_get_ipv4_proto(uint8_t * data)1807  __qdf_nbuf_data_get_ipv4_proto(uint8_t *data)
1808  {
1809  	uint8_t proto_type;
1810  
1811  	proto_type = (uint8_t)(*(uint8_t *)(data +
1812  				QDF_NBUF_TRAC_IPV4_PROTO_TYPE_OFFSET));
1813  	return proto_type;
1814  }
1815  
1816  uint8_t
__qdf_nbuf_data_get_ipv6_tc(uint8_t * data)1817  __qdf_nbuf_data_get_ipv6_tc(uint8_t *data)
1818  {
1819  	struct ipv6hdr *hdr;
1820  
1821  	hdr =  (struct ipv6hdr *)(data + QDF_NBUF_TRAC_IPV6_OFFSET);
1822  	return ip6_tclass(ip6_flowinfo(hdr));
1823  }
1824  
1825  void
__qdf_nbuf_data_set_ipv6_tc(uint8_t * data,uint8_t tc)1826  __qdf_nbuf_data_set_ipv6_tc(uint8_t *data, uint8_t tc)
1827  {
1828  	struct ipv6hdr *hdr;
1829  
1830  	hdr =  (struct ipv6hdr *)(data + QDF_NBUF_TRAC_IPV6_OFFSET);
1831  	ip6_flow_hdr(hdr, tc, ip6_flowlabel(hdr));
1832  }
1833  
1834  uint8_t
__qdf_nbuf_data_get_ipv6_proto(uint8_t * data)1835  __qdf_nbuf_data_get_ipv6_proto(uint8_t *data)
1836  {
1837  	uint8_t proto_type;
1838  
1839  	proto_type = (uint8_t)(*(uint8_t *)(data +
1840  				QDF_NBUF_TRAC_IPV6_PROTO_TYPE_OFFSET));
1841  	return proto_type;
1842  }
1843  
__qdf_nbuf_data_is_ipv4_pkt(uint8_t * data)1844  bool __qdf_nbuf_data_is_ipv4_pkt(uint8_t *data)
1845  {
1846  	uint16_t ether_type;
1847  
1848  	ether_type = (uint16_t)(*(uint16_t *)(data +
1849  				QDF_NBUF_TRAC_ETH_TYPE_OFFSET));
1850  
1851  	if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_IPV4_ETH_TYPE))
1852  		return true;
1853  	else
1854  		return false;
1855  }
1856  qdf_export_symbol(__qdf_nbuf_data_is_ipv4_pkt);
1857  
__qdf_nbuf_data_is_ipv4_dhcp_pkt(uint8_t * data)1858  bool __qdf_nbuf_data_is_ipv4_dhcp_pkt(uint8_t *data)
1859  {
1860  	uint16_t sport;
1861  	uint16_t dport;
1862  	uint8_t ipv4_offset;
1863  	uint8_t ipv4_hdr_len;
1864  	struct iphdr *iphdr;
1865  
1866  	if (__qdf_nbuf_get_ether_type(data) !=
1867  	    QDF_SWAP_U16(QDF_NBUF_TRAC_IPV4_ETH_TYPE))
1868  		return false;
1869  
1870  	ipv4_offset = __qdf_nbuf_get_ip_offset(data);
1871  	iphdr = (struct iphdr *)(data + ipv4_offset);
1872  	ipv4_hdr_len = iphdr->ihl * QDF_NBUF_IPV4_HDR_SIZE_UNIT;
1873  
1874  	sport = *(uint16_t *)(data + ipv4_offset + ipv4_hdr_len);
1875  	dport = *(uint16_t *)(data + ipv4_offset + ipv4_hdr_len +
1876  			      sizeof(uint16_t));
1877  
1878  	if (((sport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP_SRV_PORT)) &&
1879  	     (dport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP_CLI_PORT))) ||
1880  	    ((sport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP_CLI_PORT)) &&
1881  	     (dport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP_SRV_PORT))))
1882  		return true;
1883  	else
1884  		return false;
1885  }
1886  qdf_export_symbol(__qdf_nbuf_data_is_ipv4_dhcp_pkt);
1887  
1888  /**
1889   * qdf_is_eapol_type() - check if packet is EAPOL
1890   * @type: Packet type
1891   *
1892   * This api is to check if frame is EAPOL packet type.
1893   *
1894   * Return: true if it is EAPOL frame
1895   *         false otherwise.
1896   */
1897  #ifdef BIG_ENDIAN_HOST
qdf_is_eapol_type(uint16_t type)1898  static inline bool qdf_is_eapol_type(uint16_t type)
1899  {
1900  	return (type == QDF_NBUF_TRAC_EAPOL_ETH_TYPE);
1901  }
1902  #else
qdf_is_eapol_type(uint16_t type)1903  static inline bool qdf_is_eapol_type(uint16_t type)
1904  {
1905  	return (type == QDF_SWAP_U16(QDF_NBUF_TRAC_EAPOL_ETH_TYPE));
1906  }
1907  #endif
1908  
__qdf_nbuf_data_is_ipv4_eapol_pkt(uint8_t * data)1909  bool __qdf_nbuf_data_is_ipv4_eapol_pkt(uint8_t *data)
1910  {
1911  	uint16_t ether_type;
1912  
1913  	ether_type = __qdf_nbuf_get_ether_type(data);
1914  
1915  	return qdf_is_eapol_type(ether_type);
1916  }
1917  qdf_export_symbol(__qdf_nbuf_data_is_ipv4_eapol_pkt);
1918  
__qdf_nbuf_is_ipv4_wapi_pkt(struct sk_buff * skb)1919  bool __qdf_nbuf_is_ipv4_wapi_pkt(struct sk_buff *skb)
1920  {
1921  	uint16_t ether_type;
1922  
1923  	ether_type = (uint16_t)(*(uint16_t *)(skb->data +
1924  				QDF_NBUF_TRAC_ETH_TYPE_OFFSET));
1925  
1926  	if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_WAPI_ETH_TYPE))
1927  		return true;
1928  	else
1929  		return false;
1930  }
1931  qdf_export_symbol(__qdf_nbuf_is_ipv4_wapi_pkt);
1932  
1933  /**
1934   * qdf_nbuf_is_ipv6_vlan_pkt() - check whether packet is vlan IPV6
1935   * @data: Pointer to network data buffer
1936   *
1937   * This api is for vlan header included ipv6 packet.
1938   *
1939   * Return: true if packet is vlan header included IPV6
1940   *	   false otherwise.
1941   */
qdf_nbuf_is_ipv6_vlan_pkt(uint8_t * data)1942  static bool qdf_nbuf_is_ipv6_vlan_pkt(uint8_t *data)
1943  {
1944  	uint16_t ether_type;
1945  
1946  	ether_type = *(uint16_t *)(data + QDF_NBUF_TRAC_ETH_TYPE_OFFSET);
1947  
1948  	if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021Q))) {
1949  		ether_type = *(uint16_t *)(data +
1950  					   QDF_NBUF_TRAC_VLAN_ETH_TYPE_OFFSET);
1951  
1952  		if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_IPV6_ETH_TYPE))
1953  			return true;
1954  	}
1955  	return false;
1956  }
1957  
1958  /**
1959   * qdf_nbuf_is_ipv4_vlan_pkt() - check whether packet is vlan IPV4
1960   * @data: Pointer to network data buffer
1961   *
1962   * This api is for vlan header included ipv4 packet.
1963   *
1964   * Return: true if packet is vlan header included IPV4
1965   *	   false otherwise.
1966   */
qdf_nbuf_is_ipv4_vlan_pkt(uint8_t * data)1967  static bool qdf_nbuf_is_ipv4_vlan_pkt(uint8_t *data)
1968  {
1969  	uint16_t ether_type;
1970  
1971  	ether_type = *(uint16_t *)(data + QDF_NBUF_TRAC_ETH_TYPE_OFFSET);
1972  
1973  	if (unlikely(ether_type == QDF_SWAP_U16(QDF_ETH_TYPE_8021Q))) {
1974  		ether_type = *(uint16_t *)(data +
1975  					   QDF_NBUF_TRAC_VLAN_ETH_TYPE_OFFSET);
1976  
1977  		if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_IPV4_ETH_TYPE))
1978  			return true;
1979  	}
1980  	return false;
1981  }
1982  
__qdf_nbuf_data_is_ipv4_igmp_pkt(uint8_t * data)1983  bool __qdf_nbuf_data_is_ipv4_igmp_pkt(uint8_t *data)
1984  {
1985  	uint8_t pkt_type;
1986  
1987  	if (__qdf_nbuf_data_is_ipv4_pkt(data)) {
1988  		pkt_type = (uint8_t)(*(uint8_t *)(data +
1989  				QDF_NBUF_TRAC_IPV4_PROTO_TYPE_OFFSET));
1990  		goto is_igmp;
1991  	}
1992  
1993  	if (qdf_nbuf_is_ipv4_vlan_pkt(data)) {
1994  		pkt_type = (uint8_t)(*(uint8_t *)(
1995  				data +
1996  				QDF_NBUF_TRAC_VLAN_IPV4_PROTO_TYPE_OFFSET));
1997  		goto is_igmp;
1998  	}
1999  
2000  	return false;
2001  is_igmp:
2002  	if (pkt_type == QDF_NBUF_TRAC_IGMP_TYPE)
2003  		return true;
2004  
2005  	return false;
2006  }
2007  
2008  qdf_export_symbol(__qdf_nbuf_data_is_ipv4_igmp_pkt);
2009  
__qdf_nbuf_data_is_ipv6_igmp_pkt(uint8_t * data)2010  bool __qdf_nbuf_data_is_ipv6_igmp_pkt(uint8_t *data)
2011  {
2012  	uint8_t pkt_type;
2013  	uint8_t next_hdr;
2014  
2015  	if (__qdf_nbuf_data_is_ipv6_pkt(data)) {
2016  		pkt_type = (uint8_t)(*(uint8_t *)(data +
2017  				QDF_NBUF_TRAC_IPV6_PROTO_TYPE_OFFSET));
2018  		next_hdr = (uint8_t)(*(uint8_t *)(
2019  				data +
2020  				QDF_NBUF_TRAC_IPV6_OFFSET +
2021  				QDF_NBUF_TRAC_IPV6_HEADER_SIZE));
2022  		goto is_mld;
2023  	}
2024  
2025  	if (qdf_nbuf_is_ipv6_vlan_pkt(data)) {
2026  		pkt_type = (uint8_t)(*(uint8_t *)(
2027  				data +
2028  				QDF_NBUF_TRAC_VLAN_IPV6_PROTO_TYPE_OFFSET));
2029  		next_hdr = (uint8_t)(*(uint8_t *)(
2030  				data +
2031  				QDF_NBUF_TRAC_VLAN_IPV6_OFFSET +
2032  				QDF_NBUF_TRAC_IPV6_HEADER_SIZE));
2033  		goto is_mld;
2034  	}
2035  
2036  	return false;
2037  is_mld:
2038  	if (pkt_type == QDF_NBUF_TRAC_ICMPV6_TYPE)
2039  		return true;
2040  	if ((pkt_type == QDF_NBUF_TRAC_HOPOPTS_TYPE) &&
2041  	    (next_hdr == QDF_NBUF_TRAC_ICMPV6_TYPE))
2042  		return true;
2043  
2044  	return false;
2045  }
2046  
2047  qdf_export_symbol(__qdf_nbuf_data_is_ipv6_igmp_pkt);
2048  
__qdf_nbuf_is_ipv4_igmp_leave_pkt(__qdf_nbuf_t buf)2049  bool __qdf_nbuf_is_ipv4_igmp_leave_pkt(__qdf_nbuf_t buf)
2050  {
2051  	qdf_ether_header_t *eh = NULL;
2052  	uint16_t ether_type;
2053  	uint8_t eth_hdr_size = sizeof(qdf_ether_header_t);
2054  
2055  	eh = (qdf_ether_header_t *)qdf_nbuf_data(buf);
2056  	ether_type = eh->ether_type;
2057  
2058  	if (ether_type == htons(ETH_P_8021Q)) {
2059  		struct vlan_ethhdr *veth =
2060  				(struct vlan_ethhdr *)qdf_nbuf_data(buf);
2061  		ether_type = veth->h_vlan_encapsulated_proto;
2062  		eth_hdr_size = sizeof(struct vlan_ethhdr);
2063  	}
2064  
2065  	if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_IPV4_ETH_TYPE)) {
2066  		struct iphdr *iph = NULL;
2067  		struct igmphdr *ih = NULL;
2068  
2069  		iph = (struct iphdr *)(qdf_nbuf_data(buf) + eth_hdr_size);
2070  		ih = (struct igmphdr *)((uint8_t *)iph + iph->ihl * 4);
2071  		switch (ih->type) {
2072  		case IGMP_HOST_LEAVE_MESSAGE:
2073  			return true;
2074  		case IGMPV3_HOST_MEMBERSHIP_REPORT:
2075  		{
2076  			struct igmpv3_report *ihv3 = (struct igmpv3_report *)ih;
2077  			struct igmpv3_grec *grec = NULL;
2078  			int num = 0;
2079  			int i = 0;
2080  			int len = 0;
2081  			int type = 0;
2082  
2083  			num = ntohs(ihv3->ngrec);
2084  			for (i = 0; i < num; i++) {
2085  				grec = (void *)((uint8_t *)(ihv3->grec) + len);
2086  				type = grec->grec_type;
2087  				if ((type == IGMPV3_MODE_IS_INCLUDE) ||
2088  				    (type == IGMPV3_CHANGE_TO_INCLUDE))
2089  					return true;
2090  
2091  				len += sizeof(struct igmpv3_grec);
2092  				len += ntohs(grec->grec_nsrcs) * 4;
2093  			}
2094  			break;
2095  		}
2096  		default:
2097  			break;
2098  		}
2099  	}
2100  
2101  	return false;
2102  }
2103  
2104  qdf_export_symbol(__qdf_nbuf_is_ipv4_igmp_leave_pkt);
2105  
__qdf_nbuf_is_ipv6_igmp_leave_pkt(__qdf_nbuf_t buf)2106  bool __qdf_nbuf_is_ipv6_igmp_leave_pkt(__qdf_nbuf_t buf)
2107  {
2108  	qdf_ether_header_t *eh = NULL;
2109  	uint16_t ether_type;
2110  	uint8_t eth_hdr_size = sizeof(qdf_ether_header_t);
2111  
2112  	eh = (qdf_ether_header_t *)qdf_nbuf_data(buf);
2113  	ether_type = eh->ether_type;
2114  
2115  	if (ether_type == htons(ETH_P_8021Q)) {
2116  		struct vlan_ethhdr *veth =
2117  				(struct vlan_ethhdr *)qdf_nbuf_data(buf);
2118  		ether_type = veth->h_vlan_encapsulated_proto;
2119  		eth_hdr_size = sizeof(struct vlan_ethhdr);
2120  	}
2121  
2122  	if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_IPV6_ETH_TYPE)) {
2123  		struct ipv6hdr *ip6h = NULL;
2124  		struct icmp6hdr *icmp6h = NULL;
2125  		uint8_t nexthdr;
2126  		uint16_t frag_off = 0;
2127  		int offset;
2128  		qdf_nbuf_t buf_copy = NULL;
2129  
2130  		ip6h = (struct ipv6hdr *)(qdf_nbuf_data(buf) + eth_hdr_size);
2131  		if (ip6h->nexthdr != IPPROTO_HOPOPTS ||
2132  		    ip6h->payload_len == 0)
2133  			return false;
2134  
2135  		buf_copy = qdf_nbuf_copy(buf);
2136  		if (qdf_likely(!buf_copy))
2137  			return false;
2138  
2139  		nexthdr = ip6h->nexthdr;
2140  		offset = ipv6_skip_exthdr(buf_copy,
2141  					  eth_hdr_size + sizeof(*ip6h),
2142  					  &nexthdr,
2143  					  &frag_off);
2144  		qdf_nbuf_free(buf_copy);
2145  		if (offset < 0 || nexthdr != IPPROTO_ICMPV6)
2146  			return false;
2147  
2148  		icmp6h = (struct icmp6hdr *)(qdf_nbuf_data(buf) + offset);
2149  
2150  		switch (icmp6h->icmp6_type) {
2151  		case ICMPV6_MGM_REDUCTION:
2152  			return true;
2153  		case ICMPV6_MLD2_REPORT:
2154  		{
2155  			struct mld2_report *mh = NULL;
2156  			struct mld2_grec *grec = NULL;
2157  			int num = 0;
2158  			int i = 0;
2159  			int len = 0;
2160  			int type = -1;
2161  
2162  			mh = (struct mld2_report *)icmp6h;
2163  			num = ntohs(mh->mld2r_ngrec);
2164  			for (i = 0; i < num; i++) {
2165  				grec = (void *)(((uint8_t *)mh->mld2r_grec) +
2166  						len);
2167  				type = grec->grec_type;
2168  				if ((type == MLD2_MODE_IS_INCLUDE) ||
2169  				    (type == MLD2_CHANGE_TO_INCLUDE))
2170  					return true;
2171  				else if (type == MLD2_BLOCK_OLD_SOURCES)
2172  					return true;
2173  
2174  				len += sizeof(struct mld2_grec);
2175  				len += ntohs(grec->grec_nsrcs) *
2176  						sizeof(struct in6_addr);
2177  			}
2178  			break;
2179  		}
2180  		default:
2181  			break;
2182  		}
2183  	}
2184  
2185  	return false;
2186  }
2187  
2188  qdf_export_symbol(__qdf_nbuf_is_ipv6_igmp_leave_pkt);
2189  
__qdf_nbuf_is_ipv4_tdls_pkt(struct sk_buff * skb)2190  bool __qdf_nbuf_is_ipv4_tdls_pkt(struct sk_buff *skb)
2191  {
2192  	uint16_t ether_type;
2193  
2194  	ether_type = *(uint16_t *)(skb->data +
2195  				QDF_NBUF_TRAC_ETH_TYPE_OFFSET);
2196  
2197  	if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_TDLS_ETH_TYPE))
2198  		return true;
2199  	else
2200  		return false;
2201  }
2202  qdf_export_symbol(__qdf_nbuf_is_ipv4_tdls_pkt);
2203  
__qdf_nbuf_data_is_ipv4_arp_pkt(uint8_t * data)2204  bool __qdf_nbuf_data_is_ipv4_arp_pkt(uint8_t *data)
2205  {
2206  	uint16_t ether_type;
2207  
2208  	ether_type = __qdf_nbuf_get_ether_type(data);
2209  
2210  	if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_ARP_ETH_TYPE))
2211  		return true;
2212  	else
2213  		return false;
2214  }
2215  qdf_export_symbol(__qdf_nbuf_data_is_ipv4_arp_pkt);
2216  
__qdf_nbuf_data_is_arp_req(uint8_t * data)2217  bool __qdf_nbuf_data_is_arp_req(uint8_t *data)
2218  {
2219  	uint16_t op_code;
2220  
2221  	op_code = (uint16_t)(*(uint16_t *)(data +
2222  				QDF_NBUF_PKT_ARP_OPCODE_OFFSET));
2223  
2224  	if (op_code == QDF_SWAP_U16(QDF_NBUF_PKT_ARPOP_REQ))
2225  		return true;
2226  	return false;
2227  }
2228  
__qdf_nbuf_data_is_arp_rsp(uint8_t * data)2229  bool __qdf_nbuf_data_is_arp_rsp(uint8_t *data)
2230  {
2231  	uint16_t op_code;
2232  
2233  	op_code = (uint16_t)(*(uint16_t *)(data +
2234  				QDF_NBUF_PKT_ARP_OPCODE_OFFSET));
2235  
2236  	if (op_code == QDF_SWAP_U16(QDF_NBUF_PKT_ARPOP_REPLY))
2237  		return true;
2238  	return false;
2239  }
2240  
__qdf_nbuf_get_arp_src_ip(uint8_t * data)2241  uint32_t  __qdf_nbuf_get_arp_src_ip(uint8_t *data)
2242  {
2243  	uint32_t src_ip;
2244  
2245  	src_ip = (uint32_t)(*(uint32_t *)(data +
2246  				QDF_NBUF_PKT_ARP_SRC_IP_OFFSET));
2247  
2248  	return src_ip;
2249  }
2250  
__qdf_nbuf_get_arp_tgt_ip(uint8_t * data)2251  uint32_t  __qdf_nbuf_get_arp_tgt_ip(uint8_t *data)
2252  {
2253  	uint32_t tgt_ip;
2254  
2255  	tgt_ip = (uint32_t)(*(uint32_t *)(data +
2256  				QDF_NBUF_PKT_ARP_TGT_IP_OFFSET));
2257  
2258  	return tgt_ip;
2259  }
2260  
__qdf_nbuf_get_dns_domain_name(uint8_t * data,uint32_t len)2261  uint8_t *__qdf_nbuf_get_dns_domain_name(uint8_t *data, uint32_t len)
2262  {
2263  	uint8_t *domain_name;
2264  
2265  	domain_name = (uint8_t *)
2266  			(data + QDF_NBUF_PKT_DNS_NAME_OVER_UDP_OFFSET);
2267  	return domain_name;
2268  }
2269  
__qdf_nbuf_data_is_dns_query(uint8_t * data)2270  bool __qdf_nbuf_data_is_dns_query(uint8_t *data)
2271  {
2272  	uint16_t op_code;
2273  	uint16_t tgt_port;
2274  
2275  	tgt_port = (uint16_t)(*(uint16_t *)(data +
2276  				QDF_NBUF_PKT_DNS_DST_PORT_OFFSET));
2277  	/* Standard DNS query always happen on Dest Port 53. */
2278  	if (tgt_port == QDF_SWAP_U16(QDF_NBUF_PKT_DNS_STANDARD_PORT)) {
2279  		op_code = (uint16_t)(*(uint16_t *)(data +
2280  				QDF_NBUF_PKT_DNS_OVER_UDP_OPCODE_OFFSET));
2281  		if ((QDF_SWAP_U16(op_code) & QDF_NBUF_PKT_DNSOP_BITMAP) ==
2282  				QDF_NBUF_PKT_DNSOP_STANDARD_QUERY)
2283  			return true;
2284  	}
2285  	return false;
2286  }
2287  
__qdf_nbuf_data_is_dns_response(uint8_t * data)2288  bool __qdf_nbuf_data_is_dns_response(uint8_t *data)
2289  {
2290  	uint16_t op_code;
2291  	uint16_t src_port;
2292  
2293  	src_port = (uint16_t)(*(uint16_t *)(data +
2294  				QDF_NBUF_PKT_DNS_SRC_PORT_OFFSET));
2295  	/* Standard DNS response always comes on Src Port 53. */
2296  	if (src_port == QDF_SWAP_U16(QDF_NBUF_PKT_DNS_STANDARD_PORT)) {
2297  		op_code = (uint16_t)(*(uint16_t *)(data +
2298  				QDF_NBUF_PKT_DNS_OVER_UDP_OPCODE_OFFSET));
2299  
2300  		if ((QDF_SWAP_U16(op_code) & QDF_NBUF_PKT_DNSOP_BITMAP) ==
2301  				QDF_NBUF_PKT_DNSOP_STANDARD_RESPONSE)
2302  			return true;
2303  	}
2304  	return false;
2305  }
2306  
__qdf_nbuf_data_is_tcp_fin(uint8_t * data)2307  bool __qdf_nbuf_data_is_tcp_fin(uint8_t *data)
2308  {
2309  	uint8_t op_code;
2310  
2311  	op_code = (uint8_t)(*(uint8_t *)(data +
2312  				QDF_NBUF_PKT_TCP_OPCODE_OFFSET));
2313  
2314  	if (op_code == QDF_NBUF_PKT_TCPOP_FIN)
2315  		return true;
2316  
2317  	return false;
2318  }
2319  
__qdf_nbuf_data_is_tcp_fin_ack(uint8_t * data)2320  bool __qdf_nbuf_data_is_tcp_fin_ack(uint8_t *data)
2321  {
2322  	uint8_t op_code;
2323  
2324  	op_code = (uint8_t)(*(uint8_t *)(data +
2325  				QDF_NBUF_PKT_TCP_OPCODE_OFFSET));
2326  
2327  	if (op_code == QDF_NBUF_PKT_TCPOP_FIN_ACK)
2328  		return true;
2329  
2330  	return false;
2331  }
2332  
__qdf_nbuf_data_is_tcp_syn(uint8_t * data)2333  bool __qdf_nbuf_data_is_tcp_syn(uint8_t *data)
2334  {
2335  	uint8_t op_code;
2336  
2337  	op_code = (uint8_t)(*(uint8_t *)(data +
2338  				QDF_NBUF_PKT_TCP_OPCODE_OFFSET));
2339  
2340  	if (op_code == QDF_NBUF_PKT_TCPOP_SYN)
2341  		return true;
2342  	return false;
2343  }
2344  
__qdf_nbuf_data_is_tcp_syn_ack(uint8_t * data)2345  bool __qdf_nbuf_data_is_tcp_syn_ack(uint8_t *data)
2346  {
2347  	uint8_t op_code;
2348  
2349  	op_code = (uint8_t)(*(uint8_t *)(data +
2350  				QDF_NBUF_PKT_TCP_OPCODE_OFFSET));
2351  
2352  	if (op_code == QDF_NBUF_PKT_TCPOP_SYN_ACK)
2353  		return true;
2354  	return false;
2355  }
2356  
__qdf_nbuf_data_is_tcp_rst(uint8_t * data)2357  bool __qdf_nbuf_data_is_tcp_rst(uint8_t *data)
2358  {
2359  	uint8_t op_code;
2360  
2361  	op_code = (uint8_t)(*(uint8_t *)(data +
2362  				QDF_NBUF_PKT_TCP_OPCODE_OFFSET));
2363  
2364  	if (op_code == QDF_NBUF_PKT_TCPOP_RST)
2365  		return true;
2366  
2367  	return false;
2368  }
2369  
__qdf_nbuf_data_is_tcp_ack(uint8_t * data)2370  bool __qdf_nbuf_data_is_tcp_ack(uint8_t *data)
2371  {
2372  	uint8_t op_code;
2373  
2374  	op_code = (uint8_t)(*(uint8_t *)(data +
2375  				QDF_NBUF_PKT_TCP_OPCODE_OFFSET));
2376  
2377  	if (op_code == QDF_NBUF_PKT_TCPOP_ACK)
2378  		return true;
2379  	return false;
2380  }
2381  
__qdf_nbuf_data_get_tcp_src_port(uint8_t * data)2382  uint16_t __qdf_nbuf_data_get_tcp_src_port(uint8_t *data)
2383  {
2384  	uint16_t src_port;
2385  
2386  	src_port = (uint16_t)(*(uint16_t *)(data +
2387  				QDF_NBUF_PKT_TCP_SRC_PORT_OFFSET));
2388  
2389  	return src_port;
2390  }
2391  
__qdf_nbuf_data_get_tcp_dst_port(uint8_t * data)2392  uint16_t __qdf_nbuf_data_get_tcp_dst_port(uint8_t *data)
2393  {
2394  	uint16_t tgt_port;
2395  
2396  	tgt_port = (uint16_t)(*(uint16_t *)(data +
2397  				QDF_NBUF_PKT_TCP_DST_PORT_OFFSET));
2398  
2399  	return tgt_port;
2400  }
2401  
__qdf_nbuf_data_is_icmpv4_req(uint8_t * data)2402  bool __qdf_nbuf_data_is_icmpv4_req(uint8_t *data)
2403  {
2404  	uint8_t op_code;
2405  
2406  	op_code = (uint8_t)(*(uint8_t *)(data +
2407  				QDF_NBUF_PKT_ICMPv4_OPCODE_OFFSET));
2408  
2409  	if (op_code == QDF_NBUF_PKT_ICMPv4OP_REQ)
2410  		return true;
2411  	return false;
2412  }
2413  
__qdf_nbuf_data_is_icmpv4_rsp(uint8_t * data)2414  bool __qdf_nbuf_data_is_icmpv4_rsp(uint8_t *data)
2415  {
2416  	uint8_t op_code;
2417  
2418  	op_code = (uint8_t)(*(uint8_t *)(data +
2419  				QDF_NBUF_PKT_ICMPv4_OPCODE_OFFSET));
2420  
2421  	if (op_code == QDF_NBUF_PKT_ICMPv4OP_REPLY)
2422  		return true;
2423  	return false;
2424  }
2425  
__qdf_nbuf_data_is_icmpv4_redirect(uint8_t * data)2426  bool __qdf_nbuf_data_is_icmpv4_redirect(uint8_t *data)
2427  {
2428  	uint8_t op_code;
2429  
2430  	op_code = (uint8_t)(*(uint8_t *)(data +
2431  				QDF_NBUF_PKT_ICMPv4_OPCODE_OFFSET));
2432  
2433  	if (op_code == QDF_NBUF_PKT_ICMPV4_REDIRECT)
2434  		return true;
2435  	return false;
2436  }
2437  
2438  qdf_export_symbol(__qdf_nbuf_data_is_icmpv4_redirect);
2439  
__qdf_nbuf_data_is_icmpv6_redirect(uint8_t * data)2440  bool __qdf_nbuf_data_is_icmpv6_redirect(uint8_t *data)
2441  {
2442  	uint8_t subtype;
2443  
2444  	subtype = (uint8_t)(*(uint8_t *)(data + ICMPV6_SUBTYPE_OFFSET));
2445  
2446  	if (subtype == ICMPV6_REDIRECT)
2447  		return true;
2448  	return false;
2449  }
2450  
2451  qdf_export_symbol(__qdf_nbuf_data_is_icmpv6_redirect);
2452  
__qdf_nbuf_get_icmpv4_src_ip(uint8_t * data)2453  uint32_t __qdf_nbuf_get_icmpv4_src_ip(uint8_t *data)
2454  {
2455  	uint32_t src_ip;
2456  
2457  	src_ip = (uint32_t)(*(uint32_t *)(data +
2458  				QDF_NBUF_PKT_ICMPv4_SRC_IP_OFFSET));
2459  
2460  	return src_ip;
2461  }
2462  
__qdf_nbuf_get_icmpv4_tgt_ip(uint8_t * data)2463  uint32_t __qdf_nbuf_get_icmpv4_tgt_ip(uint8_t *data)
2464  {
2465  	uint32_t tgt_ip;
2466  
2467  	tgt_ip = (uint32_t)(*(uint32_t *)(data +
2468  				QDF_NBUF_PKT_ICMPv4_TGT_IP_OFFSET));
2469  
2470  	return tgt_ip;
2471  }
2472  
__qdf_nbuf_data_is_ipv6_pkt(uint8_t * data)2473  bool __qdf_nbuf_data_is_ipv6_pkt(uint8_t *data)
2474  {
2475  	uint16_t ether_type;
2476  
2477  	ether_type = (uint16_t)(*(uint16_t *)(data +
2478  				QDF_NBUF_TRAC_ETH_TYPE_OFFSET));
2479  
2480  	if (ether_type == QDF_SWAP_U16(QDF_NBUF_TRAC_IPV6_ETH_TYPE))
2481  		return true;
2482  	else
2483  		return false;
2484  }
2485  qdf_export_symbol(__qdf_nbuf_data_is_ipv6_pkt);
2486  
__qdf_nbuf_data_is_ipv6_dhcp_pkt(uint8_t * data)2487  bool __qdf_nbuf_data_is_ipv6_dhcp_pkt(uint8_t *data)
2488  {
2489  	uint16_t sport;
2490  	uint16_t dport;
2491  	uint8_t ipv6_offset;
2492  
2493  	if (!__qdf_nbuf_data_is_ipv6_pkt(data))
2494  		return false;
2495  
2496  	ipv6_offset = __qdf_nbuf_get_ip_offset(data);
2497  	sport = *(uint16_t *)(data + ipv6_offset +
2498  			      QDF_NBUF_TRAC_IPV6_HEADER_SIZE);
2499  	dport = *(uint16_t *)(data + ipv6_offset +
2500  			      QDF_NBUF_TRAC_IPV6_HEADER_SIZE +
2501  			      sizeof(uint16_t));
2502  
2503  	if (((sport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP6_SRV_PORT)) &&
2504  	     (dport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP6_CLI_PORT))) ||
2505  	    ((sport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP6_CLI_PORT)) &&
2506  	     (dport == QDF_SWAP_U16(QDF_NBUF_TRAC_DHCP6_SRV_PORT))))
2507  		return true;
2508  	else
2509  		return false;
2510  }
2511  qdf_export_symbol(__qdf_nbuf_data_is_ipv6_dhcp_pkt);
2512  
__qdf_nbuf_data_is_ipv6_mdns_pkt(uint8_t * data)2513  bool __qdf_nbuf_data_is_ipv6_mdns_pkt(uint8_t *data)
2514  {
2515  	uint16_t sport;
2516  	uint16_t dport;
2517  
2518  	sport = *(uint16_t *)(data + QDF_NBUF_TRAC_IPV6_OFFSET +
2519  				QDF_NBUF_TRAC_IPV6_HEADER_SIZE);
2520  	dport = *(uint16_t *)(data + QDF_NBUF_TRAC_IPV6_OFFSET +
2521  					QDF_NBUF_TRAC_IPV6_HEADER_SIZE +
2522  					sizeof(uint16_t));
2523  
2524  	if (sport == QDF_SWAP_U16(QDF_NBUF_TRAC_MDNS_SRC_N_DST_PORT) &&
2525  	    dport == sport)
2526  		return true;
2527  	else
2528  		return false;
2529  }
2530  
2531  qdf_export_symbol(__qdf_nbuf_data_is_ipv6_mdns_pkt);
2532  
__qdf_nbuf_data_is_ipv4_mcast_pkt(uint8_t * data)2533  bool __qdf_nbuf_data_is_ipv4_mcast_pkt(uint8_t *data)
2534  {
2535  	if (__qdf_nbuf_data_is_ipv4_pkt(data)) {
2536  		uint32_t *dst_addr =
2537  		      (uint32_t *)(data + QDF_NBUF_TRAC_IPV4_DEST_ADDR_OFFSET);
2538  
2539  		/*
2540  		 * Check first word of the IPV4 address and if it is
2541  		 * equal to 0xE then it represents multicast IP.
2542  		 */
2543  		if ((*dst_addr & QDF_NBUF_TRAC_IPV4_ADDR_BCAST_MASK) ==
2544  				QDF_NBUF_TRAC_IPV4_ADDR_MCAST_MASK)
2545  			return true;
2546  		else
2547  			return false;
2548  	} else
2549  		return false;
2550  }
2551  
__qdf_nbuf_data_is_ipv6_mcast_pkt(uint8_t * data)2552  bool __qdf_nbuf_data_is_ipv6_mcast_pkt(uint8_t *data)
2553  {
2554  	if (__qdf_nbuf_data_is_ipv6_pkt(data)) {
2555  		uint16_t *dst_addr;
2556  
2557  		dst_addr = (uint16_t *)
2558  			(data + QDF_NBUF_TRAC_IPV6_DEST_ADDR_OFFSET);
2559  
2560  		/*
2561  		 * Check first byte of the IP address and if it
2562  		 * 0xFF00 then it is a IPV6 mcast packet.
2563  		 */
2564  		if (*dst_addr ==
2565  		     QDF_SWAP_U16(QDF_NBUF_TRAC_IPV6_DEST_ADDR))
2566  			return true;
2567  		else
2568  			return false;
2569  	} else
2570  		return false;
2571  }
2572  
__qdf_nbuf_data_is_icmp_pkt(uint8_t * data)2573  bool __qdf_nbuf_data_is_icmp_pkt(uint8_t *data)
2574  {
2575  	if (__qdf_nbuf_data_is_ipv4_pkt(data)) {
2576  		uint8_t pkt_type;
2577  
2578  		pkt_type = (uint8_t)(*(uint8_t *)(data +
2579  				QDF_NBUF_TRAC_IPV4_PROTO_TYPE_OFFSET));
2580  
2581  		if (pkt_type == QDF_NBUF_TRAC_ICMP_TYPE)
2582  			return true;
2583  		else
2584  			return false;
2585  	} else
2586  		return false;
2587  }
2588  
2589  qdf_export_symbol(__qdf_nbuf_data_is_icmp_pkt);
2590  
__qdf_nbuf_data_is_icmpv6_pkt(uint8_t * data)2591  bool __qdf_nbuf_data_is_icmpv6_pkt(uint8_t *data)
2592  {
2593  	if (__qdf_nbuf_data_is_ipv6_pkt(data)) {
2594  		uint8_t pkt_type;
2595  
2596  		pkt_type = (uint8_t)(*(uint8_t *)(data +
2597  				QDF_NBUF_TRAC_IPV6_PROTO_TYPE_OFFSET));
2598  
2599  		if (pkt_type == QDF_NBUF_TRAC_ICMPV6_TYPE)
2600  			return true;
2601  		else
2602  			return false;
2603  	} else
2604  		return false;
2605  }
2606  
2607  qdf_export_symbol(__qdf_nbuf_data_is_icmpv6_pkt);
2608  
__qdf_nbuf_data_is_ipv4_udp_pkt(uint8_t * data)2609  bool __qdf_nbuf_data_is_ipv4_udp_pkt(uint8_t *data)
2610  {
2611  	if (__qdf_nbuf_data_is_ipv4_pkt(data)) {
2612  		uint8_t pkt_type;
2613  
2614  		pkt_type = (uint8_t)(*(uint8_t *)(data +
2615  				QDF_NBUF_TRAC_IPV4_PROTO_TYPE_OFFSET));
2616  
2617  		if (pkt_type == QDF_NBUF_TRAC_UDP_TYPE)
2618  			return true;
2619  		else
2620  			return false;
2621  	} else
2622  		return false;
2623  }
2624  
__qdf_nbuf_data_is_ipv4_tcp_pkt(uint8_t * data)2625  bool __qdf_nbuf_data_is_ipv4_tcp_pkt(uint8_t *data)
2626  {
2627  	if (__qdf_nbuf_data_is_ipv4_pkt(data)) {
2628  		uint8_t pkt_type;
2629  
2630  		pkt_type = (uint8_t)(*(uint8_t *)(data +
2631  				QDF_NBUF_TRAC_IPV4_PROTO_TYPE_OFFSET));
2632  
2633  		if (pkt_type == QDF_NBUF_TRAC_TCP_TYPE)
2634  			return true;
2635  		else
2636  			return false;
2637  	} else
2638  		return false;
2639  }
2640  
__qdf_nbuf_data_is_ipv6_udp_pkt(uint8_t * data)2641  bool __qdf_nbuf_data_is_ipv6_udp_pkt(uint8_t *data)
2642  {
2643  	if (__qdf_nbuf_data_is_ipv6_pkt(data)) {
2644  		uint8_t pkt_type;
2645  
2646  		pkt_type = (uint8_t)(*(uint8_t *)(data +
2647  				QDF_NBUF_TRAC_IPV6_PROTO_TYPE_OFFSET));
2648  
2649  		if (pkt_type == QDF_NBUF_TRAC_UDP_TYPE)
2650  			return true;
2651  		else
2652  			return false;
2653  	} else
2654  		return false;
2655  }
2656  
__qdf_nbuf_data_is_ipv6_tcp_pkt(uint8_t * data)2657  bool __qdf_nbuf_data_is_ipv6_tcp_pkt(uint8_t *data)
2658  {
2659  	if (__qdf_nbuf_data_is_ipv6_pkt(data)) {
2660  		uint8_t pkt_type;
2661  
2662  		pkt_type = (uint8_t)(*(uint8_t *)(data +
2663  				QDF_NBUF_TRAC_IPV6_PROTO_TYPE_OFFSET));
2664  
2665  		if (pkt_type == QDF_NBUF_TRAC_TCP_TYPE)
2666  			return true;
2667  		else
2668  			return false;
2669  	} else
2670  		return false;
2671  }
2672  
__qdf_nbuf_is_bcast_pkt(qdf_nbuf_t nbuf)2673  bool __qdf_nbuf_is_bcast_pkt(qdf_nbuf_t nbuf)
2674  {
2675  	struct ethhdr *eh = (struct ethhdr *)qdf_nbuf_data(nbuf);
2676  	return qdf_is_macaddr_broadcast((struct qdf_mac_addr *)eh->h_dest);
2677  }
2678  qdf_export_symbol(__qdf_nbuf_is_bcast_pkt);
2679  
__qdf_nbuf_is_mcast_replay(qdf_nbuf_t nbuf)2680  bool __qdf_nbuf_is_mcast_replay(qdf_nbuf_t nbuf)
2681  {
2682  	struct sk_buff *skb = (struct sk_buff *)nbuf;
2683  	struct ethhdr *eth = eth_hdr(skb);
2684  
2685  	if (qdf_likely(skb->pkt_type != PACKET_MULTICAST))
2686  		return false;
2687  
2688  	if (qdf_unlikely(ether_addr_equal(eth->h_source, skb->dev->dev_addr)))
2689  		return true;
2690  
2691  	return false;
2692  }
2693  
__qdf_nbuf_is_arp_local(struct sk_buff * skb)2694  bool __qdf_nbuf_is_arp_local(struct sk_buff *skb)
2695  {
2696  	struct arphdr *arp;
2697  	struct in_ifaddr **ifap = NULL;
2698  	struct in_ifaddr *ifa = NULL;
2699  	struct in_device *in_dev;
2700  	unsigned char *arp_ptr;
2701  	__be32 tip;
2702  
2703  	arp = (struct arphdr *)skb->data;
2704  	if (arp->ar_op == htons(ARPOP_REQUEST)) {
2705  		/* if fail to acquire rtnl lock, assume it's local arp */
2706  		if (!rtnl_trylock())
2707  			return true;
2708  
2709  		in_dev = __in_dev_get_rtnl(skb->dev);
2710  		if (in_dev) {
2711  			for (ifap = &in_dev->ifa_list; (ifa = *ifap) != NULL;
2712  				ifap = &ifa->ifa_next) {
2713  				if (!strcmp(skb->dev->name, ifa->ifa_label))
2714  					break;
2715  			}
2716  		}
2717  
2718  		if (ifa && ifa->ifa_local) {
2719  			arp_ptr = (unsigned char *)(arp + 1);
2720  			arp_ptr += (skb->dev->addr_len + 4 +
2721  					skb->dev->addr_len);
2722  			memcpy(&tip, arp_ptr, 4);
2723  			qdf_debug("ARP packet: local IP: %x dest IP: %x",
2724  				  ifa->ifa_local, tip);
2725  			if (ifa->ifa_local == tip) {
2726  				rtnl_unlock();
2727  				return true;
2728  			}
2729  		}
2730  		rtnl_unlock();
2731  	}
2732  
2733  	return false;
2734  }
2735  
2736  /**
2737   * __qdf_nbuf_data_get_tcp_hdr_len() - get TCP header length
2738   * @data: pointer to data of network buffer
2739   * @tcp_hdr_len_offset: bytes offset for tcp header length of ethernet packets
2740   *
2741   * Return: TCP header length in unit of byte
2742   */
2743  static inline
__qdf_nbuf_data_get_tcp_hdr_len(uint8_t * data,uint8_t tcp_hdr_len_offset)2744  uint8_t __qdf_nbuf_data_get_tcp_hdr_len(uint8_t *data,
2745  					uint8_t tcp_hdr_len_offset)
2746  {
2747  	uint8_t tcp_hdr_len;
2748  
2749  	tcp_hdr_len =
2750  		*((uint8_t *)(data + tcp_hdr_len_offset));
2751  
2752  	tcp_hdr_len = ((tcp_hdr_len & QDF_NBUF_PKT_TCP_HDR_LEN_MASK) >>
2753  		       QDF_NBUF_PKT_TCP_HDR_LEN_LSB) *
2754  		       QDF_NBUF_PKT_TCP_HDR_LEN_UNIT;
2755  
2756  	return tcp_hdr_len;
2757  }
2758  
__qdf_nbuf_is_ipv4_v6_pure_tcp_ack(struct sk_buff * skb)2759  bool __qdf_nbuf_is_ipv4_v6_pure_tcp_ack(struct sk_buff *skb)
2760  {
2761  	bool is_tcp_ack = false;
2762  	uint8_t op_code, tcp_hdr_len;
2763  	uint16_t ip_payload_len;
2764  	uint8_t *data = skb->data;
2765  
2766  	/*
2767  	 * If packet length > TCP ACK max length or it's nonlinearized,
2768  	 * then it must not be TCP ACK.
2769  	 */
2770  	if (qdf_nbuf_len(skb) > QDF_NBUF_PKT_TCP_ACK_MAX_LEN ||
2771  	    qdf_nbuf_is_nonlinear(skb))
2772  		return false;
2773  
2774  	if (qdf_nbuf_is_ipv4_tcp_pkt(skb)) {
2775  		ip_payload_len =
2776  			QDF_SWAP_U16(*((uint16_t *)(data +
2777  				     QDF_NBUF_TRAC_IPV4_TOTAL_LEN_OFFSET)))
2778  					- QDF_NBUF_TRAC_IPV4_HEADER_SIZE;
2779  
2780  		tcp_hdr_len = __qdf_nbuf_data_get_tcp_hdr_len(
2781  					data,
2782  					QDF_NBUF_PKT_IPV4_TCP_HDR_LEN_OFFSET);
2783  
2784  		op_code = (uint8_t)(*(uint8_t *)(data +
2785  				QDF_NBUF_PKT_IPV4_TCP_OPCODE_OFFSET));
2786  
2787  		if (ip_payload_len == tcp_hdr_len &&
2788  		    op_code == QDF_NBUF_PKT_TCPOP_ACK)
2789  			is_tcp_ack = true;
2790  
2791  	} else if (qdf_nbuf_is_ipv6_tcp_pkt(skb)) {
2792  		ip_payload_len =
2793  			QDF_SWAP_U16(*((uint16_t *)(data +
2794  				QDF_NBUF_TRAC_IPV6_PAYLOAD_LEN_OFFSET)));
2795  
2796  		tcp_hdr_len = __qdf_nbuf_data_get_tcp_hdr_len(
2797  					data,
2798  					QDF_NBUF_PKT_IPV6_TCP_HDR_LEN_OFFSET);
2799  		op_code = (uint8_t)(*(uint8_t *)(data +
2800  				QDF_NBUF_PKT_IPV6_TCP_OPCODE_OFFSET));
2801  
2802  		if (ip_payload_len == tcp_hdr_len &&
2803  		    op_code == QDF_NBUF_PKT_TCPOP_ACK)
2804  			is_tcp_ack = true;
2805  	}
2806  
2807  	return is_tcp_ack;
2808  }
2809  
2810  #ifdef QCA_DP_NBUF_FAST_RECYCLE_CHECK
qdf_nbuf_fast_xmit(qdf_nbuf_t nbuf)2811  bool qdf_nbuf_fast_xmit(qdf_nbuf_t nbuf)
2812  {
2813  	return nbuf->fast_xmit;
2814  }
2815  
2816  qdf_export_symbol(qdf_nbuf_fast_xmit);
2817  
qdf_nbuf_set_fast_xmit(qdf_nbuf_t nbuf,int value)2818  void qdf_nbuf_set_fast_xmit(qdf_nbuf_t nbuf, int value)
2819  {
2820  	nbuf->fast_xmit = value;
2821  }
2822  
2823  qdf_export_symbol(qdf_nbuf_set_fast_xmit);
2824  #else
qdf_nbuf_fast_xmit(qdf_nbuf_t nbuf)2825  bool qdf_nbuf_fast_xmit(qdf_nbuf_t nbuf)
2826  {
2827  	return false;
2828  }
2829  
2830  qdf_export_symbol(qdf_nbuf_fast_xmit);
2831  
qdf_nbuf_set_fast_xmit(qdf_nbuf_t nbuf,int value)2832  void qdf_nbuf_set_fast_xmit(qdf_nbuf_t nbuf, int value)
2833  {
2834  }
2835  
2836  qdf_export_symbol(qdf_nbuf_set_fast_xmit);
2837  #endif
2838  
2839  #ifdef NBUF_MEMORY_DEBUG
2840  
2841  static spinlock_t g_qdf_net_buf_track_lock[QDF_NET_BUF_TRACK_MAX_SIZE];
2842  
2843  static QDF_NBUF_TRACK *gp_qdf_net_buf_track_tbl[QDF_NET_BUF_TRACK_MAX_SIZE];
2844  static struct kmem_cache *nbuf_tracking_cache;
2845  static QDF_NBUF_TRACK *qdf_net_buf_track_free_list;
2846  static spinlock_t qdf_net_buf_track_free_list_lock;
2847  static uint32_t qdf_net_buf_track_free_list_count;
2848  static uint32_t qdf_net_buf_track_used_list_count;
2849  static uint32_t qdf_net_buf_track_max_used;
2850  static uint32_t qdf_net_buf_track_max_free;
2851  static uint32_t qdf_net_buf_track_max_allocated;
2852  static uint32_t qdf_net_buf_track_fail_count;
2853  
2854  /**
2855   * update_max_used() - update qdf_net_buf_track_max_used tracking variable
2856   *
2857   * tracks the max number of network buffers that the wlan driver was tracking
2858   * at any one time.
2859   *
2860   * Return: none
2861   */
update_max_used(void)2862  static inline void update_max_used(void)
2863  {
2864  	int sum;
2865  
2866  	if (qdf_net_buf_track_max_used <
2867  	    qdf_net_buf_track_used_list_count)
2868  		qdf_net_buf_track_max_used = qdf_net_buf_track_used_list_count;
2869  	sum = qdf_net_buf_track_free_list_count +
2870  		qdf_net_buf_track_used_list_count;
2871  	if (qdf_net_buf_track_max_allocated < sum)
2872  		qdf_net_buf_track_max_allocated = sum;
2873  }
2874  
2875  /**
2876   * update_max_free() - update qdf_net_buf_track_free_list_count
2877   *
2878   * tracks the max number tracking buffers kept in the freelist.
2879   *
2880   * Return: none
2881   */
update_max_free(void)2882  static inline void update_max_free(void)
2883  {
2884  	if (qdf_net_buf_track_max_free <
2885  	    qdf_net_buf_track_free_list_count)
2886  		qdf_net_buf_track_max_free = qdf_net_buf_track_free_list_count;
2887  }
2888  
2889  /**
2890   * qdf_nbuf_track_alloc() - allocate a cookie to track nbufs allocated by wlan
2891   *
2892   * This function pulls from a freelist if possible and uses kmem_cache_alloc.
2893   * This function also ads fexibility to adjust the allocation and freelist
2894   * scheems.
2895   *
2896   * Return: a pointer to an unused QDF_NBUF_TRACK structure may not be zeroed.
2897   */
qdf_nbuf_track_alloc(void)2898  static QDF_NBUF_TRACK *qdf_nbuf_track_alloc(void)
2899  {
2900  	int flags = GFP_KERNEL;
2901  	unsigned long irq_flag;
2902  	QDF_NBUF_TRACK *new_node = NULL;
2903  
2904  	spin_lock_irqsave(&qdf_net_buf_track_free_list_lock, irq_flag);
2905  	qdf_net_buf_track_used_list_count++;
2906  	if (qdf_net_buf_track_free_list) {
2907  		new_node = qdf_net_buf_track_free_list;
2908  		qdf_net_buf_track_free_list =
2909  			qdf_net_buf_track_free_list->p_next;
2910  		qdf_net_buf_track_free_list_count--;
2911  	}
2912  	update_max_used();
2913  	spin_unlock_irqrestore(&qdf_net_buf_track_free_list_lock, irq_flag);
2914  
2915  	if (new_node)
2916  		return new_node;
2917  
2918  	if (in_interrupt() || irqs_disabled() || in_atomic())
2919  		flags = GFP_ATOMIC;
2920  
2921  	return kmem_cache_alloc(nbuf_tracking_cache, flags);
2922  }
2923  
2924  /* FREEQ_POOLSIZE initial and minimum desired freelist poolsize */
2925  #define FREEQ_POOLSIZE 2048
2926  
2927  /**
2928   * qdf_nbuf_track_free() - free the nbuf tracking cookie.
2929   * @node: nbuf tracking node
2930   *
2931   * Matches calls to qdf_nbuf_track_alloc.
2932   * Either frees the tracking cookie to kernel or an internal
2933   * freelist based on the size of the freelist.
2934   *
2935   * Return: none
2936   */
qdf_nbuf_track_free(QDF_NBUF_TRACK * node)2937  static void qdf_nbuf_track_free(QDF_NBUF_TRACK *node)
2938  {
2939  	unsigned long irq_flag;
2940  
2941  	if (!node)
2942  		return;
2943  
2944  	/* Try to shrink the freelist if free_list_count > than FREEQ_POOLSIZE
2945  	 * only shrink the freelist if it is bigger than twice the number of
2946  	 * nbufs in use. If the driver is stalling in a consistent bursty
2947  	 * fashion, this will keep 3/4 of thee allocations from the free list
2948  	 * while also allowing the system to recover memory as less frantic
2949  	 * traffic occurs.
2950  	 */
2951  
2952  	spin_lock_irqsave(&qdf_net_buf_track_free_list_lock, irq_flag);
2953  
2954  	qdf_net_buf_track_used_list_count--;
2955  	if (qdf_net_buf_track_free_list_count > FREEQ_POOLSIZE &&
2956  	   (qdf_net_buf_track_free_list_count >
2957  	    qdf_net_buf_track_used_list_count << 1)) {
2958  		kmem_cache_free(nbuf_tracking_cache, node);
2959  	} else {
2960  		node->p_next = qdf_net_buf_track_free_list;
2961  		qdf_net_buf_track_free_list = node;
2962  		qdf_net_buf_track_free_list_count++;
2963  	}
2964  	update_max_free();
2965  	spin_unlock_irqrestore(&qdf_net_buf_track_free_list_lock, irq_flag);
2966  }
2967  
2968  /**
2969   * qdf_nbuf_track_prefill() - prefill the nbuf tracking cookie freelist
2970   *
2971   * Removes a 'warmup time' characteristic of the freelist.  Prefilling
2972   * the freelist first makes it performant for the first iperf udp burst
2973   * as well as steady state.
2974   *
2975   * Return: None
2976   */
qdf_nbuf_track_prefill(void)2977  static void qdf_nbuf_track_prefill(void)
2978  {
2979  	int i;
2980  	QDF_NBUF_TRACK *node, *head;
2981  
2982  	/* prepopulate the freelist */
2983  	head = NULL;
2984  	for (i = 0; i < FREEQ_POOLSIZE; i++) {
2985  		node = qdf_nbuf_track_alloc();
2986  		if (!node)
2987  			continue;
2988  		node->p_next = head;
2989  		head = node;
2990  	}
2991  	while (head) {
2992  		node = head->p_next;
2993  		qdf_nbuf_track_free(head);
2994  		head = node;
2995  	}
2996  
2997  	/* prefilled buffers should not count as used */
2998  	qdf_net_buf_track_max_used = 0;
2999  }
3000  
3001  /**
3002   * qdf_nbuf_track_memory_manager_create() - manager for nbuf tracking cookies
3003   *
3004   * This initializes the memory manager for the nbuf tracking cookies.  Because
3005   * these cookies are all the same size and only used in this feature, we can
3006   * use a kmem_cache to provide tracking as well as to speed up allocations.
3007   * To avoid the overhead of allocating and freeing the buffers (including SLUB
3008   * features) a freelist is prepopulated here.
3009   *
3010   * Return: None
3011   */
qdf_nbuf_track_memory_manager_create(void)3012  static void qdf_nbuf_track_memory_manager_create(void)
3013  {
3014  	spin_lock_init(&qdf_net_buf_track_free_list_lock);
3015  	nbuf_tracking_cache = kmem_cache_create("qdf_nbuf_tracking_cache",
3016  						sizeof(QDF_NBUF_TRACK),
3017  						0, 0, NULL);
3018  
3019  	qdf_nbuf_track_prefill();
3020  }
3021  
3022  /**
3023   * qdf_nbuf_track_memory_manager_destroy() - manager for nbuf tracking cookies
3024   *
3025   * Empty the freelist and print out usage statistics when it is no longer
3026   * needed. Also the kmem_cache should be destroyed here so that it can warn if
3027   * any nbuf tracking cookies were leaked.
3028   *
3029   * Return: None
3030   */
qdf_nbuf_track_memory_manager_destroy(void)3031  static void qdf_nbuf_track_memory_manager_destroy(void)
3032  {
3033  	QDF_NBUF_TRACK *node, *tmp;
3034  	unsigned long irq_flag;
3035  
3036  	spin_lock_irqsave(&qdf_net_buf_track_free_list_lock, irq_flag);
3037  	node = qdf_net_buf_track_free_list;
3038  
3039  	if (qdf_net_buf_track_max_used > FREEQ_POOLSIZE * 4)
3040  		qdf_print("%s: unexpectedly large max_used count %d",
3041  			  __func__, qdf_net_buf_track_max_used);
3042  
3043  	if (qdf_net_buf_track_max_used < qdf_net_buf_track_max_allocated)
3044  		qdf_print("%s: %d unused trackers were allocated",
3045  			  __func__,
3046  			  qdf_net_buf_track_max_allocated -
3047  			  qdf_net_buf_track_max_used);
3048  
3049  	if (qdf_net_buf_track_free_list_count > FREEQ_POOLSIZE &&
3050  	    qdf_net_buf_track_free_list_count > 3*qdf_net_buf_track_max_used/4)
3051  		qdf_print("%s: check freelist shrinking functionality",
3052  			  __func__);
3053  
3054  	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO,
3055  		  "%s: %d residual freelist size",
3056  		  __func__, qdf_net_buf_track_free_list_count);
3057  
3058  	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO,
3059  		  "%s: %d max freelist size observed",
3060  		  __func__, qdf_net_buf_track_max_free);
3061  
3062  	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO,
3063  		  "%s: %d max buffers used observed",
3064  		  __func__, qdf_net_buf_track_max_used);
3065  
3066  	QDF_TRACE(QDF_MODULE_ID_QDF, QDF_TRACE_LEVEL_INFO,
3067  		  "%s: %d max buffers allocated observed",
3068  		  __func__, qdf_net_buf_track_max_allocated);
3069  
3070  	while (node) {
3071  		tmp = node;
3072  		node = node->p_next;
3073  		kmem_cache_free(nbuf_tracking_cache, tmp);
3074  		qdf_net_buf_track_free_list_count--;
3075  	}
3076  
3077  	if (qdf_net_buf_track_free_list_count != 0)
3078  		qdf_info("%d unfreed tracking memory lost in freelist",
3079  			 qdf_net_buf_track_free_list_count);
3080  
3081  	if (qdf_net_buf_track_used_list_count != 0)
3082  		qdf_info("%d unfreed tracking memory still in use",
3083  			 qdf_net_buf_track_used_list_count);
3084  
3085  	spin_unlock_irqrestore(&qdf_net_buf_track_free_list_lock, irq_flag);
3086  	kmem_cache_destroy(nbuf_tracking_cache);
3087  	qdf_net_buf_track_free_list = NULL;
3088  }
3089  
qdf_net_buf_debug_init(void)3090  void qdf_net_buf_debug_init(void)
3091  {
3092  	uint32_t i;
3093  
3094  	is_initial_mem_debug_disabled = qdf_mem_debug_config_get();
3095  
3096  	if (is_initial_mem_debug_disabled)
3097  		return;
3098  
3099  	qdf_atomic_set(&qdf_nbuf_history_index, -1);
3100  
3101  	qdf_nbuf_map_tracking_init();
3102  	qdf_nbuf_smmu_map_tracking_init();
3103  	qdf_nbuf_track_memory_manager_create();
3104  
3105  	for (i = 0; i < QDF_NET_BUF_TRACK_MAX_SIZE; i++) {
3106  		gp_qdf_net_buf_track_tbl[i] = NULL;
3107  		spin_lock_init(&g_qdf_net_buf_track_lock[i]);
3108  	}
3109  }
3110  qdf_export_symbol(qdf_net_buf_debug_init);
3111  
qdf_net_buf_debug_exit(void)3112  void qdf_net_buf_debug_exit(void)
3113  {
3114  	uint32_t i;
3115  	uint32_t count = 0;
3116  	unsigned long irq_flag;
3117  	QDF_NBUF_TRACK *p_node;
3118  	QDF_NBUF_TRACK *p_prev;
3119  
3120  	if (is_initial_mem_debug_disabled)
3121  		return;
3122  
3123  	for (i = 0; i < QDF_NET_BUF_TRACK_MAX_SIZE; i++) {
3124  		spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag);
3125  		p_node = gp_qdf_net_buf_track_tbl[i];
3126  		while (p_node) {
3127  			p_prev = p_node;
3128  			p_node = p_node->p_next;
3129  			count++;
3130  			qdf_info("SKB buf memory Leak@ Func %s, @Line %d, size %zu, nbuf %pK",
3131  				 p_prev->func_name, p_prev->line_num,
3132  				 p_prev->size, p_prev->net_buf);
3133  			qdf_info("SKB leak map %s, line %d, unmap %s line %d mapped=%d",
3134  				 p_prev->map_func_name,
3135  				 p_prev->map_line_num,
3136  				 p_prev->unmap_func_name,
3137  				 p_prev->unmap_line_num,
3138  				 p_prev->is_nbuf_mapped);
3139  			qdf_nbuf_track_free(p_prev);
3140  		}
3141  		spin_unlock_irqrestore(&g_qdf_net_buf_track_lock[i], irq_flag);
3142  	}
3143  
3144  	qdf_nbuf_track_memory_manager_destroy();
3145  	qdf_nbuf_map_tracking_deinit();
3146  	qdf_nbuf_smmu_map_tracking_deinit();
3147  
3148  #ifdef CONFIG_HALT_KMEMLEAK
3149  	if (count) {
3150  		qdf_err("%d SKBs leaked .. please fix the SKB leak", count);
3151  		QDF_BUG(0);
3152  	}
3153  #endif
3154  }
3155  qdf_export_symbol(qdf_net_buf_debug_exit);
3156  
3157  /**
3158   * qdf_net_buf_debug_hash() - hash network buffer pointer
3159   * @net_buf: network buffer
3160   *
3161   * Return: hash value
3162   */
qdf_net_buf_debug_hash(qdf_nbuf_t net_buf)3163  static uint32_t qdf_net_buf_debug_hash(qdf_nbuf_t net_buf)
3164  {
3165  	uint32_t i;
3166  
3167  	i = (uint32_t) (((uintptr_t) net_buf) >> 4);
3168  	i += (uint32_t) (((uintptr_t) net_buf) >> 14);
3169  	i &= (QDF_NET_BUF_TRACK_MAX_SIZE - 1);
3170  
3171  	return i;
3172  }
3173  
3174  /**
3175   * qdf_net_buf_debug_look_up() - look up network buffer in debug hash table
3176   * @net_buf: network buffer
3177   *
3178   * Return: If skb is found in hash table then return pointer to network buffer
3179   *	else return %NULL
3180   */
qdf_net_buf_debug_look_up(qdf_nbuf_t net_buf)3181  static QDF_NBUF_TRACK *qdf_net_buf_debug_look_up(qdf_nbuf_t net_buf)
3182  {
3183  	uint32_t i;
3184  	QDF_NBUF_TRACK *p_node;
3185  
3186  	i = qdf_net_buf_debug_hash(net_buf);
3187  	p_node = gp_qdf_net_buf_track_tbl[i];
3188  
3189  	while (p_node) {
3190  		if (p_node->net_buf == net_buf)
3191  			return p_node;
3192  		p_node = p_node->p_next;
3193  	}
3194  
3195  	return NULL;
3196  }
3197  
qdf_net_buf_debug_add_node(qdf_nbuf_t net_buf,size_t size,const char * func_name,uint32_t line_num)3198  void qdf_net_buf_debug_add_node(qdf_nbuf_t net_buf, size_t size,
3199  				const char *func_name, uint32_t line_num)
3200  {
3201  	uint32_t i;
3202  	unsigned long irq_flag;
3203  	QDF_NBUF_TRACK *p_node;
3204  	QDF_NBUF_TRACK *new_node;
3205  
3206  	if (is_initial_mem_debug_disabled)
3207  		return;
3208  
3209  	new_node = qdf_nbuf_track_alloc();
3210  
3211  	i = qdf_net_buf_debug_hash(net_buf);
3212  	spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag);
3213  
3214  	p_node = qdf_net_buf_debug_look_up(net_buf);
3215  
3216  	if (p_node) {
3217  		qdf_print("Double allocation of skb ! Already allocated from %pK %s %d current alloc from %pK %s %d",
3218  			  p_node->net_buf, p_node->func_name, p_node->line_num,
3219  			  net_buf, func_name, line_num);
3220  		qdf_nbuf_track_free(new_node);
3221  	} else {
3222  		p_node = new_node;
3223  		if (p_node) {
3224  			p_node->net_buf = net_buf;
3225  			qdf_str_lcopy(p_node->func_name, func_name,
3226  				      QDF_MEM_FUNC_NAME_SIZE);
3227  			p_node->line_num = line_num;
3228  			p_node->is_nbuf_mapped = false;
3229  			p_node->map_line_num = 0;
3230  			p_node->unmap_line_num = 0;
3231  			p_node->map_func_name[0] = '\0';
3232  			p_node->unmap_func_name[0] = '\0';
3233  			p_node->size = size;
3234  			p_node->time = qdf_get_log_timestamp();
3235  			qdf_net_buf_update_smmu_params(p_node);
3236  			qdf_mem_skb_inc(size);
3237  			p_node->p_next = gp_qdf_net_buf_track_tbl[i];
3238  			gp_qdf_net_buf_track_tbl[i] = p_node;
3239  		} else {
3240  			qdf_net_buf_track_fail_count++;
3241  			qdf_print(
3242  				  "Mem alloc failed ! Could not track skb from %s %d of size %zu",
3243  				  func_name, line_num, size);
3244  		}
3245  	}
3246  
3247  	spin_unlock_irqrestore(&g_qdf_net_buf_track_lock[i], irq_flag);
3248  }
3249  qdf_export_symbol(qdf_net_buf_debug_add_node);
3250  
qdf_net_buf_debug_update_node(qdf_nbuf_t net_buf,const char * func_name,uint32_t line_num)3251  void qdf_net_buf_debug_update_node(qdf_nbuf_t net_buf, const char *func_name,
3252  				   uint32_t line_num)
3253  {
3254  	uint32_t i;
3255  	unsigned long irq_flag;
3256  	QDF_NBUF_TRACK *p_node;
3257  
3258  	if (is_initial_mem_debug_disabled)
3259  		return;
3260  
3261  	i = qdf_net_buf_debug_hash(net_buf);
3262  	spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag);
3263  
3264  	p_node = qdf_net_buf_debug_look_up(net_buf);
3265  
3266  	if (p_node) {
3267  		qdf_str_lcopy(p_node->func_name, kbasename(func_name),
3268  			      QDF_MEM_FUNC_NAME_SIZE);
3269  		p_node->line_num = line_num;
3270  	}
3271  
3272  	spin_unlock_irqrestore(&g_qdf_net_buf_track_lock[i], irq_flag);
3273  }
3274  
3275  qdf_export_symbol(qdf_net_buf_debug_update_node);
3276  
qdf_net_buf_debug_update_map_node(qdf_nbuf_t net_buf,const char * func_name,uint32_t line_num)3277  void qdf_net_buf_debug_update_map_node(qdf_nbuf_t net_buf,
3278  				       const char *func_name,
3279  				       uint32_t line_num)
3280  {
3281  	uint32_t i;
3282  	unsigned long irq_flag;
3283  	QDF_NBUF_TRACK *p_node;
3284  
3285  	if (is_initial_mem_debug_disabled)
3286  		return;
3287  
3288  	i = qdf_net_buf_debug_hash(net_buf);
3289  	spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag);
3290  
3291  	p_node = qdf_net_buf_debug_look_up(net_buf);
3292  
3293  	if (p_node) {
3294  		qdf_str_lcopy(p_node->map_func_name, func_name,
3295  			      QDF_MEM_FUNC_NAME_SIZE);
3296  		p_node->map_line_num = line_num;
3297  		p_node->is_nbuf_mapped = true;
3298  	}
3299  	spin_unlock_irqrestore(&g_qdf_net_buf_track_lock[i], irq_flag);
3300  }
3301  
3302  #ifdef NBUF_SMMU_MAP_UNMAP_DEBUG
qdf_net_buf_debug_update_smmu_map_node(qdf_nbuf_t nbuf,unsigned long iova,unsigned long pa,const char * func,uint32_t line)3303  void qdf_net_buf_debug_update_smmu_map_node(qdf_nbuf_t nbuf,
3304  					    unsigned long iova,
3305  					    unsigned long pa,
3306  					    const char *func,
3307  					    uint32_t line)
3308  {
3309  	uint32_t i;
3310  	unsigned long irq_flag;
3311  	QDF_NBUF_TRACK *p_node;
3312  
3313  	if (is_initial_mem_debug_disabled)
3314  		return;
3315  
3316  	i = qdf_net_buf_debug_hash(nbuf);
3317  	spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag);
3318  
3319  	p_node = qdf_net_buf_debug_look_up(nbuf);
3320  
3321  	if (p_node) {
3322  		qdf_str_lcopy(p_node->smmu_map_func_name, func,
3323  			      QDF_MEM_FUNC_NAME_SIZE);
3324  		p_node->smmu_map_line_num = line;
3325  		p_node->is_nbuf_smmu_mapped = true;
3326  		p_node->smmu_map_iova_addr = iova;
3327  		p_node->smmu_map_pa_addr = pa;
3328  	}
3329  	spin_unlock_irqrestore(&g_qdf_net_buf_track_lock[i], irq_flag);
3330  }
3331  
qdf_net_buf_debug_update_smmu_unmap_node(qdf_nbuf_t nbuf,unsigned long iova,unsigned long pa,const char * func,uint32_t line)3332  void qdf_net_buf_debug_update_smmu_unmap_node(qdf_nbuf_t nbuf,
3333  					      unsigned long iova,
3334  					      unsigned long pa,
3335  					      const char *func,
3336  					      uint32_t line)
3337  {
3338  	uint32_t i;
3339  	unsigned long irq_flag;
3340  	QDF_NBUF_TRACK *p_node;
3341  
3342  	if (is_initial_mem_debug_disabled)
3343  		return;
3344  
3345  	i = qdf_net_buf_debug_hash(nbuf);
3346  	spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag);
3347  
3348  	p_node = qdf_net_buf_debug_look_up(nbuf);
3349  
3350  	if (p_node) {
3351  		qdf_str_lcopy(p_node->smmu_unmap_func_name, func,
3352  			      QDF_MEM_FUNC_NAME_SIZE);
3353  		p_node->smmu_unmap_line_num = line;
3354  		p_node->is_nbuf_smmu_mapped = false;
3355  		p_node->smmu_unmap_iova_addr = iova;
3356  		p_node->smmu_unmap_pa_addr = pa;
3357  	}
3358  	spin_unlock_irqrestore(&g_qdf_net_buf_track_lock[i], irq_flag);
3359  }
3360  #endif
3361  
qdf_net_buf_debug_update_unmap_node(qdf_nbuf_t net_buf,const char * func_name,uint32_t line_num)3362  void qdf_net_buf_debug_update_unmap_node(qdf_nbuf_t net_buf,
3363  					 const char *func_name,
3364  					 uint32_t line_num)
3365  {
3366  	uint32_t i;
3367  	unsigned long irq_flag;
3368  	QDF_NBUF_TRACK *p_node;
3369  
3370  	if (is_initial_mem_debug_disabled)
3371  		return;
3372  
3373  	i = qdf_net_buf_debug_hash(net_buf);
3374  	spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag);
3375  
3376  	p_node = qdf_net_buf_debug_look_up(net_buf);
3377  
3378  	if (p_node) {
3379  		qdf_str_lcopy(p_node->unmap_func_name, func_name,
3380  			      QDF_MEM_FUNC_NAME_SIZE);
3381  		p_node->unmap_line_num = line_num;
3382  		p_node->is_nbuf_mapped = false;
3383  	}
3384  	spin_unlock_irqrestore(&g_qdf_net_buf_track_lock[i], irq_flag);
3385  }
3386  
qdf_net_buf_debug_delete_node(qdf_nbuf_t net_buf)3387  void qdf_net_buf_debug_delete_node(qdf_nbuf_t net_buf)
3388  {
3389  	uint32_t i;
3390  	QDF_NBUF_TRACK *p_head;
3391  	QDF_NBUF_TRACK *p_node = NULL;
3392  	unsigned long irq_flag;
3393  	QDF_NBUF_TRACK *p_prev;
3394  
3395  	if (is_initial_mem_debug_disabled)
3396  		return;
3397  
3398  	i = qdf_net_buf_debug_hash(net_buf);
3399  	spin_lock_irqsave(&g_qdf_net_buf_track_lock[i], irq_flag);
3400  
3401  	p_head = gp_qdf_net_buf_track_tbl[i];
3402  
3403  	/* Unallocated SKB */
3404  	if (!p_head)
3405  		goto done;
3406  
3407  	p_node = p_head;
3408  	/* Found at head of the table */
3409  	if (p_head->net_buf == net_buf) {
3410  		gp_qdf_net_buf_track_tbl[i] = p_node->p_next;
3411  		goto done;
3412  	}
3413  
3414  	/* Search in collision list */
3415  	while (p_node) {
3416  		p_prev = p_node;
3417  		p_node = p_node->p_next;
3418  		if ((p_node) && (p_node->net_buf == net_buf)) {
3419  			p_prev->p_next = p_node->p_next;
3420  			break;
3421  		}
3422  	}
3423  
3424  done:
3425  	spin_unlock_irqrestore(&g_qdf_net_buf_track_lock[i], irq_flag);
3426  
3427  	if (p_node) {
3428  		qdf_mem_skb_dec(p_node->size);
3429  		qdf_nbuf_track_free(p_node);
3430  	} else {
3431  		if (qdf_net_buf_track_fail_count) {
3432  			qdf_print("Untracked net_buf free: %pK with tracking failures count: %u",
3433  				  net_buf, qdf_net_buf_track_fail_count);
3434  		} else
3435  			QDF_MEMDEBUG_PANIC("Unallocated buffer ! Double free of net_buf %pK ?",
3436  					   net_buf);
3437  	}
3438  }
3439  qdf_export_symbol(qdf_net_buf_debug_delete_node);
3440  
qdf_net_buf_debug_acquire_skb(qdf_nbuf_t net_buf,const char * func_name,uint32_t line_num)3441  void qdf_net_buf_debug_acquire_skb(qdf_nbuf_t net_buf,
3442  				   const char *func_name, uint32_t line_num)
3443  {
3444  	qdf_nbuf_t ext_list = qdf_nbuf_get_ext_list(net_buf);
3445  
3446  	if (is_initial_mem_debug_disabled)
3447  		return;
3448  
3449  	while (ext_list) {
3450  		/*
3451  		 * Take care to add if it is Jumbo packet connected using
3452  		 * frag_list
3453  		 */
3454  		qdf_nbuf_t next;
3455  
3456  		next = qdf_nbuf_queue_next(ext_list);
3457  		qdf_net_buf_debug_add_node(ext_list, 0, func_name, line_num);
3458  		ext_list = next;
3459  	}
3460  	qdf_net_buf_debug_add_node(net_buf, 0, func_name, line_num);
3461  }
3462  qdf_export_symbol(qdf_net_buf_debug_acquire_skb);
3463  
qdf_net_buf_debug_release_skb(qdf_nbuf_t net_buf)3464  void qdf_net_buf_debug_release_skb(qdf_nbuf_t net_buf)
3465  {
3466  	qdf_nbuf_t ext_list;
3467  
3468  	if (is_initial_mem_debug_disabled)
3469  		return;
3470  
3471  	ext_list = qdf_nbuf_get_ext_list(net_buf);
3472  	while (ext_list) {
3473  		/*
3474  		 * Take care to free if it is Jumbo packet connected using
3475  		 * frag_list
3476  		 */
3477  		qdf_nbuf_t next;
3478  
3479  		next = qdf_nbuf_queue_next(ext_list);
3480  
3481  		if (qdf_nbuf_get_users(ext_list) > 1) {
3482  			ext_list = next;
3483  			continue;
3484  		}
3485  
3486  		qdf_net_buf_debug_delete_node(ext_list);
3487  		ext_list = next;
3488  	}
3489  
3490  	if (qdf_nbuf_get_users(net_buf) > 1)
3491  		return;
3492  
3493  	qdf_net_buf_debug_delete_node(net_buf);
3494  }
3495  qdf_export_symbol(qdf_net_buf_debug_release_skb);
3496  
qdf_nbuf_alloc_debug(qdf_device_t osdev,qdf_size_t size,int reserve,int align,int prio,const char * func,uint32_t line)3497  qdf_nbuf_t qdf_nbuf_alloc_debug(qdf_device_t osdev, qdf_size_t size,
3498  				int reserve, int align, int prio,
3499  				const char *func, uint32_t line)
3500  {
3501  	qdf_nbuf_t nbuf;
3502  
3503  	if (is_initial_mem_debug_disabled)
3504  		return __qdf_nbuf_alloc(osdev, size,
3505  					reserve, align,
3506  					prio, func, line);
3507  
3508  	nbuf = __qdf_nbuf_alloc(osdev, size, reserve, align, prio, func, line);
3509  
3510  	/* Store SKB in internal QDF tracking table */
3511  	if (qdf_likely(nbuf)) {
3512  		qdf_net_buf_debug_add_node(nbuf, size, func, line);
3513  		qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_ALLOC);
3514  	} else {
3515  		qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_ALLOC_FAILURE);
3516  	}
3517  
3518  	return nbuf;
3519  }
3520  qdf_export_symbol(qdf_nbuf_alloc_debug);
3521  
qdf_nbuf_frag_alloc_debug(qdf_device_t osdev,qdf_size_t size,int reserve,int align,int prio,const char * func,uint32_t line)3522  qdf_nbuf_t qdf_nbuf_frag_alloc_debug(qdf_device_t osdev, qdf_size_t size,
3523  				     int reserve, int align, int prio,
3524  				     const char *func, uint32_t line)
3525  {
3526  	qdf_nbuf_t nbuf;
3527  
3528  	if (is_initial_mem_debug_disabled)
3529  		return __qdf_nbuf_frag_alloc(osdev, size,
3530  					reserve, align,
3531  					prio, func, line);
3532  
3533  	nbuf = __qdf_nbuf_frag_alloc(osdev, size, reserve, align, prio,
3534  				     func, line);
3535  
3536  	/* Store SKB in internal QDF tracking table */
3537  	if (qdf_likely(nbuf)) {
3538  		qdf_net_buf_debug_add_node(nbuf, size, func, line);
3539  		qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_ALLOC);
3540  	} else {
3541  		qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_ALLOC_FAILURE);
3542  	}
3543  
3544  	return nbuf;
3545  }
3546  
3547  qdf_export_symbol(qdf_nbuf_frag_alloc_debug);
3548  
qdf_nbuf_alloc_no_recycler_debug(size_t size,int reserve,int align,const char * func,uint32_t line)3549  qdf_nbuf_t qdf_nbuf_alloc_no_recycler_debug(size_t size, int reserve, int align,
3550  					    const char *func, uint32_t line)
3551  {
3552  	qdf_nbuf_t nbuf;
3553  
3554  	if (is_initial_mem_debug_disabled)
3555  		return __qdf_nbuf_alloc_no_recycler(size, reserve, align, func,
3556  						    line);
3557  
3558  	nbuf = __qdf_nbuf_alloc_no_recycler(size, reserve, align, func, line);
3559  
3560  	/* Store SKB in internal QDF tracking table */
3561  	if (qdf_likely(nbuf)) {
3562  		qdf_net_buf_debug_add_node(nbuf, size, func, line);
3563  		qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_ALLOC);
3564  	} else {
3565  		qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_ALLOC_FAILURE);
3566  	}
3567  
3568  	return nbuf;
3569  }
3570  
3571  qdf_export_symbol(qdf_nbuf_alloc_no_recycler_debug);
3572  
qdf_nbuf_free_debug(qdf_nbuf_t nbuf,const char * func,uint32_t line)3573  void qdf_nbuf_free_debug(qdf_nbuf_t nbuf, const char *func, uint32_t line)
3574  {
3575  	qdf_nbuf_t ext_list;
3576  	qdf_frag_t p_frag;
3577  	uint32_t num_nr_frags;
3578  	uint32_t idx = 0;
3579  
3580  	if (qdf_unlikely(!nbuf))
3581  		return;
3582  
3583  	if (is_initial_mem_debug_disabled)
3584  		goto free_buf;
3585  
3586  	if (qdf_nbuf_get_users(nbuf) > 1)
3587  		goto free_buf;
3588  
3589  	/* Remove SKB from internal QDF tracking table */
3590  	qdf_nbuf_panic_on_free_if_smmu_mapped(nbuf, func, line);
3591  	qdf_nbuf_panic_on_free_if_mapped(nbuf, func, line);
3592  	qdf_net_buf_debug_delete_node(nbuf);
3593  	qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_FREE);
3594  
3595  	/* Take care to delete the debug entries for frags */
3596  	num_nr_frags = qdf_nbuf_get_nr_frags(nbuf);
3597  
3598  	qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
3599  
3600  	while (idx < num_nr_frags) {
3601  		p_frag = qdf_nbuf_get_frag_addr(nbuf, idx);
3602  		if (qdf_likely(p_frag))
3603  			qdf_frag_debug_refcount_dec(p_frag, func, line);
3604  		idx++;
3605  	}
3606  
3607  	/*
3608  	 * Take care to update the debug entries for frag_list and also
3609  	 * for the frags attached to frag_list
3610  	 */
3611  	ext_list = qdf_nbuf_get_ext_list(nbuf);
3612  	while (ext_list) {
3613  		if (qdf_nbuf_get_users(ext_list) == 1) {
3614  			qdf_nbuf_panic_on_free_if_smmu_mapped(ext_list, func,
3615  							      line);
3616  			qdf_nbuf_panic_on_free_if_mapped(ext_list, func, line);
3617  			idx = 0;
3618  			num_nr_frags = qdf_nbuf_get_nr_frags(ext_list);
3619  			qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
3620  			while (idx < num_nr_frags) {
3621  				p_frag = qdf_nbuf_get_frag_addr(ext_list, idx);
3622  				if (qdf_likely(p_frag))
3623  					qdf_frag_debug_refcount_dec(p_frag,
3624  								    func, line);
3625  				idx++;
3626  			}
3627  			qdf_net_buf_debug_delete_node(ext_list);
3628  		}
3629  
3630  		ext_list = qdf_nbuf_queue_next(ext_list);
3631  	}
3632  
3633  free_buf:
3634  	__qdf_nbuf_free(nbuf);
3635  }
3636  qdf_export_symbol(qdf_nbuf_free_debug);
3637  
__qdf_nbuf_alloc_simple(qdf_device_t osdev,size_t size,const char * func,uint32_t line)3638  struct sk_buff *__qdf_nbuf_alloc_simple(qdf_device_t osdev, size_t size,
3639  					const char *func, uint32_t line)
3640  {
3641  	struct sk_buff *skb;
3642  	int flags = GFP_KERNEL;
3643  
3644  	if (in_interrupt() || irqs_disabled() || in_atomic()) {
3645  		flags = GFP_ATOMIC;
3646  #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
3647  		/*
3648  		 * Observed that kcompactd burns out CPU to make order-3 page.
3649  		 *__netdev_alloc_skb has 4k page fallback option just in case of
3650  		 * failing high order page allocation so we don't need to be
3651  		 * hard. Make kcompactd rest in piece.
3652  		 */
3653  		flags = flags & ~__GFP_KSWAPD_RECLAIM;
3654  #endif
3655  	}
3656  
3657  	skb = __netdev_alloc_skb(NULL, size, flags);
3658  
3659  
3660  	if (qdf_likely(is_initial_mem_debug_disabled)) {
3661  		if (qdf_likely(skb))
3662  			qdf_nbuf_count_inc(skb);
3663  	} else {
3664  		if (qdf_likely(skb)) {
3665  			qdf_nbuf_count_inc(skb);
3666  			qdf_net_buf_debug_add_node(skb, size, func, line);
3667  			qdf_nbuf_history_add(skb, func, line, QDF_NBUF_ALLOC);
3668  		} else {
3669  			qdf_nbuf_history_add(skb, func, line, QDF_NBUF_ALLOC_FAILURE);
3670  		}
3671  	}
3672  
3673  
3674  	return skb;
3675  }
3676  
3677  qdf_export_symbol(__qdf_nbuf_alloc_simple);
3678  
qdf_nbuf_free_debug_simple(qdf_nbuf_t nbuf,const char * func,uint32_t line)3679  void qdf_nbuf_free_debug_simple(qdf_nbuf_t nbuf, const char *func,
3680  				uint32_t line)
3681  {
3682  	if (qdf_likely(nbuf)) {
3683  		if (is_initial_mem_debug_disabled) {
3684  			dev_kfree_skb_any(nbuf);
3685  		} else {
3686  			qdf_nbuf_free_debug(nbuf, func, line);
3687  		}
3688  	}
3689  }
3690  
3691  qdf_export_symbol(qdf_nbuf_free_debug_simple);
3692  
qdf_nbuf_clone_debug(qdf_nbuf_t buf,const char * func,uint32_t line)3693  qdf_nbuf_t qdf_nbuf_clone_debug(qdf_nbuf_t buf, const char *func, uint32_t line)
3694  {
3695  	uint32_t num_nr_frags;
3696  	uint32_t idx = 0;
3697  	qdf_nbuf_t ext_list;
3698  	qdf_frag_t p_frag;
3699  
3700  	qdf_nbuf_t cloned_buf = __qdf_nbuf_clone(buf);
3701  
3702  	if (is_initial_mem_debug_disabled)
3703  		return cloned_buf;
3704  
3705  	if (qdf_unlikely(!cloned_buf))
3706  		return NULL;
3707  
3708  	/* Take care to update the debug entries for frags */
3709  	num_nr_frags = qdf_nbuf_get_nr_frags(cloned_buf);
3710  
3711  	qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
3712  
3713  	while (idx < num_nr_frags) {
3714  		p_frag = qdf_nbuf_get_frag_addr(cloned_buf, idx);
3715  		if (qdf_likely(p_frag))
3716  			qdf_frag_debug_refcount_inc(p_frag, func, line);
3717  		idx++;
3718  	}
3719  
3720  	/* Take care to update debug entries for frags attached to frag_list */
3721  	ext_list = qdf_nbuf_get_ext_list(cloned_buf);
3722  	while (ext_list) {
3723  		idx = 0;
3724  		num_nr_frags = qdf_nbuf_get_nr_frags(ext_list);
3725  
3726  		qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
3727  
3728  		while (idx < num_nr_frags) {
3729  			p_frag = qdf_nbuf_get_frag_addr(ext_list, idx);
3730  			if (qdf_likely(p_frag))
3731  				qdf_frag_debug_refcount_inc(p_frag, func, line);
3732  			idx++;
3733  		}
3734  		ext_list = qdf_nbuf_queue_next(ext_list);
3735  	}
3736  
3737  	/* Store SKB in internal QDF tracking table */
3738  	qdf_net_buf_debug_add_node(cloned_buf, 0, func, line);
3739  	qdf_nbuf_history_add(cloned_buf, func, line, QDF_NBUF_ALLOC_CLONE);
3740  
3741  	return cloned_buf;
3742  }
3743  qdf_export_symbol(qdf_nbuf_clone_debug);
3744  
3745  qdf_nbuf_t
qdf_nbuf_page_frag_alloc_debug(qdf_device_t osdev,qdf_size_t size,int reserve,int align,__qdf_frag_cache_t * pf_cache,const char * func,uint32_t line)3746  qdf_nbuf_page_frag_alloc_debug(qdf_device_t osdev, qdf_size_t size, int reserve,
3747  			       int align, __qdf_frag_cache_t *pf_cache,
3748  			       const char *func, uint32_t line)
3749  {
3750  	qdf_nbuf_t nbuf;
3751  
3752  	if (is_initial_mem_debug_disabled)
3753  		return __qdf_nbuf_page_frag_alloc(osdev, size, reserve, align,
3754  						  pf_cache, func, line);
3755  
3756  	nbuf = __qdf_nbuf_page_frag_alloc(osdev, size, reserve, align,
3757  					  pf_cache, func, line);
3758  
3759  	/* Store SKB in internal QDF tracking table */
3760  	if (qdf_likely(nbuf)) {
3761  		qdf_net_buf_debug_add_node(nbuf, size, func, line);
3762  		qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_ALLOC);
3763  	} else {
3764  		qdf_nbuf_history_add(nbuf, func, line, QDF_NBUF_ALLOC_FAILURE);
3765  	}
3766  
3767  	return nbuf;
3768  }
3769  
3770  qdf_export_symbol(qdf_nbuf_page_frag_alloc_debug);
3771  
qdf_nbuf_copy_debug(qdf_nbuf_t buf,const char * func,uint32_t line)3772  qdf_nbuf_t qdf_nbuf_copy_debug(qdf_nbuf_t buf, const char *func, uint32_t line)
3773  {
3774  	qdf_nbuf_t copied_buf = __qdf_nbuf_copy(buf);
3775  
3776  	if (is_initial_mem_debug_disabled)
3777  		return copied_buf;
3778  
3779  	if (qdf_unlikely(!copied_buf))
3780  		return NULL;
3781  
3782  	/* Store SKB in internal QDF tracking table */
3783  	qdf_net_buf_debug_add_node(copied_buf, 0, func, line);
3784  	qdf_nbuf_history_add(copied_buf, func, line, QDF_NBUF_ALLOC_COPY);
3785  
3786  	return copied_buf;
3787  }
3788  qdf_export_symbol(qdf_nbuf_copy_debug);
3789  
3790  qdf_nbuf_t
qdf_nbuf_copy_expand_debug(qdf_nbuf_t buf,int headroom,int tailroom,const char * func,uint32_t line)3791  qdf_nbuf_copy_expand_debug(qdf_nbuf_t buf, int headroom, int tailroom,
3792  			   const char *func, uint32_t line)
3793  {
3794  	qdf_nbuf_t copied_buf = __qdf_nbuf_copy_expand(buf, headroom, tailroom);
3795  
3796  	if (qdf_unlikely(!copied_buf))
3797  		return NULL;
3798  
3799  	if (is_initial_mem_debug_disabled)
3800  		return copied_buf;
3801  
3802  	/* Store SKB in internal QDF tracking table */
3803  	qdf_net_buf_debug_add_node(copied_buf, 0, func, line);
3804  	qdf_nbuf_history_add(copied_buf, func, line,
3805  			     QDF_NBUF_ALLOC_COPY_EXPAND);
3806  
3807  	return copied_buf;
3808  }
3809  
3810  qdf_export_symbol(qdf_nbuf_copy_expand_debug);
3811  
3812  qdf_nbuf_t
qdf_nbuf_unshare_debug(qdf_nbuf_t buf,const char * func_name,uint32_t line_num)3813  qdf_nbuf_unshare_debug(qdf_nbuf_t buf, const char *func_name,
3814  		       uint32_t line_num)
3815  {
3816  	qdf_nbuf_t unshared_buf;
3817  	qdf_frag_t p_frag;
3818  	uint32_t num_nr_frags;
3819  	uint32_t idx = 0;
3820  	qdf_nbuf_t ext_list, next;
3821  
3822  	if (is_initial_mem_debug_disabled)
3823  		return __qdf_nbuf_unshare(buf);
3824  
3825  	/* Not a shared buffer, nothing to do */
3826  	if (!qdf_nbuf_is_cloned(buf))
3827  		return buf;
3828  
3829  	if (qdf_nbuf_get_users(buf) > 1)
3830  		goto unshare_buf;
3831  
3832  	/* Take care to delete the debug entries for frags */
3833  	num_nr_frags = qdf_nbuf_get_nr_frags(buf);
3834  
3835  	while (idx < num_nr_frags) {
3836  		p_frag = qdf_nbuf_get_frag_addr(buf, idx);
3837  		if (qdf_likely(p_frag))
3838  			qdf_frag_debug_refcount_dec(p_frag, func_name,
3839  						    line_num);
3840  		idx++;
3841  	}
3842  
3843  	qdf_net_buf_debug_delete_node(buf);
3844  
3845  	 /* Take care of jumbo packet connected using frag_list and frags */
3846  	ext_list = qdf_nbuf_get_ext_list(buf);
3847  	while (ext_list) {
3848  		idx = 0;
3849  		next = qdf_nbuf_queue_next(ext_list);
3850  		num_nr_frags = qdf_nbuf_get_nr_frags(ext_list);
3851  
3852  		if (qdf_nbuf_get_users(ext_list) > 1) {
3853  			ext_list = next;
3854  			continue;
3855  		}
3856  
3857  		while (idx < num_nr_frags) {
3858  			p_frag = qdf_nbuf_get_frag_addr(ext_list, idx);
3859  			if (qdf_likely(p_frag))
3860  				qdf_frag_debug_refcount_dec(p_frag, func_name,
3861  							    line_num);
3862  			idx++;
3863  		}
3864  
3865  		qdf_net_buf_debug_delete_node(ext_list);
3866  		ext_list = next;
3867  	}
3868  
3869  unshare_buf:
3870  	unshared_buf = __qdf_nbuf_unshare(buf);
3871  
3872  	if (qdf_likely(unshared_buf))
3873  		qdf_net_buf_debug_add_node(unshared_buf, 0, func_name,
3874  					   line_num);
3875  
3876  	return unshared_buf;
3877  }
3878  
3879  qdf_export_symbol(qdf_nbuf_unshare_debug);
3880  
3881  void
qdf_nbuf_dev_kfree_list_debug(__qdf_nbuf_queue_head_t * nbuf_queue_head,const char * func,uint32_t line)3882  qdf_nbuf_dev_kfree_list_debug(__qdf_nbuf_queue_head_t *nbuf_queue_head,
3883  			      const char *func, uint32_t line)
3884  {
3885  	qdf_nbuf_t  buf;
3886  
3887  	if (qdf_nbuf_queue_empty(nbuf_queue_head))
3888  		return;
3889  
3890  	if (is_initial_mem_debug_disabled)
3891  		return __qdf_nbuf_dev_kfree_list(nbuf_queue_head);
3892  
3893  	while ((buf = qdf_nbuf_queue_head_dequeue(nbuf_queue_head)) != NULL)
3894  		qdf_nbuf_free_debug(buf, func, line);
3895  }
3896  
3897  qdf_export_symbol(qdf_nbuf_dev_kfree_list_debug);
3898  #endif /* NBUF_MEMORY_DEBUG */
3899  
3900  #if defined(QCA_DP_NBUF_FAST_PPEDS)
3901  #if defined(NBUF_MEMORY_DEBUG)
__qdf_nbuf_alloc_ppe_ds(qdf_device_t osdev,size_t size,const char * func,uint32_t line)3902  struct sk_buff *__qdf_nbuf_alloc_ppe_ds(qdf_device_t osdev, size_t size,
3903  					const char *func, uint32_t line)
3904  {
3905  	struct sk_buff *skb;
3906  	int flags = GFP_KERNEL;
3907  
3908  	if (in_interrupt() || irqs_disabled() || in_atomic()) {
3909  		flags = GFP_ATOMIC;
3910  #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
3911  		/*
3912  		 * Observed that kcompactd burns out CPU to make order-3
3913  		 * page.__netdev_alloc_skb has 4k page fallback option
3914  		 * just in case of
3915  		 * failing high order page allocation so we don't need
3916  		 * to be hard. Make kcompactd rest in piece.
3917  		 */
3918  		flags = flags & ~__GFP_KSWAPD_RECLAIM;
3919  #endif
3920  	}
3921  	skb = __netdev_alloc_skb_no_skb_reset(NULL, size, flags);
3922  	if (qdf_likely(is_initial_mem_debug_disabled)) {
3923  		if (qdf_likely(skb))
3924  			qdf_nbuf_count_inc(skb);
3925  	} else {
3926  		if (qdf_likely(skb)) {
3927  			qdf_nbuf_count_inc(skb);
3928  			qdf_net_buf_debug_add_node(skb, size, func, line);
3929  			qdf_nbuf_history_add(skb, func, line,
3930  					     QDF_NBUF_ALLOC);
3931  		} else {
3932  			qdf_nbuf_history_add(skb, func, line,
3933  					     QDF_NBUF_ALLOC_FAILURE);
3934  		}
3935  	}
3936  	return skb;
3937  }
3938  #else
__qdf_nbuf_alloc_ppe_ds(qdf_device_t osdev,size_t size,const char * func,uint32_t line)3939  struct sk_buff *__qdf_nbuf_alloc_ppe_ds(qdf_device_t osdev, size_t size,
3940  					const char *func, uint32_t line)
3941  {
3942  	struct sk_buff *skb;
3943  	int flags = GFP_KERNEL;
3944  
3945  	if (in_interrupt() || irqs_disabled() || in_atomic()) {
3946  		flags = GFP_ATOMIC;
3947  #if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 4, 0)
3948  		/*
3949  		 * Observed that kcompactd burns out CPU to make order-3
3950  		 * page.__netdev_alloc_skb has 4k page fallback option
3951  		 * just in case of
3952  		 * failing high order page allocation so we don't need
3953  		 * to be hard. Make kcompactd rest in piece.
3954  		 */
3955  		flags = flags & ~__GFP_KSWAPD_RECLAIM;
3956  #endif
3957  	}
3958  	skb = __netdev_alloc_skb_no_skb_reset(NULL, size, flags);
3959  	if (qdf_likely(skb))
3960  		qdf_nbuf_count_inc(skb);
3961  
3962  	return skb;
3963  }
3964  #endif
3965  qdf_export_symbol(__qdf_nbuf_alloc_ppe_ds);
3966  #endif
3967  
3968  #if defined(FEATURE_TSO)
3969  
3970  /**
3971   * struct qdf_tso_cmn_seg_info_t - TSO common info structure
3972   *
3973   * @ethproto: ethernet type of the msdu
3974   * @ip_tcp_hdr_len: ip + tcp length for the msdu
3975   * @l2_len: L2 length for the msdu
3976   * @eit_hdr: pointer to EIT header
3977   * @eit_hdr_len: EIT header length for the msdu
3978   * @eit_hdr_dma_map_addr: dma addr for EIT header
3979   * @tcphdr: pointer to tcp header
3980   * @ipv4_csum_en: ipv4 checksum enable
3981   * @tcp_ipv4_csum_en: TCP ipv4 checksum enable
3982   * @tcp_ipv6_csum_en: TCP ipv6 checksum enable
3983   * @ip_id: IP id
3984   * @tcp_seq_num: TCP sequence number
3985   *
3986   * This structure holds the TSO common info that is common
3987   * across all the TCP segments of the jumbo packet.
3988   */
3989  struct qdf_tso_cmn_seg_info_t {
3990  	uint16_t ethproto;
3991  	uint16_t ip_tcp_hdr_len;
3992  	uint16_t l2_len;
3993  	uint8_t *eit_hdr;
3994  	uint32_t eit_hdr_len;
3995  	qdf_dma_addr_t eit_hdr_dma_map_addr;
3996  	struct tcphdr *tcphdr;
3997  	uint16_t ipv4_csum_en;
3998  	uint16_t tcp_ipv4_csum_en;
3999  	uint16_t tcp_ipv6_csum_en;
4000  	uint16_t ip_id;
4001  	uint32_t tcp_seq_num;
4002  };
4003  
4004  /**
4005   * qdf_nbuf_adj_tso_frag() - adjustment for buffer address of tso fragment
4006   * @skb: network buffer
4007   *
4008   * Return: byte offset length of 8 bytes aligned.
4009   */
4010  #ifdef FIX_TXDMA_LIMITATION
qdf_nbuf_adj_tso_frag(struct sk_buff * skb)4011  static uint8_t qdf_nbuf_adj_tso_frag(struct sk_buff *skb)
4012  {
4013  	uint32_t eit_hdr_len;
4014  	uint8_t *eit_hdr;
4015  	uint8_t byte_8_align_offset;
4016  
4017  	eit_hdr = skb->data;
4018  	eit_hdr_len = (skb_transport_header(skb)
4019  		 - skb_mac_header(skb)) + tcp_hdrlen(skb);
4020  	byte_8_align_offset = ((unsigned long)(eit_hdr) + eit_hdr_len) & 0x7L;
4021  	if (qdf_unlikely(byte_8_align_offset)) {
4022  		TSO_DEBUG("%pK,Len %d %d",
4023  			  eit_hdr, eit_hdr_len, byte_8_align_offset);
4024  		if (unlikely(skb_headroom(skb) < byte_8_align_offset)) {
4025  			TSO_DEBUG("[%d]Insufficient headroom,[%pK],[%pK],[%d]",
4026  				  __LINE__, skb->head, skb->data,
4027  				 byte_8_align_offset);
4028  			return 0;
4029  		}
4030  		qdf_nbuf_push_head(skb, byte_8_align_offset);
4031  		qdf_mem_move(skb->data,
4032  			     skb->data + byte_8_align_offset,
4033  			     eit_hdr_len);
4034  		skb->len -= byte_8_align_offset;
4035  		skb->mac_header -= byte_8_align_offset;
4036  		skb->network_header -= byte_8_align_offset;
4037  		skb->transport_header -= byte_8_align_offset;
4038  	}
4039  	return byte_8_align_offset;
4040  }
4041  #else
qdf_nbuf_adj_tso_frag(struct sk_buff * skb)4042  static uint8_t qdf_nbuf_adj_tso_frag(struct sk_buff *skb)
4043  {
4044  	return 0;
4045  }
4046  #endif
4047  
4048  #ifdef CONFIG_WLAN_SYSFS_MEM_STATS
qdf_record_nbuf_nbytes(uint32_t nbytes,qdf_dma_dir_t dir,bool is_mapped)4049  void qdf_record_nbuf_nbytes(
4050  	uint32_t nbytes, qdf_dma_dir_t dir, bool is_mapped)
4051  {
4052  	__qdf_record_nbuf_nbytes(nbytes, dir, is_mapped);
4053  }
4054  
4055  qdf_export_symbol(qdf_record_nbuf_nbytes);
4056  
4057  #endif /* CONFIG_WLAN_SYSFS_MEM_STATS */
4058  
4059  /**
4060   * qdf_nbuf_tso_map_frag() - Map TSO segment
4061   * @osdev: qdf device handle
4062   * @tso_frag_vaddr: addr of tso fragment
4063   * @nbytes: number of bytes
4064   * @dir: direction
4065   *
4066   * Map TSO segment and for MCL record the amount of memory mapped
4067   *
4068   * Return: DMA address of mapped TSO fragment in success and
4069   * NULL in case of DMA mapping failure
4070   */
qdf_nbuf_tso_map_frag(qdf_device_t osdev,void * tso_frag_vaddr,uint32_t nbytes,qdf_dma_dir_t dir)4071  static inline qdf_dma_addr_t qdf_nbuf_tso_map_frag(
4072  	qdf_device_t osdev, void *tso_frag_vaddr,
4073  	uint32_t nbytes, qdf_dma_dir_t dir)
4074  {
4075  	qdf_dma_addr_t tso_frag_paddr = 0;
4076  
4077  	tso_frag_paddr = dma_map_single(osdev->dev, tso_frag_vaddr,
4078  					nbytes, __qdf_dma_dir_to_os(dir));
4079  	if (unlikely(dma_mapping_error(osdev->dev, tso_frag_paddr))) {
4080  		qdf_err("DMA mapping error!");
4081  		qdf_assert_always(0);
4082  		return 0;
4083  	}
4084  	qdf_record_nbuf_nbytes(nbytes, dir, true);
4085  	return tso_frag_paddr;
4086  }
4087  
4088  /**
4089   * qdf_nbuf_tso_unmap_frag() - Unmap TSO segment
4090   * @osdev: qdf device handle
4091   * @tso_frag_paddr: DMA addr of tso fragment
4092   * @dir: direction
4093   * @nbytes: number of bytes
4094   *
4095   * Unmap TSO segment and for MCL record the amount of memory mapped
4096   *
4097   * Return: None
4098   */
qdf_nbuf_tso_unmap_frag(qdf_device_t osdev,qdf_dma_addr_t tso_frag_paddr,uint32_t nbytes,qdf_dma_dir_t dir)4099  static inline void qdf_nbuf_tso_unmap_frag(
4100  	qdf_device_t osdev, qdf_dma_addr_t tso_frag_paddr,
4101  	uint32_t nbytes, qdf_dma_dir_t dir)
4102  {
4103  	qdf_record_nbuf_nbytes(nbytes, dir, false);
4104  	dma_unmap_single(osdev->dev, tso_frag_paddr,
4105  			 nbytes, __qdf_dma_dir_to_os(dir));
4106  }
4107  
4108  /**
4109   * __qdf_nbuf_get_tso_cmn_seg_info() - get TSO common
4110   * information
4111   * @osdev: qdf device handle
4112   * @skb: skb buffer
4113   * @tso_info: Parameters common to all segments
4114   *
4115   * Get the TSO information that is common across all the TCP
4116   * segments of the jumbo packet
4117   *
4118   * Return: 0 - success 1 - failure
4119   */
__qdf_nbuf_get_tso_cmn_seg_info(qdf_device_t osdev,struct sk_buff * skb,struct qdf_tso_cmn_seg_info_t * tso_info)4120  static uint8_t __qdf_nbuf_get_tso_cmn_seg_info(qdf_device_t osdev,
4121  			struct sk_buff *skb,
4122  			struct qdf_tso_cmn_seg_info_t *tso_info)
4123  {
4124  	/* Get ethernet type and ethernet header length */
4125  	tso_info->ethproto = vlan_get_protocol(skb);
4126  
4127  	/* Determine whether this is an IPv4 or IPv6 packet */
4128  	if (tso_info->ethproto == htons(ETH_P_IP)) { /* IPv4 */
4129  		/* for IPv4, get the IP ID and enable TCP and IP csum */
4130  		struct iphdr *ipv4_hdr = ip_hdr(skb);
4131  
4132  		tso_info->ip_id = ntohs(ipv4_hdr->id);
4133  		tso_info->ipv4_csum_en = 1;
4134  		tso_info->tcp_ipv4_csum_en = 1;
4135  		if (qdf_unlikely(ipv4_hdr->protocol != IPPROTO_TCP)) {
4136  			qdf_err("TSO IPV4 proto 0x%x not TCP",
4137  				ipv4_hdr->protocol);
4138  			return 1;
4139  		}
4140  	} else if (tso_info->ethproto == htons(ETH_P_IPV6)) { /* IPv6 */
4141  		/* for IPv6, enable TCP csum. No IP ID or IP csum */
4142  		tso_info->tcp_ipv6_csum_en = 1;
4143  	} else {
4144  		qdf_err("TSO: ethertype 0x%x is not supported!",
4145  			tso_info->ethproto);
4146  		return 1;
4147  	}
4148  	tso_info->l2_len = (skb_network_header(skb) - skb_mac_header(skb));
4149  	tso_info->tcphdr = tcp_hdr(skb);
4150  	tso_info->tcp_seq_num = ntohl(tcp_hdr(skb)->seq);
4151  	/* get pointer to the ethernet + IP + TCP header and their length */
4152  	tso_info->eit_hdr = skb->data;
4153  	tso_info->eit_hdr_len = (skb_transport_header(skb)
4154  		 - skb_mac_header(skb)) + tcp_hdrlen(skb);
4155  	tso_info->eit_hdr_dma_map_addr = qdf_nbuf_tso_map_frag(
4156  						osdev, tso_info->eit_hdr,
4157  						tso_info->eit_hdr_len,
4158  						QDF_DMA_TO_DEVICE);
4159  	if (qdf_unlikely(!tso_info->eit_hdr_dma_map_addr))
4160  		return 1;
4161  
4162  	if (tso_info->ethproto == htons(ETH_P_IP)) {
4163  		/* include IPv4 header length for IPV4 (total length) */
4164  		tso_info->ip_tcp_hdr_len =
4165  			tso_info->eit_hdr_len - tso_info->l2_len;
4166  	} else if (tso_info->ethproto == htons(ETH_P_IPV6)) {
4167  		/* exclude IPv6 header length for IPv6 (payload length) */
4168  		tso_info->ip_tcp_hdr_len = tcp_hdrlen(skb);
4169  	}
4170  	/*
4171  	 * The length of the payload (application layer data) is added to
4172  	 * tso_info->ip_tcp_hdr_len before passing it on to the msdu link ext
4173  	 * descriptor.
4174  	 */
4175  
4176  	TSO_DEBUG("%s seq# %u eit hdr len %u l2 len %u  skb len %u\n", __func__,
4177  		tso_info->tcp_seq_num,
4178  		tso_info->eit_hdr_len,
4179  		tso_info->l2_len,
4180  		skb->len);
4181  	return 0;
4182  }
4183  
4184  
4185  /**
4186   * __qdf_nbuf_fill_tso_cmn_seg_info() - Init function for each TSO nbuf segment
4187   *
4188   * @curr_seg: Segment whose contents are initialized
4189   * @tso_cmn_info: Parameters common to all segments
4190   *
4191   * Return: None
4192   */
__qdf_nbuf_fill_tso_cmn_seg_info(struct qdf_tso_seg_elem_t * curr_seg,struct qdf_tso_cmn_seg_info_t * tso_cmn_info)4193  static inline void __qdf_nbuf_fill_tso_cmn_seg_info(
4194  				struct qdf_tso_seg_elem_t *curr_seg,
4195  				struct qdf_tso_cmn_seg_info_t *tso_cmn_info)
4196  {
4197  	/* Initialize the flags to 0 */
4198  	memset(&curr_seg->seg, 0x0, sizeof(curr_seg->seg));
4199  
4200  	/*
4201  	 * The following fields remain the same across all segments of
4202  	 * a jumbo packet
4203  	 */
4204  	curr_seg->seg.tso_flags.tso_enable = 1;
4205  	curr_seg->seg.tso_flags.ipv4_checksum_en =
4206  		tso_cmn_info->ipv4_csum_en;
4207  	curr_seg->seg.tso_flags.tcp_ipv6_checksum_en =
4208  		tso_cmn_info->tcp_ipv6_csum_en;
4209  	curr_seg->seg.tso_flags.tcp_ipv4_checksum_en =
4210  		tso_cmn_info->tcp_ipv4_csum_en;
4211  	curr_seg->seg.tso_flags.tcp_flags_mask = 0x1FF;
4212  
4213  	/* The following fields change for the segments */
4214  	curr_seg->seg.tso_flags.ip_id = tso_cmn_info->ip_id;
4215  	tso_cmn_info->ip_id++;
4216  
4217  	curr_seg->seg.tso_flags.syn = tso_cmn_info->tcphdr->syn;
4218  	curr_seg->seg.tso_flags.rst = tso_cmn_info->tcphdr->rst;
4219  	curr_seg->seg.tso_flags.ack = tso_cmn_info->tcphdr->ack;
4220  	curr_seg->seg.tso_flags.urg = tso_cmn_info->tcphdr->urg;
4221  	curr_seg->seg.tso_flags.ece = tso_cmn_info->tcphdr->ece;
4222  	curr_seg->seg.tso_flags.cwr = tso_cmn_info->tcphdr->cwr;
4223  
4224  	curr_seg->seg.tso_flags.tcp_seq_num = tso_cmn_info->tcp_seq_num;
4225  
4226  	/*
4227  	 * First fragment for each segment always contains the ethernet,
4228  	 * IP and TCP header
4229  	 */
4230  	curr_seg->seg.tso_frags[0].vaddr = tso_cmn_info->eit_hdr;
4231  	curr_seg->seg.tso_frags[0].length = tso_cmn_info->eit_hdr_len;
4232  	curr_seg->seg.total_len = curr_seg->seg.tso_frags[0].length;
4233  	curr_seg->seg.tso_frags[0].paddr = tso_cmn_info->eit_hdr_dma_map_addr;
4234  
4235  	TSO_DEBUG("%s %d eit hdr %pK eit_hdr_len %d tcp_seq_num %u tso_info->total_len %u\n",
4236  		   __func__, __LINE__, tso_cmn_info->eit_hdr,
4237  		   tso_cmn_info->eit_hdr_len,
4238  		   curr_seg->seg.tso_flags.tcp_seq_num,
4239  		   curr_seg->seg.total_len);
4240  	qdf_tso_seg_dbg_record(curr_seg, TSOSEG_LOC_FILLCMNSEG);
4241  }
4242  
__qdf_nbuf_get_tso_info(qdf_device_t osdev,struct sk_buff * skb,struct qdf_tso_info_t * tso_info)4243  uint32_t __qdf_nbuf_get_tso_info(qdf_device_t osdev, struct sk_buff *skb,
4244  		struct qdf_tso_info_t *tso_info)
4245  {
4246  	/* common across all segments */
4247  	struct qdf_tso_cmn_seg_info_t tso_cmn_info;
4248  	/* segment specific */
4249  	void *tso_frag_vaddr;
4250  	qdf_dma_addr_t tso_frag_paddr = 0;
4251  	uint32_t num_seg = 0;
4252  	struct qdf_tso_seg_elem_t *curr_seg;
4253  	struct qdf_tso_num_seg_elem_t *total_num_seg;
4254  	skb_frag_t *frag = NULL;
4255  	uint32_t tso_frag_len = 0; /* tso segment's fragment length*/
4256  	uint32_t skb_frag_len = 0; /* skb's fragment length (contiguous memory)*/
4257  	uint32_t skb_proc = skb->len; /* bytes of skb pending processing */
4258  	uint32_t tso_seg_size = skb_shinfo(skb)->gso_size;
4259  	int j = 0; /* skb fragment index */
4260  	uint8_t byte_8_align_offset;
4261  
4262  	memset(&tso_cmn_info, 0x0, sizeof(tso_cmn_info));
4263  	total_num_seg = tso_info->tso_num_seg_list;
4264  	curr_seg = tso_info->tso_seg_list;
4265  	total_num_seg->num_seg.tso_cmn_num_seg = 0;
4266  
4267  	byte_8_align_offset = qdf_nbuf_adj_tso_frag(skb);
4268  
4269  	if (qdf_unlikely(__qdf_nbuf_get_tso_cmn_seg_info(osdev,
4270  						skb, &tso_cmn_info))) {
4271  		qdf_warn("TSO: error getting common segment info");
4272  		return 0;
4273  	}
4274  
4275  	/* length of the first chunk of data in the skb */
4276  	skb_frag_len = skb_headlen(skb);
4277  
4278  	/* the 0th tso segment's 0th fragment always contains the EIT header */
4279  	/* update the remaining skb fragment length and TSO segment length */
4280  	skb_frag_len -= tso_cmn_info.eit_hdr_len;
4281  	skb_proc -= tso_cmn_info.eit_hdr_len;
4282  
4283  	/* get the address to the next tso fragment */
4284  	tso_frag_vaddr = skb->data +
4285  			 tso_cmn_info.eit_hdr_len +
4286  			 byte_8_align_offset;
4287  	/* get the length of the next tso fragment */
4288  	tso_frag_len = min(skb_frag_len, tso_seg_size);
4289  
4290  	if (tso_frag_len != 0) {
4291  		tso_frag_paddr = qdf_nbuf_tso_map_frag(
4292  					osdev, tso_frag_vaddr, tso_frag_len,
4293  					QDF_DMA_TO_DEVICE);
4294  		if (qdf_unlikely(!tso_frag_paddr))
4295  			return 0;
4296  	}
4297  
4298  	TSO_DEBUG("%s[%d] skb frag len %d tso frag len %d\n", __func__,
4299  		__LINE__, skb_frag_len, tso_frag_len);
4300  	num_seg = tso_info->num_segs;
4301  	tso_info->num_segs = 0;
4302  	tso_info->is_tso = 1;
4303  
4304  	while (num_seg && curr_seg) {
4305  		int i = 1; /* tso fragment index */
4306  		uint8_t more_tso_frags = 1;
4307  
4308  		curr_seg->seg.num_frags = 0;
4309  		tso_info->num_segs++;
4310  		total_num_seg->num_seg.tso_cmn_num_seg++;
4311  
4312  		__qdf_nbuf_fill_tso_cmn_seg_info(curr_seg,
4313  						 &tso_cmn_info);
4314  
4315  		/* If TCP PSH flag is set, set it in the last or only segment */
4316  		if (num_seg == 1)
4317  			curr_seg->seg.tso_flags.psh = tso_cmn_info.tcphdr->psh;
4318  
4319  		if (unlikely(skb_proc == 0))
4320  			return tso_info->num_segs;
4321  
4322  		curr_seg->seg.tso_flags.ip_len = tso_cmn_info.ip_tcp_hdr_len;
4323  		curr_seg->seg.tso_flags.l2_len = tso_cmn_info.l2_len;
4324  		/* frag len is added to ip_len in while loop below*/
4325  
4326  		curr_seg->seg.num_frags++;
4327  
4328  		while (more_tso_frags) {
4329  			if (tso_frag_len != 0) {
4330  				curr_seg->seg.tso_frags[i].vaddr =
4331  					tso_frag_vaddr;
4332  				curr_seg->seg.tso_frags[i].length =
4333  					tso_frag_len;
4334  				curr_seg->seg.total_len += tso_frag_len;
4335  				curr_seg->seg.tso_flags.ip_len +=  tso_frag_len;
4336  				curr_seg->seg.num_frags++;
4337  				skb_proc = skb_proc - tso_frag_len;
4338  
4339  				/* increment the TCP sequence number */
4340  
4341  				tso_cmn_info.tcp_seq_num += tso_frag_len;
4342  				curr_seg->seg.tso_frags[i].paddr =
4343  					tso_frag_paddr;
4344  
4345  				qdf_assert_always(curr_seg->seg.tso_frags[i].paddr);
4346  			}
4347  
4348  			TSO_DEBUG("%s[%d] frag %d frag len %d total_len %u vaddr %pK\n",
4349  					__func__, __LINE__,
4350  					i,
4351  					tso_frag_len,
4352  					curr_seg->seg.total_len,
4353  					curr_seg->seg.tso_frags[i].vaddr);
4354  
4355  			/* if there is no more data left in the skb */
4356  			if (!skb_proc)
4357  				return tso_info->num_segs;
4358  
4359  			/* get the next payload fragment information */
4360  			/* check if there are more fragments in this segment */
4361  			if (tso_frag_len < tso_seg_size) {
4362  				more_tso_frags = 1;
4363  				if (tso_frag_len != 0) {
4364  					tso_seg_size = tso_seg_size -
4365  						tso_frag_len;
4366  					i++;
4367  					if (curr_seg->seg.num_frags ==
4368  								FRAG_NUM_MAX) {
4369  						more_tso_frags = 0;
4370  						/*
4371  						 * reset i and the tso
4372  						 * payload size
4373  						 */
4374  						i = 1;
4375  						tso_seg_size =
4376  							skb_shinfo(skb)->
4377  								gso_size;
4378  					}
4379  				}
4380  			} else {
4381  				more_tso_frags = 0;
4382  				/* reset i and the tso payload size */
4383  				i = 1;
4384  				tso_seg_size = skb_shinfo(skb)->gso_size;
4385  			}
4386  
4387  			/* if the next fragment is contiguous */
4388  			if ((tso_frag_len != 0)  && (tso_frag_len < skb_frag_len)) {
4389  				tso_frag_vaddr = tso_frag_vaddr + tso_frag_len;
4390  				skb_frag_len = skb_frag_len - tso_frag_len;
4391  				tso_frag_len = min(skb_frag_len, tso_seg_size);
4392  
4393  			} else { /* the next fragment is not contiguous */
4394  				if (skb_shinfo(skb)->nr_frags == 0) {
4395  					qdf_info("TSO: nr_frags == 0!");
4396  					qdf_assert(0);
4397  					return 0;
4398  				}
4399  				if (j >= skb_shinfo(skb)->nr_frags) {
4400  					qdf_info("TSO: nr_frags %d j %d",
4401  						 skb_shinfo(skb)->nr_frags, j);
4402  					qdf_assert(0);
4403  					return 0;
4404  				}
4405  				frag = &skb_shinfo(skb)->frags[j];
4406  				skb_frag_len = skb_frag_size(frag);
4407  				tso_frag_len = min(skb_frag_len, tso_seg_size);
4408  				tso_frag_vaddr = skb_frag_address_safe(frag);
4409  				j++;
4410  			}
4411  
4412  			TSO_DEBUG("%s[%d] skb frag len %d tso frag %d len tso_seg_size %d\n",
4413  				__func__, __LINE__, skb_frag_len, tso_frag_len,
4414  				tso_seg_size);
4415  
4416  			if (!(tso_frag_vaddr)) {
4417  				TSO_DEBUG("%s: Fragment virtual addr is NULL",
4418  						__func__);
4419  				return 0;
4420  			}
4421  
4422  			tso_frag_paddr = qdf_nbuf_tso_map_frag(
4423  						osdev, tso_frag_vaddr,
4424  						tso_frag_len,
4425  						QDF_DMA_TO_DEVICE);
4426  			if (qdf_unlikely(!tso_frag_paddr))
4427  				return 0;
4428  		}
4429  		TSO_DEBUG("%s tcp_seq_num: %u", __func__,
4430  				curr_seg->seg.tso_flags.tcp_seq_num);
4431  		num_seg--;
4432  		/* if TCP FIN flag was set, set it in the last segment */
4433  		if (!num_seg)
4434  			curr_seg->seg.tso_flags.fin = tso_cmn_info.tcphdr->fin;
4435  
4436  		qdf_tso_seg_dbg_record(curr_seg, TSOSEG_LOC_GETINFO);
4437  		curr_seg = curr_seg->next;
4438  	}
4439  	return tso_info->num_segs;
4440  }
4441  qdf_export_symbol(__qdf_nbuf_get_tso_info);
4442  
__qdf_nbuf_unmap_tso_segment(qdf_device_t osdev,struct qdf_tso_seg_elem_t * tso_seg,bool is_last_seg)4443  void __qdf_nbuf_unmap_tso_segment(qdf_device_t osdev,
4444  			  struct qdf_tso_seg_elem_t *tso_seg,
4445  			  bool is_last_seg)
4446  {
4447  	uint32_t num_frags = 0;
4448  
4449  	if (tso_seg->seg.num_frags > 0)
4450  		num_frags = tso_seg->seg.num_frags - 1;
4451  
4452  	/*Num of frags in a tso seg cannot be less than 2 */
4453  	if (num_frags < 1) {
4454  		/*
4455  		 * If Num of frags is 1 in a tso seg but is_last_seg true,
4456  		 * this may happen when qdf_nbuf_get_tso_info failed,
4457  		 * do dma unmap for the 0th frag in this seg.
4458  		 */
4459  		if (is_last_seg && tso_seg->seg.num_frags == 1)
4460  			goto last_seg_free_first_frag;
4461  
4462  		qdf_assert(0);
4463  		qdf_err("ERROR: num of frags in a tso segment is %d",
4464  			(num_frags + 1));
4465  		return;
4466  	}
4467  
4468  	while (num_frags) {
4469  		/*Do dma unmap the tso seg except the 0th frag */
4470  		if (0 ==  tso_seg->seg.tso_frags[num_frags].paddr) {
4471  			qdf_err("ERROR: TSO seg frag %d mapped physical address is NULL",
4472  				num_frags);
4473  			qdf_assert(0);
4474  			return;
4475  		}
4476  		qdf_nbuf_tso_unmap_frag(
4477  			osdev,
4478  			tso_seg->seg.tso_frags[num_frags].paddr,
4479  			tso_seg->seg.tso_frags[num_frags].length,
4480  			QDF_DMA_TO_DEVICE);
4481  		tso_seg->seg.tso_frags[num_frags].paddr = 0;
4482  		num_frags--;
4483  		qdf_tso_seg_dbg_record(tso_seg, TSOSEG_LOC_UNMAPTSO);
4484  	}
4485  
4486  last_seg_free_first_frag:
4487  	if (is_last_seg) {
4488  		/*Do dma unmap for the tso seg 0th frag */
4489  		if (0 ==  tso_seg->seg.tso_frags[0].paddr) {
4490  			qdf_err("ERROR: TSO seg frag 0 mapped physical address is NULL");
4491  			qdf_assert(0);
4492  			return;
4493  		}
4494  		qdf_nbuf_tso_unmap_frag(osdev,
4495  					tso_seg->seg.tso_frags[0].paddr,
4496  					tso_seg->seg.tso_frags[0].length,
4497  					QDF_DMA_TO_DEVICE);
4498  		tso_seg->seg.tso_frags[0].paddr = 0;
4499  		qdf_tso_seg_dbg_record(tso_seg, TSOSEG_LOC_UNMAPLAST);
4500  	}
4501  }
4502  qdf_export_symbol(__qdf_nbuf_unmap_tso_segment);
4503  
__qdf_nbuf_get_tcp_payload_len(struct sk_buff * skb)4504  size_t __qdf_nbuf_get_tcp_payload_len(struct sk_buff *skb)
4505  {
4506  	size_t packet_len;
4507  
4508  	packet_len = skb->len -
4509  		((skb_transport_header(skb) - skb_mac_header(skb)) +
4510  		 tcp_hdrlen(skb));
4511  
4512  	return packet_len;
4513  }
4514  
4515  qdf_export_symbol(__qdf_nbuf_get_tcp_payload_len);
4516  
4517  #ifndef BUILD_X86
__qdf_nbuf_get_tso_num_seg(struct sk_buff * skb)4518  uint32_t __qdf_nbuf_get_tso_num_seg(struct sk_buff *skb)
4519  {
4520  	uint32_t tso_seg_size = skb_shinfo(skb)->gso_size;
4521  	uint32_t remainder, num_segs = 0;
4522  	uint8_t skb_nr_frags = skb_shinfo(skb)->nr_frags;
4523  	uint8_t frags_per_tso = 0;
4524  	uint32_t skb_frag_len = 0;
4525  	uint32_t eit_hdr_len = (skb_transport_header(skb)
4526  			 - skb_mac_header(skb)) + tcp_hdrlen(skb);
4527  	skb_frag_t *frag = NULL;
4528  	int j = 0;
4529  	uint32_t temp_num_seg = 0;
4530  
4531  	/* length of the first chunk of data in the skb minus eit header*/
4532  	skb_frag_len = skb_headlen(skb) - eit_hdr_len;
4533  
4534  	/* Calculate num of segs for skb's first chunk of data*/
4535  	remainder = skb_frag_len % tso_seg_size;
4536  	num_segs = skb_frag_len / tso_seg_size;
4537  	/*
4538  	 * Remainder non-zero and nr_frags zero implies end of skb data.
4539  	 * In that case, one more tso seg is required to accommodate
4540  	 * remaining data, hence num_segs++. If nr_frags is non-zero,
4541  	 * then remaining data will be accommodated while doing the calculation
4542  	 * for nr_frags data. Hence, frags_per_tso++.
4543  	 */
4544  	if (remainder) {
4545  		if (!skb_nr_frags)
4546  			num_segs++;
4547  		else
4548  			frags_per_tso++;
4549  	}
4550  
4551  	while (skb_nr_frags) {
4552  		if (j >= skb_shinfo(skb)->nr_frags) {
4553  			qdf_info("TSO: nr_frags %d j %d",
4554  				 skb_shinfo(skb)->nr_frags, j);
4555  			qdf_assert(0);
4556  			return 0;
4557  		}
4558  		/*
4559  		 * Calculate the number of tso seg for nr_frags data:
4560  		 * Get the length of each frag in skb_frag_len, add to
4561  		 * remainder.Get the number of segments by dividing it to
4562  		 * tso_seg_size and calculate the new remainder.
4563  		 * Decrement the nr_frags value and keep
4564  		 * looping all the skb_fragments.
4565  		 */
4566  		frag = &skb_shinfo(skb)->frags[j];
4567  		skb_frag_len = skb_frag_size(frag);
4568  		temp_num_seg = num_segs;
4569  		remainder += skb_frag_len;
4570  		num_segs += remainder / tso_seg_size;
4571  		remainder = remainder % tso_seg_size;
4572  		skb_nr_frags--;
4573  		if (remainder) {
4574  			if (num_segs > temp_num_seg)
4575  				frags_per_tso = 0;
4576  			/*
4577  			 * increment the tso per frags whenever remainder is
4578  			 * positive. If frags_per_tso reaches the (max-1),
4579  			 * [First frags always have EIT header, therefore max-1]
4580  			 * increment the num_segs as no more data can be
4581  			 * accommodated in the curr tso seg. Reset the remainder
4582  			 * and frags per tso and keep looping.
4583  			 */
4584  			frags_per_tso++;
4585  			if (frags_per_tso == FRAG_NUM_MAX - 1) {
4586  				num_segs++;
4587  				frags_per_tso = 0;
4588  				remainder = 0;
4589  			}
4590  			/*
4591  			 * If this is the last skb frag and still remainder is
4592  			 * non-zero(frags_per_tso is not reached to the max-1)
4593  			 * then increment the num_segs to take care of the
4594  			 * remaining length.
4595  			 */
4596  			if (!skb_nr_frags && remainder) {
4597  				num_segs++;
4598  				frags_per_tso = 0;
4599  			}
4600  		} else {
4601  			 /* Whenever remainder is 0, reset the frags_per_tso. */
4602  			frags_per_tso = 0;
4603  		}
4604  		j++;
4605  	}
4606  
4607  	return num_segs;
4608  }
4609  #elif !defined(QCA_WIFI_QCN9000)
__qdf_nbuf_get_tso_num_seg(struct sk_buff * skb)4610  uint32_t __qdf_nbuf_get_tso_num_seg(struct sk_buff *skb)
4611  {
4612  	uint32_t i, gso_size, tmp_len, num_segs = 0;
4613  	skb_frag_t *frag = NULL;
4614  
4615  	/*
4616  	 * Check if the head SKB or any of frags are allocated in < 0x50000000
4617  	 * region which cannot be accessed by Target
4618  	 */
4619  	if (virt_to_phys(skb->data) < 0x50000040) {
4620  		TSO_DEBUG("%s %d: Invalid Address nr_frags = %d, paddr = %pK \n",
4621  				__func__, __LINE__, skb_shinfo(skb)->nr_frags,
4622  				virt_to_phys(skb->data));
4623  		goto fail;
4624  
4625  	}
4626  
4627  	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
4628  		frag = &skb_shinfo(skb)->frags[i];
4629  
4630  		if (!frag)
4631  			goto fail;
4632  
4633  		if (virt_to_phys(skb_frag_address_safe(frag)) < 0x50000040)
4634  			goto fail;
4635  	}
4636  
4637  
4638  	gso_size = skb_shinfo(skb)->gso_size;
4639  	tmp_len = skb->len - ((skb_transport_header(skb) - skb_mac_header(skb))
4640  			+ tcp_hdrlen(skb));
4641  	while (tmp_len) {
4642  		num_segs++;
4643  		if (tmp_len > gso_size)
4644  			tmp_len -= gso_size;
4645  		else
4646  			break;
4647  	}
4648  
4649  	return num_segs;
4650  
4651  	/*
4652  	 * Do not free this frame, just do socket level accounting
4653  	 * so that this is not reused.
4654  	 */
4655  fail:
4656  	if (skb->sk)
4657  		atomic_sub(skb->truesize, &(skb->sk->sk_wmem_alloc));
4658  
4659  	return 0;
4660  }
4661  #else
__qdf_nbuf_get_tso_num_seg(struct sk_buff * skb)4662  uint32_t __qdf_nbuf_get_tso_num_seg(struct sk_buff *skb)
4663  {
4664  	uint32_t i, gso_size, tmp_len, num_segs = 0;
4665  	skb_frag_t *frag = NULL;
4666  
4667  	for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
4668  		frag = &skb_shinfo(skb)->frags[i];
4669  
4670  		if (!frag)
4671  			goto fail;
4672  	}
4673  
4674  	gso_size = skb_shinfo(skb)->gso_size;
4675  	tmp_len = skb->len - ((skb_transport_header(skb) - skb_mac_header(skb))
4676  			+ tcp_hdrlen(skb));
4677  	while (tmp_len) {
4678  		num_segs++;
4679  		if (tmp_len > gso_size)
4680  			tmp_len -= gso_size;
4681  		else
4682  			break;
4683  	}
4684  
4685  	return num_segs;
4686  
4687  	/*
4688  	 * Do not free this frame, just do socket level accounting
4689  	 * so that this is not reused.
4690  	 */
4691  fail:
4692  	if (skb->sk)
4693  		atomic_sub(skb->truesize, &(skb->sk->sk_wmem_alloc));
4694  
4695  	return 0;
4696  }
4697  #endif
4698  qdf_export_symbol(__qdf_nbuf_get_tso_num_seg);
4699  
4700  #endif /* FEATURE_TSO */
4701  
__qdf_dmaaddr_to_32s(qdf_dma_addr_t dmaaddr,uint32_t * lo,uint32_t * hi)4702  void __qdf_dmaaddr_to_32s(qdf_dma_addr_t dmaaddr,
4703  			  uint32_t *lo, uint32_t *hi)
4704  {
4705  	if (sizeof(dmaaddr) > sizeof(uint32_t)) {
4706  		*lo = lower_32_bits(dmaaddr);
4707  		*hi = upper_32_bits(dmaaddr);
4708  	} else {
4709  		*lo = dmaaddr;
4710  		*hi = 0;
4711  	}
4712  }
4713  
4714  qdf_export_symbol(__qdf_dmaaddr_to_32s);
4715  
__qdf_nbuf_inc_users(struct sk_buff * skb)4716  struct sk_buff *__qdf_nbuf_inc_users(struct sk_buff *skb)
4717  {
4718  	qdf_nbuf_users_inc(&skb->users);
4719  	return skb;
4720  }
4721  qdf_export_symbol(__qdf_nbuf_inc_users);
4722  
__qdf_nbuf_get_users(struct sk_buff * skb)4723  int __qdf_nbuf_get_users(struct sk_buff *skb)
4724  {
4725  	return qdf_nbuf_users_read(&skb->users);
4726  }
4727  qdf_export_symbol(__qdf_nbuf_get_users);
4728  
__qdf_nbuf_ref(struct sk_buff * skb)4729  void __qdf_nbuf_ref(struct sk_buff *skb)
4730  {
4731  	skb_get(skb);
4732  }
4733  qdf_export_symbol(__qdf_nbuf_ref);
4734  
__qdf_nbuf_shared(struct sk_buff * skb)4735  int __qdf_nbuf_shared(struct sk_buff *skb)
4736  {
4737  	return skb_shared(skb);
4738  }
4739  qdf_export_symbol(__qdf_nbuf_shared);
4740  
4741  QDF_STATUS
__qdf_nbuf_dmamap_create(qdf_device_t osdev,__qdf_dma_map_t * dmap)4742  __qdf_nbuf_dmamap_create(qdf_device_t osdev, __qdf_dma_map_t *dmap)
4743  {
4744  	QDF_STATUS error = QDF_STATUS_SUCCESS;
4745  	/*
4746  	 * driver can tell its SG capability, it must be handled.
4747  	 * Bounce buffers if they are there
4748  	 */
4749  	(*dmap) = kzalloc(sizeof(struct __qdf_dma_map), GFP_KERNEL);
4750  	if (!(*dmap))
4751  		error = QDF_STATUS_E_NOMEM;
4752  
4753  	return error;
4754  }
4755  qdf_export_symbol(__qdf_nbuf_dmamap_create);
4756  
4757  void
__qdf_nbuf_dmamap_destroy(qdf_device_t osdev,__qdf_dma_map_t dmap)4758  __qdf_nbuf_dmamap_destroy(qdf_device_t osdev, __qdf_dma_map_t dmap)
4759  {
4760  	kfree(dmap);
4761  }
4762  qdf_export_symbol(__qdf_nbuf_dmamap_destroy);
4763  
4764  #ifdef QDF_OS_DEBUG
4765  QDF_STATUS
__qdf_nbuf_map_nbytes(qdf_device_t osdev,struct sk_buff * skb,qdf_dma_dir_t dir,int nbytes)4766  __qdf_nbuf_map_nbytes(
4767  	qdf_device_t osdev,
4768  	struct sk_buff *skb,
4769  	qdf_dma_dir_t dir,
4770  	int nbytes)
4771  {
4772  	struct skb_shared_info  *sh = skb_shinfo(skb);
4773  
4774  	qdf_assert((dir == QDF_DMA_TO_DEVICE) || (dir == QDF_DMA_FROM_DEVICE));
4775  
4776  	/*
4777  	 * Assume there's only a single fragment.
4778  	 * To support multiple fragments, it would be necessary to change
4779  	 * adf_nbuf_t to be a separate object that stores meta-info
4780  	 * (including the bus address for each fragment) and a pointer
4781  	 * to the underlying sk_buff.
4782  	 */
4783  	qdf_assert(sh->nr_frags == 0);
4784  
4785  	return __qdf_nbuf_map_nbytes_single(osdev, skb, dir, nbytes);
4786  }
4787  qdf_export_symbol(__qdf_nbuf_map_nbytes);
4788  #else
4789  QDF_STATUS
__qdf_nbuf_map_nbytes(qdf_device_t osdev,struct sk_buff * skb,qdf_dma_dir_t dir,int nbytes)4790  __qdf_nbuf_map_nbytes(
4791  	qdf_device_t osdev,
4792  	struct sk_buff *skb,
4793  	qdf_dma_dir_t dir,
4794  	int nbytes)
4795  {
4796  	return __qdf_nbuf_map_nbytes_single(osdev, skb, dir, nbytes);
4797  }
4798  qdf_export_symbol(__qdf_nbuf_map_nbytes);
4799  #endif
4800  void
__qdf_nbuf_unmap_nbytes(qdf_device_t osdev,struct sk_buff * skb,qdf_dma_dir_t dir,int nbytes)4801  __qdf_nbuf_unmap_nbytes(
4802  	qdf_device_t osdev,
4803  	struct sk_buff *skb,
4804  	qdf_dma_dir_t dir,
4805  	int nbytes)
4806  {
4807  	qdf_assert((dir == QDF_DMA_TO_DEVICE) || (dir == QDF_DMA_FROM_DEVICE));
4808  
4809  	/*
4810  	 * Assume there's a single fragment.
4811  	 * If this is not true, the assertion in __adf_nbuf_map will catch it.
4812  	 */
4813  	__qdf_nbuf_unmap_nbytes_single(osdev, skb, dir, nbytes);
4814  }
4815  qdf_export_symbol(__qdf_nbuf_unmap_nbytes);
4816  
4817  void
__qdf_nbuf_dma_map_info(__qdf_dma_map_t bmap,qdf_dmamap_info_t * sg)4818  __qdf_nbuf_dma_map_info(__qdf_dma_map_t bmap, qdf_dmamap_info_t *sg)
4819  {
4820  	qdf_assert(bmap->mapped);
4821  	qdf_assert(bmap->nsegs <= QDF_MAX_SCATTER);
4822  
4823  	memcpy(sg->dma_segs, bmap->seg, bmap->nsegs *
4824  			sizeof(struct __qdf_segment));
4825  	sg->nsegs = bmap->nsegs;
4826  }
4827  qdf_export_symbol(__qdf_nbuf_dma_map_info);
4828  
4829  #if defined(__QDF_SUPPORT_FRAG_MEM)
4830  void
__qdf_nbuf_frag_info(struct sk_buff * skb,qdf_sglist_t * sg)4831  __qdf_nbuf_frag_info(struct sk_buff *skb, qdf_sglist_t  *sg)
4832  {
4833  	qdf_assert(skb);
4834  	sg->sg_segs[0].vaddr = skb->data;
4835  	sg->sg_segs[0].len   = skb->len;
4836  	sg->nsegs            = 1;
4837  
4838  	for (int i = 1; i <= sh->nr_frags; i++) {
4839  		skb_frag_t    *f        = &sh->frags[i - 1];
4840  
4841  		sg->sg_segs[i].vaddr    = (uint8_t *)(page_address(f->page) +
4842  			f->page_offset);
4843  		sg->sg_segs[i].len      = f->size;
4844  
4845  		qdf_assert(i < QDF_MAX_SGLIST);
4846  	}
4847  	sg->nsegs += i;
4848  
4849  }
4850  qdf_export_symbol(__qdf_nbuf_frag_info);
4851  #else
4852  #ifdef QDF_OS_DEBUG
4853  void
__qdf_nbuf_frag_info(struct sk_buff * skb,qdf_sglist_t * sg)4854  __qdf_nbuf_frag_info(struct sk_buff *skb, qdf_sglist_t  *sg)
4855  {
4856  
4857  	struct skb_shared_info  *sh = skb_shinfo(skb);
4858  
4859  	qdf_assert(skb);
4860  	sg->sg_segs[0].vaddr = skb->data;
4861  	sg->sg_segs[0].len   = skb->len;
4862  	sg->nsegs            = 1;
4863  
4864  	qdf_assert(sh->nr_frags == 0);
4865  }
4866  qdf_export_symbol(__qdf_nbuf_frag_info);
4867  #else
4868  void
__qdf_nbuf_frag_info(struct sk_buff * skb,qdf_sglist_t * sg)4869  __qdf_nbuf_frag_info(struct sk_buff *skb, qdf_sglist_t  *sg)
4870  {
4871  	sg->sg_segs[0].vaddr = skb->data;
4872  	sg->sg_segs[0].len   = skb->len;
4873  	sg->nsegs            = 1;
4874  }
4875  qdf_export_symbol(__qdf_nbuf_frag_info);
4876  #endif
4877  #endif
4878  uint32_t
__qdf_nbuf_get_frag_size(__qdf_nbuf_t nbuf,uint32_t cur_frag)4879  __qdf_nbuf_get_frag_size(__qdf_nbuf_t nbuf, uint32_t cur_frag)
4880  {
4881  	struct skb_shared_info  *sh = skb_shinfo(nbuf);
4882  	const skb_frag_t *frag = sh->frags + cur_frag;
4883  
4884  	return skb_frag_size(frag);
4885  }
4886  qdf_export_symbol(__qdf_nbuf_get_frag_size);
4887  
4888  #ifdef A_SIMOS_DEVHOST
__qdf_nbuf_frag_map(qdf_device_t osdev,__qdf_nbuf_t nbuf,int offset,qdf_dma_dir_t dir,int cur_frag)4889  QDF_STATUS __qdf_nbuf_frag_map(
4890  	qdf_device_t osdev, __qdf_nbuf_t nbuf,
4891  	int offset, qdf_dma_dir_t dir, int cur_frag)
4892  {
4893  	int32_t paddr, frag_len;
4894  
4895  	QDF_NBUF_CB_PADDR(nbuf) = paddr = nbuf->data;
4896  	return QDF_STATUS_SUCCESS;
4897  }
4898  qdf_export_symbol(__qdf_nbuf_frag_map);
4899  #else
__qdf_nbuf_frag_map(qdf_device_t osdev,__qdf_nbuf_t nbuf,int offset,qdf_dma_dir_t dir,int cur_frag)4900  QDF_STATUS __qdf_nbuf_frag_map(
4901  	qdf_device_t osdev, __qdf_nbuf_t nbuf,
4902  	int offset, qdf_dma_dir_t dir, int cur_frag)
4903  {
4904  	dma_addr_t paddr, frag_len;
4905  	struct skb_shared_info *sh = skb_shinfo(nbuf);
4906  	const skb_frag_t *frag = sh->frags + cur_frag;
4907  
4908  	frag_len = skb_frag_size(frag);
4909  
4910  	QDF_NBUF_CB_TX_EXTRA_FRAG_PADDR(nbuf) = paddr =
4911  		skb_frag_dma_map(osdev->dev, frag, offset, frag_len,
4912  					__qdf_dma_dir_to_os(dir));
4913  	return dma_mapping_error(osdev->dev, paddr) ?
4914  			QDF_STATUS_E_FAULT : QDF_STATUS_SUCCESS;
4915  }
4916  qdf_export_symbol(__qdf_nbuf_frag_map);
4917  #endif
4918  void
__qdf_nbuf_dmamap_set_cb(__qdf_dma_map_t dmap,void * cb,void * arg)4919  __qdf_nbuf_dmamap_set_cb(__qdf_dma_map_t dmap, void *cb, void *arg)
4920  {
4921  	return;
4922  }
4923  qdf_export_symbol(__qdf_nbuf_dmamap_set_cb);
4924  
4925  /**
4926   * __qdf_nbuf_sync_single_for_cpu() - nbuf sync
4927   * @osdev: os device
4928   * @buf: sk buff
4929   * @dir: direction
4930   *
4931   * Return: none
4932   */
4933  #if defined(A_SIMOS_DEVHOST)
__qdf_nbuf_sync_single_for_cpu(qdf_device_t osdev,qdf_nbuf_t buf,qdf_dma_dir_t dir)4934  static void __qdf_nbuf_sync_single_for_cpu(
4935  	qdf_device_t osdev, qdf_nbuf_t buf, qdf_dma_dir_t dir)
4936  {
4937  	return;
4938  }
4939  #else
__qdf_nbuf_sync_single_for_cpu(qdf_device_t osdev,qdf_nbuf_t buf,qdf_dma_dir_t dir)4940  static void __qdf_nbuf_sync_single_for_cpu(
4941  	qdf_device_t osdev, qdf_nbuf_t buf, qdf_dma_dir_t dir)
4942  {
4943  	if (0 ==  QDF_NBUF_CB_PADDR(buf)) {
4944  		qdf_err("ERROR: NBUF mapped physical address is NULL");
4945  		return;
4946  	}
4947  	dma_sync_single_for_cpu(osdev->dev, QDF_NBUF_CB_PADDR(buf),
4948  		skb_end_offset(buf) - skb_headroom(buf),
4949  		__qdf_dma_dir_to_os(dir));
4950  }
4951  #endif
4952  
4953  void
__qdf_nbuf_sync_for_cpu(qdf_device_t osdev,struct sk_buff * skb,qdf_dma_dir_t dir)4954  __qdf_nbuf_sync_for_cpu(qdf_device_t osdev,
4955  	struct sk_buff *skb, qdf_dma_dir_t dir)
4956  {
4957  	qdf_assert(
4958  	(dir == QDF_DMA_TO_DEVICE) || (dir == QDF_DMA_FROM_DEVICE));
4959  
4960  	/*
4961  	 * Assume there's a single fragment.
4962  	 * If this is not true, the assertion in __adf_nbuf_map will catch it.
4963  	 */
4964  	__qdf_nbuf_sync_single_for_cpu(osdev, skb, dir);
4965  }
4966  qdf_export_symbol(__qdf_nbuf_sync_for_cpu);
4967  
4968  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 0))
4969  /**
4970   * qdf_nbuf_update_radiotap_vht_flags() - Update radiotap header VHT flags
4971   * @rx_status: Pointer to rx_status.
4972   * @rtap_buf: Buf to which VHT info has to be updated.
4973   * @rtap_len: Current length of radiotap buffer
4974   *
4975   * Return: Length of radiotap after VHT flags updated.
4976   */
qdf_nbuf_update_radiotap_vht_flags(struct mon_rx_status * rx_status,int8_t * rtap_buf,uint32_t rtap_len)4977  static unsigned int qdf_nbuf_update_radiotap_vht_flags(
4978  					struct mon_rx_status *rx_status,
4979  					int8_t *rtap_buf,
4980  					uint32_t rtap_len)
4981  {
4982  	uint16_t vht_flags = 0;
4983  	struct mon_rx_user_status *rx_user_status = rx_status->rx_user_status;
4984  
4985  	rtap_len = qdf_align(rtap_len, 2);
4986  
4987  	/* IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16 */
4988  	vht_flags |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC |
4989  		IEEE80211_RADIOTAP_VHT_KNOWN_GI |
4990  		IEEE80211_RADIOTAP_VHT_KNOWN_LDPC_EXTRA_OFDM_SYM |
4991  		IEEE80211_RADIOTAP_VHT_KNOWN_BEAMFORMED |
4992  		IEEE80211_RADIOTAP_VHT_KNOWN_BANDWIDTH |
4993  		IEEE80211_RADIOTAP_VHT_KNOWN_GROUP_ID;
4994  	put_unaligned_le16(vht_flags, &rtap_buf[rtap_len]);
4995  	rtap_len += 2;
4996  
4997  	rtap_buf[rtap_len] |=
4998  		(rx_status->is_stbc ?
4999  		 IEEE80211_RADIOTAP_VHT_FLAG_STBC : 0) |
5000  		(rx_status->sgi ? IEEE80211_RADIOTAP_VHT_FLAG_SGI : 0) |
5001  		(rx_status->ldpc ?
5002  		 IEEE80211_RADIOTAP_VHT_FLAG_LDPC_EXTRA_OFDM_SYM : 0) |
5003  		(rx_status->beamformed ?
5004  		 IEEE80211_RADIOTAP_VHT_FLAG_BEAMFORMED : 0);
5005  	rtap_len += 1;
5006  
5007  	if (!rx_user_status) {
5008  		switch (rx_status->vht_flag_values2) {
5009  		case IEEE80211_RADIOTAP_VHT_BW_20:
5010  			rtap_buf[rtap_len] = RADIOTAP_VHT_BW_20;
5011  			break;
5012  		case IEEE80211_RADIOTAP_VHT_BW_40:
5013  			rtap_buf[rtap_len] = RADIOTAP_VHT_BW_40;
5014  			break;
5015  		case IEEE80211_RADIOTAP_VHT_BW_80:
5016  			rtap_buf[rtap_len] = RADIOTAP_VHT_BW_80;
5017  			break;
5018  		case IEEE80211_RADIOTAP_VHT_BW_160:
5019  			rtap_buf[rtap_len] = RADIOTAP_VHT_BW_160;
5020  			break;
5021  		}
5022  		rtap_len += 1;
5023  		rtap_buf[rtap_len] = (rx_status->vht_flag_values3[0]);
5024  		rtap_len += 1;
5025  		rtap_buf[rtap_len] = (rx_status->vht_flag_values3[1]);
5026  		rtap_len += 1;
5027  		rtap_buf[rtap_len] = (rx_status->vht_flag_values3[2]);
5028  		rtap_len += 1;
5029  		rtap_buf[rtap_len] = (rx_status->vht_flag_values3[3]);
5030  		rtap_len += 1;
5031  		rtap_buf[rtap_len] = (rx_status->vht_flag_values4);
5032  		rtap_len += 1;
5033  		rtap_buf[rtap_len] = (rx_status->vht_flag_values5);
5034  		rtap_len += 1;
5035  		put_unaligned_le16(rx_status->vht_flag_values6,
5036  				   &rtap_buf[rtap_len]);
5037  		rtap_len += 2;
5038  	} else {
5039  		switch (rx_user_status->vht_flag_values2) {
5040  		case IEEE80211_RADIOTAP_VHT_BW_20:
5041  			rtap_buf[rtap_len] = RADIOTAP_VHT_BW_20;
5042  			break;
5043  		case IEEE80211_RADIOTAP_VHT_BW_40:
5044  			rtap_buf[rtap_len] = RADIOTAP_VHT_BW_40;
5045  			break;
5046  		case IEEE80211_RADIOTAP_VHT_BW_80:
5047  			rtap_buf[rtap_len] = RADIOTAP_VHT_BW_80;
5048  			break;
5049  		case IEEE80211_RADIOTAP_VHT_BW_160:
5050  			rtap_buf[rtap_len] = RADIOTAP_VHT_BW_160;
5051  			break;
5052  		}
5053  		rtap_len += 1;
5054  		rtap_buf[rtap_len] = (rx_user_status->vht_flag_values3[0]);
5055  		rtap_len += 1;
5056  		rtap_buf[rtap_len] = (rx_user_status->vht_flag_values3[1]);
5057  		rtap_len += 1;
5058  		rtap_buf[rtap_len] = (rx_user_status->vht_flag_values3[2]);
5059  		rtap_len += 1;
5060  		rtap_buf[rtap_len] = (rx_user_status->vht_flag_values3[3]);
5061  		rtap_len += 1;
5062  		rtap_buf[rtap_len] = (rx_user_status->vht_flag_values4);
5063  		rtap_len += 1;
5064  		rtap_buf[rtap_len] = (rx_user_status->vht_flag_values5);
5065  		rtap_len += 1;
5066  		put_unaligned_le16(rx_user_status->vht_flag_values6,
5067  				   &rtap_buf[rtap_len]);
5068  		rtap_len += 2;
5069  	}
5070  
5071  	return rtap_len;
5072  }
5073  
5074  /**
5075   * qdf_nbuf_update_radiotap_he_flags() - Update radiotap header from rx_status
5076   * @rx_status: Pointer to rx_status.
5077   * @rtap_buf: buffer to which radiotap has to be updated
5078   * @rtap_len: radiotap length
5079   *
5080   * API update high-efficiency (11ax) fields in the radiotap header
5081   *
5082   * Return: length of rtap_len updated.
5083   */
5084  static unsigned int
qdf_nbuf_update_radiotap_he_flags(struct mon_rx_status * rx_status,int8_t * rtap_buf,uint32_t rtap_len)5085  qdf_nbuf_update_radiotap_he_flags(struct mon_rx_status *rx_status,
5086  				     int8_t *rtap_buf, uint32_t rtap_len)
5087  {
5088  	/*
5089  	 * IEEE80211_RADIOTAP_HE u16, u16, u16, u16, u16, u16
5090  	 * Enable all "known" HE radiotap flags for now
5091  	 */
5092  	struct mon_rx_user_status *rx_user_status = rx_status->rx_user_status;
5093  
5094  	rtap_len = qdf_align(rtap_len, 2);
5095  
5096  	if (!rx_user_status) {
5097  		put_unaligned_le16(rx_status->he_data1, &rtap_buf[rtap_len]);
5098  		rtap_len += 2;
5099  
5100  		put_unaligned_le16(rx_status->he_data2, &rtap_buf[rtap_len]);
5101  		rtap_len += 2;
5102  
5103  		put_unaligned_le16(rx_status->he_data3, &rtap_buf[rtap_len]);
5104  		rtap_len += 2;
5105  
5106  		put_unaligned_le16(rx_status->he_data4, &rtap_buf[rtap_len]);
5107  		rtap_len += 2;
5108  
5109  		put_unaligned_le16(rx_status->he_data5, &rtap_buf[rtap_len]);
5110  		rtap_len += 2;
5111  
5112  		put_unaligned_le16(rx_status->he_data6, &rtap_buf[rtap_len]);
5113  		rtap_len += 2;
5114  	} else {
5115  		put_unaligned_le16(rx_user_status->he_data1 |
5116  				   rx_status->he_data1, &rtap_buf[rtap_len]);
5117  		rtap_len += 2;
5118  
5119  		put_unaligned_le16(rx_user_status->he_data2 |
5120  				   rx_status->he_data2, &rtap_buf[rtap_len]);
5121  		rtap_len += 2;
5122  
5123  		put_unaligned_le16(rx_user_status->he_data3 |
5124  				   rx_status->he_data3, &rtap_buf[rtap_len]);
5125  		rtap_len += 2;
5126  
5127  		put_unaligned_le16(rx_user_status->he_data4 |
5128  				   rx_status->he_data4, &rtap_buf[rtap_len]);
5129  		rtap_len += 2;
5130  
5131  		put_unaligned_le16(rx_user_status->he_data5 |
5132  				   rx_status->he_data5, &rtap_buf[rtap_len]);
5133  		rtap_len += 2;
5134  
5135  		put_unaligned_le16(rx_user_status->he_data6 |
5136  				   rx_status->he_data6, &rtap_buf[rtap_len]);
5137  		rtap_len += 2;
5138  	}
5139  
5140  	return rtap_len;
5141  }
5142  
5143  
5144  /**
5145   * qdf_nbuf_update_radiotap_he_mu_flags() - update he-mu radiotap flags
5146   * @rx_status: Pointer to rx_status.
5147   * @rtap_buf: buffer to which radiotap has to be updated
5148   * @rtap_len: radiotap length
5149   *
5150   * API update HE-MU fields in the radiotap header
5151   *
5152   * Return: length of rtap_len updated.
5153   */
5154  static unsigned int
qdf_nbuf_update_radiotap_he_mu_flags(struct mon_rx_status * rx_status,int8_t * rtap_buf,uint32_t rtap_len)5155  qdf_nbuf_update_radiotap_he_mu_flags(struct mon_rx_status *rx_status,
5156  				     int8_t *rtap_buf, uint32_t rtap_len)
5157  {
5158  	struct mon_rx_user_status *rx_user_status = rx_status->rx_user_status;
5159  
5160  	rtap_len = qdf_align(rtap_len, 2);
5161  
5162  	/*
5163  	 * IEEE80211_RADIOTAP_HE_MU u16, u16, u8[4]
5164  	 * Enable all "known" he-mu radiotap flags for now
5165  	 */
5166  
5167  	if (!rx_user_status) {
5168  		put_unaligned_le16(rx_status->he_flags1, &rtap_buf[rtap_len]);
5169  		rtap_len += 2;
5170  
5171  		put_unaligned_le16(rx_status->he_flags2, &rtap_buf[rtap_len]);
5172  		rtap_len += 2;
5173  
5174  		rtap_buf[rtap_len] = rx_status->he_RU[0];
5175  		rtap_len += 1;
5176  
5177  		rtap_buf[rtap_len] = rx_status->he_RU[1];
5178  		rtap_len += 1;
5179  
5180  		rtap_buf[rtap_len] = rx_status->he_RU[2];
5181  		rtap_len += 1;
5182  
5183  		rtap_buf[rtap_len] = rx_status->he_RU[3];
5184  		rtap_len += 1;
5185  	} else {
5186  		put_unaligned_le16(rx_user_status->he_flags1,
5187  				   &rtap_buf[rtap_len]);
5188  		rtap_len += 2;
5189  
5190  		put_unaligned_le16(rx_user_status->he_flags2,
5191  				   &rtap_buf[rtap_len]);
5192  		rtap_len += 2;
5193  
5194  		rtap_buf[rtap_len] = rx_user_status->he_RU[0];
5195  		rtap_len += 1;
5196  
5197  		rtap_buf[rtap_len] = rx_user_status->he_RU[1];
5198  		rtap_len += 1;
5199  
5200  		rtap_buf[rtap_len] = rx_user_status->he_RU[2];
5201  		rtap_len += 1;
5202  
5203  		rtap_buf[rtap_len] = rx_user_status->he_RU[3];
5204  		rtap_len += 1;
5205  		qdf_debug("he_flags %x %x he-RU %x %x %x %x",
5206  			  rx_user_status->he_flags1,
5207  			  rx_user_status->he_flags2, rx_user_status->he_RU[0],
5208  			  rx_user_status->he_RU[1], rx_user_status->he_RU[2],
5209  			  rx_user_status->he_RU[3]);
5210  	}
5211  
5212  	return rtap_len;
5213  }
5214  
5215  /**
5216   * qdf_nbuf_update_radiotap_he_mu_other_flags() - update he_mu_other flags
5217   * @rx_status: Pointer to rx_status.
5218   * @rtap_buf: buffer to which radiotap has to be updated
5219   * @rtap_len: radiotap length
5220   *
5221   * API update he-mu-other fields in the radiotap header
5222   *
5223   * Return: length of rtap_len updated.
5224   */
5225  static unsigned int
qdf_nbuf_update_radiotap_he_mu_other_flags(struct mon_rx_status * rx_status,int8_t * rtap_buf,uint32_t rtap_len)5226  qdf_nbuf_update_radiotap_he_mu_other_flags(struct mon_rx_status *rx_status,
5227  				     int8_t *rtap_buf, uint32_t rtap_len)
5228  {
5229  	struct mon_rx_user_status *rx_user_status = rx_status->rx_user_status;
5230  
5231  	rtap_len = qdf_align(rtap_len, 2);
5232  
5233  	/*
5234  	 * IEEE80211_RADIOTAP_HE-MU-OTHER u16, u16, u8, u8
5235  	 * Enable all "known" he-mu-other radiotap flags for now
5236  	 */
5237  	if (!rx_user_status) {
5238  		put_unaligned_le16(rx_status->he_per_user_1,
5239  				   &rtap_buf[rtap_len]);
5240  		rtap_len += 2;
5241  
5242  		put_unaligned_le16(rx_status->he_per_user_2,
5243  				   &rtap_buf[rtap_len]);
5244  		rtap_len += 2;
5245  
5246  		rtap_buf[rtap_len] = rx_status->he_per_user_position;
5247  		rtap_len += 1;
5248  
5249  		rtap_buf[rtap_len] = rx_status->he_per_user_known;
5250  		rtap_len += 1;
5251  	} else {
5252  		put_unaligned_le16(rx_user_status->he_per_user_1,
5253  				   &rtap_buf[rtap_len]);
5254  		rtap_len += 2;
5255  
5256  		put_unaligned_le16(rx_user_status->he_per_user_2,
5257  				   &rtap_buf[rtap_len]);
5258  		rtap_len += 2;
5259  
5260  		rtap_buf[rtap_len] = rx_user_status->he_per_user_position;
5261  		rtap_len += 1;
5262  
5263  		rtap_buf[rtap_len] = rx_user_status->he_per_user_known;
5264  		rtap_len += 1;
5265  	}
5266  
5267  	return rtap_len;
5268  }
5269  
5270  /**
5271   * qdf_nbuf_update_radiotap_usig_flags() - Update radiotap header with USIG data
5272   *						from rx_status
5273   * @rx_status: Pointer to rx_status.
5274   * @rtap_buf: buffer to which radiotap has to be updated
5275   * @rtap_len: radiotap length
5276   *
5277   * API update Extra High Throughput (11be) fields in the radiotap header
5278   *
5279   * Return: length of rtap_len updated.
5280   */
5281  static unsigned int
qdf_nbuf_update_radiotap_usig_flags(struct mon_rx_status * rx_status,int8_t * rtap_buf,uint32_t rtap_len)5282  qdf_nbuf_update_radiotap_usig_flags(struct mon_rx_status *rx_status,
5283  				    int8_t *rtap_buf, uint32_t rtap_len)
5284  {
5285  	/*
5286  	 * IEEE80211_RADIOTAP_USIG:
5287  	 *		u32, u32, u32
5288  	 */
5289  	rtap_len = qdf_align(rtap_len, 4);
5290  
5291  	put_unaligned_le32(rx_status->usig_common, &rtap_buf[rtap_len]);
5292  	rtap_len += 4;
5293  
5294  	put_unaligned_le32(rx_status->usig_value, &rtap_buf[rtap_len]);
5295  	rtap_len += 4;
5296  
5297  	put_unaligned_le32(rx_status->usig_mask, &rtap_buf[rtap_len]);
5298  	rtap_len += 4;
5299  
5300  	qdf_rl_debug("U-SIG data %x %x %x",
5301  		     rx_status->usig_common, rx_status->usig_value,
5302  		     rx_status->usig_mask);
5303  
5304  	return rtap_len;
5305  }
5306  
5307  /**
5308   * qdf_nbuf_update_radiotap_eht_flags() - Update radiotap header with EHT data
5309   *					from rx_status
5310   * @rx_status: Pointer to rx_status.
5311   * @rtap_buf: buffer to which radiotap has to be updated
5312   * @rtap_len: radiotap length
5313   *
5314   * API update Extra High Throughput (11be) fields in the radiotap header
5315   *
5316   * Return: length of rtap_len updated.
5317   */
5318  static unsigned int
qdf_nbuf_update_radiotap_eht_flags(struct mon_rx_status * rx_status,int8_t * rtap_buf,uint32_t rtap_len)5319  qdf_nbuf_update_radiotap_eht_flags(struct mon_rx_status *rx_status,
5320  				   int8_t *rtap_buf, uint32_t rtap_len)
5321  {
5322  	struct mon_rx_user_status *rx_user_status = rx_status->rx_user_status;
5323  	/*
5324  	 * IEEE80211_RADIOTAP_EHT:
5325  	 *		u32, u32, u32, u32, u32, u32, u32, u16, [u32, u32, u32]
5326  	 */
5327  	rtap_len = qdf_align(rtap_len, 4);
5328  
5329  	if (!rx_user_status) {
5330  		put_unaligned_le32(rx_status->eht_known, &rtap_buf[rtap_len]);
5331  		rtap_len += 4;
5332  
5333  		put_unaligned_le32(rx_status->eht_data[0], &rtap_buf[rtap_len]);
5334  		rtap_len += 4;
5335  
5336  		put_unaligned_le32(rx_status->eht_data[1], &rtap_buf[rtap_len]);
5337  		rtap_len += 4;
5338  	} else {
5339  		put_unaligned_le32(rx_status->eht_known |
5340  				   rx_user_status->eht_known,
5341  				   &rtap_buf[rtap_len]);
5342  		rtap_len += 4;
5343  
5344  		put_unaligned_le32(rx_status->eht_data[0] |
5345  				   rx_user_status->eht_data[0],
5346  				   &rtap_buf[rtap_len]);
5347  		rtap_len += 4;
5348  
5349  		put_unaligned_le32(rx_status->eht_data[1] |
5350  				   rx_user_status->eht_data[1],
5351  				   &rtap_buf[rtap_len]);
5352  		rtap_len += 4;
5353  	}
5354  
5355  	put_unaligned_le32(rx_status->eht_data[2], &rtap_buf[rtap_len]);
5356  	rtap_len += 4;
5357  
5358  	put_unaligned_le32(rx_status->eht_data[3], &rtap_buf[rtap_len]);
5359  	rtap_len += 4;
5360  
5361  	put_unaligned_le32(rx_status->eht_data[4], &rtap_buf[rtap_len]);
5362  	rtap_len += 4;
5363  
5364  	put_unaligned_le32(rx_status->eht_data[5], &rtap_buf[rtap_len]);
5365  	rtap_len += 4;
5366  
5367  	if (!rx_user_status) {
5368  		qdf_rl_debug("EHT data %x %x %x %x %x %x %x",
5369  			     rx_status->eht_known, rx_status->eht_data[0],
5370  			     rx_status->eht_data[1], rx_status->eht_data[2],
5371  			     rx_status->eht_data[3], rx_status->eht_data[4],
5372  			     rx_status->eht_data[5]);
5373  	} else {
5374  		put_unaligned_le32(rx_user_status->eht_user_info, &rtap_buf[rtap_len]);
5375  		rtap_len += 4;
5376  
5377  		qdf_rl_debug("EHT data %x %x %x %x %x %x %x",
5378  			     rx_status->eht_known | rx_user_status->eht_known,
5379  			     rx_status->eht_data[0] |
5380  			     rx_user_status->eht_data[0],
5381  			     rx_status->eht_data[1] |
5382  			     rx_user_status->eht_data[1],
5383  			     rx_status->eht_data[2], rx_status->eht_data[3],
5384  			     rx_status->eht_data[4], rx_status->eht_data[5]);
5385  	}
5386  
5387  	return rtap_len;
5388  }
5389  
5390  #define IEEE80211_RADIOTAP_TX_STATUS 0
5391  #define IEEE80211_RADIOTAP_RETRY_COUNT 1
5392  #define IEEE80211_RADIOTAP_EXTENSION2 2
5393  uint8_t ATH_OUI[] = {0x00, 0x03, 0x7f}; /* Atheros OUI */
5394  
5395  /**
5396   * qdf_nbuf_update_radiotap_ampdu_flags() - Update radiotap header ampdu flags
5397   * @rx_status: Pointer to rx_status.
5398   * @rtap_buf: Buf to which AMPDU info has to be updated.
5399   * @rtap_len: Current length of radiotap buffer
5400   *
5401   * Return: Length of radiotap after AMPDU flags updated.
5402   */
qdf_nbuf_update_radiotap_ampdu_flags(struct mon_rx_status * rx_status,uint8_t * rtap_buf,uint32_t rtap_len)5403  static unsigned int qdf_nbuf_update_radiotap_ampdu_flags(
5404  					struct mon_rx_status *rx_status,
5405  					uint8_t *rtap_buf,
5406  					uint32_t rtap_len)
5407  {
5408  	/*
5409  	 * IEEE80211_RADIOTAP_AMPDU_STATUS u32 u16 u8 u8
5410  	 * First 32 bits of AMPDU represents the reference number
5411  	 */
5412  
5413  	uint32_t ampdu_reference_num = rx_status->ppdu_id;
5414  	uint16_t ampdu_flags = 0;
5415  	uint16_t ampdu_reserved_flags = 0;
5416  
5417  	rtap_len = qdf_align(rtap_len, 4);
5418  
5419  	put_unaligned_le32(ampdu_reference_num, &rtap_buf[rtap_len]);
5420  	rtap_len += 4;
5421  	put_unaligned_le16(ampdu_flags, &rtap_buf[rtap_len]);
5422  	rtap_len += 2;
5423  	put_unaligned_le16(ampdu_reserved_flags, &rtap_buf[rtap_len]);
5424  	rtap_len += 2;
5425  
5426  	return rtap_len;
5427  }
5428  
5429  #ifdef DP_MON_RSSI_IN_DBM
5430  #define QDF_MON_STATUS_GET_RSSI_IN_DBM(rx_status) \
5431  (rx_status->rssi_comb)
5432  #else
5433  #ifdef QCA_RSSI_DB2DBM
5434  #define QDF_MON_STATUS_GET_RSSI_IN_DBM(rx_status) \
5435  (((rx_status)->rssi_dbm_conv_support) ? \
5436  ((rx_status)->rssi_comb + (rx_status)->rssi_offset) :\
5437  ((rx_status)->rssi_comb + (rx_status)->chan_noise_floor))
5438  #else
5439  #define QDF_MON_STATUS_GET_RSSI_IN_DBM(rx_status) \
5440  (rx_status->rssi_comb + rx_status->chan_noise_floor)
5441  #endif
5442  #endif
5443  
5444  /**
5445   * qdf_nbuf_update_radiotap_tx_flags() - Update radiotap header tx flags
5446   * @rx_status: Pointer to rx_status.
5447   * @rtap_buf: Buf to which tx info has to be updated.
5448   * @rtap_len: Current length of radiotap buffer
5449   *
5450   * Return: Length of radiotap after tx flags updated.
5451   */
qdf_nbuf_update_radiotap_tx_flags(struct mon_rx_status * rx_status,uint8_t * rtap_buf,uint32_t rtap_len)5452  static unsigned int qdf_nbuf_update_radiotap_tx_flags(
5453  						struct mon_rx_status *rx_status,
5454  						uint8_t *rtap_buf,
5455  						uint32_t rtap_len)
5456  {
5457  	/*
5458  	 * IEEE80211_RADIOTAP_TX_FLAGS u16
5459  	 */
5460  
5461  	uint16_t tx_flags = 0;
5462  
5463  	rtap_len = qdf_align(rtap_len, 2);
5464  
5465  	switch (rx_status->tx_status) {
5466  	case RADIOTAP_TX_STATUS_FAIL:
5467  		tx_flags |= IEEE80211_RADIOTAP_F_TX_FAIL;
5468  		break;
5469  	case RADIOTAP_TX_STATUS_NOACK:
5470  		tx_flags |= IEEE80211_RADIOTAP_F_TX_NOACK;
5471  		break;
5472  	}
5473  	put_unaligned_le16(tx_flags, &rtap_buf[rtap_len]);
5474  	rtap_len += 2;
5475  
5476  	return rtap_len;
5477  }
5478  
qdf_nbuf_update_radiotap(struct mon_rx_status * rx_status,qdf_nbuf_t nbuf,uint32_t headroom_sz)5479  unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
5480  				      qdf_nbuf_t nbuf, uint32_t headroom_sz)
5481  {
5482  	uint8_t rtap_buf[RADIOTAP_HEADER_LEN] = {0};
5483  	struct ieee80211_radiotap_header *rthdr =
5484  		(struct ieee80211_radiotap_header *)rtap_buf;
5485  	uint32_t rtap_hdr_len = sizeof(struct ieee80211_radiotap_header);
5486  	uint32_t rtap_len = rtap_hdr_len;
5487  	uint8_t length = rtap_len;
5488  	struct qdf_radiotap_vendor_ns_ath *radiotap_vendor_ns_ath;
5489  	struct qdf_radiotap_ext2 *rtap_ext2;
5490  	struct mon_rx_user_status *rx_user_status = rx_status->rx_user_status;
5491  
5492  	/* per user info */
5493  	qdf_le32_t *it_present;
5494  	uint32_t it_present_val;
5495  	bool radiotap_ext1_hdr_present = false;
5496  
5497  	it_present = &rthdr->it_present;
5498  
5499  	/* Adding Extended Header space */
5500  	if (rx_status->add_rtap_ext || rx_status->add_rtap_ext2 ||
5501  	    rx_status->usig_flags || rx_status->eht_flags) {
5502  		rtap_hdr_len += RADIOTAP_HEADER_EXT_LEN;
5503  		rtap_len = rtap_hdr_len;
5504  		radiotap_ext1_hdr_present = true;
5505  	}
5506  
5507  	length = rtap_len;
5508  
5509  	/* IEEE80211_RADIOTAP_TSFT              __le64       microseconds*/
5510  	it_present_val = (1 << IEEE80211_RADIOTAP_TSFT);
5511  	put_unaligned_le64(rx_status->tsft, &rtap_buf[rtap_len]);
5512  	rtap_len += 8;
5513  
5514  	/* IEEE80211_RADIOTAP_FLAGS u8 */
5515  	it_present_val |= (1 << IEEE80211_RADIOTAP_FLAGS);
5516  
5517  	if (rx_status->rs_fcs_err)
5518  		rx_status->rtap_flags |= IEEE80211_RADIOTAP_F_BADFCS;
5519  
5520  	rtap_buf[rtap_len] = rx_status->rtap_flags;
5521  	rtap_len += 1;
5522  
5523  	/* IEEE80211_RADIOTAP_RATE  u8           500kb/s */
5524  	if (!rx_status->ht_flags && !rx_status->vht_flags &&
5525  	    !rx_status->he_flags && !rx_status->eht_flags) {
5526  		it_present_val |= (1 << IEEE80211_RADIOTAP_RATE);
5527  		rtap_buf[rtap_len] = rx_status->rate;
5528  	} else
5529  		rtap_buf[rtap_len] = 0;
5530  	rtap_len += 1;
5531  
5532  	/* IEEE80211_RADIOTAP_CHANNEL 2 x __le16   MHz, bitmap */
5533  	it_present_val |= (1 << IEEE80211_RADIOTAP_CHANNEL);
5534  	put_unaligned_le16(rx_status->chan_freq, &rtap_buf[rtap_len]);
5535  	rtap_len += 2;
5536  	/* Channel flags. */
5537  	if (rx_status->chan_freq > CHANNEL_FREQ_5150)
5538  		rx_status->chan_flags = RADIOTAP_5G_SPECTRUM_CHANNEL;
5539  	else
5540  		rx_status->chan_flags = RADIOTAP_2G_SPECTRUM_CHANNEL;
5541  	if (rx_status->cck_flag)
5542  		rx_status->chan_flags |= RADIOTAP_CCK_CHANNEL;
5543  	if (rx_status->ofdm_flag)
5544  		rx_status->chan_flags |= RADIOTAP_OFDM_CHANNEL;
5545  	put_unaligned_le16(rx_status->chan_flags, &rtap_buf[rtap_len]);
5546  	rtap_len += 2;
5547  
5548  	/* IEEE80211_RADIOTAP_DBM_ANTSIGNAL s8  decibels from one milliwatt
5549  	 *					(dBm)
5550  	 */
5551  	it_present_val |= (1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
5552  	/*
5553  	 * rssi_comb is int dB, need to convert it to dBm.
5554  	 * normalize value to noise floor of -96 dBm
5555  	 */
5556  	rtap_buf[rtap_len] = QDF_MON_STATUS_GET_RSSI_IN_DBM(rx_status);
5557  	rtap_len += 1;
5558  
5559  	/* RX signal noise floor */
5560  	it_present_val |= (1 << IEEE80211_RADIOTAP_DBM_ANTNOISE);
5561  	rtap_buf[rtap_len] = (uint8_t)rx_status->chan_noise_floor;
5562  	rtap_len += 1;
5563  
5564  	/* IEEE80211_RADIOTAP_ANTENNA   u8      antenna index */
5565  	it_present_val |= (1 << IEEE80211_RADIOTAP_ANTENNA);
5566  	rtap_buf[rtap_len] = rx_status->nr_ant;
5567  	rtap_len += 1;
5568  
5569  	if ((rtap_len - length) > RADIOTAP_FIXED_HEADER_LEN) {
5570  		qdf_print("length is greater than RADIOTAP_FIXED_HEADER_LEN");
5571  		return 0;
5572  	}
5573  
5574  	/* update tx flags for pkt capture*/
5575  	if (rx_status->add_rtap_ext) {
5576  		it_present_val |=
5577  			cpu_to_le32(1 << IEEE80211_RADIOTAP_TX_FLAGS);
5578  		rtap_len = qdf_nbuf_update_radiotap_tx_flags(rx_status,
5579  							     rtap_buf,
5580  							     rtap_len);
5581  
5582  		if ((rtap_len - length) > RADIOTAP_TX_FLAGS_LEN) {
5583  			qdf_print("length is greater than RADIOTAP_TX_FLAGS_LEN");
5584  			return 0;
5585  		}
5586  	}
5587  
5588  	if (rx_status->ht_flags) {
5589  		length = rtap_len;
5590  		/* IEEE80211_RADIOTAP_VHT u8, u8, u8 */
5591  		it_present_val |= (1 << IEEE80211_RADIOTAP_MCS);
5592  		rtap_buf[rtap_len] = IEEE80211_RADIOTAP_MCS_HAVE_BW |
5593  					IEEE80211_RADIOTAP_MCS_HAVE_MCS |
5594  					IEEE80211_RADIOTAP_MCS_HAVE_GI;
5595  		rtap_len += 1;
5596  
5597  		if (rx_status->sgi)
5598  			rtap_buf[rtap_len] |= IEEE80211_RADIOTAP_MCS_SGI;
5599  		if (rx_status->bw)
5600  			rtap_buf[rtap_len] |= IEEE80211_RADIOTAP_MCS_BW_40;
5601  		else
5602  			rtap_buf[rtap_len] |= IEEE80211_RADIOTAP_MCS_BW_20;
5603  		rtap_len += 1;
5604  
5605  		rtap_buf[rtap_len] = rx_status->ht_mcs;
5606  		rtap_len += 1;
5607  
5608  		if ((rtap_len - length) > RADIOTAP_HT_FLAGS_LEN) {
5609  			qdf_print("length is greater than RADIOTAP_HT_FLAGS_LEN");
5610  			return 0;
5611  		}
5612  	}
5613  
5614  	if (rx_status->rs_flags & IEEE80211_AMPDU_FLAG) {
5615  		/* IEEE80211_RADIOTAP_AMPDU_STATUS u32 u16 u8 u8 */
5616  		it_present_val |= (1 << IEEE80211_RADIOTAP_AMPDU_STATUS);
5617  		rtap_len = qdf_nbuf_update_radiotap_ampdu_flags(rx_status,
5618  								rtap_buf,
5619  								rtap_len);
5620  	}
5621  
5622  	if (rx_status->vht_flags) {
5623  		length = rtap_len;
5624  		/* IEEE80211_RADIOTAP_VHT u16, u8, u8, u8[4], u8, u8, u16 */
5625  		it_present_val |= (1 << IEEE80211_RADIOTAP_VHT);
5626  		rtap_len = qdf_nbuf_update_radiotap_vht_flags(rx_status,
5627  								rtap_buf,
5628  								rtap_len);
5629  
5630  		if ((rtap_len - length) > RADIOTAP_VHT_FLAGS_LEN) {
5631  			qdf_print("length is greater than RADIOTAP_VHT_FLAGS_LEN");
5632  			return 0;
5633  		}
5634  	}
5635  
5636  	if (rx_status->he_flags) {
5637  		length = rtap_len;
5638  		/* IEEE80211_RADIOTAP_HE */
5639  		it_present_val |= (1 << IEEE80211_RADIOTAP_HE);
5640  		rtap_len = qdf_nbuf_update_radiotap_he_flags(rx_status,
5641  								rtap_buf,
5642  								rtap_len);
5643  
5644  		if ((rtap_len - length) > RADIOTAP_HE_FLAGS_LEN) {
5645  			qdf_print("length is greater than RADIOTAP_HE_FLAGS_LEN");
5646  			return 0;
5647  		}
5648  	}
5649  
5650  	if (rx_status->he_mu_flags) {
5651  		length = rtap_len;
5652  		/* IEEE80211_RADIOTAP_HE-MU */
5653  		it_present_val |= (1 << IEEE80211_RADIOTAP_HE_MU);
5654  		rtap_len = qdf_nbuf_update_radiotap_he_mu_flags(rx_status,
5655  								rtap_buf,
5656  								rtap_len);
5657  
5658  		if ((rtap_len - length) > RADIOTAP_HE_MU_FLAGS_LEN) {
5659  			qdf_print("length is greater than RADIOTAP_HE_MU_FLAGS_LEN");
5660  			return 0;
5661  		}
5662  	}
5663  
5664  	if (rx_status->he_mu_other_flags) {
5665  		length = rtap_len;
5666  		/* IEEE80211_RADIOTAP_HE-MU-OTHER */
5667  		it_present_val |= (1 << IEEE80211_RADIOTAP_HE_MU_OTHER);
5668  		rtap_len =
5669  			qdf_nbuf_update_radiotap_he_mu_other_flags(rx_status,
5670  								rtap_buf,
5671  								rtap_len);
5672  
5673  		if ((rtap_len - length) > RADIOTAP_HE_MU_OTHER_FLAGS_LEN) {
5674  			qdf_print("length is greater than RADIOTAP_HE_MU_OTHER_FLAGS_LEN");
5675  			return 0;
5676  		}
5677  	}
5678  
5679  	rtap_len = qdf_align(rtap_len, 2);
5680  	/*
5681  	 * Radiotap Vendor Namespace
5682  	 */
5683  	it_present_val |= (1 << IEEE80211_RADIOTAP_VENDOR_NAMESPACE);
5684  	radiotap_vendor_ns_ath = (struct qdf_radiotap_vendor_ns_ath *)
5685  					(rtap_buf + rtap_len);
5686  	/*
5687  	 * Copy Atheros OUI - 3 bytes (4th byte is 0)
5688  	 */
5689  	qdf_mem_copy(radiotap_vendor_ns_ath->hdr.oui, ATH_OUI, sizeof(ATH_OUI));
5690  	/*
5691  	 * Name space selector = 0
5692  	 * We only will have one namespace for now
5693  	 */
5694  	radiotap_vendor_ns_ath->hdr.selector = 0;
5695  	radiotap_vendor_ns_ath->hdr.skip_length = cpu_to_le16(
5696  					sizeof(*radiotap_vendor_ns_ath) -
5697  					sizeof(radiotap_vendor_ns_ath->hdr));
5698  	radiotap_vendor_ns_ath->device_id = cpu_to_le32(rx_status->device_id);
5699  	radiotap_vendor_ns_ath->lsig = cpu_to_le32(rx_status->l_sig_a_info);
5700  	radiotap_vendor_ns_ath->lsig_b = cpu_to_le32(rx_status->l_sig_b_info);
5701  	radiotap_vendor_ns_ath->ppdu_start_timestamp =
5702  				cpu_to_le32(rx_status->ppdu_timestamp);
5703  	rtap_len += sizeof(*radiotap_vendor_ns_ath);
5704  
5705  	/* Move to next it_present */
5706  	if (radiotap_ext1_hdr_present) {
5707  		it_present_val |= (1 << IEEE80211_RADIOTAP_EXT);
5708  		put_unaligned_le32(it_present_val, it_present);
5709  		it_present_val = 0;
5710  		it_present++;
5711  	}
5712  
5713  	/* Add Extension to Radiotap Header & corresponding data */
5714  	if (rx_status->add_rtap_ext) {
5715  		it_present_val |= (1 << IEEE80211_RADIOTAP_TX_STATUS);
5716  		it_present_val |= (1 << IEEE80211_RADIOTAP_RETRY_COUNT);
5717  
5718  		rtap_buf[rtap_len] = rx_status->tx_status;
5719  		rtap_len += 1;
5720  		rtap_buf[rtap_len] = rx_status->tx_retry_cnt;
5721  		rtap_len += 1;
5722  	}
5723  
5724  	/* Add Extension2 to Radiotap Header */
5725  	if (rx_status->add_rtap_ext2) {
5726  		it_present_val |= (1 << IEEE80211_RADIOTAP_EXTENSION2);
5727  
5728  		rtap_ext2 = (struct qdf_radiotap_ext2 *)(rtap_buf + rtap_len);
5729  		rtap_ext2->ppdu_id = rx_status->ppdu_id;
5730  		rtap_ext2->prev_ppdu_id = rx_status->prev_ppdu_id;
5731  		if (!rx_user_status) {
5732  			rtap_ext2->tid = rx_status->tid;
5733  			rtap_ext2->start_seq = rx_status->start_seq;
5734  			qdf_mem_copy(rtap_ext2->ba_bitmap,
5735  				     rx_status->ba_bitmap,
5736  				     8 * (sizeof(uint32_t)));
5737  		} else {
5738  			uint8_t ba_bitmap_sz = rx_user_status->ba_bitmap_sz;
5739  
5740  			/* set default bitmap sz if not set */
5741  			ba_bitmap_sz = ba_bitmap_sz ? ba_bitmap_sz : 8;
5742  			rtap_ext2->tid = rx_user_status->tid;
5743  			rtap_ext2->start_seq = rx_user_status->start_seq;
5744  			qdf_mem_copy(rtap_ext2->ba_bitmap,
5745  				     rx_user_status->ba_bitmap,
5746  				     ba_bitmap_sz * (sizeof(uint32_t)));
5747  		}
5748  
5749  		rtap_len += sizeof(*rtap_ext2);
5750  	}
5751  
5752  	if (rx_status->usig_flags) {
5753  		length = rtap_len;
5754  		/* IEEE80211_RADIOTAP_USIG */
5755  		it_present_val |= (1 << IEEE80211_RADIOTAP_EXT1_USIG);
5756  		rtap_len = qdf_nbuf_update_radiotap_usig_flags(rx_status,
5757  							       rtap_buf,
5758  							       rtap_len);
5759  
5760  		if ((rtap_len - length) > RADIOTAP_EHT_FLAGS_LEN) {
5761  			qdf_print("length is greater than RADIOTAP_EHT_FLAGS_LEN");
5762  			return 0;
5763  		}
5764  	}
5765  
5766  	if (rx_status->eht_flags) {
5767  		length = rtap_len;
5768  		/* IEEE80211_RADIOTAP_EHT */
5769  		it_present_val |= (1 << IEEE80211_RADIOTAP_EXT1_EHT);
5770  		rtap_len = qdf_nbuf_update_radiotap_eht_flags(rx_status,
5771  							      rtap_buf,
5772  							      rtap_len);
5773  
5774  		if ((rtap_len - length) > RADIOTAP_EHT_FLAGS_LEN) {
5775  			qdf_print("length is greater than RADIOTAP_EHT_FLAGS_LEN");
5776  			return 0;
5777  		}
5778  	}
5779  
5780  	put_unaligned_le32(it_present_val, it_present);
5781  	rthdr->it_len = cpu_to_le16(rtap_len);
5782  
5783  	if (headroom_sz < rtap_len) {
5784  		qdf_debug("DEBUG: Not enough space to update radiotap");
5785  		return 0;
5786  	}
5787  
5788  	qdf_nbuf_push_head(nbuf, rtap_len);
5789  	qdf_mem_copy(qdf_nbuf_data(nbuf), rtap_buf, rtap_len);
5790  	return rtap_len;
5791  }
5792  #else
qdf_nbuf_update_radiotap_vht_flags(struct mon_rx_status * rx_status,int8_t * rtap_buf,uint32_t rtap_len)5793  static unsigned int qdf_nbuf_update_radiotap_vht_flags(
5794  					struct mon_rx_status *rx_status,
5795  					int8_t *rtap_buf,
5796  					uint32_t rtap_len)
5797  {
5798  	qdf_err("ERROR: struct ieee80211_radiotap_header not supported");
5799  	return 0;
5800  }
5801  
qdf_nbuf_update_radiotap_he_flags(struct mon_rx_status * rx_status,int8_t * rtap_buf,uint32_t rtap_len)5802  unsigned int qdf_nbuf_update_radiotap_he_flags(struct mon_rx_status *rx_status,
5803  				      int8_t *rtap_buf, uint32_t rtap_len)
5804  {
5805  	qdf_err("ERROR: struct ieee80211_radiotap_header not supported");
5806  	return 0;
5807  }
5808  
qdf_nbuf_update_radiotap_ampdu_flags(struct mon_rx_status * rx_status,uint8_t * rtap_buf,uint32_t rtap_len)5809  static unsigned int qdf_nbuf_update_radiotap_ampdu_flags(
5810  					struct mon_rx_status *rx_status,
5811  					uint8_t *rtap_buf,
5812  					uint32_t rtap_len)
5813  {
5814  	qdf_err("ERROR: struct ieee80211_radiotap_header not supported");
5815  	return 0;
5816  }
5817  
qdf_nbuf_update_radiotap(struct mon_rx_status * rx_status,qdf_nbuf_t nbuf,uint32_t headroom_sz)5818  unsigned int qdf_nbuf_update_radiotap(struct mon_rx_status *rx_status,
5819  				      qdf_nbuf_t nbuf, uint32_t headroom_sz)
5820  {
5821  	qdf_err("ERROR: struct ieee80211_radiotap_header not supported");
5822  	return 0;
5823  }
5824  #endif
5825  qdf_export_symbol(qdf_nbuf_update_radiotap);
5826  
__qdf_nbuf_reg_free_cb(qdf_nbuf_free_t cb_func_ptr)5827  void __qdf_nbuf_reg_free_cb(qdf_nbuf_free_t cb_func_ptr)
5828  {
5829  	nbuf_free_cb = cb_func_ptr;
5830  }
5831  
5832  qdf_export_symbol(__qdf_nbuf_reg_free_cb);
5833  
qdf_nbuf_classify_pkt(struct sk_buff * skb)5834  void qdf_nbuf_classify_pkt(struct sk_buff *skb)
5835  {
5836  	struct ethhdr *eh = (struct ethhdr *)skb->data;
5837  
5838  	/* check destination mac address is broadcast/multicast */
5839  	if (is_broadcast_ether_addr((uint8_t *)eh))
5840  		QDF_NBUF_CB_SET_BCAST(skb);
5841  	else if (is_multicast_ether_addr((uint8_t *)eh))
5842  		QDF_NBUF_CB_SET_MCAST(skb);
5843  
5844  	if (qdf_nbuf_is_ipv4_arp_pkt(skb))
5845  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
5846  			QDF_NBUF_CB_PACKET_TYPE_ARP;
5847  	else if (qdf_nbuf_is_ipv4_dhcp_pkt(skb))
5848  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
5849  			QDF_NBUF_CB_PACKET_TYPE_DHCP;
5850  	else if (qdf_nbuf_is_ipv4_eapol_pkt(skb))
5851  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
5852  			QDF_NBUF_CB_PACKET_TYPE_EAPOL;
5853  	else if (qdf_nbuf_is_ipv4_wapi_pkt(skb))
5854  		QDF_NBUF_CB_GET_PACKET_TYPE(skb) =
5855  			QDF_NBUF_CB_PACKET_TYPE_WAPI;
5856  }
5857  qdf_export_symbol(qdf_nbuf_classify_pkt);
5858  
__qdf_nbuf_init(__qdf_nbuf_t nbuf)5859  void __qdf_nbuf_init(__qdf_nbuf_t nbuf)
5860  {
5861  	qdf_nbuf_users_set(&nbuf->users, 1);
5862  	nbuf->data = nbuf->head + NET_SKB_PAD;
5863  	skb_reset_tail_pointer(nbuf);
5864  }
5865  qdf_export_symbol(__qdf_nbuf_init);
5866  
5867  #ifdef WLAN_FEATURE_FASTPATH
qdf_nbuf_init_fast(qdf_nbuf_t nbuf)5868  void qdf_nbuf_init_fast(qdf_nbuf_t nbuf)
5869  {
5870  	qdf_nbuf_users_set(&nbuf->users, 1);
5871  	skb_reset_tail_pointer(nbuf);
5872  }
5873  qdf_export_symbol(qdf_nbuf_init_fast);
5874  #endif /* WLAN_FEATURE_FASTPATH */
5875  
5876  
5877  #ifdef QDF_NBUF_GLOBAL_COUNT
__qdf_nbuf_mod_init(void)5878  void __qdf_nbuf_mod_init(void)
5879  {
5880  	is_initial_mem_debug_disabled = qdf_mem_debug_config_get();
5881  	qdf_atomic_init(&nbuf_count);
5882  	qdf_debugfs_create_atomic(NBUF_DEBUGFS_NAME, S_IRUSR, NULL, &nbuf_count);
5883  }
5884  
__qdf_nbuf_mod_exit(void)5885  void __qdf_nbuf_mod_exit(void)
5886  {
5887  }
5888  #endif
5889  
5890  #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0))
__qdf_nbuf_move_frag_page_offset(__qdf_nbuf_t nbuf,uint8_t idx,int offset)5891  QDF_STATUS __qdf_nbuf_move_frag_page_offset(__qdf_nbuf_t nbuf, uint8_t idx,
5892  					    int offset)
5893  {
5894  	unsigned int frag_offset;
5895  	skb_frag_t *frag;
5896  
5897  	if (qdf_unlikely(idx >= __qdf_nbuf_get_nr_frags(nbuf)))
5898  		return QDF_STATUS_E_FAILURE;
5899  
5900  	frag = &skb_shinfo(nbuf)->frags[idx];
5901  	frag_offset = skb_frag_off(frag);
5902  
5903  	frag_offset += offset;
5904  	skb_frag_off_set(frag, frag_offset);
5905  
5906  	__qdf_nbuf_trim_add_frag_size(nbuf, idx, -(offset), 0);
5907  
5908  	return QDF_STATUS_SUCCESS;
5909  }
5910  
5911  #else
__qdf_nbuf_move_frag_page_offset(__qdf_nbuf_t nbuf,uint8_t idx,int offset)5912  QDF_STATUS __qdf_nbuf_move_frag_page_offset(__qdf_nbuf_t nbuf, uint8_t idx,
5913  					    int offset)
5914  {
5915  	uint16_t frag_offset;
5916  	skb_frag_t *frag;
5917  
5918  	if (qdf_unlikely(idx >= __qdf_nbuf_get_nr_frags(nbuf)))
5919  		return QDF_STATUS_E_FAILURE;
5920  
5921  	frag = &skb_shinfo(nbuf)->frags[idx];
5922  	frag_offset = frag->page_offset;
5923  
5924  	frag_offset += offset;
5925  	frag->page_offset = frag_offset;
5926  
5927  	__qdf_nbuf_trim_add_frag_size(nbuf, idx, -(offset), 0);
5928  
5929  	return QDF_STATUS_SUCCESS;
5930  }
5931  #endif
5932  
5933  qdf_export_symbol(__qdf_nbuf_move_frag_page_offset);
5934  
__qdf_nbuf_remove_frag(__qdf_nbuf_t nbuf,uint16_t idx,uint16_t truesize)5935  void __qdf_nbuf_remove_frag(__qdf_nbuf_t nbuf,
5936  			    uint16_t idx,
5937  			    uint16_t truesize)
5938  {
5939  	struct page *page;
5940  	uint16_t frag_len;
5941  
5942  	page = skb_frag_page(&skb_shinfo(nbuf)->frags[idx]);
5943  
5944  	if (qdf_unlikely(!page))
5945  		return;
5946  
5947  	frag_len = qdf_nbuf_get_frag_size_by_idx(nbuf, idx);
5948  	put_page(page);
5949  	nbuf->len -= frag_len;
5950  	nbuf->data_len -= frag_len;
5951  	nbuf->truesize -= truesize;
5952  	skb_shinfo(nbuf)->nr_frags--;
5953  }
5954  
5955  qdf_export_symbol(__qdf_nbuf_remove_frag);
5956  
__qdf_nbuf_add_rx_frag(__qdf_frag_t buf,__qdf_nbuf_t nbuf,int offset,int frag_len,unsigned int truesize,bool take_frag_ref)5957  void __qdf_nbuf_add_rx_frag(__qdf_frag_t buf, __qdf_nbuf_t nbuf,
5958  			    int offset, int frag_len,
5959  			    unsigned int truesize, bool take_frag_ref)
5960  {
5961  	struct page *page;
5962  	int frag_offset;
5963  	uint8_t nr_frag;
5964  
5965  	nr_frag = __qdf_nbuf_get_nr_frags(nbuf);
5966  	qdf_assert_always(nr_frag < QDF_NBUF_MAX_FRAGS);
5967  
5968  	page = virt_to_head_page(buf);
5969  	frag_offset = buf - page_address(page);
5970  
5971  	skb_add_rx_frag(nbuf, nr_frag, page,
5972  			(frag_offset + offset),
5973  			frag_len, truesize);
5974  
5975  	if (unlikely(take_frag_ref)) {
5976  		qdf_frag_count_inc(QDF_NBUF_FRAG_DEBUG_COUNT_ONE);
5977  		skb_frag_ref(nbuf, nr_frag);
5978  	}
5979  }
5980  
5981  qdf_export_symbol(__qdf_nbuf_add_rx_frag);
5982  
5983  #ifdef NBUF_FRAG_MEMORY_DEBUG
5984  
qdf_nbuf_move_frag_page_offset_debug(qdf_nbuf_t nbuf,uint8_t idx,int offset,const char * func,uint32_t line)5985  QDF_STATUS qdf_nbuf_move_frag_page_offset_debug(qdf_nbuf_t nbuf, uint8_t idx,
5986  						int offset, const char *func,
5987  						uint32_t line)
5988  {
5989  	QDF_STATUS result;
5990  	qdf_frag_t p_fragp, n_fragp;
5991  
5992  	p_fragp = qdf_nbuf_get_frag_addr(nbuf, idx);
5993  	result = __qdf_nbuf_move_frag_page_offset(nbuf, idx, offset);
5994  
5995  	if (qdf_likely(is_initial_mem_debug_disabled))
5996  		return result;
5997  
5998  	n_fragp = qdf_nbuf_get_frag_addr(nbuf, idx);
5999  
6000  	/*
6001  	 * Update frag address in frag debug tracker
6002  	 * when frag offset is successfully changed in skb
6003  	 */
6004  	if (result == QDF_STATUS_SUCCESS)
6005  		qdf_frag_debug_update_addr(p_fragp, n_fragp, func, line);
6006  
6007  	return result;
6008  }
6009  
6010  qdf_export_symbol(qdf_nbuf_move_frag_page_offset_debug);
6011  
qdf_nbuf_add_rx_frag_debug(qdf_frag_t buf,qdf_nbuf_t nbuf,int offset,int frag_len,unsigned int truesize,bool take_frag_ref,const char * func,uint32_t line)6012  void qdf_nbuf_add_rx_frag_debug(qdf_frag_t buf, qdf_nbuf_t nbuf,
6013  				int offset, int frag_len,
6014  				unsigned int truesize, bool take_frag_ref,
6015  				const char *func, uint32_t line)
6016  {
6017  	qdf_frag_t fragp;
6018  	uint32_t num_nr_frags;
6019  
6020  	__qdf_nbuf_add_rx_frag(buf, nbuf, offset,
6021  			       frag_len, truesize, take_frag_ref);
6022  
6023  	if (qdf_likely(is_initial_mem_debug_disabled))
6024  		return;
6025  
6026  	num_nr_frags = qdf_nbuf_get_nr_frags(nbuf);
6027  
6028  	qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
6029  
6030  	fragp = qdf_nbuf_get_frag_addr(nbuf, num_nr_frags - 1);
6031  
6032  	/* Update frag address in frag debug tracking table */
6033  	if (fragp != buf && !take_frag_ref)
6034  		qdf_frag_debug_update_addr(buf, fragp, func, line);
6035  
6036  	/* Update frag refcount in frag debug tracking table */
6037  	qdf_frag_debug_refcount_inc(fragp, func, line);
6038  }
6039  
6040  qdf_export_symbol(qdf_nbuf_add_rx_frag_debug);
6041  
qdf_net_buf_debug_acquire_frag(qdf_nbuf_t buf,const char * func,uint32_t line)6042  void qdf_net_buf_debug_acquire_frag(qdf_nbuf_t buf, const char *func,
6043  				    uint32_t line)
6044  {
6045  	uint32_t num_nr_frags;
6046  	uint32_t idx = 0;
6047  	qdf_nbuf_t ext_list;
6048  	qdf_frag_t p_frag;
6049  
6050  	if (qdf_likely(is_initial_mem_debug_disabled))
6051  		return;
6052  
6053  	if (qdf_unlikely(!buf))
6054  		return;
6055  
6056  	/* Take care to update the refcount in the debug entries for frags */
6057  	num_nr_frags = qdf_nbuf_get_nr_frags(buf);
6058  
6059  	qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
6060  
6061  	while (idx < num_nr_frags) {
6062  		p_frag = qdf_nbuf_get_frag_addr(buf, idx);
6063  		if (qdf_likely(p_frag))
6064  			qdf_frag_debug_refcount_inc(p_frag, func, line);
6065  		idx++;
6066  	}
6067  
6068  	/*
6069  	 * Take care to update the refcount in the debug entries for the
6070  	 * frags attached to frag_list
6071  	 */
6072  	ext_list = qdf_nbuf_get_ext_list(buf);
6073  	while (ext_list) {
6074  		idx = 0;
6075  		num_nr_frags = qdf_nbuf_get_nr_frags(ext_list);
6076  
6077  		qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
6078  
6079  		while (idx < num_nr_frags) {
6080  			p_frag = qdf_nbuf_get_frag_addr(ext_list, idx);
6081  			if (qdf_likely(p_frag))
6082  				qdf_frag_debug_refcount_inc(p_frag, func, line);
6083  			idx++;
6084  		}
6085  		ext_list = qdf_nbuf_queue_next(ext_list);
6086  	}
6087  }
6088  
6089  qdf_export_symbol(qdf_net_buf_debug_acquire_frag);
6090  
qdf_net_buf_debug_release_frag(qdf_nbuf_t buf,const char * func,uint32_t line)6091  void qdf_net_buf_debug_release_frag(qdf_nbuf_t buf, const char *func,
6092  				    uint32_t line)
6093  {
6094  	uint32_t num_nr_frags;
6095  	qdf_nbuf_t ext_list;
6096  	uint32_t idx = 0;
6097  	qdf_frag_t p_frag;
6098  
6099  	if (qdf_likely(is_initial_mem_debug_disabled))
6100  		return;
6101  
6102  	if (qdf_unlikely(!buf))
6103  		return;
6104  
6105  	/*
6106  	 * Decrement refcount for frag debug nodes only when last user
6107  	 * of nbuf calls this API so as to avoid decrementing refcount
6108  	 * on every call expect the last one in case where nbuf has multiple
6109  	 * users
6110  	 */
6111  	if (qdf_nbuf_get_users(buf) > 1)
6112  		return;
6113  
6114  	/* Take care to update the refcount in the debug entries for frags */
6115  	num_nr_frags = qdf_nbuf_get_nr_frags(buf);
6116  
6117  	qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
6118  
6119  	while (idx < num_nr_frags) {
6120  		p_frag = qdf_nbuf_get_frag_addr(buf, idx);
6121  		if (qdf_likely(p_frag))
6122  			qdf_frag_debug_refcount_dec(p_frag, func, line);
6123  		idx++;
6124  	}
6125  
6126  	/* Take care to update debug entries for frags attached to frag_list */
6127  	ext_list = qdf_nbuf_get_ext_list(buf);
6128  	while (ext_list) {
6129  		if (qdf_nbuf_get_users(ext_list) == 1) {
6130  			idx = 0;
6131  			num_nr_frags = qdf_nbuf_get_nr_frags(ext_list);
6132  			qdf_assert_always(num_nr_frags <= QDF_NBUF_MAX_FRAGS);
6133  			while (idx < num_nr_frags) {
6134  				p_frag = qdf_nbuf_get_frag_addr(ext_list, idx);
6135  				if (qdf_likely(p_frag))
6136  					qdf_frag_debug_refcount_dec(p_frag,
6137  								    func, line);
6138  				idx++;
6139  			}
6140  		}
6141  		ext_list = qdf_nbuf_queue_next(ext_list);
6142  	}
6143  }
6144  
6145  qdf_export_symbol(qdf_net_buf_debug_release_frag);
6146  
6147  QDF_STATUS
qdf_nbuf_remove_frag_debug(qdf_nbuf_t nbuf,uint16_t idx,uint16_t truesize,const char * func,uint32_t line)6148  qdf_nbuf_remove_frag_debug(qdf_nbuf_t nbuf,
6149  			   uint16_t idx,
6150  			   uint16_t truesize,
6151  			   const char *func,
6152  			   uint32_t line)
6153  {
6154  	uint16_t num_frags;
6155  	qdf_frag_t frag;
6156  
6157  	if (qdf_unlikely(!nbuf))
6158  		return QDF_STATUS_E_INVAL;
6159  
6160  	num_frags = qdf_nbuf_get_nr_frags(nbuf);
6161  	if (idx >= num_frags)
6162  		return QDF_STATUS_E_INVAL;
6163  
6164  	if (qdf_likely(is_initial_mem_debug_disabled)) {
6165  		__qdf_nbuf_remove_frag(nbuf, idx, truesize);
6166  		return QDF_STATUS_SUCCESS;
6167  	}
6168  
6169  	frag = qdf_nbuf_get_frag_addr(nbuf, idx);
6170  	if (qdf_likely(frag))
6171  		qdf_frag_debug_refcount_dec(frag, func, line);
6172  
6173  	__qdf_nbuf_remove_frag(nbuf, idx, truesize);
6174  
6175  	return QDF_STATUS_SUCCESS;
6176  }
6177  
6178  qdf_export_symbol(qdf_nbuf_remove_frag_debug);
6179  
6180  #endif /* NBUF_FRAG_MEMORY_DEBUG */
6181  
qdf_get_nbuf_valid_frag(qdf_nbuf_t nbuf)6182  qdf_nbuf_t qdf_get_nbuf_valid_frag(qdf_nbuf_t nbuf)
6183  {
6184  	qdf_nbuf_t last_nbuf;
6185  	uint32_t num_frags;
6186  
6187  	if (qdf_unlikely(!nbuf))
6188  		return NULL;
6189  
6190  	num_frags = qdf_nbuf_get_nr_frags(nbuf);
6191  
6192  	/* Check nbuf has enough memory to store frag memory */
6193  	if (num_frags < QDF_NBUF_MAX_FRAGS)
6194  		return nbuf;
6195  
6196  	if (!__qdf_nbuf_has_fraglist(nbuf))
6197  		return NULL;
6198  
6199  	last_nbuf = __qdf_nbuf_get_last_frag_list_nbuf(nbuf);
6200  	if (qdf_unlikely(!last_nbuf))
6201  		return NULL;
6202  
6203  	num_frags = qdf_nbuf_get_nr_frags(last_nbuf);
6204  	if (num_frags < QDF_NBUF_MAX_FRAGS)
6205  		return last_nbuf;
6206  
6207  	return NULL;
6208  }
6209  
6210  qdf_export_symbol(qdf_get_nbuf_valid_frag);
6211  
6212  QDF_STATUS
qdf_nbuf_add_frag_debug(qdf_device_t osdev,qdf_frag_t buf,qdf_nbuf_t nbuf,int offset,int frag_len,unsigned int truesize,bool take_frag_ref,unsigned int minsize,const char * func,uint32_t line)6213  qdf_nbuf_add_frag_debug(qdf_device_t osdev, qdf_frag_t buf,
6214  			qdf_nbuf_t nbuf, int offset,
6215  			int frag_len, unsigned int truesize,
6216  			bool take_frag_ref, unsigned int minsize,
6217  			const char *func, uint32_t line)
6218  {
6219  	qdf_nbuf_t cur_nbuf;
6220  	qdf_nbuf_t this_nbuf;
6221  
6222  	cur_nbuf = nbuf;
6223  	this_nbuf = nbuf;
6224  
6225  	if (qdf_unlikely(!frag_len || !buf)) {
6226  		qdf_nofl_err("%s : %d frag[ buf[%pK] len[%d]] not valid\n",
6227  			     func, line,
6228  			     buf, frag_len);
6229  		return QDF_STATUS_E_INVAL;
6230  	}
6231  
6232  	this_nbuf = qdf_get_nbuf_valid_frag(this_nbuf);
6233  
6234  	if (this_nbuf) {
6235  		cur_nbuf = this_nbuf;
6236  	} else {
6237  		/* allocate a dummy mpdu buffer of 64 bytes headroom */
6238  		this_nbuf = qdf_nbuf_alloc(osdev, minsize, minsize, 4, false);
6239  		if (qdf_unlikely(!this_nbuf)) {
6240  			qdf_nofl_err("%s : %d no memory to allocate\n",
6241  				     func, line);
6242  			return QDF_STATUS_E_NOMEM;
6243  		}
6244  	}
6245  
6246  	qdf_nbuf_add_rx_frag(buf, this_nbuf, offset, frag_len, truesize,
6247  			     take_frag_ref);
6248  
6249  	if (this_nbuf != cur_nbuf) {
6250  		/* add new skb to frag list */
6251  		qdf_nbuf_append_ext_list(nbuf, this_nbuf,
6252  					 qdf_nbuf_len(this_nbuf));
6253  	}
6254  
6255  	return QDF_STATUS_SUCCESS;
6256  }
6257  
6258  qdf_export_symbol(qdf_nbuf_add_frag_debug);
6259  
6260  #ifdef MEMORY_DEBUG
qdf_nbuf_acquire_track_lock(uint32_t index,unsigned long irq_flag)6261  void qdf_nbuf_acquire_track_lock(uint32_t index,
6262  				 unsigned long irq_flag)
6263  {
6264  	spin_lock_irqsave(&g_qdf_net_buf_track_lock[index],
6265  			  irq_flag);
6266  }
6267  
qdf_nbuf_release_track_lock(uint32_t index,unsigned long irq_flag)6268  void qdf_nbuf_release_track_lock(uint32_t index,
6269  				 unsigned long irq_flag)
6270  {
6271  	spin_unlock_irqrestore(&g_qdf_net_buf_track_lock[index],
6272  			       irq_flag);
6273  }
6274  
qdf_nbuf_get_track_tbl(uint32_t index)6275  QDF_NBUF_TRACK *qdf_nbuf_get_track_tbl(uint32_t index)
6276  {
6277  	return gp_qdf_net_buf_track_tbl[index];
6278  }
6279  #endif /* MEMORY_DEBUG */
6280  
6281  #ifdef ENHANCED_OS_ABSTRACTION
qdf_nbuf_set_timestamp(qdf_nbuf_t buf)6282  void qdf_nbuf_set_timestamp(qdf_nbuf_t buf)
6283  {
6284  	__qdf_nbuf_set_timestamp(buf);
6285  }
6286  
6287  qdf_export_symbol(qdf_nbuf_set_timestamp);
6288  
qdf_nbuf_get_timestamp(qdf_nbuf_t buf)6289  uint64_t qdf_nbuf_get_timestamp(qdf_nbuf_t buf)
6290  {
6291  	return __qdf_nbuf_get_timestamp(buf);
6292  }
6293  
6294  qdf_export_symbol(qdf_nbuf_get_timestamp);
6295  
qdf_nbuf_get_timestamp_us(qdf_nbuf_t buf)6296  uint64_t qdf_nbuf_get_timestamp_us(qdf_nbuf_t buf)
6297  {
6298  	return __qdf_nbuf_get_timestamp_us(buf);
6299  }
6300  
6301  qdf_export_symbol(qdf_nbuf_get_timestamp_us);
6302  
qdf_nbuf_get_timedelta_us(qdf_nbuf_t buf)6303  uint64_t qdf_nbuf_get_timedelta_us(qdf_nbuf_t buf)
6304  {
6305  	return __qdf_nbuf_get_timedelta_us(buf);
6306  }
6307  
6308  qdf_export_symbol(qdf_nbuf_get_timedelta_us);
6309  
qdf_nbuf_get_timedelta_ms(qdf_nbuf_t buf)6310  uint64_t qdf_nbuf_get_timedelta_ms(qdf_nbuf_t buf)
6311  {
6312  	return __qdf_nbuf_get_timedelta_ms(buf);
6313  }
6314  
6315  qdf_export_symbol(qdf_nbuf_get_timedelta_ms);
6316  
qdf_nbuf_net_timedelta(qdf_ktime_t t)6317  qdf_ktime_t qdf_nbuf_net_timedelta(qdf_ktime_t t)
6318  {
6319  	return __qdf_nbuf_net_timedelta(t);
6320  }
6321  
6322  qdf_export_symbol(qdf_nbuf_net_timedelta);
6323  #endif
6324