xref: /freebsd/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv.c (revision b626f5a73a48f44a31a200291b141e1da408a2ff)
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
ar9300_get_rx_dp(struct ath_hal * ath,HAL_RX_QUEUE qtype)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
ar9300_set_rx_dp(struct ath_hal * ah,u_int32_t rxdp,HAL_RX_QUEUE qtype)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
ar9300_enable_receive(struct ath_hal * ah)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
ar9300_set_rx_abort(struct ath_hal * ah,HAL_BOOL set)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
ar9300_stop_dma_receive(struct ath_hal * ah,u_int timeout)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
ar9300_start_pcu_receive(struct ath_hal * ah,HAL_BOOL is_scanning)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
ar9300_stop_pcu_receive(struct ath_hal * ah)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
ar9300_set_multicast_filter(struct ath_hal * ah,u_int32_t filter0,u_int32_t filter1)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
ar9300_get_rx_filter(struct ath_hal * ah)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
ar9300_set_rx_filter(struct ath_hal * ah,u_int32_t bits)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
ar9300_set_rx_sel_evm(struct ath_hal * ah,HAL_BOOL sel_evm,HAL_BOOL just_query)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 
ar9300_promisc_mode(struct ath_hal * ah,HAL_BOOL enable)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
ar9300_read_pktlog_reg(struct ath_hal * ah,u_int32_t * rxfilter_val,u_int32_t * rxcfg_val,u_int32_t * phy_err_mask_val,u_int32_t * mac_pcu_phy_err_regval)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
ar9300_write_pktlog_reg(struct ath_hal * ah,HAL_BOOL enable,u_int32_t rxfilter_val,u_int32_t rxcfg_val,u_int32_t phy_err_mask_val,u_int32_t mac_pcu_phy_err_reg_val)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