blob: 02ab4255b051eb6277064c2434f351ef9d4e5bf8 [file] [log] [blame]
Prakash Dhavali7090c5f2015-11-02 17:55:19 -08001/*
Anurag Chouhan50220ce2016-02-18 20:11:33 +05302 * Copyright (c) 2012-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/*=== header file includes ===*/
29/* generic utilities */
Nirav Shahcbc6d722016-03-01 16:24:53 +053030#include <qdf_nbuf.h> /* qdf_nbuf_t, etc. */
Anurag Chouhan754fbd82016-02-19 17:00:08 +053031#include <qdf_timer.h>
Anurag Chouhan50220ce2016-02-18 20:11:33 +053032#include <qdf_time.h>
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080033
34/* datapath internal interfaces */
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080035#include <ol_txrx_internal.h> /* TXRX_ASSERT, etc. */
36#include <ol_rx_reorder.h> /* ol_rx_reorder_flush, etc. */
37
38#ifdef QCA_SUPPORT_OL_RX_REORDER_TIMEOUT
39
40void ol_rx_reorder_timeout_remove(struct ol_txrx_peer_t *peer, unsigned tid)
41{
42 struct ol_txrx_pdev_t *pdev;
43 struct ol_tx_reorder_cat_timeout_t *rx_reorder_timeout_ac;
44 struct ol_rx_reorder_timeout_list_elem_t *list_elem;
45 int ac;
46
47 pdev = peer->vdev->pdev;
48 ac = TXRX_TID_TO_WMM_AC(tid);
49 rx_reorder_timeout_ac = &pdev->rx.reorder_timeout.access_cats[ac];
50 list_elem = &peer->tids_rx_reorder[tid].timeout;
51 if (!list_elem->active) {
52 /* this element has already been removed */
53 return;
54 }
55 list_elem->active = 0;
56 TAILQ_REMOVE(&rx_reorder_timeout_ac->virtual_timer_list, list_elem,
57 reorder_timeout_list_elem);
58}
59
60static void
61ol_rx_reorder_timeout_start(struct ol_tx_reorder_cat_timeout_t
62 *rx_reorder_timeout_ac, uint32_t time_now_ms)
63{
64 uint32_t duration_ms;
65 struct ol_rx_reorder_timeout_list_elem_t *list_elem;
66
67 list_elem = TAILQ_FIRST(&rx_reorder_timeout_ac->virtual_timer_list);
68
69 duration_ms = list_elem->timestamp_ms - time_now_ms;
Anurag Chouhan754fbd82016-02-19 17:00:08 +053070 qdf_timer_start(&rx_reorder_timeout_ac->timer, duration_ms);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080071}
72
73static inline void
74ol_rx_reorder_timeout_add(struct ol_txrx_peer_t *peer, uint8_t tid)
75{
76 uint32_t time_now_ms;
77 struct ol_txrx_pdev_t *pdev;
78 struct ol_tx_reorder_cat_timeout_t *rx_reorder_timeout_ac;
79 struct ol_rx_reorder_timeout_list_elem_t *list_elem;
80 int ac;
81 int start;
82
83 pdev = peer->vdev->pdev;
84 ac = TXRX_TID_TO_WMM_AC(tid);
85 rx_reorder_timeout_ac = &pdev->rx.reorder_timeout.access_cats[ac];
86 list_elem = &peer->tids_rx_reorder[tid].timeout;
87
88 list_elem->active = 1;
89 list_elem->peer = peer;
90 list_elem->tid = tid;
91
92 /* set the expiration timestamp */
Anurag Chouhan50220ce2016-02-18 20:11:33 +053093 time_now_ms = qdf_system_ticks_to_msecs(qdf_system_ticks());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -080094 list_elem->timestamp_ms =
95 time_now_ms + rx_reorder_timeout_ac->duration_ms;
96
97 /* add to the queue */
98 start = TAILQ_EMPTY(&rx_reorder_timeout_ac->virtual_timer_list);
99 TAILQ_INSERT_TAIL(&rx_reorder_timeout_ac->virtual_timer_list,
100 list_elem, reorder_timeout_list_elem);
101 if (start)
102 ol_rx_reorder_timeout_start(rx_reorder_timeout_ac, time_now_ms);
103}
104
105void ol_rx_reorder_timeout_update(struct ol_txrx_peer_t *peer, uint8_t tid)
106{
107 if (!peer)
108 return;
109
110 /*
111 * If there are no holes, i.e. no queued frames,
112 * then timeout doesn't apply.
113 */
114 if (peer->tids_rx_reorder[tid].num_mpdus == 0)
115 return;
116
117 /*
118 * If the virtual timer for this peer-TID is already running,
119 * then leave it.
120 */
121 if (peer->tids_rx_reorder[tid].timeout.active)
122 return;
123
124 ol_rx_reorder_timeout_add(peer, tid);
125}
126
127static void ol_rx_reorder_timeout(void *arg)
128{
129 struct ol_txrx_pdev_t *pdev;
130 struct ol_rx_reorder_timeout_list_elem_t *list_elem, *tmp;
131 uint32_t time_now_ms;
132 struct ol_tx_reorder_cat_timeout_t *rx_reorder_timeout_ac;
133
134 rx_reorder_timeout_ac = (struct ol_tx_reorder_cat_timeout_t *)arg;
Anurag Chouhan50220ce2016-02-18 20:11:33 +0530135 time_now_ms = qdf_system_ticks_to_msecs(qdf_system_ticks());
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800136
137 pdev = rx_reorder_timeout_ac->pdev;
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530138 qdf_spin_lock(&pdev->rx.mutex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800139/* TODO: conditionally take mutex lock during regular rx */
140 TAILQ_FOREACH_SAFE(list_elem,
141 &rx_reorder_timeout_ac->virtual_timer_list,
142 reorder_timeout_list_elem, tmp) {
143 unsigned idx_start, idx_end;
144 struct ol_txrx_peer_t *peer;
145
146 if (list_elem->timestamp_ms > time_now_ms)
147 break; /* time has not expired yet for this element */
148
149 list_elem->active = 0;
150 /* remove the expired element from the list */
151 TAILQ_REMOVE(&rx_reorder_timeout_ac->virtual_timer_list,
152 list_elem, reorder_timeout_list_elem);
153
154 peer = list_elem->peer;
155
156 idx_start = 0xffff; /* start from next_rel_idx */
157 ol_rx_reorder_first_hole(peer, list_elem->tid, &idx_end);
158 ol_rx_reorder_flush(peer->vdev,
159 peer,
160 list_elem->tid,
161 idx_start, idx_end, htt_rx_flush_release);
162 }
163 /* restart the timer if unexpired elements are left in the list */
164 if (!TAILQ_EMPTY(&rx_reorder_timeout_ac->virtual_timer_list))
165 ol_rx_reorder_timeout_start(rx_reorder_timeout_ac, time_now_ms);
166
Anurag Chouhana37b5b72016-02-21 14:53:42 +0530167 qdf_spin_unlock(&pdev->rx.mutex);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800168}
169
170void ol_rx_reorder_timeout_init(struct ol_txrx_pdev_t *pdev)
171{
172 int i;
173
Anurag Chouhan6d760662016-02-20 16:05:43 +0530174 for (i = 0; i < QDF_ARRAY_SIZE(pdev->rx.reorder_timeout.access_cats);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800175 i++) {
176 struct ol_tx_reorder_cat_timeout_t *rx_reorder_timeout_ac;
177 rx_reorder_timeout_ac =
178 &pdev->rx.reorder_timeout.access_cats[i];
179 /* init the per-AC timers */
Anurag Chouhan754fbd82016-02-19 17:00:08 +0530180 qdf_timer_init(pdev->osdev,
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800181 &rx_reorder_timeout_ac->timer,
182 ol_rx_reorder_timeout,
183 rx_reorder_timeout_ac);
184 /* init the virtual timer list */
185 TAILQ_INIT(&rx_reorder_timeout_ac->virtual_timer_list);
186 rx_reorder_timeout_ac->pdev = pdev;
187 }
188 pdev->rx.reorder_timeout.access_cats[TXRX_WMM_AC_VO].duration_ms = 40;
189 pdev->rx.reorder_timeout.access_cats[TXRX_WMM_AC_VI].duration_ms = 100;
190 pdev->rx.reorder_timeout.access_cats[TXRX_WMM_AC_BE].duration_ms = 100;
191 pdev->rx.reorder_timeout.access_cats[TXRX_WMM_AC_BK].duration_ms = 100;
192}
193
194void ol_rx_reorder_timeout_peer_cleanup(struct ol_txrx_peer_t *peer)
195{
196 int tid;
197
198 for (tid = 0; tid < OL_TXRX_NUM_EXT_TIDS; tid++) {
199 if (peer->tids_rx_reorder[tid].timeout.active)
200 ol_rx_reorder_timeout_remove(peer, tid);
201 }
202}
203
204void ol_rx_reorder_timeout_cleanup(struct ol_txrx_pdev_t *pdev)
205{
206 int i;
207
Anurag Chouhan6d760662016-02-20 16:05:43 +0530208 for (i = 0; i < QDF_ARRAY_SIZE(pdev->rx.reorder_timeout.access_cats);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800209 i++) {
210 struct ol_tx_reorder_cat_timeout_t *rx_reorder_timeout_ac;
211 rx_reorder_timeout_ac =
212 &pdev->rx.reorder_timeout.access_cats[i];
Anurag Chouhan754fbd82016-02-19 17:00:08 +0530213 qdf_timer_stop(&rx_reorder_timeout_ac->timer);
214 qdf_timer_free(&rx_reorder_timeout_ac->timer);
Prakash Dhavali7090c5f2015-11-02 17:55:19 -0800215 }
216}
217
218#endif /* QCA_SUPPORT_OL_RX_REORDER_TIMEOUT */