blob: 466510ff5cb35f85b3bcb1cbf504a0ff54c19119 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Dhanashri Atre83d373d2015-07-28 16:45:59 -07002 * Copyright (c) 2011, 2014-2016 The Linux Foundation. All rights reserved.
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08003 *
4 * Previously licensed under the ISC license by Qualcomm Atheros, Inc.
5 *
6 *
7 * Permission to use, copy, modify, and/or distribute this software for
8 * any purpose with or without fee is hereby granted, provided that the
9 * above copyright notice and this permission notice appear in all
10 * copies.
11 *
12 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
13 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
14 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE
15 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
16 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
17 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
18 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
19 * PERFORMANCE OF THIS SOFTWARE.
20 */
21
22/*
23 * This file was originally distributed by Qualcomm Atheros, Inc.
24 * under proprietary terms before Copyright ownership was assigned
25 * to the Linux Foundation.
26 */
27
28/**
29 * @file ol_tx_desc.h
30 * @brief API definitions for the tx descriptor module within the data SW.
31 */
32#ifndef _OL_TX_DESC__H_
33#define _OL_TX_DESC__H_
34
35#include <cds_queue.h> /* TAILQ_HEAD */
Nirav Shahcbc6d722016-03-01 16:24:53 +053036#include <qdf_nbuf.h> /* qdf_nbuf_t */
Dhanashri Atre12a08392016-02-17 13:10:34 -080037#include <cdp_txrx_cmn.h> /* ol_txrx_vdev_t, etc. */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080038#include <ol_txrx_internal.h> /*TXRX_ASSERT2 */
Nirav Shah2e583a02016-04-30 14:06:12 +053039#include <ol_htt_tx_api.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080040
Nirav Shah76291962016-04-25 10:50:37 +053041#define DIV_BY_8 3
42#define DIV_BY_32 5
43#define MOD_BY_8 0x7
44#define MOD_BY_32 0x1F
45
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080046struct ol_tx_desc_t *
47ol_tx_desc_alloc_wrapper(struct ol_txrx_pdev_t *pdev,
48 struct ol_txrx_vdev_t *vdev,
49 struct ol_txrx_msdu_info_t *msdu_info);
50
51
52/**
53 * @brief Allocate and initialize a tx descriptor for a LL system.
54 * @details
55 * Allocate a tx descriptor pair for a new tx frame - a SW tx descriptor
56 * for private use within the host data SW, and a HTT tx descriptor for
57 * downloading tx meta-data to the target FW/HW.
58 * Fill in the fields of this pair of tx descriptors based on the
59 * information in the netbuf.
60 * For LL, this includes filling in a fragmentation descriptor to
61 * specify to the MAC HW where to find the tx frame's fragments.
62 *
63 * @param pdev - the data physical device sending the data
64 * (for accessing the tx desc pool)
65 * @param vdev - the virtual device sending the data
66 * (for specifying the transmitter address for multicast / broadcast data)
67 * @param netbuf - the tx frame
68 * @param msdu_info - tx meta-data
69 */
70struct ol_tx_desc_t *ol_tx_desc_ll(struct ol_txrx_pdev_t *pdev,
71 struct ol_txrx_vdev_t *vdev,
Nirav Shahcbc6d722016-03-01 16:24:53 +053072 qdf_nbuf_t netbuf,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080073 struct ol_txrx_msdu_info_t *msdu_info);
74
Siddarth Poddarb2011f62016-04-27 20:45:42 +053075
76/**
77 * @brief Allocate and initialize a tx descriptor for a HL system.
78 * @details
79 * Allocate a tx descriptor pair for a new tx frame - a SW tx descriptor
80 * for private use within the host data SW, and a HTT tx descriptor for
81 * downloading tx meta-data to the target FW/HW.
82 * Fill in the fields of this pair of tx descriptors based on the
83 * information in the netbuf.
84 *
85 * @param pdev - the data physical device sending the data
86 * (for accessing the tx desc pool)
87 * @param vdev - the virtual device sending the data
88 * (for specifying the transmitter address for multicast / broadcast data)
89 * @param netbuf - the tx frame
90 * @param msdu_info - tx meta-data
91 */
92struct ol_tx_desc_t *
93ol_tx_desc_hl(
94 struct ol_txrx_pdev_t *pdev,
95 struct ol_txrx_vdev_t *vdev,
96 qdf_nbuf_t netbuf,
97 struct ol_txrx_msdu_info_t *msdu_info);
98
99
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800100/**
101 * @brief Use a tx descriptor ID to find the corresponding desriptor object.
102 *
103 * @param pdev - the data physical device sending the data
104 * @param tx_desc_id - the ID of the descriptor in question
105 * @return the descriptor object that has the specified ID
106 */
Leo Chang376398b2015-10-23 14:19:02 -0700107static inline struct ol_tx_desc_t *ol_tx_desc_find(
108 struct ol_txrx_pdev_t *pdev, uint16_t tx_desc_id)
109{
110 void **td_base = (void **)pdev->tx_desc.desc_pages.cacheable_pages;
111
112 return &((union ol_tx_desc_list_elem_t *)
113 (td_base[tx_desc_id >> pdev->tx_desc.page_divider] +
114 (pdev->tx_desc.desc_reserved_size *
115 (tx_desc_id & pdev->tx_desc.offset_filter))))->tx_desc;
116}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800117
118/**
gbiane55c9562016-11-01 14:47:47 +0800119 * @brief Use a tx descriptor ID to find the corresponding desriptor object
120 * and add sanity check.
121 *
122 * @param pdev - the data physical device sending the data
123 * @param tx_desc_id - the ID of the descriptor in question
124 * @return the descriptor object that has the specified ID,
125 * if failure, will return NULL.
126 */
127
128#ifdef QCA_SUPPORT_TXDESC_SANITY_CHECKS
129static inline struct ol_tx_desc_t *
130ol_tx_desc_find_check(struct ol_txrx_pdev_t *pdev, u_int16_t tx_desc_id)
131{
132 struct ol_tx_desc_t *tx_desc;
133
134 tx_desc = ol_tx_desc_find(pdev, tx_desc_id);
135
136 if (tx_desc->pkt_type == ol_tx_frm_freed) {
137 return NULL;
138 }
139
140 return tx_desc;
141}
142
143#else
144
145static inline struct ol_tx_desc_t *
146ol_tx_desc_find_check(struct ol_txrx_pdev_t *pdev, u_int16_t tx_desc_id)
147{
148 return ol_tx_desc_find(pdev, tx_desc_id);
149}
150#endif
151
152/**
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800153 * @brief Free a list of tx descriptors and the tx frames they refer to.
154 * @details
155 * Free a batch of "standard" tx descriptors and their tx frames.
156 * Free each tx descriptor, by returning it to the freelist.
157 * Unmap each netbuf, and free the netbufs as a batch.
158 * Irregular tx frames like TSO or managment frames that require
159 * special handling are processed by the ol_tx_desc_frame_free_nonstd
160 * function rather than this function.
161 *
162 * @param pdev - the data physical device that sent the data
163 * @param tx_descs - a list of SW tx descriptors for the tx frames
164 * @param had_error - bool indication of whether the transmission failed.
165 * This is provided to callback functions that get notified of
166 * the tx frame completion.
167 */
168void ol_tx_desc_frame_list_free(struct ol_txrx_pdev_t *pdev,
169 ol_tx_desc_list *tx_descs, int had_error);
170
171/**
172 * @brief Free a non-standard tx frame and its tx descriptor.
173 * @details
174 * Check the tx frame type (e.g. TSO vs. management) to determine what
175 * special steps, if any, need to be performed prior to freeing the
176 * tx frame and its tx descriptor.
177 * This function can also be used to free single standard tx frames.
178 * After performing any special steps based on tx frame type, free the
179 * tx descriptor, i.e. return it to the freelist, and unmap and
180 * free the netbuf referenced by the tx descriptor.
181 *
182 * @param pdev - the data physical device that sent the data
183 * @param tx_desc - the SW tx descriptor for the tx frame that was sent
184 * @param had_error - bool indication of whether the transmission failed.
185 * This is provided to callback functions that get notified of
186 * the tx frame completion.
187 */
188void ol_tx_desc_frame_free_nonstd(struct ol_txrx_pdev_t *pdev,
189 struct ol_tx_desc_t *tx_desc, int had_error);
190
191/*
192 * @brief Determine the ID of a tx descriptor.
193 *
194 * @param pdev - the physical device that is sending the data
195 * @param tx_desc - the descriptor whose ID is being determined
196 * @return numeric ID that uniquely identifies the tx descriptor
197 */
198static inline uint16_t
199ol_tx_desc_id(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc)
200{
Leo Chang376398b2015-10-23 14:19:02 -0700201 TXRX_ASSERT2(tx_desc->id < pdev->tx_desc.pool_size);
202 return tx_desc->id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800203}
204
205/*
206 * @brief Retrieves the beacon headr for the vdev
207 * @param pdev - opaque pointe to scn
208 * @param vdevid - vdev id
209 * @return void pointer to the beacon header for the given vdev
210 */
211
212void *ol_ath_get_bcn_header(ol_pdev_handle pdev, A_UINT32 vdev_id);
213
214/*
215 * @brief Free a tx descriptor, without freeing the matching frame.
216 * @details
217 * This function is using during the function call that submits tx frames
218 * into the txrx layer, for cases where a tx descriptor is successfully
219 * allocated, but for other reasons the frame could not be accepted.
220 *
221 * @param pdev - the data physical device that is sending the data
222 * @param tx_desc - the descriptor being freed
223 */
224void ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc);
225
226#if defined(FEATURE_TSO)
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530227struct qdf_tso_seg_elem_t *ol_tso_alloc_segment(struct ol_txrx_pdev_t *pdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800228
229void ol_tso_free_segment(struct ol_txrx_pdev_t *pdev,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530230 struct qdf_tso_seg_elem_t *tso_seg);
Dhanashri Atre83d373d2015-07-28 16:45:59 -0700231#else
232#define ol_tso_alloc_segment(pdev) /*no-op*/
233#define ol_tso_free_segment(pdev, tso_seg) /*no-op*/
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800234#endif
235
Nirav Shah9d7f2e82015-09-28 11:09:09 -0700236/**
237 * ol_tx_get_desc_global_pool() - get descriptor from global pool
238 * @pdev: pdev handler
239 *
240 * Caller needs to take lock and do sanity checks.
241 *
242 * Return: tx descriptor
243 */
244static inline
245struct ol_tx_desc_t *ol_tx_get_desc_global_pool(struct ol_txrx_pdev_t *pdev)
246{
247 struct ol_tx_desc_t *tx_desc = &pdev->tx_desc.freelist->tx_desc;
248 pdev->tx_desc.freelist = pdev->tx_desc.freelist->next;
249 pdev->tx_desc.num_free--;
250 return tx_desc;
251}
252
253/**
254 * ol_tx_put_desc_global_pool() - put descriptor to global pool freelist
255 * @pdev: pdev handle
256 * @tx_desc: tx descriptor
257 *
258 * Caller needs to take lock and do sanity checks.
259 *
260 * Return: none
261 */
262static inline
263void ol_tx_put_desc_global_pool(struct ol_txrx_pdev_t *pdev,
264 struct ol_tx_desc_t *tx_desc)
265{
266 ((union ol_tx_desc_list_elem_t *)tx_desc)->next =
267 pdev->tx_desc.freelist;
268 pdev->tx_desc.freelist =
269 (union ol_tx_desc_list_elem_t *)tx_desc;
270 pdev->tx_desc.num_free++;
271 return;
272}
273
274
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800275#ifdef QCA_LL_TX_FLOW_CONTROL_V2
276int ol_tx_free_invalid_flow_pool(struct ol_tx_flow_pool_t *pool);
Nirav Shah9d7f2e82015-09-28 11:09:09 -0700277/**
278 * ol_tx_get_desc_flow_pool() - get descriptor from flow pool
279 * @pool: flow pool
280 *
281 * Caller needs to take lock and do sanity checks.
282 *
283 * Return: tx descriptor
284 */
285static inline
286struct ol_tx_desc_t *ol_tx_get_desc_flow_pool(struct ol_tx_flow_pool_t *pool)
287{
288 struct ol_tx_desc_t *tx_desc = &pool->freelist->tx_desc;
289 pool->freelist = pool->freelist->next;
290 pool->avail_desc--;
291 return tx_desc;
292}
293
294/**
295 * ol_tx_put_desc_flow_pool() - put descriptor to flow pool freelist
296 * @pool: flow pool
297 * @tx_desc: tx descriptor
298 *
299 * Caller needs to take lock and do sanity checks.
300 *
301 * Return: none
302 */
303static inline
304void ol_tx_put_desc_flow_pool(struct ol_tx_flow_pool_t *pool,
305 struct ol_tx_desc_t *tx_desc)
306{
307 tx_desc->pool = pool;
308 ((union ol_tx_desc_list_elem_t *)tx_desc)->next = pool->freelist;
309 pool->freelist = (union ol_tx_desc_list_elem_t *)tx_desc;
310 pool->avail_desc++;
311 return;
312}
313
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800314#else
315static inline int ol_tx_free_invalid_flow_pool(void *pool)
316{
317 return 0;
318}
319#endif
320
Nirav Shah76291962016-04-25 10:50:37 +0530321#ifdef DESC_DUP_DETECT_DEBUG
322/**
323 * ol_tx_desc_dup_detect_init() - initialize descriptor duplication logic
324 * @pdev: pdev handle
325 * @pool_size: global pool size
326 *
327 * Return: none
328 */
329static inline
330void ol_tx_desc_dup_detect_init(struct ol_txrx_pdev_t *pdev, uint16_t pool_size)
331{
332 uint16_t size = (pool_size >> DIV_BY_8) +
Houston Hoffman088e4b92016-09-01 13:51:06 -0700333 sizeof(*pdev->tx_desc.free_list_bitmap);
Nirav Shah76291962016-04-25 10:50:37 +0530334 pdev->tx_desc.free_list_bitmap = qdf_mem_malloc(size);
335 if (!pdev->tx_desc.free_list_bitmap)
336 qdf_print("%s: malloc failed", __func__);
337}
338
339/**
340 * ol_tx_desc_dup_detect_deinit() - deinit descriptor duplication logic
341 * @pdev: pdev handle
342 *
343 * Return: none
344 */
345static inline
346void ol_tx_desc_dup_detect_deinit(struct ol_txrx_pdev_t *pdev)
347{
348 qdf_print("%s: pool_size %d num_free %d\n", __func__,
349 pdev->tx_desc.pool_size, pdev->tx_desc.num_free);
350 if (pdev->tx_desc.free_list_bitmap)
351 qdf_mem_free(pdev->tx_desc.free_list_bitmap);
352}
353
354/**
355 * ol_tx_desc_dup_detect_set() - set bit for msdu_id
356 * @pdev: pdev handle
357 * @tx_desc: tx descriptor
358 *
359 * Return: none
360 */
361static inline
362void ol_tx_desc_dup_detect_set(struct ol_txrx_pdev_t *pdev,
363 struct ol_tx_desc_t *tx_desc)
364{
365 uint16_t msdu_id = ol_tx_desc_id(pdev, tx_desc);
Houston Hoffman088e4b92016-09-01 13:51:06 -0700366 bool test;
Nirav Shah76291962016-04-25 10:50:37 +0530367
368 if (!pdev->tx_desc.free_list_bitmap)
369 return;
370
Houston Hoffman088e4b92016-09-01 13:51:06 -0700371 if (qdf_unlikely(msdu_id > pdev->tx_desc.pool_size)) {
372 qdf_print("%s: msdu_id %d > pool_size %d",
373 __func__, msdu_id, pdev->tx_desc.pool_size);
374 QDF_BUG(0);
375 }
376
377 test = test_and_set_bit(msdu_id, pdev->tx_desc.free_list_bitmap);
378 if (qdf_unlikely(test)) {
Nirav Shah76291962016-04-25 10:50:37 +0530379 uint16_t size = (pdev->tx_desc.pool_size >> DIV_BY_8) +
380 ((pdev->tx_desc.pool_size & MOD_BY_8) ? 1 : 0);
381 qdf_print("duplicate msdu_id %d detected !!\n", msdu_id);
382 qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
383 (void *)pdev->tx_desc.free_list_bitmap, size);
384 QDF_BUG(0);
385 }
Nirav Shah76291962016-04-25 10:50:37 +0530386}
387
388/**
389 * ol_tx_desc_dup_detect_reset() - reset bit for msdu_id
390 * @pdev: pdev handle
391 * @tx_desc: tx descriptor
392 *
393 * Return: none
394 */
395static inline
396void ol_tx_desc_dup_detect_reset(struct ol_txrx_pdev_t *pdev,
397 struct ol_tx_desc_t *tx_desc)
398{
399 uint16_t msdu_id = ol_tx_desc_id(pdev, tx_desc);
Houston Hoffman088e4b92016-09-01 13:51:06 -0700400 bool test;
Nirav Shah76291962016-04-25 10:50:37 +0530401
402 if (!pdev->tx_desc.free_list_bitmap)
403 return;
404
Houston Hoffman088e4b92016-09-01 13:51:06 -0700405 if (qdf_unlikely(msdu_id > pdev->tx_desc.pool_size)) {
406 qdf_print("%s: msdu_id %d > pool_size %d",
407 __func__, msdu_id, pdev->tx_desc.pool_size);
408 QDF_BUG(0);
409 }
410
411 test = !test_and_clear_bit(msdu_id, pdev->tx_desc.free_list_bitmap);
412 if (qdf_unlikely(test)) {
Nirav Shah76291962016-04-25 10:50:37 +0530413 uint16_t size = (pdev->tx_desc.pool_size >> DIV_BY_8) +
414 ((pdev->tx_desc.pool_size & MOD_BY_8) ? 1 : 0);
415 qdf_print("duplicate free msg received for msdu_id %d!!\n",
416 msdu_id);
417 qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
418 (void *)pdev->tx_desc.free_list_bitmap, size);
419 QDF_BUG(0);
420 }
Nirav Shah76291962016-04-25 10:50:37 +0530421}
422#else
423static inline
424void ol_tx_desc_dup_detect_init(struct ol_txrx_pdev_t *pdev, uint16_t size)
425{
426}
427
428static inline
429void ol_tx_desc_dup_detect_deinit(struct ol_txrx_pdev_t *pdev)
430{
431}
432
433static inline
434void ol_tx_desc_dup_detect_set(struct ol_txrx_pdev_t *pdev,
435 struct ol_tx_desc_t *tx_desc)
436{
437}
438
439static inline
440void ol_tx_desc_dup_detect_reset(struct ol_txrx_pdev_t *pdev,
441 struct ol_tx_desc_t *tx_desc)
442{
443}
444#endif
445
Nirav Shah2e583a02016-04-30 14:06:12 +0530446enum extension_header_type
447ol_tx_get_ext_header_type(struct ol_txrx_vdev_t *vdev,
448 qdf_nbuf_t netbuf);
449enum extension_header_type
450ol_tx_get_wisa_ext_type(qdf_nbuf_t netbuf);
451
452
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800453#endif /* _OL_TX_DESC__H_ */