1  /*
2   * Copyright (c) 2016-2021 The Linux Foundation. All rights reserved.
3   * Copyright (c) 2021-2023 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  #ifndef DP_TX_DESC_H
21  #define DP_TX_DESC_H
22  
23  #include "dp_types.h"
24  #include "dp_tx.h"
25  #include "dp_internal.h"
26  
27  /*
28   * 21 bits cookie
29   * 1 bit special pool indicator
30   * 3 bits unused
31   * 2 bits pool id 0 ~ 3,
32   * 10 bits page id 0 ~ 1023
33   * 5 bits offset id 0 ~ 31 (Desc size = 128, Num descs per page = 4096/128 = 32)
34   */
35  /* ???Ring ID needed??? */
36  
37  /* TODO: Need to revisit this change for Rhine */
38  #ifdef WLAN_SOFTUMAC_SUPPORT
39  #define DP_TX_DESC_ID_SPCL_MASK    0x100000
40  #define DP_TX_DESC_ID_SPCL_OS      20
41  #define DP_TX_DESC_ID_POOL_MASK    0x018000
42  #define DP_TX_DESC_ID_POOL_OS      15
43  #define DP_TX_DESC_ID_PAGE_MASK    0x007FF0
44  #define DP_TX_DESC_ID_PAGE_OS      4
45  #define DP_TX_DESC_ID_OFFSET_MASK  0x00000F
46  #define DP_TX_DESC_ID_OFFSET_OS    0
47  #else
48  #define DP_TX_DESC_ID_SPCL_MASK    0x100000
49  #define DP_TX_DESC_ID_SPCL_OS      20
50  #define DP_TX_DESC_ID_POOL_MASK    0x018000
51  #define DP_TX_DESC_ID_POOL_OS      15
52  #define DP_TX_DESC_ID_PAGE_MASK    0x007FE0
53  #define DP_TX_DESC_ID_PAGE_OS      5
54  #define DP_TX_DESC_ID_OFFSET_MASK  0x00001F
55  #define DP_TX_DESC_ID_OFFSET_OS    0
56  #endif /* WLAN_SOFTUMAC_SUPPORT */
57  
58  /*
59   * Compilation assert on tx desc size
60   *
61   * if assert is hit please update POOL_MASK,
62   * PAGE_MASK according to updated size
63   *
64   * for current PAGE mask allowed size range of tx_desc
65   * is between 128 and 256
66   */
67  QDF_COMPILE_TIME_ASSERT(dp_tx_desc_size,
68  			((sizeof(struct dp_tx_desc_s)) <=
69  			 (DP_BLOCKMEM_SIZE >> DP_TX_DESC_ID_PAGE_OS)) &&
70  			((sizeof(struct dp_tx_desc_s)) >
71  			 (DP_BLOCKMEM_SIZE >> (DP_TX_DESC_ID_PAGE_OS + 1)))
72  		       );
73  
74  #ifdef QCA_LL_TX_FLOW_CONTROL_V2
75  #define TX_DESC_LOCK_CREATE(lock)
76  #define TX_DESC_LOCK_DESTROY(lock)
77  #define TX_DESC_LOCK_LOCK(lock)
78  #define TX_DESC_LOCK_UNLOCK(lock)
79  #define IS_TX_DESC_POOL_STATUS_INACTIVE(pool) \
80  	((pool)->status == FLOW_POOL_INACTIVE)
81  #ifdef QCA_AC_BASED_FLOW_CONTROL
82  #define TX_DESC_POOL_MEMBER_CLEAN(_tx_desc_pool)       \
83  	dp_tx_flow_pool_member_clean(_tx_desc_pool)
84  
85  #else /* !QCA_AC_BASED_FLOW_CONTROL */
86  #define TX_DESC_POOL_MEMBER_CLEAN(_tx_desc_pool)       \
87  do {                                                   \
88  	(_tx_desc_pool)->elem_size = 0;                \
89  	(_tx_desc_pool)->freelist = NULL;              \
90  	(_tx_desc_pool)->pool_size = 0;                \
91  	(_tx_desc_pool)->avail_desc = 0;               \
92  	(_tx_desc_pool)->start_th = 0;                 \
93  	(_tx_desc_pool)->stop_th = 0;                  \
94  	(_tx_desc_pool)->status = FLOW_POOL_INACTIVE;  \
95  } while (0)
96  #endif /* QCA_AC_BASED_FLOW_CONTROL */
97  #else /* !QCA_LL_TX_FLOW_CONTROL_V2 */
98  #define TX_DESC_LOCK_CREATE(lock)  qdf_spinlock_create(lock)
99  #define TX_DESC_LOCK_DESTROY(lock) qdf_spinlock_destroy(lock)
100  #define TX_DESC_LOCK_LOCK(lock)    qdf_spin_lock_bh(lock)
101  #define TX_DESC_LOCK_UNLOCK(lock)  qdf_spin_unlock_bh(lock)
102  #define IS_TX_DESC_POOL_STATUS_INACTIVE(pool) (false)
103  #define TX_DESC_POOL_MEMBER_CLEAN(_tx_desc_pool)       \
104  do {                                                   \
105  	(_tx_desc_pool)->elem_size = 0;                \
106  	(_tx_desc_pool)->num_allocated = 0;            \
107  	(_tx_desc_pool)->freelist = NULL;              \
108  	(_tx_desc_pool)->elem_count = 0;               \
109  	(_tx_desc_pool)->num_free = 0;                 \
110  } while (0)
111  #endif /* !QCA_LL_TX_FLOW_CONTROL_V2 */
112  #define MAX_POOL_BUFF_COUNT 10000
113  
114  #ifdef DP_TX_TRACKING
dp_tx_desc_set_magic(struct dp_tx_desc_s * tx_desc,uint32_t magic_pattern)115  static inline void dp_tx_desc_set_magic(struct dp_tx_desc_s *tx_desc,
116  					uint32_t magic_pattern)
117  {
118  	tx_desc->magic = magic_pattern;
119  }
120  #else
dp_tx_desc_set_magic(struct dp_tx_desc_s * tx_desc,uint32_t magic_pattern)121  static inline void dp_tx_desc_set_magic(struct dp_tx_desc_s *tx_desc,
122  					uint32_t magic_pattern)
123  {
124  }
125  #endif
126  
127  /**
128   * dp_tx_desc_pool_alloc() - Allocate Tx Descriptor pool(s)
129   * @soc: Handle to DP SoC structure
130   * @pool_id: pool to allocate
131   * @num_elem: Number of descriptor elements per pool
132   * @spcl_tx_desc: if special desc
133   *
134   * This function allocates memory for SW tx descriptors
135   * (used within host for tx data path).
136   * The number of tx descriptors required will be large
137   * since based on number of clients (1024 clients x 3 radios),
138   * outstanding MSDUs stored in TQM queues and LMAC queues will be significantly
139   * large.
140   *
141   * To avoid allocating a large contiguous memory, it uses multi_page_alloc qdf
142   * function to allocate memory
143   * in multiple pages. It then iterates through the memory allocated across pages
144   * and links each descriptor
145   * to next descriptor, taking care of page boundaries.
146   *
147   * Since WiFi 3.0 HW supports multiple Tx rings, multiple pools are allocated,
148   * one for each ring;
149   * This minimizes lock contention when hard_start_xmit is called
150   * from multiple CPUs.
151   * Alternately, multiple pools can be used for multiple VDEVs for VDEV level
152   * flow control.
153   *
154   * Return: Status code. 0 for success.
155   */
156  QDF_STATUS dp_tx_desc_pool_alloc(struct dp_soc *soc, uint8_t pool_id,
157  				 uint32_t num_elem, bool spcl_tx_desc);
158  
159  /**
160   * dp_tx_desc_pool_init() - Initialize Tx Descriptor pool(s)
161   * @soc: Handle to DP SoC structure
162   * @pool_id: pool to allocate
163   * @num_elem: Number of descriptor elements per pool
164   * @spcl_tx_desc: if special desc
165   *
166   * Return: QDF_STATUS_SUCCESS
167   *	   QDF_STATUS_E_FAULT
168   */
169  QDF_STATUS dp_tx_desc_pool_init(struct dp_soc *soc, uint8_t pool_id,
170  				uint32_t num_elem, bool spcl_tx_desc);
171  
172  /**
173   * dp_tx_desc_pool_free() -  Free the tx dexcriptor pools
174   * @soc: Handle to DP SoC structure
175   * @pool_id: pool to free
176   * @spcl_tx_desc: if special desc
177   *
178   */
179  void dp_tx_desc_pool_free(struct dp_soc *soc, uint8_t pool_id,
180  			  bool spcl_tx_desc);
181  
182  /**
183   * dp_tx_desc_pool_deinit() - de-initialize Tx Descriptor pool(s)
184   * @soc: Handle to DP SoC structure
185   * @pool_id: pool to de-initialize
186   * @spcl_tx_desc: if special desc
187   *
188   */
189  void dp_tx_desc_pool_deinit(struct dp_soc *soc, uint8_t pool_id,
190  			    bool spcl_tx_desc);
191  
192  /**
193   * dp_tx_ext_desc_pool_alloc_by_id() - allocate TX extension Descriptor pool
194   *                                     based on pool ID
195   * @soc: Handle to DP SoC structure
196   * @num_elem: Number of descriptor elements per pool
197   * @pool_id: Pool ID
198   *
199   * Return - QDF_STATUS_SUCCESS
200   *	    QDF_STATUS_E_NOMEM
201   */
202  QDF_STATUS dp_tx_ext_desc_pool_alloc_by_id(struct dp_soc *soc,
203  					   uint32_t num_elem,
204  					   uint8_t pool_id);
205  /**
206   * dp_tx_ext_desc_pool_alloc() - allocate Tx extension Descriptor pool(s)
207   * @soc: Handle to DP SoC structure
208   * @num_pool: Number of pools to allocate
209   * @num_elem: Number of descriptor elements per pool
210   *
211   * Return: QDF_STATUS_SUCCESS
212   *	   QDF_STATUS_E_NOMEM
213   */
214  QDF_STATUS dp_tx_ext_desc_pool_alloc(struct dp_soc *soc, uint8_t num_pool,
215  				     uint32_t num_elem);
216  
217  /**
218   * dp_tx_ext_desc_pool_init_by_id() - initialize Tx extension Descriptor pool
219   *                                    based on pool ID
220   * @soc: Handle to DP SoC structure
221   * @num_elem: Number of descriptor elements per pool
222   * @pool_id: Pool ID
223   *
224   * Return - QDF_STATUS_SUCCESS
225   *	    QDF_STATUS_E_FAULT
226   */
227  QDF_STATUS dp_tx_ext_desc_pool_init_by_id(struct dp_soc *soc, uint32_t num_elem,
228  					  uint8_t pool_id);
229  
230  /**
231   * dp_tx_ext_desc_pool_init() - initialize Tx extension Descriptor pool(s)
232   * @soc: Handle to DP SoC structure
233   * @num_pool: Number of pools to initialize
234   * @num_elem: Number of descriptor elements per pool
235   *
236   * Return: QDF_STATUS_SUCCESS
237   *	   QDF_STATUS_E_NOMEM
238   */
239  QDF_STATUS dp_tx_ext_desc_pool_init(struct dp_soc *soc, uint8_t num_pool,
240  				    uint32_t num_elem);
241  
242  /**
243   * dp_tx_ext_desc_pool_free_by_id() - free TX extension Descriptor pool
244   *                                    based on pool ID
245   * @soc: Handle to DP SoC structure
246   * @pool_id: Pool ID
247   *
248   */
249  void dp_tx_ext_desc_pool_free_by_id(struct dp_soc *soc, uint8_t pool_id);
250  
251  /**
252   * dp_tx_ext_desc_pool_free() -  free Tx extension Descriptor pool(s)
253   * @soc: Handle to DP SoC structure
254   * @num_pool: Number of pools to free
255   *
256   */
257  void dp_tx_ext_desc_pool_free(struct dp_soc *soc, uint8_t num_pool);
258  
259  /**
260   * dp_tx_ext_desc_pool_deinit_by_id() - deinit Tx extension Descriptor pool
261   *                                      based on pool ID
262   * @soc: Handle to DP SoC structure
263   * @pool_id: Pool ID
264   *
265   */
266  void dp_tx_ext_desc_pool_deinit_by_id(struct dp_soc *soc, uint8_t pool_id);
267  
268  /**
269   * dp_tx_ext_desc_pool_deinit() -  deinit Tx extension Descriptor pool(s)
270   * @soc: Handle to DP SoC structure
271   * @num_pool: Number of pools to de-initialize
272   *
273   */
274  void dp_tx_ext_desc_pool_deinit(struct dp_soc *soc, uint8_t num_pool);
275  
276  /**
277   * dp_tx_tso_desc_pool_alloc_by_id() - allocate TSO Descriptor pool based
278   *                                     on pool ID
279   * @soc: Handle to DP SoC structure
280   * @num_elem: Number of descriptor elements per pool
281   * @pool_id: Pool ID
282   *
283   * Return - QDF_STATUS_SUCCESS
284   *	    QDF_STATUS_E_NOMEM
285   */
286  QDF_STATUS dp_tx_tso_desc_pool_alloc_by_id(struct dp_soc *soc, uint32_t num_elem,
287  					   uint8_t pool_id);
288  
289  /**
290   * dp_tx_tso_desc_pool_alloc() - allocate TSO Descriptor pool(s)
291   * @soc: Handle to DP SoC structure
292   * @num_pool: Number of pools to allocate
293   * @num_elem: Number of descriptor elements per pool
294   *
295   * Return: QDF_STATUS_SUCCESS
296   *	   QDF_STATUS_E_NOMEM
297   */
298  QDF_STATUS dp_tx_tso_desc_pool_alloc(struct dp_soc *soc, uint8_t num_pool,
299  				     uint32_t num_elem);
300  
301  /**
302   * dp_tx_tso_desc_pool_init_by_id() - initialize TSO Descriptor pool
303   *                                    based on pool ID
304   * @soc: Handle to DP SoC structure
305   * @num_elem: Number of descriptor elements per pool
306   * @pool_id: Pool ID
307   *
308   * Return - QDF_STATUS_SUCCESS
309   *	    QDF_STATUS_E_NOMEM
310   */
311  QDF_STATUS dp_tx_tso_desc_pool_init_by_id(struct dp_soc *soc, uint32_t num_elem,
312  					  uint8_t pool_id);
313  
314  /**
315   * dp_tx_tso_desc_pool_init() - initialize TSO Descriptor pool(s)
316   * @soc: Handle to DP SoC structure
317   * @num_pool: Number of pools to initialize
318   * @num_elem: Number of descriptor elements per pool
319   *
320   * Return: QDF_STATUS_SUCCESS
321   *	   QDF_STATUS_E_NOMEM
322   */
323  QDF_STATUS dp_tx_tso_desc_pool_init(struct dp_soc *soc, uint8_t num_pool,
324  				    uint32_t num_elem);
325  
326  /**
327   * dp_tx_tso_desc_pool_free_by_id() - free TSO Descriptor pool based on pool ID
328   * @soc: Handle to DP SoC structure
329   * @pool_id: Pool ID
330   */
331  void dp_tx_tso_desc_pool_free_by_id(struct dp_soc *soc, uint8_t pool_id);
332  
333  /**
334   * dp_tx_tso_desc_pool_free() - free TSO Descriptor pool(s)
335   * @soc: Handle to DP SoC structure
336   * @num_pool: Number of pools to free
337   *
338   */
339  void dp_tx_tso_desc_pool_free(struct dp_soc *soc, uint8_t num_pool);
340  
341  /**
342   * dp_tx_tso_desc_pool_deinit_by_id() - deinitialize TSO Descriptor pool
343   *                                      based on pool ID
344   * @soc: Handle to DP SoC structure
345   * @pool_id: Pool ID
346   */
347  void dp_tx_tso_desc_pool_deinit_by_id(struct dp_soc *soc, uint8_t pool_id);
348  
349  /**
350   * dp_tx_tso_desc_pool_deinit() - deinitialize TSO Descriptor pool(s)
351   * @soc: Handle to DP SoC structure
352   * @num_pool: Number of pools to free
353   *
354   */
355  void dp_tx_tso_desc_pool_deinit(struct dp_soc *soc, uint8_t num_pool);
356  
357  /**
358   * dp_tx_tso_num_seg_pool_alloc_by_id() - Allocate descriptors that tracks the
359   *                             fragments in each tso segment based on pool ID
360   * @soc: handle to dp soc structure
361   * @num_elem: total number of descriptors to be allocated
362   * @pool_id: Pool ID
363   *
364   * Return - QDF_STATUS_SUCCESS
365   *	    QDF_STATUS_E_NOMEM
366   */
367  QDF_STATUS dp_tx_tso_num_seg_pool_alloc_by_id(struct dp_soc *soc,
368  					      uint32_t num_elem,
369  					      uint8_t pool_id);
370  
371  /**
372   * dp_tx_tso_num_seg_pool_alloc() - Allocate descriptors that tracks the
373   *                              fragments in each tso segment
374   *
375   * @soc: handle to dp soc structure
376   * @num_pool: number of pools to allocate
377   * @num_elem: total number of descriptors to be allocated
378   *
379   * Return: QDF_STATUS_SUCCESS
380   *	   QDF_STATUS_E_NOMEM
381   */
382  QDF_STATUS dp_tx_tso_num_seg_pool_alloc(struct dp_soc *soc, uint8_t num_pool,
383  					uint32_t num_elem);
384  
385  /**
386   * dp_tx_tso_num_seg_pool_init_by_id() - Initialize descriptors that tracks the
387   *                              fragments in each tso segment based on pool ID
388   *
389   * @soc: handle to dp soc structure
390   * @num_elem: total number of descriptors to be initialized
391   * @pool_id: Pool ID
392   *
393   * Return - QDF_STATUS_SUCCESS
394   *	    QDF_STATUS_E_FAULT
395   */
396  QDF_STATUS dp_tx_tso_num_seg_pool_init_by_id(struct dp_soc *soc,
397  					     uint32_t num_elem,
398  					     uint8_t pool_id);
399  
400  /**
401   * dp_tx_tso_num_seg_pool_init() - Initialize descriptors that tracks the
402   *                              fragments in each tso segment
403   *
404   * @soc: handle to dp soc structure
405   * @num_pool: number of pools to initialize
406   * @num_elem: total number of descriptors to be initialized
407   *
408   * Return: QDF_STATUS_SUCCESS
409   *	   QDF_STATUS_E_FAULT
410   */
411  QDF_STATUS dp_tx_tso_num_seg_pool_init(struct dp_soc *soc, uint8_t num_pool,
412  				       uint32_t num_elem);
413  
414  /**
415   * dp_tx_tso_num_seg_pool_free_by_id() - free descriptors that tracks the
416   *                              fragments in each tso segment based on pool ID
417   *
418   * @soc: handle to dp soc structure
419   * @pool_id: Pool ID
420   */
421  void dp_tx_tso_num_seg_pool_free_by_id(struct dp_soc *soc, uint8_t pool_id);
422  
423  /**
424   * dp_tx_tso_num_seg_pool_free() - free descriptors that tracks the
425   *                              fragments in each tso segment
426   *
427   * @soc: handle to dp soc structure
428   * @num_pool: number of pools to free
429   */
430  void dp_tx_tso_num_seg_pool_free(struct dp_soc *soc, uint8_t num_pool);
431  
432  /**
433   * dp_tx_tso_num_seg_pool_deinit_by_id() - de-initialize descriptors that tracks
434   *                           the fragments in each tso segment based on pool ID
435   * @soc: handle to dp soc structure
436   * @pool_id: Pool ID
437   */
438  void dp_tx_tso_num_seg_pool_deinit_by_id(struct dp_soc *soc, uint8_t pool_id);
439  
440  /**
441   * dp_tx_tso_num_seg_pool_deinit() - de-initialize descriptors that tracks the
442   *                              fragments in each tso segment
443   *
444   * @soc: handle to dp soc structure
445   * @num_pool: number of pools to de-initialize
446   *
447   * Return: QDF_STATUS_SUCCESS
448   *	   QDF_STATUS_E_FAULT
449   */
450  void dp_tx_tso_num_seg_pool_deinit(struct dp_soc *soc, uint8_t num_pool);
451  
452  #ifdef DP_UMAC_HW_RESET_SUPPORT
453  /**
454   * dp_tx_desc_pool_cleanup() -  Clean up the tx dexcriptor pools
455   * @soc: Handle to DP SoC structure
456   * @nbuf_list: nbuf list for delayed free
457   * @cleanup: cleanup the pool
458   *
459   */
460  void dp_tx_desc_pool_cleanup(struct dp_soc *soc, qdf_nbuf_t *nbuf_list,
461  			     bool cleanup);
462  #endif
463  
464  /**
465   * dp_tx_desc_clear() - Clear contents of tx desc
466   * @tx_desc: descriptor to free
467   *
468   * Return: none
469   */
470  static inline void
dp_tx_desc_clear(struct dp_tx_desc_s * tx_desc)471  dp_tx_desc_clear(struct dp_tx_desc_s *tx_desc)
472  {
473  	tx_desc->vdev_id = DP_INVALID_VDEV_ID;
474  	tx_desc->nbuf = NULL;
475  	tx_desc->flags = 0;
476  	tx_desc->next = NULL;
477  }
478  
479  #ifdef QCA_LL_TX_FLOW_CONTROL_V2
480  void dp_tx_flow_control_init(struct dp_soc *);
481  void dp_tx_flow_control_deinit(struct dp_soc *);
482  
483  QDF_STATUS dp_txrx_register_pause_cb(struct cdp_soc_t *soc,
484  	tx_pause_callback pause_cb);
485  QDF_STATUS dp_tx_flow_pool_map(struct cdp_soc_t *soc, uint8_t pdev_id,
486  			       uint8_t vdev_id);
487  void dp_tx_flow_pool_unmap(struct cdp_soc_t *handle, uint8_t pdev_id,
488  			   uint8_t vdev_id);
489  void dp_tx_clear_flow_pool_stats(struct dp_soc *soc);
490  struct dp_tx_desc_pool_s *dp_tx_create_flow_pool(struct dp_soc *soc,
491  	uint8_t flow_pool_id, uint32_t flow_pool_size);
492  
493  QDF_STATUS dp_tx_flow_pool_map_handler(struct dp_pdev *pdev, uint8_t flow_id,
494  	uint8_t flow_type, uint8_t flow_pool_id, uint32_t flow_pool_size);
495  void dp_tx_flow_pool_unmap_handler(struct dp_pdev *pdev, uint8_t flow_id,
496  	uint8_t flow_type, uint8_t flow_pool_id);
497  
498  /**
499   * dp_tx_get_desc_flow_pool() - get descriptor from flow pool
500   * @pool: flow pool
501   *
502   * Caller needs to take lock and do sanity checks.
503   *
504   * Return: tx descriptor
505   */
506  static inline
dp_tx_get_desc_flow_pool(struct dp_tx_desc_pool_s * pool)507  struct dp_tx_desc_s *dp_tx_get_desc_flow_pool(struct dp_tx_desc_pool_s *pool)
508  {
509  	struct dp_tx_desc_s *tx_desc = pool->freelist;
510  
511  	pool->freelist = pool->freelist->next;
512  	pool->avail_desc--;
513  	return tx_desc;
514  }
515  
516  /**
517   * dp_tx_put_desc_flow_pool() - put descriptor to flow pool freelist
518   * @pool: flow pool
519   * @tx_desc: tx descriptor
520   *
521   * Caller needs to take lock and do sanity checks.
522   *
523   * Return: none
524   */
525  static inline
dp_tx_put_desc_flow_pool(struct dp_tx_desc_pool_s * pool,struct dp_tx_desc_s * tx_desc)526  void dp_tx_put_desc_flow_pool(struct dp_tx_desc_pool_s *pool,
527  			struct dp_tx_desc_s *tx_desc)
528  {
529  	tx_desc->next = pool->freelist;
530  	pool->freelist = tx_desc;
531  	pool->avail_desc++;
532  }
533  
534  static inline void
dp_tx_desc_free_list(struct dp_tx_desc_pool_s * pool,struct dp_tx_desc_s * head_desc,struct dp_tx_desc_s * tail_desc,uint32_t fast_desc_count)535  dp_tx_desc_free_list(struct dp_tx_desc_pool_s *pool,
536  		     struct dp_tx_desc_s *head_desc,
537  		     struct dp_tx_desc_s *tail_desc,
538  		     uint32_t fast_desc_count)
539  {
540  }
541  
542  #ifdef QCA_AC_BASED_FLOW_CONTROL
543  
544  /**
545   * dp_tx_flow_pool_member_clean() - Clean the members of TX flow pool
546   * @pool: flow pool
547   *
548   * Return: None
549   */
550  static inline void
dp_tx_flow_pool_member_clean(struct dp_tx_desc_pool_s * pool)551  dp_tx_flow_pool_member_clean(struct dp_tx_desc_pool_s *pool)
552  {
553  	pool->elem_size = 0;
554  	pool->freelist = NULL;
555  	pool->pool_size = 0;
556  	pool->avail_desc = 0;
557  	qdf_mem_zero(pool->start_th, FL_TH_MAX);
558  	qdf_mem_zero(pool->stop_th, FL_TH_MAX);
559  	pool->status = FLOW_POOL_INACTIVE;
560  }
561  
562  /**
563   * dp_tx_is_threshold_reached() - Check if current avail desc meet threshold
564   * @pool: flow pool
565   * @avail_desc: available descriptor number
566   *
567   * Return: true if threshold is met, false if not
568   */
569  static inline bool
dp_tx_is_threshold_reached(struct dp_tx_desc_pool_s * pool,uint16_t avail_desc)570  dp_tx_is_threshold_reached(struct dp_tx_desc_pool_s *pool, uint16_t avail_desc)
571  {
572  	if (qdf_unlikely(avail_desc == pool->stop_th[DP_TH_BE_BK]))
573  		return true;
574  	else if (qdf_unlikely(avail_desc == pool->stop_th[DP_TH_VI]))
575  		return true;
576  	else if (qdf_unlikely(avail_desc == pool->stop_th[DP_TH_VO]))
577  		return true;
578  	else if (qdf_unlikely(avail_desc == pool->stop_th[DP_TH_HI]))
579  		return true;
580  	else
581  		return false;
582  }
583  
584  /**
585   * dp_tx_adjust_flow_pool_state() - Adjust flow pool state
586   * @soc: dp soc
587   * @pool: flow pool
588   */
589  static inline void
dp_tx_adjust_flow_pool_state(struct dp_soc * soc,struct dp_tx_desc_pool_s * pool)590  dp_tx_adjust_flow_pool_state(struct dp_soc *soc,
591  			     struct dp_tx_desc_pool_s *pool)
592  {
593  	if (pool->avail_desc > pool->stop_th[DP_TH_BE_BK]) {
594  		pool->status = FLOW_POOL_ACTIVE_UNPAUSED;
595  		return;
596  	} else if (pool->avail_desc <= pool->stop_th[DP_TH_BE_BK] &&
597  		   pool->avail_desc > pool->stop_th[DP_TH_VI]) {
598  		pool->status = FLOW_POOL_BE_BK_PAUSED;
599  	} else if (pool->avail_desc <= pool->stop_th[DP_TH_VI] &&
600  		   pool->avail_desc > pool->stop_th[DP_TH_VO]) {
601  		pool->status = FLOW_POOL_VI_PAUSED;
602  	} else if (pool->avail_desc <= pool->stop_th[DP_TH_VO] &&
603  		   pool->avail_desc > pool->stop_th[DP_TH_HI]) {
604  		pool->status = FLOW_POOL_VO_PAUSED;
605  	} else if (pool->avail_desc <= pool->stop_th[DP_TH_HI]) {
606  		pool->status = FLOW_POOL_ACTIVE_PAUSED;
607  	}
608  
609  	switch (pool->status) {
610  	case FLOW_POOL_ACTIVE_PAUSED:
611  		soc->pause_cb(pool->flow_pool_id,
612  			      WLAN_NETIF_PRIORITY_QUEUE_OFF,
613  			      WLAN_DATA_FLOW_CTRL_PRI);
614  		fallthrough;
615  
616  	case FLOW_POOL_VO_PAUSED:
617  		soc->pause_cb(pool->flow_pool_id,
618  			      WLAN_NETIF_VO_QUEUE_OFF,
619  			      WLAN_DATA_FLOW_CTRL_VO);
620  		fallthrough;
621  
622  	case FLOW_POOL_VI_PAUSED:
623  		soc->pause_cb(pool->flow_pool_id,
624  			      WLAN_NETIF_VI_QUEUE_OFF,
625  			      WLAN_DATA_FLOW_CTRL_VI);
626  		fallthrough;
627  
628  	case FLOW_POOL_BE_BK_PAUSED:
629  		soc->pause_cb(pool->flow_pool_id,
630  			      WLAN_NETIF_BE_BK_QUEUE_OFF,
631  			      WLAN_DATA_FLOW_CTRL_BE_BK);
632  		break;
633  	default:
634  		dp_err("Invalid pool status:%u to adjust", pool->status);
635  	}
636  }
637  
638  /**
639   * dp_tx_desc_alloc() - Allocate a Software Tx descriptor from given pool
640   * @soc: Handle to DP SoC structure
641   * @desc_pool_id: ID of the flow control fool
642   *
643   * Return: TX descriptor allocated or NULL
644   */
645  static inline struct dp_tx_desc_s *
dp_tx_desc_alloc(struct dp_soc * soc,uint8_t desc_pool_id)646  dp_tx_desc_alloc(struct dp_soc *soc, uint8_t desc_pool_id)
647  {
648  	struct dp_tx_desc_s *tx_desc = NULL;
649  	struct dp_tx_desc_pool_s *pool = &soc->tx_desc[desc_pool_id];
650  	bool is_pause = false;
651  	enum netif_action_type act = WLAN_NETIF_ACTION_TYPE_NONE;
652  	enum dp_fl_ctrl_threshold level = DP_TH_BE_BK;
653  	enum netif_reason_type reason;
654  
655  	if (qdf_likely(pool)) {
656  		qdf_spin_lock_bh(&pool->flow_pool_lock);
657  		if (qdf_likely(pool->avail_desc &&
658  		    pool->status != FLOW_POOL_INVALID &&
659  		    pool->status != FLOW_POOL_INACTIVE)) {
660  			tx_desc = dp_tx_get_desc_flow_pool(pool);
661  			tx_desc->pool_id = desc_pool_id;
662  			tx_desc->flags = DP_TX_DESC_FLAG_ALLOCATED;
663  			dp_tx_desc_set_magic(tx_desc,
664  					     DP_TX_MAGIC_PATTERN_INUSE);
665  			is_pause = dp_tx_is_threshold_reached(pool,
666  							      pool->avail_desc);
667  
668  			if (qdf_unlikely(pool->status ==
669  					 FLOW_POOL_ACTIVE_UNPAUSED_REATTACH)) {
670  				dp_tx_adjust_flow_pool_state(soc, pool);
671  				is_pause = false;
672  			}
673  
674  			if (qdf_unlikely(is_pause)) {
675  				switch (pool->status) {
676  				case FLOW_POOL_ACTIVE_UNPAUSED:
677  					/* pause network BE\BK queue */
678  					act = WLAN_NETIF_BE_BK_QUEUE_OFF;
679  					reason = WLAN_DATA_FLOW_CTRL_BE_BK;
680  					level = DP_TH_BE_BK;
681  					pool->status = FLOW_POOL_BE_BK_PAUSED;
682  					break;
683  				case FLOW_POOL_BE_BK_PAUSED:
684  					/* pause network VI queue */
685  					act = WLAN_NETIF_VI_QUEUE_OFF;
686  					reason = WLAN_DATA_FLOW_CTRL_VI;
687  					level = DP_TH_VI;
688  					pool->status = FLOW_POOL_VI_PAUSED;
689  					break;
690  				case FLOW_POOL_VI_PAUSED:
691  					/* pause network VO queue */
692  					act = WLAN_NETIF_VO_QUEUE_OFF;
693  					reason = WLAN_DATA_FLOW_CTRL_VO;
694  					level = DP_TH_VO;
695  					pool->status = FLOW_POOL_VO_PAUSED;
696  					break;
697  				case FLOW_POOL_VO_PAUSED:
698  					/* pause network HI PRI queue */
699  					act = WLAN_NETIF_PRIORITY_QUEUE_OFF;
700  					reason = WLAN_DATA_FLOW_CTRL_PRI;
701  					level = DP_TH_HI;
702  					pool->status = FLOW_POOL_ACTIVE_PAUSED;
703  					break;
704  				case FLOW_POOL_ACTIVE_PAUSED:
705  					act = WLAN_NETIF_ACTION_TYPE_NONE;
706  					break;
707  				default:
708  					dp_err_rl("pool status is %d!",
709  						  pool->status);
710  					break;
711  				}
712  
713  				if (act != WLAN_NETIF_ACTION_TYPE_NONE) {
714  					pool->latest_pause_time[level] =
715  						qdf_get_system_timestamp();
716  					soc->pause_cb(desc_pool_id,
717  						      act,
718  						      reason);
719  				}
720  			}
721  		} else {
722  			pool->pkt_drop_no_desc++;
723  		}
724  		qdf_spin_unlock_bh(&pool->flow_pool_lock);
725  	} else {
726  		dp_err_rl("NULL desc pool pool_id %d", desc_pool_id);
727  		soc->pool_stats.pkt_drop_no_pool++;
728  	}
729  
730  	return tx_desc;
731  }
732  
733  /**
734   * dp_tx_desc_free() - Free a tx descriptor and attach it to free list
735   * @soc: Handle to DP SoC structure
736   * @tx_desc: the tx descriptor to be freed
737   * @desc_pool_id: ID of the flow control pool
738   *
739   * Return: None
740   */
741  static inline void
dp_tx_desc_free(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc,uint8_t desc_pool_id)742  dp_tx_desc_free(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc,
743  		uint8_t desc_pool_id)
744  {
745  	struct dp_tx_desc_pool_s *pool = &soc->tx_desc[desc_pool_id];
746  	qdf_time_t unpause_time = qdf_get_system_timestamp(), pause_dur;
747  	enum netif_action_type act = WLAN_WAKE_ALL_NETIF_QUEUE;
748  	enum netif_reason_type reason;
749  
750  	qdf_spin_lock_bh(&pool->flow_pool_lock);
751  	tx_desc->vdev_id = DP_INVALID_VDEV_ID;
752  	tx_desc->nbuf = NULL;
753  	tx_desc->flags = 0;
754  	dp_tx_desc_set_magic(tx_desc, DP_TX_MAGIC_PATTERN_FREE);
755  	dp_tx_put_desc_flow_pool(pool, tx_desc);
756  	switch (pool->status) {
757  	case FLOW_POOL_ACTIVE_PAUSED:
758  		if (pool->avail_desc > pool->start_th[DP_TH_HI]) {
759  			act = WLAN_NETIF_PRIORITY_QUEUE_ON;
760  			reason = WLAN_DATA_FLOW_CTRL_PRI;
761  			pool->status = FLOW_POOL_VO_PAUSED;
762  
763  			/* Update maximum pause duration for HI queue */
764  			pause_dur = unpause_time -
765  					pool->latest_pause_time[DP_TH_HI];
766  			if (pool->max_pause_time[DP_TH_HI] < pause_dur)
767  				pool->max_pause_time[DP_TH_HI] = pause_dur;
768  		}
769  		break;
770  	case FLOW_POOL_VO_PAUSED:
771  		if (pool->avail_desc > pool->start_th[DP_TH_VO]) {
772  			act = WLAN_NETIF_VO_QUEUE_ON;
773  			reason = WLAN_DATA_FLOW_CTRL_VO;
774  			pool->status = FLOW_POOL_VI_PAUSED;
775  
776  			/* Update maximum pause duration for VO queue */
777  			pause_dur = unpause_time -
778  					pool->latest_pause_time[DP_TH_VO];
779  			if (pool->max_pause_time[DP_TH_VO] < pause_dur)
780  				pool->max_pause_time[DP_TH_VO] = pause_dur;
781  		}
782  		break;
783  	case FLOW_POOL_VI_PAUSED:
784  		if (pool->avail_desc > pool->start_th[DP_TH_VI]) {
785  			act = WLAN_NETIF_VI_QUEUE_ON;
786  			reason = WLAN_DATA_FLOW_CTRL_VI;
787  			pool->status = FLOW_POOL_BE_BK_PAUSED;
788  
789  			/* Update maximum pause duration for VI queue */
790  			pause_dur = unpause_time -
791  					pool->latest_pause_time[DP_TH_VI];
792  			if (pool->max_pause_time[DP_TH_VI] < pause_dur)
793  				pool->max_pause_time[DP_TH_VI] = pause_dur;
794  		}
795  		break;
796  	case FLOW_POOL_BE_BK_PAUSED:
797  		if (pool->avail_desc > pool->start_th[DP_TH_BE_BK]) {
798  			act = WLAN_NETIF_BE_BK_QUEUE_ON;
799  			reason = WLAN_DATA_FLOW_CTRL_BE_BK;
800  			pool->status = FLOW_POOL_ACTIVE_UNPAUSED;
801  
802  			/* Update maximum pause duration for BE_BK queue */
803  			pause_dur = unpause_time -
804  					pool->latest_pause_time[DP_TH_BE_BK];
805  			if (pool->max_pause_time[DP_TH_BE_BK] < pause_dur)
806  				pool->max_pause_time[DP_TH_BE_BK] = pause_dur;
807  		}
808  		break;
809  	case FLOW_POOL_INVALID:
810  		if (pool->avail_desc == pool->pool_size) {
811  			dp_tx_desc_pool_deinit(soc, desc_pool_id, false);
812  			dp_tx_desc_pool_free(soc, desc_pool_id, false);
813  			qdf_spin_unlock_bh(&pool->flow_pool_lock);
814  			dp_err_rl("pool %d is freed!!", desc_pool_id);
815  			return;
816  		}
817  		break;
818  
819  	case FLOW_POOL_ACTIVE_UNPAUSED:
820  		break;
821  
822  	case FLOW_POOL_ACTIVE_UNPAUSED_REATTACH:
823  		fallthrough;
824  	default:
825  		dp_err_rl("pool %d status: %d",
826  			  desc_pool_id, pool->status);
827  		break;
828  	};
829  
830  	if (act != WLAN_WAKE_ALL_NETIF_QUEUE)
831  		soc->pause_cb(pool->flow_pool_id,
832  			      act, reason);
833  	qdf_spin_unlock_bh(&pool->flow_pool_lock);
834  }
835  
836  static inline void
dp_tx_spcl_desc_free(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc,uint8_t desc_pool_id)837  dp_tx_spcl_desc_free(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc,
838  		     uint8_t desc_pool_id)
839  {
840  }
841  
dp_tx_spcl_desc_alloc(struct dp_soc * soc,uint8_t desc_pool_id)842  static inline struct dp_tx_desc_s *dp_tx_spcl_desc_alloc(struct dp_soc *soc,
843  							 uint8_t desc_pool_id)
844  {
845  	return NULL;
846  }
847  #else /* QCA_AC_BASED_FLOW_CONTROL */
848  
849  static inline bool
dp_tx_is_threshold_reached(struct dp_tx_desc_pool_s * pool,uint16_t avail_desc)850  dp_tx_is_threshold_reached(struct dp_tx_desc_pool_s *pool, uint16_t avail_desc)
851  {
852  	if (qdf_unlikely(avail_desc < pool->stop_th))
853  		return true;
854  	else
855  		return false;
856  }
857  
858  /**
859   * dp_tx_desc_alloc() - Allocate a Software Tx Descriptor from given pool
860   * @soc: Handle to DP SoC structure
861   * @desc_pool_id:
862   *
863   * Return: Tx descriptor or NULL
864   */
865  static inline struct dp_tx_desc_s *
dp_tx_desc_alloc(struct dp_soc * soc,uint8_t desc_pool_id)866  dp_tx_desc_alloc(struct dp_soc *soc, uint8_t desc_pool_id)
867  {
868  	struct dp_tx_desc_s *tx_desc = NULL;
869  	struct dp_tx_desc_pool_s *pool = &soc->tx_desc[desc_pool_id];
870  
871  	if (pool) {
872  		qdf_spin_lock_bh(&pool->flow_pool_lock);
873  		if (pool->status <= FLOW_POOL_ACTIVE_PAUSED &&
874  		    pool->avail_desc) {
875  			tx_desc = dp_tx_get_desc_flow_pool(pool);
876  			tx_desc->pool_id = desc_pool_id;
877  			tx_desc->flags = DP_TX_DESC_FLAG_ALLOCATED;
878  			dp_tx_desc_set_magic(tx_desc,
879  					     DP_TX_MAGIC_PATTERN_INUSE);
880  			if (qdf_unlikely(pool->avail_desc < pool->stop_th)) {
881  				pool->status = FLOW_POOL_ACTIVE_PAUSED;
882  				qdf_spin_unlock_bh(&pool->flow_pool_lock);
883  				/* pause network queues */
884  				soc->pause_cb(desc_pool_id,
885  					       WLAN_STOP_ALL_NETIF_QUEUE,
886  					       WLAN_DATA_FLOW_CONTROL);
887  			} else {
888  				qdf_spin_unlock_bh(&pool->flow_pool_lock);
889  			}
890  		} else {
891  			pool->pkt_drop_no_desc++;
892  			qdf_spin_unlock_bh(&pool->flow_pool_lock);
893  		}
894  	} else {
895  		soc->pool_stats.pkt_drop_no_pool++;
896  	}
897  
898  	return tx_desc;
899  }
900  
dp_tx_spcl_desc_alloc(struct dp_soc * soc,uint8_t desc_pool_id)901  static inline struct dp_tx_desc_s *dp_tx_spcl_desc_alloc(struct dp_soc *soc,
902  							 uint8_t desc_pool_id)
903  {
904  	return NULL;
905  }
906  /**
907   * dp_tx_desc_free() - Free a tx descriptor and attach it to free list
908   * @soc: Handle to DP SoC structure
909   * @tx_desc: Descriptor to free
910   * @desc_pool_id: Descriptor pool Id
911   *
912   * Return: None
913   */
914  static inline void
dp_tx_desc_free(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc,uint8_t desc_pool_id)915  dp_tx_desc_free(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc,
916  		uint8_t desc_pool_id)
917  {
918  	struct dp_tx_desc_pool_s *pool = &soc->tx_desc[desc_pool_id];
919  
920  	qdf_spin_lock_bh(&pool->flow_pool_lock);
921  	tx_desc->vdev_id = DP_INVALID_VDEV_ID;
922  	tx_desc->nbuf = NULL;
923  	tx_desc->flags = 0;
924  	dp_tx_desc_set_magic(tx_desc, DP_TX_MAGIC_PATTERN_FREE);
925  	dp_tx_put_desc_flow_pool(pool, tx_desc);
926  	switch (pool->status) {
927  	case FLOW_POOL_ACTIVE_PAUSED:
928  		if (pool->avail_desc > pool->start_th) {
929  			soc->pause_cb(pool->flow_pool_id,
930  				       WLAN_WAKE_ALL_NETIF_QUEUE,
931  				       WLAN_DATA_FLOW_CONTROL);
932  			pool->status = FLOW_POOL_ACTIVE_UNPAUSED;
933  		}
934  		break;
935  	case FLOW_POOL_INVALID:
936  		if (pool->avail_desc == pool->pool_size) {
937  			dp_tx_desc_pool_deinit(soc, desc_pool_id, false);
938  			dp_tx_desc_pool_free(soc, desc_pool_id, false);
939  			qdf_spin_unlock_bh(&pool->flow_pool_lock);
940  			qdf_print("%s %d pool is freed!!",
941  				  __func__, __LINE__);
942  			return;
943  		}
944  		break;
945  
946  	case FLOW_POOL_ACTIVE_UNPAUSED:
947  		break;
948  	default:
949  		qdf_print("%s %d pool is INACTIVE State!!",
950  			  __func__, __LINE__);
951  		break;
952  	};
953  
954  	qdf_spin_unlock_bh(&pool->flow_pool_lock);
955  }
956  
957  static inline void
dp_tx_spcl_desc_free(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc,uint8_t desc_pool_id)958  dp_tx_spcl_desc_free(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc,
959  		     uint8_t desc_pool_id)
960  {
961  }
962  #endif /* QCA_AC_BASED_FLOW_CONTROL */
963  
964  static inline bool
dp_tx_desc_thresh_reached(struct cdp_soc_t * soc_hdl,uint8_t vdev_id)965  dp_tx_desc_thresh_reached(struct cdp_soc_t *soc_hdl, uint8_t vdev_id)
966  {
967  	struct dp_soc *soc = cdp_soc_t_to_dp_soc(soc_hdl);
968  	struct dp_vdev *vdev = dp_vdev_get_ref_by_id(soc, vdev_id,
969  						     DP_MOD_ID_CDP);
970  	struct dp_tx_desc_pool_s *pool;
971  	bool status;
972  
973  	if (!vdev)
974  		return false;
975  
976  	pool = vdev->pool;
977  	status = dp_tx_is_threshold_reached(pool, pool->avail_desc);
978  	dp_vdev_unref_delete(soc, vdev, DP_MOD_ID_CDP);
979  
980  	return status;
981  }
982  #else /* QCA_LL_TX_FLOW_CONTROL_V2 */
983  
dp_tx_flow_control_init(struct dp_soc * handle)984  static inline void dp_tx_flow_control_init(struct dp_soc *handle)
985  {
986  }
987  
dp_tx_flow_control_deinit(struct dp_soc * handle)988  static inline void dp_tx_flow_control_deinit(struct dp_soc *handle)
989  {
990  }
991  
dp_tx_flow_pool_map_handler(struct dp_pdev * pdev,uint8_t flow_id,uint8_t flow_type,uint8_t flow_pool_id,uint32_t flow_pool_size)992  static inline QDF_STATUS dp_tx_flow_pool_map_handler(struct dp_pdev *pdev,
993  	uint8_t flow_id, uint8_t flow_type, uint8_t flow_pool_id,
994  	uint32_t flow_pool_size)
995  {
996  	return QDF_STATUS_SUCCESS;
997  }
998  
dp_tx_flow_pool_unmap_handler(struct dp_pdev * pdev,uint8_t flow_id,uint8_t flow_type,uint8_t flow_pool_id)999  static inline void dp_tx_flow_pool_unmap_handler(struct dp_pdev *pdev,
1000  	uint8_t flow_id, uint8_t flow_type, uint8_t flow_pool_id)
1001  {
1002  }
1003  
1004  #ifdef QCA_DP_TX_HW_SW_NBUF_DESC_PREFETCH
1005  static inline
dp_tx_prefetch_desc(struct dp_tx_desc_s * tx_desc)1006  void dp_tx_prefetch_desc(struct dp_tx_desc_s *tx_desc)
1007  {
1008  	if (tx_desc)
1009  		prefetch(tx_desc);
1010  }
1011  #else
1012  static inline
dp_tx_prefetch_desc(struct dp_tx_desc_s * tx_desc)1013  void dp_tx_prefetch_desc(struct dp_tx_desc_s *tx_desc)
1014  {
1015  }
1016  #endif
1017  
1018  /**
1019   * dp_tx_desc_alloc() - Allocate a Software Tx Descriptor from given pool
1020   * @soc: Handle to DP SoC structure
1021   * @desc_pool_id: pool id
1022   *
1023   * Return: Tx Descriptor or NULL
1024   */
dp_tx_desc_alloc(struct dp_soc * soc,uint8_t desc_pool_id)1025  static inline struct dp_tx_desc_s *dp_tx_desc_alloc(struct dp_soc *soc,
1026  						uint8_t desc_pool_id)
1027  {
1028  	struct dp_tx_desc_s *tx_desc = NULL;
1029  	struct dp_tx_desc_pool_s *pool = NULL;
1030  
1031  	pool = dp_get_tx_desc_pool(soc, desc_pool_id);
1032  
1033  	TX_DESC_LOCK_LOCK(&pool->lock);
1034  
1035  	tx_desc = pool->freelist;
1036  
1037  	/* Pool is exhausted */
1038  	if (!tx_desc) {
1039  		TX_DESC_LOCK_UNLOCK(&pool->lock);
1040  		return NULL;
1041  	}
1042  
1043  	pool->freelist = pool->freelist->next;
1044  	pool->num_allocated++;
1045  	pool->num_free--;
1046  	dp_tx_prefetch_desc(pool->freelist);
1047  
1048  	tx_desc->flags = DP_TX_DESC_FLAG_ALLOCATED;
1049  
1050  	TX_DESC_LOCK_UNLOCK(&pool->lock);
1051  
1052  	return tx_desc;
1053  }
1054  
dp_tx_spcl_desc_alloc(struct dp_soc * soc,uint8_t desc_pool_id)1055  static inline struct dp_tx_desc_s *dp_tx_spcl_desc_alloc(struct dp_soc *soc,
1056  							 uint8_t desc_pool_id)
1057  {
1058  	struct dp_tx_desc_s *tx_desc = NULL;
1059  	struct dp_tx_desc_pool_s *pool = NULL;
1060  
1061  	pool = dp_get_spcl_tx_desc_pool(soc, desc_pool_id);
1062  
1063  	TX_DESC_LOCK_LOCK(&pool->lock);
1064  
1065  	tx_desc = pool->freelist;
1066  
1067  	/* Pool is exhausted */
1068  	if (!tx_desc) {
1069  		TX_DESC_LOCK_UNLOCK(&pool->lock);
1070  		return NULL;
1071  	}
1072  
1073  	pool->freelist = pool->freelist->next;
1074  	pool->num_allocated++;
1075  	pool->num_free--;
1076  	dp_tx_prefetch_desc(pool->freelist);
1077  
1078  	tx_desc->flags = DP_TX_DESC_FLAG_ALLOCATED;
1079  	tx_desc->flags |= DP_TX_DESC_FLAG_SPECIAL;
1080  
1081  	TX_DESC_LOCK_UNLOCK(&pool->lock);
1082  
1083  	return tx_desc;
1084  }
1085  
1086  /**
1087   * dp_tx_desc_alloc_multiple() - Allocate batch of software Tx Descriptors
1088   *                            from given pool
1089   * @soc: Handle to DP SoC structure
1090   * @desc_pool_id: pool id should pick up
1091   * @num_requested: number of required descriptor
1092   *
1093   * allocate multiple tx descriptor and make a link
1094   *
1095   * Return: first descriptor pointer or NULL
1096   */
dp_tx_desc_alloc_multiple(struct dp_soc * soc,uint8_t desc_pool_id,uint8_t num_requested)1097  static inline struct dp_tx_desc_s *dp_tx_desc_alloc_multiple(
1098  		struct dp_soc *soc, uint8_t desc_pool_id, uint8_t num_requested)
1099  {
1100  	struct dp_tx_desc_s *c_desc = NULL, *h_desc = NULL;
1101  	uint8_t count;
1102  	struct dp_tx_desc_pool_s *pool = NULL;
1103  
1104  	pool = dp_get_tx_desc_pool(soc, desc_pool_id);
1105  
1106  	TX_DESC_LOCK_LOCK(&pool->lock);
1107  
1108  	if ((num_requested == 0) ||
1109  			(pool->num_free < num_requested)) {
1110  		TX_DESC_LOCK_UNLOCK(&pool->lock);
1111  		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
1112  			"%s, No Free Desc: Available(%d) num_requested(%d)",
1113  			__func__, pool->num_free,
1114  			num_requested);
1115  		return NULL;
1116  	}
1117  
1118  	h_desc = pool->freelist;
1119  
1120  	/* h_desc should never be NULL since num_free > requested */
1121  	qdf_assert_always(h_desc);
1122  
1123  	c_desc = h_desc;
1124  	for (count = 0; count < (num_requested - 1); count++) {
1125  		c_desc->flags = DP_TX_DESC_FLAG_ALLOCATED;
1126  		c_desc = c_desc->next;
1127  	}
1128  	pool->num_free -= count;
1129  	pool->num_allocated += count;
1130  	pool->freelist = c_desc->next;
1131  	c_desc->next = NULL;
1132  
1133  	TX_DESC_LOCK_UNLOCK(&pool->lock);
1134  	return h_desc;
1135  }
1136  
1137  /**
1138   * dp_tx_desc_free() - Free a tx descriptor and attach it to free list
1139   * @soc: Handle to DP SoC structure
1140   * @tx_desc: descriptor to free
1141   * @desc_pool_id: ID of the free pool
1142   */
1143  static inline void
dp_tx_desc_free(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc,uint8_t desc_pool_id)1144  dp_tx_desc_free(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc,
1145  		uint8_t desc_pool_id)
1146  {
1147  	struct dp_tx_desc_pool_s *pool = NULL;
1148  
1149  	dp_tx_desc_clear(tx_desc);
1150  	pool = dp_get_tx_desc_pool(soc, desc_pool_id);
1151  	TX_DESC_LOCK_LOCK(&pool->lock);
1152  	tx_desc->next = pool->freelist;
1153  	pool->freelist = tx_desc;
1154  	pool->num_allocated--;
1155  	pool->num_free++;
1156  	TX_DESC_LOCK_UNLOCK(&pool->lock);
1157  }
1158  
1159  static inline void
dp_tx_spcl_desc_free(struct dp_soc * soc,struct dp_tx_desc_s * tx_desc,uint8_t desc_pool_id)1160  dp_tx_spcl_desc_free(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc,
1161  		     uint8_t desc_pool_id)
1162  {
1163  	struct dp_tx_desc_pool_s *pool = NULL;
1164  
1165  	dp_tx_desc_clear(tx_desc);
1166  
1167  	pool = dp_get_spcl_tx_desc_pool(soc, desc_pool_id);
1168  	TX_DESC_LOCK_LOCK(&pool->lock);
1169  	tx_desc->next = pool->freelist;
1170  	pool->freelist = tx_desc;
1171  	pool->num_allocated--;
1172  	pool->num_free++;
1173  	TX_DESC_LOCK_UNLOCK(&pool->lock);
1174  }
1175  
1176  static inline void
dp_tx_desc_free_list(struct dp_tx_desc_pool_s * pool,struct dp_tx_desc_s * head_desc,struct dp_tx_desc_s * tail_desc,uint32_t fast_desc_count)1177  dp_tx_desc_free_list(struct dp_tx_desc_pool_s *pool,
1178  		     struct dp_tx_desc_s *head_desc,
1179  		     struct dp_tx_desc_s *tail_desc,
1180  		     uint32_t fast_desc_count)
1181  {
1182  	TX_DESC_LOCK_LOCK(&pool->lock);
1183  	pool->num_allocated -= fast_desc_count;
1184  	pool->num_free += fast_desc_count;
1185  	tail_desc->next = pool->freelist;
1186  	pool->freelist = head_desc;
1187  	TX_DESC_LOCK_UNLOCK(&pool->lock);
1188  }
1189  
1190  #endif /* QCA_LL_TX_FLOW_CONTROL_V2 */
1191  
1192  #ifdef QCA_DP_TX_DESC_ID_CHECK
1193  /**
1194   * dp_tx_is_desc_id_valid() - check is the tx desc id valid
1195   * @soc: Handle to DP SoC structure
1196   * @tx_desc_id:
1197   *
1198   * Return: true or false
1199   */
1200  static inline bool
dp_tx_is_desc_id_valid(struct dp_soc * soc,uint32_t tx_desc_id)1201  dp_tx_is_desc_id_valid(struct dp_soc *soc, uint32_t tx_desc_id)
1202  {
1203  	uint8_t pool_id;
1204  	uint16_t page_id, offset;
1205  	struct dp_tx_desc_pool_s *pool;
1206  
1207  	pool_id = (tx_desc_id & DP_TX_DESC_ID_POOL_MASK) >>
1208  			DP_TX_DESC_ID_POOL_OS;
1209  	/* Pool ID is out of limit */
1210  	if (pool_id > wlan_cfg_get_num_tx_desc_pool(
1211  				soc->wlan_cfg_ctx)) {
1212  		QDF_TRACE(QDF_MODULE_ID_DP,
1213  			  QDF_TRACE_LEVEL_FATAL,
1214  			  "%s:Tx Comp pool id %d not valid",
1215  			  __func__,
1216  			  pool_id);
1217  		goto warn_exit;
1218  	}
1219  
1220  	pool = &soc->tx_desc[pool_id];
1221  	/* the pool is freed */
1222  	if (IS_TX_DESC_POOL_STATUS_INACTIVE(pool)) {
1223  		QDF_TRACE(QDF_MODULE_ID_DP,
1224  			  QDF_TRACE_LEVEL_FATAL,
1225  			  "%s:the pool %d has been freed",
1226  			  __func__,
1227  			  pool_id);
1228  		goto warn_exit;
1229  	}
1230  
1231  	page_id = (tx_desc_id & DP_TX_DESC_ID_PAGE_MASK) >>
1232  				DP_TX_DESC_ID_PAGE_OS;
1233  	/* the page id is out of limit */
1234  	if (page_id >= pool->desc_pages.num_pages) {
1235  		QDF_TRACE(QDF_MODULE_ID_DP,
1236  			  QDF_TRACE_LEVEL_FATAL,
1237  			  "%s:the page id %d invalid, pool id %d, num_page %d",
1238  			  __func__,
1239  			  page_id,
1240  			  pool_id,
1241  			  pool->desc_pages.num_pages);
1242  		goto warn_exit;
1243  	}
1244  
1245  	offset = (tx_desc_id & DP_TX_DESC_ID_OFFSET_MASK) >>
1246  				DP_TX_DESC_ID_OFFSET_OS;
1247  	/* the offset is out of limit */
1248  	if (offset >= pool->desc_pages.num_element_per_page) {
1249  		QDF_TRACE(QDF_MODULE_ID_DP,
1250  			  QDF_TRACE_LEVEL_FATAL,
1251  			  "%s:offset %d invalid, pool%d,num_elem_per_page %d",
1252  			  __func__,
1253  			  offset,
1254  			  pool_id,
1255  			  pool->desc_pages.num_element_per_page);
1256  		goto warn_exit;
1257  	}
1258  
1259  	return true;
1260  
1261  warn_exit:
1262  	QDF_TRACE(QDF_MODULE_ID_DP,
1263  		  QDF_TRACE_LEVEL_FATAL,
1264  		  "%s:Tx desc id 0x%x not valid",
1265  		  __func__,
1266  		  tx_desc_id);
1267  	qdf_assert_always(0);
1268  	return false;
1269  }
1270  
1271  #else
1272  static inline bool
dp_tx_is_desc_id_valid(struct dp_soc * soc,uint32_t tx_desc_id)1273  dp_tx_is_desc_id_valid(struct dp_soc *soc, uint32_t tx_desc_id)
1274  {
1275  	return true;
1276  }
1277  #endif /* QCA_DP_TX_DESC_ID_CHECK */
1278  
1279  #ifdef QCA_DP_TX_DESC_FAST_COMP_ENABLE
dp_tx_desc_update_fast_comp_flag(struct dp_soc * soc,struct dp_tx_desc_s * desc,uint8_t allow_fast_comp)1280  static inline void dp_tx_desc_update_fast_comp_flag(struct dp_soc *soc,
1281  						    struct dp_tx_desc_s *desc,
1282  						    uint8_t allow_fast_comp)
1283  {
1284  	if (qdf_likely(!(desc->flags & DP_TX_DESC_FLAG_TO_FW)) &&
1285  	    qdf_likely(allow_fast_comp))
1286  		desc->flags |= DP_TX_DESC_FLAG_SIMPLE;
1287  
1288  	if (qdf_likely(desc->nbuf->is_from_recycler) &&
1289  	    qdf_likely(desc->nbuf->fast_xmit))
1290  		desc->flags |= DP_TX_DESC_FLAG_FAST;
1291  }
1292  
1293  #else
dp_tx_desc_update_fast_comp_flag(struct dp_soc * soc,struct dp_tx_desc_s * desc,uint8_t allow_fast_comp)1294  static inline void dp_tx_desc_update_fast_comp_flag(struct dp_soc *soc,
1295  						    struct dp_tx_desc_s *desc,
1296  						    uint8_t allow_fast_comp)
1297  {
1298  }
1299  #endif /* QCA_DP_TX_DESC_FAST_COMP_ENABLE */
1300  
1301  /**
1302   * dp_tx_desc_find() - find dp tx descriptor from pool/page/offset
1303   * @soc: handle for the device sending the data
1304   * @pool_id: pool id
1305   * @page_id: page id
1306   * @offset: offset from base address
1307   * @spcl_pool: bit to indicate if this is a special pool
1308   *
1309   * Use page and offset to find the corresponding descriptor object in
1310   * the given descriptor pool.
1311   *
1312   * Return: the descriptor object that has the specified ID
1313   */
1314  static inline
dp_tx_desc_find(struct dp_soc * soc,uint8_t pool_id,uint16_t page_id,uint16_t offset,bool spcl_pool)1315  struct dp_tx_desc_s *dp_tx_desc_find(struct dp_soc *soc,
1316  				     uint8_t pool_id, uint16_t page_id,
1317  				     uint16_t offset, bool spcl_pool)
1318  {
1319  	struct dp_tx_desc_pool_s *tx_desc_pool = NULL;
1320  
1321  	tx_desc_pool = spcl_pool ? dp_get_spcl_tx_desc_pool(soc, pool_id) :
1322  				dp_get_tx_desc_pool(soc, pool_id);
1323  
1324  	return tx_desc_pool->desc_pages.cacheable_pages[page_id] +
1325  		tx_desc_pool->elem_size * offset;
1326  }
1327  
1328  /**
1329   * dp_tx_ext_desc_alloc() - Get tx extension descriptor from pool
1330   * @soc: handle for the device sending the data
1331   * @desc_pool_id: target pool id
1332   *
1333   * Return: None
1334   */
1335  static inline
dp_tx_ext_desc_alloc(struct dp_soc * soc,uint8_t desc_pool_id)1336  struct dp_tx_ext_desc_elem_s *dp_tx_ext_desc_alloc(struct dp_soc *soc,
1337  		uint8_t desc_pool_id)
1338  {
1339  	struct dp_tx_ext_desc_elem_s *c_elem;
1340  
1341  	desc_pool_id = dp_tx_ext_desc_pool_override(desc_pool_id);
1342  	qdf_spin_lock_bh(&soc->tx_ext_desc[desc_pool_id].lock);
1343  	if (soc->tx_ext_desc[desc_pool_id].num_free <= 0) {
1344  		qdf_spin_unlock_bh(&soc->tx_ext_desc[desc_pool_id].lock);
1345  		return NULL;
1346  	}
1347  	c_elem = soc->tx_ext_desc[desc_pool_id].freelist;
1348  	soc->tx_ext_desc[desc_pool_id].freelist =
1349  		soc->tx_ext_desc[desc_pool_id].freelist->next;
1350  	soc->tx_ext_desc[desc_pool_id].num_free--;
1351  	qdf_spin_unlock_bh(&soc->tx_ext_desc[desc_pool_id].lock);
1352  	return c_elem;
1353  }
1354  
1355  /**
1356   * dp_tx_ext_desc_free() - Release tx extension descriptor to the pool
1357   * @soc: handle for the device sending the data
1358   * @elem: ext descriptor pointer should release
1359   * @desc_pool_id: target pool id
1360   *
1361   * Return: None
1362   */
dp_tx_ext_desc_free(struct dp_soc * soc,struct dp_tx_ext_desc_elem_s * elem,uint8_t desc_pool_id)1363  static inline void dp_tx_ext_desc_free(struct dp_soc *soc,
1364  	struct dp_tx_ext_desc_elem_s *elem, uint8_t desc_pool_id)
1365  {
1366  	desc_pool_id = dp_tx_ext_desc_pool_override(desc_pool_id);
1367  	qdf_spin_lock_bh(&soc->tx_ext_desc[desc_pool_id].lock);
1368  	elem->next = soc->tx_ext_desc[desc_pool_id].freelist;
1369  	soc->tx_ext_desc[desc_pool_id].freelist = elem;
1370  	soc->tx_ext_desc[desc_pool_id].num_free++;
1371  	qdf_spin_unlock_bh(&soc->tx_ext_desc[desc_pool_id].lock);
1372  	return;
1373  }
1374  
1375  /**
1376   * dp_tx_ext_desc_free_multiple() - Free multiple tx extension descriptor and
1377   *                           attach it to free list
1378   * @soc: Handle to DP SoC structure
1379   * @desc_pool_id: pool id should pick up
1380   * @elem: tx descriptor should be freed
1381   * @num_free: number of descriptors should be freed
1382   *
1383   * Return: none
1384   */
dp_tx_ext_desc_free_multiple(struct dp_soc * soc,struct dp_tx_ext_desc_elem_s * elem,uint8_t desc_pool_id,uint8_t num_free)1385  static inline void dp_tx_ext_desc_free_multiple(struct dp_soc *soc,
1386  		struct dp_tx_ext_desc_elem_s *elem, uint8_t desc_pool_id,
1387  		uint8_t num_free)
1388  {
1389  	struct dp_tx_ext_desc_elem_s *head, *tail, *c_elem;
1390  	uint8_t freed = num_free;
1391  
1392  	/* caller should always guarantee atleast list of num_free nodes */
1393  	qdf_assert_always(elem);
1394  
1395  	head = elem;
1396  	c_elem = head;
1397  	tail = head;
1398  	while (c_elem && freed) {
1399  		tail = c_elem;
1400  		c_elem = c_elem->next;
1401  		freed--;
1402  	}
1403  
1404  	/* caller should always guarantee atleast list of num_free nodes */
1405  	qdf_assert_always(tail);
1406  
1407  	desc_pool_id = dp_tx_ext_desc_pool_override(desc_pool_id);
1408  	qdf_spin_lock_bh(&soc->tx_ext_desc[desc_pool_id].lock);
1409  	tail->next = soc->tx_ext_desc[desc_pool_id].freelist;
1410  	soc->tx_ext_desc[desc_pool_id].freelist = head;
1411  	soc->tx_ext_desc[desc_pool_id].num_free += num_free;
1412  	qdf_spin_unlock_bh(&soc->tx_ext_desc[desc_pool_id].lock);
1413  
1414  	return;
1415  }
1416  
1417  #if defined(FEATURE_TSO)
1418  /**
1419   * dp_tx_tso_desc_alloc() - function to allocate a TSO segment
1420   * @soc: device soc instance
1421   * @pool_id: pool id should pick up tso descriptor
1422   *
1423   * Allocates a TSO segment element from the free list held in
1424   * the soc
1425   *
1426   * Return: tso_seg, tso segment memory pointer
1427   */
dp_tx_tso_desc_alloc(struct dp_soc * soc,uint8_t pool_id)1428  static inline struct qdf_tso_seg_elem_t *dp_tx_tso_desc_alloc(
1429  		struct dp_soc *soc, uint8_t pool_id)
1430  {
1431  	struct qdf_tso_seg_elem_t *tso_seg = NULL;
1432  
1433  	qdf_spin_lock_bh(&soc->tx_tso_desc[pool_id].lock);
1434  	if (soc->tx_tso_desc[pool_id].freelist) {
1435  		soc->tx_tso_desc[pool_id].num_free--;
1436  		tso_seg = soc->tx_tso_desc[pool_id].freelist;
1437  		soc->tx_tso_desc[pool_id].freelist =
1438  			soc->tx_tso_desc[pool_id].freelist->next;
1439  	}
1440  	qdf_spin_unlock_bh(&soc->tx_tso_desc[pool_id].lock);
1441  
1442  	return tso_seg;
1443  }
1444  
1445  /**
1446   * dp_tx_tso_desc_free() - function to free a TSO segment
1447   * @soc: device soc instance
1448   * @pool_id: pool id should pick up tso descriptor
1449   * @tso_seg: tso segment memory pointer
1450   *
1451   * Returns a TSO segment element to the free list held in the
1452   * HTT pdev
1453   *
1454   * Return: none
1455   */
dp_tx_tso_desc_free(struct dp_soc * soc,uint8_t pool_id,struct qdf_tso_seg_elem_t * tso_seg)1456  static inline void dp_tx_tso_desc_free(struct dp_soc *soc,
1457  		uint8_t pool_id, struct qdf_tso_seg_elem_t *tso_seg)
1458  {
1459  	qdf_spin_lock_bh(&soc->tx_tso_desc[pool_id].lock);
1460  	tso_seg->next = soc->tx_tso_desc[pool_id].freelist;
1461  	soc->tx_tso_desc[pool_id].freelist = tso_seg;
1462  	soc->tx_tso_desc[pool_id].num_free++;
1463  	qdf_spin_unlock_bh(&soc->tx_tso_desc[pool_id].lock);
1464  }
1465  
1466  static inline
dp_tso_num_seg_alloc(struct dp_soc * soc,uint8_t pool_id)1467  struct qdf_tso_num_seg_elem_t  *dp_tso_num_seg_alloc(struct dp_soc *soc,
1468  		uint8_t pool_id)
1469  {
1470  	struct qdf_tso_num_seg_elem_t *tso_num_seg = NULL;
1471  
1472  	qdf_spin_lock_bh(&soc->tx_tso_num_seg[pool_id].lock);
1473  	if (soc->tx_tso_num_seg[pool_id].freelist) {
1474  		soc->tx_tso_num_seg[pool_id].num_free--;
1475  		tso_num_seg = soc->tx_tso_num_seg[pool_id].freelist;
1476  		soc->tx_tso_num_seg[pool_id].freelist =
1477  			soc->tx_tso_num_seg[pool_id].freelist->next;
1478  	}
1479  	qdf_spin_unlock_bh(&soc->tx_tso_num_seg[pool_id].lock);
1480  
1481  	return tso_num_seg;
1482  }
1483  
1484  static inline
dp_tso_num_seg_free(struct dp_soc * soc,uint8_t pool_id,struct qdf_tso_num_seg_elem_t * tso_num_seg)1485  void dp_tso_num_seg_free(struct dp_soc *soc,
1486  		uint8_t pool_id, struct qdf_tso_num_seg_elem_t *tso_num_seg)
1487  {
1488  	qdf_spin_lock_bh(&soc->tx_tso_num_seg[pool_id].lock);
1489  	tso_num_seg->next = soc->tx_tso_num_seg[pool_id].freelist;
1490  	soc->tx_tso_num_seg[pool_id].freelist = tso_num_seg;
1491  	soc->tx_tso_num_seg[pool_id].num_free++;
1492  	qdf_spin_unlock_bh(&soc->tx_tso_num_seg[pool_id].lock);
1493  }
1494  #endif
1495  
1496  /**
1497   * dp_tx_me_alloc_buf() - Alloc descriptor from me pool
1498   * @pdev: DP_PDEV handle for datapath
1499   *
1500   * Return: tx descriptor on success, NULL on error
1501   */
1502  static inline struct dp_tx_me_buf_t*
dp_tx_me_alloc_buf(struct dp_pdev * pdev)1503  dp_tx_me_alloc_buf(struct dp_pdev *pdev)
1504  {
1505  	struct dp_tx_me_buf_t *buf = NULL;
1506  	qdf_spin_lock_bh(&pdev->tx_mutex);
1507  	if (pdev->me_buf.freelist) {
1508  		buf = pdev->me_buf.freelist;
1509  		pdev->me_buf.freelist = pdev->me_buf.freelist->next;
1510  		pdev->me_buf.buf_in_use++;
1511  	} else {
1512  		QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
1513  				"Error allocating memory in pool");
1514  		qdf_spin_unlock_bh(&pdev->tx_mutex);
1515  		return NULL;
1516  	}
1517  	qdf_spin_unlock_bh(&pdev->tx_mutex);
1518  	return buf;
1519  }
1520  
1521  /**
1522   * dp_tx_me_free_buf() - Unmap the buffer holding the dest
1523   * address, free me descriptor and add it to the free-pool
1524   * @pdev: DP_PDEV handle for datapath
1525   * @buf : Allocated ME BUF
1526   *
1527   * Return:void
1528   */
1529  static inline void
dp_tx_me_free_buf(struct dp_pdev * pdev,struct dp_tx_me_buf_t * buf)1530  dp_tx_me_free_buf(struct dp_pdev *pdev, struct dp_tx_me_buf_t *buf)
1531  {
1532  	/*
1533  	 * If the buf containing mac address was mapped,
1534  	 * it must be unmapped before freeing the me_buf.
1535  	 * The "paddr_macbuf" member in the me_buf structure
1536  	 * holds the mapped physical address and it must be
1537  	 * set to 0 after unmapping.
1538  	 */
1539  	if (buf->paddr_macbuf) {
1540  		qdf_mem_unmap_nbytes_single(pdev->soc->osdev,
1541  					    buf->paddr_macbuf,
1542  					    QDF_DMA_TO_DEVICE,
1543  					    QDF_MAC_ADDR_SIZE);
1544  		buf->paddr_macbuf = 0;
1545  	}
1546  	qdf_spin_lock_bh(&pdev->tx_mutex);
1547  	buf->next = pdev->me_buf.freelist;
1548  	pdev->me_buf.freelist = buf;
1549  	pdev->me_buf.buf_in_use--;
1550  	qdf_spin_unlock_bh(&pdev->tx_mutex);
1551  }
1552  #endif /* DP_TX_DESC_H */
1553