realtekwifi: Import changes from FreeBSD HEAD.

Same source commit as the previous import of net80211 changes.

May help with USB stalls and other issues.
Tested, WiFi still works.
This commit is contained in:
Augustin Cavalier 2024-11-21 10:43:40 -05:00
parent da3ca31854
commit 7de59aee29
8 changed files with 136 additions and 43 deletions

View File

@ -113,8 +113,7 @@ rtwn_key_alloc(struct ieee80211vap *vap, struct ieee80211_key *k,
struct rtwn_softc *sc = vap->iv_ic->ic_softc;
int i, start;
if (&vap->iv_nw_keys[0] <= k &&
k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) {
if (ieee80211_is_key_global(vap, k)) {
*keyix = ieee80211_crypto_get_key_wepidx(vap, k);
if (sc->sc_hwcrypto != RTWN_CRYPTO_FULL)
k->wk_flags |= IEEE80211_KEY_SWCRYPT;
@ -308,8 +307,7 @@ rtwn_process_key(struct ieee80211vap *vap, const struct ieee80211_key *k,
return (1);
}
if (&vap->iv_nw_keys[0] <= k &&
k < &vap->iv_nw_keys[IEEE80211_WEP_NKID]) {
if (ieee80211_is_key_global(vap, k)) {
if (sc->sc_hwcrypto == RTWN_CRYPTO_FULL) {
struct rtwn_vap *rvp = RTWN_VAP(vap);

View File

@ -263,6 +263,11 @@ rtwn_start(struct rtwn_softc *sc)
struct mbuf *m;
RTWN_ASSERT_LOCKED(sc);
/* Ensure no work is scheduled during reset/teardown */
if ((sc->sc_flags & RTWN_RUNNING) == 0)
return;
while ((m = mbufq_dequeue(&sc->sc_snd)) != NULL) {
if (sc->qfullmsk != 0) {
mbufq_prepend(&sc->sc_snd, m);

View File

@ -32,7 +32,7 @@
#define RTWN_MACID_VALID 0x8000
#define RTWN_MACID_LIMIT 128
#define RTWN_TX_TIMEOUT 5000 /* ms */
#define RTWN_TX_TIMEOUT 1000 /* ms */
#define RTWN_MAX_EPOUT 4
#define RTWN_PORT_COUNT 2

View File

@ -157,10 +157,12 @@ rtwn_usb_alloc_tx_list(struct rtwn_softc *sc)
if (error != 0)
return (error);
STAILQ_INIT(&uc->uc_tx_active);
STAILQ_INIT(&uc->uc_tx_inactive);
STAILQ_INIT(&uc->uc_tx_pending);
for (i = RTWN_BULK_TX_FIRST; i < RTWN_BULK_EP_COUNT; i++) {
STAILQ_INIT(&uc->uc_tx_active[i]);
STAILQ_INIT(&uc->uc_tx_pending[i]);
}
STAILQ_INIT(&uc->uc_tx_inactive);
for (i = 0; i < RTWN_USB_TX_LIST_COUNT; i++)
STAILQ_INSERT_HEAD(&uc->uc_tx_inactive, &uc->uc_tx[i], next);
@ -208,23 +210,29 @@ static void
rtwn_usb_free_tx_list(struct rtwn_softc *sc)
{
struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc);
int i;
rtwn_usb_free_list(sc, uc->uc_tx, RTWN_USB_TX_LIST_COUNT);
STAILQ_INIT(&uc->uc_tx_active);
for (i = RTWN_BULK_TX_FIRST; i < RTWN_BULK_EP_COUNT; i++) {
STAILQ_INIT(&uc->uc_tx_active[i]);
STAILQ_INIT(&uc->uc_tx_pending[i]);
}
STAILQ_INIT(&uc->uc_tx_inactive);
STAILQ_INIT(&uc->uc_tx_pending);
}
static void
rtwn_usb_reset_lists(struct rtwn_softc *sc, struct ieee80211vap *vap)
{
struct rtwn_usb_softc *uc = RTWN_USB_SOFTC(sc);
int i;
RTWN_ASSERT_LOCKED(sc);
rtwn_usb_reset_tx_list(uc, &uc->uc_tx_active, vap);
rtwn_usb_reset_tx_list(uc, &uc->uc_tx_pending, vap);
for (i = RTWN_BULK_TX_FIRST; i < RTWN_BULK_EP_COUNT; i++) {
rtwn_usb_reset_tx_list(uc, &uc->uc_tx_active[i], vap);
rtwn_usb_reset_tx_list(uc, &uc->uc_tx_pending[i], vap);
}
if (vap == NULL) {
rtwn_usb_reset_rx_list(uc);
sc->qfullmsk = 0;
@ -296,7 +304,7 @@ rtwn_usb_abort_xfers(struct rtwn_softc *sc)
/* abort any pending transfers */
RTWN_UNLOCK(sc);
for (i = 0; i < RTWN_N_TRANSFER; i++)
for (i = 0; i < RTWN_BULK_EP_COUNT; i++)
usbd_transfer_drain(uc->uc_xfer[i]);
RTWN_LOCK(sc);
}
@ -433,7 +441,7 @@ rtwn_usb_detach(device_t self)
rtwn_usb_free_rx_list(sc);
/* Detach all USB transfers. */
usbd_transfer_unsetup(uc->uc_xfer, RTWN_N_TRANSFER);
usbd_transfer_unsetup(uc->uc_xfer, RTWN_BULK_EP_COUNT);
rtwn_detach_private(sc);
mtx_destroy(&sc->sc_mtx);

View File

@ -55,7 +55,7 @@
#include <dev/rtwn/rtl8192c/usb/r92cu_reg.h>
static const struct usb_config rtwn_config_common[RTWN_N_TRANSFER] = {
static const struct usb_config rtwn_config_common[RTWN_BULK_EP_COUNT] = {
[RTWN_BULK_RX] = {
.type = UE_BULK,
.endpoint = UE_ADDR_ANY,
@ -76,7 +76,7 @@ static const struct usb_config rtwn_config_common[RTWN_N_TRANSFER] = {
.pipe_bof = 1,
.force_short_xfer = 1,
},
.callback = rtwn_bulk_tx_callback,
.callback = rtwn_bulk_tx_callback_be,
.timeout = RTWN_TX_TIMEOUT, /* ms */
},
[RTWN_BULK_TX_BK] = {
@ -89,7 +89,7 @@ static const struct usb_config rtwn_config_common[RTWN_N_TRANSFER] = {
.pipe_bof = 1,
.force_short_xfer = 1,
},
.callback = rtwn_bulk_tx_callback,
.callback = rtwn_bulk_tx_callback_bk,
.timeout = RTWN_TX_TIMEOUT, /* ms */
},
[RTWN_BULK_TX_VI] = {
@ -102,7 +102,7 @@ static const struct usb_config rtwn_config_common[RTWN_N_TRANSFER] = {
.pipe_bof = 1,
.force_short_xfer = 1
},
.callback = rtwn_bulk_tx_callback,
.callback = rtwn_bulk_tx_callback_vi,
.timeout = RTWN_TX_TIMEOUT, /* ms */
},
[RTWN_BULK_TX_VO] = {
@ -115,7 +115,7 @@ static const struct usb_config rtwn_config_common[RTWN_N_TRANSFER] = {
.pipe_bof = 1,
.force_short_xfer = 1
},
.callback = rtwn_bulk_tx_callback,
.callback = rtwn_bulk_tx_callback_vo,
.timeout = RTWN_TX_TIMEOUT, /* ms */
},
};
@ -200,22 +200,33 @@ rtwn_usb_setup_endpoints(struct rtwn_usb_softc *uc)
/* NB: keep in sync with rtwn_dma_init(). */
rtwn_config[RTWN_BULK_TX_VO].endpoint = addr[0];
uc->wme2qid[WME_AC_VO] = RTWN_BULK_TX_VO;
switch (uc->ntx) {
case 4:
case 3:
rtwn_config[RTWN_BULK_TX_BE].endpoint = addr[2];
rtwn_config[RTWN_BULK_TX_BK].endpoint = addr[2];
rtwn_config[RTWN_BULK_TX_VI].endpoint = addr[1];
uc->wme2qid[WME_AC_BE] = RTWN_BULK_TX_BE;
uc->wme2qid[WME_AC_BK] = RTWN_BULK_TX_BE;
uc->wme2qid[WME_AC_VI] = RTWN_BULK_TX_VI;
break;
case 2:
rtwn_config[RTWN_BULK_TX_BE].endpoint = addr[1];
rtwn_config[RTWN_BULK_TX_BK].endpoint = addr[1];
rtwn_config[RTWN_BULK_TX_VI].endpoint = addr[0];
uc->wme2qid[WME_AC_BE] = RTWN_BULK_TX_VI;
uc->wme2qid[WME_AC_BK] = RTWN_BULK_TX_VI;
uc->wme2qid[WME_AC_VI] = RTWN_BULK_TX_VO;
break;
case 1:
rtwn_config[RTWN_BULK_TX_BE].endpoint = addr[0];
rtwn_config[RTWN_BULK_TX_BK].endpoint = addr[0];
rtwn_config[RTWN_BULK_TX_VI].endpoint = addr[0];
uc->wme2qid[WME_AC_BE] = RTWN_BULK_TX_VO;
uc->wme2qid[WME_AC_BK] = RTWN_BULK_TX_VO;
uc->wme2qid[WME_AC_VI] = RTWN_BULK_TX_VO;
break;
default:
KASSERT(0, ("unhandled number of endpoints %d\n", uc->ntx));
@ -225,7 +236,7 @@ rtwn_usb_setup_endpoints(struct rtwn_usb_softc *uc)
rtwn_config[RTWN_BULK_RX].bufsize =
uc->uc_rx_buf_size * RTWN_USB_RXBUFSZ_UNIT;
error = usbd_transfer_setup(uc->uc_udev, &iface_index,
uc->uc_xfer, rtwn_config, RTWN_N_TRANSFER, uc, &sc->sc_mtx);
uc->uc_xfer, rtwn_config, RTWN_BULK_EP_COUNT, uc, &sc->sc_mtx);
free(rtwn_config, M_TEMP);
if (error) {

View File

@ -65,10 +65,6 @@ static struct rtwn_data * rtwn_usb_getbuf(struct rtwn_usb_softc *);
static void rtwn_usb_txeof(struct rtwn_usb_softc *,
struct rtwn_data *, int);
static const uint8_t wme2qid[] =
{ RTWN_BULK_TX_BE, RTWN_BULK_TX_BK,
RTWN_BULK_TX_VI, RTWN_BULK_TX_VO };
static struct rtwn_data *
_rtwn_usb_getbuf(struct rtwn_usb_softc *uc)
{
@ -105,6 +101,7 @@ static void
rtwn_usb_txeof(struct rtwn_usb_softc *uc, struct rtwn_data *data, int status)
{
struct rtwn_softc *sc = &uc->uc_sc;
bool is_empty = true;
RTWN_ASSERT_LOCKED(sc);
@ -120,42 +117,54 @@ rtwn_usb_txeof(struct rtwn_usb_softc *uc, struct rtwn_data *data, int status)
STAILQ_INSERT_TAIL(&uc->uc_tx_inactive, data, next);
sc->qfullmsk = 0;
#ifndef D4054
if (STAILQ_EMPTY(&uc->uc_tx_active) && STAILQ_EMPTY(&uc->uc_tx_pending))
for (int i = RTWN_BULK_TX_FIRST; i < RTWN_BULK_EP_COUNT; i++) {
if (!STAILQ_EMPTY(&uc->uc_tx_active[i]) ||
!STAILQ_EMPTY(&uc->uc_tx_pending[i]))
is_empty = false;
}
if (is_empty)
sc->sc_tx_timer = 0;
else
sc->sc_tx_timer = 5;
#endif
}
void
rtwn_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
static void
rtwn_bulk_tx_callback_qid(struct usb_xfer *xfer, usb_error_t error, int qid)
{
struct rtwn_usb_softc *uc = usbd_xfer_softc(xfer);
struct rtwn_softc *sc = &uc->uc_sc;
struct rtwn_data *data;
bool do_is_empty_check = false;
int i;
RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT,
"%s: called, qid=%d\n", __func__, qid);
RTWN_ASSERT_LOCKED(sc);
switch (USB_GET_STATE(xfer)){
case USB_ST_TRANSFERRED:
data = STAILQ_FIRST(&uc->uc_tx_active);
data = STAILQ_FIRST(&uc->uc_tx_active[qid]);
if (data == NULL)
goto tr_setup;
STAILQ_REMOVE_HEAD(&uc->uc_tx_active, next);
STAILQ_REMOVE_HEAD(&uc->uc_tx_active[qid], next);
rtwn_usb_txeof(uc, data, 0);
/* FALLTHROUGH */
case USB_ST_SETUP:
tr_setup:
data = STAILQ_FIRST(&uc->uc_tx_pending);
data = STAILQ_FIRST(&uc->uc_tx_pending[qid]);
if (data == NULL) {
RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT,
"%s: empty pending queue\n", __func__);
sc->sc_tx_n_active = 0;
do_is_empty_check = true;
goto finish;
}
STAILQ_REMOVE_HEAD(&uc->uc_tx_pending, next);
STAILQ_INSERT_TAIL(&uc->uc_tx_active, data, next);
STAILQ_REMOVE_HEAD(&uc->uc_tx_pending[qid], next);
STAILQ_INSERT_TAIL(&uc->uc_tx_active[qid], data, next);
/*
* Note: if this is a beacon frame, ensure that it will go
@ -169,11 +178,17 @@ tr_setup:
sc->sc_tx_n_active++;
break;
default:
data = STAILQ_FIRST(&uc->uc_tx_active);
data = STAILQ_FIRST(&uc->uc_tx_active[qid]);
if (data == NULL)
goto tr_setup;
STAILQ_REMOVE_HEAD(&uc->uc_tx_active, next);
STAILQ_REMOVE_HEAD(&uc->uc_tx_active[qid], next);
rtwn_usb_txeof(uc, data, 1);
if (error != 0)
device_printf(sc->sc_dev,
"%s: called; txeof qid=%d, error=%s\n",
__func__,
qid,
usbd_errstr(error));
if (error != USB_ERR_CANCELLED) {
usbd_xfer_set_stall(xfer);
goto tr_setup;
@ -181,6 +196,19 @@ tr_setup:
break;
}
finish:
/*
* Clear sc_tx_n_active if all the pending transfers are 0.
*
* This is currently a crutch because net80211 doesn't provide
* a way to defer all the FF checks or one of the FF checks.
* Eventually this should just be tracked per-endpoint.
*/
for (i = RTWN_BULK_TX_FIRST; i < RTWN_BULK_EP_COUNT; i++)
if (STAILQ_FIRST(&uc->uc_tx_pending[i]) != NULL)
do_is_empty_check = false;
if (do_is_empty_check)
sc->sc_tx_n_active = 0;
#ifdef IEEE80211_SUPPORT_SUPERG
/*
* If the TX active queue drops below a certain
@ -210,6 +238,34 @@ finish:
rtwn_start(sc);
}
void
rtwn_bulk_tx_callback_be(struct usb_xfer *xfer, usb_error_t error)
{
rtwn_bulk_tx_callback_qid(xfer, error, RTWN_BULK_TX_BE);
}
void
rtwn_bulk_tx_callback_bk(struct usb_xfer *xfer, usb_error_t error)
{
rtwn_bulk_tx_callback_qid(xfer, error, RTWN_BULK_TX_BK);
}
void
rtwn_bulk_tx_callback_vi(struct usb_xfer *xfer, usb_error_t error)
{
rtwn_bulk_tx_callback_qid(xfer, error, RTWN_BULK_TX_VI);
}
void
rtwn_bulk_tx_callback_vo(struct usb_xfer *xfer, usb_error_t error)
{
rtwn_bulk_tx_callback_qid(xfer, error, RTWN_BULK_TX_VO);
}
static void
rtwn_usb_tx_checksum(struct rtwn_tx_desc_common *txd)
{
@ -226,6 +282,7 @@ rtwn_usb_tx_start(struct rtwn_softc *sc, struct ieee80211_node *ni,
struct rtwn_data *data;
struct usb_xfer *xfer;
uint16_t ac;
int qid = 0;
RTWN_ASSERT_LOCKED(sc);
@ -236,17 +293,23 @@ rtwn_usb_tx_start(struct rtwn_softc *sc, struct ieee80211_node *ni,
if (data == NULL)
return (ENOBUFS);
/* TODO: should really get a consistent AC/TID, ath(4) style */
ac = M_WME_GETAC(m);
switch (type) {
case IEEE80211_FC0_TYPE_CTL:
case IEEE80211_FC0_TYPE_MGT:
xfer = uc->uc_xfer[RTWN_BULK_TX_VO];
qid = RTWN_BULK_TX_VO;
break;
default:
xfer = uc->uc_xfer[wme2qid[ac]];
qid = uc->wme2qid[ac];
break;
}
xfer = uc->uc_xfer[qid];
RTWN_DPRINTF(sc, RTWN_DEBUG_XMIT,
"%s: called, ac=%d, qid=%d, xfer=%p\n",
__func__, ac, qid, xfer);
txd = (struct rtwn_tx_desc_common *)tx_desc;
txd->pktlen = htole16(m->m_pkthdr.len);
@ -264,6 +327,7 @@ rtwn_usb_tx_start(struct rtwn_softc *sc, struct ieee80211_node *ni,
data->buflen = m->m_pkthdr.len + sc->txdesc_len;
data->id = id;
data->ni = ni;
data->qid = qid;
if (data->ni != NULL) {
data->m = m;
#ifndef D4054
@ -271,7 +335,7 @@ rtwn_usb_tx_start(struct rtwn_softc *sc, struct ieee80211_node *ni,
#endif
}
STAILQ_INSERT_TAIL(&uc->uc_tx_pending, data, next);
STAILQ_INSERT_TAIL(&uc->uc_tx_pending[qid], data, next);
if (STAILQ_EMPTY(&uc->uc_tx_inactive))
sc->qfullmsk = 1;

View File

@ -17,7 +17,10 @@
#ifndef RTWN_USB_TX_H
#define RTWN_USB_TX_H
void rtwn_bulk_tx_callback(struct usb_xfer *, usb_error_t);
void rtwn_bulk_tx_callback_bk(struct usb_xfer *, usb_error_t);
void rtwn_bulk_tx_callback_be(struct usb_xfer *, usb_error_t);
void rtwn_bulk_tx_callback_vi(struct usb_xfer *, usb_error_t);
void rtwn_bulk_tx_callback_vo(struct usb_xfer *, usb_error_t);
int rtwn_usb_tx_start(struct rtwn_softc *, struct ieee80211_node *,
struct mbuf *, uint8_t *, uint8_t, int);

View File

@ -37,6 +37,7 @@ struct rtwn_data {
uint8_t *buf;
/* 'id' is meaningful for beacons only */
int id;
int qid;
uint16_t buflen;
struct mbuf *m;
struct ieee80211_node *ni;
@ -50,15 +51,16 @@ enum {
RTWN_BULK_TX_BK, /* = WME_AC_BK */
RTWN_BULK_TX_VI, /* = WME_AC_VI */
RTWN_BULK_TX_VO, /* = WME_AC_VO */
RTWN_N_TRANSFER = 5,
RTWN_BULK_EP_COUNT = 5,
};
#define RTWN_EP_QUEUES RTWN_BULK_RX
#define RTWN_BULK_TX_FIRST RTWN_BULK_TX_BE
struct rtwn_usb_softc {
struct rtwn_softc uc_sc; /* must be the first */
struct usb_device *uc_udev;
struct usb_xfer *uc_xfer[RTWN_N_TRANSFER];
struct usb_xfer *uc_xfer[RTWN_BULK_EP_COUNT];
struct rtwn_data uc_rx[RTWN_USB_RX_LIST_COUNT];
rtwn_datahead uc_rx_active;
@ -70,14 +72,16 @@ struct rtwn_usb_softc {
int uc_rx_off;
struct rtwn_data uc_tx[RTWN_USB_TX_LIST_COUNT];
rtwn_datahead uc_tx_active;
rtwn_datahead uc_tx_active[RTWN_BULK_EP_COUNT];
rtwn_datahead uc_tx_inactive;
rtwn_datahead uc_tx_pending;
rtwn_datahead uc_tx_pending[RTWN_BULK_EP_COUNT];
int (*uc_align_rx)(int, int);
int ntx;
int tx_agg_desc_num;
uint8_t wme2qid[4];
};
#define RTWN_USB_SOFTC(sc) ((struct rtwn_usb_softc *)(sc))