Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv.c
48526 views
1
/*
2
* Copyright (c) 2013 Qualcomm Atheros, Inc.
3
*
4
* Permission to use, copy, modify, and/or distribute this software for any
5
* purpose with or without fee is hereby granted, provided that the above
6
* copyright notice and this permission notice appear in all copies.
7
*
8
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9
* REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10
* AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11
* INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12
* LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13
* OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14
* PERFORMANCE OF THIS SOFTWARE.
15
*/
16
17
#include "opt_ah.h"
18
19
#include "ah.h"
20
#include "ah_desc.h"
21
#include "ah_internal.h"
22
23
#include "ar9300/ar9300.h"
24
#include "ar9300/ar9300reg.h"
25
#include "ar9300/ar9300desc.h"
26
27
/*
28
* Get the RXDP.
29
*/
30
u_int32_t
31
ar9300_get_rx_dp(struct ath_hal *ath, HAL_RX_QUEUE qtype)
32
{
33
if (qtype == HAL_RX_QUEUE_HP) {
34
return OS_REG_READ(ath, AR_HP_RXDP);
35
} else {
36
return OS_REG_READ(ath, AR_LP_RXDP);
37
}
38
}
39
40
/*
41
* Set the rx_dp.
42
*/
43
void
44
ar9300_set_rx_dp(struct ath_hal *ah, u_int32_t rxdp, HAL_RX_QUEUE qtype)
45
{
46
HALASSERT((qtype == HAL_RX_QUEUE_HP) || (qtype == HAL_RX_QUEUE_LP));
47
48
if (qtype == HAL_RX_QUEUE_HP) {
49
OS_REG_WRITE(ah, AR_HP_RXDP, rxdp);
50
} else {
51
OS_REG_WRITE(ah, AR_LP_RXDP, rxdp);
52
}
53
}
54
55
/*
56
* Set Receive Enable bits.
57
*/
58
void
59
ar9300_enable_receive(struct ath_hal *ah)
60
{
61
OS_REG_WRITE(ah, AR_CR, 0);
62
}
63
64
/*
65
* Set the RX abort bit.
66
*/
67
HAL_BOOL
68
ar9300_set_rx_abort(struct ath_hal *ah, HAL_BOOL set)
69
{
70
if (set) {
71
/* Set the force_rx_abort bit */
72
OS_REG_SET_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
73
74
if ( AH9300(ah)->ah_reset_reason == HAL_RESET_BBPANIC ){
75
/* depending upon the BB panic status, rx state may not return to 0,
76
* so skipping the wait for BB panic reset */
77
OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
78
return AH_FALSE;
79
} else {
80
HAL_BOOL okay;
81
okay = ath_hal_wait(
82
ah, AR_OBS_BUS_1, AR_OBS_BUS_1_RX_STATE, 0);
83
/* Wait for Rx state to return to 0 */
84
if (!okay) {
85
/* abort: chip rx failed to go idle in 10 ms */
86
OS_REG_CLR_BIT(ah, AR_DIAG_SW,
87
(AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
88
89
HALDEBUG(ah, HAL_DEBUG_RX,
90
"%s: rx failed to go idle in 10 ms RXSM=0x%x\n",
91
__func__, OS_REG_READ(ah, AR_OBS_BUS_1));
92
93
return AH_FALSE; /* failure */
94
}
95
}
96
} else {
97
OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
98
}
99
100
return AH_TRUE; /* success */
101
}
102
103
/*
104
* Stop Receive at the DMA engine
105
*/
106
HAL_BOOL
107
ar9300_stop_dma_receive(struct ath_hal *ah, u_int timeout)
108
{
109
int wait;
110
HAL_BOOL status, okay;
111
u_int32_t org_value;
112
113
#define AH_RX_STOP_DMA_TIMEOUT 10000 /* usec */
114
#define AH_TIME_QUANTUM 100 /* usec */
115
116
OS_MARK(ah, AH_MARK_RX_CTL, AH_MARK_RX_CTL_DMA_STOP);
117
118
if (timeout == 0) {
119
timeout = AH_RX_STOP_DMA_TIMEOUT;
120
}
121
122
org_value = OS_REG_READ(ah, AR_MACMISC);
123
124
OS_REG_WRITE(ah, AR_MACMISC,
125
((AR_MACMISC_DMA_OBS_LINE_8 << AR_MACMISC_DMA_OBS_S) |
126
(AR_MACMISC_MISC_OBS_BUS_1 << AR_MACMISC_MISC_OBS_BUS_MSB_S)));
127
128
okay = ath_hal_wait(
129
ah, AR_DMADBG_7, AR_DMADBG_RX_STATE, 0);
130
/* wait for Rx DMA state machine to become idle */
131
if (!okay) {
132
HALDEBUG(ah, HAL_DEBUG_RX,
133
"reg AR_DMADBG_7 is not 0, instead 0x%08x\n",
134
OS_REG_READ(ah, AR_DMADBG_7));
135
}
136
137
/* Set receive disable bit */
138
OS_REG_WRITE(ah, AR_CR, AR_CR_RXD);
139
140
/* Wait for rx enable bit to go low */
141
for (wait = timeout / AH_TIME_QUANTUM; wait != 0; wait--) {
142
if ((OS_REG_READ(ah, AR_CR) & AR_CR_RXE) == 0) {
143
break;
144
}
145
OS_DELAY(AH_TIME_QUANTUM);
146
}
147
148
if (wait == 0) {
149
HALDEBUG(ah, HAL_DEBUG_RX, "%s: dma failed to stop in %d ms\n"
150
"AR_CR=0x%08x\nAR_DIAG_SW=0x%08x\n",
151
__func__,
152
timeout / 1000,
153
OS_REG_READ(ah, AR_CR),
154
OS_REG_READ(ah, AR_DIAG_SW));
155
status = AH_FALSE;
156
} else {
157
status = AH_TRUE;
158
}
159
160
OS_REG_WRITE(ah, AR_MACMISC, org_value);
161
162
OS_MARK(ah, AH_MARK_RX_CTL,
163
status ? AH_MARK_RX_CTL_DMA_STOP_OK : AH_MARK_RX_CTL_DMA_STOP_ERR);
164
165
return status;
166
#undef AH_RX_STOP_DMA_TIMEOUT
167
#undef AH_TIME_QUANTUM
168
}
169
170
/*
171
* Start Transmit at the PCU engine (unpause receive)
172
*/
173
void
174
ar9300_start_pcu_receive(struct ath_hal *ah, HAL_BOOL is_scanning)
175
{
176
ar9300_enable_mib_counters(ah);
177
ar9300_ani_reset(ah, is_scanning);
178
/* Clear RX_DIS and RX_ABORT after enabling phy errors in ani_reset */
179
OS_REG_CLR_BIT(ah, AR_DIAG_SW, (AR_DIAG_RX_DIS | AR_DIAG_RX_ABORT));
180
}
181
182
/*
183
* Stop Transmit at the PCU engine (pause receive)
184
*/
185
void
186
ar9300_stop_pcu_receive(struct ath_hal *ah)
187
{
188
OS_REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_RX_DIS);
189
ar9300_disable_mib_counters(ah);
190
}
191
192
/*
193
* Set multicast filter 0 (lower 32-bits)
194
* filter 1 (upper 32-bits)
195
*/
196
void
197
ar9300_set_multicast_filter(
198
struct ath_hal *ah,
199
u_int32_t filter0,
200
u_int32_t filter1)
201
{
202
OS_REG_WRITE(ah, AR_MCAST_FIL0, filter0);
203
OS_REG_WRITE(ah, AR_MCAST_FIL1, filter1);
204
}
205
206
/*
207
* Get the receive filter.
208
*/
209
u_int32_t
210
ar9300_get_rx_filter(struct ath_hal *ah)
211
{
212
u_int32_t bits = OS_REG_READ(ah, AR_RX_FILTER);
213
u_int32_t phybits = OS_REG_READ(ah, AR_PHY_ERR);
214
if (phybits & AR_PHY_ERR_RADAR) {
215
bits |= HAL_RX_FILTER_PHYRADAR;
216
}
217
if (phybits & (AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING)) {
218
bits |= HAL_RX_FILTER_PHYERR;
219
}
220
return bits;
221
}
222
223
/*
224
* Set the receive filter.
225
*/
226
void
227
ar9300_set_rx_filter(struct ath_hal *ah, u_int32_t bits)
228
{
229
u_int32_t phybits;
230
231
if (AR_SREV_SCORPION(ah) || AR_SREV_HONEYBEE(ah)) {
232
/* Enable Rx for 4 address frames */
233
bits |= AR_RX_4ADDRESS;
234
}
235
if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
236
/* HW fix for rx hang and corruption. */
237
bits |= AR_RX_CONTROL_WRAPPER;
238
}
239
OS_REG_WRITE(ah, AR_RX_FILTER,
240
bits | AR_RX_UNCOM_BA_BAR | AR_RX_COMPR_BAR);
241
phybits = 0;
242
if (bits & HAL_RX_FILTER_PHYRADAR) {
243
phybits |= AR_PHY_ERR_RADAR;
244
}
245
if (bits & HAL_RX_FILTER_PHYERR) {
246
phybits |= AR_PHY_ERR_OFDM_TIMING | AR_PHY_ERR_CCK_TIMING;
247
}
248
OS_REG_WRITE(ah, AR_PHY_ERR, phybits);
249
if (phybits) {
250
OS_REG_WRITE(ah, AR_RXCFG,
251
OS_REG_READ(ah, AR_RXCFG) | AR_RXCFG_ZLFDMA);
252
} else {
253
OS_REG_WRITE(ah, AR_RXCFG,
254
OS_REG_READ(ah, AR_RXCFG) &~ AR_RXCFG_ZLFDMA);
255
}
256
}
257
258
/*
259
* Select to pass PLCP headr or EVM data.
260
*/
261
HAL_BOOL
262
ar9300_set_rx_sel_evm(struct ath_hal *ah, HAL_BOOL sel_evm, HAL_BOOL just_query)
263
{
264
struct ath_hal_9300 *ahp = AH9300(ah);
265
HAL_BOOL old_value = ahp->ah_get_plcp_hdr == 0;
266
267
if (just_query) {
268
return old_value;
269
}
270
if (sel_evm) {
271
OS_REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM);
272
} else {
273
OS_REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_SEL_EVM);
274
}
275
276
ahp->ah_get_plcp_hdr = !sel_evm;
277
278
return old_value;
279
}
280
281
void ar9300_promisc_mode(struct ath_hal *ah, HAL_BOOL enable)
282
{
283
u_int32_t reg_val = 0;
284
reg_val = OS_REG_READ(ah, AR_RX_FILTER);
285
if (enable){
286
reg_val |= AR_RX_PROM;
287
} else{ /*Disable promisc mode */
288
reg_val &= ~AR_RX_PROM;
289
}
290
OS_REG_WRITE(ah, AR_RX_FILTER, reg_val);
291
}
292
293
void
294
ar9300_read_pktlog_reg(
295
struct ath_hal *ah,
296
u_int32_t *rxfilter_val,
297
u_int32_t *rxcfg_val,
298
u_int32_t *phy_err_mask_val,
299
u_int32_t *mac_pcu_phy_err_regval)
300
{
301
*rxfilter_val = OS_REG_READ(ah, AR_RX_FILTER);
302
*rxcfg_val = OS_REG_READ(ah, AR_RXCFG);
303
*phy_err_mask_val = OS_REG_READ(ah, AR_PHY_ERR);
304
*mac_pcu_phy_err_regval = OS_REG_READ(ah, 0x8338);
305
HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
306
"%s[%d] rxfilter_val 0x%08x , rxcfg_val 0x%08x, "
307
"phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n",
308
__func__, __LINE__,
309
*rxfilter_val, *rxcfg_val, *phy_err_mask_val, *mac_pcu_phy_err_regval);
310
}
311
312
void
313
ar9300_write_pktlog_reg(
314
struct ath_hal *ah,
315
HAL_BOOL enable,
316
u_int32_t rxfilter_val,
317
u_int32_t rxcfg_val,
318
u_int32_t phy_err_mask_val,
319
u_int32_t mac_pcu_phy_err_reg_val)
320
{
321
if (AR_SREV_JUPITER(ah) || AR_SREV_APHRODITE(ah)) {
322
/* HW fix for rx hang and corruption. */
323
rxfilter_val |= AR_RX_CONTROL_WRAPPER;
324
}
325
if (enable) { /* Enable pktlog phyerr setting */
326
OS_REG_WRITE(ah, AR_RX_FILTER, 0xffff | AR_RX_COMPR_BAR | rxfilter_val);
327
OS_REG_WRITE(ah, AR_PHY_ERR, 0xFFFFFFFF);
328
OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val | AR_RXCFG_ZLFDMA);
329
OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val | 0xFF);
330
} else { /* Disable phyerr and Restore regs */
331
OS_REG_WRITE(ah, AR_RX_FILTER, rxfilter_val);
332
OS_REG_WRITE(ah, AR_PHY_ERR, phy_err_mask_val);
333
OS_REG_WRITE(ah, AR_RXCFG, rxcfg_val);
334
OS_REG_WRITE(ah, AR_PHY_ERR_MASK_REG, mac_pcu_phy_err_reg_val);
335
}
336
HALDEBUG(ah, HAL_DEBUG_UNMASKABLE,
337
"%s[%d] ena %d rxfilter_val 0x%08x , rxcfg_val 0x%08x, "
338
"phy_err_mask_val 0x%08x mac_pcu_phy_err_regval 0x%08x\n",
339
__func__, __LINE__,
340
enable, rxfilter_val, rxcfg_val,
341
phy_err_mask_val, mac_pcu_phy_err_reg_val);
342
}
343
344