xref: /dflybsd-src/sys/contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c (revision a20e5e5100e71be018e157de86834f5dc77186c3)
1b7d5e03cSMatthew Dillon /*
2b7d5e03cSMatthew Dillon  * Copyright (c) 2013 Qualcomm Atheros, Inc.
3b7d5e03cSMatthew Dillon  *
4b7d5e03cSMatthew Dillon  * Permission to use, copy, modify, and/or distribute this software for any
5b7d5e03cSMatthew Dillon  * purpose with or without fee is hereby granted, provided that the above
6b7d5e03cSMatthew Dillon  * copyright notice and this permission notice appear in all copies.
7b7d5e03cSMatthew Dillon  *
8b7d5e03cSMatthew Dillon  * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
9b7d5e03cSMatthew Dillon  * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
10b7d5e03cSMatthew Dillon  * AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
11b7d5e03cSMatthew Dillon  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
12b7d5e03cSMatthew Dillon  * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
13b7d5e03cSMatthew Dillon  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
14b7d5e03cSMatthew Dillon  * PERFORMANCE OF THIS SOFTWARE.
15b7d5e03cSMatthew Dillon  */
16b7d5e03cSMatthew Dillon 
17b7d5e03cSMatthew Dillon #include "opt_ah.h"
18b7d5e03cSMatthew Dillon 
19b7d5e03cSMatthew Dillon #include "ah.h"
20b7d5e03cSMatthew Dillon #include "ah_desc.h"
21b7d5e03cSMatthew Dillon #include "ah_internal.h"
22b7d5e03cSMatthew Dillon 
23b7d5e03cSMatthew Dillon #include "ar9300/ar9300.h"
24b7d5e03cSMatthew Dillon #include "ar9300/ar9300reg.h"
25b7d5e03cSMatthew Dillon #include "ar9300/ar9300desc.h"
26b7d5e03cSMatthew Dillon 
27b7d5e03cSMatthew Dillon 
28b7d5e03cSMatthew Dillon /*
29b7d5e03cSMatthew Dillon  * Process an RX descriptor, and return the status to the caller.
30b7d5e03cSMatthew Dillon  * Copy some hardware specific items into the software portion
31b7d5e03cSMatthew Dillon  * of the descriptor.
32b7d5e03cSMatthew Dillon  *
33b7d5e03cSMatthew Dillon  * NB: the caller is responsible for validating the memory contents
34b7d5e03cSMatthew Dillon  *     of the descriptor (e.g. flushing any cached copy).
35b7d5e03cSMatthew Dillon  */
36b7d5e03cSMatthew Dillon HAL_STATUS
ar9300_proc_rx_desc_fast(struct ath_hal * ah,struct ath_desc * ds,u_int32_t pa,struct ath_desc * nds,struct ath_rx_status * rxs,void * buf_addr)37b7d5e03cSMatthew Dillon ar9300_proc_rx_desc_fast(struct ath_hal *ah, struct ath_desc *ds,
38b7d5e03cSMatthew Dillon     u_int32_t pa, struct ath_desc *nds, struct ath_rx_status *rxs,
39b7d5e03cSMatthew Dillon     void *buf_addr)
40b7d5e03cSMatthew Dillon {
41b7d5e03cSMatthew Dillon     struct ar9300_rxs *rxsp = AR9300RXS(buf_addr);
42b7d5e03cSMatthew Dillon 
43b7d5e03cSMatthew Dillon     /*
44b7d5e03cSMatthew Dillon     ath_hal_printf(ah,"CHH=RX: ds_info 0x%x  status1: 0x%x  status11: 0x%x\n",
45b7d5e03cSMatthew Dillon                         rxsp->ds_info,rxsp->status1,rxsp->status11);
46b7d5e03cSMatthew Dillon      */
47b7d5e03cSMatthew Dillon 
48b7d5e03cSMatthew Dillon     if ((rxsp->status11 & AR_rx_done) == 0) {
49b7d5e03cSMatthew Dillon         return HAL_EINPROGRESS;
50b7d5e03cSMatthew Dillon     }
51b7d5e03cSMatthew Dillon 
52b7d5e03cSMatthew Dillon     if (MS(rxsp->ds_info, AR_desc_id) != 0x168c) {
53b7d5e03cSMatthew Dillon #if __PKT_SERIOUS_ERRORS__
54b7d5e03cSMatthew Dillon        /*BUG: 63564-HT */
55b7d5e03cSMatthew Dillon         HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE, "%s: Rx Descriptor error 0x%x\n",
56b7d5e03cSMatthew Dillon                  __func__, rxsp->ds_info);
57b7d5e03cSMatthew Dillon #endif
58b7d5e03cSMatthew Dillon         return HAL_EINVAL;
59b7d5e03cSMatthew Dillon     }
60b7d5e03cSMatthew Dillon 
61b7d5e03cSMatthew Dillon     if ((rxsp->ds_info & (AR_tx_rx_desc | AR_ctrl_stat)) != 0) {
62b7d5e03cSMatthew Dillon #if __PKT_SERIOUS_ERRORS__
63b7d5e03cSMatthew Dillon         HALDEBUG(AH_NULL, HAL_DEBUG_UNMASKABLE,
64b7d5e03cSMatthew Dillon             "%s: Rx Descriptor wrong info 0x%x\n", __func__, rxsp->ds_info);
65b7d5e03cSMatthew Dillon #endif
66b7d5e03cSMatthew Dillon         return HAL_EINPROGRESS;
67b7d5e03cSMatthew Dillon     }
68b7d5e03cSMatthew Dillon 
69b7d5e03cSMatthew Dillon     rxs->rs_status = 0;
70b7d5e03cSMatthew Dillon     rxs->rs_flags =  0;
71*a20e5e51SMatthew Dillon     rxs->rs_phyerr = 0;
72b7d5e03cSMatthew Dillon 
73b7d5e03cSMatthew Dillon     rxs->rs_datalen = rxsp->status2 & AR_data_len;
74b7d5e03cSMatthew Dillon     rxs->rs_tstamp =  rxsp->status3;
75b7d5e03cSMatthew Dillon 
76b7d5e03cSMatthew Dillon     /* XXX what about key_cache_miss? */
77b7d5e03cSMatthew Dillon     rxs->rs_rssi = MS(rxsp->status5, AR_rx_rssi_combined);
78b7d5e03cSMatthew Dillon     rxs->rs_rssi_ctl[0] = MS(rxsp->status1, AR_rx_rssi_ant00);
79b7d5e03cSMatthew Dillon     rxs->rs_rssi_ctl[1] = MS(rxsp->status1, AR_rx_rssi_ant01);
80b7d5e03cSMatthew Dillon     rxs->rs_rssi_ctl[2] = MS(rxsp->status1, AR_rx_rssi_ant02);
81b7d5e03cSMatthew Dillon     rxs->rs_rssi_ext[0] = MS(rxsp->status5, AR_rx_rssi_ant10);
82b7d5e03cSMatthew Dillon     rxs->rs_rssi_ext[1] = MS(rxsp->status5, AR_rx_rssi_ant11);
83b7d5e03cSMatthew Dillon     rxs->rs_rssi_ext[2] = MS(rxsp->status5, AR_rx_rssi_ant12);
84b7d5e03cSMatthew Dillon     if (rxsp->status11 & AR_rx_key_idx_valid) {
85b7d5e03cSMatthew Dillon         rxs->rs_keyix = MS(rxsp->status11, AR_key_idx);
86b7d5e03cSMatthew Dillon     } else {
87b7d5e03cSMatthew Dillon         rxs->rs_keyix = HAL_RXKEYIX_INVALID;
88b7d5e03cSMatthew Dillon     }
89b7d5e03cSMatthew Dillon     /* NB: caller expected to do rate table mapping */
90b7d5e03cSMatthew Dillon     rxs->rs_rate = MS(rxsp->status1, AR_rx_rate);
91b7d5e03cSMatthew Dillon     rxs->rs_more = (rxsp->status2 & AR_rx_more) ? 1 : 0;
92b7d5e03cSMatthew Dillon 
93b7d5e03cSMatthew Dillon     rxs->rs_isaggr = (rxsp->status11 & AR_rx_aggr) ? 1 : 0;
94b7d5e03cSMatthew Dillon     rxs->rs_moreaggr = (rxsp->status11 & AR_rx_more_aggr) ? 1 : 0;
95b7d5e03cSMatthew Dillon     rxs->rs_antenna = (MS(rxsp->status4, AR_rx_antenna) & 0x7);
96b7d5e03cSMatthew Dillon     rxs->rs_flags = (rxsp->status11 & AR_apsd_trig) ? HAL_RX_IS_APSD : 0;
97b7d5e03cSMatthew Dillon     rxs->rs_flags  |= (rxsp->status4 & AR_gi) ? HAL_RX_GI : 0;
98b7d5e03cSMatthew Dillon     rxs->rs_flags  |= (rxsp->status4 & AR_2040) ? HAL_RX_2040 : 0;
99b7d5e03cSMatthew Dillon 
100b7d5e03cSMatthew Dillon     /* Copy EVM information */
101b7d5e03cSMatthew Dillon     rxs->rs_evm0 = rxsp->status6;
102b7d5e03cSMatthew Dillon     rxs->rs_evm1 = rxsp->status7;
103b7d5e03cSMatthew Dillon     rxs->rs_evm2 = rxsp->status8;
104b7d5e03cSMatthew Dillon     rxs->rs_evm3 = rxsp->status9;
105b7d5e03cSMatthew Dillon     rxs->rs_evm4 = (rxsp->status10 & 0xffff);
106b7d5e03cSMatthew Dillon 
107b7d5e03cSMatthew Dillon     if (rxsp->status11 & AR_pre_delim_crc_err) {
108b7d5e03cSMatthew Dillon         rxs->rs_flags |= HAL_RX_DELIM_CRC_PRE;
109b7d5e03cSMatthew Dillon     }
110b7d5e03cSMatthew Dillon     if (rxsp->status11 & AR_post_delim_crc_err) {
111b7d5e03cSMatthew Dillon         rxs->rs_flags |= HAL_RX_DELIM_CRC_POST;
112b7d5e03cSMatthew Dillon     }
113b7d5e03cSMatthew Dillon     if (rxsp->status11 & AR_decrypt_busy_err) {
114b7d5e03cSMatthew Dillon         rxs->rs_flags |= HAL_RX_DECRYPT_BUSY;
115b7d5e03cSMatthew Dillon     }
116b7d5e03cSMatthew Dillon     if (rxsp->status11 & AR_hi_rx_chain) {
117b7d5e03cSMatthew Dillon         rxs->rs_flags |= HAL_RX_HI_RX_CHAIN;
118b7d5e03cSMatthew Dillon     }
119b7d5e03cSMatthew Dillon     if (rxsp->status11 & AR_key_miss) {
120b7d5e03cSMatthew Dillon         rxs->rs_status |= HAL_RXERR_KEYMISS;
121b7d5e03cSMatthew Dillon     }
122b7d5e03cSMatthew Dillon 
123b7d5e03cSMatthew Dillon     if ((rxsp->status11 & AR_rx_frame_ok) == 0) {
124b7d5e03cSMatthew Dillon         /*
125b7d5e03cSMatthew Dillon          * These four bits should not be set together.  The
126b7d5e03cSMatthew Dillon          * 9300 spec states a Michael error can only occur if
127b7d5e03cSMatthew Dillon          * decrypt_crc_err not set (and TKIP is used).  Experience
128b7d5e03cSMatthew Dillon          * indicates however that you can also get Michael errors
129b7d5e03cSMatthew Dillon          * when a CRC error is detected, but these are specious.
130b7d5e03cSMatthew Dillon          * Consequently we filter them out here so we don't
131b7d5e03cSMatthew Dillon          * confuse and/or complicate drivers.
132b7d5e03cSMatthew Dillon          */
133*a20e5e51SMatthew Dillon 
134b7d5e03cSMatthew Dillon         if (rxsp->status11 & AR_crc_err) {
135b7d5e03cSMatthew Dillon             rxs->rs_status |= HAL_RXERR_CRC;
136b7d5e03cSMatthew Dillon             /*
137*a20e5e51SMatthew Dillon 			 * ignore CRC flag for phy reports
138b7d5e03cSMatthew Dillon 			 */
139b7d5e03cSMatthew Dillon             if (rxsp->status11 & AR_phyerr) {
140b7d5e03cSMatthew Dillon                 u_int phyerr = MS(rxsp->status11, AR_phy_err_code);
141b7d5e03cSMatthew Dillon                 rxs->rs_status |= HAL_RXERR_PHY;
142b7d5e03cSMatthew Dillon                 rxs->rs_phyerr = phyerr;
143b7d5e03cSMatthew Dillon             }
144b7d5e03cSMatthew Dillon         } else if (rxsp->status11 & AR_phyerr) {
145b7d5e03cSMatthew Dillon             u_int phyerr;
146b7d5e03cSMatthew Dillon 
147b7d5e03cSMatthew Dillon             /*
148b7d5e03cSMatthew Dillon              * Packets with OFDM_RESTART on post delimiter are CRC OK and
149b7d5e03cSMatthew Dillon              * usable and MAC ACKs them.
150b7d5e03cSMatthew Dillon              * To avoid packet from being lost, we remove the PHY Err flag
151b7d5e03cSMatthew Dillon              * so that lmac layer does not drop them.
152b7d5e03cSMatthew Dillon              * (EV 70071)
153b7d5e03cSMatthew Dillon              */
154b7d5e03cSMatthew Dillon             phyerr = MS(rxsp->status11, AR_phy_err_code);
155b7d5e03cSMatthew Dillon             if ((phyerr == HAL_PHYERR_OFDM_RESTART) &&
156b7d5e03cSMatthew Dillon                     (rxsp->status11 & AR_post_delim_crc_err)) {
157b7d5e03cSMatthew Dillon                 rxs->rs_phyerr = 0;
158b7d5e03cSMatthew Dillon             } else {
159b7d5e03cSMatthew Dillon                 rxs->rs_status |= HAL_RXERR_PHY;
160b7d5e03cSMatthew Dillon                 rxs->rs_phyerr = phyerr;
161b7d5e03cSMatthew Dillon             }
162b7d5e03cSMatthew Dillon         } else if (rxsp->status11 & AR_decrypt_crc_err) {
163b7d5e03cSMatthew Dillon             rxs->rs_status |= HAL_RXERR_DECRYPT;
164b7d5e03cSMatthew Dillon         } else if (rxsp->status11 & AR_michael_err) {
165b7d5e03cSMatthew Dillon             rxs->rs_status |= HAL_RXERR_MIC;
166b7d5e03cSMatthew Dillon         }
167b7d5e03cSMatthew Dillon     }
168*a20e5e51SMatthew Dillon #if 0
169*a20e5e51SMatthew Dillon     rxs->rs_channel = AH_PRIVATE(ah)->ah_curchan->channel;
170*a20e5e51SMatthew Dillon #endif
171b7d5e03cSMatthew Dillon     return HAL_OK;
172b7d5e03cSMatthew Dillon }
173b7d5e03cSMatthew Dillon 
174b7d5e03cSMatthew Dillon HAL_STATUS
ar9300_proc_rx_desc(struct ath_hal * ah,struct ath_desc * ds,u_int32_t pa,struct ath_desc * nds,u_int64_t tsf,struct ath_rx_status * rxs)175b7d5e03cSMatthew Dillon ar9300_proc_rx_desc(struct ath_hal *ah, struct ath_desc *ds,
176b7d5e03cSMatthew Dillon     u_int32_t pa, struct ath_desc *nds, u_int64_t tsf,
177b7d5e03cSMatthew Dillon     struct ath_rx_status *rxs)
178b7d5e03cSMatthew Dillon {
179b7d5e03cSMatthew Dillon     return HAL_ENOTSUPP;
180b7d5e03cSMatthew Dillon }
181b7d5e03cSMatthew Dillon 
182b7d5e03cSMatthew Dillon /*
183b7d5e03cSMatthew Dillon  * rx path in ISR is different for ar9300 from ar5416, and
184b7d5e03cSMatthew Dillon  * ath_rx_proc_descfast will not be called if edmasupport is true.
185b7d5e03cSMatthew Dillon  * So this function ath_hal_get_rxkeyidx will not be
186b7d5e03cSMatthew Dillon  * called for ar9300.
187b7d5e03cSMatthew Dillon  * This function in ar9300's HAL is just a stub one because we need
188b7d5e03cSMatthew Dillon  * to link something to the callback interface of the HAL module.
189b7d5e03cSMatthew Dillon  */
190b7d5e03cSMatthew Dillon HAL_STATUS
ar9300_get_rx_key_idx(struct ath_hal * ah,struct ath_desc * ds,u_int8_t * keyix,u_int8_t * status)191b7d5e03cSMatthew Dillon ar9300_get_rx_key_idx(struct ath_hal *ah, struct ath_desc *ds, u_int8_t *keyix,
192b7d5e03cSMatthew Dillon     u_int8_t *status)
193b7d5e03cSMatthew Dillon {
194b7d5e03cSMatthew Dillon     *status = 0;
195b7d5e03cSMatthew Dillon     *keyix = HAL_RXKEYIX_INVALID;
196b7d5e03cSMatthew Dillon     return HAL_ENOTSUPP;
197b7d5e03cSMatthew Dillon }
198