blob: ed726503ae6d020b72f897e722d882369a089a90 [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 */
39
Nirav Shah76291962016-04-25 10:50:37 +053040#define DIV_BY_8 3
41#define DIV_BY_32 5
42#define MOD_BY_8 0x7
43#define MOD_BY_32 0x1F
44
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080045struct ol_tx_desc_t *
46ol_tx_desc_alloc_wrapper(struct ol_txrx_pdev_t *pdev,
47 struct ol_txrx_vdev_t *vdev,
48 struct ol_txrx_msdu_info_t *msdu_info);
49
50
51/**
52 * @brief Allocate and initialize a tx descriptor for a LL system.
53 * @details
54 * Allocate a tx descriptor pair for a new tx frame - a SW tx descriptor
55 * for private use within the host data SW, and a HTT tx descriptor for
56 * downloading tx meta-data to the target FW/HW.
57 * Fill in the fields of this pair of tx descriptors based on the
58 * information in the netbuf.
59 * For LL, this includes filling in a fragmentation descriptor to
60 * specify to the MAC HW where to find the tx frame's fragments.
61 *
62 * @param pdev - the data physical device sending the data
63 * (for accessing the tx desc pool)
64 * @param vdev - the virtual device sending the data
65 * (for specifying the transmitter address for multicast / broadcast data)
66 * @param netbuf - the tx frame
67 * @param msdu_info - tx meta-data
68 */
69struct ol_tx_desc_t *ol_tx_desc_ll(struct ol_txrx_pdev_t *pdev,
70 struct ol_txrx_vdev_t *vdev,
Nirav Shahcbc6d722016-03-01 16:24:53 +053071 qdf_nbuf_t netbuf,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080072 struct ol_txrx_msdu_info_t *msdu_info);
73
74/**
75 * @brief Use a tx descriptor ID to find the corresponding desriptor object.
76 *
77 * @param pdev - the data physical device sending the data
78 * @param tx_desc_id - the ID of the descriptor in question
79 * @return the descriptor object that has the specified ID
80 */
Leo Chang376398b2015-10-23 14:19:02 -070081static inline struct ol_tx_desc_t *ol_tx_desc_find(
82 struct ol_txrx_pdev_t *pdev, uint16_t tx_desc_id)
83{
84 void **td_base = (void **)pdev->tx_desc.desc_pages.cacheable_pages;
85
86 return &((union ol_tx_desc_list_elem_t *)
87 (td_base[tx_desc_id >> pdev->tx_desc.page_divider] +
88 (pdev->tx_desc.desc_reserved_size *
89 (tx_desc_id & pdev->tx_desc.offset_filter))))->tx_desc;
90}
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080091
92/**
93 * @brief Free a list of tx descriptors and the tx frames they refer to.
94 * @details
95 * Free a batch of "standard" tx descriptors and their tx frames.
96 * Free each tx descriptor, by returning it to the freelist.
97 * Unmap each netbuf, and free the netbufs as a batch.
98 * Irregular tx frames like TSO or managment frames that require
99 * special handling are processed by the ol_tx_desc_frame_free_nonstd
100 * function rather than this function.
101 *
102 * @param pdev - the data physical device that sent the data
103 * @param tx_descs - a list of SW tx descriptors for the tx frames
104 * @param had_error - bool indication of whether the transmission failed.
105 * This is provided to callback functions that get notified of
106 * the tx frame completion.
107 */
108void ol_tx_desc_frame_list_free(struct ol_txrx_pdev_t *pdev,
109 ol_tx_desc_list *tx_descs, int had_error);
110
111/**
112 * @brief Free a non-standard tx frame and its tx descriptor.
113 * @details
114 * Check the tx frame type (e.g. TSO vs. management) to determine what
115 * special steps, if any, need to be performed prior to freeing the
116 * tx frame and its tx descriptor.
117 * This function can also be used to free single standard tx frames.
118 * After performing any special steps based on tx frame type, free the
119 * tx descriptor, i.e. return it to the freelist, and unmap and
120 * free the netbuf referenced by the tx descriptor.
121 *
122 * @param pdev - the data physical device that sent the data
123 * @param tx_desc - the SW tx descriptor for the tx frame that was sent
124 * @param had_error - bool indication of whether the transmission failed.
125 * This is provided to callback functions that get notified of
126 * the tx frame completion.
127 */
128void ol_tx_desc_frame_free_nonstd(struct ol_txrx_pdev_t *pdev,
129 struct ol_tx_desc_t *tx_desc, int had_error);
130
131/*
132 * @brief Determine the ID of a tx descriptor.
133 *
134 * @param pdev - the physical device that is sending the data
135 * @param tx_desc - the descriptor whose ID is being determined
136 * @return numeric ID that uniquely identifies the tx descriptor
137 */
138static inline uint16_t
139ol_tx_desc_id(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc)
140{
Leo Chang376398b2015-10-23 14:19:02 -0700141 TXRX_ASSERT2(tx_desc->id < pdev->tx_desc.pool_size);
142 return tx_desc->id;
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800143}
144
145/*
146 * @brief Retrieves the beacon headr for the vdev
147 * @param pdev - opaque pointe to scn
148 * @param vdevid - vdev id
149 * @return void pointer to the beacon header for the given vdev
150 */
151
152void *ol_ath_get_bcn_header(ol_pdev_handle pdev, A_UINT32 vdev_id);
153
154/*
155 * @brief Free a tx descriptor, without freeing the matching frame.
156 * @details
157 * This function is using during the function call that submits tx frames
158 * into the txrx layer, for cases where a tx descriptor is successfully
159 * allocated, but for other reasons the frame could not be accepted.
160 *
161 * @param pdev - the data physical device that is sending the data
162 * @param tx_desc - the descriptor being freed
163 */
164void ol_tx_desc_free(struct ol_txrx_pdev_t *pdev, struct ol_tx_desc_t *tx_desc);
165
166#if defined(FEATURE_TSO)
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530167struct qdf_tso_seg_elem_t *ol_tso_alloc_segment(struct ol_txrx_pdev_t *pdev);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168
169void ol_tso_free_segment(struct ol_txrx_pdev_t *pdev,
Anurag Chouhanf04e84f2016-03-03 10:12:12 +0530170 struct qdf_tso_seg_elem_t *tso_seg);
Dhanashri Atre83d373d2015-07-28 16:45:59 -0700171#else
172#define ol_tso_alloc_segment(pdev) /*no-op*/
173#define ol_tso_free_segment(pdev, tso_seg) /*no-op*/
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800174#endif
175
Nirav Shah9d7f2e82015-09-28 11:09:09 -0700176/**
177 * ol_tx_get_desc_global_pool() - get descriptor from global pool
178 * @pdev: pdev handler
179 *
180 * Caller needs to take lock and do sanity checks.
181 *
182 * Return: tx descriptor
183 */
184static inline
185struct ol_tx_desc_t *ol_tx_get_desc_global_pool(struct ol_txrx_pdev_t *pdev)
186{
187 struct ol_tx_desc_t *tx_desc = &pdev->tx_desc.freelist->tx_desc;
188 pdev->tx_desc.freelist = pdev->tx_desc.freelist->next;
189 pdev->tx_desc.num_free--;
190 return tx_desc;
191}
192
193/**
194 * ol_tx_put_desc_global_pool() - put descriptor to global pool freelist
195 * @pdev: pdev handle
196 * @tx_desc: tx descriptor
197 *
198 * Caller needs to take lock and do sanity checks.
199 *
200 * Return: none
201 */
202static inline
203void ol_tx_put_desc_global_pool(struct ol_txrx_pdev_t *pdev,
204 struct ol_tx_desc_t *tx_desc)
205{
206 ((union ol_tx_desc_list_elem_t *)tx_desc)->next =
207 pdev->tx_desc.freelist;
208 pdev->tx_desc.freelist =
209 (union ol_tx_desc_list_elem_t *)tx_desc;
210 pdev->tx_desc.num_free++;
211 return;
212}
213
214
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800215#ifdef QCA_LL_TX_FLOW_CONTROL_V2
216int ol_tx_free_invalid_flow_pool(struct ol_tx_flow_pool_t *pool);
Nirav Shah9d7f2e82015-09-28 11:09:09 -0700217/**
218 * ol_tx_get_desc_flow_pool() - get descriptor from flow pool
219 * @pool: flow pool
220 *
221 * Caller needs to take lock and do sanity checks.
222 *
223 * Return: tx descriptor
224 */
225static inline
226struct ol_tx_desc_t *ol_tx_get_desc_flow_pool(struct ol_tx_flow_pool_t *pool)
227{
228 struct ol_tx_desc_t *tx_desc = &pool->freelist->tx_desc;
229 pool->freelist = pool->freelist->next;
230 pool->avail_desc--;
231 return tx_desc;
232}
233
234/**
235 * ol_tx_put_desc_flow_pool() - put descriptor to flow pool freelist
236 * @pool: flow pool
237 * @tx_desc: tx descriptor
238 *
239 * Caller needs to take lock and do sanity checks.
240 *
241 * Return: none
242 */
243static inline
244void ol_tx_put_desc_flow_pool(struct ol_tx_flow_pool_t *pool,
245 struct ol_tx_desc_t *tx_desc)
246{
247 tx_desc->pool = pool;
248 ((union ol_tx_desc_list_elem_t *)tx_desc)->next = pool->freelist;
249 pool->freelist = (union ol_tx_desc_list_elem_t *)tx_desc;
250 pool->avail_desc++;
251 return;
252}
253
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800254#else
255static inline int ol_tx_free_invalid_flow_pool(void *pool)
256{
257 return 0;
258}
259#endif
260
Nirav Shah76291962016-04-25 10:50:37 +0530261#ifdef DESC_DUP_DETECT_DEBUG
262/**
263 * ol_tx_desc_dup_detect_init() - initialize descriptor duplication logic
264 * @pdev: pdev handle
265 * @pool_size: global pool size
266 *
267 * Return: none
268 */
269static inline
270void ol_tx_desc_dup_detect_init(struct ol_txrx_pdev_t *pdev, uint16_t pool_size)
271{
272 uint16_t size = (pool_size >> DIV_BY_8) +
273 ((pool_size & MOD_BY_8) ? 1 : 0);
274 pdev->tx_desc.free_list_bitmap = qdf_mem_malloc(size);
275 if (!pdev->tx_desc.free_list_bitmap)
276 qdf_print("%s: malloc failed", __func__);
277}
278
279/**
280 * ol_tx_desc_dup_detect_deinit() - deinit descriptor duplication logic
281 * @pdev: pdev handle
282 *
283 * Return: none
284 */
285static inline
286void ol_tx_desc_dup_detect_deinit(struct ol_txrx_pdev_t *pdev)
287{
288 qdf_print("%s: pool_size %d num_free %d\n", __func__,
289 pdev->tx_desc.pool_size, pdev->tx_desc.num_free);
290 if (pdev->tx_desc.free_list_bitmap)
291 qdf_mem_free(pdev->tx_desc.free_list_bitmap);
292}
293
294/**
295 * ol_tx_desc_dup_detect_set() - set bit for msdu_id
296 * @pdev: pdev handle
297 * @tx_desc: tx descriptor
298 *
299 * Return: none
300 */
301static inline
302void ol_tx_desc_dup_detect_set(struct ol_txrx_pdev_t *pdev,
303 struct ol_tx_desc_t *tx_desc)
304{
305 uint16_t msdu_id = ol_tx_desc_id(pdev, tx_desc);
306 uint16_t index = msdu_id >> DIV_BY_32;
307 uint8_t pos = msdu_id & MOD_BY_32;
308
309 if (!pdev->tx_desc.free_list_bitmap)
310 return;
311
312 if (qdf_unlikely(pdev->tx_desc.free_list_bitmap[index] & (1 << pos))) {
313 uint16_t size = (pdev->tx_desc.pool_size >> DIV_BY_8) +
314 ((pdev->tx_desc.pool_size & MOD_BY_8) ? 1 : 0);
315 qdf_print("duplicate msdu_id %d detected !!\n", msdu_id);
316 qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
317 (void *)pdev->tx_desc.free_list_bitmap, size);
318 QDF_BUG(0);
319 }
320 pdev->tx_desc.free_list_bitmap[index] |= (1 << pos);
321}
322
323/**
324 * ol_tx_desc_dup_detect_reset() - reset bit for msdu_id
325 * @pdev: pdev handle
326 * @tx_desc: tx descriptor
327 *
328 * Return: none
329 */
330static inline
331void ol_tx_desc_dup_detect_reset(struct ol_txrx_pdev_t *pdev,
332 struct ol_tx_desc_t *tx_desc)
333{
334 uint16_t msdu_id = ol_tx_desc_id(pdev, tx_desc);
335 uint16_t index = msdu_id >> DIV_BY_32;
336 uint8_t pos = msdu_id & MOD_BY_32;
337
338 if (!pdev->tx_desc.free_list_bitmap)
339 return;
340
341 if (qdf_unlikely(!
342 (pdev->tx_desc.free_list_bitmap[index] & (1 << pos)))) {
343 uint16_t size = (pdev->tx_desc.pool_size >> DIV_BY_8) +
344 ((pdev->tx_desc.pool_size & MOD_BY_8) ? 1 : 0);
345 qdf_print("duplicate free msg received for msdu_id %d!!\n",
346 msdu_id);
347 qdf_trace_hex_dump(QDF_MODULE_ID_TXRX, QDF_TRACE_LEVEL_ERROR,
348 (void *)pdev->tx_desc.free_list_bitmap, size);
349 QDF_BUG(0);
350 }
351 pdev->tx_desc.free_list_bitmap[index] &= ~(1 << pos);
352}
353#else
354static inline
355void ol_tx_desc_dup_detect_init(struct ol_txrx_pdev_t *pdev, uint16_t size)
356{
357}
358
359static inline
360void ol_tx_desc_dup_detect_deinit(struct ol_txrx_pdev_t *pdev)
361{
362}
363
364static inline
365void ol_tx_desc_dup_detect_set(struct ol_txrx_pdev_t *pdev,
366 struct ol_tx_desc_t *tx_desc)
367{
368}
369
370static inline
371void ol_tx_desc_dup_detect_reset(struct ol_txrx_pdev_t *pdev,
372 struct ol_tx_desc_t *tx_desc)
373{
374}
375#endif
376
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800377#endif /* _OL_TX_DESC__H_ */