]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/rtwn/rtl8812a/r12a_rx.c
Merge OpenSSL 1.1.1g.
[FreeBSD/FreeBSD.git] / sys / dev / rtwn / rtl8812a / r12a_rx.c
1 /*-
2  * Copyright (c) 2016 Andriy Voskoboinyk <avos@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <sys/cdefs.h>
28 __FBSDID("$FreeBSD$");
29
30 #include "opt_wlan.h"
31
32 #include <sys/param.h>
33 #include <sys/lock.h>
34 #include <sys/mutex.h>
35 #include <sys/mbuf.h>
36 #include <sys/kernel.h>
37 #include <sys/socket.h>
38 #include <sys/systm.h>
39 #include <sys/malloc.h>
40 #include <sys/queue.h>
41 #include <sys/taskqueue.h>
42 #include <sys/bus.h>
43 #include <sys/endian.h>
44 #include <sys/linker.h>
45
46 #include <net/if.h>
47 #include <net/ethernet.h>
48 #include <net/if_media.h>
49
50 #include <net80211/ieee80211_var.h>
51 #include <net80211/ieee80211_radiotap.h>
52 #include <net80211/ieee80211_ratectl.h>
53
54 #include <dev/rtwn/if_rtwnreg.h>
55 #include <dev/rtwn/if_rtwnvar.h>
56
57 #include <dev/rtwn/if_rtwn_debug.h>
58 #include <dev/rtwn/if_rtwn_ridx.h>
59
60 #include <dev/rtwn/rtl8812a/r12a.h>
61 #include <dev/rtwn/rtl8812a/r12a_var.h>
62 #include <dev/rtwn/rtl8812a/r12a_fw_cmd.h>
63 #include <dev/rtwn/rtl8812a/r12a_rx_desc.h>
64
65
66 #ifndef RTWN_WITHOUT_UCODE
67 void
68 r12a_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len)
69 {
70 #if __FreeBSD_version >= 1200012
71         struct ieee80211_ratectl_tx_status txs;
72 #endif
73         struct r12a_c2h_tx_rpt *rpt;
74         struct ieee80211_node *ni;
75         int ntries;
76
77         /* Skip Rx descriptor / report id / sequence fields. */
78         buf += sizeof(struct r92c_rx_stat) + 2;
79         len -= sizeof(struct r92c_rx_stat) + 2;
80
81         rpt = (struct r12a_c2h_tx_rpt *)buf;
82         if (len != sizeof(*rpt)) {
83                 device_printf(sc->sc_dev,
84                     "%s: wrong report size (%d, must be %zu)\n",
85                     __func__, len, sizeof(*rpt));
86                 return;
87         }
88
89         RTWN_DPRINTF(sc, RTWN_DEBUG_INTR,
90             "%s: ccx report dump: 0: %02X, id: %02X, 2: %02X, queue time: "
91             "low %02X, high %02X, final ridx: %02X, rsvd: %04X\n",
92             __func__, rpt->txrptb0, rpt->macid, rpt->txrptb2,
93             rpt->queue_time_low, rpt->queue_time_high, rpt->final_rate,
94             rpt->reserved);
95
96         if (rpt->macid > sc->macid_limit) {
97                 device_printf(sc->sc_dev,
98                     "macid %u is too big; increase MACID_MAX limit\n",
99                     rpt->macid);
100                 return;
101         }
102
103         ntries = MS(rpt->txrptb2, R12A_TXRPTB2_RETRY_CNT);
104
105         ni = sc->node_list[rpt->macid];
106         if (ni != NULL) {
107                 RTWN_DPRINTF(sc, RTWN_DEBUG_INTR, "%s: frame for macid %u was"
108                     "%s sent (%d retries)\n", __func__, rpt->macid,
109                     (rpt->txrptb0 & (R12A_TXRPTB0_RETRY_OVER |
110                     R12A_TXRPTB0_LIFE_EXPIRE)) ? " not" : "", ntries);
111
112 #if __FreeBSD_version >= 1200012
113                 txs.flags = IEEE80211_RATECTL_STATUS_LONG_RETRY |
114                             IEEE80211_RATECTL_STATUS_FINAL_RATE;
115                 txs.long_retries = ntries;
116                 if (rpt->final_rate > RTWN_RIDX_OFDM54) {       /* MCS */
117                         txs.final_rate =
118                             rpt->final_rate - RTWN_RIDX_HT_MCS_SHIFT;
119                         txs.final_rate |= IEEE80211_RATE_MCS;
120                 } else
121                         txs.final_rate = ridx2rate[rpt->final_rate];
122                 if (rpt->txrptb0 & R12A_TXRPTB0_RETRY_OVER)
123                         txs.status = IEEE80211_RATECTL_TX_FAIL_LONG;
124                 else if (rpt->txrptb0 & R12A_TXRPTB0_LIFE_EXPIRE)
125                         txs.status = IEEE80211_RATECTL_TX_FAIL_EXPIRED;
126                 else
127                         txs.status = IEEE80211_RATECTL_TX_SUCCESS;
128                 ieee80211_ratectl_tx_complete(ni, &txs);
129 #else
130                 struct ieee80211vap *vap = ni->ni_vap;
131                 if (rpt->txrptb0 & R12A_TXRPTB0_RETRY_OVER) {
132                         ieee80211_ratectl_tx_complete(vap, ni,
133                             IEEE80211_RATECTL_TX_FAILURE, &ntries, NULL);
134                 } else {
135                         ieee80211_ratectl_tx_complete(vap, ni,
136                             IEEE80211_RATECTL_TX_SUCCESS, &ntries, NULL);
137                 }
138 #endif
139         } else {
140                 RTWN_DPRINTF(sc, RTWN_DEBUG_INTR,
141                     "%s: macid %u, ni is NULL\n", __func__, rpt->macid);
142         }
143 }
144
145 void
146 r12a_handle_c2h_report(struct rtwn_softc *sc, uint8_t *buf, int len)
147 {
148         struct r12a_softc *rs = sc->sc_priv;
149
150         /* Skip Rx descriptor. */
151         buf += sizeof(struct r92c_rx_stat);
152         len -= sizeof(struct r92c_rx_stat);
153
154         if (len < 2) {
155                 device_printf(sc->sc_dev, "C2H report too short (len %d)\n",
156                     len);
157                 return;
158         }
159         len -= 2;
160
161         switch (buf[0]) {       /* command id */
162         case R12A_C2H_TX_REPORT:
163                 /* NOTREACHED */
164                 KASSERT(0, ("use handle_tx_report() instead of %s\n",
165                     __func__));
166                 break;
167         case R12A_C2H_IQK_FINISHED:
168                 RTWN_DPRINTF(sc, RTWN_DEBUG_CALIB,
169                     "FW IQ calibration finished\n");
170                 rs->rs_flags &= ~R12A_IQK_RUNNING;
171                 break;
172         default:
173                 device_printf(sc->sc_dev,
174                     "%s: C2H report %u was not handled\n",
175                     __func__, buf[0]);
176         }
177 }
178 #else
179 void
180 r12a_ratectl_tx_complete(struct rtwn_softc *sc, uint8_t *buf, int len)
181 {
182         /* Should not happen. */
183         device_printf(sc->sc_dev, "%s: called\n", __func__);
184 }
185
186 void
187 r12a_handle_c2h_report(struct rtwn_softc *sc, uint8_t *buf, int len)
188 {
189         /* Should not happen. */
190         device_printf(sc->sc_dev, "%s: called\n", __func__);
191 }
192 #endif
193
194 int
195 r12a_check_frame_checksum(struct rtwn_softc *sc, struct mbuf *m)
196 {
197         struct r12a_softc *rs = sc->sc_priv;
198         struct r92c_rx_stat *stat;
199         uint32_t rxdw1;
200
201         stat = mtod(m, struct r92c_rx_stat *);
202         rxdw1 = le32toh(stat->rxdw1);
203         if (rxdw1 & R12A_RXDW1_CKSUM) {
204                 RTWN_DPRINTF(sc, RTWN_DEBUG_RECV,
205                     "%s: %s/%s checksum is %s\n", __func__,
206                     (rxdw1 & R12A_RXDW1_UDP) ? "UDP" : "TCP",
207                     (rxdw1 & R12A_RXDW1_IPV6) ? "IPv6" : "IP",
208                     (rxdw1 & R12A_RXDW1_CKSUM_ERR) ? "invalid" : "valid");
209
210                 if (rxdw1 & R12A_RXDW1_CKSUM_ERR)
211                         return (-1);
212
213                 if ((rxdw1 & R12A_RXDW1_IPV6) ?
214                     (rs->rs_flags & R12A_RXCKSUM6_EN) :
215                     (rs->rs_flags & R12A_RXCKSUM_EN)) {
216                         m->m_pkthdr.csum_flags = CSUM_IP_CHECKED |
217                             CSUM_IP_VALID | CSUM_DATA_VALID | CSUM_PSEUDO_HDR;
218                         m->m_pkthdr.csum_data = 0xffff;
219                 }
220         }
221
222         return (0);
223 }
224
225 uint8_t
226 r12a_rx_radiotap_flags(const void *buf)
227 {
228         const struct r92c_rx_stat *stat = buf;
229         uint8_t flags, rate;
230
231         if (!(stat->rxdw4 & htole32(R12A_RXDW4_SPLCP)))
232                 return (0);
233         rate = MS(le32toh(stat->rxdw3), R12A_RXDW3_RATE);
234         if (RTWN_RATE_IS_CCK(rate))
235                 flags = IEEE80211_RADIOTAP_F_SHORTPRE;
236         else
237                 flags = IEEE80211_RADIOTAP_F_SHORTGI;
238         return (flags);
239 }
240
241 void
242 r12a_get_rx_stats(struct rtwn_softc *sc, struct ieee80211_rx_stats *rxs,
243     const void *desc, const void *physt_ptr)
244 {
245         const struct r92c_rx_stat *stat = desc;
246         const struct r12a_rx_phystat *physt = physt_ptr;
247         uint32_t rxdw0, rxdw1, rxdw3, rxdw4;
248         uint8_t rate;
249
250         rxdw0 = le32toh(stat->rxdw0);
251         rxdw1 = le32toh(stat->rxdw1);
252         rxdw3 = le32toh(stat->rxdw3);
253         rxdw4 = le32toh(stat->rxdw4);
254         rate = MS(rxdw3, R12A_RXDW3_RATE);
255
256         /* TODO: STBC */
257         if (rxdw4 & R12A_RXDW4_LDPC)
258                 rxs->c_pktflags |= IEEE80211_RX_F_LDPC;
259         if (rxdw1 & R12A_RXDW1_AMPDU) {
260                 if (rxdw0 & R92C_RXDW0_PHYST)
261                         rxs->c_pktflags |= IEEE80211_RX_F_AMPDU;
262                 else
263                         rxs->c_pktflags |= IEEE80211_RX_F_AMPDU_MORE;
264         }
265
266         if ((rxdw4 & R12A_RXDW4_SPLCP) && rate >= RTWN_RIDX_HT_MCS(0))
267                 rxs->c_pktflags |= IEEE80211_RX_F_SHORTGI;
268
269         switch (MS(rxdw4, R12A_RXDW4_BW)) {
270         case R12A_RXDW4_BW20:
271                 rxs->c_width = IEEE80211_RX_FW_20MHZ;
272                 break;
273         case R12A_RXDW4_BW40:
274                 rxs->c_width = IEEE80211_RX_FW_40MHZ;
275                 break;
276         case R12A_RXDW4_BW80:
277                 rxs->c_width = IEEE80211_RX_FW_80MHZ;
278                 break;
279         default:
280                 break;
281         }
282
283         if (RTWN_RATE_IS_CCK(rate))
284                 rxs->c_phytype = IEEE80211_RX_FP_11B;
285         else {
286                 int is5ghz;
287
288                 /* XXX magic */
289                 /* XXX check with RTL8812AU */
290                 is5ghz = (physt->cfosho[2] != 0x01);
291
292                 if (rate < RTWN_RIDX_HT_MCS(0)) {
293                         if (is5ghz)
294                                 rxs->c_phytype = IEEE80211_RX_FP_11A;
295                         else
296                                 rxs->c_phytype = IEEE80211_RX_FP_11G;
297                 } else {
298                         if (is5ghz)
299                                 rxs->c_phytype = IEEE80211_RX_FP_11NA;
300                         else
301                                 rxs->c_phytype = IEEE80211_RX_FP_11NG;
302                 }
303         }
304
305         /* Map HW rate index to 802.11 rate. */
306         if (rate < RTWN_RIDX_HT_MCS(0)) {
307                 rxs->c_rate = ridx2rate[rate];
308                 if (RTWN_RATE_IS_CCK(rate))
309                         rxs->c_pktflags |= IEEE80211_RX_F_CCK;
310                 else
311                         rxs->c_pktflags |= IEEE80211_RX_F_OFDM;
312         } else {        /* MCS0~15. */
313                 /* TODO: VHT rates */
314                 rxs->c_rate =
315                     IEEE80211_RATE_MCS | (rate - RTWN_RIDX_HT_MCS_SHIFT);
316                 rxs->c_pktflags |= IEEE80211_RX_F_HT;
317         }
318
319         /*
320          * XXX always zero for RTL8821AU
321          * (vendor driver does not check this field)
322          */
323 #if 0
324         rxs->r_flags |= IEEE80211_R_IEEE | IEEE80211_R_FREQ;
325         rxs->c_ieee = MS(le16toh(physt->phyw1), R12A_PHYW1_CHAN);
326         rxs->c_freq = ieee80211_ieee2mhz(rxs->c_ieee,
327             (rxs->c_ieee < 36) ? IEEE80211_CHAN_2GHZ : IEEE80211_CHAN_5GHZ);
328 #endif
329 }