diff --git a/sys/dev/rtwn/rtl8192c/r92c_tx.c b/sys/dev/rtwn/rtl8192c/r92c_tx.c index d5cbc3ad9db9..a7451bf22375 100644 --- a/sys/dev/rtwn/rtl8192c/r92c_tx.c +++ b/sys/dev/rtwn/rtl8192c/r92c_tx.c @@ -422,6 +422,8 @@ r92c_fill_tx_desc_raw(struct rtwn_softc *sc, struct ieee80211_node *ni, rtwn_r92c_tx_setup_macid(sc, txd, RTWN_MACID_BC); txd->txdw1 |= htole32(SM(R92C_TXDW1_QSEL, R92C_TXDW1_QSEL_MGNT)); + txd->txdw2 |= htole32(R92C_TXDW2_CCX_RPT); + /* Set TX rate index. */ txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE, ridx)); txd->txdw5 |= htole32(SM(R92C_TXDW5_DATARATE_FB_LMT, 0x1f)); diff --git a/sys/dev/rtwn/rtl8192e/r92e_chan.c b/sys/dev/rtwn/rtl8192e/r92e_chan.c index 4c7121a80c89..1c4bbd60bf96 100644 --- a/sys/dev/rtwn/rtl8192e/r92e_chan.c +++ b/sys/dev/rtwn/rtl8192e/r92e_chan.c @@ -196,9 +196,10 @@ r92e_set_bw40(struct rtwn_softc *sc, uint8_t chan, int prichlo) rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, 0, R92C_RFMOD_40MHZ); /* Select 40MHz bandwidth. */ - for (i = 0; i < sc->nrxchains; i++) + for (i = 0; i < sc->nrxchains; i++) { rtwn_rf_setbits(sc, i, R92C_RF_CHNLBW, R88E_RF_CHNLBW_BW20, 0x400); + } /* Set CCK side band. */ rtwn_bb_setbits(sc, R92C_CCK0_SYSTEM, @@ -224,9 +225,10 @@ r92e_set_bw20(struct rtwn_softc *sc, uint8_t chan) rtwn_bb_setbits(sc, R92C_FPGA1_RFMOD, R92C_RFMOD_40MHZ, 0); /* Select 20MHz bandwidth. */ - for (i = 0; i < sc->nrxchains; i++) + for (i = 0; i < sc->nrxchains; i++) { rtwn_rf_setbits(sc, i, R92C_RF_CHNLBW, R88E_RF_CHNLBW_BW20, 0xc00); + } rtwn_bb_setbits(sc, R92C_OFDM0_TXPSEUDONOISEWGT, 0xc0000000, 0); } @@ -252,4 +254,23 @@ r92e_set_chan(struct rtwn_softc *sc, struct ieee80211_channel *c) /* Set Tx power for this new channel. */ r92e_set_txpower(sc, c); + + /* + * This seems to .. just fix it? Without the other sleeps + * in this path? + * + * Maybe there's a race between finishing programming the channels (and + * a bunch of writes being pending in an internal FIFO in the NIC) + * and the first frame being sent during association/authentication? + */ +#if 0 + device_printf(sc->sc_dev, "%s: TXPAUSE=0x%02x\n", + __func__, + rtwn_read_1(sc, R92C_TXPAUSE)); +#endif + + /* Re-enable all the TX queues */ +// rtwn_write_1(sc, R92C_TXPAUSE, 0x0); + + rtwn_delay(sc, 10000); } diff --git a/sys/dev/rtwn/rtl8192e/r92e_init.c b/sys/dev/rtwn/rtl8192e/r92e_init.c index 925221bdabb1..d6a497eccd36 100644 --- a/sys/dev/rtwn/rtl8192e/r92e_init.c +++ b/sys/dev/rtwn/rtl8192e/r92e_init.c @@ -104,6 +104,7 @@ r92e_init_bb(struct rtwn_softc *sc) R92C_SYS_FUNC_EN_DIO_RF); /* PathA RF Power On. */ + /* linux.git: 5d03f882c2fc0bb588e8a91ba3955f56170fc891 */ rtwn_write_1(sc, R92C_RF_CTRL, R92C_RF_CTRL_EN | R92C_RF_CTRL_RSTB | R92C_RF_CTRL_SDMRSTB); @@ -160,6 +161,8 @@ r92e_init_bb(struct rtwn_softc *sc) r92e_crystalcap_write(sc); } +/* TODO: where's the equivalent code to rtl8192e_enable_rf() ? */ + void r92e_init_rf(struct rtwn_softc *sc) { @@ -210,7 +213,6 @@ r92e_init_rf(struct rtwn_softc *sc) static void r92e_adj_crystal(struct rtwn_softc *sc) { - rtwn_setbits_1(sc, R92C_AFE_PLL_CTRL, R92C_AFE_PLL_CTRL_FREF_SEL, 0); rtwn_setbits_4(sc, R92E_APE_PLL_CTRL_EXT, 0x00000380, 0); rtwn_setbits_1(sc, R92C_AFE_PLL_CTRL, 0x40, 0); @@ -226,6 +228,8 @@ r92e_power_on(struct rtwn_softc *sc) } while(0) int ntries; + device_printf(sc->sc_dev, "%s: called\n", __func__); + if (rtwn_read_4(sc, R92C_SYS_CFG) & R92C_SYS_CFG_TRP_BT_EN) RTWN_CHK(rtwn_write_1(sc, R92C_LDO_SWR_CTRL, 0xc3)); else { @@ -234,9 +238,12 @@ r92e_power_on(struct rtwn_softc *sc) RTWN_CHK(rtwn_write_1(sc, R92C_LDO_SWR_CTRL, 0x83)); } + /* Adjust AFE before enabling the PLL */ r92e_adj_crystal(sc); /* Enable WL suspend. */ + /* Clear suspend enable and power down enable */ + /* This is where a second power-up fails */ RTWN_CHK(rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_AFSM_HSUS | R92C_APS_FSMCO_AFSM_PCIE, 0, 1)); @@ -269,11 +276,15 @@ r92e_power_on(struct rtwn_softc *sc) break; rtwn_delay(sc, 10); } - if (ntries == 5000) + if (ntries == 5000) { + device_printf(sc->sc_dev, + "timeout waiting for mac enable?\n"); return (ETIMEDOUT); + } /* Enable MAC DMA/WMAC/SCHEDULE/SEC blocks. */ RTWN_CHK(rtwn_write_2(sc, R92C_CR, 0)); + RTWN_CHK(rtwn_setbits_2(sc, R92C_CR, 0, R92C_CR_HCI_TXDMA_EN | R92C_CR_TXDMA_EN | R92C_CR_HCI_RXDMA_EN | R92C_CR_RXDMA_EN | @@ -281,6 +292,8 @@ r92e_power_on(struct rtwn_softc *sc) ((sc->sc_hwcrypto != RTWN_CRYPTO_SW) ? R92C_CR_ENSEC : 0) | R92C_CR_CALTMR_EN)); + device_printf(sc->sc_dev, "%s: finished\n", __func__); + return (0); } @@ -288,15 +301,30 @@ void r92e_power_off(struct rtwn_softc *sc) { int error, ntries; + uint8_t val; + + device_printf(sc->sc_dev, "%s: called\n", __func__); + /* XXX rtl8xxxu_flush_fifo() ? */ + + /* XXX disable report timer? */ /* Stop Rx. */ error = rtwn_write_1(sc, R92C_CR, 0); if (error == ENXIO) /* hardware gone */ return; + /* Turn off RF */ + rtwn_write_1(sc, R92C_RF_CTRL, 0); + + /* rtl8192eu_active_to_lps() begin */ + /* Move card to Low Power state. */ /* Block all Tx queues. */ - rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL); + if (rtwn_write_1(sc, R92C_TXPAUSE, R92C_TX_QUEUE_ALL) != 0) { + device_printf(sc->sc_dev, "%s: TXPAUSE write failed!\n", + __func__); + return; + } for (ntries = 0; ntries < 5000; ntries++) { /* Should be zero if no packet is transmitting. */ @@ -314,7 +342,7 @@ r92e_power_off(struct rtwn_softc *sc) /* CCK and OFDM are disabled, and clock are gated. */ rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BBRSTB, 0); - rtwn_delay(sc, 1); + rtwn_delay(sc, 2); /* Reset whole BB. */ rtwn_setbits_1(sc, R92C_SYS_FUNC_EN, R92C_SYS_FUNC_EN_BB_GLB_RST, 0); @@ -329,9 +357,24 @@ r92e_power_off(struct rtwn_softc *sc) /* Respond TxOK to scheduler */ rtwn_setbits_1(sc, R92C_DUAL_TSF_RST, 0, R92C_DUAL_TSF_RST_TXOK); + /* rtl8192eu_active_to_lps() end */ + + /* missing reset firmware if running in RAM? */ + if (rtwn_read_1(sc, R92C_MCUFWDL) & R92C_MCUFWDL_RAM_DL_SEL) { + device_printf(sc->sc_dev, + "%s: firmware running in RAM; need to reset firmware!\n", + __func__); + } + + /* XXX Linux does a reset MCU here first */ + rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, + R92C_SYS_FUNC_EN_CPUEN, 0, 1); + /* Reset MCU. */ + /* Reset MC ready status */ rtwn_write_1(sc, R92C_MCUFWDL, 0); + /* rtl8xxxu_reset_8051(), but missing re-enabling the CPU after */ #ifndef RTWN_WITHOUT_UCODE /* Reset MCU IO wrapper. */ rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0x01, 0); @@ -341,11 +384,19 @@ r92e_power_off(struct rtwn_softc *sc) /* Enable MCU IO wrapper. */ rtwn_setbits_1(sc, R92C_RSV_CTRL + 1, 0, 0x01); + + /* XXX linux does this? */ + rtwn_setbits_1_shift(sc, R92C_SYS_FUNC_EN, + 0, R92C_SYS_FUNC_EN_CPUEN, 1); #endif + /* rtl8192eu_active_to_emu() begin */ + /* Move card to Disabled state. */ /* Turn off RF. */ - rtwn_write_1(sc, R92C_RF_CTRL, 0); + val = rtwn_read_1(sc, R92C_RF_CTRL); + val &= ~R92C_RF_CTRL_EN; + rtwn_write_1(sc, R92C_RF_CTRL, val); /* Switch DPDT_SEL_P output. */ rtwn_setbits_1(sc, R92C_LEDCFG2, 0x80, 0); @@ -367,22 +418,37 @@ r92e_power_off(struct rtwn_softc *sc) __func__); return; } + /* rtl8192eu_active_to_emu() end */ +#if 0 /* SOP option to disable BG/MB. */ + /* XXX ? */ rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0xff, R92C_APS_FSMCO_SOP_RCK, 3); /* Unlock small LDO Register. */ + /* XXX ? */ rtwn_setbits_1(sc, 0xcc, 0, 0x4); /* Disable small LDO. */ + /* XXX ? */ rtwn_setbits_1(sc, R92C_SPS0_CTRL, 0x1, 0); +#endif + + /* rtl8192eu_emu_to_disabled() begin */ /* Enable WL suspend. */ rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, R92C_APS_FSMCO_AFSM_PCIE, R92C_APS_FSMCO_AFSM_HSUS, 1); + /* rtl8192eu_emu_to_disabled() end */ + + /* XXX This causes the RTL8192EU to not come back after a power-off! */ +#if 0 /* Enable SW LPS. */ rtwn_setbits_1_shift(sc, R92C_APS_FSMCO, 0, R92C_APS_FSMCO_APFM_RSM, 1); +#endif + + device_printf(sc->sc_dev, "%s: finished\n", __func__); }