MFC r267066 and r267041:
Fixes for the RSU driver: - The R92S_TCR register is an 8-bit register. Don't access it like a 16-bit register. - Disable parsing the delete station event, due to many false events. - Ensure that there is only one transfer queue for each endpoint, so to hal packets transmitted don't get out of order. - Properly align temporary buffer to 32-bit. - Add an extra parenthesis to make expression clear. - Range check the association ID received from hardware.
This commit is contained in:
parent
6976be81b3
commit
7905925f36
@ -127,10 +127,8 @@ static const STRUCT_USB_HOST_ID rsu_devs[] = {
|
||||
static device_probe_t rsu_match;
|
||||
static device_attach_t rsu_attach;
|
||||
static device_detach_t rsu_detach;
|
||||
static usb_callback_t rsu_bulk_tx_callback_0;
|
||||
static usb_callback_t rsu_bulk_tx_callback_1;
|
||||
static usb_callback_t rsu_bulk_tx_callback_2;
|
||||
static usb_callback_t rsu_bulk_tx_callback_3;
|
||||
static usb_callback_t rsu_bulk_tx_callback_be_bk;
|
||||
static usb_callback_t rsu_bulk_tx_callback_vi_vo;
|
||||
static usb_callback_t rsu_bulk_rx_callback;
|
||||
static usb_error_t rsu_do_request(struct rsu_softc *,
|
||||
struct usb_device_request *, void *);
|
||||
@ -220,6 +218,13 @@ MODULE_DEPEND(rsu, usb, 1, 1, 1);
|
||||
MODULE_DEPEND(rsu, firmware, 1, 1, 1);
|
||||
MODULE_VERSION(rsu, 1);
|
||||
|
||||
static uint8_t rsu_wme_ac_xfer_map[4] = {
|
||||
[WME_AC_BE] = RSU_BULK_TX_BE_BK,
|
||||
[WME_AC_BK] = RSU_BULK_TX_BE_BK,
|
||||
[WME_AC_VI] = RSU_BULK_TX_VI_VO,
|
||||
[WME_AC_VO] = RSU_BULK_TX_VI_VO,
|
||||
};
|
||||
|
||||
static const struct usb_config rsu_config[RSU_N_TRANSFER] = {
|
||||
[RSU_BULK_RX] = {
|
||||
.type = UE_BULK,
|
||||
@ -232,7 +237,7 @@ static const struct usb_config rsu_config[RSU_N_TRANSFER] = {
|
||||
},
|
||||
.callback = rsu_bulk_rx_callback
|
||||
},
|
||||
[RSU_BULK_TX_BE] = {
|
||||
[RSU_BULK_TX_BE_BK] = {
|
||||
.type = UE_BULK,
|
||||
.endpoint = 0x06,
|
||||
.direction = UE_DIR_OUT,
|
||||
@ -242,23 +247,10 @@ static const struct usb_config rsu_config[RSU_N_TRANSFER] = {
|
||||
.pipe_bof = 1,
|
||||
.force_short_xfer = 1
|
||||
},
|
||||
.callback = rsu_bulk_tx_callback_0,
|
||||
.callback = rsu_bulk_tx_callback_be_bk,
|
||||
.timeout = RSU_TX_TIMEOUT
|
||||
},
|
||||
[RSU_BULK_TX_BK] = {
|
||||
.type = UE_BULK,
|
||||
.endpoint = 0x06,
|
||||
.direction = UE_DIR_OUT,
|
||||
.bufsize = RSU_TXBUFSZ,
|
||||
.flags = {
|
||||
.ext_buffer = 1,
|
||||
.pipe_bof = 1,
|
||||
.force_short_xfer = 1
|
||||
},
|
||||
.callback = rsu_bulk_tx_callback_1,
|
||||
.timeout = RSU_TX_TIMEOUT
|
||||
},
|
||||
[RSU_BULK_TX_VI] = {
|
||||
[RSU_BULK_TX_VI_VO] = {
|
||||
.type = UE_BULK,
|
||||
.endpoint = 0x04,
|
||||
.direction = UE_DIR_OUT,
|
||||
@ -268,20 +260,7 @@ static const struct usb_config rsu_config[RSU_N_TRANSFER] = {
|
||||
.pipe_bof = 1,
|
||||
.force_short_xfer = 1
|
||||
},
|
||||
.callback = rsu_bulk_tx_callback_2,
|
||||
.timeout = RSU_TX_TIMEOUT
|
||||
},
|
||||
[RSU_BULK_TX_VO] = {
|
||||
.type = UE_BULK,
|
||||
.endpoint = 0x04,
|
||||
.direction = UE_DIR_OUT,
|
||||
.bufsize = RSU_TXBUFSZ,
|
||||
.flags = {
|
||||
.ext_buffer = 1,
|
||||
.pipe_bof = 1,
|
||||
.force_short_xfer = 1
|
||||
},
|
||||
.callback = rsu_bulk_tx_callback_3,
|
||||
.callback = rsu_bulk_tx_callback_vi_vo,
|
||||
.timeout = RSU_TX_TIMEOUT
|
||||
},
|
||||
};
|
||||
@ -613,7 +592,7 @@ rsu_alloc_tx_list(struct rsu_softc *sc)
|
||||
|
||||
STAILQ_INIT(&sc->sc_tx_inactive);
|
||||
|
||||
for (i = 0; i != RSU_MAX_TX_EP; i++) {
|
||||
for (i = 0; i != RSU_N_TRANSFER; i++) {
|
||||
STAILQ_INIT(&sc->sc_tx_active[i]);
|
||||
STAILQ_INIT(&sc->sc_tx_pending[i]);
|
||||
}
|
||||
@ -633,7 +612,7 @@ rsu_free_tx_list(struct rsu_softc *sc)
|
||||
/* prevent further allocations from TX list(s) */
|
||||
STAILQ_INIT(&sc->sc_tx_inactive);
|
||||
|
||||
for (i = 0; i != RSU_MAX_TX_EP; i++) {
|
||||
for (i = 0; i != RSU_N_TRANSFER; i++) {
|
||||
STAILQ_INIT(&sc->sc_tx_active[i]);
|
||||
STAILQ_INIT(&sc->sc_tx_pending[i]);
|
||||
}
|
||||
@ -873,7 +852,7 @@ rsu_read_rom(struct rsu_softc *sc)
|
||||
static int
|
||||
rsu_fw_cmd(struct rsu_softc *sc, uint8_t code, void *buf, int len)
|
||||
{
|
||||
const uint8_t which = RSU_BULK_TX_VO - RSU_BULK_TX_BE;
|
||||
const uint8_t which = rsu_wme_ac_xfer_map[WME_AC_VO];
|
||||
struct rsu_data *data;
|
||||
struct r92s_tx_desc *txd;
|
||||
struct r92s_fw_cmd_hdr *cmd;
|
||||
@ -912,7 +891,7 @@ rsu_fw_cmd(struct rsu_softc *sc, uint8_t code, void *buf, int len)
|
||||
DPRINTFN(2, "Tx cmd code=0x%x len=0x%x\n", code, cmdsz);
|
||||
data->buflen = xferlen;
|
||||
STAILQ_INSERT_TAIL(&sc->sc_tx_pending[which], data, next);
|
||||
usbd_transfer_start(sc->sc_xfer[which + RSU_BULK_TX_BE]);
|
||||
usbd_transfer_start(sc->sc_xfer[which]);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -925,6 +904,7 @@ rsu_calib_task(void *arg, int pending __unused)
|
||||
uint32_t reg;
|
||||
|
||||
DPRINTFN(6, "running calibration task\n");
|
||||
|
||||
RSU_LOCK(sc);
|
||||
#ifdef notyet
|
||||
/* Read WPS PBC status. */
|
||||
@ -941,12 +921,9 @@ rsu_calib_task(void *arg, int pending __unused)
|
||||
reg = rsu_read_4(sc, R92S_IOCMD_DATA);
|
||||
DPRINTFN(8, "RSSI=%d%%\n", reg >> 4);
|
||||
}
|
||||
if (sc->sc_calibrating) {
|
||||
RSU_UNLOCK(sc);
|
||||
taskqueue_enqueue_timeout(taskqueue_thread, &sc->calib_task,
|
||||
hz * 2);
|
||||
} else
|
||||
RSU_UNLOCK(sc);
|
||||
if (sc->sc_calibrating)
|
||||
taskqueue_enqueue_timeout(taskqueue_thread, &sc->calib_task, hz);
|
||||
RSU_UNLOCK(sc);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1000,11 +977,10 @@ rsu_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
break;
|
||||
}
|
||||
sc->sc_calibrating = 1;
|
||||
/* Start periodic calibration. */
|
||||
taskqueue_enqueue_timeout(taskqueue_thread, &sc->calib_task, hz);
|
||||
RSU_UNLOCK(sc);
|
||||
IEEE80211_LOCK(ic);
|
||||
/* Start periodic calibration. */
|
||||
taskqueue_enqueue_timeout(taskqueue_thread, &sc->calib_task, hz * 2);
|
||||
|
||||
return (uvp->newstate(vap, nstate, arg));
|
||||
}
|
||||
|
||||
@ -1080,7 +1056,8 @@ rsu_join_bss(struct rsu_softc *sc, struct ieee80211_node *ni)
|
||||
struct ndis_wlan_bssid_ex *bss;
|
||||
struct ndis_802_11_fixed_ies *fixed;
|
||||
struct r92s_fw_cmd_auth auth;
|
||||
uint8_t buf[sizeof(*bss) + 128], *frm;
|
||||
uint8_t buf[sizeof(*bss) + 128] __aligned(4);
|
||||
uint8_t *frm;
|
||||
uint8_t opmode;
|
||||
int error;
|
||||
|
||||
@ -1094,7 +1071,7 @@ rsu_join_bss(struct rsu_softc *sc, struct ieee80211_node *ni)
|
||||
memset(&auth, 0, sizeof(auth));
|
||||
if (vap->iv_flags & IEEE80211_F_WPA) {
|
||||
auth.mode = R92S_AUTHMODE_WPA;
|
||||
auth.dot1x = ni->ni_authmode == IEEE80211_AUTH_8021X;
|
||||
auth.dot1x = (ni->ni_authmode == IEEE80211_AUTH_8021X);
|
||||
} else
|
||||
auth.mode = R92S_AUTHMODE_OPEN;
|
||||
DPRINTF("setting auth mode to %d\n", auth.mode);
|
||||
@ -1222,6 +1199,7 @@ rsu_event_join_bss(struct rsu_softc *sc, uint8_t *buf, int len)
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
struct ieee80211_node *ni = vap->iv_bss;
|
||||
struct r92s_event_join_bss *rsp;
|
||||
uint32_t tmp;
|
||||
int res;
|
||||
|
||||
if (__predict_false(len < sizeof(*rsp)))
|
||||
@ -1236,9 +1214,14 @@ rsu_event_join_bss(struct rsu_softc *sc, uint8_t *buf, int len)
|
||||
RSU_LOCK(sc);
|
||||
return;
|
||||
}
|
||||
tmp = le32toh(rsp->associd);
|
||||
if (tmp >= vap->iv_max_aid) {
|
||||
DPRINTF("Assoc ID overflow\n");
|
||||
tmp = 1;
|
||||
}
|
||||
DPRINTF("associated with %s associd=%d\n",
|
||||
ether_sprintf(rsp->bss.macaddr), le32toh(rsp->associd));
|
||||
ni->ni_associd = le32toh(rsp->associd) | 0xc000;
|
||||
ether_sprintf(rsp->bss.macaddr), tmp);
|
||||
ni->ni_associd = tmp | 0xc000;
|
||||
RSU_UNLOCK(sc);
|
||||
ieee80211_new_state(vap, IEEE80211_S_RUN,
|
||||
IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
|
||||
@ -1277,6 +1260,9 @@ rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
|
||||
if (vap->iv_state == IEEE80211_S_AUTH)
|
||||
rsu_event_join_bss(sc, buf, len);
|
||||
break;
|
||||
#if 0
|
||||
XXX This event is occurring regularly, possibly due to some power saving event
|
||||
XXX and disrupts the WLAN traffic. Disable for now.
|
||||
case R92S_EVT_DEL_STA:
|
||||
DPRINTF("disassociated from %s\n", ether_sprintf(buf));
|
||||
if (vap->iv_state == IEEE80211_S_RUN &&
|
||||
@ -1286,6 +1272,7 @@ rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
|
||||
RSU_LOCK(sc);
|
||||
}
|
||||
break;
|
||||
#endif
|
||||
case R92S_EVT_WPS_PBC:
|
||||
DPRINTF("WPS PBC pushed.\n");
|
||||
break;
|
||||
@ -1295,6 +1282,8 @@ rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
|
||||
printf("FWDBG: %s\n", (char *)buf);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -1676,27 +1665,15 @@ tr_setup:
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_bulk_tx_callback_0(struct usb_xfer *xfer, usb_error_t error)
|
||||
rsu_bulk_tx_callback_be_bk(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
rsu_bulk_tx_callback_sub(xfer, error, 0);
|
||||
rsu_bulk_tx_callback_sub(xfer, error, RSU_BULK_TX_BE_BK);
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_bulk_tx_callback_1(struct usb_xfer *xfer, usb_error_t error)
|
||||
rsu_bulk_tx_callback_vi_vo(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
rsu_bulk_tx_callback_sub(xfer, error, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_bulk_tx_callback_2(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
rsu_bulk_tx_callback_sub(xfer, error, 2);
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_bulk_tx_callback_3(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
rsu_bulk_tx_callback_sub(xfer, error, 3);
|
||||
rsu_bulk_tx_callback_sub(xfer, error, RSU_BULK_TX_VI_VO);
|
||||
}
|
||||
|
||||
static int
|
||||
@ -1734,12 +1711,10 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
|
||||
switch (type) {
|
||||
case IEEE80211_FC0_TYPE_CTL:
|
||||
case IEEE80211_FC0_TYPE_MGT:
|
||||
which = RSU_BULK_TX_VO - RSU_BULK_TX_BE;
|
||||
which = rsu_wme_ac_xfer_map[WME_AC_VO];
|
||||
break;
|
||||
default:
|
||||
which = M_WME_GETAC(m0);
|
||||
KASSERT(which < RSU_MAX_TX_EP,
|
||||
("unsupported WME pipe %d", which));
|
||||
which = rsu_wme_ac_xfer_map[M_WME_GETAC(m0)];
|
||||
break;
|
||||
}
|
||||
hasqos = 0;
|
||||
@ -1804,7 +1779,7 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
|
||||
STAILQ_INSERT_TAIL(&sc->sc_tx_pending[which], data, next);
|
||||
|
||||
/* start transfer, if any */
|
||||
usbd_transfer_start(sc->sc_xfer[which + RSU_BULK_TX_BE]);
|
||||
usbd_transfer_start(sc->sc_xfer[which]);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -2119,7 +2094,7 @@ rsu_power_off(struct rsu_softc *sc)
|
||||
static int
|
||||
rsu_fw_loadsection(struct rsu_softc *sc, const uint8_t *buf, int len)
|
||||
{
|
||||
const uint8_t which = RSU_BULK_TX_VO - RSU_BULK_TX_BE;
|
||||
const uint8_t which = rsu_wme_ac_xfer_map[WME_AC_VO];
|
||||
struct rsu_data *data;
|
||||
struct r92s_tx_desc *txd;
|
||||
int mlen;
|
||||
@ -2144,7 +2119,7 @@ rsu_fw_loadsection(struct rsu_softc *sc, const uint8_t *buf, int len)
|
||||
buf += mlen;
|
||||
len -= mlen;
|
||||
}
|
||||
usbd_transfer_start(sc->sc_xfer[RSU_BULK_TX_BE + which]);
|
||||
usbd_transfer_start(sc->sc_xfer[which]);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -2160,6 +2135,11 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
uint32_t reg;
|
||||
int ntries, error;
|
||||
|
||||
if (rsu_read_1(sc, R92S_TCR) & R92S_TCR_FWRDY) {
|
||||
DPRINTF("Firmware already loaded\n");
|
||||
return (0);
|
||||
}
|
||||
|
||||
RSU_UNLOCK(sc);
|
||||
/* Read firmware image from the filesystem. */
|
||||
if ((fw = firmware_get("rsu-rtl8712fw")) == NULL) {
|
||||
@ -2216,7 +2196,7 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
/* Wait for load to complete. */
|
||||
for (ntries = 0; ntries != 50; ntries++) {
|
||||
usb_pause_mtx(&sc->sc_mtx, hz / 100);
|
||||
reg = rsu_read_2(sc, R92S_TCR);
|
||||
reg = rsu_read_1(sc, R92S_TCR);
|
||||
if (reg & R92S_TCR_IMEM_CODE_DONE)
|
||||
break;
|
||||
}
|
||||
@ -2225,7 +2205,6 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
error = ETIMEDOUT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Load EMEM section. */
|
||||
error = rsu_fw_loadsection(sc, emem, ememsz);
|
||||
if (error != 0) {
|
||||
@ -2245,7 +2224,6 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
error = ETIMEDOUT;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* Enable CPU. */
|
||||
rsu_write_1(sc, R92S_SYS_CLKR,
|
||||
rsu_read_1(sc, R92S_SYS_CLKR) | R92S_SYS_CPU_CLKSEL);
|
||||
@ -2264,7 +2242,7 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
}
|
||||
/* Wait for CPU to initialize. */
|
||||
for (ntries = 0; ntries < 100; ntries++) {
|
||||
if (rsu_read_2(sc, R92S_TCR) & R92S_TCR_IMEM_RDY)
|
||||
if (rsu_read_1(sc, R92S_TCR) & R92S_TCR_IMEM_RDY)
|
||||
break;
|
||||
rsu_ms_delay(sc);
|
||||
}
|
||||
@ -2296,7 +2274,7 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
}
|
||||
/* Wait for load to complete. */
|
||||
for (ntries = 0; ntries < 100; ntries++) {
|
||||
if (rsu_read_2(sc, R92S_TCR) & R92S_TCR_DMEM_CODE_DONE)
|
||||
if (rsu_read_1(sc, R92S_TCR) & R92S_TCR_DMEM_CODE_DONE)
|
||||
break;
|
||||
rsu_ms_delay(sc);
|
||||
}
|
||||
@ -2308,7 +2286,7 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
}
|
||||
/* Wait for firmware readiness. */
|
||||
for (ntries = 0; ntries < 60; ntries++) {
|
||||
if (!(rsu_read_2(sc, R92S_TCR) & R92S_TCR_FWRDY))
|
||||
if (!(rsu_read_1(sc, R92S_TCR) & R92S_TCR_FWRDY))
|
||||
break;
|
||||
rsu_ms_delay(sc);
|
||||
}
|
||||
@ -2386,6 +2364,7 @@ rsu_init_locked(struct rsu_softc *sc)
|
||||
rsu_power_on_acut(sc);
|
||||
else
|
||||
rsu_power_on_bcut(sc);
|
||||
|
||||
/* Load firmware. */
|
||||
error = rsu_load_firmware(sc);
|
||||
if (error != 0)
|
||||
|
@ -698,11 +698,9 @@ struct rsu_host_cmd_ring {
|
||||
|
||||
enum {
|
||||
RSU_BULK_RX,
|
||||
RSU_BULK_TX_BE, /* = WME_AC_BE */
|
||||
RSU_BULK_TX_BK, /* = WME_AC_BK */
|
||||
RSU_BULK_TX_VI, /* = WME_AC_VI */
|
||||
RSU_BULK_TX_VO, /* = WME_AC_VI */
|
||||
RSU_N_TRANSFER = 5,
|
||||
RSU_BULK_TX_BE_BK, /* = WME_AC_BE/BK */
|
||||
RSU_BULK_TX_VI_VO, /* = WME_AC_VI/VO */
|
||||
RSU_N_TRANSFER,
|
||||
};
|
||||
|
||||
struct rsu_data {
|
||||
@ -727,8 +725,6 @@ struct rsu_vap {
|
||||
#define RSU_UNLOCK(sc) mtx_unlock(&(sc)->sc_mtx)
|
||||
#define RSU_ASSERT_LOCKED(sc) mtx_assert(&(sc)->sc_mtx, MA_OWNED)
|
||||
|
||||
#define RSU_MAX_TX_EP 4
|
||||
|
||||
struct rsu_softc {
|
||||
struct ifnet *sc_ifp;
|
||||
device_t sc_dev;
|
||||
@ -754,9 +750,9 @@ struct rsu_softc {
|
||||
|
||||
STAILQ_HEAD(, rsu_data) sc_rx_active;
|
||||
STAILQ_HEAD(, rsu_data) sc_rx_inactive;
|
||||
STAILQ_HEAD(, rsu_data) sc_tx_active[RSU_MAX_TX_EP];
|
||||
STAILQ_HEAD(, rsu_data) sc_tx_active[RSU_N_TRANSFER];
|
||||
STAILQ_HEAD(, rsu_data) sc_tx_inactive;
|
||||
STAILQ_HEAD(, rsu_data) sc_tx_pending[RSU_MAX_TX_EP];
|
||||
STAILQ_HEAD(, rsu_data) sc_tx_pending[RSU_N_TRANSFER];
|
||||
|
||||
union {
|
||||
struct rsu_rx_radiotap_header th;
|
||||
|
Loading…
x
Reference in New Issue
Block a user