| @@ -1,39 +1,39 @@ | | | @@ -1,39 +1,39 @@ |
1 | /* $NetBSD: rt2860.c,v 1.6 2016/05/02 17:37:23 christos Exp $ */ | | 1 | /* $NetBSD: rt2860.c,v 1.7 2016/05/03 00:19:32 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.6 2016/05/02 17:37:23 christos Exp $"); | | 26 | __KERNEL_RCSID(0, "$NetBSD: rt2860.c,v 1.7 2016/05/03 00:19:32 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> |
| @@ -1197,28 +1197,29 @@ rt2860_tx_intr(struct rt2860_softc *sc, | | | @@ -1197,28 +1197,29 @@ rt2860_tx_intr(struct rt2860_softc *sc, |
1197 | ieee80211_free_node(data->ni); | | 1197 | ieee80211_free_node(data->ni); |
1198 | data->ni = NULL; | | 1198 | data->ni = NULL; |
1199 | | | 1199 | |
1200 | SLIST_INSERT_HEAD(&sc->data_pool, data, next); | | 1200 | SLIST_INSERT_HEAD(&sc->data_pool, data, next); |
1201 | ring->data[ring->next] = NULL; | | 1201 | ring->data[ring->next] = NULL; |
1202 | | | 1202 | |
1203 | ifp->if_opackets++; | | 1203 | ifp->if_opackets++; |
1204 | } | | 1204 | } |
1205 | ring->queued--; | | 1205 | ring->queued--; |
1206 | ring->next = (ring->next + 1) % RT2860_TX_RING_COUNT; | | 1206 | ring->next = (ring->next + 1) % RT2860_TX_RING_COUNT; |
1207 | } | | 1207 | } |
1208 | | | 1208 | |
1209 | sc->sc_tx_timer = 0; | | 1209 | sc->sc_tx_timer = 0; |
1210 | if (ring->queued < RT2860_TX_RING_ONEMORE) | | 1210 | if (ring->queued <= RT2860_TX_RING_ONEMORE) |
1211 | sc->qfullmsk &= ~(1 << qid); | | 1211 | sc->qfullmsk &= ~(1 << qid); |
| | | 1212 | ifp->if_flags &= ~IFF_OACTIVE; |
1212 | rt2860_start(ifp); | | 1213 | rt2860_start(ifp); |
1213 | } | | 1214 | } |
1214 | | | 1215 | |
1215 | /* | | 1216 | /* |
1216 | * Return the Rx chain with the highest RSSI for a given frame. | | 1217 | * Return the Rx chain with the highest RSSI for a given frame. |
1217 | */ | | 1218 | */ |
1218 | static __inline uint8_t | | 1219 | static __inline uint8_t |
1219 | rt2860_maxrssi_chain(struct rt2860_softc *sc, const struct rt2860_rxwi *rxwi) | | 1220 | rt2860_maxrssi_chain(struct rt2860_softc *sc, const struct rt2860_rxwi *rxwi) |
1220 | { | | 1221 | { |
1221 | uint8_t rxchain = 0; | | 1222 | uint8_t rxchain = 0; |
1222 | | | 1223 | |
1223 | if (sc->nrxchains > 1) { | | 1224 | if (sc->nrxchains > 1) { |
1224 | if (rxwi->rssi[1] > rxwi->rssi[rxchain]) | | 1225 | if (rxwi->rssi[1] > rxwi->rssi[rxchain]) |
| @@ -1314,27 +1315,27 @@ rt2860_rx_intr(struct rt2860_softc *sc) | | | @@ -1314,27 +1315,27 @@ rt2860_rx_intr(struct rt2860_softc *sc) |
1314 | /* finalize mbuf */ | | 1315 | /* finalize mbuf */ |
1315 | m->m_data = (void *)(rxwi + 1); | | 1316 | m->m_data = (void *)(rxwi + 1); |
1316 | m->m_pkthdr.len = m->m_len = le16toh(rxwi->len) & 0xfff; | | 1317 | m->m_pkthdr.len = m->m_len = le16toh(rxwi->len) & 0xfff; |
1317 | | | 1318 | |
1318 | wh = mtod(m, struct ieee80211_frame *); | | 1319 | wh = mtod(m, struct ieee80211_frame *); |
1319 | if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { | | 1320 | if (wh->i_fc[1] & IEEE80211_FC1_PROTECTED) { |
1320 | /* frame is decrypted by hardware */ | | 1321 | /* frame is decrypted by hardware */ |
1321 | wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; | | 1322 | wh->i_fc[1] &= ~IEEE80211_FC1_PROTECTED; |
1322 | } | | 1323 | } |
1323 | | | 1324 | |
1324 | /* HW may insert 2 padding bytes after 802.11 header */ | | 1325 | /* HW may insert 2 padding bytes after 802.11 header */ |
1325 | if (rxd->flags & htole32(RT2860_RX_L2PAD)) { | | 1326 | if (rxd->flags & htole32(RT2860_RX_L2PAD)) { |
1326 | u_int hdrlen = ieee80211_hdrspace(ic, wh); | | 1327 | u_int hdrlen = ieee80211_hdrspace(ic, wh); |
1327 | memmove(wh + 2, wh, hdrlen); | | 1328 | memmove((char *)wh + 2, wh, hdrlen); |
1328 | m->m_data += 2; | | 1329 | m->m_data += 2; |
1329 | wh = mtod(m, struct ieee80211_frame *); | | 1330 | wh = mtod(m, struct ieee80211_frame *); |
1330 | } | | 1331 | } |
1331 | | | 1332 | |
1332 | if (__predict_false(rxd->flags & htole32(RT2860_RX_MICERR))) { | | 1333 | if (__predict_false(rxd->flags & htole32(RT2860_RX_MICERR))) { |
1333 | /* report MIC failures to net80211 for TKIP */ | | 1334 | /* report MIC failures to net80211 for TKIP */ |
1334 | ieee80211_notify_michael_failure(ic, wh, 0/* XXX */); | | 1335 | ieee80211_notify_michael_failure(ic, wh, 0/* XXX */); |
1335 | ifp->if_ierrors++; | | 1336 | ifp->if_ierrors++; |
1336 | goto skip; | | 1337 | goto skip; |
1337 | } | | 1338 | } |
1338 | | | 1339 | |
1339 | ant = rt2860_maxrssi_chain(sc, rxwi); | | 1340 | ant = rt2860_maxrssi_chain(sc, rxwi); |
1340 | rssi = rxwi->rssi[ant]; | | 1341 | rssi = rxwi->rssi[ant]; |
| @@ -1479,28 +1480,29 @@ rt2860_intr(void *arg) | | | @@ -1479,28 +1480,29 @@ rt2860_intr(void *arg) |
1479 | | | 1480 | |
1480 | if (r & RT2860_TX_DONE_INT2) | | 1481 | if (r & RT2860_TX_DONE_INT2) |
1481 | rt2860_tx_intr(sc, 2); | | 1482 | rt2860_tx_intr(sc, 2); |
1482 | | | 1483 | |
1483 | if (r & RT2860_TX_DONE_INT1) | | 1484 | if (r & RT2860_TX_DONE_INT1) |
1484 | rt2860_tx_intr(sc, 1); | | 1485 | rt2860_tx_intr(sc, 1); |
1485 | | | 1486 | |
1486 | if (r & RT2860_TX_DONE_INT0) | | 1487 | if (r & RT2860_TX_DONE_INT0) |
1487 | rt2860_tx_intr(sc, 0); | | 1488 | rt2860_tx_intr(sc, 0); |
1488 | | | 1489 | |
1489 | if (r & RT2860_MAC_INT_0) /* TBTT */ | | 1490 | if (r & RT2860_MAC_INT_0) /* TBTT */ |
1490 | rt2860_tbtt_intr(sc); | | 1491 | rt2860_tbtt_intr(sc); |
1491 | | | 1492 | |
1492 | if (r & RT2860_MAC_INT_3) /* Auto wakeup */ | | 1493 | if (r & RT2860_MAC_INT_3) { /* Auto wakeup */ |
1493 | /* TBD wakeup */{}; | | 1494 | /* TBD wakeup */ |
| | | 1495 | } |
1494 | | | 1496 | |
1495 | if (r & RT2860_MAC_INT_4) /* GP timer */ | | 1497 | if (r & RT2860_MAC_INT_4) /* GP timer */ |
1496 | rt2860_gp_intr(sc); | | 1498 | rt2860_gp_intr(sc); |
1497 | | | 1499 | |
1498 | return 1; | | 1500 | return 1; |
1499 | } | | 1501 | } |
1500 | | | 1502 | |
1501 | static int | | 1503 | static int |
1502 | rt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni) | | 1504 | rt2860_tx(struct rt2860_softc *sc, struct mbuf *m, struct ieee80211_node *ni) |
1503 | { | | 1505 | { |
1504 | struct ieee80211com *ic = &sc->sc_ic; | | 1506 | struct ieee80211com *ic = &sc->sc_ic; |
1505 | struct rt2860_node *rn = (void *)ni; | | 1507 | struct rt2860_node *rn = (void *)ni; |
1506 | struct rt2860_tx_ring *ring; | | 1508 | struct rt2860_tx_ring *ring; |