| @@ -1,39 +1,39 @@ | | | @@ -1,39 +1,39 @@ |
1 | /* $NetBSD: rt2860.c,v 1.14 2016/06/16 15:51:13 riastradh Exp $ */ | | 1 | /* $NetBSD: rt2860.c,v 1.15 2016/06/17 15:38:54 christos Exp $ */ |
2 | /* $OpenBSD: rt2860.c,v 1.90 2016/04/13 10:49:26 mpi Exp $ */ | | 2 | /* $OpenBSD: rt2860.c,v 1.90 2016/04/13 10:49:26 mpi Exp $ */ |
3 | | | 3 | |
4 | /*- | | 4 | /*- |
5 | * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr> | | 5 | * Copyright (c) 2007-2010 Damien Bergamini <damien.bergamini@free.fr> |
6 | * | | 6 | * |
7 | * Permission to use, copy, modify, and distribute this software for any | | 7 | * Permission to use, copy, modify, and distribute this software for any |
8 | * purpose with or without fee is hereby granted, provided that the above | | 8 | * purpose with or without fee is hereby granted, provided that the above |
9 | * copyright notice and this permission notice appear in all copies. | | 9 | * copyright notice and this permission notice appear in all copies. |
10 | * | | 10 | * |
11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | | 11 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | | 12 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | | 13 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | | 14 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | | 15 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | | 16 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | | 17 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
18 | */ | | 18 | */ |
19 | | | 19 | |
20 | /*- | | 20 | /*- |
21 | * Ralink Technology RT2860/RT3090/RT3390/RT3562 chipset driver | | 21 | * Ralink Technology RT2860/RT3090/RT3390/RT3562 chipset driver |
22 | * http://www.ralinktech.com/ | | 22 | * http://www.ralinktech.com/ |
23 | */ | | 23 | */ |
24 | | | 24 | |
25 | #include <sys/cdefs.h> | | 25 | #include <sys/cdefs.h> |
26 | __KERNEL_RCSID(0, "$NetBSD: rt2860.c,v 1.14 2016/06/16 15:51:13 riastradh Exp $"); | | 26 | __KERNEL_RCSID(0, "$NetBSD: rt2860.c,v 1.15 2016/06/17 15:38:54 christos Exp $"); |
27 | | | 27 | |
28 | #include <sys/param.h> | | 28 | #include <sys/param.h> |
29 | #include <sys/sockio.h> | | 29 | #include <sys/sockio.h> |
30 | #include <sys/sysctl.h> | | 30 | #include <sys/sysctl.h> |
31 | #include <sys/mbuf.h> | | 31 | #include <sys/mbuf.h> |
32 | #include <sys/kernel.h> | | 32 | #include <sys/kernel.h> |
33 | #include <sys/socket.h> | | 33 | #include <sys/socket.h> |
34 | #include <sys/systm.h> | | 34 | #include <sys/systm.h> |
35 | #include <sys/malloc.h> | | 35 | #include <sys/malloc.h> |
36 | #include <sys/queue.h> | | 36 | #include <sys/queue.h> |
37 | #include <sys/callout.h> | | 37 | #include <sys/callout.h> |
38 | #include <sys/module.h> | | 38 | #include <sys/module.h> |
39 | #include <sys/conf.h> | | 39 | #include <sys/conf.h> |
| @@ -127,30 +127,32 @@ static void rt2860_set_chan(struct rt286 | | | @@ -127,30 +127,32 @@ static void rt2860_set_chan(struct rt286 |
127 | static void rt3090_set_chan(struct rt2860_softc *, u_int); | | 127 | static void rt3090_set_chan(struct rt2860_softc *, u_int); |
128 | static int rt3090_rf_init(struct rt2860_softc *); | | 128 | static int rt3090_rf_init(struct rt2860_softc *); |
129 | static void rt3090_rf_wakeup(struct rt2860_softc *); | | 129 | static void rt3090_rf_wakeup(struct rt2860_softc *); |
130 | static int rt3090_filter_calib(struct rt2860_softc *, uint8_t, uint8_t, | | 130 | static int rt3090_filter_calib(struct rt2860_softc *, uint8_t, uint8_t, |
131 | uint8_t *); | | 131 | uint8_t *); |
132 | static void rt3090_rf_setup(struct rt2860_softc *); | | 132 | static void rt3090_rf_setup(struct rt2860_softc *); |
133 | static void rt2860_set_leds(struct rt2860_softc *, uint16_t); | | 133 | static void rt2860_set_leds(struct rt2860_softc *, uint16_t); |
134 | static void rt2860_set_gp_timer(struct rt2860_softc *, int); | | 134 | static void rt2860_set_gp_timer(struct rt2860_softc *, int); |
135 | static void rt2860_set_bssid(struct rt2860_softc *, const uint8_t *); | | 135 | static void rt2860_set_bssid(struct rt2860_softc *, const uint8_t *); |
136 | static void rt2860_set_macaddr(struct rt2860_softc *, const uint8_t *); | | 136 | static void rt2860_set_macaddr(struct rt2860_softc *, const uint8_t *); |
137 | static void rt2860_updateslot(struct ifnet *); | | 137 | static void rt2860_updateslot(struct ifnet *); |
138 | static void rt2860_updateprot(struct ieee80211com *); | | 138 | static void rt2860_updateprot(struct ieee80211com *); |
139 | static int rt2860_updateedca(struct ieee80211com *); | | 139 | static int rt2860_updateedca(struct ieee80211com *); |
| | | 140 | #ifdef HW_CRYPTO |
140 | static int rt2860_set_key(struct ieee80211com *, | | 141 | static int rt2860_set_key(struct ieee80211com *, |
141 | const struct ieee80211_key *, const uint8_t *); | | 142 | const struct ieee80211_key *, const uint8_t *); |
142 | static int rt2860_delete_key(struct ieee80211com *, | | 143 | static int rt2860_delete_key(struct ieee80211com *, |
143 | const struct ieee80211_key *); | | 144 | const struct ieee80211_key *); |
| | | 145 | #endif |
144 | static int8_t rt2860_rssi2dbm(struct rt2860_softc *, uint8_t, uint8_t); | | 146 | static int8_t rt2860_rssi2dbm(struct rt2860_softc *, uint8_t, uint8_t); |
145 | static const char * rt2860_get_rf(uint8_t); | | 147 | static const char * rt2860_get_rf(uint8_t); |
146 | static int rt2860_read_eeprom(struct rt2860_softc *); | | 148 | static int rt2860_read_eeprom(struct rt2860_softc *); |
147 | static int rt2860_bbp_init(struct rt2860_softc *); | | 149 | static int rt2860_bbp_init(struct rt2860_softc *); |
148 | static int rt2860_txrx_enable(struct rt2860_softc *); | | 150 | static int rt2860_txrx_enable(struct rt2860_softc *); |
149 | static int rt2860_init(struct ifnet *); | | 151 | static int rt2860_init(struct ifnet *); |
150 | static void rt2860_stop(struct ifnet *, int); | | 152 | static void rt2860_stop(struct ifnet *, int); |
151 | static int rt2860_load_microcode(struct rt2860_softc *); | | 153 | static int rt2860_load_microcode(struct rt2860_softc *); |
152 | #if 0 | | 154 | #if 0 |
153 | static void rt2860_calib(struct rt2860_softc *); | | 155 | static void rt2860_calib(struct rt2860_softc *); |
154 | #endif | | 156 | #endif |
155 | static void rt3090_set_rx_antenna(struct rt2860_softc *, int); | | 157 | static void rt3090_set_rx_antenna(struct rt2860_softc *, int); |
156 | static void rt2860_switch_chan(struct rt2860_softc *, | | 158 | static void rt2860_switch_chan(struct rt2860_softc *, |
| @@ -368,28 +370,30 @@ rt2860_attachhook(device_t self) | | | @@ -368,28 +370,30 @@ rt2860_attachhook(device_t self) |
368 | IFQ_SET_READY(&ifp->if_snd); | | 370 | IFQ_SET_READY(&ifp->if_snd); |
369 | memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); | | 371 | memcpy(ifp->if_xname, device_xname(sc->sc_dev), IFNAMSIZ); |
370 | | | 372 | |
371 | if_attach(ifp); | | 373 | if_attach(ifp); |
372 | ieee80211_ifattach(ic); | | 374 | ieee80211_ifattach(ic); |
373 | ic->ic_node_alloc = rt2860_node_alloc; | | 375 | ic->ic_node_alloc = rt2860_node_alloc; |
374 | ic->ic_newassoc = rt2860_newassoc; | | 376 | ic->ic_newassoc = rt2860_newassoc; |
375 | #ifdef notyet | | 377 | #ifdef notyet |
376 | ic->ic_ampdu_rx_start = rt2860_ampdu_rx_start; | | 378 | ic->ic_ampdu_rx_start = rt2860_ampdu_rx_start; |
377 | ic->ic_ampdu_rx_stop = rt2860_ampdu_rx_stop; | | 379 | ic->ic_ampdu_rx_stop = rt2860_ampdu_rx_stop; |
378 | #endif | | 380 | #endif |
379 | ic->ic_updateslot = rt2860_updateslot; | | 381 | ic->ic_updateslot = rt2860_updateslot; |
380 | ic->ic_wme.wme_update = rt2860_updateedca; | | 382 | ic->ic_wme.wme_update = rt2860_updateedca; |
| | | 383 | #ifdef HW_CRYPTO |
381 | ic->ic_crypto.cs_key_set = rt2860_set_key; | | 384 | ic->ic_crypto.cs_key_set = rt2860_set_key; |
382 | ic->ic_crypto.cs_key_delete = rt2860_delete_key; | | 385 | ic->ic_crypto.cs_key_delete = rt2860_delete_key; |
| | | 386 | #endif |
383 | /* override state transition machine */ | | 387 | /* override state transition machine */ |
384 | sc->sc_newstate = ic->ic_newstate; | | 388 | sc->sc_newstate = ic->ic_newstate; |
385 | ic->ic_newstate = rt2860_newstate; | | 389 | ic->ic_newstate = rt2860_newstate; |
386 | ieee80211_media_init(ic, rt2860_media_change, ieee80211_media_status); | | 390 | ieee80211_media_init(ic, rt2860_media_change, ieee80211_media_status); |
387 | | | 391 | |
388 | bpf_attach2(ifp, DLT_IEEE802_11_RADIO, | | 392 | bpf_attach2(ifp, DLT_IEEE802_11_RADIO, |
389 | sizeof (struct ieee80211_frame) + 64, &sc->sc_drvbpf); | | 393 | sizeof (struct ieee80211_frame) + 64, &sc->sc_drvbpf); |
390 | | | 394 | |
391 | sc->sc_rxtap_len = sizeof sc->sc_rxtapu; | | 395 | sc->sc_rxtap_len = sizeof sc->sc_rxtapu; |
392 | sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); | | 396 | sc->sc_rxtap.wr_ihdr.it_len = htole16(sc->sc_rxtap_len); |
393 | sc->sc_rxtap.wr_ihdr.it_present = htole32(RT2860_RX_RADIOTAP_PRESENT); | | 397 | sc->sc_rxtap.wr_ihdr.it_present = htole32(RT2860_RX_RADIOTAP_PRESENT); |
394 | | | 398 | |
395 | sc->sc_txtap_len = sizeof sc->sc_txtapu; | | 399 | sc->sc_txtap_len = sizeof sc->sc_txtapu; |
| @@ -1279,26 +1283,35 @@ rt2860_rx_intr(struct rt2860_softc *sc) | | | @@ -1279,26 +1283,35 @@ rt2860_rx_intr(struct rt2860_softc *sc) |
1279 | sizeof (struct rt2860_rxd), BUS_DMASYNC_POSTREAD); | | 1283 | sizeof (struct rt2860_rxd), BUS_DMASYNC_POSTREAD); |
1280 | | | 1284 | |
1281 | if (__predict_false(!(rxd->sdl0 & htole16(RT2860_RX_DDONE)))) { | | 1285 | if (__predict_false(!(rxd->sdl0 & htole16(RT2860_RX_DDONE)))) { |
1282 | DPRINTF(("RXD DDONE bit not set!\n")); | | 1286 | DPRINTF(("RXD DDONE bit not set!\n")); |
1283 | break; /* should not happen */ | | 1287 | break; /* should not happen */ |
1284 | } | | 1288 | } |
1285 | | | 1289 | |
1286 | if (__predict_false(rxd->flags & | | 1290 | if (__predict_false(rxd->flags & |
1287 | htole32(RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { | | 1291 | htole32(RT2860_RX_CRCERR | RT2860_RX_ICVERR))) { |
1288 | ifp->if_ierrors++; | | 1292 | ifp->if_ierrors++; |
1289 | goto skip; | | 1293 | goto skip; |
1290 | } | | 1294 | } |
1291 | | | 1295 | |
| | | 1296 | #ifdef HW_CRYPTO |
| | | 1297 | if (__predict_false(rxd->flags & htole32(RT2860_RX_MICERR))) { |
| | | 1298 | /* report MIC failures to net80211 for TKIP */ |
| | | 1299 | ieee80211_notify_michael_failure(ic, wh, 0/* XXX */); |
| | | 1300 | ifp->if_ierrors++; |
| | | 1301 | goto skip; |
| | | 1302 | } |
| | | 1303 | #endif |
| | | 1304 | |
1292 | MGETHDR(m1, M_DONTWAIT, MT_DATA); | | 1305 | MGETHDR(m1, M_DONTWAIT, MT_DATA); |
1293 | if (__predict_false(m1 == NULL)) { | | 1306 | if (__predict_false(m1 == NULL)) { |
1294 | ifp->if_ierrors++; | | 1307 | ifp->if_ierrors++; |
1295 | goto skip; | | 1308 | goto skip; |
1296 | } | | 1309 | } |
1297 | MCLGET(m1, M_DONTWAIT); | | 1310 | MCLGET(m1, M_DONTWAIT); |
1298 | if (__predict_false((m1->m_flags & M_EXT) == 0)) { | | 1311 | if (__predict_false((m1->m_flags & M_EXT) == 0)) { |
1299 | m_freem(m1); | | 1312 | m_freem(m1); |
1300 | ifp->if_ierrors++; | | 1313 | ifp->if_ierrors++; |
1301 | goto skip; | | 1314 | goto skip; |
1302 | } | | 1315 | } |
1303 | | | 1316 | |
1304 | bus_dmamap_sync(sc->sc_dmat, data->map, 0, | | 1317 | bus_dmamap_sync(sc->sc_dmat, data->map, 0, |
| @@ -1331,46 +1344,41 @@ rt2860_rx_intr(struct rt2860_softc *sc) | | | @@ -1331,46 +1344,41 @@ rt2860_rx_intr(struct rt2860_softc *sc) |
1331 | */ | | 1344 | */ |
1332 | m = data->m; | | 1345 | m = data->m; |
1333 | data->m = m1; | | 1346 | data->m = m1; |
1334 | rxd->sdp0 = htole32(data->map->dm_segs[0].ds_addr); | | 1347 | rxd->sdp0 = htole32(data->map->dm_segs[0].ds_addr); |
1335 | | | 1348 | |
1336 | rxwi = mtod(m, struct rt2860_rxwi *); | | 1349 | rxwi = mtod(m, struct rt2860_rxwi *); |
1337 | | | 1350 | |
1338 | /* finalize mbuf */ | | 1351 | /* finalize mbuf */ |
1339 | m->m_data = (void *)(rxwi + 1); | | 1352 | m->m_data = (void *)(rxwi + 1); |
1340 | m_set_rcvif(m, ifp); | | 1353 | m_set_rcvif(m, ifp); |
1341 | m->m_pkthdr.len = m->m_len = le16toh(rxwi->len) & 0xfff; | | 1354 | m->m_pkthdr.len = m->m_len = le16toh(rxwi->len) & 0xfff; |
1342 | | | 1355 | |
1343 | wh = mtod(m, struct ieee80211_frame *); | | 1356 | wh = mtod(m, struct ieee80211_frame *); |
| | | 1357 | #ifdef HW_CRYPTO |
1344 | if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { | | 1358 | if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { |
1345 | /* frame is decrypted by hardware */ | | 1359 | /* frame is decrypted by hardware */ |
1346 | wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; | | 1360 | wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; |
1347 | } | | 1361 | } |
| | | 1362 | #endif |
1348 | | | 1363 | |
1349 | /* HW may insert 2 padding bytes after 802.11 header */ | | 1364 | /* HW may insert 2 padding bytes after 802.11 header */ |
1350 | if (rxd->flags & htole32(RT2860_RX_L2PAD)) { | | 1365 | if (rxd->flags & htole32(RT2860_RX_L2PAD)) { |
1351 | u_int hdrlen = ieee80211_hdrspace(ic, wh); | | 1366 | u_int hdrlen = ieee80211_hdrspace(ic, wh); |
1352 | memmove((char *)wh + 2, wh, hdrlen); | | 1367 | memmove((char *)wh + 2, wh, hdrlen); |
1353 | m->m_data += 2; | | 1368 | m->m_data += 2; |
1354 | wh = mtod(m, struct ieee80211_frame *); | | 1369 | wh = mtod(m, struct ieee80211_frame *); |
1355 | } | | 1370 | } |
1356 | | | 1371 | |
1357 | if (__predict_false(rxd->flags & htole32(RT2860_RX_MICERR))) { | | | |
1358 | /* report MIC failures to net80211 for TKIP */ | | | |
1359 | ieee80211_notify_michael_failure(ic, wh, 0/* XXX */); | | | |
1360 | ifp->if_ierrors++; | | | |
1361 | goto skip; | | | |
1362 | } | | | |
1363 | | | | |
1364 | ant = rt2860_maxrssi_chain(sc, rxwi); | | 1372 | ant = rt2860_maxrssi_chain(sc, rxwi); |
1365 | rssi = rxwi->rssi[ant]; | | 1373 | rssi = rxwi->rssi[ant]; |
1366 | | | 1374 | |
1367 | if (__predict_true(sc->sc_drvbpf == NULL)) | | 1375 | if (__predict_true(sc->sc_drvbpf == NULL)) |
1368 | goto skipbpf; | | 1376 | goto skipbpf; |
1369 | | | 1377 | |
1370 | tap = &sc->sc_rxtap; | | 1378 | tap = &sc->sc_rxtap; |
1371 | tap->wr_flags = 0; | | 1379 | tap->wr_flags = 0; |
1372 | tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); | | 1380 | tap->wr_chan_freq = htole16(ic->ic_curchan->ic_freq); |
1373 | tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); | | 1381 | tap->wr_chan_flags = htole16(ic->ic_curchan->ic_flags); |
1374 | tap->wr_antsignal = rssi; | | 1382 | tap->wr_antsignal = rssi; |
1375 | tap->wr_antenna = ant; | | 1383 | tap->wr_antenna = ant; |
1376 | tap->wr_dbm_antsignal = rt2860_rssi2dbm(sc, rssi, ant); | | 1384 | tap->wr_dbm_antsignal = rt2860_rssi2dbm(sc, rssi, ant); |
| @@ -1392,26 +1400,27 @@ rt2860_rx_intr(struct rt2860_softc *sc) | | | @@ -1392,26 +1400,27 @@ rt2860_rx_intr(struct rt2860_softc *sc) |
1392 | case 0: tap->wr_rate = 12; break; | | 1400 | case 0: tap->wr_rate = 12; break; |
1393 | case 1: tap->wr_rate = 18; break; | | 1401 | case 1: tap->wr_rate = 18; break; |
1394 | case 2: tap->wr_rate = 24; break; | | 1402 | case 2: tap->wr_rate = 24; break; |
1395 | case 3: tap->wr_rate = 36; break; | | 1403 | case 3: tap->wr_rate = 36; break; |
1396 | case 4: tap->wr_rate = 48; break; | | 1404 | case 4: tap->wr_rate = 48; break; |
1397 | case 5: tap->wr_rate = 72; break; | | 1405 | case 5: tap->wr_rate = 72; break; |
1398 | case 6: tap->wr_rate = 96; break; | | 1406 | case 6: tap->wr_rate = 96; break; |
1399 | case 7: tap->wr_rate = 108; break; | | 1407 | case 7: tap->wr_rate = 108; break; |
1400 | } | | 1408 | } |
1401 | break; | | 1409 | break; |
1402 | } | | 1410 | } |
1403 | bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m); | | 1411 | bpf_mtap2(sc->sc_drvbpf, tap, sc->sc_rxtap_len, m); |
1404 | skipbpf: | | 1412 | skipbpf: |
| | | 1413 | wh = mtod(m, struct ieee80211_frame *); |
1405 | /* grab a reference to the source node */ | | 1414 | /* grab a reference to the source node */ |
1406 | ni = ieee80211_find_rxnode(ic, | | 1415 | ni = ieee80211_find_rxnode(ic, |
1407 | (struct ieee80211_frame_min *)wh); | | 1416 | (struct ieee80211_frame_min *)wh); |
1408 | | | 1417 | |
1409 | /* send the frame to the 802.11 layer */ | | 1418 | /* send the frame to the 802.11 layer */ |
1410 | ieee80211_input(ic, m, ni, rssi, 0); | | 1419 | ieee80211_input(ic, m, ni, rssi, 0); |
1411 | | | 1420 | |
1412 | /* node is no longer needed */ | | 1421 | /* node is no longer needed */ |
1413 | ieee80211_free_node(ni); | | 1422 | ieee80211_free_node(ni); |
1414 | | | 1423 | |
1415 | skip: rxd->sdl0 &= ~htole16(RT2860_RX_DDONE); | | 1424 | skip: rxd->sdl0 &= ~htole16(RT2860_RX_DDONE); |
1416 | | | 1425 | |
1417 | bus_dmamap_sync(sc->sc_dmat, sc->rxq.map, | | 1426 | bus_dmamap_sync(sc->sc_dmat, sc->rxq.map, |