blob: 59175f972543881f080edae5efbafbef032b3005 [file] [log] [blame]
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301/*
Sravan Kumar Kairam9d6acea2019-05-13 18:14:59 +05302 * Copyright (c) 2016-2019 The Linux Foundation. All rights reserved.
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303 *
4 * Permission to use, copy, modify, and/or distribute this software for
5 * any purpose with or without fee is hereby granted, provided that the
6 * above copyright notice and this permission notice appear in all
7 * copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
10 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
11 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
12 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
13 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
14 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
15 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
16 * PERFORMANCE OF THIS SOFTWARE.
17 */
18
19#include "htt.h"
Balamurugan Mahalingamd0159642018-07-11 15:02:29 +053020#include "hal_hw_headers.h"
Pamidipati, Vijay576bd152016-09-27 20:58:18 +053021#include "dp_tx.h"
22#include "dp_tx_desc.h"
Ishank Jain1e7401c2017-02-17 15:38:39 +053023#include "dp_peer.h"
Pamidipati, Vijay576bd152016-09-27 20:58:18 +053024#include "dp_types.h"
25#include "hal_tx.h"
26#include "qdf_mem.h"
27#include "qdf_nbuf.h"
Pamidipati, Vijayef2cbc62017-09-27 23:09:06 +053028#include "qdf_net_types.h"
Ravi Joshiaf9ace82017-02-17 12:41:48 -080029#include <wlan_cfg.h>
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +053030#ifdef MESH_MODE_SUPPORT
31#include "if_meta_hdr.h"
32#endif
Srinivas Girigowda99f2a292019-02-12 14:20:58 -080033#include "enet.h"
nobeljdebe2b32019-04-23 11:18:47 -070034#include "dp_internal.h"
Amir Patelcb990262019-05-28 15:12:48 +053035#ifdef FEATURE_WDS
36#include "dp_txrx_wds.h"
37#endif
Pamidipati, Vijay576bd152016-09-27 20:58:18 +053038
Prathyusha Guduri02ed9482018-04-17 19:06:30 +053039#define DP_TX_QUEUE_MASK 0x3
Pamidipati, Vijay576bd152016-09-27 20:58:18 +053040
41/* TODO Add support in TSO */
42#define DP_DESC_NUM_FRAG(x) 0
Ankit Gupta20e59582016-12-06 14:24:00 -080043
44/* disable TQM_BYPASS */
Dhanashri Atre10a93232016-11-11 18:47:05 -080045#define TQM_BYPASS_WAR 0
Ankit Gupta20e59582016-12-06 14:24:00 -080046
Ruchi, Agrawalbd894b32017-11-03 17:24:56 +053047/* invalid peer id for reinject*/
48#define DP_INVALID_PEER 0XFFFE
49
ruchi agrawal45f3ac42017-10-25 09:03:28 +053050/*mapping between hal encrypt type and cdp_sec_type*/
51#define MAX_CDP_SEC_TYPE 12
52static const uint8_t sec_type_map[MAX_CDP_SEC_TYPE] = {
53 HAL_TX_ENCRYPT_TYPE_NO_CIPHER,
54 HAL_TX_ENCRYPT_TYPE_WEP_128,
55 HAL_TX_ENCRYPT_TYPE_WEP_104,
56 HAL_TX_ENCRYPT_TYPE_WEP_40,
57 HAL_TX_ENCRYPT_TYPE_TKIP_WITH_MIC,
58 HAL_TX_ENCRYPT_TYPE_TKIP_NO_MIC,
59 HAL_TX_ENCRYPT_TYPE_AES_CCMP_128,
60 HAL_TX_ENCRYPT_TYPE_WAPI,
61 HAL_TX_ENCRYPT_TYPE_AES_CCMP_256,
62 HAL_TX_ENCRYPT_TYPE_AES_GCMP_128,
63 HAL_TX_ENCRYPT_TYPE_AES_GCMP_256,
64 HAL_TX_ENCRYPT_TYPE_WAPI_GCM_SM4};
65
nobeljdebe2b32019-04-23 11:18:47 -070066#ifdef WLAN_TX_PKT_CAPTURE_ENH
67#include "dp_tx_capture.h"
68#endif
69
Pamidipati, Vijay576bd152016-09-27 20:58:18 +053070/**
71 * dp_tx_get_queue() - Returns Tx queue IDs to be used for this Tx frame
72 * @vdev: DP Virtual device handle
73 * @nbuf: Buffer pointer
74 * @queue: queue ids container for nbuf
75 *
76 * TX packet queue has 2 instances, software descriptors id and dma ring id
77 * Based on tx feature and hardware configuration queue id combination could be
78 * different.
79 * For example -
80 * With XPS enabled,all TX descriptor pools and dma ring are assigned per cpu id
81 * With no XPS,lock based resource protection, Descriptor pool ids are different
82 * for each vdev, dma ring id will be same as single pdev id
83 *
84 * Return: None
85 */
Prathyusha Guduri02ed9482018-04-17 19:06:30 +053086#ifdef QCA_OL_TX_MULTIQ_SUPPORT
87static inline void dp_tx_get_queue(struct dp_vdev *vdev,
88 qdf_nbuf_t nbuf, struct dp_tx_queue *queue)
89{
90 uint16_t queue_offset = qdf_nbuf_get_queue_mapping(nbuf) & DP_TX_QUEUE_MASK;
91 queue->desc_pool_id = queue_offset;
92 queue->ring_id = vdev->pdev->soc->tx_ring_map[queue_offset];
93
94 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
95 "%s, pool_id:%d ring_id: %d",
96 __func__, queue->desc_pool_id, queue->ring_id);
97
98 return;
99}
100#else /* QCA_OL_TX_MULTIQ_SUPPORT */
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530101static inline void dp_tx_get_queue(struct dp_vdev *vdev,
102 qdf_nbuf_t nbuf, struct dp_tx_queue *queue)
103{
Manjunathappa Prakashced7ea62017-07-02 03:02:15 -0700104 /* get flow id */
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530105 queue->desc_pool_id = DP_TX_GET_DESC_POOL_ID(vdev);
106 queue->ring_id = DP_TX_GET_RING_ID(vdev);
107
Houston Hoffman41b912c2017-08-30 14:27:51 -0700108 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
Yun Parkb9a7b5a2017-09-06 14:34:58 -0700109 "%s, pool_id:%d ring_id: %d",
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530110 __func__, queue->desc_pool_id, queue->ring_id);
111
112 return;
113}
Prathyusha Guduri02ed9482018-04-17 19:06:30 +0530114#endif
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530115
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700116#if defined(FEATURE_TSO)
117/**
chenguoee42a322018-03-15 18:05:46 +0800118 * dp_tx_tso_unmap_segment() - Unmap TSO segment
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700119 *
chenguoee42a322018-03-15 18:05:46 +0800120 * @soc - core txrx main context
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800121 * @seg_desc - tso segment descriptor
122 * @num_seg_desc - tso number segment descriptor
chenguoee42a322018-03-15 18:05:46 +0800123 */
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800124static void dp_tx_tso_unmap_segment(
125 struct dp_soc *soc,
126 struct qdf_tso_seg_elem_t *seg_desc,
127 struct qdf_tso_num_seg_elem_t *num_seg_desc)
chenguoee42a322018-03-15 18:05:46 +0800128{
129 TSO_DEBUG("%s: Unmap the tso segment", __func__);
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800130 if (qdf_unlikely(!seg_desc)) {
131 DP_TRACE(ERROR, "%s %d TSO desc is NULL!",
132 __func__, __LINE__);
chenguoee42a322018-03-15 18:05:46 +0800133 qdf_assert(0);
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800134 } else if (qdf_unlikely(!num_seg_desc)) {
135 DP_TRACE(ERROR, "%s %d TSO num desc is NULL!",
136 __func__, __LINE__);
chenguoee42a322018-03-15 18:05:46 +0800137 qdf_assert(0);
138 } else {
139 bool is_last_seg;
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800140 /* no tso segment left to do dma unmap */
141 if (num_seg_desc->num_seg.tso_cmn_num_seg < 1)
142 return;
chenguoee42a322018-03-15 18:05:46 +0800143
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800144 is_last_seg = (num_seg_desc->num_seg.tso_cmn_num_seg == 1) ?
145 true : false;
chenguoee42a322018-03-15 18:05:46 +0800146 qdf_nbuf_unmap_tso_segment(soc->osdev,
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800147 seg_desc, is_last_seg);
148 num_seg_desc->num_seg.tso_cmn_num_seg--;
chenguoee42a322018-03-15 18:05:46 +0800149 }
150}
151
152/**
153 * dp_tx_tso_desc_release() - Release the tso segment and tso_cmn_num_seg
154 * back to the freelist
155 *
156 * @soc - soc device handle
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700157 * @tx_desc - Tx software descriptor
158 */
159static void dp_tx_tso_desc_release(struct dp_soc *soc,
chenguoee42a322018-03-15 18:05:46 +0800160 struct dp_tx_desc_s *tx_desc)
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700161{
162 TSO_DEBUG("%s: Free the tso descriptor", __func__);
chenguoee42a322018-03-15 18:05:46 +0800163 if (qdf_unlikely(!tx_desc->tso_desc)) {
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700164 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
chenguoee42a322018-03-15 18:05:46 +0800165 "%s %d TSO desc is NULL!",
166 __func__, __LINE__);
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700167 qdf_assert(0);
chenguoee42a322018-03-15 18:05:46 +0800168 } else if (qdf_unlikely(!tx_desc->tso_num_desc)) {
169 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
170 "%s %d TSO num desc is NULL!",
171 __func__, __LINE__);
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700172 qdf_assert(0);
173 } else {
174 struct qdf_tso_num_seg_elem_t *tso_num_desc =
chenguoee42a322018-03-15 18:05:46 +0800175 (struct qdf_tso_num_seg_elem_t *)tx_desc->tso_num_desc;
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700176
chenguoee42a322018-03-15 18:05:46 +0800177 /* Add the tso num segment into the free list */
178 if (tso_num_desc->num_seg.tso_cmn_num_seg == 0) {
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700179 dp_tso_num_seg_free(soc, tx_desc->pool_id,
chenguoee42a322018-03-15 18:05:46 +0800180 tx_desc->tso_num_desc);
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700181 tx_desc->tso_num_desc = NULL;
182 }
chenguoee42a322018-03-15 18:05:46 +0800183
184 /* Add the tso segment into the free list*/
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700185 dp_tx_tso_desc_free(soc,
chenguoee42a322018-03-15 18:05:46 +0800186 tx_desc->pool_id, tx_desc->tso_desc);
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700187 tx_desc->tso_desc = NULL;
188 }
189}
190#else
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800191static void dp_tx_tso_unmap_segment(
192 struct dp_soc *soc,
193 struct qdf_tso_seg_elem_t *seg_desc,
194 struct qdf_tso_num_seg_elem_t *num_seg_desc)
chenguoee42a322018-03-15 18:05:46 +0800195
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700196{
chenguoee42a322018-03-15 18:05:46 +0800197}
198
199static void dp_tx_tso_desc_release(struct dp_soc *soc,
200 struct dp_tx_desc_s *tx_desc)
201{
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700202}
203#endif
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530204/**
205 * dp_tx_desc_release() - Release Tx Descriptor
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530206 * @tx_desc : Tx Descriptor
207 * @desc_pool_id: Descriptor Pool ID
208 *
209 * Deallocate all resources attached to Tx descriptor and free the Tx
210 * descriptor.
211 *
212 * Return:
213 */
Chaithanya Garrepallief40fec2019-05-16 22:26:05 +0530214static void
Ravi Joshiab33d9b2017-02-11 21:43:28 -0800215dp_tx_desc_release(struct dp_tx_desc_s *tx_desc, uint8_t desc_pool_id)
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530216{
Ravi Joshiab33d9b2017-02-11 21:43:28 -0800217 struct dp_pdev *pdev = tx_desc->pdev;
218 struct dp_soc *soc;
Debashis Duttaf645222017-01-20 19:29:25 -0800219 uint8_t comp_status = 0;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530220
Ravi Joshiab33d9b2017-02-11 21:43:28 -0800221 qdf_assert(pdev);
222
223 soc = pdev->soc;
Ishank Jainbc2d91f2017-01-03 18:14:54 +0530224
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700225 if (tx_desc->frm_type == dp_tx_frm_tso)
226 dp_tx_tso_desc_release(soc, tx_desc);
227
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530228 if (tx_desc->flags & DP_TX_DESC_FLAG_FRAG)
229 dp_tx_ext_desc_free(soc, tx_desc->msdu_ext_desc, desc_pool_id);
230
Ruchi, Agrawalc0f9c972018-02-02 11:24:05 +0530231 if (tx_desc->flags & DP_TX_DESC_FLAG_ME)
232 dp_tx_me_free_buf(tx_desc->pdev, tx_desc->me_buffer);
233
Vijay Pamidipati4d5d4362017-02-09 22:49:00 +0530234 qdf_atomic_dec(&pdev->num_tx_outstanding);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530235
236 if (tx_desc->flags & DP_TX_DESC_FLAG_TO_FW)
Vijay Pamidipati4d5d4362017-02-09 22:49:00 +0530237 qdf_atomic_dec(&pdev->num_tx_exception);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530238
Debashis Duttaf645222017-01-20 19:29:25 -0800239 if (HAL_TX_COMP_RELEASE_SOURCE_TQM ==
240 hal_tx_comp_get_buffer_source(&tx_desc->comp))
Balamurugan Mahalingam764219e2018-09-17 15:34:25 +0530241 comp_status = hal_tx_comp_get_release_reason(&tx_desc->comp,
242 soc->hal_soc);
Debashis Duttaf645222017-01-20 19:29:25 -0800243 else
244 comp_status = HAL_TX_COMP_RELEASE_REASON_FW;
245
Houston Hoffman41b912c2017-08-30 14:27:51 -0700246 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
Yun Parkb9a7b5a2017-09-06 14:34:58 -0700247 "Tx Completion Release desc %d status %d outstanding %d",
248 tx_desc->id, comp_status,
249 qdf_atomic_read(&pdev->num_tx_outstanding));
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530250
251 dp_tx_desc_free(soc, tx_desc, desc_pool_id);
252 return;
253}
254
255/**
256 * dp_tx_htt_metadata_prepare() - Prepare HTT metadata for special frames
257 * @vdev: DP vdev Handle
258 * @nbuf: skb
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530259 *
260 * Prepares and fills HTT metadata in the frame pre-header for special frames
261 * that should be transmitted using varying transmit parameters.
262 * There are 2 VDEV modes that currently needs this special metadata -
263 * 1) Mesh Mode
264 * 2) DSRC Mode
265 *
266 * Return: HTT metadata size
267 *
268 */
Jeff Johnson755f2612017-01-05 16:28:13 -0800269static uint8_t dp_tx_prepare_htt_metadata(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
Pamidipati, Vijay8a4e27c2017-04-06 01:04:08 +0530270 uint32_t *meta_data)
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530271{
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +0530272 struct htt_tx_msdu_desc_ext2_t *desc_ext =
273 (struct htt_tx_msdu_desc_ext2_t *) meta_data;
Pamidipati, Vijay8a4e27c2017-04-06 01:04:08 +0530274
275 uint8_t htt_desc_size;
276
277 /* Size rounded of multiple of 8 bytes */
278 uint8_t htt_desc_size_aligned;
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +0530279
280 uint8_t *hdr = NULL;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530281
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530282 /*
283 * Metadata - HTT MSDU Extension header
284 */
285 htt_desc_size = sizeof(struct htt_tx_msdu_desc_ext2_t);
Pamidipati, Vijay8a4e27c2017-04-06 01:04:08 +0530286 htt_desc_size_aligned = (htt_desc_size + 7) & ~0x7;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530287
288 if (vdev->mesh_vdev) {
Venkateswara Swamy Bandaru41ebb332018-09-12 18:25:29 +0530289 if (qdf_unlikely(qdf_nbuf_headroom(nbuf) <
290 htt_desc_size_aligned)) {
291 DP_STATS_INC(vdev,
292 tx_i.dropped.headroom_insufficient, 1);
293 return 0;
294 }
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530295 /* Fill and add HTT metaheader */
Pamidipati, Vijay8a4e27c2017-04-06 01:04:08 +0530296 hdr = qdf_nbuf_push_head(nbuf, htt_desc_size_aligned);
Jeff Johnsona8edf332019-03-18 09:51:52 -0700297 if (!hdr) {
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +0530298 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +0530299 "Error in filling HTT metadata");
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +0530300
301 return 0;
302 }
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +0530303 qdf_mem_copy(hdr, desc_ext, htt_desc_size);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530304
305 } else if (vdev->opmode == wlan_op_mode_ocb) {
306 /* Todo - Add support for DSRC */
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530307 }
308
Pamidipati, Vijay8a4e27c2017-04-06 01:04:08 +0530309 return htt_desc_size_aligned;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530310}
311
312/**
Ishank Jain5122f8f2017-03-15 22:22:47 +0530313 * dp_tx_prepare_tso_ext_desc() - Prepare MSDU extension descriptor for TSO
314 * @tso_seg: TSO segment to process
315 * @ext_desc: Pointer to MSDU extension descriptor
316 *
317 * Return: void
318 */
319#if defined(FEATURE_TSO)
320static void dp_tx_prepare_tso_ext_desc(struct qdf_tso_seg_t *tso_seg,
321 void *ext_desc)
322{
323 uint8_t num_frag;
Ishank Jain5122f8f2017-03-15 22:22:47 +0530324 uint32_t tso_flags;
325
326 /*
327 * Set tso_en, tcp_flags(NS, CWR, ECE, URG, ACK, PSH, RST, SYN, FIN),
328 * tcp_flag_mask
329 *
330 * Checksum enable flags are set in TCL descriptor and not in Extension
331 * Descriptor (H/W ignores checksum_en flags in MSDU ext descriptor)
332 */
333 tso_flags = *(uint32_t *) &tso_seg->tso_flags;
334
335 hal_tx_ext_desc_set_tso_flags(ext_desc, tso_flags);
336
337 hal_tx_ext_desc_set_msdu_length(ext_desc, tso_seg->tso_flags.l2_len,
338 tso_seg->tso_flags.ip_len);
339
340 hal_tx_ext_desc_set_tcp_seq(ext_desc, tso_seg->tso_flags.tcp_seq_num);
341 hal_tx_ext_desc_set_ip_id(ext_desc, tso_seg->tso_flags.ip_id);
342
343
344 for (num_frag = 0; num_frag < tso_seg->num_frags; num_frag++) {
345 uint32_t lo = 0;
346 uint32_t hi = 0;
347
348 qdf_dmaaddr_to_32s(
349 tso_seg->tso_frags[num_frag].paddr, &lo, &hi);
350 hal_tx_ext_desc_set_buffer(ext_desc, num_frag, lo, hi,
351 tso_seg->tso_frags[num_frag].length);
352 }
353
354 return;
355}
356#else
357static void dp_tx_prepare_tso_ext_desc(struct qdf_tso_seg_t *tso_seg,
358 void *ext_desc)
359{
360 return;
361}
362#endif
363
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700364#if defined(FEATURE_TSO)
365/**
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800366 * dp_tx_free_tso_seg_list() - Loop through the tso segments
367 * allocated and free them
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700368 *
369 * @soc: soc handle
370 * @free_seg: list of tso segments
371 * @msdu_info: msdu descriptor
372 *
373 * Return - void
374 */
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800375static void dp_tx_free_tso_seg_list(
376 struct dp_soc *soc,
377 struct qdf_tso_seg_elem_t *free_seg,
378 struct dp_tx_msdu_info_s *msdu_info)
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700379{
380 struct qdf_tso_seg_elem_t *next_seg;
381
382 while (free_seg) {
383 next_seg = free_seg->next;
384 dp_tx_tso_desc_free(soc,
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800385 msdu_info->tx_queue.desc_pool_id,
386 free_seg);
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700387 free_seg = next_seg;
388 }
389}
390
391/**
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800392 * dp_tx_free_tso_num_seg_list() - Loop through the tso num segments
393 * allocated and free them
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700394 *
395 * @soc: soc handle
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800396 * @free_num_seg: list of tso number segments
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700397 * @msdu_info: msdu descriptor
398 * Return - void
399 */
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800400static void dp_tx_free_tso_num_seg_list(
401 struct dp_soc *soc,
402 struct qdf_tso_num_seg_elem_t *free_num_seg,
403 struct dp_tx_msdu_info_s *msdu_info)
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700404{
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800405 struct qdf_tso_num_seg_elem_t *next_num_seg;
406
407 while (free_num_seg) {
408 next_num_seg = free_num_seg->next;
409 dp_tso_num_seg_free(soc,
410 msdu_info->tx_queue.desc_pool_id,
411 free_num_seg);
412 free_num_seg = next_num_seg;
413 }
414}
415
416/**
417 * dp_tx_unmap_tso_seg_list() - Loop through the tso segments
418 * do dma unmap for each segment
419 *
420 * @soc: soc handle
421 * @free_seg: list of tso segments
422 * @num_seg_desc: tso number segment descriptor
423 *
424 * Return - void
425 */
426static void dp_tx_unmap_tso_seg_list(
427 struct dp_soc *soc,
428 struct qdf_tso_seg_elem_t *free_seg,
429 struct qdf_tso_num_seg_elem_t *num_seg_desc)
430{
431 struct qdf_tso_seg_elem_t *next_seg;
432
433 if (qdf_unlikely(!num_seg_desc)) {
434 DP_TRACE(ERROR, "TSO number seg desc is NULL!");
435 return;
436 }
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700437
438 while (free_seg) {
439 next_seg = free_seg->next;
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800440 dp_tx_tso_unmap_segment(soc, free_seg, num_seg_desc);
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700441 free_seg = next_seg;
442 }
443}
444
Ishank Jain5122f8f2017-03-15 22:22:47 +0530445/**
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800446 * dp_tx_free_remaining_tso_desc() - do dma unmap for tso segments if any,
447 * free the tso segments descriptor and
448 * tso num segments descriptor
449 *
450 * @soc: soc handle
451 * @msdu_info: msdu descriptor
452 * @tso_seg_unmap: flag to show if dma unmap is necessary
453 *
454 * Return - void
455 */
456static void dp_tx_free_remaining_tso_desc(struct dp_soc *soc,
457 struct dp_tx_msdu_info_s *msdu_info,
458 bool tso_seg_unmap)
459{
460 struct qdf_tso_info_t *tso_info = &msdu_info->u.tso_info;
461 struct qdf_tso_seg_elem_t *free_seg = tso_info->tso_seg_list;
462 struct qdf_tso_num_seg_elem_t *tso_num_desc =
463 tso_info->tso_num_seg_list;
464
465 /* do dma unmap for each segment */
466 if (tso_seg_unmap)
467 dp_tx_unmap_tso_seg_list(soc, free_seg, tso_num_desc);
468
469 /* free all tso number segment descriptor though looks only have 1 */
470 dp_tx_free_tso_num_seg_list(soc, tso_num_desc, msdu_info);
471
472 /* free all tso segment descriptor */
473 dp_tx_free_tso_seg_list(soc, free_seg, msdu_info);
474}
475
476/**
Ishank Jain5122f8f2017-03-15 22:22:47 +0530477 * dp_tx_prepare_tso() - Given a jumbo msdu, prepare the TSO info
478 * @vdev: virtual device handle
479 * @msdu: network buffer
480 * @msdu_info: meta data associated with the msdu
481 *
482 * Return: QDF_STATUS_SUCCESS success
483 */
Ishank Jain5122f8f2017-03-15 22:22:47 +0530484static QDF_STATUS dp_tx_prepare_tso(struct dp_vdev *vdev,
485 qdf_nbuf_t msdu, struct dp_tx_msdu_info_s *msdu_info)
486{
487 struct qdf_tso_seg_elem_t *tso_seg;
488 int num_seg = qdf_nbuf_get_tso_num_seg(msdu);
489 struct dp_soc *soc = vdev->pdev->soc;
490 struct qdf_tso_info_t *tso_info;
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700491 struct qdf_tso_num_seg_elem_t *tso_num_seg;
Ishank Jain5122f8f2017-03-15 22:22:47 +0530492
493 tso_info = &msdu_info->u.tso_info;
494 tso_info->curr_seg = NULL;
495 tso_info->tso_seg_list = NULL;
496 tso_info->num_segs = num_seg;
497 msdu_info->frm_type = dp_tx_frm_tso;
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700498 tso_info->tso_num_seg_list = NULL;
499
500 TSO_DEBUG(" %s: num_seg: %d", __func__, num_seg);
Ishank Jain5122f8f2017-03-15 22:22:47 +0530501
502 while (num_seg) {
503 tso_seg = dp_tx_tso_desc_alloc(
504 soc, msdu_info->tx_queue.desc_pool_id);
505 if (tso_seg) {
506 tso_seg->next = tso_info->tso_seg_list;
507 tso_info->tso_seg_list = tso_seg;
508 num_seg--;
509 } else {
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800510 DP_TRACE(ERROR, "%s: Failed to alloc tso seg desc",
511 __func__);
512 dp_tx_free_remaining_tso_desc(soc, msdu_info, false);
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700513
Ishank Jain5122f8f2017-03-15 22:22:47 +0530514 return QDF_STATUS_E_NOMEM;
515 }
516 }
517
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700518 TSO_DEBUG(" %s: num_seg: %d", __func__, num_seg);
519
520 tso_num_seg = dp_tso_num_seg_alloc(soc,
521 msdu_info->tx_queue.desc_pool_id);
522
523 if (tso_num_seg) {
524 tso_num_seg->next = tso_info->tso_num_seg_list;
525 tso_info->tso_num_seg_list = tso_num_seg;
526 } else {
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800527 DP_TRACE(ERROR, "%s: Failed to alloc - Number of segs desc",
528 __func__);
529 dp_tx_free_remaining_tso_desc(soc, msdu_info, false);
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700530
531 return QDF_STATUS_E_NOMEM;
532 }
533
Ishank Jain5122f8f2017-03-15 22:22:47 +0530534 msdu_info->num_seg =
535 qdf_nbuf_get_tso_info(soc->osdev, msdu, tso_info);
536
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700537 TSO_DEBUG(" %s: msdu_info->num_seg: %d", __func__,
538 msdu_info->num_seg);
539
540 if (!(msdu_info->num_seg)) {
Jinwei Chen73e0dd52018-11-26 14:11:36 +0800541 /*
542 * Free allocated TSO seg desc and number seg desc,
543 * do unmap for segments if dma map has done.
544 */
545 DP_TRACE(ERROR, "%s: Failed to get tso info", __func__);
546 dp_tx_free_remaining_tso_desc(soc, msdu_info, true);
547
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700548 return QDF_STATUS_E_INVAL;
549 }
550
Ishank Jain5122f8f2017-03-15 22:22:47 +0530551 tso_info->curr_seg = tso_info->tso_seg_list;
552
553 return QDF_STATUS_SUCCESS;
554}
555#else
556static QDF_STATUS dp_tx_prepare_tso(struct dp_vdev *vdev,
557 qdf_nbuf_t msdu, struct dp_tx_msdu_info_s *msdu_info)
558{
559 return QDF_STATUS_E_NOMEM;
560}
561#endif
562
563/**
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530564 * dp_tx_prepare_ext_desc() - Allocate and prepare MSDU extension descriptor
565 * @vdev: DP Vdev handle
566 * @msdu_info: MSDU info to be setup in MSDU extension descriptor
567 * @desc_pool_id: Descriptor Pool ID
568 *
569 * Return:
570 */
Jeff Johnson755f2612017-01-05 16:28:13 -0800571static
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530572struct dp_tx_ext_desc_elem_s *dp_tx_prepare_ext_desc(struct dp_vdev *vdev,
573 struct dp_tx_msdu_info_s *msdu_info, uint8_t desc_pool_id)
574{
575 uint8_t i;
Ishank Jain2f81e962017-01-23 22:42:37 +0530576 uint8_t cached_ext_desc[HAL_TX_EXT_DESC_WITH_META_DATA];
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530577 struct dp_tx_seg_info_s *seg_info;
578 struct dp_tx_ext_desc_elem_s *msdu_ext_desc;
579 struct dp_soc *soc = vdev->pdev->soc;
580
581 /* Allocate an extension descriptor */
582 msdu_ext_desc = dp_tx_ext_desc_alloc(soc, desc_pool_id);
Ishank Jain2f81e962017-01-23 22:42:37 +0530583 qdf_mem_zero(&cached_ext_desc[0], HAL_TX_EXT_DESC_WITH_META_DATA);
Ishank Jain5122f8f2017-03-15 22:22:47 +0530584
Ishank Jain57c42a12017-04-12 10:42:22 +0530585 if (!msdu_ext_desc) {
Ruchi, Agrawalc3e68bc2018-07-16 16:45:34 +0530586 DP_STATS_INC(vdev, tx_i.dropped.desc_na.num, 1);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530587 return NULL;
Ishank Jain57c42a12017-04-12 10:42:22 +0530588 }
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530589
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +0530590 if (msdu_info->exception_fw &&
591 qdf_unlikely(vdev->mesh_vdev)) {
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +0530592 qdf_mem_copy(&cached_ext_desc[HAL_TX_EXTENSION_DESC_LEN_BYTES],
593 &msdu_info->meta_data[0],
594 sizeof(struct htt_tx_msdu_desc_ext2_t));
595 qdf_atomic_inc(&vdev->pdev->num_tx_exception);
Venkateswara Swamy Bandaru97ca7e92018-04-27 18:30:10 +0530596 }
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +0530597
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530598 switch (msdu_info->frm_type) {
599 case dp_tx_frm_sg:
600 case dp_tx_frm_me:
601 case dp_tx_frm_raw:
602 seg_info = msdu_info->u.sg_info.curr_seg;
603 /* Update the buffer pointers in MSDU Extension Descriptor */
604 for (i = 0; i < seg_info->frag_cnt; i++) {
605 hal_tx_ext_desc_set_buffer(&cached_ext_desc[0], i,
606 seg_info->frags[i].paddr_lo,
607 seg_info->frags[i].paddr_hi,
608 seg_info->frags[i].len);
609 }
610
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530611 break;
612
613 case dp_tx_frm_tso:
Ishank Jain5122f8f2017-03-15 22:22:47 +0530614 dp_tx_prepare_tso_ext_desc(&msdu_info->u.tso_info.curr_seg->seg,
615 &cached_ext_desc[0]);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530616 break;
617
Ishank Jain5122f8f2017-03-15 22:22:47 +0530618
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530619 default:
620 break;
621 }
622
Yun Park11d46e02017-11-27 10:51:53 -0800623 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
624 cached_ext_desc, HAL_TX_EXT_DESC_WITH_META_DATA);
Ishank Jain5122f8f2017-03-15 22:22:47 +0530625
626 hal_tx_ext_desc_sync(&cached_ext_desc[0],
627 msdu_ext_desc->vaddr);
628
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530629 return msdu_ext_desc;
630}
631
632/**
Mohit Khanna163c3172018-06-27 01:34:02 -0700633 * dp_tx_trace_pkt() - Trace TX packet at DP layer
634 *
635 * @skb: skb to be traced
636 * @msdu_id: msdu_id of the packet
637 * @vdev_id: vdev_id of the packet
638 *
639 * Return: None
640 */
641static void dp_tx_trace_pkt(qdf_nbuf_t skb, uint16_t msdu_id,
642 uint8_t vdev_id)
643{
644 QDF_NBUF_CB_TX_PACKET_TRACK(skb) = QDF_NBUF_TX_PKT_DATA_TRACK;
645 QDF_NBUF_CB_TX_DP_TRACE(skb) = 1;
646 DPTRACE(qdf_dp_trace_ptr(skb,
647 QDF_DP_TRACE_LI_DP_TX_PACKET_PTR_RECORD,
648 QDF_TRACE_DEFAULT_PDEV_ID,
649 qdf_nbuf_data_addr(skb),
650 sizeof(qdf_nbuf_data(skb)),
651 msdu_id, vdev_id));
652
653 qdf_dp_trace_log_pkt(vdev_id, skb, QDF_TX, QDF_TRACE_DEFAULT_PDEV_ID);
654
655 DPTRACE(qdf_dp_trace_data_pkt(skb, QDF_TRACE_DEFAULT_PDEV_ID,
656 QDF_DP_TRACE_LI_DP_TX_PACKET_RECORD,
657 msdu_id, QDF_TX));
658}
659
Shashikala Prabhu550e69c2019-03-13 17:41:17 +0530660#ifdef QCA_512M_CONFIG
661/**
662 * dp_tx_pdev_pflow_control - Check if allocated tx descriptors reached max
663 * tx descriptor configured value
664 * @vdev: DP vdev handle
665 *
666 * Return: true if allocated tx descriptors reached max configured value, else
667 * false.
668 */
669static inline bool
670dp_tx_pdev_pflow_control(struct dp_vdev *vdev)
671{
672 struct dp_pdev *pdev = vdev->pdev;
673
674 if (qdf_atomic_read(&pdev->num_tx_outstanding) >=
675 pdev->num_tx_allowed) {
676 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
677 "%s: queued packets are more than max tx, drop the frame",
678 __func__);
679 DP_STATS_INC(vdev, tx_i.dropped.desc_na.num, 1);
680 return true;
681 }
682
683 return false;
684}
685#else
686static inline bool
687dp_tx_pdev_pflow_control(struct dp_vdev *vdev)
688{
689 return false;
690}
691#endif
692
Mohit Khanna163c3172018-06-27 01:34:02 -0700693/**
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530694 * dp_tx_desc_prepare_single - Allocate and prepare Tx descriptor
695 * @vdev: DP vdev handle
696 * @nbuf: skb
697 * @desc_pool_id: Descriptor pool ID
Prathyusha Guduribe41d972018-01-19 14:17:14 +0530698 * @meta_data: Metadata to the fw
699 * @tx_exc_metadata: Handle that holds exception path metadata
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530700 * Allocate and prepare Tx descriptor with msdu information.
701 *
702 * Return: Pointer to Tx Descriptor on success,
703 * NULL on failure
704 */
Jeff Johnson755f2612017-01-05 16:28:13 -0800705static
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530706struct dp_tx_desc_s *dp_tx_prepare_desc_single(struct dp_vdev *vdev,
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +0530707 qdf_nbuf_t nbuf, uint8_t desc_pool_id,
708 struct dp_tx_msdu_info_s *msdu_info,
Prathyusha Guduribe41d972018-01-19 14:17:14 +0530709 struct cdp_tx_exception_metadata *tx_exc_metadata)
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530710{
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530711 uint8_t align_pad;
Dhanashri Atre10a93232016-11-11 18:47:05 -0800712 uint8_t is_exception = 0;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530713 uint8_t htt_hdr_size;
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -0800714 qdf_ether_header_t *eh;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530715 struct dp_tx_desc_s *tx_desc;
716 struct dp_pdev *pdev = vdev->pdev;
717 struct dp_soc *soc = pdev->soc;
718
Shashikala Prabhu550e69c2019-03-13 17:41:17 +0530719 if (dp_tx_pdev_pflow_control(vdev))
720 return NULL;
721
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530722 /* Allocate software Tx descriptor */
723 tx_desc = dp_tx_desc_alloc(soc, desc_pool_id);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530724 if (qdf_unlikely(!tx_desc)) {
Ruchi, Agrawalc3e68bc2018-07-16 16:45:34 +0530725 DP_STATS_INC(vdev, tx_i.dropped.desc_na.num, 1);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530726 return NULL;
727 }
728
729 /* Flow control/Congestion Control counters */
Vijay Pamidipati4d5d4362017-02-09 22:49:00 +0530730 qdf_atomic_inc(&pdev->num_tx_outstanding);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530731
732 /* Initialize the SW tx descriptor */
733 tx_desc->nbuf = nbuf;
734 tx_desc->frm_type = dp_tx_frm_std;
Prathyusha Guduribe41d972018-01-19 14:17:14 +0530735 tx_desc->tx_encap_type = (tx_exc_metadata ?
736 tx_exc_metadata->tx_encap_type : vdev->tx_encap_type);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530737 tx_desc->vdev = vdev;
Ravi Joshiab33d9b2017-02-11 21:43:28 -0800738 tx_desc->pdev = pdev;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530739 tx_desc->msdu_ext_desc = NULL;
Pamidipati, Vijay871850e2017-11-05 16:18:25 +0530740 tx_desc->pkt_offset = 0;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530741
Mohit Khanna163c3172018-06-27 01:34:02 -0700742 dp_tx_trace_pkt(nbuf, tx_desc->id, vdev->vdev_id);
743
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530744 /*
745 * For special modes (vdev_type == ocb or mesh), data frames should be
746 * transmitted using varying transmit parameters (tx spec) which include
747 * transmit rate, power, priority, channel, channel bandwidth , nss etc.
748 * These are filled in HTT MSDU descriptor and sent in frame pre-header.
749 * These frames are sent as exception packets to firmware.
Pamidipati, Vijay8a4e27c2017-04-06 01:04:08 +0530750 *
Pamidipati, Vijay871850e2017-11-05 16:18:25 +0530751 * HW requirement is that metadata should always point to a
752 * 8-byte aligned address. So we add alignment pad to start of buffer.
Pamidipati, Vijay8a4e27c2017-04-06 01:04:08 +0530753 * HTT Metadata should be ensured to be multiple of 8-bytes,
Pamidipati, Vijay871850e2017-11-05 16:18:25 +0530754 * to get 8-byte aligned start address along with align_pad added
Pamidipati, Vijay8a4e27c2017-04-06 01:04:08 +0530755 *
756 * |-----------------------------|
757 * | |
758 * |-----------------------------| <-----Buffer Pointer Address given
759 * | | ^ in HW descriptor (aligned)
760 * | HTT Metadata | |
761 * | | |
762 * | | | Packet Offset given in descriptor
763 * | | |
764 * |-----------------------------| |
765 * | Alignment Pad | v
766 * |-----------------------------| <----- Actual buffer start address
767 * | SKB Data | (Unaligned)
768 * | |
769 * | |
770 * | |
771 * | |
772 * | |
773 * |-----------------------------|
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530774 */
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +0530775 if (qdf_unlikely((msdu_info->exception_fw)) ||
776 (vdev->opmode == wlan_op_mode_ocb)) {
Pamidipati, Vijay871850e2017-11-05 16:18:25 +0530777 align_pad = ((unsigned long) qdf_nbuf_data(nbuf)) & 0x7;
Venkateswara Swamy Bandaru41ebb332018-09-12 18:25:29 +0530778
779 if (qdf_unlikely(qdf_nbuf_headroom(nbuf) < align_pad)) {
780 DP_STATS_INC(vdev,
781 tx_i.dropped.headroom_insufficient, 1);
782 goto failure;
783 }
784
Pamidipati, Vijay871850e2017-11-05 16:18:25 +0530785 if (qdf_nbuf_push_head(nbuf, align_pad) == NULL) {
786 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +0530787 "qdf_nbuf_push_head failed");
Pamidipati, Vijay871850e2017-11-05 16:18:25 +0530788 goto failure;
789 }
790
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530791 htt_hdr_size = dp_tx_prepare_htt_metadata(vdev, nbuf,
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +0530792 msdu_info->meta_data);
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +0530793 if (htt_hdr_size == 0)
794 goto failure;
Pamidipati, Vijay871850e2017-11-05 16:18:25 +0530795 tx_desc->pkt_offset = align_pad + htt_hdr_size;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530796 tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW;
Dhanashri Atre10a93232016-11-11 18:47:05 -0800797 is_exception = 1;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530798 }
799
Pamidipati, Vijay8a4e27c2017-04-06 01:04:08 +0530800 if (qdf_unlikely(QDF_STATUS_SUCCESS !=
801 qdf_nbuf_map(soc->osdev, nbuf,
802 QDF_DMA_TO_DEVICE))) {
803 /* Handle failure */
804 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +0530805 "qdf_nbuf_map failed");
Ishank Jain57c42a12017-04-12 10:42:22 +0530806 DP_STATS_INC(vdev, tx_i.dropped.dma_error, 1);
Pamidipati, Vijay8a4e27c2017-04-06 01:04:08 +0530807 goto failure;
808 }
809
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530810 if (qdf_unlikely(vdev->nawds_enabled)) {
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -0800811 eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530812 if (DP_FRAME_IS_MULTICAST((eh)->ether_dhost)) {
813 tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW;
Dhanashri Atre10a93232016-11-11 18:47:05 -0800814 is_exception = 1;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530815 }
816 }
817
Dhanashri Atre10a93232016-11-11 18:47:05 -0800818#if !TQM_BYPASS_WAR
Prathyusha Guduribe41d972018-01-19 14:17:14 +0530819 if (is_exception || tx_exc_metadata)
Dhanashri Atre10a93232016-11-11 18:47:05 -0800820#endif
821 {
822 /* Temporary WAR due to TQM VP issues */
823 tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW;
Vijay Pamidipati4d5d4362017-02-09 22:49:00 +0530824 qdf_atomic_inc(&pdev->num_tx_exception);
Dhanashri Atre10a93232016-11-11 18:47:05 -0800825 }
826
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530827 return tx_desc;
828
829failure:
Ravi Joshiab33d9b2017-02-11 21:43:28 -0800830 dp_tx_desc_release(tx_desc, desc_pool_id);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530831 return NULL;
832}
833
834/**
Ishank Jain5122f8f2017-03-15 22:22:47 +0530835 * dp_tx_prepare_desc() - Allocate and prepare Tx descriptor for multisegment frame
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530836 * @vdev: DP vdev handle
837 * @nbuf: skb
838 * @msdu_info: Info to be setup in MSDU descriptor and MSDU extension descriptor
839 * @desc_pool_id : Descriptor Pool ID
840 *
841 * Allocate and prepare Tx descriptor with msdu and fragment descritor
842 * information. For frames wth fragments, allocate and prepare
843 * an MSDU extension descriptor
844 *
845 * Return: Pointer to Tx Descriptor on success,
846 * NULL on failure
847 */
Jeff Johnson755f2612017-01-05 16:28:13 -0800848static struct dp_tx_desc_s *dp_tx_prepare_desc(struct dp_vdev *vdev,
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530849 qdf_nbuf_t nbuf, struct dp_tx_msdu_info_s *msdu_info,
850 uint8_t desc_pool_id)
851{
852 struct dp_tx_desc_s *tx_desc;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530853 struct dp_tx_ext_desc_elem_s *msdu_ext_desc;
854 struct dp_pdev *pdev = vdev->pdev;
855 struct dp_soc *soc = pdev->soc;
856
Shashikala Prabhu550e69c2019-03-13 17:41:17 +0530857 if (dp_tx_pdev_pflow_control(vdev))
858 return NULL;
859
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530860 /* Allocate software Tx descriptor */
861 tx_desc = dp_tx_desc_alloc(soc, desc_pool_id);
Ishank Jain57c42a12017-04-12 10:42:22 +0530862 if (!tx_desc) {
Ruchi, Agrawalc3e68bc2018-07-16 16:45:34 +0530863 DP_STATS_INC(vdev, tx_i.dropped.desc_na.num, 1);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530864 return NULL;
Ishank Jain57c42a12017-04-12 10:42:22 +0530865 }
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530866
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530867 /* Flow control/Congestion Control counters */
Vijay Pamidipati4d5d4362017-02-09 22:49:00 +0530868 qdf_atomic_inc(&pdev->num_tx_outstanding);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530869
870 /* Initialize the SW tx descriptor */
871 tx_desc->nbuf = nbuf;
872 tx_desc->frm_type = msdu_info->frm_type;
873 tx_desc->tx_encap_type = vdev->tx_encap_type;
874 tx_desc->vdev = vdev;
Ravi Joshiab33d9b2017-02-11 21:43:28 -0800875 tx_desc->pdev = pdev;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530876 tx_desc->pkt_offset = 0;
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -0700877 tx_desc->tso_desc = msdu_info->u.tso_info.curr_seg;
878 tx_desc->tso_num_desc = msdu_info->u.tso_info.tso_num_seg_list;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530879
Mohit Khanna163c3172018-06-27 01:34:02 -0700880 dp_tx_trace_pkt(nbuf, tx_desc->id, vdev->vdev_id);
881
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530882 /* Handle scattered frames - TSO/SG/ME */
883 /* Allocate and prepare an extension descriptor for scattered frames */
884 msdu_ext_desc = dp_tx_prepare_ext_desc(vdev, msdu_info, desc_pool_id);
885 if (!msdu_ext_desc) {
886 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
Aditya Sathishded018e2018-07-02 16:25:21 +0530887 "%s Tx Extension Descriptor Alloc Fail",
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530888 __func__);
889 goto failure;
890 }
891
Dhanashri Atre10a93232016-11-11 18:47:05 -0800892#if TQM_BYPASS_WAR
893 /* Temporary WAR due to TQM VP issues */
894 tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW;
Vijay Pamidipati4d5d4362017-02-09 22:49:00 +0530895 qdf_atomic_inc(&pdev->num_tx_exception);
Dhanashri Atre10a93232016-11-11 18:47:05 -0800896#endif
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +0530897 if (qdf_unlikely(msdu_info->exception_fw))
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +0530898 tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW;
Dhanashri Atre10a93232016-11-11 18:47:05 -0800899
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530900 tx_desc->msdu_ext_desc = msdu_ext_desc;
901 tx_desc->flags |= DP_TX_DESC_FLAG_FRAG;
902
903 return tx_desc;
904failure:
Ravi Joshiab33d9b2017-02-11 21:43:28 -0800905 dp_tx_desc_release(tx_desc, desc_pool_id);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530906 return NULL;
907}
908
909/**
Venkateswara Swamy Bandaru99075962016-12-27 11:55:15 +0530910 * dp_tx_prepare_raw() - Prepare RAW packet TX
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530911 * @vdev: DP vdev handle
912 * @nbuf: buffer pointer
Venkateswara Swamy Bandaru99075962016-12-27 11:55:15 +0530913 * @seg_info: Pointer to Segment info Descriptor to be prepared
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530914 * @msdu_info: MSDU info to be setup in MSDU descriptor and MSDU extension
915 * descriptor
916 *
917 * Return:
918 */
Jeff Johnson755f2612017-01-05 16:28:13 -0800919static qdf_nbuf_t dp_tx_prepare_raw(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
Venkateswara Swamy Bandaru99075962016-12-27 11:55:15 +0530920 struct dp_tx_seg_info_s *seg_info, struct dp_tx_msdu_info_s *msdu_info)
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530921{
Venkateswara Swamy Bandaru99075962016-12-27 11:55:15 +0530922 qdf_nbuf_t curr_nbuf = NULL;
923 uint16_t total_len = 0;
Pamidipati, Vijayda917d52017-07-18 20:13:22 +0530924 qdf_dma_addr_t paddr;
Venkateswara Swamy Bandaru99075962016-12-27 11:55:15 +0530925 int32_t i;
Ruchi, Agrawald8532ff2017-12-15 15:50:22 +0530926 int32_t mapped_buf_num = 0;
Venkateswara Swamy Bandaru99075962016-12-27 11:55:15 +0530927
928 struct dp_tx_sg_info_s *sg_info = &msdu_info->u.sg_info;
Sathish Kumare7e784d2017-05-04 16:24:22 +0530929 qdf_dot3_qosframe_t *qos_wh = (qdf_dot3_qosframe_t *) nbuf->data;
Venkateswara Swamy Bandaru99075962016-12-27 11:55:15 +0530930
Ishank Jain57c42a12017-04-12 10:42:22 +0530931 DP_STATS_INC_PKT(vdev, tx_i.raw.raw_pkt, 1, qdf_nbuf_len(nbuf));
932
Sathish Kumare7e784d2017-05-04 16:24:22 +0530933 /* SWAR for HW: Enable WEP bit in the AMSDU frames for RAW mode */
Venkateswara Swamy Bandaru6ca41122018-08-03 16:07:06 +0530934 if (vdev->raw_mode_war &&
Pamidipati, Vijay480c9312018-06-25 20:12:49 +0530935 (qos_wh->i_fc[0] & QDF_IEEE80211_FC0_SUBTYPE_QOS) &&
936 (qos_wh->i_qos[0] & IEEE80211_QOS_AMSDU))
Sathish Kumare7e784d2017-05-04 16:24:22 +0530937 qos_wh->i_fc[1] |= IEEE80211_FC1_WEP;
Sathish Kumare7e784d2017-05-04 16:24:22 +0530938
Venkateswara Swamy Bandaru99075962016-12-27 11:55:15 +0530939 for (curr_nbuf = nbuf, i = 0; curr_nbuf;
Ruchi, Agrawald8532ff2017-12-15 15:50:22 +0530940 curr_nbuf = qdf_nbuf_next(curr_nbuf), i++) {
941
942 if (QDF_STATUS_SUCCESS != qdf_nbuf_map(vdev->osdev, curr_nbuf,
943 QDF_DMA_TO_DEVICE)) {
944 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +0530945 "%s dma map error ", __func__);
Ruchi, Agrawald8532ff2017-12-15 15:50:22 +0530946 DP_STATS_INC(vdev, tx_i.raw.dma_map_error, 1);
947 mapped_buf_num = i;
948 goto error;
949 }
950
Pamidipati, Vijayda917d52017-07-18 20:13:22 +0530951 paddr = qdf_nbuf_get_frag_paddr(curr_nbuf, 0);
952 seg_info->frags[i].paddr_lo = paddr;
953 seg_info->frags[i].paddr_hi = ((uint64_t)paddr >> 32);
Venkateswara Swamy Bandaru99075962016-12-27 11:55:15 +0530954 seg_info->frags[i].len = qdf_nbuf_len(curr_nbuf);
955 seg_info->frags[i].vaddr = (void *) curr_nbuf;
956 total_len += qdf_nbuf_len(curr_nbuf);
957 }
958
959 seg_info->frag_cnt = i;
960 seg_info->total_len = total_len;
961 seg_info->next = NULL;
962
963 sg_info->curr_seg = seg_info;
964
965 msdu_info->frm_type = dp_tx_frm_raw;
966 msdu_info->num_seg = 1;
967
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530968 return nbuf;
Ruchi, Agrawald8532ff2017-12-15 15:50:22 +0530969
970error:
971 i = 0;
972 while (nbuf) {
973 curr_nbuf = nbuf;
974 if (i < mapped_buf_num) {
975 qdf_nbuf_unmap(vdev->osdev, curr_nbuf, QDF_DMA_TO_DEVICE);
976 i++;
977 }
978 nbuf = qdf_nbuf_next(nbuf);
979 qdf_nbuf_free(curr_nbuf);
980 }
981 return NULL;
982
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530983}
984
985/**
986 * dp_tx_hw_enqueue() - Enqueue to TCL HW for transmit
987 * @soc: DP Soc Handle
988 * @vdev: DP vdev handle
989 * @tx_desc: Tx Descriptor Handle
990 * @tid: TID from HLOS for overriding default DSCP-TID mapping
991 * @fw_metadata: Metadata to send to Target Firmware along with frame
992 * @ring_id: Ring ID of H/W ring to which we enqueue the packet
Prathyusha Guduribe41d972018-01-19 14:17:14 +0530993 * @tx_exc_metadata: Handle that holds exception path meta data
Pamidipati, Vijay576bd152016-09-27 20:58:18 +0530994 *
995 * Gets the next free TCL HW DMA descriptor and sets up required parameters
996 * from software Tx descriptor
997 *
998 * Return:
999 */
Jeff Johnson755f2612017-01-05 16:28:13 -08001000static QDF_STATUS dp_tx_hw_enqueue(struct dp_soc *soc, struct dp_vdev *vdev,
1001 struct dp_tx_desc_s *tx_desc, uint8_t tid,
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301002 uint16_t fw_metadata, uint8_t ring_id,
1003 struct cdp_tx_exception_metadata
1004 *tx_exc_metadata)
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301005{
1006 uint8_t type;
1007 uint16_t length;
1008 void *hal_tx_desc, *hal_tx_desc_cached;
1009 qdf_dma_addr_t dma_addr;
1010 uint8_t cached_desc[HAL_TX_DESC_LEN_BYTES];
1011
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301012 enum cdp_sec_type sec_type = (tx_exc_metadata ?
1013 tx_exc_metadata->sec_type : vdev->sec_type);
1014
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301015 /* Return Buffer Manager ID */
1016 uint8_t bm_id = ring_id;
1017 void *hal_srng = soc->tcl_data_ring[ring_id].hal_srng;
1018
1019 hal_tx_desc_cached = (void *) cached_desc;
Dustin Brownb5b21ca2019-03-01 15:20:58 -08001020 qdf_mem_zero(hal_tx_desc_cached, HAL_TX_DESC_LEN_BYTES);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301021
1022 if (tx_desc->flags & DP_TX_DESC_FLAG_FRAG) {
Pamidipati, Vijay110bf962017-03-24 21:38:20 +05301023 length = HAL_TX_EXT_DESC_WITH_META_DATA;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301024 type = HAL_TX_BUF_TYPE_EXT_DESC;
1025 dma_addr = tx_desc->msdu_ext_desc->paddr;
1026 } else {
Pamidipati, Vijay8a4e27c2017-04-06 01:04:08 +05301027 length = qdf_nbuf_len(tx_desc->nbuf) - tx_desc->pkt_offset;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301028 type = HAL_TX_BUF_TYPE_BUFFER;
Pamidipati, Vijay8a4e27c2017-04-06 01:04:08 +05301029 dma_addr = qdf_nbuf_mapped_paddr_get(tx_desc->nbuf);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301030 }
1031
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301032 hal_tx_desc_set_fw_metadata(hal_tx_desc_cached, fw_metadata);
1033 hal_tx_desc_set_buf_addr(hal_tx_desc_cached,
Balamurugan Mahalingam3715aa42018-08-22 02:13:14 +05301034 dma_addr, bm_id, tx_desc->id,
1035 type, soc->hal_soc);
Jinwei Chenfc765552018-05-18 13:27:32 +08001036
1037 if (!dp_tx_is_desc_id_valid(soc, tx_desc->id))
1038 return QDF_STATUS_E_RESOURCES;
1039
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301040 hal_tx_desc_set_buf_length(hal_tx_desc_cached, length);
1041 hal_tx_desc_set_buf_offset(hal_tx_desc_cached, tx_desc->pkt_offset);
1042 hal_tx_desc_set_encap_type(hal_tx_desc_cached, tx_desc->tx_encap_type);
Balamurugan Mahalingamd0159642018-07-11 15:02:29 +05301043 hal_tx_desc_set_lmac_id(soc->hal_soc, hal_tx_desc_cached,
Chaithanya Garrepalli1f64b242018-09-21 22:50:23 +05301044 vdev->pdev->lmac_id);
Chaithanya Garrepalli2467ed12018-09-11 23:57:43 +05301045 hal_tx_desc_set_search_type(soc->hal_soc, hal_tx_desc_cached,
1046 vdev->search_type);
1047 hal_tx_desc_set_search_index(soc->hal_soc, hal_tx_desc_cached,
1048 vdev->bss_ast_hash);
Balamurugan Mahalingamd0159642018-07-11 15:02:29 +05301049 hal_tx_desc_set_dscp_tid_table_id(soc->hal_soc, hal_tx_desc_cached,
1050 vdev->dscp_tid_map_id);
ruchi agrawal45f3ac42017-10-25 09:03:28 +05301051 hal_tx_desc_set_encrypt_type(hal_tx_desc_cached,
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301052 sec_type_map[sec_type]);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301053
Krunal Sonic96a1162019-02-21 11:33:26 -08001054 dp_verbose_debug("length:%d , type = %d, dma_addr %llx, offset %d desc id %u",
1055 length, type, (uint64_t)dma_addr,
1056 tx_desc->pkt_offset, tx_desc->id);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301057
1058 if (tx_desc->flags & DP_TX_DESC_FLAG_TO_FW)
1059 hal_tx_desc_set_to_fw(hal_tx_desc_cached, 1);
1060
Pamidipati, Vijayc9a13a52017-04-06 17:45:49 +05301061 hal_tx_desc_set_addr_search_flags(hal_tx_desc_cached,
1062 vdev->hal_desc_addr_search_flags);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301063
chenguo8d0c2192017-12-01 19:35:53 +08001064 /* verify checksum offload configuration*/
1065 if ((wlan_cfg_get_checksum_offload(soc->wlan_cfg_ctx)) &&
1066 ((qdf_nbuf_get_tx_cksum(tx_desc->nbuf) == QDF_NBUF_TX_CKSUM_TCP_UDP)
1067 || qdf_nbuf_is_tso(tx_desc->nbuf))) {
Ishank Jain5122f8f2017-03-15 22:22:47 +05301068 hal_tx_desc_set_l3_checksum_en(hal_tx_desc_cached, 1);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301069 hal_tx_desc_set_l4_checksum_en(hal_tx_desc_cached, 1);
Ishank Jain5122f8f2017-03-15 22:22:47 +05301070 }
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301071
1072 if (tid != HTT_TX_EXT_TID_INVALID)
1073 hal_tx_desc_set_hlos_tid(hal_tx_desc_cached, tid);
1074
1075 if (tx_desc->flags & DP_TX_DESC_FLAG_MESH)
1076 hal_tx_desc_set_mesh_en(hal_tx_desc_cached, 1);
1077
1078
Varsha Mishraa331e6e2019-03-11 12:16:14 +05301079 tx_desc->timestamp = qdf_ktime_to_ms(qdf_ktime_get());
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301080 /* Sync cached descriptor with HW */
1081 hal_tx_desc = hal_srng_src_get_next(soc->hal_soc, hal_srng);
1082
1083 if (!hal_tx_desc) {
Krunal Sonic96a1162019-02-21 11:33:26 -08001084 dp_verbose_debug("TCL ring full ring_id:%d", ring_id);
Ishank Jainbc2d91f2017-01-03 18:14:54 +05301085 DP_STATS_INC(soc, tx.tcl_ring_full[ring_id], 1);
Ishank Jain57c42a12017-04-12 10:42:22 +05301086 DP_STATS_INC(vdev, tx_i.dropped.enqueue_fail, 1);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301087 return QDF_STATUS_E_RESOURCES;
1088 }
1089
1090 tx_desc->flags |= DP_TX_DESC_FLAG_QUEUED_TX;
1091
1092 hal_tx_desc_sync(hal_tx_desc_cached, hal_tx_desc);
Ishank Jain1e7401c2017-02-17 15:38:39 +05301093 DP_STATS_INC_PKT(vdev, tx_i.processed, 1, length);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301094
1095 return QDF_STATUS_SUCCESS;
1096}
1097
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301098
1099/**
1100 * dp_cce_classify() - Classify the frame based on CCE rules
1101 * @vdev: DP vdev handle
1102 * @nbuf: skb
1103 *
1104 * Classify frames based on CCE rules
1105 * Return: bool( true if classified,
1106 * else false)
1107 */
Ruchi, Agrawal4c1468f2017-12-08 00:04:33 +05301108static bool dp_cce_classify(struct dp_vdev *vdev, qdf_nbuf_t nbuf)
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301109{
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08001110 qdf_ether_header_t *eh = NULL;
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301111 uint16_t ether_type;
1112 qdf_llc_t *llcHdr;
1113 qdf_nbuf_t nbuf_clone = NULL;
Ruchi, Agrawal4c1468f2017-12-08 00:04:33 +05301114 qdf_dot3_qosframe_t *qos_wh = NULL;
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301115
Ruchi, Agrawal4c1468f2017-12-08 00:04:33 +05301116 /* for mesh packets don't do any classification */
1117 if (qdf_unlikely(vdev->mesh_vdev))
1118 return false;
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301119
Ruchi, Agrawal4c1468f2017-12-08 00:04:33 +05301120 if (qdf_likely(vdev->tx_encap_type != htt_cmn_pkt_type_raw)) {
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08001121 eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf);
Ruchi, Agrawal4c1468f2017-12-08 00:04:33 +05301122 ether_type = eh->ether_type;
1123 llcHdr = (qdf_llc_t *)(nbuf->data +
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08001124 sizeof(qdf_ether_header_t));
Ruchi, Agrawal4c1468f2017-12-08 00:04:33 +05301125 } else {
1126 qos_wh = (qdf_dot3_qosframe_t *) nbuf->data;
Ruchi, Agrawalbd225402018-05-10 11:19:17 +05301127 /* For encrypted packets don't do any classification */
1128 if (qdf_unlikely(qos_wh->i_fc[1] & IEEE80211_FC1_WEP))
1129 return false;
Ruchi, Agrawal4c1468f2017-12-08 00:04:33 +05301130
1131 if (qdf_unlikely(qos_wh->i_fc[0] & QDF_IEEE80211_FC0_SUBTYPE_QOS)) {
1132 if (qdf_unlikely(
1133 qos_wh->i_fc[1] & QDF_IEEE80211_FC1_TODS &&
1134 qos_wh->i_fc[1] & QDF_IEEE80211_FC1_FROMDS)) {
1135
1136 ether_type = *(uint16_t *)(nbuf->data
1137 + QDF_IEEE80211_4ADDR_HDR_LEN
1138 + sizeof(qdf_llc_t)
1139 - sizeof(ether_type));
1140 llcHdr = (qdf_llc_t *)(nbuf->data +
1141 QDF_IEEE80211_4ADDR_HDR_LEN);
1142 } else {
1143 ether_type = *(uint16_t *)(nbuf->data
1144 + QDF_IEEE80211_3ADDR_HDR_LEN
1145 + sizeof(qdf_llc_t)
1146 - sizeof(ether_type));
1147 llcHdr = (qdf_llc_t *)(nbuf->data +
1148 QDF_IEEE80211_3ADDR_HDR_LEN);
1149 }
1150
1151 if (qdf_unlikely(DP_FRAME_IS_SNAP(llcHdr)
1152 && (ether_type ==
1153 qdf_htons(QDF_NBUF_TRAC_EAPOL_ETH_TYPE)))) {
1154
1155 DP_STATS_INC(vdev, tx_i.cce_classified_raw, 1);
1156 return true;
1157 }
1158 }
1159
1160 return false;
1161 }
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301162
1163 if (qdf_unlikely(DP_FRAME_IS_SNAP(llcHdr))) {
Srinivas Girigowda2751b6d2019-02-27 12:28:13 -08001164 ether_type = *(uint16_t *)(nbuf->data + 2*QDF_MAC_ADDR_SIZE +
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301165 sizeof(*llcHdr));
1166 nbuf_clone = qdf_nbuf_clone(nbuf);
Ruchi, Agrawal1ca70f02018-03-19 13:53:07 +05301167 if (qdf_unlikely(nbuf_clone)) {
1168 qdf_nbuf_pull_head(nbuf_clone, sizeof(*llcHdr));
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301169
Srinivas Girigowda99f2a292019-02-12 14:20:58 -08001170 if (ether_type == htons(ETHERTYPE_VLAN)) {
Ruchi, Agrawal1ca70f02018-03-19 13:53:07 +05301171 qdf_nbuf_pull_head(nbuf_clone,
Ruchi, Agrawal4c1468f2017-12-08 00:04:33 +05301172 sizeof(qdf_net_vlanhdr_t));
Ruchi, Agrawal1ca70f02018-03-19 13:53:07 +05301173 }
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301174 }
1175 } else {
Srinivas Girigowda99f2a292019-02-12 14:20:58 -08001176 if (ether_type == htons(ETHERTYPE_VLAN)) {
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301177 nbuf_clone = qdf_nbuf_clone(nbuf);
Ruchi, Agrawal1ca70f02018-03-19 13:53:07 +05301178 if (qdf_unlikely(nbuf_clone)) {
1179 qdf_nbuf_pull_head(nbuf_clone,
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301180 sizeof(qdf_net_vlanhdr_t));
Ruchi, Agrawal1ca70f02018-03-19 13:53:07 +05301181 }
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301182 }
1183 }
1184
1185 if (qdf_unlikely(nbuf_clone))
1186 nbuf = nbuf_clone;
1187
Ruchi, Agrawal4c1468f2017-12-08 00:04:33 +05301188
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301189 if (qdf_unlikely(qdf_nbuf_is_ipv4_eapol_pkt(nbuf)
1190 || qdf_nbuf_is_ipv4_arp_pkt(nbuf)
1191 || qdf_nbuf_is_ipv4_wapi_pkt(nbuf)
1192 || qdf_nbuf_is_ipv4_tdls_pkt(nbuf)
1193 || (qdf_nbuf_is_ipv4_pkt(nbuf)
1194 && qdf_nbuf_is_ipv4_dhcp_pkt(nbuf))
1195 || (qdf_nbuf_is_ipv6_pkt(nbuf) &&
1196 qdf_nbuf_is_ipv6_dhcp_pkt(nbuf)))) {
Jeff Johnsona8edf332019-03-18 09:51:52 -07001197 if (qdf_unlikely(nbuf_clone))
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301198 qdf_nbuf_free(nbuf_clone);
1199 return true;
1200 }
1201
Jeff Johnsona8edf332019-03-18 09:51:52 -07001202 if (qdf_unlikely(nbuf_clone))
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301203 qdf_nbuf_free(nbuf_clone);
1204
1205 return false;
1206}
1207
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301208/**
Varsha Mishra18281792019-03-06 17:57:23 +05301209 * dp_tx_get_tid() - Obtain TID to be used for this frame
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301210 * @vdev: DP vdev handle
1211 * @nbuf: skb
1212 *
1213 * Extract the DSCP or PCP information from frame and map into TID value.
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301214 *
Ishank Jain949674c2017-02-27 17:09:29 +05301215 * Return: void
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301216 */
Varsha Mishra18281792019-03-06 17:57:23 +05301217static void dp_tx_get_tid(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
1218 struct dp_tx_msdu_info_s *msdu_info)
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301219{
Ishank Jain949674c2017-02-27 17:09:29 +05301220 uint8_t tos = 0, dscp_tid_override = 0;
1221 uint8_t *hdr_ptr, *L3datap;
1222 uint8_t is_mcast = 0;
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08001223 qdf_ether_header_t *eh = NULL;
Ishank Jain949674c2017-02-27 17:09:29 +05301224 qdf_ethervlan_header_t *evh = NULL;
1225 uint16_t ether_type;
1226 qdf_llc_t *llcHdr;
1227 struct dp_pdev *pdev = (struct dp_pdev *)vdev->pdev;
1228
Neil Zhao48876362018-03-22 11:23:02 -07001229 DP_TX_TID_OVERRIDE(msdu_info, nbuf);
Ishank Jain949674c2017-02-27 17:09:29 +05301230 if (qdf_likely(vdev->tx_encap_type != htt_cmn_pkt_type_raw)) {
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08001231 eh = (qdf_ether_header_t *)nbuf->data;
Ishank Jain949674c2017-02-27 17:09:29 +05301232 hdr_ptr = eh->ether_dhost;
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08001233 L3datap = hdr_ptr + sizeof(qdf_ether_header_t);
Ishank Jain949674c2017-02-27 17:09:29 +05301234 } else {
1235 qdf_dot3_qosframe_t *qos_wh =
1236 (qdf_dot3_qosframe_t *) nbuf->data;
1237 msdu_info->tid = qos_wh->i_fc[0] & DP_FC0_SUBTYPE_QOS ?
1238 qos_wh->i_qos[0] & DP_QOS_TID : 0;
1239 return;
1240 }
1241
1242 is_mcast = DP_FRAME_IS_MULTICAST(hdr_ptr);
1243 ether_type = eh->ether_type;
Pamidipati, Vijay038d0902017-07-17 09:53:31 +05301244
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08001245 llcHdr = (qdf_llc_t *)(nbuf->data + sizeof(qdf_ether_header_t));
Ishank Jain949674c2017-02-27 17:09:29 +05301246 /*
1247 * Check if packet is dot3 or eth2 type.
1248 */
Pamidipati, Vijayef2cbc62017-09-27 23:09:06 +05301249 if (DP_FRAME_IS_LLC(ether_type) && DP_FRAME_IS_SNAP(llcHdr)) {
Srinivas Girigowda2751b6d2019-02-27 12:28:13 -08001250 ether_type = (uint16_t)*(nbuf->data + 2*QDF_MAC_ADDR_SIZE +
Ishank Jain949674c2017-02-27 17:09:29 +05301251 sizeof(*llcHdr));
1252
Srinivas Girigowda99f2a292019-02-12 14:20:58 -08001253 if (ether_type == htons(ETHERTYPE_VLAN)) {
Ishank Jain949674c2017-02-27 17:09:29 +05301254 L3datap = hdr_ptr + sizeof(qdf_ethervlan_header_t) +
1255 sizeof(*llcHdr);
Srinivas Girigowda2751b6d2019-02-27 12:28:13 -08001256 ether_type = (uint16_t)*(nbuf->data + 2*QDF_MAC_ADDR_SIZE
Ishank Jain949674c2017-02-27 17:09:29 +05301257 + sizeof(*llcHdr) +
1258 sizeof(qdf_net_vlanhdr_t));
1259 } else {
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08001260 L3datap = hdr_ptr + sizeof(qdf_ether_header_t) +
Ishank Jain949674c2017-02-27 17:09:29 +05301261 sizeof(*llcHdr);
1262 }
Ishank Jain949674c2017-02-27 17:09:29 +05301263 } else {
Srinivas Girigowda99f2a292019-02-12 14:20:58 -08001264 if (ether_type == htons(ETHERTYPE_VLAN)) {
Ishank Jain949674c2017-02-27 17:09:29 +05301265 evh = (qdf_ethervlan_header_t *) eh;
1266 ether_type = evh->ether_type;
1267 L3datap = hdr_ptr + sizeof(qdf_ethervlan_header_t);
1268 }
1269 }
Pamidipati, Vijay038d0902017-07-17 09:53:31 +05301270
Ishank Jain949674c2017-02-27 17:09:29 +05301271 /*
1272 * Find priority from IP TOS DSCP field
1273 */
1274 if (qdf_nbuf_is_ipv4_pkt(nbuf)) {
1275 qdf_net_iphdr_t *ip = (qdf_net_iphdr_t *) L3datap;
1276 if (qdf_nbuf_is_ipv4_dhcp_pkt(nbuf)) {
1277 /* Only for unicast frames */
1278 if (!is_mcast) {
1279 /* send it on VO queue */
1280 msdu_info->tid = DP_VO_TID;
1281 }
1282 } else {
1283 /*
1284 * IP frame: exclude ECN bits 0-1 and map DSCP bits 2-7
1285 * from TOS byte.
1286 */
1287 tos = ip->ip_tos;
1288 dscp_tid_override = 1;
1289
1290 }
1291 } else if (qdf_nbuf_is_ipv6_pkt(nbuf)) {
1292 /* TODO
1293 * use flowlabel
1294 *igmpmld cases to be handled in phase 2
1295 */
1296 unsigned long ver_pri_flowlabel;
1297 unsigned long pri;
1298 ver_pri_flowlabel = *(unsigned long *) L3datap;
1299 pri = (ntohl(ver_pri_flowlabel) & IPV6_FLOWINFO_PRIORITY) >>
1300 DP_IPV6_PRIORITY_SHIFT;
1301 tos = pri;
1302 dscp_tid_override = 1;
1303 } else if (qdf_nbuf_is_ipv4_eapol_pkt(nbuf))
1304 msdu_info->tid = DP_VO_TID;
1305 else if (qdf_nbuf_is_ipv4_arp_pkt(nbuf)) {
1306 /* Only for unicast frames */
1307 if (!is_mcast) {
1308 /* send ucast arp on VO queue */
1309 msdu_info->tid = DP_VO_TID;
1310 }
1311 }
1312
1313 /*
1314 * Assign all MCAST packets to BE
1315 */
1316 if (qdf_unlikely(vdev->tx_encap_type != htt_cmn_pkt_type_raw)) {
1317 if (is_mcast) {
1318 tos = 0;
1319 dscp_tid_override = 1;
1320 }
1321 }
1322
1323 if (dscp_tid_override == 1) {
1324 tos = (tos >> DP_IP_DSCP_SHIFT) & DP_IP_DSCP_MASK;
1325 msdu_info->tid = pdev->dscp_tid_map[vdev->dscp_tid_map_id][tos];
1326 }
Varsha Mishra18281792019-03-06 17:57:23 +05301327
1328 if (msdu_info->tid >= CDP_MAX_DATA_TIDS)
1329 msdu_info->tid = CDP_MAX_DATA_TIDS - 1;
1330
Ishank Jain949674c2017-02-27 17:09:29 +05301331 return;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301332}
1333
Varsha Mishra18281792019-03-06 17:57:23 +05301334/**
1335 * dp_tx_classify_tid() - Obtain TID to be used for this frame
1336 * @vdev: DP vdev handle
1337 * @nbuf: skb
1338 *
1339 * Software based TID classification is required when more than 2 DSCP-TID
1340 * mapping tables are needed.
1341 * Hardware supports 2 DSCP-TID mapping tables for HKv1 and 48 for HKv2.
1342 *
1343 * Return: void
1344 */
1345static void dp_tx_classify_tid(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
1346 struct dp_tx_msdu_info_s *msdu_info)
1347{
1348 struct dp_pdev *pdev = (struct dp_pdev *)vdev->pdev;
1349
1350 DP_TX_TID_OVERRIDE(msdu_info, nbuf);
1351
1352 if (pdev->soc && vdev->dscp_tid_map_id < pdev->soc->num_hw_dscp_tid_map)
1353 return;
1354
1355 /* for mesh packets don't do any classification */
1356 if (qdf_unlikely(vdev->mesh_vdev))
1357 return;
1358
1359 dp_tx_get_tid(vdev, nbuf, msdu_info);
1360}
1361
Jeff Johnson6889ddf2019-02-08 07:22:01 -08001362#ifdef FEATURE_WLAN_TDLS
Kabilan Kannan60e3b302017-09-07 20:06:17 -07001363/**
1364 * dp_tx_update_tdls_flags() - Update descriptor flags for TDLS frame
1365 * @tx_desc: TX descriptor
1366 *
1367 * Return: None
1368 */
1369static void dp_tx_update_tdls_flags(struct dp_tx_desc_s *tx_desc)
1370{
1371 if (tx_desc->vdev) {
jiad57286242018-11-02 15:47:57 +08001372 if (tx_desc->vdev->is_tdls_frame) {
Kabilan Kannan60e3b302017-09-07 20:06:17 -07001373 tx_desc->flags |= DP_TX_DESC_FLAG_TDLS_FRAME;
1374 tx_desc->vdev->is_tdls_frame = false;
jiad57286242018-11-02 15:47:57 +08001375 }
Kabilan Kannan60e3b302017-09-07 20:06:17 -07001376 }
1377}
1378
1379/**
1380 * dp_non_std_tx_comp_free_buff() - Free the non std tx packet buffer
1381 * @tx_desc: TX descriptor
1382 * @vdev: datapath vdev handle
1383 *
1384 * Return: None
1385 */
1386static void dp_non_std_tx_comp_free_buff(struct dp_tx_desc_s *tx_desc,
Jeff Johnson6889ddf2019-02-08 07:22:01 -08001387 struct dp_vdev *vdev)
Kabilan Kannan60e3b302017-09-07 20:06:17 -07001388{
1389 struct hal_tx_completion_status ts = {0};
1390 qdf_nbuf_t nbuf = tx_desc->nbuf;
1391
Jinwei Chen79b4fc82019-04-26 13:27:27 +08001392 if (qdf_unlikely(!vdev)) {
1393 dp_err("vdev is null!");
1394 return;
1395 }
1396
Balamurugan Mahalingam3715aa42018-08-22 02:13:14 +05301397 hal_tx_comp_get_status(&tx_desc->comp, &ts, vdev->pdev->soc->hal_soc);
Kabilan Kannan60e3b302017-09-07 20:06:17 -07001398 if (vdev->tx_non_std_data_callback.func) {
1399 qdf_nbuf_set_next(tx_desc->nbuf, NULL);
1400 vdev->tx_non_std_data_callback.func(
1401 vdev->tx_non_std_data_callback.ctxt,
1402 nbuf, ts.status);
1403 return;
1404 }
1405}
Jeff Johnson6889ddf2019-02-08 07:22:01 -08001406#else
1407static inline void dp_tx_update_tdls_flags(struct dp_tx_desc_s *tx_desc)
1408{
1409}
1410
1411static inline void dp_non_std_tx_comp_free_buff(struct dp_tx_desc_s *tx_desc,
1412 struct dp_vdev *vdev)
1413{
1414}
Kabilan Kannan60e3b302017-09-07 20:06:17 -07001415#endif
1416
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301417/**
1418 * dp_tx_send_msdu_single() - Setup descriptor and enqueue single MSDU to TCL
1419 * @vdev: DP vdev handle
1420 * @nbuf: skb
1421 * @tid: TID from HLOS for overriding default DSCP-TID mapping
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301422 * @meta_data: Metadata to the fw
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301423 * @tx_q: Tx queue to be used for this Tx frame
Ishank Jain9f174c62017-03-30 18:37:42 +05301424 * @peer_id: peer_id of the peer in case of NAWDS frames
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301425 * @tx_exc_metadata: Handle that holds exception path metadata
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301426 *
1427 * Return: NULL on success,
1428 * nbuf when it fails to send
1429 */
Jeff Johnson755f2612017-01-05 16:28:13 -08001430static qdf_nbuf_t dp_tx_send_msdu_single(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05301431 struct dp_tx_msdu_info_s *msdu_info, uint16_t peer_id,
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301432 struct cdp_tx_exception_metadata *tx_exc_metadata)
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301433{
1434 struct dp_pdev *pdev = vdev->pdev;
1435 struct dp_soc *soc = pdev->soc;
1436 struct dp_tx_desc_s *tx_desc;
1437 QDF_STATUS status;
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05301438 struct dp_tx_queue *tx_q = &(msdu_info->tx_queue);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301439 void *hal_srng = soc->tcl_data_ring[tx_q->ring_id].hal_srng;
Ishank Jain9f174c62017-03-30 18:37:42 +05301440 uint16_t htt_tcl_metadata = 0;
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05301441 uint8_t tid = msdu_info->tid;
Varsha Mishra18281792019-03-06 17:57:23 +05301442 struct cdp_tid_tx_stats *tid_stats = NULL;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301443
1444 /* Setup Tx descriptor for an MSDU, and MSDU extension descriptor */
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301445 tx_desc = dp_tx_prepare_desc_single(vdev, nbuf, tx_q->desc_pool_id,
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05301446 msdu_info, tx_exc_metadata);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301447 if (!tx_desc) {
Mohit Khanna6d22eeb2019-04-06 22:51:26 -07001448 dp_err_rl("Tx_desc prepare Fail vdev %pK queue %d",
1449 vdev, tx_q->desc_pool_id);
Varsha Mishra18281792019-03-06 17:57:23 +05301450 dp_tx_get_tid(vdev, nbuf, msdu_info);
1451 tid_stats = &pdev->stats.tid_stats.tid_tx_stats[msdu_info->tid];
1452 tid_stats->swdrop_cnt[TX_DESC_ERR]++;
Pamidipati, Vijayfc779602017-08-07 17:58:19 +05301453 return nbuf;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301454 }
1455
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301456 if (qdf_unlikely(soc->cce_disable)) {
Ruchi, Agrawal4c1468f2017-12-08 00:04:33 +05301457 if (dp_cce_classify(vdev, nbuf) == true) {
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301458 DP_STATS_INC(vdev, tx_i.cce_classified, 1);
1459 tid = DP_VO_TID;
1460 tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW;
1461 }
1462 }
1463
Kabilan Kannan60e3b302017-09-07 20:06:17 -07001464 dp_tx_update_tdls_flags(tx_desc);
1465
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301466 if (qdf_unlikely(hal_srng_access_start(soc->hal_soc, hal_srng))) {
1467 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +05301468 "%s %d : HAL RING Access Failed -- %pK",
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301469 __func__, __LINE__, hal_srng);
Varsha Mishra18281792019-03-06 17:57:23 +05301470 dp_tx_get_tid(vdev, nbuf, msdu_info);
1471 tid_stats = &pdev->stats.tid_stats.tid_tx_stats[msdu_info->tid];
1472 tid_stats->swdrop_cnt[TX_HAL_RING_ACCESS_ERR]++;
Ishank Jain1e7401c2017-02-17 15:38:39 +05301473 DP_STATS_INC(vdev, tx_i.dropped.ring_full, 1);
Venkata Sharath Chandra Manchala532cd5f2017-04-24 11:15:30 -07001474 dp_tx_desc_release(tx_desc, tx_q->desc_pool_id);
chenguo60e6dd92018-11-30 20:20:47 +08001475 qdf_nbuf_unmap(vdev->osdev, nbuf, QDF_DMA_TO_DEVICE);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301476 goto fail_return;
1477 }
1478
Ruchi, Agrawalbd894b32017-11-03 17:24:56 +05301479 if (qdf_unlikely(peer_id == DP_INVALID_PEER)) {
1480 htt_tcl_metadata = vdev->htt_tcl_metadata;
1481 HTT_TX_TCL_METADATA_HOST_INSPECTED_SET(htt_tcl_metadata, 1);
1482 } else if (qdf_unlikely(peer_id != HTT_INVALID_PEER)) {
Ishank Jain9f174c62017-03-30 18:37:42 +05301483 HTT_TX_TCL_METADATA_TYPE_SET(htt_tcl_metadata,
1484 HTT_TCL_METADATA_TYPE_PEER_BASED);
1485 HTT_TX_TCL_METADATA_PEER_ID_SET(htt_tcl_metadata,
1486 peer_id);
1487 } else
1488 htt_tcl_metadata = vdev->htt_tcl_metadata;
1489
Venkateswara Swamy Bandaru97ca7e92018-04-27 18:30:10 +05301490
1491 if (msdu_info->exception_fw) {
1492 HTT_TX_TCL_METADATA_VALID_HTT_SET(htt_tcl_metadata, 1);
1493 }
1494
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301495 /* Enqueue the Tx MSDU descriptor to HW for transmit */
1496 status = dp_tx_hw_enqueue(soc, vdev, tx_desc, tid,
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301497 htt_tcl_metadata, tx_q->ring_id, tx_exc_metadata);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301498
1499 if (status != QDF_STATUS_SUCCESS) {
1500 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +05301501 "%s Tx_hw_enqueue Fail tx_desc %pK queue %d",
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301502 __func__, tx_desc, tx_q->ring_id);
Varsha Mishra18281792019-03-06 17:57:23 +05301503 dp_tx_get_tid(vdev, nbuf, msdu_info);
1504 tid_stats = &pdev->stats.tid_stats.tid_tx_stats[msdu_info->tid];
1505 tid_stats->swdrop_cnt[TX_HW_ENQUEUE]++;
Ravi Joshiab33d9b2017-02-11 21:43:28 -08001506 dp_tx_desc_release(tx_desc, tx_q->desc_pool_id);
chenguo60e6dd92018-11-30 20:20:47 +08001507 qdf_nbuf_unmap(vdev->osdev, nbuf, QDF_DMA_TO_DEVICE);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301508 goto fail_return;
1509 }
1510
Pamidipati, Vijayf82fb2b2017-06-28 05:31:50 +05301511 nbuf = NULL;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301512
1513fail_return:
Yue Ma245b47b2017-02-21 16:35:31 -08001514 if (hif_pm_runtime_get(soc->hif_handle) == 0) {
1515 hal_srng_access_end(soc->hal_soc, hal_srng);
1516 hif_pm_runtime_put(soc->hif_handle);
1517 } else {
1518 hal_srng_access_end_reap(soc->hal_soc, hal_srng);
1519 }
1520
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301521 return nbuf;
1522}
1523
1524/**
1525 * dp_tx_send_msdu_multiple() - Enqueue multiple MSDUs
1526 * @vdev: DP vdev handle
1527 * @nbuf: skb
1528 * @msdu_info: MSDU info to be setup in MSDU extension descriptor
1529 *
1530 * Prepare descriptors for multiple MSDUs (TSO segments) and enqueue to TCL
1531 *
1532 * Return: NULL on success,
1533 * nbuf when it fails to send
1534 */
Houston Hoffmanaa12e042017-01-30 14:34:43 -08001535#if QDF_LOCK_STATS
1536static noinline
1537#else
Jeff Johnson755f2612017-01-05 16:28:13 -08001538static
Houston Hoffmanaa12e042017-01-30 14:34:43 -08001539#endif
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301540qdf_nbuf_t dp_tx_send_msdu_multiple(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
Jeff Johnson755f2612017-01-05 16:28:13 -08001541 struct dp_tx_msdu_info_s *msdu_info)
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301542{
1543 uint8_t i;
1544 struct dp_pdev *pdev = vdev->pdev;
1545 struct dp_soc *soc = pdev->soc;
1546 struct dp_tx_desc_s *tx_desc;
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301547 bool is_cce_classified = false;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301548 QDF_STATUS status;
Venkateswara Swamy Bandaru97ca7e92018-04-27 18:30:10 +05301549 uint16_t htt_tcl_metadata = 0;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301550
1551 struct dp_tx_queue *tx_q = &msdu_info->tx_queue;
1552 void *hal_srng = soc->tcl_data_ring[tx_q->ring_id].hal_srng;
Varsha Mishra18281792019-03-06 17:57:23 +05301553 struct cdp_tid_tx_stats *tid_stats = NULL;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301554
1555 if (qdf_unlikely(hal_srng_access_start(soc->hal_soc, hal_srng))) {
1556 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +05301557 "%s %d : HAL RING Access Failed -- %pK",
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301558 __func__, __LINE__, hal_srng);
Varsha Mishra18281792019-03-06 17:57:23 +05301559 dp_tx_get_tid(vdev, nbuf, msdu_info);
1560 tid_stats = &pdev->stats.tid_stats.tid_tx_stats[msdu_info->tid];
1561 tid_stats->swdrop_cnt[TX_HAL_RING_ACCESS_ERR]++;
Ishank Jain1e7401c2017-02-17 15:38:39 +05301562 DP_STATS_INC(vdev, tx_i.dropped.ring_full, 1);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301563 return nbuf;
1564 }
1565
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301566 if (qdf_unlikely(soc->cce_disable)) {
Ruchi, Agrawal4c1468f2017-12-08 00:04:33 +05301567 is_cce_classified = dp_cce_classify(vdev, nbuf);
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301568 if (is_cce_classified) {
1569 DP_STATS_INC(vdev, tx_i.cce_classified, 1);
1570 msdu_info->tid = DP_VO_TID;
1571 }
1572 }
1573
Ishank Jainc838b132017-02-17 11:08:18 +05301574 if (msdu_info->frm_type == dp_tx_frm_me)
1575 nbuf = msdu_info->u.sg_info.curr_seg->nbuf;
1576
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301577 i = 0;
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -07001578 /* Print statement to track i and num_seg */
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301579 /*
1580 * For each segment (maps to 1 MSDU) , prepare software and hardware
1581 * descriptors using information in msdu_info
1582 */
1583 while (i < msdu_info->num_seg) {
1584 /*
1585 * Setup Tx descriptor for an MSDU, and MSDU extension
1586 * descriptor
1587 */
1588 tx_desc = dp_tx_prepare_desc(vdev, nbuf, msdu_info,
1589 tx_q->desc_pool_id);
1590
1591 if (!tx_desc) {
Venkata Sharath Chandra Manchala340c0d82017-06-15 08:52:23 -07001592 if (msdu_info->frm_type == dp_tx_frm_me) {
1593 dp_tx_me_free_buf(pdev,
1594 (void *)(msdu_info->u.sg_info
1595 .curr_seg->frags[0].vaddr));
1596 }
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301597 goto done;
1598 }
1599
Venkata Sharath Chandra Manchala340c0d82017-06-15 08:52:23 -07001600 if (msdu_info->frm_type == dp_tx_frm_me) {
1601 tx_desc->me_buffer =
1602 msdu_info->u.sg_info.curr_seg->frags[0].vaddr;
1603 tx_desc->flags |= DP_TX_DESC_FLAG_ME;
1604 }
1605
Ruchi, Agrawal34721392017-11-13 18:02:09 +05301606 if (is_cce_classified)
1607 tx_desc->flags |= DP_TX_DESC_FLAG_TO_FW;
1608
Venkateswara Swamy Bandaru97ca7e92018-04-27 18:30:10 +05301609 htt_tcl_metadata = vdev->htt_tcl_metadata;
1610 if (msdu_info->exception_fw) {
1611 HTT_TX_TCL_METADATA_VALID_HTT_SET(htt_tcl_metadata, 1);
1612 }
1613
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301614 /*
1615 * Enqueue the Tx MSDU descriptor to HW for transmit
1616 */
1617 status = dp_tx_hw_enqueue(soc, vdev, tx_desc, msdu_info->tid,
Venkateswara Swamy Bandaru97ca7e92018-04-27 18:30:10 +05301618 htt_tcl_metadata, tx_q->ring_id, NULL);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301619
1620 if (status != QDF_STATUS_SUCCESS) {
1621 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Varsha Mishra18281792019-03-06 17:57:23 +05301622 "%s Tx_hw_enqueue Fail tx_desc %pK queue %d",
1623 __func__, tx_desc, tx_q->ring_id);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301624
Varsha Mishra18281792019-03-06 17:57:23 +05301625 dp_tx_get_tid(vdev, nbuf, msdu_info);
1626 tid_stats = &pdev->stats.tid_stats.
1627 tid_tx_stats[msdu_info->tid];
1628 tid_stats->swdrop_cnt[TX_HW_ENQUEUE]++;
Ishank Jainc838b132017-02-17 11:08:18 +05301629 if (tx_desc->flags & DP_TX_DESC_FLAG_ME)
1630 dp_tx_me_free_buf(pdev, tx_desc->me_buffer);
1631
Ravi Joshiab33d9b2017-02-11 21:43:28 -08001632 dp_tx_desc_release(tx_desc, tx_q->desc_pool_id);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301633 goto done;
1634 }
1635
1636 /*
1637 * TODO
1638 * if tso_info structure can be modified to have curr_seg
1639 * as first element, following 2 blocks of code (for TSO and SG)
1640 * can be combined into 1
1641 */
1642
1643 /*
1644 * For frames with multiple segments (TSO, ME), jump to next
1645 * segment.
1646 */
1647 if (msdu_info->frm_type == dp_tx_frm_tso) {
1648 if (msdu_info->u.tso_info.curr_seg->next) {
1649 msdu_info->u.tso_info.curr_seg =
1650 msdu_info->u.tso_info.curr_seg->next;
Ishank Jain5122f8f2017-03-15 22:22:47 +05301651
1652 /*
1653 * If this is a jumbo nbuf, then increment the number of
1654 * nbuf users for each additional segment of the msdu.
1655 * This will ensure that the skb is freed only after
1656 * receiving tx completion for all segments of an nbuf
1657 */
1658 qdf_nbuf_inc_users(nbuf);
1659
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301660 /* Check with MCL if this is needed */
Ishank Jain5122f8f2017-03-15 22:22:47 +05301661 /* nbuf = msdu_info->u.tso_info.curr_seg->nbuf; */
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301662 }
1663 }
1664
1665 /*
1666 * For Multicast-Unicast converted packets,
1667 * each converted frame (for a client) is represented as
1668 * 1 segment
1669 */
Ishank Jainc838b132017-02-17 11:08:18 +05301670 if ((msdu_info->frm_type == dp_tx_frm_sg) ||
1671 (msdu_info->frm_type == dp_tx_frm_me)) {
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301672 if (msdu_info->u.sg_info.curr_seg->next) {
1673 msdu_info->u.sg_info.curr_seg =
1674 msdu_info->u.sg_info.curr_seg->next;
1675 nbuf = msdu_info->u.sg_info.curr_seg->nbuf;
1676 }
1677 }
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301678 i++;
1679 }
1680
1681 nbuf = NULL;
1682
1683done:
Yue Ma245b47b2017-02-21 16:35:31 -08001684 if (hif_pm_runtime_get(soc->hif_handle) == 0) {
1685 hal_srng_access_end(soc->hal_soc, hal_srng);
1686 hif_pm_runtime_put(soc->hif_handle);
1687 } else {
1688 hal_srng_access_end_reap(soc->hal_soc, hal_srng);
1689 }
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301690
1691 return nbuf;
1692}
1693
1694/**
1695 * dp_tx_prepare_sg()- Extract SG info from NBUF and prepare msdu_info
1696 * for SG frames
1697 * @vdev: DP vdev handle
1698 * @nbuf: skb
1699 * @seg_info: Pointer to Segment info Descriptor to be prepared
1700 * @msdu_info: MSDU info to be setup in MSDU descriptor and MSDU extension desc.
1701 *
1702 * Return: NULL on success,
1703 * nbuf when it fails to send
1704 */
Jeff Johnson755f2612017-01-05 16:28:13 -08001705static qdf_nbuf_t dp_tx_prepare_sg(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301706 struct dp_tx_seg_info_s *seg_info, struct dp_tx_msdu_info_s *msdu_info)
1707{
1708 uint32_t cur_frag, nr_frags;
1709 qdf_dma_addr_t paddr;
1710 struct dp_tx_sg_info_s *sg_info;
1711
1712 sg_info = &msdu_info->u.sg_info;
1713 nr_frags = qdf_nbuf_get_nr_frags(nbuf);
1714
Pamidipati, Vijay110bf962017-03-24 21:38:20 +05301715 if (QDF_STATUS_SUCCESS != qdf_nbuf_map(vdev->osdev, nbuf,
1716 QDF_DMA_TO_DEVICE)) {
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301717 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +05301718 "dma map error");
Ishank Jain57c42a12017-04-12 10:42:22 +05301719 DP_STATS_INC(vdev, tx_i.sg.dma_map_error, 1);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301720
1721 qdf_nbuf_free(nbuf);
1722 return NULL;
1723 }
1724
Pamidipati, Vijayda917d52017-07-18 20:13:22 +05301725 paddr = qdf_nbuf_get_frag_paddr(nbuf, 0);
1726 seg_info->frags[0].paddr_lo = paddr;
1727 seg_info->frags[0].paddr_hi = ((uint64_t) paddr) >> 32;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301728 seg_info->frags[0].len = qdf_nbuf_headlen(nbuf);
1729 seg_info->frags[0].vaddr = (void *) nbuf;
1730
1731 for (cur_frag = 0; cur_frag < nr_frags; cur_frag++) {
1732 if (QDF_STATUS_E_FAILURE == qdf_nbuf_frag_map(vdev->osdev,
1733 nbuf, 0, QDF_DMA_TO_DEVICE, cur_frag)) {
1734 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +05301735 "frag dma map error");
Ishank Jain57c42a12017-04-12 10:42:22 +05301736 DP_STATS_INC(vdev, tx_i.sg.dma_map_error, 1);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05301737 qdf_nbuf_free(nbuf);
1738 return NULL;
1739 }
1740
1741 paddr = qdf_nbuf_get_frag_paddr(nbuf, 0);
1742 seg_info->frags[cur_frag + 1].paddr_lo = paddr;
1743 seg_info->frags[cur_frag + 1].paddr_hi =
1744 ((uint64_t) paddr) >> 32;
1745 seg_info->frags[cur_frag + 1].len =
1746 qdf_nbuf_get_frag_size(nbuf, cur_frag);
1747 }
1748
1749 seg_info->frag_cnt = (cur_frag + 1);
1750 seg_info->total_len = qdf_nbuf_len(nbuf);
1751 seg_info->next = NULL;
1752
1753 sg_info->curr_seg = seg_info;
1754
1755 msdu_info->frm_type = dp_tx_frm_sg;
1756 msdu_info->num_seg = 1;
1757
1758 return nbuf;
1759}
1760
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05301761#ifdef MESH_MODE_SUPPORT
1762
1763/**
1764 * dp_tx_extract_mesh_meta_data()- Extract mesh meta hdr info from nbuf
1765 and prepare msdu_info for mesh frames.
1766 * @vdev: DP vdev handle
1767 * @nbuf: skb
1768 * @msdu_info: MSDU info to be setup in MSDU descriptor and MSDU extension desc.
1769 *
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +05301770 * Return: NULL on failure,
1771 * nbuf when extracted successfully
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05301772 */
1773static
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +05301774qdf_nbuf_t dp_tx_extract_mesh_meta_data(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05301775 struct dp_tx_msdu_info_s *msdu_info)
1776{
1777 struct meta_hdr_s *mhdr;
1778 struct htt_tx_msdu_desc_ext2_t *meta_data =
1779 (struct htt_tx_msdu_desc_ext2_t *)&msdu_info->meta_data[0];
1780
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05301781 mhdr = (struct meta_hdr_s *)qdf_nbuf_data(nbuf);
1782
1783 if (CB_FTYPE_MESH_TX_INFO != qdf_nbuf_get_tx_ftype(nbuf)) {
1784 msdu_info->exception_fw = 0;
1785 goto remove_meta_hdr;
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +05301786 }
1787
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05301788 msdu_info->exception_fw = 1;
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05301789
hangtianfe681a52019-01-16 17:16:28 +08001790 qdf_mem_zero(meta_data, sizeof(struct htt_tx_msdu_desc_ext2_t));
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05301791
Venkateswara Swamy Bandaru80683042017-11-07 15:11:31 +05301792 meta_data->host_tx_desc_pool = 1;
Venkateswara Swamy Bandarud004c7e2018-01-29 17:53:52 +05301793 meta_data->update_peer_cache = 1;
1794 meta_data->learning_frame = 1;
Venkateswara Swamy Bandaru80683042017-11-07 15:11:31 +05301795
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05301796 if (!(mhdr->flags & METAHDR_FLAG_AUTO_RATE)) {
1797 meta_data->power = mhdr->power;
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05301798
Venkateswara Swamy Bandaru7e19ec52017-04-17 19:32:18 +05301799 meta_data->mcs_mask = 1 << mhdr->rate_info[0].mcs;
1800 meta_data->nss_mask = 1 << mhdr->rate_info[0].nss;
1801 meta_data->pream_type = mhdr->rate_info[0].preamble_type;
1802 meta_data->retry_limit = mhdr->rate_info[0].max_tries;
1803
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05301804 meta_data->dyn_bw = 1;
1805
1806 meta_data->valid_pwr = 1;
1807 meta_data->valid_mcs_mask = 1;
1808 meta_data->valid_nss_mask = 1;
1809 meta_data->valid_preamble_type = 1;
1810 meta_data->valid_retries = 1;
1811 meta_data->valid_bw_info = 1;
1812 }
1813
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05301814 if (mhdr->flags & METAHDR_FLAG_NOENCRYPT) {
1815 meta_data->encrypt_type = 0;
1816 meta_data->valid_encrypt_type = 1;
Venkateswara Swamy Bandaru6523a022018-02-22 17:55:49 +05301817 meta_data->learning_frame = 0;
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05301818 }
1819
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05301820 meta_data->valid_key_flags = 1;
1821 meta_data->key_flags = (mhdr->keyix & 0x3);
1822
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05301823remove_meta_hdr:
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +05301824 if (qdf_nbuf_pull_head(nbuf, sizeof(struct meta_hdr_s)) == NULL) {
1825 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +05301826 "qdf_nbuf_pull_head failed");
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +05301827 qdf_nbuf_free(nbuf);
1828 return NULL;
1829 }
Venkateswara Swamy Bandaruc64c8622017-02-27 20:08:33 +05301830
Venkateswara Swamy Bandaru09444a12019-02-15 12:24:26 +05301831 msdu_info->tid = qdf_nbuf_get_priority(nbuf);
Venkateswara Swamy Bandaru165d0ab2018-02-12 19:26:56 +05301832
Venkateswara Swamy Bandaru37a3a452018-02-12 15:37:14 +05301833 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO_HIGH,
1834 "%s , Meta hdr %0x %0x %0x %0x %0x %0x"
Aditya Sathishded018e2018-07-02 16:25:21 +05301835 " tid %d to_fw %d",
Venkateswara Swamy Bandaruc64c8622017-02-27 20:08:33 +05301836 __func__, msdu_info->meta_data[0],
1837 msdu_info->meta_data[1],
1838 msdu_info->meta_data[2],
1839 msdu_info->meta_data[3],
Venkateswara Swamy Bandaru37a3a452018-02-12 15:37:14 +05301840 msdu_info->meta_data[4],
1841 msdu_info->meta_data[5],
1842 msdu_info->tid, msdu_info->exception_fw);
Venkateswara Swamy Bandaruc64c8622017-02-27 20:08:33 +05301843
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +05301844 return nbuf;
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05301845}
1846#else
1847static
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +05301848qdf_nbuf_t dp_tx_extract_mesh_meta_data(struct dp_vdev *vdev, qdf_nbuf_t nbuf,
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05301849 struct dp_tx_msdu_info_s *msdu_info)
1850{
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +05301851 return nbuf;
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05301852}
1853
1854#endif
1855
Ishank Jain9f174c62017-03-30 18:37:42 +05301856/**
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301857 * dp_check_exc_metadata() - Checks if parameters are valid
1858 * @tx_exc - holds all exception path parameters
1859 *
1860 * Returns true when all the parameters are valid else false
1861 *
1862 */
1863static bool dp_check_exc_metadata(struct cdp_tx_exception_metadata *tx_exc)
1864{
1865 if ((tx_exc->tid > DP_MAX_TIDS && tx_exc->tid != HTT_INVALID_TID) ||
1866 tx_exc->tx_encap_type > htt_cmn_pkt_num_types ||
1867 tx_exc->sec_type > cdp_num_sec_types) {
1868 return false;
1869 }
1870
1871 return true;
1872}
1873
1874/**
1875 * dp_tx_send_exception() - Transmit a frame on a given VAP in exception path
1876 * @vap_dev: DP vdev handle
1877 * @nbuf: skb
1878 * @tx_exc_metadata: Handle that holds exception path meta data
1879 *
1880 * Entry point for Core Tx layer (DP_TX) invoked from
1881 * hard_start_xmit in OSIF/HDD to transmit frames through fw
1882 *
1883 * Return: NULL on success,
1884 * nbuf when it fails to send
1885 */
1886qdf_nbuf_t dp_tx_send_exception(void *vap_dev, qdf_nbuf_t nbuf,
1887 struct cdp_tx_exception_metadata *tx_exc_metadata)
1888{
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08001889 qdf_ether_header_t *eh = NULL;
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301890 struct dp_vdev *vdev = (struct dp_vdev *) vap_dev;
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05301891 struct dp_tx_msdu_info_s msdu_info;
1892
hangtianfe681a52019-01-16 17:16:28 +08001893 qdf_mem_zero(&msdu_info, sizeof(msdu_info));
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05301894
1895 msdu_info.tid = tx_exc_metadata->tid;
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301896
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08001897 eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf);
Krunal Sonic96a1162019-02-21 11:33:26 -08001898 dp_verbose_debug("skb %pM", nbuf->data);
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301899
1900 DP_STATS_INC_PKT(vdev, tx_i.rcvd, 1, qdf_nbuf_len(nbuf));
1901
1902 if (qdf_unlikely(!dp_check_exc_metadata(tx_exc_metadata))) {
1903 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
1904 "Invalid parameters in exception path");
1905 goto fail;
1906 }
1907
1908 /* Basic sanity checks for unsupported packets */
1909
1910 /* MESH mode */
1911 if (qdf_unlikely(vdev->mesh_vdev)) {
1912 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
1913 "Mesh mode is not supported in exception path");
1914 goto fail;
1915 }
1916
1917 /* TSO or SG */
1918 if (qdf_unlikely(qdf_nbuf_is_tso(nbuf)) ||
1919 qdf_unlikely(qdf_nbuf_is_nonlinear(nbuf))) {
1920 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
1921 "TSO and SG are not supported in exception path");
1922
1923 goto fail;
1924 }
1925
1926 /* RAW */
1927 if (qdf_unlikely(tx_exc_metadata->tx_encap_type == htt_cmn_pkt_type_raw)) {
1928 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
1929 "Raw frame is not supported in exception path");
1930 goto fail;
1931 }
1932
1933
1934 /* Mcast enhancement*/
1935 if (qdf_unlikely(vdev->mcast_enhancement_en > 0)) {
Tallapragada Kalyan5e3a39c2018-08-24 16:34:12 +05301936 if (DP_FRAME_IS_MULTICAST((eh)->ether_dhost) &&
1937 !DP_FRAME_IS_BROADCAST((eh)->ether_dhost)) {
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301938 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +05301939 "Ignoring mcast_enhancement_en which is set and sending the mcast packet to the FW");
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301940 }
1941 }
1942
1943 /*
1944 * Get HW Queue to use for this frame.
1945 * TCL supports upto 4 DMA rings, out of which 3 rings are
1946 * dedicated for data and 1 for command.
1947 * "queue_id" maps to one hardware ring.
1948 * With each ring, we also associate a unique Tx descriptor pool
1949 * to minimize lock contention for these resources.
1950 */
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05301951 dp_tx_get_queue(vdev, nbuf, &msdu_info.tx_queue);
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301952
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301953 /* Single linear frame */
1954 /*
1955 * If nbuf is a simple linear frame, use send_single function to
1956 * prepare direct-buffer type TCL descriptor and enqueue to TCL
1957 * SRNG. There is no need to setup a MSDU extension descriptor.
1958 */
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05301959 nbuf = dp_tx_send_msdu_single(vdev, nbuf, &msdu_info,
1960 tx_exc_metadata->peer_id, tx_exc_metadata);
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301961
1962 return nbuf;
1963
1964fail:
Krunal Sonic96a1162019-02-21 11:33:26 -08001965 dp_verbose_debug("pkt send failed");
Prathyusha Guduribe41d972018-01-19 14:17:14 +05301966 return nbuf;
1967}
1968
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05301969/**
1970 * dp_tx_send_mesh() - Transmit mesh frame on a given VAP
1971 * @vap_dev: DP vdev handle
1972 * @nbuf: skb
1973 *
1974 * Entry point for Core Tx layer (DP_TX) invoked from
1975 * hard_start_xmit in OSIF/HDD
1976 *
1977 * Return: NULL on success,
1978 * nbuf when it fails to send
1979 */
1980#ifdef MESH_MODE_SUPPORT
1981qdf_nbuf_t dp_tx_send_mesh(void *vap_dev, qdf_nbuf_t nbuf)
1982{
1983 struct meta_hdr_s *mhdr;
1984 qdf_nbuf_t nbuf_mesh = NULL;
1985 qdf_nbuf_t nbuf_clone = NULL;
1986 struct dp_vdev *vdev = (struct dp_vdev *) vap_dev;
Venkateswara Swamy Bandaru6523a022018-02-22 17:55:49 +05301987 uint8_t no_enc_frame = 0;
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05301988
1989 nbuf_mesh = qdf_nbuf_unshare(nbuf);
Jeff Johnsona8edf332019-03-18 09:51:52 -07001990 if (!nbuf_mesh) {
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05301991 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +05301992 "qdf_nbuf_unshare failed");
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05301993 return nbuf;
1994 }
1995 nbuf = nbuf_mesh;
1996
1997 mhdr = (struct meta_hdr_s *)qdf_nbuf_data(nbuf);
Venkateswara Swamy Bandaru6523a022018-02-22 17:55:49 +05301998
1999 if ((vdev->sec_type != cdp_sec_type_none) &&
2000 (mhdr->flags & METAHDR_FLAG_NOENCRYPT))
2001 no_enc_frame = 1;
2002
Venkateswara Swamy Bandaru09444a12019-02-15 12:24:26 +05302003 if (mhdr->flags & METAHDR_FLAG_NOQOS)
2004 qdf_nbuf_set_priority(nbuf, HTT_TX_EXT_TID_NON_QOS_MCAST_BCAST);
2005
Venkateswara Swamy Bandaru6523a022018-02-22 17:55:49 +05302006 if ((mhdr->flags & METAHDR_FLAG_INFO_UPDATED) &&
2007 !no_enc_frame) {
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05302008 nbuf_clone = qdf_nbuf_clone(nbuf);
Jeff Johnsona8edf332019-03-18 09:51:52 -07002009 if (!nbuf_clone) {
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05302010 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +05302011 "qdf_nbuf_clone failed");
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05302012 return nbuf;
2013 }
2014 qdf_nbuf_set_tx_ftype(nbuf_clone, CB_FTYPE_MESH_TX_INFO);
2015 }
2016
2017 if (nbuf_clone) {
2018 if (!dp_tx_send(vap_dev, nbuf_clone)) {
2019 DP_STATS_INC(vdev, tx_i.mesh.exception_fw, 1);
Yun Parkaadee8c2018-06-04 11:21:40 -07002020 } else {
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05302021 qdf_nbuf_free(nbuf_clone);
Yun Parkaadee8c2018-06-04 11:21:40 -07002022 }
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05302023 }
2024
Venkateswara Swamy Bandaru6523a022018-02-22 17:55:49 +05302025 if (no_enc_frame)
2026 qdf_nbuf_set_tx_ftype(nbuf, CB_FTYPE_MESH_TX_INFO);
2027 else
2028 qdf_nbuf_set_tx_ftype(nbuf, CB_FTYPE_INVALID);
2029
2030 nbuf = dp_tx_send(vap_dev, nbuf);
Jeff Johnsona8edf332019-03-18 09:51:52 -07002031 if ((!nbuf) && no_enc_frame) {
Venkateswara Swamy Bandaru6523a022018-02-22 17:55:49 +05302032 DP_STATS_INC(vdev, tx_i.mesh.exception_fw, 1);
2033 }
2034
2035 return nbuf;
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05302036}
2037
2038#else
2039
2040qdf_nbuf_t dp_tx_send_mesh(void *vap_dev, qdf_nbuf_t nbuf)
2041{
2042 return dp_tx_send(vap_dev, nbuf);
2043}
2044
2045#endif
Prathyusha Guduribe41d972018-01-19 14:17:14 +05302046
2047/**
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302048 * dp_tx_send() - Transmit a frame on a given VAP
2049 * @vap_dev: DP vdev handle
2050 * @nbuf: skb
2051 *
2052 * Entry point for Core Tx layer (DP_TX) invoked from
2053 * hard_start_xmit in OSIF/HDD or from dp_rx_process for intravap forwarding
2054 * cases
2055 *
2056 * Return: NULL on success,
2057 * nbuf when it fails to send
2058 */
2059qdf_nbuf_t dp_tx_send(void *vap_dev, qdf_nbuf_t nbuf)
2060{
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08002061 qdf_ether_header_t *eh = NULL;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302062 struct dp_tx_msdu_info_s msdu_info;
2063 struct dp_tx_seg_info_s seg_info;
2064 struct dp_vdev *vdev = (struct dp_vdev *) vap_dev;
Ishank Jain9f174c62017-03-30 18:37:42 +05302065 uint16_t peer_id = HTT_INVALID_PEER;
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +05302066 qdf_nbuf_t nbuf_mesh = NULL;
2067
hangtianfe681a52019-01-16 17:16:28 +08002068 qdf_mem_zero(&msdu_info, sizeof(msdu_info));
2069 qdf_mem_zero(&seg_info, sizeof(seg_info));
Ishank Jain2f81e962017-01-23 22:42:37 +05302070
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08002071 eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf);
Pranita Solankea5a3ae72018-01-18 21:45:27 +05302072
Krunal Sonic96a1162019-02-21 11:33:26 -08002073 dp_verbose_debug("skb %pM", nbuf->data);
Prathyusha Guduribe41d972018-01-19 14:17:14 +05302074
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05302075 /*
2076 * Set Default Host TID value to invalid TID
2077 * (TID override disabled)
2078 */
2079 msdu_info.tid = HTT_TX_EXT_TID_INVALID;
Ishank Jaine73c4032017-03-16 11:48:15 +05302080 DP_STATS_INC_PKT(vdev, tx_i.rcvd, 1, qdf_nbuf_len(nbuf));
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302081
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +05302082 if (qdf_unlikely(vdev->mesh_vdev)) {
2083 nbuf_mesh = dp_tx_extract_mesh_meta_data(vdev, nbuf,
2084 &msdu_info);
Jeff Johnsona8edf332019-03-18 09:51:52 -07002085 if (!nbuf_mesh) {
Krunal Sonic96a1162019-02-21 11:33:26 -08002086 dp_verbose_debug("Extracting mesh metadata failed");
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +05302087 return nbuf;
2088 }
2089 nbuf = nbuf_mesh;
2090 }
Venkateswara Swamy Bandaruc64c8622017-02-27 20:08:33 +05302091
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302092 /*
2093 * Get HW Queue to use for this frame.
2094 * TCL supports upto 4 DMA rings, out of which 3 rings are
2095 * dedicated for data and 1 for command.
2096 * "queue_id" maps to one hardware ring.
2097 * With each ring, we also associate a unique Tx descriptor pool
2098 * to minimize lock contention for these resources.
2099 */
2100 dp_tx_get_queue(vdev, nbuf, &msdu_info.tx_queue);
2101
2102 /*
2103 * TCL H/W supports 2 DSCP-TID mapping tables.
2104 * Table 1 - Default DSCP-TID mapping table
2105 * Table 2 - 1 DSCP-TID override table
2106 *
2107 * If we need a different DSCP-TID mapping for this vap,
2108 * call tid_classify to extract DSCP/ToS from frame and
2109 * map to a TID and store in msdu_info. This is later used
2110 * to fill in TCL Input descriptor (per-packet TID override).
2111 */
Neil Zhao48876362018-03-22 11:23:02 -07002112 dp_tx_classify_tid(vdev, nbuf, &msdu_info);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302113
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302114 /*
2115 * Classify the frame and call corresponding
2116 * "prepare" function which extracts the segment (TSO)
2117 * and fragmentation information (for TSO , SG, ME, or Raw)
2118 * into MSDU_INFO structure which is later used to fill
2119 * SW and HW descriptors.
2120 */
2121 if (qdf_nbuf_is_tso(nbuf)) {
Krunal Sonic96a1162019-02-21 11:33:26 -08002122 dp_verbose_debug("TSO frame %pK", vdev);
Ishank Jain1e7401c2017-02-17 15:38:39 +05302123 DP_STATS_INC_PKT(vdev, tx_i.tso.tso_pkt, 1,
Ishank Jainbc2d91f2017-01-03 18:14:54 +05302124 qdf_nbuf_len(nbuf));
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302125
Ishank Jain5122f8f2017-03-15 22:22:47 +05302126 if (dp_tx_prepare_tso(vdev, nbuf, &msdu_info)) {
Amir Patel02911572018-07-02 13:00:53 +05302127 DP_STATS_INC_PKT(vdev, tx_i.tso.dropped_host, 1,
2128 qdf_nbuf_len(nbuf));
Ishank Jain5122f8f2017-03-15 22:22:47 +05302129 return nbuf;
2130 }
2131
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302132 goto send_multiple;
2133 }
2134
2135 /* SG */
2136 if (qdf_unlikely(qdf_nbuf_is_nonlinear(nbuf))) {
2137 nbuf = dp_tx_prepare_sg(vdev, nbuf, &seg_info, &msdu_info);
2138
Chaitanya Kiran Godavarthib1e2bf52019-01-10 15:05:17 +05302139 if (!nbuf)
2140 return NULL;
2141
Krunal Sonic96a1162019-02-21 11:33:26 -08002142 dp_verbose_debug("non-TSO SG frame %pK", vdev);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302143
Ishank Jain1e7401c2017-02-17 15:38:39 +05302144 DP_STATS_INC_PKT(vdev, tx_i.sg.sg_pkt, 1,
Ishank Jainbc2d91f2017-01-03 18:14:54 +05302145 qdf_nbuf_len(nbuf));
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302146
2147 goto send_multiple;
2148 }
2149
Ishank Jainc838b132017-02-17 11:08:18 +05302150#ifdef ATH_SUPPORT_IQUE
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302151 /* Mcast to Ucast Conversion*/
Ishank Jainc838b132017-02-17 11:08:18 +05302152 if (qdf_unlikely(vdev->mcast_enhancement_en > 0)) {
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08002153 eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf);
Chaithanya Garrepalli85c447c2018-10-16 17:54:06 +05302154 if (DP_FRAME_IS_MULTICAST((eh)->ether_dhost) &&
2155 !DP_FRAME_IS_BROADCAST((eh)->ether_dhost)) {
Krunal Sonic96a1162019-02-21 11:33:26 -08002156 dp_verbose_debug("Mcast frm for ME %pK", vdev);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302157
Ishank Jain1e7401c2017-02-17 15:38:39 +05302158 DP_STATS_INC_PKT(vdev,
2159 tx_i.mcast_en.mcast_pkt, 1,
Ishank Jainbc2d91f2017-01-03 18:14:54 +05302160 qdf_nbuf_len(nbuf));
Pamidipati, Vijay726ea122018-02-07 18:27:00 +05302161 if (dp_tx_prepare_send_me(vdev, nbuf) ==
Pamidipati, Vijayaeff4442018-01-19 22:58:32 +05302162 QDF_STATUS_SUCCESS) {
Ishank Jainc838b132017-02-17 11:08:18 +05302163 return NULL;
2164 }
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302165 }
2166 }
Ishank Jainc838b132017-02-17 11:08:18 +05302167#endif
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302168
2169 /* RAW */
Ishank Jain949674c2017-02-27 17:09:29 +05302170 if (qdf_unlikely(vdev->tx_encap_type == htt_cmn_pkt_type_raw)) {
Venkateswara Swamy Bandaru99075962016-12-27 11:55:15 +05302171 nbuf = dp_tx_prepare_raw(vdev, nbuf, &seg_info, &msdu_info);
Jeff Johnsona8edf332019-03-18 09:51:52 -07002172 if (!nbuf)
Venkateswara Swamy Bandaru99075962016-12-27 11:55:15 +05302173 return NULL;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302174
Krunal Sonic96a1162019-02-21 11:33:26 -08002175 dp_verbose_debug("Raw frame %pK", vdev);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302176
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302177 goto send_multiple;
2178
2179 }
2180
2181 /* Single linear frame */
2182 /*
2183 * If nbuf is a simple linear frame, use send_single function to
2184 * prepare direct-buffer type TCL descriptor and enqueue to TCL
2185 * SRNG. There is no need to setup a MSDU extension descriptor.
2186 */
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05302187 nbuf = dp_tx_send_msdu_single(vdev, nbuf, &msdu_info, peer_id, NULL);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302188
2189 return nbuf;
2190
2191send_multiple:
2192 nbuf = dp_tx_send_msdu_multiple(vdev, nbuf, &msdu_info);
2193
2194 return nbuf;
2195}
2196
2197/**
2198 * dp_tx_reinject_handler() - Tx Reinject Handler
2199 * @tx_desc: software descriptor head pointer
2200 * @status : Tx completion status from HTT descriptor
2201 *
2202 * This function reinjects frames back to Target.
2203 * Todo - Host queue needs to be added
2204 *
2205 * Return: none
2206 */
Jeff Johnson755f2612017-01-05 16:28:13 -08002207static
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302208void dp_tx_reinject_handler(struct dp_tx_desc_s *tx_desc, uint8_t *status)
2209{
2210 struct dp_vdev *vdev;
Ishank Jain997955e2017-03-24 18:18:50 +05302211 struct dp_peer *peer = NULL;
2212 uint32_t peer_id = HTT_INVALID_PEER;
2213 qdf_nbuf_t nbuf = tx_desc->nbuf;
2214 qdf_nbuf_t nbuf_copy = NULL;
2215 struct dp_tx_msdu_info_s msdu_info;
Ruchi, Agrawalbd894b32017-11-03 17:24:56 +05302216 struct dp_peer *sa_peer = NULL;
2217 struct dp_ast_entry *ast_entry = NULL;
2218 struct dp_soc *soc = NULL;
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08002219 qdf_ether_header_t *eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf);
Tallapragada Kalyan2a5fc622017-12-08 21:07:43 +05302220#ifdef WDS_VENDOR_EXTENSION
2221 int is_mcast = 0, is_ucast = 0;
2222 int num_peers_3addr = 0;
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08002223 qdf_ether_header_t *eth_hdr = (qdf_ether_header_t *)(qdf_nbuf_data(nbuf));
Tallapragada Kalyan2a5fc622017-12-08 21:07:43 +05302224 struct ieee80211_frame_addr4 *wh = (struct ieee80211_frame_addr4 *)(qdf_nbuf_data(nbuf));
2225#endif
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302226
2227 vdev = tx_desc->vdev;
Ruchi, Agrawalbd894b32017-11-03 17:24:56 +05302228 soc = vdev->pdev->soc;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302229
Ravi Joshiab33d9b2017-02-11 21:43:28 -08002230 qdf_assert(vdev);
2231
hangtianfe681a52019-01-16 17:16:28 +08002232 qdf_mem_zero(&msdu_info, sizeof(msdu_info));
Ishank Jain997955e2017-03-24 18:18:50 +05302233
2234 dp_tx_get_queue(vdev, nbuf, &msdu_info.tx_queue);
2235
Houston Hoffman41b912c2017-08-30 14:27:51 -07002236 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
Aditya Sathishded018e2018-07-02 16:25:21 +05302237 "%s Tx reinject path", __func__);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302238
Ishank Jain1e7401c2017-02-17 15:38:39 +05302239 DP_STATS_INC_PKT(vdev, tx_i.reinject_pkts, 1,
Ishank Jainbc2d91f2017-01-03 18:14:54 +05302240 qdf_nbuf_len(tx_desc->nbuf));
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302241
Ruchi, Agrawalbd894b32017-11-03 17:24:56 +05302242 qdf_spin_lock_bh(&(soc->ast_lock));
2243
Chaithanya Garrepallicf347d12018-09-18 14:28:55 +05302244 ast_entry = dp_peer_ast_hash_find_by_pdevid
2245 (soc,
2246 (uint8_t *)(eh->ether_shost),
2247 vdev->pdev->pdev_id);
Tallapragada Kalyan57b6bb32018-01-02 12:58:33 +05302248
Ruchi, Agrawalbd894b32017-11-03 17:24:56 +05302249 if (ast_entry)
2250 sa_peer = ast_entry->peer;
2251
2252 qdf_spin_unlock_bh(&(soc->ast_lock));
Ishank Jain997955e2017-03-24 18:18:50 +05302253
Tallapragada Kalyan2a5fc622017-12-08 21:07:43 +05302254#ifdef WDS_VENDOR_EXTENSION
2255 if (qdf_unlikely(vdev->tx_encap_type != htt_cmn_pkt_type_raw)) {
2256 is_mcast = (IS_MULTICAST(wh->i_addr1)) ? 1 : 0;
2257 } else {
2258 is_mcast = (IS_MULTICAST(eth_hdr->ether_dhost)) ? 1 : 0;
2259 }
2260 is_ucast = !is_mcast;
2261
2262 TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) {
2263 if (peer->bss_peer)
2264 continue;
2265
2266 /* Detect wds peers that use 3-addr framing for mcast.
2267 * if there are any, the bss_peer is used to send the
2268 * the mcast frame using 3-addr format. all wds enabled
2269 * peers that use 4-addr framing for mcast frames will
2270 * be duplicated and sent as 4-addr frames below.
2271 */
2272 if (!peer->wds_enabled || !peer->wds_ecm.wds_tx_mcast_4addr) {
2273 num_peers_3addr = 1;
2274 break;
2275 }
2276 }
2277#endif
2278
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05302279 if (qdf_unlikely(vdev->mesh_vdev)) {
2280 DP_TX_FREE_SINGLE_BUF(vdev->pdev->soc, tx_desc->nbuf);
Ishank Jain997955e2017-03-24 18:18:50 +05302281 } else {
2282 TAILQ_FOREACH(peer, &vdev->peer_list, peer_list_elem) {
2283 if ((peer->peer_ids[0] != HTT_INVALID_PEER) &&
Tallapragada Kalyan2a5fc622017-12-08 21:07:43 +05302284#ifdef WDS_VENDOR_EXTENSION
2285 /*
2286 * . if 3-addr STA, then send on BSS Peer
2287 * . if Peer WDS enabled and accept 4-addr mcast,
2288 * send mcast on that peer only
2289 * . if Peer WDS enabled and accept 4-addr ucast,
2290 * send ucast on that peer only
2291 */
2292 ((peer->bss_peer && num_peers_3addr && is_mcast) ||
2293 (peer->wds_enabled &&
2294 ((is_mcast && peer->wds_ecm.wds_tx_mcast_4addr) ||
2295 (is_ucast && peer->wds_ecm.wds_tx_ucast_4addr))))) {
2296#else
2297 ((peer->bss_peer &&
2298 !(vdev->osif_proxy_arp(vdev->osif_vdev, nbuf))) ||
2299 peer->nawds_enabled)) {
2300#endif
Ruchi, Agrawalbd894b32017-11-03 17:24:56 +05302301 peer_id = DP_INVALID_PEER;
2302
2303 if (peer->nawds_enabled) {
2304 peer_id = peer->peer_ids[0];
2305 if (sa_peer == peer) {
2306 QDF_TRACE(
2307 QDF_MODULE_ID_DP,
2308 QDF_TRACE_LEVEL_DEBUG,
2309 " %s: multicast packet",
2310 __func__);
2311 DP_STATS_INC(peer,
2312 tx.nawds_mcast_drop, 1);
2313 continue;
2314 }
2315 }
2316
Ishank Jain997955e2017-03-24 18:18:50 +05302317 nbuf_copy = qdf_nbuf_copy(nbuf);
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05302318
Ishank Jain997955e2017-03-24 18:18:50 +05302319 if (!nbuf_copy) {
2320 QDF_TRACE(QDF_MODULE_ID_DP,
Houston Hoffman41b912c2017-08-30 14:27:51 -07002321 QDF_TRACE_LEVEL_DEBUG,
2322 FL("nbuf copy failed"));
Ishank Jain997955e2017-03-24 18:18:50 +05302323 break;
2324 }
2325
Ishank Jain997955e2017-03-24 18:18:50 +05302326 nbuf_copy = dp_tx_send_msdu_single(vdev,
Ruchi, Agrawalbd894b32017-11-03 17:24:56 +05302327 nbuf_copy,
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05302328 &msdu_info,
Prathyusha Guduribe41d972018-01-19 14:17:14 +05302329 peer_id,
2330 NULL);
Ishank Jain997955e2017-03-24 18:18:50 +05302331
2332 if (nbuf_copy) {
2333 QDF_TRACE(QDF_MODULE_ID_DP,
Ruchi, Agrawalbd894b32017-11-03 17:24:56 +05302334 QDF_TRACE_LEVEL_DEBUG,
2335 FL("pkt send failed"));
Ishank Jain997955e2017-03-24 18:18:50 +05302336 qdf_nbuf_free(nbuf_copy);
Ruchi, Agrawalbd894b32017-11-03 17:24:56 +05302337 } else {
2338 if (peer_id != DP_INVALID_PEER)
2339 DP_STATS_INC_PKT(peer,
2340 tx.nawds_mcast,
2341 1, qdf_nbuf_len(nbuf));
Ishank Jain997955e2017-03-24 18:18:50 +05302342 }
2343 }
2344 }
2345 }
2346
Ruchi, Agrawalbd894b32017-11-03 17:24:56 +05302347 if (vdev->nawds_enabled) {
2348 peer_id = DP_INVALID_PEER;
2349
2350 DP_STATS_INC_PKT(vdev, tx_i.nawds_mcast,
2351 1, qdf_nbuf_len(nbuf));
2352
2353 nbuf = dp_tx_send_msdu_single(vdev,
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05302354 nbuf,
2355 &msdu_info,
2356 peer_id, NULL);
Ruchi, Agrawalbd894b32017-11-03 17:24:56 +05302357
2358 if (nbuf) {
2359 QDF_TRACE(QDF_MODULE_ID_DP,
2360 QDF_TRACE_LEVEL_DEBUG,
2361 FL("pkt send failed"));
2362 qdf_nbuf_free(nbuf);
2363 }
2364 } else
2365 qdf_nbuf_free(nbuf);
2366
Ravi Joshiab33d9b2017-02-11 21:43:28 -08002367 dp_tx_desc_release(tx_desc, tx_desc->pool_id);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302368}
2369
2370/**
2371 * dp_tx_inspect_handler() - Tx Inspect Handler
2372 * @tx_desc: software descriptor head pointer
2373 * @status : Tx completion status from HTT descriptor
2374 *
2375 * Handles Tx frames sent back to Host for inspection
2376 * (ProxyARP)
2377 *
2378 * Return: none
2379 */
Jeff Johnson755f2612017-01-05 16:28:13 -08002380static void dp_tx_inspect_handler(struct dp_tx_desc_s *tx_desc, uint8_t *status)
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302381{
2382
2383 struct dp_soc *soc;
Ravi Joshiab33d9b2017-02-11 21:43:28 -08002384 struct dp_pdev *pdev = tx_desc->pdev;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302385
2386 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
Aditya Sathishded018e2018-07-02 16:25:21 +05302387 "%s Tx inspect path",
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302388 __func__);
2389
Ravi Joshiab33d9b2017-02-11 21:43:28 -08002390 qdf_assert(pdev);
2391
2392 soc = pdev->soc;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302393
Ishank Jain1e7401c2017-02-17 15:38:39 +05302394 DP_STATS_INC_PKT(tx_desc->vdev, tx_i.inspect_pkts, 1,
Ishank Jainbc2d91f2017-01-03 18:14:54 +05302395 qdf_nbuf_len(tx_desc->nbuf));
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302396
Ravi Joshiab33d9b2017-02-11 21:43:28 -08002397 DP_TX_FREE_SINGLE_BUF(soc, tx_desc->nbuf);
Pamidipati, Vijayf82fb2b2017-06-28 05:31:50 +05302398 dp_tx_desc_release(tx_desc, tx_desc->pool_id);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302399}
2400
Soumya Bhatcfbb8952017-10-03 15:04:09 +05302401#ifdef FEATURE_PERPKT_INFO
Ruchi, Agrawalc0f9c972018-02-02 11:24:05 +05302402/**
2403 * dp_get_completion_indication_for_stack() - send completion to stack
Sravan Kumar Kairam26d471e2018-08-14 23:51:58 +05302404 * @soc : dp_soc handle
2405 * @pdev: dp_pdev handle
2406 * @peer: dp peer handle
Amir Patel12550f62018-09-28 19:05:28 +05302407 * @ts: transmit completion status structure
Ruchi, Agrawalc0f9c972018-02-02 11:24:05 +05302408 * @netbuf: Buffer pointer for free
2409 *
2410 * This function is used for indication whether buffer needs to be
Amir Patel12550f62018-09-28 19:05:28 +05302411 * sent to stack for freeing or not
Ruchi, Agrawalc0f9c972018-02-02 11:24:05 +05302412*/
Radha krishna Simha Jiguru47876f62017-11-30 21:08:40 +05302413QDF_STATUS
Sravan Kumar Kairam26d471e2018-08-14 23:51:58 +05302414dp_get_completion_indication_for_stack(struct dp_soc *soc,
2415 struct dp_pdev *pdev,
Amir Patel12550f62018-09-28 19:05:28 +05302416 struct dp_peer *peer,
2417 struct hal_tx_completion_status *ts,
Ankit Kumar8dc0e2a2019-02-28 18:17:15 +05302418 qdf_nbuf_t netbuf,
2419 uint64_t time_latency)
Soumya Bhatcfbb8952017-10-03 15:04:09 +05302420{
2421 struct tx_capture_hdr *ppdu_hdr;
Amir Patel12550f62018-09-28 19:05:28 +05302422 uint16_t peer_id = ts->peer_id;
2423 uint32_t ppdu_id = ts->ppdu_id;
2424 uint8_t first_msdu = ts->first_msdu;
2425 uint8_t last_msdu = ts->last_msdu;
Soumya Bhatcfbb8952017-10-03 15:04:09 +05302426
Ankit Kumar8dc0e2a2019-02-28 18:17:15 +05302427 if (qdf_unlikely(!pdev->tx_sniffer_enable && !pdev->mcopy_mode &&
2428 !pdev->latency_capture_enable))
Soumya Bhatcfbb8952017-10-03 15:04:09 +05302429 return QDF_STATUS_E_NOSUPPORT;
2430
Soumya Bhatcfbb8952017-10-03 15:04:09 +05302431 if (!peer) {
2432 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
2433 FL("Peer Invalid"));
2434 return QDF_STATUS_E_INVAL;
2435 }
2436
Soumya Bhat7422db82017-12-15 13:48:53 +05302437 if (pdev->mcopy_mode) {
Soumya Bhat2f54de22018-02-21 09:54:28 +05302438 if ((pdev->m_copy_id.tx_ppdu_id == ppdu_id) &&
Amir Patel12550f62018-09-28 19:05:28 +05302439 (pdev->m_copy_id.tx_peer_id == peer_id)) {
Soumya Bhat2f779b02017-10-24 13:10:44 +05302440 return QDF_STATUS_E_INVAL;
2441 }
2442
Soumya Bhat2f54de22018-02-21 09:54:28 +05302443 pdev->m_copy_id.tx_ppdu_id = ppdu_id;
2444 pdev->m_copy_id.tx_peer_id = peer_id;
Soumya Bhat2f779b02017-10-24 13:10:44 +05302445 }
2446
Soumya Bhatcfbb8952017-10-03 15:04:09 +05302447 if (!qdf_nbuf_push_head(netbuf, sizeof(struct tx_capture_hdr))) {
2448 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
2449 FL("No headroom"));
2450 return QDF_STATUS_E_NOMEM;
2451 }
2452
2453 ppdu_hdr = (struct tx_capture_hdr *)qdf_nbuf_data(netbuf);
Soumya Bhat2f779b02017-10-24 13:10:44 +05302454 qdf_mem_copy(ppdu_hdr->ta, peer->vdev->mac_addr.raw,
Srinivas Girigowda2751b6d2019-02-27 12:28:13 -08002455 QDF_MAC_ADDR_SIZE);
Amir Patel12550f62018-09-28 19:05:28 +05302456 qdf_mem_copy(ppdu_hdr->ra, peer->mac_addr.raw,
Srinivas Girigowda2751b6d2019-02-27 12:28:13 -08002457 QDF_MAC_ADDR_SIZE);
Soumya Bhatcfbb8952017-10-03 15:04:09 +05302458 ppdu_hdr->ppdu_id = ppdu_id;
Soumya Bhat20725572018-01-11 19:36:19 +05302459 ppdu_hdr->peer_id = peer_id;
2460 ppdu_hdr->first_msdu = first_msdu;
2461 ppdu_hdr->last_msdu = last_msdu;
Ankit Kumar8dc0e2a2019-02-28 18:17:15 +05302462 if (qdf_unlikely(pdev->latency_capture_enable)) {
2463 ppdu_hdr->tsf = ts->tsf;
2464 ppdu_hdr->time_latency = time_latency;
2465 }
Soumya Bhatcfbb8952017-10-03 15:04:09 +05302466
Ruchi, Agrawalc0f9c972018-02-02 11:24:05 +05302467 return QDF_STATUS_SUCCESS;
2468}
2469
2470
2471/**
2472 * dp_send_completion_to_stack() - send completion to stack
2473 * @soc : dp_soc handle
2474 * @pdev: dp_pdev handle
2475 * @peer_id: peer_id of the peer for which completion came
2476 * @ppdu_id: ppdu_id
2477 * @netbuf: Buffer pointer for free
2478 *
2479 * This function is used to send completion to stack
2480 * to free buffer
2481*/
2482void dp_send_completion_to_stack(struct dp_soc *soc, struct dp_pdev *pdev,
2483 uint16_t peer_id, uint32_t ppdu_id,
2484 qdf_nbuf_t netbuf)
2485{
Soumya Bhatcfbb8952017-10-03 15:04:09 +05302486 dp_wdi_event_handler(WDI_EVENT_TX_DATA, soc,
Soumya Bhat2f779b02017-10-24 13:10:44 +05302487 netbuf, peer_id,
2488 WDI_NO_VAL, pdev->pdev_id);
Soumya Bhatcfbb8952017-10-03 15:04:09 +05302489}
2490#else
2491static QDF_STATUS
Sravan Kumar Kairam26d471e2018-08-14 23:51:58 +05302492dp_get_completion_indication_for_stack(struct dp_soc *soc,
2493 struct dp_pdev *pdev,
Amir Patel12550f62018-09-28 19:05:28 +05302494 struct dp_peer *peer,
2495 struct hal_tx_completion_status *ts,
Ankit Kumar8dc0e2a2019-02-28 18:17:15 +05302496 qdf_nbuf_t netbuf,
2497 uint64_t time_latency)
Soumya Bhatcfbb8952017-10-03 15:04:09 +05302498{
2499 return QDF_STATUS_E_NOSUPPORT;
2500}
Ruchi, Agrawalc0f9c972018-02-02 11:24:05 +05302501
2502static void
2503dp_send_completion_to_stack(struct dp_soc *soc, struct dp_pdev *pdev,
Amir Patel12550f62018-09-28 19:05:28 +05302504 uint16_t peer_id, uint32_t ppdu_id, qdf_nbuf_t netbuf)
Ruchi, Agrawalc0f9c972018-02-02 11:24:05 +05302505{
2506}
Soumya Bhatcfbb8952017-10-03 15:04:09 +05302507#endif
2508
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302509/**
Pamidipati, Vijay4f7c3052017-07-25 10:01:00 +05302510 * dp_tx_comp_free_buf() - Free nbuf associated with the Tx Descriptor
2511 * @soc: Soc handle
2512 * @desc: software Tx descriptor to be processed
2513 *
2514 * Return: none
2515 */
Chaithanya Garrepallief40fec2019-05-16 22:26:05 +05302516static inline void dp_tx_comp_free_buf(struct dp_soc *soc,
2517 struct dp_tx_desc_s *desc)
Pamidipati, Vijay4f7c3052017-07-25 10:01:00 +05302518{
2519 struct dp_vdev *vdev = desc->vdev;
2520 qdf_nbuf_t nbuf = desc->nbuf;
2521
Pamidipati, Vijaycd7fda82019-03-18 10:55:00 +05302522 /* nbuf already freed in vdev detach path */
2523 if (!nbuf)
2524 return;
2525
Kabilan Kannan60e3b302017-09-07 20:06:17 -07002526 /* If it is TDLS mgmt, don't unmap or free the frame */
2527 if (desc->flags & DP_TX_DESC_FLAG_TDLS_FRAME)
2528 return dp_non_std_tx_comp_free_buff(desc, vdev);
2529
Pamidipati, Vijay4f7c3052017-07-25 10:01:00 +05302530 /* 0 : MSDU buffer, 1 : MLE */
2531 if (desc->msdu_ext_desc) {
2532 /* TSO free */
2533 if (hal_tx_ext_desc_get_tso_enable(
2534 desc->msdu_ext_desc->vaddr)) {
chenguoee42a322018-03-15 18:05:46 +08002535 /* unmap eash TSO seg before free the nbuf */
Jinwei Chen73e0dd52018-11-26 14:11:36 +08002536 dp_tx_tso_unmap_segment(soc, desc->tso_desc,
2537 desc->tso_num_desc);
chenguo94b76152018-01-24 19:39:23 +08002538 qdf_nbuf_free(nbuf);
2539 return;
Pamidipati, Vijay4f7c3052017-07-25 10:01:00 +05302540 }
2541 }
2542
Pamidipati, Vijay4f7c3052017-07-25 10:01:00 +05302543 qdf_nbuf_unmap(soc->osdev, nbuf, QDF_DMA_TO_DEVICE);
2544
Jinwei Chen79b4fc82019-04-26 13:27:27 +08002545 if (qdf_unlikely(!vdev)) {
2546 qdf_nbuf_free(nbuf);
2547 return;
2548 }
2549
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05302550 if (qdf_likely(!vdev->mesh_vdev))
Pamidipati, Vijay4f7c3052017-07-25 10:01:00 +05302551 qdf_nbuf_free(nbuf);
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05302552 else {
2553 if (desc->flags & DP_TX_DESC_FLAG_TO_FW) {
2554 qdf_nbuf_free(nbuf);
2555 DP_STATS_INC(vdev, tx_i.mesh.completion_fw, 1);
2556 } else
2557 vdev->osif_tx_free_ext((nbuf));
Pamidipati, Vijay4f7c3052017-07-25 10:01:00 +05302558 }
2559}
2560
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05302561#ifdef MESH_MODE_SUPPORT
2562/**
2563 * dp_tx_comp_fill_tx_completion_stats() - Fill per packet Tx completion stats
2564 * in mesh meta header
2565 * @tx_desc: software descriptor head pointer
2566 * @ts: pointer to tx completion stats
2567 * Return: none
2568 */
2569static
2570void dp_tx_comp_fill_tx_completion_stats(struct dp_tx_desc_s *tx_desc,
2571 struct hal_tx_completion_status *ts)
2572{
2573 struct meta_hdr_s *mhdr;
2574 qdf_nbuf_t netbuf = tx_desc->nbuf;
2575
2576 if (!tx_desc->msdu_ext_desc) {
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +05302577 if (qdf_nbuf_pull_head(netbuf, tx_desc->pkt_offset) == NULL) {
2578 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +05302579 "netbuf %pK offset %d",
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +05302580 netbuf, tx_desc->pkt_offset);
2581 return;
2582 }
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05302583 }
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +05302584 if (qdf_nbuf_push_head(netbuf, sizeof(struct meta_hdr_s)) == NULL) {
2585 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathish2f3f5382019-02-18 09:51:35 +05302586 "netbuf %pK offset %lu", netbuf,
Venkateswara Swamy Bandaru6d840bc2017-07-10 15:35:28 +05302587 sizeof(struct meta_hdr_s));
2588 return;
2589 }
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05302590
2591 mhdr = (struct meta_hdr_s *)qdf_nbuf_data(netbuf);
2592 mhdr->rssi = ts->ack_frame_rssi;
Venkateswara Swamy Bandaru15c68da2017-05-18 11:54:20 +05302593 mhdr->channel = tx_desc->pdev->operating_channel;
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05302594}
2595
2596#else
2597static
2598void dp_tx_comp_fill_tx_completion_stats(struct dp_tx_desc_s *tx_desc,
2599 struct hal_tx_completion_status *ts)
2600{
2601}
2602
2603#endif
2604
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302605/**
Varsha Mishraa331e6e2019-03-11 12:16:14 +05302606 * dp_tx_compute_delay() - Compute and fill in all timestamps
2607 * to pass in correct fields
2608 *
2609 * @vdev: pdev handle
2610 * @tx_desc: tx descriptor
2611 * @tid: tid value
2612 * Return: none
2613 */
2614static void dp_tx_compute_delay(struct dp_vdev *vdev,
2615 struct dp_tx_desc_s *tx_desc, uint8_t tid)
2616{
2617 int64_t current_timestamp, timestamp_ingress, timestamp_hw_enqueue;
2618 uint32_t sw_enqueue_delay, fwhw_transmit_delay, interframe_delay;
2619
2620 if (qdf_likely(!vdev->pdev->delay_stats_flag))
2621 return;
2622
2623 current_timestamp = qdf_ktime_to_ms(qdf_ktime_get());
2624 timestamp_ingress = qdf_nbuf_get_timestamp(tx_desc->nbuf);
2625 timestamp_hw_enqueue = tx_desc->timestamp;
2626 sw_enqueue_delay = (uint32_t)(timestamp_hw_enqueue - timestamp_ingress);
2627 fwhw_transmit_delay = (uint32_t)(current_timestamp -
2628 timestamp_hw_enqueue);
2629 interframe_delay = (uint32_t)(timestamp_ingress -
2630 vdev->prev_tx_enq_tstamp);
2631
2632 /*
2633 * Delay in software enqueue
2634 */
2635 dp_update_delay_stats(vdev->pdev, sw_enqueue_delay, tid,
2636 CDP_DELAY_STATS_SW_ENQ);
2637 /*
2638 * Delay between packet enqueued to HW and Tx completion
2639 */
2640 dp_update_delay_stats(vdev->pdev, fwhw_transmit_delay, tid,
2641 CDP_DELAY_STATS_FW_HW_TRANSMIT);
2642
2643 /*
2644 * Update interframe delay stats calculated at hardstart receive point.
2645 * Value of vdev->prev_tx_enq_tstamp will be 0 for 1st frame, so
2646 * interframe delay will not be calculate correctly for 1st frame.
2647 * On the other side, this will help in avoiding extra per packet check
2648 * of !vdev->prev_tx_enq_tstamp.
2649 */
2650 dp_update_delay_stats(vdev->pdev, interframe_delay, tid,
2651 CDP_DELAY_STATS_TX_INTERFRAME);
2652 vdev->prev_tx_enq_tstamp = timestamp_ingress;
2653}
2654
2655/**
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302656 * dp_tx_update_peer_stats() - Update peer stats from Tx completion indications
Varsha Mishraa331e6e2019-03-11 12:16:14 +05302657 * @tx_desc: software descriptor head pointer
2658 * @ts: Tx completion status
2659 * @peer: peer handle
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302660 *
2661 * Return: None
2662 */
Amir Patel12550f62018-09-28 19:05:28 +05302663static inline void
Varsha Mishraa331e6e2019-03-11 12:16:14 +05302664dp_tx_update_peer_stats(struct dp_tx_desc_s *tx_desc,
2665 struct hal_tx_completion_status *ts,
2666 struct dp_peer *peer)
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302667{
2668 struct dp_pdev *pdev = peer->vdev->pdev;
phadiman49757302018-12-18 16:13:59 +05302669 struct dp_soc *soc = NULL;
Pamidipati, Vijay57a435a2017-10-17 11:03:39 +05302670 uint8_t mcs, pkt_type;
Varsha Mishra18281792019-03-06 17:57:23 +05302671 uint8_t tid = ts->tid;
Varsha Mishraa331e6e2019-03-11 12:16:14 +05302672 uint32_t length;
Varsha Mishra18281792019-03-06 17:57:23 +05302673 struct cdp_tid_tx_stats *tid_stats;
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302674
phadiman49757302018-12-18 16:13:59 +05302675 if (!pdev)
2676 return;
2677
Varsha Mishra18281792019-03-06 17:57:23 +05302678 if (qdf_unlikely(tid >= CDP_MAX_DATA_TIDS))
2679 tid = CDP_MAX_DATA_TIDS - 1;
2680
2681 tid_stats = &pdev->stats.tid_stats.tid_tx_stats[tid];
phadiman49757302018-12-18 16:13:59 +05302682 soc = pdev->soc;
2683
Pamidipati, Vijay57a435a2017-10-17 11:03:39 +05302684 mcs = ts->mcs;
2685 pkt_type = ts->pkt_type;
2686
Venkata Sharath Chandra Manchalad18887e2018-10-02 18:18:52 -07002687 if (ts->release_src != HAL_TX_COMP_RELEASE_SOURCE_TQM) {
2688 dp_err("Release source is not from TQM");
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302689 return;
Venkata Sharath Chandra Manchalad18887e2018-10-02 18:18:52 -07002690 }
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302691
Varsha Mishraa331e6e2019-03-11 12:16:14 +05302692 length = qdf_nbuf_len(tx_desc->nbuf);
Venkata Sharath Chandra Manchalaec9a5302018-12-13 15:25:35 -08002693 DP_STATS_INC_PKT(peer, tx.comp_pkt, 1, length);
Varsha Mishraa331e6e2019-03-11 12:16:14 +05302694
2695 if (qdf_unlikely(pdev->delay_stats_flag))
2696 dp_tx_compute_delay(peer->vdev, tx_desc, tid);
Varsha Mishra18281792019-03-06 17:57:23 +05302697 tid_stats->complete_cnt++;
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302698 DP_STATS_INCC(peer, tx.dropped.age_out, 1,
Venkata Sharath Chandra Manchalafaa0d8b2018-04-09 14:39:43 -07002699 (ts->status == HAL_TX_TQM_RR_REM_CMD_AGED));
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302700
Pranita Solanke05881142018-08-17 18:20:51 +05302701 DP_STATS_INCC_PKT(peer, tx.dropped.fw_rem, 1, length,
2702 (ts->status == HAL_TX_TQM_RR_REM_CMD_REM));
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302703
2704 DP_STATS_INCC(peer, tx.dropped.fw_rem_notx, 1,
Venkata Sharath Chandra Manchalafaa0d8b2018-04-09 14:39:43 -07002705 (ts->status == HAL_TX_TQM_RR_REM_CMD_NOTX));
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302706
2707 DP_STATS_INCC(peer, tx.dropped.fw_rem_tx, 1,
Venkata Sharath Chandra Manchalafaa0d8b2018-04-09 14:39:43 -07002708 (ts->status == HAL_TX_TQM_RR_REM_CMD_TX));
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302709
Venkata Sharath Chandra Manchala65812e62018-02-15 16:04:52 -08002710 DP_STATS_INCC(peer, tx.dropped.fw_reason1, 1,
Venkata Sharath Chandra Manchalafaa0d8b2018-04-09 14:39:43 -07002711 (ts->status == HAL_TX_TQM_RR_FW_REASON1));
Venkata Sharath Chandra Manchala65812e62018-02-15 16:04:52 -08002712
2713 DP_STATS_INCC(peer, tx.dropped.fw_reason2, 1,
Venkata Sharath Chandra Manchalafaa0d8b2018-04-09 14:39:43 -07002714 (ts->status == HAL_TX_TQM_RR_FW_REASON2));
Venkata Sharath Chandra Manchala65812e62018-02-15 16:04:52 -08002715
2716 DP_STATS_INCC(peer, tx.dropped.fw_reason3, 1,
Venkata Sharath Chandra Manchalafaa0d8b2018-04-09 14:39:43 -07002717 (ts->status == HAL_TX_TQM_RR_FW_REASON3));
Venkata Sharath Chandra Manchala65812e62018-02-15 16:04:52 -08002718
Venkata Sharath Chandra Manchalad18887e2018-10-02 18:18:52 -07002719 if (ts->status != HAL_TX_TQM_RR_FRAME_ACKED) {
Varsha Mishra18281792019-03-06 17:57:23 +05302720 tid_stats->comp_fail_cnt++;
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302721 return;
Venkata Sharath Chandra Manchalad18887e2018-10-02 18:18:52 -07002722 }
Varsha Mishra18281792019-03-06 17:57:23 +05302723
2724 tid_stats->success_cnt++;
2725
Pamidipati, Vijay57a435a2017-10-17 11:03:39 +05302726 DP_STATS_INCC(peer, tx.ofdma, 1, ts->ofdma);
Pranita Solankefc2ff392017-12-15 19:25:13 +05302727
Pamidipati, Vijay57a435a2017-10-17 11:03:39 +05302728 DP_STATS_INCC(peer, tx.amsdu_cnt, 1, ts->msdu_part_of_amsdu);
Anish Nataraj50347012018-03-06 21:12:45 +05302729 DP_STATS_INCC(peer, tx.non_amsdu_cnt, 1, !ts->msdu_part_of_amsdu);
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302730
Amir Patel12550f62018-09-28 19:05:28 +05302731 /*
2732 * Following Rate Statistics are updated from HTT PPDU events from FW.
2733 * Return from here if HTT PPDU events are enabled.
2734 */
Pamidipati, Vijay57a435a2017-10-17 11:03:39 +05302735 if (!(soc->process_tx_status))
2736 return;
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302737
Pranita Solankeed0aba62018-01-12 19:14:31 +05302738 DP_STATS_INCC(peer, tx.pkt_type[pkt_type].mcs_count[MAX_MCS - 1], 1,
Pamidipati, Vijay57a435a2017-10-17 11:03:39 +05302739 ((mcs >= MAX_MCS_11A) && (pkt_type == DOT11_A)));
2740 DP_STATS_INCC(peer, tx.pkt_type[pkt_type].mcs_count[mcs], 1,
2741 ((mcs < (MAX_MCS_11A)) && (pkt_type == DOT11_A)));
Pranita Solankeed0aba62018-01-12 19:14:31 +05302742 DP_STATS_INCC(peer, tx.pkt_type[pkt_type].mcs_count[MAX_MCS - 1], 1,
Pamidipati, Vijay57a435a2017-10-17 11:03:39 +05302743 ((mcs >= MAX_MCS_11B) && (pkt_type == DOT11_B)));
2744 DP_STATS_INCC(peer, tx.pkt_type[pkt_type].mcs_count[mcs], 1,
2745 ((mcs < MAX_MCS_11B) && (pkt_type == DOT11_B)));
Pranita Solankeed0aba62018-01-12 19:14:31 +05302746 DP_STATS_INCC(peer, tx.pkt_type[pkt_type].mcs_count[MAX_MCS - 1], 1,
Pamidipati, Vijay57a435a2017-10-17 11:03:39 +05302747 ((mcs >= MAX_MCS_11A) && (pkt_type == DOT11_N)));
2748 DP_STATS_INCC(peer, tx.pkt_type[pkt_type].mcs_count[mcs], 1,
2749 ((mcs < MAX_MCS_11A) && (pkt_type == DOT11_N)));
Pranita Solankeed0aba62018-01-12 19:14:31 +05302750 DP_STATS_INCC(peer, tx.pkt_type[pkt_type].mcs_count[MAX_MCS - 1], 1,
Pamidipati, Vijay57a435a2017-10-17 11:03:39 +05302751 ((mcs >= MAX_MCS_11AC) && (pkt_type == DOT11_AC)));
2752 DP_STATS_INCC(peer, tx.pkt_type[pkt_type].mcs_count[mcs], 1,
2753 ((mcs < MAX_MCS_11AC) && (pkt_type == DOT11_AC)));
Pranita Solankeed0aba62018-01-12 19:14:31 +05302754 DP_STATS_INCC(peer, tx.pkt_type[pkt_type].mcs_count[MAX_MCS - 1], 1,
Pamidipati, Vijay57a435a2017-10-17 11:03:39 +05302755 ((mcs >= (MAX_MCS - 1)) && (pkt_type == DOT11_AX)));
2756 DP_STATS_INCC(peer, tx.pkt_type[pkt_type].mcs_count[mcs], 1,
2757 ((mcs < (MAX_MCS - 1)) && (pkt_type == DOT11_AX)));
Amir Patel12550f62018-09-28 19:05:28 +05302758
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302759 DP_STATS_INC(peer, tx.sgi_count[ts->sgi], 1);
2760 DP_STATS_INC(peer, tx.bw[ts->bw], 1);
2761 DP_STATS_UPD(peer, tx.last_ack_rssi, ts->ack_frame_rssi);
2762 DP_STATS_INC(peer, tx.wme_ac_type[TID_TO_WME_AC(ts->tid)], 1);
2763 DP_STATS_INCC(peer, tx.stbc, 1, ts->stbc);
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302764 DP_STATS_INCC(peer, tx.ldpc, 1, ts->ldpc);
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302765 DP_STATS_INCC(peer, tx.retries, 1, ts->transmit_cnt > 1);
2766
Amir Patel756d05e2018-10-10 12:35:30 +05302767#if defined(FEATURE_PERPKT_INFO) && WDI_EVENT_ENABLE
2768 dp_wdi_event_handler(WDI_EVENT_UPDATE_DP_STATS, pdev->soc,
2769 &peer->stats, ts->peer_id,
2770 UPDATE_PEER_STATS, pdev->pdev_id);
2771#endif
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05302772}
Venkateswara Swamy Bandaru3f623702017-02-25 00:12:59 +05302773
Yun Parkaadee8c2018-06-04 11:21:40 -07002774#ifdef QCA_LL_TX_FLOW_CONTROL_V2
2775/**
2776 * dp_tx_flow_pool_lock() - take flow pool lock
2777 * @soc: core txrx main context
2778 * @tx_desc: tx desc
2779 *
2780 * Return: None
2781 */
2782static inline
2783void dp_tx_flow_pool_lock(struct dp_soc *soc,
2784 struct dp_tx_desc_s *tx_desc)
2785{
2786 struct dp_tx_desc_pool_s *pool;
2787 uint8_t desc_pool_id;
2788
2789 desc_pool_id = tx_desc->pool_id;
2790 pool = &soc->tx_desc[desc_pool_id];
2791
2792 qdf_spin_lock_bh(&pool->flow_pool_lock);
2793}
2794
2795/**
2796 * dp_tx_flow_pool_unlock() - release flow pool lock
2797 * @soc: core txrx main context
2798 * @tx_desc: tx desc
2799 *
2800 * Return: None
2801 */
2802static inline
2803void dp_tx_flow_pool_unlock(struct dp_soc *soc,
2804 struct dp_tx_desc_s *tx_desc)
2805{
2806 struct dp_tx_desc_pool_s *pool;
2807 uint8_t desc_pool_id;
2808
2809 desc_pool_id = tx_desc->pool_id;
2810 pool = &soc->tx_desc[desc_pool_id];
2811
2812 qdf_spin_unlock_bh(&pool->flow_pool_lock);
2813}
2814#else
2815static inline
2816void dp_tx_flow_pool_lock(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc)
2817{
2818}
2819
2820static inline
2821void dp_tx_flow_pool_unlock(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc)
2822{
2823}
2824#endif
2825
2826/**
2827 * dp_tx_notify_completion() - Notify tx completion for this desc
2828 * @soc: core txrx main context
2829 * @tx_desc: tx desc
2830 * @netbuf: buffer
2831 *
2832 * Return: none
2833 */
2834static inline void dp_tx_notify_completion(struct dp_soc *soc,
2835 struct dp_tx_desc_s *tx_desc,
2836 qdf_nbuf_t netbuf)
2837{
2838 void *osif_dev;
2839 ol_txrx_completion_fp tx_compl_cbk = NULL;
2840
2841 qdf_assert(tx_desc);
2842
2843 dp_tx_flow_pool_lock(soc, tx_desc);
2844
2845 if (!tx_desc->vdev ||
2846 !tx_desc->vdev->osif_vdev) {
2847 dp_tx_flow_pool_unlock(soc, tx_desc);
2848 return;
2849 }
2850
2851 osif_dev = tx_desc->vdev->osif_vdev;
2852 tx_compl_cbk = tx_desc->vdev->tx_comp;
2853 dp_tx_flow_pool_unlock(soc, tx_desc);
2854
2855 if (tx_compl_cbk)
2856 tx_compl_cbk(netbuf, osif_dev);
2857}
2858
Ruchi, Agrawal2cbca3b2018-06-20 19:31:03 +05302859/** dp_tx_sojourn_stats_process() - Collect sojourn stats
2860 * @pdev: pdev handle
2861 * @tid: tid value
2862 * @txdesc_ts: timestamp from txdesc
2863 * @ppdu_id: ppdu id
2864 *
2865 * Return: none
2866 */
2867#ifdef FEATURE_PERPKT_INFO
2868static inline void dp_tx_sojourn_stats_process(struct dp_pdev *pdev,
Amir Patel468bded2019-03-21 11:42:31 +05302869 struct dp_peer *peer,
Ruchi, Agrawal2cbca3b2018-06-20 19:31:03 +05302870 uint8_t tid,
2871 uint64_t txdesc_ts,
2872 uint32_t ppdu_id)
2873{
2874 uint64_t delta_ms;
2875 struct cdp_tx_sojourn_stats *sojourn_stats;
2876
Amir Patelac7d9462019-03-28 16:16:01 +05302877 if (qdf_unlikely(pdev->enhanced_stats_en == 0))
Ruchi, Agrawal2cbca3b2018-06-20 19:31:03 +05302878 return;
2879
Amir Patelac7d9462019-03-28 16:16:01 +05302880 if (qdf_unlikely(tid == HTT_INVALID_TID ||
2881 tid >= CDP_DATA_TID_MAX))
Ruchi, Agrawal2cbca3b2018-06-20 19:31:03 +05302882 return;
2883
Amir Patelac7d9462019-03-28 16:16:01 +05302884 if (qdf_unlikely(!pdev->sojourn_buf))
2885 return;
2886
2887 sojourn_stats = (struct cdp_tx_sojourn_stats *)
2888 qdf_nbuf_data(pdev->sojourn_buf);
2889
2890 sojourn_stats->cookie = (void *)peer->wlanstats_ctx;
2891
Ruchi, Agrawal2cbca3b2018-06-20 19:31:03 +05302892 delta_ms = qdf_ktime_to_ms(qdf_ktime_get()) -
2893 txdesc_ts;
Amir Patelac7d9462019-03-28 16:16:01 +05302894 qdf_ewma_tx_lag_add(&peer->avg_sojourn_msdu[tid],
Ruchi, Agrawal2cbca3b2018-06-20 19:31:03 +05302895 delta_ms);
Amir Patelac7d9462019-03-28 16:16:01 +05302896 sojourn_stats->sum_sojourn_msdu[tid] = delta_ms;
2897 sojourn_stats->num_msdus[tid] = 1;
2898 sojourn_stats->avg_sojourn_msdu[tid].internal =
2899 peer->avg_sojourn_msdu[tid].internal;
2900 dp_wdi_event_handler(WDI_EVENT_TX_SOJOURN_STAT, pdev->soc,
2901 pdev->sojourn_buf, HTT_INVALID_PEER,
2902 WDI_NO_VAL, pdev->pdev_id);
2903 sojourn_stats->sum_sojourn_msdu[tid] = 0;
2904 sojourn_stats->num_msdus[tid] = 0;
2905 sojourn_stats->avg_sojourn_msdu[tid].internal = 0;
Ruchi, Agrawal2cbca3b2018-06-20 19:31:03 +05302906}
2907#else
2908static inline void dp_tx_sojourn_stats_process(struct dp_pdev *pdev,
2909 uint8_t tid,
2910 uint64_t txdesc_ts,
2911 uint32_t ppdu_id)
2912{
2913}
2914#endif
2915
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05302916/**
Amir Patel12550f62018-09-28 19:05:28 +05302917 * dp_tx_comp_process_desc() - Process tx descriptor and free associated nbuf
2918 * @soc: DP Soc handle
2919 * @tx_desc: software Tx descriptor
2920 * @ts : Tx completion status from HAL/HTT descriptor
2921 *
2922 * Return: none
2923 */
2924static inline void
2925dp_tx_comp_process_desc(struct dp_soc *soc,
2926 struct dp_tx_desc_s *desc,
2927 struct hal_tx_completion_status *ts,
2928 struct dp_peer *peer)
2929{
Ankit Kumar8dc0e2a2019-02-28 18:17:15 +05302930 uint64_t time_latency = 0;
Amir Patel12550f62018-09-28 19:05:28 +05302931 /*
2932 * m_copy/tx_capture modes are not supported for
2933 * scatter gather packets
2934 */
Ankit Kumar8dc0e2a2019-02-28 18:17:15 +05302935 if (qdf_unlikely(!!desc->pdev->latency_capture_enable)) {
2936 time_latency = (qdf_ktime_to_ms(qdf_ktime_get()) -
2937 desc->timestamp);
2938 }
nobeljdebe2b32019-04-23 11:18:47 -07002939 if (!(desc->msdu_ext_desc)) {
2940 if (QDF_STATUS_SUCCESS ==
2941 dp_tx_add_to_comp_queue(soc, desc, ts, peer)) {
2942 return;
2943 }
Amir Patel12550f62018-09-28 19:05:28 +05302944
nobeljdebe2b32019-04-23 11:18:47 -07002945 if (QDF_STATUS_SUCCESS ==
2946 dp_get_completion_indication_for_stack(soc,
2947 desc->pdev,
2948 peer, ts,
2949 desc->nbuf,
2950 time_latency)) {
2951 qdf_nbuf_unmap(soc->osdev, desc->nbuf,
2952 QDF_DMA_TO_DEVICE);
2953 dp_send_completion_to_stack(soc,
2954 desc->pdev,
2955 ts->peer_id,
2956 ts->ppdu_id,
2957 desc->nbuf);
2958 return;
2959 }
Amir Patel12550f62018-09-28 19:05:28 +05302960 }
nobeljdebe2b32019-04-23 11:18:47 -07002961
2962 dp_tx_comp_free_buf(soc, desc);
Amir Patel12550f62018-09-28 19:05:28 +05302963}
2964
2965/**
Vijay Pamidipati5bcfa312016-12-20 11:44:38 +05302966 * dp_tx_comp_process_tx_status() - Parse and Dump Tx completion status info
2967 * @tx_desc: software descriptor head pointer
Amir Patel12550f62018-09-28 19:05:28 +05302968 * @ts: Tx completion status
Sravan Kumar Kairam26d471e2018-08-14 23:51:58 +05302969 * @peer: peer handle
Vijay Pamidipati5bcfa312016-12-20 11:44:38 +05302970 *
Vijay Pamidipati5bcfa312016-12-20 11:44:38 +05302971 * Return: none
2972 */
Sravan Kumar Kairam26d471e2018-08-14 23:51:58 +05302973static inline
2974void dp_tx_comp_process_tx_status(struct dp_tx_desc_s *tx_desc,
Amir Patel12550f62018-09-28 19:05:28 +05302975 struct hal_tx_completion_status *ts,
2976 struct dp_peer *peer)
Vijay Pamidipati5bcfa312016-12-20 11:44:38 +05302977{
Amir Patel12550f62018-09-28 19:05:28 +05302978 uint32_t length;
Pamidipati, Vijaycd7fda82019-03-18 10:55:00 +05302979 qdf_ether_header_t *eh;
Ishank Jain1e7401c2017-02-17 15:38:39 +05302980 struct dp_soc *soc = NULL;
2981 struct dp_vdev *vdev = tx_desc->vdev;
Pamidipati, Vijaycd7fda82019-03-18 10:55:00 +05302982 qdf_nbuf_t nbuf = tx_desc->nbuf;
Pranita Solankea5a3ae72018-01-18 21:45:27 +05302983
Pamidipati, Vijaycd7fda82019-03-18 10:55:00 +05302984 if (!vdev || !nbuf) {
Balamurugan Mahalingamdb121812018-08-30 11:35:44 +05302985 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
Pamidipati, Vijaycd7fda82019-03-18 10:55:00 +05302986 "invalid tx descriptor. vdev or nbuf NULL");
Balamurugan Mahalingamdb121812018-08-30 11:35:44 +05302987 goto out;
2988 }
2989
Pamidipati, Vijaycd7fda82019-03-18 10:55:00 +05302990 eh = (qdf_ether_header_t *)qdf_nbuf_data(nbuf);
2991
Manjunathappa Prakash721bd5f2019-01-18 16:25:16 -08002992 DPTRACE(qdf_dp_trace_ptr(tx_desc->nbuf,
2993 QDF_DP_TRACE_LI_DP_FREE_PACKET_PTR_RECORD,
2994 QDF_TRACE_DEFAULT_PDEV_ID,
Pamidipati, Vijaycd7fda82019-03-18 10:55:00 +05302995 qdf_nbuf_data_addr(nbuf),
2996 sizeof(qdf_nbuf_data(nbuf)),
Manjunathappa Prakash721bd5f2019-01-18 16:25:16 -08002997 tx_desc->id,
2998 ts->status));
2999
Yun Park11d46e02017-11-27 10:51:53 -08003000 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
Vijay Pamidipatid61006c2017-01-20 19:35:57 +05303001 "-------------------- \n"
3002 "Tx Completion Stats: \n"
3003 "-------------------- \n"
3004 "ack_frame_rssi = %d \n"
3005 "first_msdu = %d \n"
3006 "last_msdu = %d \n"
3007 "msdu_part_of_amsdu = %d \n"
3008 "rate_stats valid = %d \n"
3009 "bw = %d \n"
3010 "pkt_type = %d \n"
3011 "stbc = %d \n"
3012 "ldpc = %d \n"
3013 "sgi = %d \n"
3014 "mcs = %d \n"
3015 "ofdma = %d \n"
3016 "tones_in_ru = %d \n"
3017 "tsf = %d \n"
3018 "ppdu_id = %d \n"
3019 "transmit_cnt = %d \n"
3020 "tid = %d \n"
Amir Patel12550f62018-09-28 19:05:28 +05303021 "peer_id = %d\n",
3022 ts->ack_frame_rssi, ts->first_msdu,
3023 ts->last_msdu, ts->msdu_part_of_amsdu,
3024 ts->valid, ts->bw, ts->pkt_type, ts->stbc,
3025 ts->ldpc, ts->sgi, ts->mcs, ts->ofdma,
3026 ts->tones_in_ru, ts->tsf, ts->ppdu_id,
3027 ts->transmit_cnt, ts->tid, ts->peer_id);
Vijay Pamidipati5bcfa312016-12-20 11:44:38 +05303028
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05303029 soc = vdev->pdev->soc;
3030
3031 /* Update SoC level stats */
3032 DP_STATS_INCC(soc, tx.dropped_fw_removed, 1,
Amir Patel12550f62018-09-28 19:05:28 +05303033 (ts->status == HAL_TX_TQM_RR_REM_CMD_REM));
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05303034
Amir Patel12550f62018-09-28 19:05:28 +05303035 /* Update per-packet stats for mesh mode */
Venkateswara Swamy Bandaru58c80852018-01-29 17:52:02 +05303036 if (qdf_unlikely(vdev->mesh_vdev) &&
3037 !(tx_desc->flags & DP_TX_DESC_FLAG_TO_FW))
Amir Patel12550f62018-09-28 19:05:28 +05303038 dp_tx_comp_fill_tx_completion_stats(tx_desc, ts);
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05303039
Pamidipati, Vijaycd7fda82019-03-18 10:55:00 +05303040 length = qdf_nbuf_len(nbuf);
Pamidipati, Vijay623fbee2017-07-07 10:58:15 +05303041 /* Update peer level stats */
Ishank Jain1e7401c2017-02-17 15:38:39 +05303042 if (!peer) {
Sravan Kumar Kairam1bffc852018-12-04 21:45:23 +05303043 QDF_TRACE_DEBUG_RL(QDF_MODULE_ID_DP,
3044 "peer is null or deletion in progress");
Ishank Jaine73c4032017-03-16 11:48:15 +05303045 DP_STATS_INC_PKT(soc, tx.tx_invalid_peer, 1, length);
Ishank Jain1e7401c2017-02-17 15:38:39 +05303046 goto out;
3047 }
Pranita Solankea5a3ae72018-01-18 21:45:27 +05303048
Amir Patel12550f62018-09-28 19:05:28 +05303049 if (qdf_likely(!peer->bss_peer)) {
3050 DP_STATS_INC_PKT(peer, tx.ucast, 1, length);
3051
3052 if (ts->status == HAL_TX_TQM_RR_FRAME_ACKED)
3053 DP_STATS_INC_PKT(peer, tx.tx_success, 1, length);
3054 } else {
3055 if (ts->status != HAL_TX_TQM_RR_REM_CMD_REM) {
3056 DP_STATS_INC_PKT(peer, tx.mcast, 1, length);
3057
3058 if ((peer->vdev->tx_encap_type ==
3059 htt_cmn_pkt_type_ethernet) &&
Srinivas Girigowda79502972019-02-11 12:25:12 -08003060 QDF_IS_ADDR_BROADCAST(eh->ether_dhost)) {
Amir Patel12550f62018-09-28 19:05:28 +05303061 DP_STATS_INC_PKT(peer, tx.bcast, 1, length);
3062 }
3063 }
Pranita Solankea5a3ae72018-01-18 21:45:27 +05303064 }
Ishank Jain1e7401c2017-02-17 15:38:39 +05303065
Varsha Mishraa331e6e2019-03-11 12:16:14 +05303066 dp_tx_update_peer_stats(tx_desc, ts, peer);
Ishank Jain1e7401c2017-02-17 15:38:39 +05303067
Amir Patel468bded2019-03-21 11:42:31 +05303068#ifdef QCA_SUPPORT_RDK_STATS
3069 if (soc->wlanstats_enabled)
3070 dp_tx_sojourn_stats_process(vdev->pdev, peer, ts->tid,
3071 tx_desc->timestamp,
3072 ts->ppdu_id);
3073#endif
3074
Ishank Jain1e7401c2017-02-17 15:38:39 +05303075out:
Ishank Jain1e7401c2017-02-17 15:38:39 +05303076 return;
Vijay Pamidipati5bcfa312016-12-20 11:44:38 +05303077}
Vijay Pamidipati5bcfa312016-12-20 11:44:38 +05303078/**
Amir Patel12550f62018-09-28 19:05:28 +05303079 * dp_tx_comp_process_desc_list() - Tx complete software descriptor handler
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303080 * @soc: core txrx main context
3081 * @comp_head: software descriptor head pointer
3082 *
3083 * This function will process batch of descriptors reaped by dp_tx_comp_handler
3084 * and release the software descriptors after processing is complete
3085 *
3086 * Return: none
3087 */
Amir Patel12550f62018-09-28 19:05:28 +05303088static void
3089dp_tx_comp_process_desc_list(struct dp_soc *soc,
3090 struct dp_tx_desc_s *comp_head)
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303091{
3092 struct dp_tx_desc_s *desc;
3093 struct dp_tx_desc_s *next;
Ishank Jainbc2d91f2017-01-03 18:14:54 +05303094 struct hal_tx_completion_status ts = {0};
Ishank Jain1e7401c2017-02-17 15:38:39 +05303095 struct dp_peer *peer;
Sravan Kumar Kairamd55a74c2019-04-03 16:00:57 +05303096 qdf_nbuf_t netbuf;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303097
3098 desc = comp_head;
3099
3100 while (desc) {
Balamurugan Mahalingam3715aa42018-08-22 02:13:14 +05303101 hal_tx_comp_get_status(&desc->comp, &ts, soc->hal_soc);
Ishank Jain1e7401c2017-02-17 15:38:39 +05303102 peer = dp_peer_find_by_id(soc, ts.peer_id);
Amir Patel12550f62018-09-28 19:05:28 +05303103 dp_tx_comp_process_tx_status(desc, &ts, peer);
Sravan Kumar Kairamd55a74c2019-04-03 16:00:57 +05303104
3105 netbuf = desc->nbuf;
3106 /* check tx complete notification */
3107 if (QDF_NBUF_CB_TX_EXTRA_FRAG_FLAGS_NOTIFY_COMP(netbuf))
3108 dp_tx_notify_completion(soc, desc, netbuf);
3109
Amir Patel12550f62018-09-28 19:05:28 +05303110 dp_tx_comp_process_desc(soc, desc, &ts, peer);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303111
Sravan Kumar Kairam26d471e2018-08-14 23:51:58 +05303112 if (peer)
3113 dp_peer_unref_del_find_by_id(peer);
3114
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303115 next = desc->next;
Ruchi, Agrawal2cbca3b2018-06-20 19:31:03 +05303116
Ravi Joshiab33d9b2017-02-11 21:43:28 -08003117 dp_tx_desc_release(desc, desc->pool_id);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303118 desc = next;
3119 }
Ruchi, Agrawal2cbca3b2018-06-20 19:31:03 +05303120
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303121}
3122
3123/**
Amir Patel12550f62018-09-28 19:05:28 +05303124 * dp_tx_process_htt_completion() - Tx HTT Completion Indication Handler
3125 * @tx_desc: software descriptor head pointer
3126 * @status : Tx completion status from HTT descriptor
3127 *
3128 * This function will process HTT Tx indication messages from Target
3129 *
3130 * Return: none
3131 */
3132static
3133void dp_tx_process_htt_completion(struct dp_tx_desc_s *tx_desc, uint8_t *status)
3134{
3135 uint8_t tx_status;
3136 struct dp_pdev *pdev;
3137 struct dp_vdev *vdev;
3138 struct dp_soc *soc;
3139 struct hal_tx_completion_status ts = {0};
3140 uint32_t *htt_desc = (uint32_t *)status;
3141 struct dp_peer *peer;
Varsha Mishra18281792019-03-06 17:57:23 +05303142 struct cdp_tid_tx_stats *tid_stats = NULL;
Amir Patel12550f62018-09-28 19:05:28 +05303143
3144 qdf_assert(tx_desc->pdev);
3145
3146 pdev = tx_desc->pdev;
3147 vdev = tx_desc->vdev;
3148 soc = pdev->soc;
3149
Pamidipati, Vijaycd7fda82019-03-18 10:55:00 +05303150 if (!vdev)
3151 return;
3152
Amir Patel12550f62018-09-28 19:05:28 +05303153 tx_status = HTT_TX_WBM_COMPLETION_V2_TX_STATUS_GET(htt_desc[0]);
3154
3155 switch (tx_status) {
3156 case HTT_TX_FW2WBM_TX_STATUS_OK:
3157 case HTT_TX_FW2WBM_TX_STATUS_DROP:
3158 case HTT_TX_FW2WBM_TX_STATUS_TTL:
3159 {
Varsha Mishra18281792019-03-06 17:57:23 +05303160 uint8_t tid;
Amir Patel12550f62018-09-28 19:05:28 +05303161 if (HTT_TX_WBM_COMPLETION_V2_VALID_GET(htt_desc[2])) {
3162 ts.peer_id =
3163 HTT_TX_WBM_COMPLETION_V2_SW_PEER_ID_GET(
3164 htt_desc[2]);
3165 ts.tid =
3166 HTT_TX_WBM_COMPLETION_V2_TID_NUM_GET(
3167 htt_desc[2]);
3168 } else {
3169 ts.peer_id = HTT_INVALID_PEER;
3170 ts.tid = HTT_INVALID_TID;
3171 }
3172 ts.ppdu_id =
3173 HTT_TX_WBM_COMPLETION_V2_SCH_CMD_ID_GET(
3174 htt_desc[1]);
3175 ts.ack_frame_rssi =
3176 HTT_TX_WBM_COMPLETION_V2_ACK_FRAME_RSSI_GET(
3177 htt_desc[1]);
3178
3179 ts.first_msdu = 1;
3180 ts.last_msdu = 1;
Varsha Mishra18281792019-03-06 17:57:23 +05303181 tid = ts.tid;
3182 if (qdf_unlikely(tid >= CDP_MAX_DATA_TIDS))
3183 tid = CDP_MAX_DATA_TIDS - 1;
Amir Patel12550f62018-09-28 19:05:28 +05303184
Varsha Mishra18281792019-03-06 17:57:23 +05303185 tid_stats = &pdev->stats.tid_stats.tid_tx_stats[tid];
3186
Varsha Mishraa331e6e2019-03-11 12:16:14 +05303187 if (qdf_unlikely(pdev->delay_stats_flag))
3188 dp_tx_compute_delay(vdev, tx_desc, tid);
Varsha Mishra18281792019-03-06 17:57:23 +05303189 tid_stats->complete_cnt++;
3190 if (qdf_unlikely(tx_status != HTT_TX_FW2WBM_TX_STATUS_OK)) {
Amir Patel12550f62018-09-28 19:05:28 +05303191 ts.status = HAL_TX_TQM_RR_REM_CMD_REM;
Varsha Mishra18281792019-03-06 17:57:23 +05303192 tid_stats->comp_fail_cnt++;
3193 } else {
3194 tid_stats->success_cnt++;
3195 }
Amir Patel12550f62018-09-28 19:05:28 +05303196
3197 peer = dp_peer_find_by_id(soc, ts.peer_id);
Pamidipati, Vijay7d695722018-11-24 19:41:49 +05303198
3199 if (qdf_likely(peer))
chenguo420a4422018-11-12 18:07:26 +08003200 dp_peer_unref_del_find_by_id(peer);
Pamidipati, Vijay7d695722018-11-24 19:41:49 +05303201
3202 dp_tx_comp_process_tx_status(tx_desc, &ts, peer);
3203 dp_tx_comp_process_desc(soc, tx_desc, &ts, peer);
Amir Patel12550f62018-09-28 19:05:28 +05303204 dp_tx_desc_release(tx_desc, tx_desc->pool_id);
3205
3206 break;
3207 }
3208 case HTT_TX_FW2WBM_TX_STATUS_REINJECT:
3209 {
3210 dp_tx_reinject_handler(tx_desc, status);
3211 break;
3212 }
3213 case HTT_TX_FW2WBM_TX_STATUS_INSPECT:
3214 {
3215 dp_tx_inspect_handler(tx_desc, status);
3216 break;
3217 }
3218 case HTT_TX_FW2WBM_TX_STATUS_MEC_NOTIFY:
3219 {
3220 dp_tx_mec_handler(vdev, status);
3221 break;
3222 }
3223 default:
3224 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_DEBUG,
3225 "%s Invalid HTT tx_status %d\n",
3226 __func__, tx_status);
3227 break;
3228 }
3229}
3230
Mohit Khannae5a6e942018-11-28 14:22:48 -08003231#ifdef WLAN_FEATURE_RX_SOFTIRQ_TIME_LIMIT
3232static inline
3233bool dp_tx_comp_loop_pkt_limit_hit(struct dp_soc *soc, int num_reaped)
3234{
3235 bool limit_hit = false;
3236 struct wlan_cfg_dp_soc_ctxt *cfg = soc->wlan_cfg_ctx;
3237
3238 limit_hit =
3239 (num_reaped >= cfg->tx_comp_loop_pkt_limit) ? true : false;
3240
3241 if (limit_hit)
3242 DP_STATS_INC(soc, tx.tx_comp_loop_pkt_limit_hit, 1);
3243
3244 return limit_hit;
3245}
3246
3247static inline bool dp_tx_comp_enable_eol_data_check(struct dp_soc *soc)
3248{
3249 return soc->wlan_cfg_ctx->tx_comp_enable_eol_data_check;
3250}
3251#else
3252static inline
3253bool dp_tx_comp_loop_pkt_limit_hit(struct dp_soc *soc, int num_reaped)
3254{
3255 return false;
3256}
3257
3258static inline bool dp_tx_comp_enable_eol_data_check(struct dp_soc *soc)
3259{
3260 return false;
3261}
3262#endif
3263
3264uint32_t dp_tx_comp_handler(struct dp_intr *int_ctx, struct dp_soc *soc,
3265 void *hal_srng, uint32_t quota)
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303266{
3267 void *tx_comp_hal_desc;
3268 uint8_t buffer_src;
3269 uint8_t pool_id;
3270 uint32_t tx_desc_id;
3271 struct dp_tx_desc_s *tx_desc = NULL;
3272 struct dp_tx_desc_s *head_desc = NULL;
3273 struct dp_tx_desc_s *tail_desc = NULL;
Mohit Khannae5a6e942018-11-28 14:22:48 -08003274 uint32_t num_processed = 0;
3275 uint32_t count = 0;
3276 bool force_break = false;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303277
Mohit Khannae5a6e942018-11-28 14:22:48 -08003278 DP_HIST_INIT();
3279
3280more_data:
3281 /* Re-initialize local variables to be re-used */
3282 head_desc = NULL;
3283 tail_desc = NULL;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303284 if (qdf_unlikely(hal_srng_access_start(soc->hal_soc, hal_srng))) {
3285 QDF_TRACE(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +05303286 "%s %d : HAL RING Access Failed -- %pK",
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303287 __func__, __LINE__, hal_srng);
3288 return 0;
3289 }
3290
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303291 /* Find head descriptor from completion ring */
3292 while (qdf_likely(tx_comp_hal_desc =
3293 hal_srng_dst_get_next(soc->hal_soc, hal_srng))) {
3294
3295 buffer_src = hal_tx_comp_get_buffer_source(tx_comp_hal_desc);
3296
3297 /* If this buffer was not released by TQM or FW, then it is not
Pamidipati, Vijay9e340252017-08-14 16:24:17 +05303298 * Tx completion indication, assert */
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303299 if ((buffer_src != HAL_TX_COMP_RELEASE_SOURCE_TQM) &&
3300 (buffer_src != HAL_TX_COMP_RELEASE_SOURCE_FW)) {
3301
3302 QDF_TRACE(QDF_MODULE_ID_DP,
chenguo73c7b7c2019-01-22 14:07:12 +08003303 QDF_TRACE_LEVEL_FATAL,
3304 "Tx comp release_src != TQM | FW but from %d",
3305 buffer_src);
3306 hal_dump_comp_desc(tx_comp_hal_desc);
3307 DP_STATS_INC(soc, tx.invalid_release_source, 1);
Pamidipati, Vijay9e340252017-08-14 16:24:17 +05303308 qdf_assert_always(0);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303309 }
3310
3311 /* Get descriptor id */
3312 tx_desc_id = hal_tx_comp_get_desc_id(tx_comp_hal_desc);
3313 pool_id = (tx_desc_id & DP_TX_DESC_ID_POOL_MASK) >>
3314 DP_TX_DESC_ID_POOL_OS;
3315
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303316 /* Find Tx descriptor */
3317 tx_desc = dp_tx_desc_find(soc, pool_id,
3318 (tx_desc_id & DP_TX_DESC_ID_PAGE_MASK) >>
3319 DP_TX_DESC_ID_PAGE_OS,
3320 (tx_desc_id & DP_TX_DESC_ID_OFFSET_MASK) >>
3321 DP_TX_DESC_ID_OFFSET_OS);
3322
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303323 /*
Pamidipati, Vijay12e8f332018-06-13 20:13:13 +05303324 * If the descriptor is already freed in vdev_detach,
3325 * continue to next descriptor
3326 */
Jinwei Chen79b4fc82019-04-26 13:27:27 +08003327 if (!tx_desc->vdev && !tx_desc->flags) {
Pamidipati, Vijay12e8f332018-06-13 20:13:13 +05303328 QDF_TRACE(QDF_MODULE_ID_DP,
3329 QDF_TRACE_LEVEL_INFO,
3330 "Descriptor freed in vdev_detach %d",
3331 tx_desc_id);
3332
3333 num_processed += !(count & DP_TX_NAPI_BUDGET_DIV_MASK);
3334 count++;
3335 continue;
3336 }
3337
3338 /*
Pamidipati, Vijay9e340252017-08-14 16:24:17 +05303339 * If the release source is FW, process the HTT status
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303340 */
3341 if (qdf_unlikely(buffer_src ==
3342 HAL_TX_COMP_RELEASE_SOURCE_FW)) {
3343 uint8_t htt_tx_status[HAL_TX_COMP_HTT_STATUS_LEN];
3344 hal_tx_comp_get_htt_desc(tx_comp_hal_desc,
3345 htt_tx_status);
3346 dp_tx_process_htt_completion(tx_desc,
3347 htt_tx_status);
3348 } else {
Ruchi, Agrawalc0f9c972018-02-02 11:24:05 +05303349 /* Pool id is not matching. Error */
Ruchi, Agrawale8eeb442018-02-12 16:19:58 +05303350 if (tx_desc->pool_id != pool_id) {
Ruchi, Agrawalc0f9c972018-02-02 11:24:05 +05303351 QDF_TRACE(QDF_MODULE_ID_DP,
3352 QDF_TRACE_LEVEL_FATAL,
3353 "Tx Comp pool id %d not matched %d",
3354 pool_id, tx_desc->pool_id);
3355
3356 qdf_assert_always(0);
3357 }
3358
3359 if (!(tx_desc->flags & DP_TX_DESC_FLAG_ALLOCATED) ||
3360 !(tx_desc->flags & DP_TX_DESC_FLAG_QUEUED_TX)) {
3361 QDF_TRACE(QDF_MODULE_ID_DP,
3362 QDF_TRACE_LEVEL_FATAL,
3363 "Txdesc invalid, flgs = %x,id = %d",
3364 tx_desc->flags, tx_desc_id);
3365 qdf_assert_always(0);
3366 }
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303367
3368 /* First ring descriptor on the cycle */
3369 if (!head_desc) {
3370 head_desc = tx_desc;
Pamidipati, Vijay9e340252017-08-14 16:24:17 +05303371 tail_desc = tx_desc;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303372 }
3373
Pamidipati, Vijay9e340252017-08-14 16:24:17 +05303374 tail_desc->next = tx_desc;
3375 tx_desc->next = NULL;
Pamidipati, Vijayb90a79e2016-11-29 01:29:35 +05303376 tail_desc = tx_desc;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303377
Mohit Khannae5a6e942018-11-28 14:22:48 -08003378 DP_HIST_PACKET_COUNT_INC(tx_desc->pdev->pdev_id);
3379
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303380 /* Collect hw completion contents */
3381 hal_tx_comp_desc_sync(tx_comp_hal_desc,
Pranita Solankea12b4b32017-11-20 23:04:14 +05303382 &tx_desc->comp, 1);
Pamidipati, Vijayb90a79e2016-11-29 01:29:35 +05303383
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303384 }
3385
Pamidipati, Vijay9e340252017-08-14 16:24:17 +05303386 num_processed += !(count & DP_TX_NAPI_BUDGET_DIV_MASK);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303387
3388 /*
3389 * Processed packet count is more than given quota
3390 * stop to processing
3391 */
Mohit Khannae5a6e942018-11-28 14:22:48 -08003392 if (num_processed >= quota) {
3393 force_break = true;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303394 break;
Mohit Khannae5a6e942018-11-28 14:22:48 -08003395 }
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303396
Pamidipati, Vijay9e340252017-08-14 16:24:17 +05303397 count++;
Mohit Khannae5a6e942018-11-28 14:22:48 -08003398
3399 if (dp_tx_comp_loop_pkt_limit_hit(soc, count))
3400 break;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303401 }
3402
3403 hal_srng_access_end(soc->hal_soc, hal_srng);
3404
3405 /* Process the reaped descriptors */
3406 if (head_desc)
Amir Patel12550f62018-09-28 19:05:28 +05303407 dp_tx_comp_process_desc_list(soc, head_desc);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303408
Mohit Khannae5a6e942018-11-28 14:22:48 -08003409 if (dp_tx_comp_enable_eol_data_check(soc)) {
3410 if (!force_break &&
3411 hal_srng_dst_peek_sync_locked(soc, hal_srng)) {
3412 DP_STATS_INC(soc, tx.hp_oos2, 1);
3413 if (!hif_exec_should_yield(soc->hif_handle,
3414 int_ctx->dp_intr_id))
3415 goto more_data;
3416 }
3417 }
3418 DP_TX_HIST_STATS_PER_PDEV();
3419
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303420 return num_processed;
3421}
3422
Jeff Johnson6889ddf2019-02-08 07:22:01 -08003423#ifdef FEATURE_WLAN_TDLS
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303424/**
Kabilan Kannan60e3b302017-09-07 20:06:17 -07003425 * dp_tx_non_std() - Allow the control-path SW to send data frames
3426 *
3427 * @data_vdev - which vdev should transmit the tx data frames
3428 * @tx_spec - what non-standard handling to apply to the tx data frames
3429 * @msdu_list - NULL-terminated list of tx MSDUs
3430 *
3431 * Return: NULL on success,
3432 * nbuf when it fails to send
3433 */
3434qdf_nbuf_t dp_tx_non_std(struct cdp_vdev *vdev_handle,
Kabilan Kannan78acc112017-10-10 16:16:32 -07003435 enum ol_tx_spec tx_spec, qdf_nbuf_t msdu_list)
Kabilan Kannan60e3b302017-09-07 20:06:17 -07003436{
3437 struct dp_vdev *vdev = (struct dp_vdev *) vdev_handle;
3438
3439 if (tx_spec & OL_TX_SPEC_NO_FREE)
3440 vdev->is_tdls_frame = true;
3441 return dp_tx_send(vdev_handle, msdu_list);
3442}
Kabilan Kannan78acc112017-10-10 16:16:32 -07003443#endif
Kabilan Kannan60e3b302017-09-07 20:06:17 -07003444
3445/**
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303446 * dp_tx_vdev_attach() - attach vdev to dp tx
3447 * @vdev: virtual device instance
3448 *
3449 * Return: QDF_STATUS_SUCCESS: success
3450 * QDF_STATUS_E_RESOURCES: Error return
3451 */
3452QDF_STATUS dp_tx_vdev_attach(struct dp_vdev *vdev)
3453{
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303454 /*
3455 * Fill HTT TCL Metadata with Vdev ID and MAC ID
3456 */
3457 HTT_TX_TCL_METADATA_TYPE_SET(vdev->htt_tcl_metadata,
3458 HTT_TCL_METADATA_TYPE_VDEV_BASED);
3459
3460 HTT_TX_TCL_METADATA_VDEV_ID_SET(vdev->htt_tcl_metadata,
3461 vdev->vdev_id);
3462
3463 HTT_TX_TCL_METADATA_PDEV_ID_SET(vdev->htt_tcl_metadata,
Manoj Ekbote6f565862017-02-16 10:01:24 -08003464 DP_SW2HW_MACID(vdev->pdev->pdev_id));
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303465
3466 /*
3467 * Set HTT Extension Valid bit to 0 by default
3468 */
3469 HTT_TX_TCL_METADATA_VALID_HTT_SET(vdev->htt_tcl_metadata, 0);
3470
Pamidipati, Vijayc9a13a52017-04-06 17:45:49 +05303471 dp_tx_vdev_update_search_flags(vdev);
3472
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303473 return QDF_STATUS_SUCCESS;
3474}
3475
Amir Patelcb990262019-05-28 15:12:48 +05303476#ifndef FEATURE_WDS
Pamidipati, Vijay22c79d52018-10-19 21:39:42 +05303477static inline bool dp_tx_da_search_override(struct dp_vdev *vdev)
3478{
3479 return false;
3480}
3481#endif
3482
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303483/**
Pamidipati, Vijayc9a13a52017-04-06 17:45:49 +05303484 * dp_tx_vdev_update_search_flags() - Update vdev flags as per opmode
3485 * @vdev: virtual device instance
3486 *
3487 * Return: void
3488 *
3489 */
3490void dp_tx_vdev_update_search_flags(struct dp_vdev *vdev)
3491{
Chaithanya Garrepalli9c73dc02018-09-17 12:35:13 +05303492 struct dp_soc *soc = vdev->pdev->soc;
3493
Pamidipati, Vijayc9a13a52017-04-06 17:45:49 +05303494 /*
Kabilan Kannan56bfd8f2017-04-26 13:26:47 -07003495 * Enable both AddrY (SA based search) and AddrX (Da based search)
3496 * for TDLS link
3497 *
Pamidipati, Vijayc9a13a52017-04-06 17:45:49 +05303498 * Enable AddrY (SA based search) only for non-WDS STA and
Chaithanya Garrepalli13127062018-10-11 21:34:37 +05303499 * ProxySTA VAP (in HKv1) modes.
Pamidipati, Vijayc9a13a52017-04-06 17:45:49 +05303500 *
3501 * In all other VAP modes, only DA based search should be
3502 * enabled
3503 */
Kabilan Kannan56bfd8f2017-04-26 13:26:47 -07003504 if (vdev->opmode == wlan_op_mode_sta &&
3505 vdev->tdls_link_connected)
3506 vdev->hal_desc_addr_search_flags =
3507 (HAL_TX_DESC_ADDRX_EN | HAL_TX_DESC_ADDRY_EN);
Chaithanya Garrepalli13127062018-10-11 21:34:37 +05303508 else if ((vdev->opmode == wlan_op_mode_sta) &&
Pamidipati, Vijay22c79d52018-10-19 21:39:42 +05303509 !dp_tx_da_search_override(vdev))
Pamidipati, Vijayc9a13a52017-04-06 17:45:49 +05303510 vdev->hal_desc_addr_search_flags = HAL_TX_DESC_ADDRY_EN;
3511 else
3512 vdev->hal_desc_addr_search_flags = HAL_TX_DESC_ADDRX_EN;
Chaithanya Garrepalli2467ed12018-09-11 23:57:43 +05303513
Chaithanya Garrepalli9c73dc02018-09-17 12:35:13 +05303514 /* Set search type only when peer map v2 messaging is enabled
3515 * as we will have the search index (AST hash) only when v2 is
3516 * enabled
3517 */
3518 if (soc->is_peer_map_unmap_v2 && vdev->opmode == wlan_op_mode_sta)
Chaithanya Garrepalli2467ed12018-09-11 23:57:43 +05303519 vdev->search_type = HAL_TX_ADDR_INDEX_SEARCH;
3520 else
3521 vdev->search_type = HAL_TX_ADDR_SEARCH_DEFAULT;
Pamidipati, Vijayc9a13a52017-04-06 17:45:49 +05303522}
3523
Jinwei Chen79b4fc82019-04-26 13:27:27 +08003524static inline bool
3525dp_is_tx_desc_flush_match(struct dp_pdev *pdev,
3526 struct dp_vdev *vdev,
3527 struct dp_tx_desc_s *tx_desc)
3528{
3529 if (!(tx_desc && (tx_desc->flags & DP_TX_DESC_FLAG_ALLOCATED)))
3530 return false;
3531
3532 /*
3533 * if vdev is given, then only check whether desc
3534 * vdev match. if vdev is NULL, then check whether
3535 * desc pdev match.
3536 */
3537 return vdev ? (tx_desc->vdev == vdev) : (tx_desc->pdev == pdev);
3538}
3539
Soumya Bhat33a88222018-03-21 14:47:00 +05303540#ifdef QCA_LL_TX_FLOW_CONTROL_V2
Jinwei Chen79b4fc82019-04-26 13:27:27 +08003541/**
3542 * dp_tx_desc_reset_vdev() - reset vdev to NULL in TX Desc
Soumya Bhat33a88222018-03-21 14:47:00 +05303543 *
Jinwei Chen79b4fc82019-04-26 13:27:27 +08003544 * @soc: Handle to DP SoC structure
3545 * @tx_desc: pointer of one TX desc
3546 * @desc_pool_id: TX Desc pool id
Jinwei Chenb3f9d202018-11-30 10:03:19 +08003547 */
Jinwei Chen79b4fc82019-04-26 13:27:27 +08003548static inline void
3549dp_tx_desc_reset_vdev(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc,
3550 uint8_t desc_pool_id)
3551{
3552 struct dp_tx_desc_pool_s *pool = &soc->tx_desc[desc_pool_id];
3553
3554 qdf_spin_lock_bh(&pool->flow_pool_lock);
3555
3556 tx_desc->vdev = NULL;
3557
3558 qdf_spin_unlock_bh(&pool->flow_pool_lock);
3559}
3560
3561/**
3562 * dp_tx_desc_flush() - release resources associated
3563 * to TX Desc
3564 *
3565 * @dp_pdev: Handle to DP pdev structure
3566 * @vdev: virtual device instance
3567 * NULL: no specific Vdev is required and check all allcated TX desc
3568 * on this pdev.
3569 * Non-NULL: only check the allocated TX Desc associated to this Vdev.
3570 *
3571 * @force_free:
3572 * true: flush the TX desc.
3573 * false: only reset the Vdev in each allocated TX desc
3574 * that associated to current Vdev.
3575 *
3576 * This function will go through the TX desc pool to flush
3577 * the outstanding TX data or reset Vdev to NULL in associated TX
3578 * Desc.
3579 */
3580static void dp_tx_desc_flush(struct dp_pdev *pdev,
3581 struct dp_vdev *vdev,
3582 bool force_free)
Jinwei Chenb3f9d202018-11-30 10:03:19 +08003583{
3584 uint8_t i;
3585 uint32_t j;
3586 uint32_t num_desc, page_id, offset;
3587 uint16_t num_desc_per_page;
Jinwei Chen79b4fc82019-04-26 13:27:27 +08003588 struct dp_soc *soc = pdev->soc;
Jinwei Chenb3f9d202018-11-30 10:03:19 +08003589 struct dp_tx_desc_s *tx_desc = NULL;
3590 struct dp_tx_desc_pool_s *tx_desc_pool = NULL;
3591
Jinwei Chen79b4fc82019-04-26 13:27:27 +08003592 if (!vdev && !force_free) {
3593 dp_err("Reset TX desc vdev, Vdev param is required!");
3594 return;
3595 }
3596
Jinwei Chenb3f9d202018-11-30 10:03:19 +08003597 for (i = 0; i < MAX_TXDESC_POOLS; i++) {
3598 tx_desc_pool = &soc->tx_desc[i];
3599 if (!(tx_desc_pool->pool_size) ||
3600 IS_TX_DESC_POOL_STATUS_INACTIVE(tx_desc_pool) ||
3601 !(tx_desc_pool->desc_pages.cacheable_pages))
3602 continue;
3603
3604 num_desc = tx_desc_pool->pool_size;
3605 num_desc_per_page =
3606 tx_desc_pool->desc_pages.num_element_per_page;
3607 for (j = 0; j < num_desc; j++) {
3608 page_id = j / num_desc_per_page;
3609 offset = j % num_desc_per_page;
3610
3611 if (qdf_unlikely(!(tx_desc_pool->
3612 desc_pages.cacheable_pages)))
3613 break;
3614
3615 tx_desc = dp_tx_desc_find(soc, i, page_id, offset);
Jinwei Chen79b4fc82019-04-26 13:27:27 +08003616
3617 if (dp_is_tx_desc_flush_match(pdev, vdev, tx_desc)) {
3618 /*
3619 * Free TX desc if force free is
3620 * required, otherwise only reset vdev
3621 * in this TX desc.
3622 */
3623 if (force_free) {
3624 dp_tx_comp_free_buf(soc, tx_desc);
3625 dp_tx_desc_release(tx_desc, i);
3626 } else {
3627 dp_tx_desc_reset_vdev(soc, tx_desc,
3628 i);
3629 }
Jinwei Chenb3f9d202018-11-30 10:03:19 +08003630 }
3631 }
3632 }
3633}
3634#else /* QCA_LL_TX_FLOW_CONTROL_V2! */
Jinwei Chen79b4fc82019-04-26 13:27:27 +08003635
3636static inline void
3637dp_tx_desc_reset_vdev(struct dp_soc *soc, struct dp_tx_desc_s *tx_desc,
3638 uint8_t desc_pool_id)
3639{
3640 TX_DESC_LOCK_LOCK(&soc->tx_desc[desc_pool_id].lock);
3641
3642 tx_desc->vdev = NULL;
3643
3644 TX_DESC_LOCK_UNLOCK(&soc->tx_desc[desc_pool_id].lock);
3645}
3646
3647static void dp_tx_desc_flush(struct dp_pdev *pdev,
3648 struct dp_vdev *vdev,
3649 bool force_free)
Soumya Bhat33a88222018-03-21 14:47:00 +05303650{
3651 uint8_t i, num_pool;
3652 uint32_t j;
Jinwei Chenb3f9d202018-11-30 10:03:19 +08003653 uint32_t num_desc, page_id, offset;
3654 uint16_t num_desc_per_page;
Jinwei Chen79b4fc82019-04-26 13:27:27 +08003655 struct dp_soc *soc = pdev->soc;
Soumya Bhat33a88222018-03-21 14:47:00 +05303656 struct dp_tx_desc_s *tx_desc = NULL;
3657 struct dp_tx_desc_pool_s *tx_desc_pool = NULL;
3658
Jinwei Chen79b4fc82019-04-26 13:27:27 +08003659 if (!vdev && !force_free) {
3660 dp_err("Reset TX desc vdev, Vdev param is required!");
3661 return;
3662 }
3663
Soumya Bhat33a88222018-03-21 14:47:00 +05303664 num_desc = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx);
3665 num_pool = wlan_cfg_get_num_tx_desc_pool(soc->wlan_cfg_ctx);
3666
3667 for (i = 0; i < num_pool; i++) {
Jinwei Chenb3f9d202018-11-30 10:03:19 +08003668 tx_desc_pool = &soc->tx_desc[i];
3669 if (!tx_desc_pool->desc_pages.cacheable_pages)
3670 continue;
Soumya Bhat33a88222018-03-21 14:47:00 +05303671
Jinwei Chenb3f9d202018-11-30 10:03:19 +08003672 num_desc_per_page =
3673 tx_desc_pool->desc_pages.num_element_per_page;
3674 for (j = 0; j < num_desc; j++) {
3675 page_id = j / num_desc_per_page;
3676 offset = j % num_desc_per_page;
3677 tx_desc = dp_tx_desc_find(soc, i, page_id, offset);
3678
Jinwei Chen79b4fc82019-04-26 13:27:27 +08003679 if (dp_is_tx_desc_flush_match(pdev, vdev, tx_desc)) {
3680 if (force_free) {
3681 dp_tx_comp_free_buf(soc, tx_desc);
3682 dp_tx_desc_release(tx_desc, i);
3683 } else {
3684 dp_tx_desc_reset_vdev(soc, tx_desc,
3685 i);
3686 }
Soumya Bhat33a88222018-03-21 14:47:00 +05303687 }
3688 }
3689 }
3690}
Ankit Kumar14b96222019-03-29 20:57:51 +05303691#endif /* !QCA_LL_TX_FLOW_CONTROL_V2 */
Jinwei Chen79b4fc82019-04-26 13:27:27 +08003692
Pamidipati, Vijayc9a13a52017-04-06 17:45:49 +05303693/**
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303694 * dp_tx_vdev_detach() - detach vdev from dp tx
3695 * @vdev: virtual device instance
3696 *
3697 * Return: QDF_STATUS_SUCCESS: success
3698 * QDF_STATUS_E_RESOURCES: Error return
3699 */
3700QDF_STATUS dp_tx_vdev_detach(struct dp_vdev *vdev)
3701{
Jinwei Chen79b4fc82019-04-26 13:27:27 +08003702 struct dp_pdev *pdev = vdev->pdev;
3703
3704 /* Reset TX desc associated to this Vdev as NULL */
3705 dp_tx_desc_flush(pdev, vdev, false);
3706
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303707 return QDF_STATUS_SUCCESS;
3708}
3709
3710/**
3711 * dp_tx_pdev_attach() - attach pdev to dp tx
3712 * @pdev: physical device instance
3713 *
3714 * Return: QDF_STATUS_SUCCESS: success
3715 * QDF_STATUS_E_RESOURCES: Error return
3716 */
3717QDF_STATUS dp_tx_pdev_attach(struct dp_pdev *pdev)
3718{
3719 struct dp_soc *soc = pdev->soc;
3720
3721 /* Initialize Flow control counters */
Vijay Pamidipati4d5d4362017-02-09 22:49:00 +05303722 qdf_atomic_init(&pdev->num_tx_exception);
3723 qdf_atomic_init(&pdev->num_tx_outstanding);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303724
3725 if (wlan_cfg_per_pdev_tx_ring(soc->wlan_cfg_ctx)) {
3726 /* Initialize descriptors in TCL Ring */
3727 hal_tx_init_data_ring(soc->hal_soc,
3728 soc->tcl_data_ring[pdev->pdev_id].hal_srng);
3729 }
3730
3731 return QDF_STATUS_SUCCESS;
3732}
3733
Soumya Bhat33a88222018-03-21 14:47:00 +05303734/**
3735 * dp_tx_pdev_detach() - detach pdev from dp tx
3736 * @pdev: physical device instance
3737 *
3738 * Return: QDF_STATUS_SUCCESS: success
3739 * QDF_STATUS_E_RESOURCES: Error return
3740 */
3741QDF_STATUS dp_tx_pdev_detach(struct dp_pdev *pdev)
3742{
Jinwei Chen79b4fc82019-04-26 13:27:27 +08003743 /* flush TX outstanding data per pdev */
3744 dp_tx_desc_flush(pdev, NULL, true);
Soumya Bhat33a88222018-03-21 14:47:00 +05303745 dp_tx_me_exit(pdev);
3746 return QDF_STATUS_SUCCESS;
3747}
3748
Ruchi, Agrawale8eeb442018-02-12 16:19:58 +05303749#ifdef QCA_LL_TX_FLOW_CONTROL_V2
3750/* Pools will be allocated dynamically */
3751static int dp_tx_alloc_static_pools(struct dp_soc *soc, int num_pool,
3752 int num_desc)
3753{
3754 uint8_t i;
3755
3756 for (i = 0; i < num_pool; i++) {
3757 qdf_spinlock_create(&soc->tx_desc[i].flow_pool_lock);
3758 soc->tx_desc[i].status = FLOW_POOL_INACTIVE;
3759 }
3760
3761 return 0;
3762}
3763
3764static void dp_tx_delete_static_pools(struct dp_soc *soc, int num_pool)
3765{
3766 uint8_t i;
3767
3768 for (i = 0; i < num_pool; i++)
3769 qdf_spinlock_destroy(&soc->tx_desc[i].flow_pool_lock);
3770}
Ruchi, Agrawale8eeb442018-02-12 16:19:58 +05303771#else /* QCA_LL_TX_FLOW_CONTROL_V2! */
3772static int dp_tx_alloc_static_pools(struct dp_soc *soc, int num_pool,
3773 int num_desc)
3774{
3775 uint8_t i;
3776
3777 /* Allocate software Tx descriptor pools */
3778 for (i = 0; i < num_pool; i++) {
3779 if (dp_tx_desc_pool_alloc(soc, i, num_desc)) {
3780 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +05303781 "%s Tx Desc Pool alloc %d failed %pK",
Ruchi, Agrawale8eeb442018-02-12 16:19:58 +05303782 __func__, i, soc);
3783 return ENOMEM;
3784 }
3785 }
3786 return 0;
3787}
3788
3789static void dp_tx_delete_static_pools(struct dp_soc *soc, int num_pool)
3790{
3791 uint8_t i;
3792
3793 for (i = 0; i < num_pool; i++) {
Soumya Bhat33a88222018-03-21 14:47:00 +05303794 qdf_assert_always(!soc->tx_desc[i].num_allocated);
Ruchi, Agrawale8eeb442018-02-12 16:19:58 +05303795 if (dp_tx_desc_pool_free(soc, i)) {
3796 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
Aditya Sathishded018e2018-07-02 16:25:21 +05303797 "%s Tx Desc Pool Free failed", __func__);
Ruchi, Agrawale8eeb442018-02-12 16:19:58 +05303798 }
3799 }
3800}
3801
Ruchi, Agrawale8eeb442018-02-12 16:19:58 +05303802#endif /* !QCA_LL_TX_FLOW_CONTROL_V2 */
Ruchi, Agrawalc0f9c972018-02-02 11:24:05 +05303803
Anish Nataraje9d4c3b2018-11-24 22:24:56 +05303804#ifndef QCA_MEM_ATTACH_ON_WIFI3
3805/**
3806 * dp_tso_attach_wifi3() - TSO attach handler
3807 * @txrx_soc: Opaque Dp handle
3808 *
3809 * Reserve TSO descriptor buffers
3810 *
3811 * Return: QDF_STATUS_E_FAILURE on failure or
3812 * QDF_STATUS_SUCCESS on success
3813 */
3814static
3815QDF_STATUS dp_tso_attach_wifi3(void *txrx_soc)
3816{
3817 return dp_tso_soc_attach(txrx_soc);
3818}
3819
3820/**
3821 * dp_tso_detach_wifi3() - TSO Detach handler
3822 * @txrx_soc: Opaque Dp handle
3823 *
3824 * Deallocate TSO descriptor buffers
3825 *
3826 * Return: QDF_STATUS_E_FAILURE on failure or
3827 * QDF_STATUS_SUCCESS on success
3828 */
3829static
3830QDF_STATUS dp_tso_detach_wifi3(void *txrx_soc)
3831{
3832 return dp_tso_soc_detach(txrx_soc);
3833}
3834#else
3835static
3836QDF_STATUS dp_tso_attach_wifi3(void *txrx_soc)
3837{
3838 return QDF_STATUS_SUCCESS;
3839}
3840
3841static
3842QDF_STATUS dp_tso_detach_wifi3(void *txrx_soc)
3843{
3844 return QDF_STATUS_SUCCESS;
3845}
3846#endif
3847
3848QDF_STATUS dp_tso_soc_detach(void *txrx_soc)
3849{
3850 struct dp_soc *soc = (struct dp_soc *)txrx_soc;
3851 uint8_t i;
3852 uint8_t num_pool;
3853 uint32_t num_desc;
3854
3855 num_pool = wlan_cfg_get_num_tx_desc_pool(soc->wlan_cfg_ctx);
3856 num_desc = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx);
3857
3858 for (i = 0; i < num_pool; i++)
3859 dp_tx_tso_desc_pool_free(soc, i);
3860
3861 dp_info("%s TSO Desc Pool %d Free descs = %d",
3862 __func__, num_pool, num_desc);
3863
3864 for (i = 0; i < num_pool; i++)
3865 dp_tx_tso_num_seg_pool_free(soc, i);
3866
3867 dp_info("%s TSO Num of seg Desc Pool %d Free descs = %d",
3868 __func__, num_pool, num_desc);
3869
3870 return QDF_STATUS_SUCCESS;
3871}
3872
3873/**
3874 * dp_tso_attach() - TSO attach handler
3875 * @txrx_soc: Opaque Dp handle
3876 *
3877 * Reserve TSO descriptor buffers
3878 *
3879 * Return: QDF_STATUS_E_FAILURE on failure or
3880 * QDF_STATUS_SUCCESS on success
3881 */
3882QDF_STATUS dp_tso_soc_attach(void *txrx_soc)
3883{
3884 struct dp_soc *soc = (struct dp_soc *)txrx_soc;
3885 uint8_t i;
3886 uint8_t num_pool;
3887 uint32_t num_desc;
3888
3889 num_pool = wlan_cfg_get_num_tx_desc_pool(soc->wlan_cfg_ctx);
3890 num_desc = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx);
3891
3892 for (i = 0; i < num_pool; i++) {
3893 if (dp_tx_tso_desc_pool_alloc(soc, i, num_desc)) {
3894 dp_err("TSO Desc Pool alloc %d failed %pK",
3895 i, soc);
3896
3897 return QDF_STATUS_E_FAILURE;
3898 }
3899 }
3900
3901 dp_info("%s TSO Desc Alloc %d, descs = %d",
3902 __func__, num_pool, num_desc);
3903
3904 for (i = 0; i < num_pool; i++) {
3905 if (dp_tx_tso_num_seg_pool_alloc(soc, i, num_desc)) {
3906 dp_err("TSO Num of seg Pool alloc %d failed %pK",
3907 i, soc);
3908
3909 return QDF_STATUS_E_FAILURE;
3910 }
3911 }
3912 return QDF_STATUS_SUCCESS;
3913}
3914
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303915/**
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303916 * dp_tx_soc_detach() - detach soc from dp tx
3917 * @soc: core txrx main context
3918 *
3919 * This function will detach dp tx into main device context
3920 * will free dp tx resource and initialize resources
3921 *
3922 * Return: QDF_STATUS_SUCCESS: success
3923 * QDF_STATUS_E_RESOURCES: Error return
3924 */
3925QDF_STATUS dp_tx_soc_detach(struct dp_soc *soc)
3926{
3927 uint8_t num_pool;
Leo Chang5ea93a42016-11-03 12:39:49 -07003928 uint16_t num_desc;
3929 uint16_t num_ext_desc;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303930 uint8_t i;
Anish Nataraje9d4c3b2018-11-24 22:24:56 +05303931 QDF_STATUS status = QDF_STATUS_SUCCESS;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303932
3933 num_pool = wlan_cfg_get_num_tx_desc_pool(soc->wlan_cfg_ctx);
3934 num_desc = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx);
3935 num_ext_desc = wlan_cfg_get_num_tx_ext_desc(soc->wlan_cfg_ctx);
3936
Manjunathappa Prakashced7ea62017-07-02 03:02:15 -07003937 dp_tx_flow_control_deinit(soc);
3938 dp_tx_delete_static_pools(soc, num_pool);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303939
3940 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
Aditya Sathishded018e2018-07-02 16:25:21 +05303941 "%s Tx Desc Pool Free num_pool = %d, descs = %d",
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303942 __func__, num_pool, num_desc);
3943
3944 for (i = 0; i < num_pool; i++) {
3945 if (dp_tx_ext_desc_pool_free(soc, i)) {
3946 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
Aditya Sathishded018e2018-07-02 16:25:21 +05303947 "%s Tx Ext Desc Pool Free failed",
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303948 __func__);
3949 return QDF_STATUS_E_RESOURCES;
3950 }
3951 }
3952
3953 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
Aditya Sathishded018e2018-07-02 16:25:21 +05303954 "%s MSDU Ext Desc Pool %d Free descs = %d",
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303955 __func__, num_pool, num_ext_desc);
3956
Anish Nataraje9d4c3b2018-11-24 22:24:56 +05303957 status = dp_tso_detach_wifi3(soc);
3958 if (status != QDF_STATUS_SUCCESS)
3959 return status;
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -07003960
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303961 return QDF_STATUS_SUCCESS;
3962}
3963
3964/**
3965 * dp_tx_soc_attach() - attach soc to dp tx
3966 * @soc: core txrx main context
3967 *
3968 * This function will attach dp tx into main device context
3969 * will allocate dp tx resource and initialize resources
3970 *
3971 * Return: QDF_STATUS_SUCCESS: success
3972 * QDF_STATUS_E_RESOURCES: Error return
3973 */
3974QDF_STATUS dp_tx_soc_attach(struct dp_soc *soc)
3975{
Manjunathappa Prakashced7ea62017-07-02 03:02:15 -07003976 uint8_t i;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303977 uint8_t num_pool;
3978 uint32_t num_desc;
3979 uint32_t num_ext_desc;
Anish Nataraje9d4c3b2018-11-24 22:24:56 +05303980 QDF_STATUS status = QDF_STATUS_SUCCESS;
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303981
3982 num_pool = wlan_cfg_get_num_tx_desc_pool(soc->wlan_cfg_ctx);
3983 num_desc = wlan_cfg_get_num_tx_desc(soc->wlan_cfg_ctx);
3984 num_ext_desc = wlan_cfg_get_num_tx_ext_desc(soc->wlan_cfg_ctx);
3985
Chaitanya Kiran Godavarthib1e2bf52019-01-10 15:05:17 +05303986 if (num_pool > MAX_TXDESC_POOLS)
3987 goto fail;
3988
Manjunathappa Prakashced7ea62017-07-02 03:02:15 -07003989 if (dp_tx_alloc_static_pools(soc, num_pool, num_desc))
3990 goto fail;
3991
3992 dp_tx_flow_control_init(soc);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303993
3994 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
Aditya Sathishded018e2018-07-02 16:25:21 +05303995 "%s Tx Desc Alloc num_pool = %d, descs = %d",
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05303996 __func__, num_pool, num_desc);
3997
3998 /* Allocate extension tx descriptor pools */
3999 for (i = 0; i < num_pool; i++) {
4000 if (dp_tx_ext_desc_pool_alloc(soc, i, num_ext_desc)) {
4001 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
Aditya Sathishded018e2018-07-02 16:25:21 +05304002 "MSDU Ext Desc Pool alloc %d failed %pK",
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05304003 i, soc);
4004
4005 goto fail;
4006 }
4007 }
4008
4009 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
Aditya Sathishded018e2018-07-02 16:25:21 +05304010 "%s MSDU Ext Desc Alloc %d, descs = %d",
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05304011 __func__, num_pool, num_ext_desc);
4012
Anish Nataraje9d4c3b2018-11-24 22:24:56 +05304013 status = dp_tso_attach_wifi3((void *)soc);
4014 if (status != QDF_STATUS_SUCCESS)
4015 goto fail;
Ishank Jain5122f8f2017-03-15 22:22:47 +05304016
Venkata Sharath Chandra Manchala35503cc2017-04-06 15:30:54 -07004017
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05304018 /* Initialize descriptors in TCL Rings */
4019 if (!wlan_cfg_per_pdev_tx_ring(soc->wlan_cfg_ctx)) {
4020 for (i = 0; i < soc->num_tcl_data_rings; i++) {
4021 hal_tx_init_data_ring(soc->hal_soc,
4022 soc->tcl_data_ring[i].hal_srng);
4023 }
4024 }
4025
Vijay Pamidipati5bcfa312016-12-20 11:44:38 +05304026 /*
Vijay Pamidipati5bcfa312016-12-20 11:44:38 +05304027 * todo - Add a runtime config option to enable this.
4028 */
Debashis Duttaf645222017-01-20 19:29:25 -08004029 /*
4030 * Due to multiple issues on NPR EMU, enable it selectively
4031 * only for NPR EMU, should be removed, once NPR platforms
4032 * are stable.
4033 */
chenguo9bece1a2017-12-19 18:49:41 +08004034 soc->process_tx_status = CONFIG_PROCESS_TX_STATUS;
Vijay Pamidipati5bcfa312016-12-20 11:44:38 +05304035
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05304036 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
Aditya Sathishded018e2018-07-02 16:25:21 +05304037 "%s HAL Tx init Success", __func__);
Pamidipati, Vijay576bd152016-09-27 20:58:18 +05304038
4039 return QDF_STATUS_SUCCESS;
4040
4041fail:
4042 /* Detach will take care of freeing only allocated resources */
4043 dp_tx_soc_detach(soc);
4044 return QDF_STATUS_E_RESOURCES;
4045}
Ishank Jainc838b132017-02-17 11:08:18 +05304046
4047/*
4048 * dp_tx_me_mem_free(): Function to free allocated memory in mcast enahncement
4049 * pdev: pointer to DP PDEV structure
4050 * seg_info_head: Pointer to the head of list
4051 *
4052 * return: void
4053 */
Pamidipati, Vijay726ea122018-02-07 18:27:00 +05304054static void dp_tx_me_mem_free(struct dp_pdev *pdev,
Ishank Jainc838b132017-02-17 11:08:18 +05304055 struct dp_tx_seg_info_s *seg_info_head)
4056{
4057 struct dp_tx_me_buf_t *mc_uc_buf;
4058 struct dp_tx_seg_info_s *seg_info_new = NULL;
4059 qdf_nbuf_t nbuf = NULL;
4060 uint64_t phy_addr;
4061
4062 while (seg_info_head) {
4063 nbuf = seg_info_head->nbuf;
4064 mc_uc_buf = (struct dp_tx_me_buf_t *)
Pamidipati, Vijayfb0d54d2018-01-03 20:06:08 +05304065 seg_info_head->frags[0].vaddr;
Ishank Jainc838b132017-02-17 11:08:18 +05304066 phy_addr = seg_info_head->frags[0].paddr_hi;
4067 phy_addr = (phy_addr << 32) | seg_info_head->frags[0].paddr_lo;
4068 qdf_mem_unmap_nbytes_single(pdev->soc->osdev,
4069 phy_addr,
Srinivas Girigowda2751b6d2019-02-27 12:28:13 -08004070 QDF_DMA_TO_DEVICE , QDF_MAC_ADDR_SIZE);
Ishank Jainc838b132017-02-17 11:08:18 +05304071 dp_tx_me_free_buf(pdev, mc_uc_buf);
4072 qdf_nbuf_free(nbuf);
4073 seg_info_new = seg_info_head;
4074 seg_info_head = seg_info_head->next;
4075 qdf_mem_free(seg_info_new);
4076 }
4077}
4078
4079/**
Jeff Johnsond087ede2018-05-06 15:33:22 -07004080 * dp_tx_me_send_convert_ucast(): function to convert multicast to unicast
Ishank Jainc838b132017-02-17 11:08:18 +05304081 * @vdev: DP VDEV handle
4082 * @nbuf: Multicast nbuf
4083 * @newmac: Table of the clients to which packets have to be sent
4084 * @new_mac_cnt: No of clients
4085 *
4086 * return: no of converted packets
4087 */
4088uint16_t
4089dp_tx_me_send_convert_ucast(struct cdp_vdev *vdev_handle, qdf_nbuf_t nbuf,
Srinivas Girigowda2751b6d2019-02-27 12:28:13 -08004090 uint8_t newmac[][QDF_MAC_ADDR_SIZE], uint8_t new_mac_cnt)
Ishank Jainc838b132017-02-17 11:08:18 +05304091{
4092 struct dp_vdev *vdev = (struct dp_vdev *) vdev_handle;
4093 struct dp_pdev *pdev = vdev->pdev;
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08004094 qdf_ether_header_t *eh;
Ishank Jainc838b132017-02-17 11:08:18 +05304095 uint8_t *data;
4096 uint16_t len;
4097
4098 /* reference to frame dst addr */
4099 uint8_t *dstmac;
4100 /* copy of original frame src addr */
Srinivas Girigowda2751b6d2019-02-27 12:28:13 -08004101 uint8_t srcmac[QDF_MAC_ADDR_SIZE];
Ishank Jainc838b132017-02-17 11:08:18 +05304102
4103 /* local index into newmac */
4104 uint8_t new_mac_idx = 0;
4105 struct dp_tx_me_buf_t *mc_uc_buf;
4106 qdf_nbuf_t nbuf_clone;
4107 struct dp_tx_msdu_info_s msdu_info;
4108 struct dp_tx_seg_info_s *seg_info_head = NULL;
4109 struct dp_tx_seg_info_s *seg_info_tail = NULL;
4110 struct dp_tx_seg_info_s *seg_info_new;
Ishank Jainc838b132017-02-17 11:08:18 +05304111 qdf_dma_addr_t paddr_data;
4112 qdf_dma_addr_t paddr_mcbuf = 0;
Srinivas Girigowda2751b6d2019-02-27 12:28:13 -08004113 uint8_t empty_entry_mac[QDF_MAC_ADDR_SIZE] = {0};
Ishank Jainc838b132017-02-17 11:08:18 +05304114 QDF_STATUS status;
4115
hangtianfe681a52019-01-16 17:16:28 +08004116 qdf_mem_zero(&msdu_info, sizeof(msdu_info));
Kiran Venkatappaa7b68422017-07-14 20:53:37 +05304117
Ishank Jainc838b132017-02-17 11:08:18 +05304118 dp_tx_get_queue(vdev, nbuf, &msdu_info.tx_queue);
4119
Srinivas Girigowda03bd4b62019-02-25 10:57:08 -08004120 eh = (qdf_ether_header_t *)nbuf;
Srinivas Girigowda2751b6d2019-02-27 12:28:13 -08004121 qdf_mem_copy(srcmac, eh->ether_shost, QDF_MAC_ADDR_SIZE);
Ishank Jainc838b132017-02-17 11:08:18 +05304122
4123 len = qdf_nbuf_len(nbuf);
4124
4125 data = qdf_nbuf_data(nbuf);
4126
4127 status = qdf_nbuf_map(vdev->osdev, nbuf,
4128 QDF_DMA_TO_DEVICE);
4129
4130 if (status) {
4131 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
4132 "Mapping failure Error:%d", status);
4133 DP_STATS_INC(vdev, tx_i.mcast_en.dropped_map_error, 1);
Pamidipati, Vijay726ea122018-02-07 18:27:00 +05304134 qdf_nbuf_free(nbuf);
4135 return 1;
Ishank Jainc838b132017-02-17 11:08:18 +05304136 }
4137
Varsha Mishra0c201e22019-04-01 20:53:00 +05304138 paddr_data = qdf_nbuf_mapped_paddr_get(nbuf) + QDF_MAC_ADDR_SIZE;
Ishank Jainc838b132017-02-17 11:08:18 +05304139
4140 for (new_mac_idx = 0; new_mac_idx < new_mac_cnt; new_mac_idx++) {
4141 dstmac = newmac[new_mac_idx];
4142 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_INFO,
4143 "added mac addr (%pM)", dstmac);
4144
4145 /* Check for NULL Mac Address */
Srinivas Girigowda2751b6d2019-02-27 12:28:13 -08004146 if (!qdf_mem_cmp(dstmac, empty_entry_mac, QDF_MAC_ADDR_SIZE))
Ishank Jainc838b132017-02-17 11:08:18 +05304147 continue;
4148
4149 /* frame to self mac. skip */
Srinivas Girigowda2751b6d2019-02-27 12:28:13 -08004150 if (!qdf_mem_cmp(dstmac, srcmac, QDF_MAC_ADDR_SIZE))
Ishank Jainc838b132017-02-17 11:08:18 +05304151 continue;
4152
4153 /*
4154 * TODO: optimize to avoid malloc in per-packet path
4155 * For eg. seg_pool can be made part of vdev structure
4156 */
4157 seg_info_new = qdf_mem_malloc(sizeof(*seg_info_new));
4158
4159 if (!seg_info_new) {
4160 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
4161 "alloc failed");
4162 DP_STATS_INC(vdev, tx_i.mcast_en.fail_seg_alloc, 1);
4163 goto fail_seg_alloc;
4164 }
4165
4166 mc_uc_buf = dp_tx_me_alloc_buf(pdev);
Jeff Johnsona8edf332019-03-18 09:51:52 -07004167 if (!mc_uc_buf)
Ishank Jainc838b132017-02-17 11:08:18 +05304168 goto fail_buf_alloc;
4169
4170 /*
4171 * TODO: Check if we need to clone the nbuf
4172 * Or can we just use the reference for all cases
4173 */
4174 if (new_mac_idx < (new_mac_cnt - 1)) {
4175 nbuf_clone = qdf_nbuf_clone((qdf_nbuf_t)nbuf);
Jeff Johnsona8edf332019-03-18 09:51:52 -07004176 if (!nbuf_clone) {
Ishank Jainc838b132017-02-17 11:08:18 +05304177 DP_STATS_INC(vdev, tx_i.mcast_en.clone_fail, 1);
4178 goto fail_clone;
4179 }
4180 } else {
4181 /*
4182 * Update the ref
4183 * to account for frame sent without cloning
4184 */
4185 qdf_nbuf_ref(nbuf);
4186 nbuf_clone = nbuf;
4187 }
4188
Srinivas Girigowda2751b6d2019-02-27 12:28:13 -08004189 qdf_mem_copy(mc_uc_buf->data, dstmac, QDF_MAC_ADDR_SIZE);
Ishank Jainc838b132017-02-17 11:08:18 +05304190
4191 status = qdf_mem_map_nbytes_single(vdev->osdev, mc_uc_buf->data,
Srinivas Girigowda2751b6d2019-02-27 12:28:13 -08004192 QDF_DMA_TO_DEVICE, QDF_MAC_ADDR_SIZE,
Ishank Jainc838b132017-02-17 11:08:18 +05304193 &paddr_mcbuf);
4194
4195 if (status) {
4196 QDF_TRACE(QDF_MODULE_ID_DP, QDF_TRACE_LEVEL_ERROR,
4197 "Mapping failure Error:%d", status);
4198 DP_STATS_INC(vdev, tx_i.mcast_en.dropped_map_error, 1);
4199 goto fail_map;
4200 }
4201
4202 seg_info_new->frags[0].vaddr = (uint8_t *)mc_uc_buf;
4203 seg_info_new->frags[0].paddr_lo = (uint32_t) paddr_mcbuf;
4204 seg_info_new->frags[0].paddr_hi =
Varsha Mishra0c201e22019-04-01 20:53:00 +05304205 (uint16_t)((uint64_t)paddr_mcbuf >> 32);
Srinivas Girigowda2751b6d2019-02-27 12:28:13 -08004206 seg_info_new->frags[0].len = QDF_MAC_ADDR_SIZE;
Ishank Jainc838b132017-02-17 11:08:18 +05304207
Varsha Mishra0c201e22019-04-01 20:53:00 +05304208 /*preparing data fragment*/
4209 seg_info_new->frags[1].vaddr =
4210 qdf_nbuf_data(nbuf) + QDF_MAC_ADDR_SIZE;
4211 seg_info_new->frags[1].paddr_lo = (uint32_t)paddr_data;
4212 seg_info_new->frags[1].paddr_hi =
4213 (uint16_t)(((uint64_t)paddr_data) >> 32);
4214 seg_info_new->frags[1].len = len - QDF_MAC_ADDR_SIZE;
4215
Ishank Jainc838b132017-02-17 11:08:18 +05304216 seg_info_new->nbuf = nbuf_clone;
4217 seg_info_new->frag_cnt = 2;
4218 seg_info_new->total_len = len;
4219
4220 seg_info_new->next = NULL;
4221
Jeff Johnsona8edf332019-03-18 09:51:52 -07004222 if (!seg_info_head)
Ishank Jainc838b132017-02-17 11:08:18 +05304223 seg_info_head = seg_info_new;
4224 else
4225 seg_info_tail->next = seg_info_new;
4226
4227 seg_info_tail = seg_info_new;
4228 }
4229
Pamidipati, Vijay726ea122018-02-07 18:27:00 +05304230 if (!seg_info_head) {
4231 goto free_return;
4232 }
Ishank Jainc838b132017-02-17 11:08:18 +05304233
4234 msdu_info.u.sg_info.curr_seg = seg_info_head;
4235 msdu_info.num_seg = new_mac_cnt;
4236 msdu_info.frm_type = dp_tx_frm_me;
4237
Varsha Mishra5827fd02019-05-03 16:59:57 +05304238 msdu_info.tid = HTT_INVALID_TID;
Shashikala Prabhu8f6703b2018-10-31 09:43:00 +05304239 if (qdf_unlikely(vdev->mcast_enhancement_en > 0) &&
4240 qdf_unlikely(pdev->hmmc_tid_override_en))
4241 msdu_info.tid = pdev->hmmc_tid;
4242
Ishank Jainc838b132017-02-17 11:08:18 +05304243 DP_STATS_INC(vdev, tx_i.mcast_en.ucast, new_mac_cnt);
4244 dp_tx_send_msdu_multiple(vdev, nbuf, &msdu_info);
4245
4246 while (seg_info_head->next) {
4247 seg_info_new = seg_info_head;
4248 seg_info_head = seg_info_head->next;
4249 qdf_mem_free(seg_info_new);
4250 }
4251 qdf_mem_free(seg_info_head);
4252
Pamidipati, Vijay726ea122018-02-07 18:27:00 +05304253 qdf_nbuf_unmap(pdev->soc->osdev, nbuf, QDF_DMA_TO_DEVICE);
4254 qdf_nbuf_free(nbuf);
Ishank Jainc838b132017-02-17 11:08:18 +05304255 return new_mac_cnt;
4256
4257fail_map:
4258 qdf_nbuf_free(nbuf_clone);
4259
4260fail_clone:
4261 dp_tx_me_free_buf(pdev, mc_uc_buf);
4262
4263fail_buf_alloc:
4264 qdf_mem_free(seg_info_new);
4265
4266fail_seg_alloc:
4267 dp_tx_me_mem_free(pdev, seg_info_head);
Pamidipati, Vijay726ea122018-02-07 18:27:00 +05304268
4269free_return:
Ishank Jainc838b132017-02-17 11:08:18 +05304270 qdf_nbuf_unmap(pdev->soc->osdev, nbuf, QDF_DMA_TO_DEVICE);
Pamidipati, Vijay726ea122018-02-07 18:27:00 +05304271 qdf_nbuf_free(nbuf);
4272 return 1;
Ishank Jainc838b132017-02-17 11:08:18 +05304273}
Ruchi, Agrawalc0f9c972018-02-02 11:24:05 +05304274