rtwn: enable 11n support for RTL8188CE.
- Increase Rx buffer size from MCLBYTES to MJUMPAGESIZE. - Provide an additional defragmentation routine for frames larger than MCLBYTES; that is required by A-MSDU / Atheros Fast-Frames support to work with current Tx path implementation. Enabled features list for RTL8188CE: - Atheros Fast-Frames; - A-MPDU (Tx / Rx); - A-MSDU (Tx / Rx; 4k only); - Short Guard Interval. Tested with: - RTL8188CE (STA+AP) + RTL8821AU (STA). - RTL8188CE (STA) + RTL8188CUS (AP). Relnotes: yes
This commit is contained in:
parent
dd670c9738
commit
ee2a82541f
@ -29,7 +29,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"/
|
||||
.Dd October 17, 2016
|
||||
.Dd November 12, 2016
|
||||
.Dt RTWN_PCI 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -58,6 +58,3 @@ It operates in the 2GHz spectrum only.
|
||||
.Xr rtwnfw 4 ,
|
||||
.Xr rtwn_usb 4 ,
|
||||
.Xr pci 4
|
||||
.Sh CAVEATS
|
||||
Most 802.11 capabilities were turned off; some more testing
|
||||
is required to re-enable them.
|
||||
|
@ -20,7 +20,9 @@
|
||||
#define IF_RTWN_TX_H
|
||||
|
||||
void rtwn_drain_mbufq(struct rtwn_softc *);
|
||||
#ifdef IEEE80211_SUPPORT_SUPERG
|
||||
void rtwn_ff_flush_all(struct rtwn_softc *, union sec_param *);
|
||||
#endif
|
||||
int rtwn_transmit(struct ieee80211com *, struct mbuf *);
|
||||
void rtwn_start(struct rtwn_softc *);
|
||||
int rtwn_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
|
@ -149,8 +149,8 @@ rtwn_pci_alloc_rx_list(struct rtwn_softc *sc)
|
||||
|
||||
/* Create RX buffer DMA tag. */
|
||||
error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
|
||||
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
|
||||
1, MCLBYTES, 0, NULL, NULL, &rx_ring->data_dmat);
|
||||
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
|
||||
MJUMPAGESIZE, 1, MJUMPAGESIZE, 0, NULL, NULL, &rx_ring->data_dmat);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not create rx buf DMA tag\n");
|
||||
goto fail;
|
||||
@ -166,7 +166,8 @@ rtwn_pci_alloc_rx_list(struct rtwn_softc *sc)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rx_data->m = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
|
||||
rx_data->m = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR,
|
||||
MJUMPAGESIZE);
|
||||
if (rx_data->m == NULL) {
|
||||
device_printf(sc->sc_dev,
|
||||
"could not allocate rx mbuf\n");
|
||||
@ -175,8 +176,8 @@ rtwn_pci_alloc_rx_list(struct rtwn_softc *sc)
|
||||
}
|
||||
|
||||
error = bus_dmamap_load(rx_ring->data_dmat, rx_data->map,
|
||||
mtod(rx_data->m, void *), MCLBYTES, rtwn_pci_dma_map_addr,
|
||||
&rx_data->paddr, BUS_DMA_NOWAIT);
|
||||
mtod(rx_data->m, void *), MJUMPAGESIZE,
|
||||
rtwn_pci_dma_map_addr, &rx_data->paddr, BUS_DMA_NOWAIT);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev,
|
||||
"could not load rx buf DMA map");
|
||||
@ -184,7 +185,7 @@ rtwn_pci_alloc_rx_list(struct rtwn_softc *sc)
|
||||
}
|
||||
|
||||
rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i], rx_data->paddr,
|
||||
MCLBYTES, i);
|
||||
MJUMPAGESIZE, i);
|
||||
}
|
||||
rx_ring->cur = 0;
|
||||
|
||||
@ -206,7 +207,7 @@ rtwn_pci_reset_rx_list(struct rtwn_softc *sc)
|
||||
for (i = 0; i < RTWN_PCI_RX_LIST_COUNT; i++) {
|
||||
rx_data = &rx_ring->rx_data[i];
|
||||
rtwn_pci_setup_rx_desc(pc, &rx_ring->desc[i],
|
||||
rx_data->paddr, MCLBYTES, i);
|
||||
rx_data->paddr, MJUMPAGESIZE, i);
|
||||
}
|
||||
rx_ring->cur = 0;
|
||||
}
|
||||
@ -287,8 +288,8 @@ rtwn_pci_alloc_tx_list(struct rtwn_softc *sc, int qid)
|
||||
BUS_DMASYNC_PREWRITE);
|
||||
|
||||
error = bus_dma_tag_create(bus_get_dma_tag(sc->sc_dev), 1, 0,
|
||||
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES,
|
||||
1, MCLBYTES, 0, NULL, NULL, &tx_ring->data_dmat);
|
||||
BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL,
|
||||
MJUMPAGESIZE, 1, MJUMPAGESIZE, 0, NULL, NULL, &tx_ring->data_dmat);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not create tx buf DMA tag\n");
|
||||
goto fail;
|
||||
|
@ -50,6 +50,7 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/rtwn/if_rtwnvar.h>
|
||||
#include <dev/rtwn/if_rtwn_debug.h>
|
||||
#include <dev/rtwn/if_rtwn_rx.h>
|
||||
#include <dev/rtwn/if_rtwn_task.h>
|
||||
#include <dev/rtwn/if_rtwn_tx.h>
|
||||
|
||||
#include <dev/rtwn/pci/rtwn_pci_var.h>
|
||||
@ -120,7 +121,7 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc,
|
||||
|
||||
pktlen = MS(rxdw0, R92C_RXDW0_PKTLEN);
|
||||
if (__predict_false(pktlen < sizeof(struct ieee80211_frame_ack) ||
|
||||
pktlen > MCLBYTES)) {
|
||||
pktlen > MJUMPAGESIZE)) {
|
||||
RTWN_DPRINTF(sc, RTWN_DEBUG_RECV,
|
||||
"%s: frame is too short/long: %d\n", __func__, pktlen);
|
||||
goto fail;
|
||||
@ -129,7 +130,7 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc,
|
||||
infosz = MS(rxdw0, R92C_RXDW0_INFOSZ) * 8;
|
||||
shift = MS(rxdw0, R92C_RXDW0_SHIFT);
|
||||
|
||||
m1 = m_getcl(M_NOWAIT, MT_DATA, M_PKTHDR);
|
||||
m1 = m_getjcl(M_NOWAIT, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
|
||||
if (__predict_false(m1 == NULL)) {
|
||||
device_printf(sc->sc_dev, "%s: could not allocate RX mbuf\n",
|
||||
__func__);
|
||||
@ -139,20 +140,20 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc,
|
||||
bus_dmamap_unload(ring->data_dmat, rx_data->map);
|
||||
|
||||
error = bus_dmamap_load(ring->data_dmat, rx_data->map, mtod(m1, void *),
|
||||
MCLBYTES, rtwn_pci_dma_map_addr, &rx_data->paddr, 0);
|
||||
MJUMPAGESIZE, rtwn_pci_dma_map_addr, &rx_data->paddr, 0);
|
||||
if (error != 0) {
|
||||
m_freem(m1);
|
||||
|
||||
error = bus_dmamap_load(ring->data_dmat, rx_data->map,
|
||||
mtod(rx_data->m, void *), MCLBYTES, rtwn_pci_dma_map_addr,
|
||||
&rx_data->paddr, BUS_DMA_NOWAIT);
|
||||
mtod(rx_data->m, void *), MJUMPAGESIZE,
|
||||
rtwn_pci_dma_map_addr, &rx_data->paddr, BUS_DMA_NOWAIT);
|
||||
if (error != 0)
|
||||
panic("%s: could not load old RX mbuf",
|
||||
device_get_name(sc->sc_dev));
|
||||
|
||||
/* Physical address may have changed. */
|
||||
rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MCLBYTES,
|
||||
desc_idx);
|
||||
rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr,
|
||||
MJUMPAGESIZE, desc_idx);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
@ -169,7 +170,7 @@ rtwn_pci_rx_frame(struct rtwn_softc *sc, struct r92ce_rx_stat *rx_desc,
|
||||
__func__, pktlen, infosz, shift, rssi);
|
||||
|
||||
/* Update RX descriptor. */
|
||||
rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MCLBYTES,
|
||||
rtwn_pci_setup_rx_desc(pc, rx_desc, rx_data->paddr, MJUMPAGESIZE,
|
||||
desc_idx);
|
||||
|
||||
/* Send the frame to the 802.11 layer. */
|
||||
@ -222,6 +223,8 @@ rtwn_pci_tx_done(struct rtwn_softc *sc, int qid)
|
||||
|
||||
data->ni = NULL;
|
||||
ring->queued--;
|
||||
KASSERT(ring->queued >= 0,
|
||||
("ring->queued (qid %d) underflow!\n", qid));
|
||||
} else
|
||||
m_freem(data->m);
|
||||
|
||||
@ -235,9 +238,27 @@ rtwn_pci_tx_done(struct rtwn_softc *sc, int qid)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (ring->queued < (RTWN_PCI_TX_LIST_COUNT - 1))
|
||||
if ((sc->qfullmsk & (1 << qid)) != 0 &&
|
||||
ring->queued < (RTWN_PCI_TX_LIST_COUNT - 1)) {
|
||||
sc->qfullmsk &= ~(1 << qid);
|
||||
rtwn_start(sc);
|
||||
rtwn_start(sc);
|
||||
}
|
||||
|
||||
#ifdef IEEE80211_SUPPORT_SUPERG
|
||||
/*
|
||||
* If the TX active queue drops below a certain
|
||||
* threshold, ensure we age fast-frames out so they're
|
||||
* transmitted.
|
||||
*/
|
||||
if (sc->sc_ratectl != RTWN_RATECTL_NET80211 && ring->queued <= 1) {
|
||||
/*
|
||||
* XXX TODO: just make this a callout timer schedule
|
||||
* so we can flush the FF staging queue if we're
|
||||
* approaching idle.
|
||||
*/
|
||||
rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
@ -261,6 +282,17 @@ rtwn_pci_rx_done(struct rtwn_softc *sc)
|
||||
|
||||
ring->cur = (ring->cur + 1) % RTWN_PCI_RX_LIST_COUNT;
|
||||
}
|
||||
|
||||
/* Finished receive; age anything left on the FF queue by a little bump */
|
||||
/*
|
||||
* XXX TODO: just make this a callout timer schedule so we can
|
||||
* flush the FF staging queue if we're approaching idle.
|
||||
*/
|
||||
#ifdef IEEE80211_SUPPORT_SUPERG
|
||||
if (!(sc->sc_flags & RTWN_FW_LOADED) ||
|
||||
sc->sc_ratectl != RTWN_RATECTL_NET80211)
|
||||
rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all);
|
||||
#endif
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -58,6 +58,37 @@ __FBSDID("$FreeBSD$");
|
||||
#include <dev/rtwn/rtl8192c/pci/r92ce_reg.h>
|
||||
|
||||
|
||||
static struct mbuf *
|
||||
rtwn_mbuf_defrag(struct mbuf *m0, int how)
|
||||
{
|
||||
struct mbuf *m = NULL;
|
||||
|
||||
KASSERT(m0->m_flags & M_PKTHDR,
|
||||
("M_PKTHDR flag is absent (m %p)!", m0));
|
||||
|
||||
/* NB: we need _exactly_ one mbuf (no less, no more). */
|
||||
if (m0->m_pkthdr.len > MJUMPAGESIZE) {
|
||||
/* XXX MJUM9BYTES? */
|
||||
return (NULL);
|
||||
} else if (m0->m_pkthdr.len > MCLBYTES) {
|
||||
m = m_getjcl(how, MT_DATA, M_PKTHDR, MJUMPAGESIZE);
|
||||
if (m == NULL)
|
||||
return (NULL);
|
||||
|
||||
if (m_dup_pkthdr(m, m0, how) == 0) {
|
||||
m_freem(m);
|
||||
return (NULL);
|
||||
}
|
||||
|
||||
m_copydata(m0, 0, m0->m_pkthdr.len, mtod(m, caddr_t));
|
||||
m->m_len = m->m_pkthdr.len;
|
||||
m_freem(m0);
|
||||
|
||||
return (m);
|
||||
} else
|
||||
return (m_defrag(m0, how));
|
||||
}
|
||||
|
||||
static int
|
||||
rtwn_pci_tx_start_frame(struct rtwn_softc *sc, struct ieee80211_node *ni,
|
||||
struct mbuf *m, uint8_t *tx_desc, uint8_t type)
|
||||
@ -114,7 +145,7 @@ rtwn_pci_tx_start_frame(struct rtwn_softc *sc, struct ieee80211_node *ni,
|
||||
if (error != 0) {
|
||||
struct mbuf *mnew;
|
||||
|
||||
mnew = m_defrag(m, M_NOWAIT);
|
||||
mnew = rtwn_mbuf_defrag(m, M_NOWAIT);
|
||||
if (mnew == NULL) {
|
||||
device_printf(sc->sc_dev, "can't defragment mbuf\n");
|
||||
return (ENOBUFS);
|
||||
|
@ -138,15 +138,11 @@ r92ce_adj_devcaps(struct rtwn_softc *sc)
|
||||
{
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
|
||||
/* XXX TODO: test everything that removed here before enabling. */
|
||||
/* XX do NOT enable PMGT until RSVD_PAGE command will not be fixed. */
|
||||
ic->ic_caps &= ~(
|
||||
IEEE80211_C_PMGT /* check null frame / device usability */
|
||||
| IEEE80211_C_SWAMSDUTX
|
||||
| IEEE80211_C_FF
|
||||
);
|
||||
|
||||
ic->ic_htcaps = 0;
|
||||
/*
|
||||
* XXX do NOT enable PMGT until RSVD_PAGE command
|
||||
* will not be tested / fixed + HRPWM register must be set too.
|
||||
*/
|
||||
ic->ic_caps &= ~IEEE80211_C_PMGT;
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -326,7 +326,8 @@ rtwn_bulk_rx_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
* flush the FF staging queue if we're approaching idle.
|
||||
*/
|
||||
#ifdef IEEE80211_SUPPORT_SUPERG
|
||||
if (!(sc->sc_flags & RTWN_FW_LOADED))
|
||||
if (!(sc->sc_flags & RTWN_FW_LOADED) ||
|
||||
sc->sc_ratectl != RTWN_RATECTL_NET80211)
|
||||
rtwn_cmd_sleepable(sc, NULL, 0, rtwn_ff_flush_all);
|
||||
#endif
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user