MFC r266466, r266471, r266484, r266505, r266535 and r266542:
Fix multiple issues in the RSU driver.
This commit is contained in:
parent
6e5f8e9e85
commit
a2758dea62
@ -127,7 +127,10 @@ 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;
|
||||
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_rx_callback;
|
||||
static usb_error_t rsu_do_request(struct rsu_softc *,
|
||||
struct usb_device_request *, void *);
|
||||
@ -186,7 +189,6 @@ static int rsu_raw_xmit(struct ieee80211_node *, struct mbuf *,
|
||||
const struct ieee80211_bpf_params *);
|
||||
static void rsu_init(void *);
|
||||
static void rsu_init_locked(struct rsu_softc *);
|
||||
static void rsu_watchdog(void *);
|
||||
static int rsu_tx_start(struct rsu_softc *, struct ieee80211_node *,
|
||||
struct mbuf *, struct rsu_data *);
|
||||
static void rsu_start(struct ifnet *);
|
||||
@ -194,6 +196,7 @@ static void rsu_start_locked(struct ifnet *);
|
||||
static int rsu_ioctl(struct ifnet *, u_long, caddr_t);
|
||||
static void rsu_stop(struct ifnet *, int);
|
||||
static void rsu_stop_locked(struct ifnet *, int);
|
||||
static void rsu_ms_delay(struct rsu_softc *);
|
||||
|
||||
static device_method_t rsu_methods[] = {
|
||||
DEVMETHOD(device_probe, rsu_match),
|
||||
@ -239,7 +242,7 @@ static const struct usb_config rsu_config[RSU_N_TRANSFER] = {
|
||||
.pipe_bof = 1,
|
||||
.force_short_xfer = 1
|
||||
},
|
||||
.callback = rsu_bulk_tx_callback,
|
||||
.callback = rsu_bulk_tx_callback_0,
|
||||
.timeout = RSU_TX_TIMEOUT
|
||||
},
|
||||
[RSU_BULK_TX_BK] = {
|
||||
@ -252,7 +255,7 @@ static const struct usb_config rsu_config[RSU_N_TRANSFER] = {
|
||||
.pipe_bof = 1,
|
||||
.force_short_xfer = 1
|
||||
},
|
||||
.callback = rsu_bulk_tx_callback,
|
||||
.callback = rsu_bulk_tx_callback_1,
|
||||
.timeout = RSU_TX_TIMEOUT
|
||||
},
|
||||
[RSU_BULK_TX_VI] = {
|
||||
@ -265,7 +268,7 @@ static const struct usb_config rsu_config[RSU_N_TRANSFER] = {
|
||||
.pipe_bof = 1,
|
||||
.force_short_xfer = 1
|
||||
},
|
||||
.callback = rsu_bulk_tx_callback,
|
||||
.callback = rsu_bulk_tx_callback_2,
|
||||
.timeout = RSU_TX_TIMEOUT
|
||||
},
|
||||
[RSU_BULK_TX_VO] = {
|
||||
@ -278,7 +281,7 @@ static const struct usb_config rsu_config[RSU_N_TRANSFER] = {
|
||||
.pipe_bof = 1,
|
||||
.force_short_xfer = 1
|
||||
},
|
||||
.callback = rsu_bulk_tx_callback,
|
||||
.callback = rsu_bulk_tx_callback_3,
|
||||
.timeout = RSU_TX_TIMEOUT
|
||||
},
|
||||
};
|
||||
@ -314,7 +317,20 @@ rsu_attach(device_t self)
|
||||
MTX_DEF);
|
||||
TIMEOUT_TASK_INIT(taskqueue_thread, &sc->calib_task, 0,
|
||||
rsu_calib_task, sc);
|
||||
callout_init(&sc->sc_watchdog_ch, 0);
|
||||
|
||||
/* Allocate Tx/Rx buffers. */
|
||||
error = rsu_alloc_rx_list(sc);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not allocate Rx buffers\n");
|
||||
goto fail_usb;
|
||||
}
|
||||
|
||||
error = rsu_alloc_tx_list(sc);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not allocate Tx buffers\n");
|
||||
rsu_free_rx_list(sc);
|
||||
goto fail_usb;
|
||||
}
|
||||
|
||||
iface_index = 0;
|
||||
error = usbd_transfer_setup(uaa->device, &iface_index, sc->sc_xfer,
|
||||
@ -422,13 +438,10 @@ rsu_detach(device_t self)
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct ieee80211com *ic = ifp->if_l2com;
|
||||
|
||||
if (!device_is_attached(self))
|
||||
return (0);
|
||||
rsu_stop(ifp, 1);
|
||||
usbd_transfer_unsetup(sc->sc_xfer, RSU_N_TRANSFER);
|
||||
ieee80211_ifdetach(ic);
|
||||
|
||||
callout_drain(&sc->sc_watchdog_ch);
|
||||
taskqueue_drain_timeout(taskqueue_thread, &sc->calib_task);
|
||||
|
||||
/* Free Tx/Rx buffers. */
|
||||
@ -453,7 +466,7 @@ rsu_do_request(struct rsu_softc *sc, struct usb_device_request *req,
|
||||
while (ntries--) {
|
||||
err = usbd_do_request_flags(sc->sc_udev, &sc->sc_mtx,
|
||||
req, data, 0, NULL, 250 /* ms */);
|
||||
if (err == 0 || !device_is_attached(sc->sc_dev))
|
||||
if (err == 0 || err == USB_ERR_NOT_CONFIGURED)
|
||||
break;
|
||||
DPRINTFN(1, "Control request failed, %s (retrying)\n",
|
||||
usbd_errstr(err));
|
||||
@ -598,9 +611,12 @@ rsu_alloc_tx_list(struct rsu_softc *sc)
|
||||
if (error != 0)
|
||||
return (error);
|
||||
|
||||
STAILQ_INIT(&sc->sc_tx_active);
|
||||
STAILQ_INIT(&sc->sc_tx_inactive);
|
||||
STAILQ_INIT(&sc->sc_tx_pending);
|
||||
|
||||
for (i = 0; i != RSU_MAX_TX_EP; i++) {
|
||||
STAILQ_INIT(&sc->sc_tx_active[i]);
|
||||
STAILQ_INIT(&sc->sc_tx_pending[i]);
|
||||
}
|
||||
|
||||
for (i = 0; i < RSU_TX_LIST_COUNT; i++) {
|
||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, &sc->sc_tx[i], next);
|
||||
@ -612,12 +628,26 @@ rsu_alloc_tx_list(struct rsu_softc *sc)
|
||||
static void
|
||||
rsu_free_tx_list(struct rsu_softc *sc)
|
||||
{
|
||||
int i;
|
||||
|
||||
/* prevent further allocations from TX list(s) */
|
||||
STAILQ_INIT(&sc->sc_tx_inactive);
|
||||
|
||||
for (i = 0; i != RSU_MAX_TX_EP; i++) {
|
||||
STAILQ_INIT(&sc->sc_tx_active[i]);
|
||||
STAILQ_INIT(&sc->sc_tx_pending[i]);
|
||||
}
|
||||
|
||||
rsu_free_list(sc, sc->sc_tx, RSU_TX_LIST_COUNT);
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_free_rx_list(struct rsu_softc *sc)
|
||||
{
|
||||
/* prevent further allocations from RX list(s) */
|
||||
STAILQ_INIT(&sc->sc_rx_inactive);
|
||||
STAILQ_INIT(&sc->sc_rx_active);
|
||||
|
||||
rsu_free_list(sc, sc->sc_rx, RSU_RX_LIST_COUNT);
|
||||
}
|
||||
|
||||
@ -757,11 +787,11 @@ rsu_fw_iocmd(struct rsu_softc *sc, uint32_t iocmd)
|
||||
int ntries;
|
||||
|
||||
rsu_write_4(sc, R92S_IOCMD_CTRL, iocmd);
|
||||
DELAY(100);
|
||||
rsu_ms_delay(sc);
|
||||
for (ntries = 0; ntries < 50; ntries++) {
|
||||
if (rsu_read_4(sc, R92S_IOCMD_CTRL) == 0)
|
||||
return (0);
|
||||
DELAY(10);
|
||||
rsu_ms_delay(sc);
|
||||
}
|
||||
return (ETIMEDOUT);
|
||||
}
|
||||
@ -781,7 +811,7 @@ rsu_efuse_read_1(struct rsu_softc *sc, uint16_t addr)
|
||||
reg = rsu_read_4(sc, R92S_EFUSE_CTRL);
|
||||
if (reg & R92S_EFUSE_CTRL_VALID)
|
||||
return (MS(reg, R92S_EFUSE_CTRL_DATA));
|
||||
DELAY(5);
|
||||
rsu_ms_delay(sc);
|
||||
}
|
||||
device_printf(sc->sc_dev,
|
||||
"could not read efuse byte at address 0x%x\n", addr);
|
||||
@ -805,7 +835,7 @@ rsu_read_rom(struct rsu_softc *sc)
|
||||
/* Turn on 2.5V to prevent eFuse leakage. */
|
||||
reg = rsu_read_1(sc, R92S_EFUSE_TEST + 3);
|
||||
rsu_write_1(sc, R92S_EFUSE_TEST + 3, reg | 0x80);
|
||||
DELAY(1000);
|
||||
rsu_ms_delay(sc);
|
||||
rsu_write_1(sc, R92S_EFUSE_TEST + 3, reg & ~0x80);
|
||||
|
||||
/* Read full ROM image. */
|
||||
@ -843,10 +873,12 @@ 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;
|
||||
struct rsu_data *data;
|
||||
struct r92s_tx_desc *txd;
|
||||
struct r92s_fw_cmd_hdr *cmd;
|
||||
int cmdsz, xferlen;
|
||||
int cmdsz;
|
||||
int xferlen;
|
||||
|
||||
data = rsu_getbuf(sc);
|
||||
if (data == NULL)
|
||||
@ -879,8 +911,8 @@ 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, data, next);
|
||||
usbd_transfer_start(sc->sc_xfer[RSU_BULK_TX_VO]);
|
||||
STAILQ_INSERT_TAIL(&sc->sc_tx_pending[which], data, next);
|
||||
usbd_transfer_start(sc->sc_xfer[which + RSU_BULK_TX_BE]);
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -1589,13 +1621,13 @@ rsu_txeof(struct usb_xfer *xfer, struct rsu_data *data)
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
}
|
||||
sc->sc_tx_timer = 0;
|
||||
ifp->if_opackets++;
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
rsu_bulk_tx_callback_sub(struct usb_xfer *xfer, usb_error_t error,
|
||||
uint8_t which)
|
||||
{
|
||||
struct rsu_softc *sc = usbd_xfer_softc(xfer);
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
@ -1605,37 +1637,36 @@ rsu_bulk_tx_callback(struct usb_xfer *xfer, usb_error_t error)
|
||||
|
||||
switch (USB_GET_STATE(xfer)) {
|
||||
case USB_ST_TRANSFERRED:
|
||||
data = STAILQ_FIRST(&sc->sc_tx_active);
|
||||
data = STAILQ_FIRST(&sc->sc_tx_active[which]);
|
||||
if (data == NULL)
|
||||
goto tr_setup;
|
||||
DPRINTF("transfer done %p\n", data);
|
||||
STAILQ_REMOVE_HEAD(&sc->sc_tx_active, next);
|
||||
STAILQ_REMOVE_HEAD(&sc->sc_tx_active[which], next);
|
||||
rsu_txeof(xfer, data);
|
||||
STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next);
|
||||
/* FALLTHROUGH */
|
||||
case USB_ST_SETUP:
|
||||
tr_setup:
|
||||
data = STAILQ_FIRST(&sc->sc_tx_pending);
|
||||
data = STAILQ_FIRST(&sc->sc_tx_pending[which]);
|
||||
if (data == NULL) {
|
||||
DPRINTF("empty pending queue sc %p\n", sc);
|
||||
return;
|
||||
}
|
||||
STAILQ_REMOVE_HEAD(&sc->sc_tx_pending, next);
|
||||
STAILQ_INSERT_TAIL(&sc->sc_tx_active, data, next);
|
||||
STAILQ_REMOVE_HEAD(&sc->sc_tx_pending[which], next);
|
||||
STAILQ_INSERT_TAIL(&sc->sc_tx_active[which], data, next);
|
||||
usbd_xfer_set_frame_data(xfer, 0, data->buf, data->buflen);
|
||||
DPRINTF("submitting transfer %p\n", data);
|
||||
usbd_transfer_submit(xfer);
|
||||
rsu_start_locked(ifp);
|
||||
break;
|
||||
default:
|
||||
data = STAILQ_FIRST(&sc->sc_tx_active);
|
||||
if (data == NULL)
|
||||
goto tr_setup;
|
||||
if (data->ni != NULL) {
|
||||
ieee80211_free_node(data->ni);
|
||||
data->ni = NULL;
|
||||
ifp->if_oerrors++;
|
||||
data = STAILQ_FIRST(&sc->sc_tx_active[which]);
|
||||
if (data != NULL) {
|
||||
STAILQ_REMOVE_HEAD(&sc->sc_tx_active[which], next);
|
||||
rsu_txeof(xfer, data);
|
||||
STAILQ_INSERT_TAIL(&sc->sc_tx_inactive, data, next);
|
||||
}
|
||||
ifp->if_oerrors++;
|
||||
|
||||
if (error != USB_ERR_CANCELLED) {
|
||||
usbd_xfer_set_stall(xfer);
|
||||
goto tr_setup;
|
||||
@ -1644,6 +1675,30 @@ tr_setup:
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_bulk_tx_callback_0(struct usb_xfer *xfer, usb_error_t error)
|
||||
{
|
||||
rsu_bulk_tx_callback_sub(xfer, error, 0);
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_bulk_tx_callback_1(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);
|
||||
}
|
||||
|
||||
static int
|
||||
rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
|
||||
struct mbuf *m0, struct rsu_data *data)
|
||||
@ -1654,15 +1709,11 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
|
||||
struct ieee80211_frame *wh;
|
||||
struct ieee80211_key *k = NULL;
|
||||
struct r92s_tx_desc *txd;
|
||||
struct usb_xfer *xfer;
|
||||
uint8_t type, tid = 0;
|
||||
int hasqos, xferlen;
|
||||
struct usb_xfer *rsu_pipes[4] = {
|
||||
sc->sc_xfer[RSU_BULK_TX_BE],
|
||||
sc->sc_xfer[RSU_BULK_TX_BK],
|
||||
sc->sc_xfer[RSU_BULK_TX_VI],
|
||||
sc->sc_xfer[RSU_BULK_TX_VO]
|
||||
};
|
||||
uint8_t type;
|
||||
uint8_t tid = 0;
|
||||
uint8_t which;
|
||||
int hasqos;
|
||||
int xferlen;
|
||||
|
||||
RSU_ASSERT_LOCKED(sc);
|
||||
|
||||
@ -1683,12 +1734,12 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
|
||||
switch (type) {
|
||||
case IEEE80211_FC0_TYPE_CTL:
|
||||
case IEEE80211_FC0_TYPE_MGT:
|
||||
xfer = sc->sc_xfer[RSU_BULK_TX_VO];
|
||||
which = RSU_BULK_TX_VO - RSU_BULK_TX_BE;
|
||||
break;
|
||||
default:
|
||||
KASSERT(M_WME_GETAC(m0) < 4,
|
||||
("unsupported WME pipe %d", M_WME_GETAC(m0)));
|
||||
xfer = rsu_pipes[M_WME_GETAC(m0)];
|
||||
which = M_WME_GETAC(m0);
|
||||
KASSERT(which < RSU_MAX_TX_EP,
|
||||
("unsupported WME pipe %d", which));
|
||||
break;
|
||||
}
|
||||
hasqos = 0;
|
||||
@ -1750,9 +1801,10 @@ rsu_tx_start(struct rsu_softc *sc, struct ieee80211_node *ni,
|
||||
data->buflen = xferlen;
|
||||
data->ni = ni;
|
||||
data->m = m0;
|
||||
STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next);
|
||||
usbd_transfer_start(xfer);
|
||||
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]);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -1774,8 +1826,8 @@ rsu_start_locked(struct ifnet *ifp)
|
||||
{
|
||||
struct rsu_softc *sc = ifp->if_softc;
|
||||
struct ieee80211_node *ni;
|
||||
struct mbuf *m;
|
||||
struct rsu_data *bf;
|
||||
struct mbuf *m;
|
||||
|
||||
RSU_ASSERT_LOCKED(sc);
|
||||
|
||||
@ -1783,39 +1835,19 @@ rsu_start_locked(struct ifnet *ifp)
|
||||
IFQ_DRV_DEQUEUE(&ifp->if_snd, m);
|
||||
if (m == NULL)
|
||||
break;
|
||||
bf = rsu_getbuf(sc);
|
||||
if (bf == NULL) {
|
||||
IFQ_DRV_PREPEND(&ifp->if_snd, m);
|
||||
break;
|
||||
}
|
||||
ni = (struct ieee80211_node *)m->m_pkthdr.rcvif;
|
||||
m->m_pkthdr.rcvif = NULL;
|
||||
|
||||
if (rsu_tx_start(sc, ni, m, bf) != 0) {
|
||||
bf = rsu_getbuf(sc);
|
||||
if (bf == NULL) {
|
||||
ifp->if_iqdrops++;
|
||||
m_freem(m);
|
||||
ieee80211_free_node(ni);
|
||||
} else if (rsu_tx_start(sc, ni, m, bf) != 0) {
|
||||
ifp->if_oerrors++;
|
||||
STAILQ_INSERT_HEAD(&sc->sc_tx_inactive, bf, next);
|
||||
ieee80211_free_node(ni);
|
||||
break;
|
||||
}
|
||||
sc->sc_tx_timer = 5;
|
||||
callout_reset(&sc->sc_watchdog_ch, hz, rsu_watchdog, sc);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_watchdog(void *arg)
|
||||
{
|
||||
struct rsu_softc *sc = arg;
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
|
||||
if (sc->sc_tx_timer > 0) {
|
||||
if (--sc->sc_tx_timer == 0) {
|
||||
device_printf(sc->sc_dev, "device timeout\n");
|
||||
/* rsu_init(ifp); XXX needs a process context! */
|
||||
ifp->if_oerrors++;
|
||||
return;
|
||||
}
|
||||
callout_reset(&sc->sc_watchdog_ch, hz, rsu_watchdog, sc);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1947,7 +1979,7 @@ rsu_power_on_bcut(struct rsu_softc *sc)
|
||||
|
||||
/* Prevent eFuse leakage. */
|
||||
rsu_write_1(sc, 0x37, 0xb0);
|
||||
usb_pause_mtx(&sc->sc_mtx, 10);
|
||||
usb_pause_mtx(&sc->sc_mtx, hz / 100);
|
||||
rsu_write_1(sc, 0x37, 0x30);
|
||||
|
||||
/* Switch the control path to hardware. */
|
||||
@ -1958,7 +1990,7 @@ rsu_power_on_bcut(struct rsu_softc *sc)
|
||||
}
|
||||
rsu_write_1(sc, R92S_SYS_FUNC_EN + 1,
|
||||
rsu_read_1(sc, R92S_SYS_FUNC_EN + 1) & ~0x8c);
|
||||
DELAY(1000);
|
||||
rsu_ms_delay(sc);
|
||||
|
||||
rsu_write_1(sc, R92S_SPS0_CTRL + 1, 0x53);
|
||||
rsu_write_1(sc, R92S_SPS0_CTRL + 0, 0x57);
|
||||
@ -1991,11 +2023,11 @@ rsu_power_on_bcut(struct rsu_softc *sc)
|
||||
/* Enable AFE PLL macro block. */
|
||||
reg = rsu_read_1(sc, R92S_AFE_PLL_CTRL);
|
||||
rsu_write_1(sc, R92S_AFE_PLL_CTRL, reg | 0x11);
|
||||
DELAY(500);
|
||||
rsu_ms_delay(sc);
|
||||
rsu_write_1(sc, R92S_AFE_PLL_CTRL, reg | 0x51);
|
||||
DELAY(500);
|
||||
rsu_ms_delay(sc);
|
||||
rsu_write_1(sc, R92S_AFE_PLL_CTRL, reg | 0x11);
|
||||
DELAY(500);
|
||||
rsu_ms_delay(sc);
|
||||
|
||||
/* Attach AFE PLL to MACTOP/BB. */
|
||||
rsu_write_1(sc, R92S_SYS_ISO_CTRL,
|
||||
@ -2042,14 +2074,14 @@ rsu_power_on_bcut(struct rsu_softc *sc)
|
||||
if ((reg & (R92S_TCR_IMEM_CHK_RPT | R92S_TCR_EMEM_CHK_RPT)) ==
|
||||
(R92S_TCR_IMEM_CHK_RPT | R92S_TCR_EMEM_CHK_RPT))
|
||||
break;
|
||||
DELAY(5);
|
||||
rsu_ms_delay(sc);
|
||||
}
|
||||
if (ntries == 20) {
|
||||
DPRINTF("TxDMA is not ready\n");
|
||||
/* Reset TxDMA. */
|
||||
reg = rsu_read_1(sc, R92S_CR);
|
||||
rsu_write_1(sc, R92S_CR, reg & ~R92S_CR_TXDMA_EN);
|
||||
DELAY(2);
|
||||
rsu_ms_delay(sc);
|
||||
rsu_write_1(sc, R92S_CR, reg | R92S_CR_TXDMA_EN);
|
||||
}
|
||||
}
|
||||
@ -2059,7 +2091,7 @@ rsu_power_off(struct rsu_softc *sc)
|
||||
{
|
||||
/* Turn RF off. */
|
||||
rsu_write_1(sc, R92S_RF_CTRL, 0x00);
|
||||
usb_pause_mtx(&sc->sc_mtx, 5);
|
||||
usb_pause_mtx(&sc->sc_mtx, hz / 200);
|
||||
|
||||
/* Turn MAC off. */
|
||||
/* Switch control path. */
|
||||
@ -2087,6 +2119,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;
|
||||
struct rsu_data *data;
|
||||
struct r92s_tx_desc *txd;
|
||||
int mlen;
|
||||
@ -2107,12 +2140,11 @@ rsu_fw_loadsection(struct rsu_softc *sc, const uint8_t *buf, int len)
|
||||
memcpy(&txd[1], buf, mlen);
|
||||
data->buflen = sizeof(*txd) + mlen;
|
||||
DPRINTF("starting transfer %p\n", data);
|
||||
STAILQ_INSERT_TAIL(&sc->sc_tx_pending, data, next);
|
||||
STAILQ_INSERT_TAIL(&sc->sc_tx_pending[which], data, next);
|
||||
buf += mlen;
|
||||
len -= mlen;
|
||||
}
|
||||
usbd_transfer_start(sc->sc_xfer[RSU_BULK_TX_VO]);
|
||||
|
||||
usbd_transfer_start(sc->sc_xfer[RSU_BULK_TX_BE + which]);
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -2182,15 +2214,14 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
goto fail;
|
||||
}
|
||||
/* Wait for load to complete. */
|
||||
for (ntries = 0; ntries < 10; ntries++) {
|
||||
usb_pause_mtx(&sc->sc_mtx, 10);
|
||||
for (ntries = 0; ntries != 50; ntries++) {
|
||||
usb_pause_mtx(&sc->sc_mtx, hz / 100);
|
||||
reg = rsu_read_2(sc, R92S_TCR);
|
||||
if (reg & R92S_TCR_IMEM_CODE_DONE)
|
||||
break;
|
||||
}
|
||||
if (ntries == 10 || !(reg & R92S_TCR_IMEM_CHK_RPT)) {
|
||||
device_printf(sc->sc_dev, "timeout waiting for %s transfer\n",
|
||||
"IMEM");
|
||||
if (ntries == 50) {
|
||||
device_printf(sc->sc_dev, "timeout waiting for IMEM transfer\n");
|
||||
error = ETIMEDOUT;
|
||||
goto fail;
|
||||
}
|
||||
@ -2203,15 +2234,14 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
goto fail;
|
||||
}
|
||||
/* Wait for load to complete. */
|
||||
for (ntries = 0; ntries < 10; ntries++) {
|
||||
usb_pause_mtx(&sc->sc_mtx, 10);
|
||||
for (ntries = 0; ntries != 50; ntries++) {
|
||||
usb_pause_mtx(&sc->sc_mtx, hz / 100);
|
||||
reg = rsu_read_2(sc, R92S_TCR);
|
||||
if (reg & R92S_TCR_EMEM_CODE_DONE)
|
||||
break;
|
||||
}
|
||||
if (ntries == 10 || !(reg & R92S_TCR_EMEM_CHK_RPT)) {
|
||||
device_printf(sc->sc_dev, "timeout waiting for %s transfer\n",
|
||||
"EMEM");
|
||||
if (ntries == 50) {
|
||||
device_printf(sc->sc_dev, "timeout waiting for EMEM transfer\n");
|
||||
error = ETIMEDOUT;
|
||||
goto fail;
|
||||
}
|
||||
@ -2236,7 +2266,7 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
for (ntries = 0; ntries < 100; ntries++) {
|
||||
if (rsu_read_2(sc, R92S_TCR) & R92S_TCR_IMEM_RDY)
|
||||
break;
|
||||
DELAY(1000);
|
||||
rsu_ms_delay(sc);
|
||||
}
|
||||
if (ntries == 100) {
|
||||
device_printf(sc->sc_dev,
|
||||
@ -2249,7 +2279,7 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
dmem = __DECONST(struct r92s_fw_priv *, &hdr->priv);
|
||||
memset(dmem, 0, sizeof(*dmem));
|
||||
dmem->hci_sel = R92S_HCI_SEL_USB | R92S_HCI_SEL_8172;
|
||||
dmem->nendpoints = sc->npipes;
|
||||
dmem->nendpoints = 0;
|
||||
dmem->rf_config = 0x12; /* 1T2R */
|
||||
dmem->vcs_type = R92S_VCS_TYPE_AUTO;
|
||||
dmem->vcs_mode = R92S_VCS_MODE_RTS_CTS;
|
||||
@ -2268,7 +2298,7 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
for (ntries = 0; ntries < 100; ntries++) {
|
||||
if (rsu_read_2(sc, R92S_TCR) & R92S_TCR_DMEM_CODE_DONE)
|
||||
break;
|
||||
DELAY(1000);
|
||||
rsu_ms_delay(sc);
|
||||
}
|
||||
if (ntries == 100) {
|
||||
device_printf(sc->sc_dev, "timeout waiting for %s transfer\n",
|
||||
@ -2280,7 +2310,7 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
for (ntries = 0; ntries < 60; ntries++) {
|
||||
if (!(rsu_read_2(sc, R92S_TCR) & R92S_TCR_FWRDY))
|
||||
break;
|
||||
DELAY(1000);
|
||||
rsu_ms_delay(sc);
|
||||
}
|
||||
if (ntries == 60) {
|
||||
device_printf(sc->sc_dev,
|
||||
@ -2326,7 +2356,6 @@ rsu_raw_xmit(struct ieee80211_node *ni, struct mbuf *m,
|
||||
return (EIO);
|
||||
}
|
||||
RSU_UNLOCK(sc);
|
||||
sc->sc_tx_timer = 5;
|
||||
|
||||
return (0);
|
||||
}
|
||||
@ -2347,22 +2376,11 @@ rsu_init_locked(struct rsu_softc *sc)
|
||||
struct ifnet *ifp = sc->sc_ifp;
|
||||
struct r92s_set_pwr_mode cmd;
|
||||
int error;
|
||||
int i;
|
||||
|
||||
/* Init host async commands ring. */
|
||||
sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
|
||||
|
||||
/* Allocate Tx/Rx buffers. */
|
||||
error = rsu_alloc_rx_list(sc);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not allocate Rx buffers\n");
|
||||
return;
|
||||
}
|
||||
error = rsu_alloc_tx_list(sc);
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not allocate Tx buffers\n");
|
||||
rsu_free_rx_list(sc);
|
||||
return;
|
||||
}
|
||||
/* Power on adapter. */
|
||||
if (sc->cut == 1)
|
||||
rsu_power_on_acut(sc);
|
||||
@ -2401,8 +2419,8 @@ rsu_init_locked(struct rsu_softc *sc)
|
||||
rsu_write_region_1(sc, R92S_MACID, IF_LLADDR(ifp),
|
||||
IEEE80211_ADDR_LEN);
|
||||
|
||||
/* NB: it really takes that long for firmware to boot. */
|
||||
usb_pause_mtx(&sc->sc_mtx, 1500);
|
||||
/* It really takes 1.5 seconds for the firmware to boot: */
|
||||
usb_pause_mtx(&sc->sc_mtx, (3 * hz) / 2);
|
||||
|
||||
DPRINTF("setting MAC address to %s\n", ether_sprintf(IF_LLADDR(ifp)));
|
||||
error = rsu_fw_cmd(sc, R92S_CMD_SET_MAC_ADDRESS, IF_LLADDR(ifp),
|
||||
@ -2447,14 +2465,11 @@ rsu_init_locked(struct rsu_softc *sc)
|
||||
/* We're ready to go. */
|
||||
ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
|
||||
ifp->if_drv_flags |= IFF_DRV_RUNNING;
|
||||
|
||||
callout_reset(&sc->sc_watchdog_ch, hz, rsu_watchdog, sc);
|
||||
|
||||
return;
|
||||
fail:
|
||||
rsu_free_rx_list(sc);
|
||||
rsu_free_tx_list(sc);
|
||||
return;
|
||||
/* Need to stop all failed transfers, if any */
|
||||
for (i = 0; i != RSU_N_TRANSFER; i++)
|
||||
usbd_transfer_stop(sc->sc_xfer[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -2474,7 +2489,6 @@ rsu_stop_locked(struct ifnet *ifp, int disable __unused)
|
||||
int i;
|
||||
|
||||
ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
|
||||
callout_stop(&sc->sc_watchdog_ch);
|
||||
sc->sc_calibrating = 0;
|
||||
taskqueue_cancel_timeout(taskqueue_thread, &sc->calib_task, NULL);
|
||||
|
||||
@ -2485,3 +2499,8 @@ rsu_stop_locked(struct ifnet *ifp, int disable __unused)
|
||||
usbd_transfer_stop(sc->sc_xfer[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
rsu_ms_delay(struct rsu_softc *sc)
|
||||
{
|
||||
usb_pause_mtx(&sc->sc_mtx, hz / 1000);
|
||||
}
|
||||
|
@ -1,4 +1,3 @@
|
||||
|
||||
/*-
|
||||
* Copyright (c) 2010 Damien Bergamini <damien.bergamini@free.fr>
|
||||
*
|
||||
@ -18,9 +17,6 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
/* Maximum number of pipes is 11. */
|
||||
#define R92S_MAX_EP 11
|
||||
|
||||
/* USB Requests. */
|
||||
#define R92S_REQ_REGS 0x05
|
||||
|
||||
@ -519,7 +515,7 @@ struct r92s_rx_stat {
|
||||
|
||||
uint32_t rxdw4;
|
||||
uint32_t rxdw5;
|
||||
} __packed __attribute__((aligned(4)));
|
||||
} __packed __aligned(4);
|
||||
|
||||
/* Rx PHY descriptor. */
|
||||
struct r92s_rx_phystat {
|
||||
@ -531,7 +527,7 @@ struct r92s_rx_phystat {
|
||||
uint32_t phydw5;
|
||||
uint32_t phydw6;
|
||||
uint32_t phydw7;
|
||||
} __packed __attribute__((aligned(4)));
|
||||
} __packed __aligned(4);
|
||||
|
||||
/* Rx PHY CCK descriptor. */
|
||||
struct r92s_rx_cck {
|
||||
@ -595,18 +591,14 @@ struct r92s_tx_desc {
|
||||
|
||||
uint16_t txbufsize;
|
||||
uint16_t reserved1;
|
||||
} __packed __attribute__((aligned(4)));
|
||||
} __packed __aligned(4);
|
||||
|
||||
|
||||
/*
|
||||
* Driver definitions.
|
||||
*/
|
||||
#define RSU_RX_LIST_COUNT 1
|
||||
#ifdef __OpenBSD__
|
||||
#define RSU_TX_LIST_COUNT (8 + 1) /* NB: +1 for FW commands. */
|
||||
#else
|
||||
#define RSU_TX_LIST_COUNT 32
|
||||
#endif
|
||||
|
||||
#define RSU_HOST_CMD_RING_COUNT 32
|
||||
|
||||
@ -735,6 +727,8 @@ 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;
|
||||
@ -743,15 +737,11 @@ struct rsu_softc {
|
||||
enum ieee80211_state, int);
|
||||
struct usbd_interface *sc_iface;
|
||||
struct timeout_task calib_task;
|
||||
struct callout sc_watchdog_ch;
|
||||
struct usbd_pipe *pipe[R92S_MAX_EP];
|
||||
int npipes;
|
||||
const uint8_t *qid2idx;
|
||||
struct mtx sc_mtx;
|
||||
|
||||
u_int cut;
|
||||
int scan_pass;
|
||||
int sc_tx_timer;
|
||||
struct rsu_host_cmd_ring cmdq;
|
||||
struct rsu_data sc_rx[RSU_RX_LIST_COUNT];
|
||||
struct rsu_data sc_tx[RSU_TX_LIST_COUNT];
|
||||
@ -764,9 +754,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;
|
||||
STAILQ_HEAD(, rsu_data) sc_tx_active[RSU_MAX_TX_EP];
|
||||
STAILQ_HEAD(, rsu_data) sc_tx_inactive;
|
||||
STAILQ_HEAD(, rsu_data) sc_tx_pending;
|
||||
STAILQ_HEAD(, rsu_data) sc_tx_pending[RSU_MAX_TX_EP];
|
||||
|
||||
union {
|
||||
struct rsu_rx_radiotap_header th;
|
||||
|
Loading…
x
Reference in New Issue
Block a user