mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-18 10:35:55 +00:00
Begin fleshing out basic power-on / power-off and A-MPDU TX support.
* Add a new method to control NIC poweron / network-sleep / power off; * Add in A-MPDU TX negotiation support, but comment it out because it does break TX traffic; * blank out the tx buffer before sending a firmware message, just in case; * go into network-sleep once associated; TODO: * figure out why ampdu negotiation isn't working and breaking TX traffic, then enable it.
This commit is contained in:
parent
82e8c646b4
commit
6acf853d7a
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=288089
@ -100,6 +100,7 @@ TUNABLE_INT("hw.usb.rsu.enable_11n", &rsu_enable_11n);
|
||||
#define RSU_DEBUG_TXDONE 0x00000080
|
||||
#define RSU_DEBUG_FW 0x00000100
|
||||
#define RSU_DEBUG_FWDBG 0x00000200
|
||||
#define RSU_DEBUG_AMPDU 0x00000400
|
||||
|
||||
static const STRUCT_USB_HOST_ID rsu_devs[] = {
|
||||
#define RSU_HT_NOT_SUPPORTED 0
|
||||
@ -336,11 +337,51 @@ rsu_update_chw(struct ieee80211com *ic)
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* notification from net80211 that it'd like to do A-MPDU on the given TID.
|
||||
*
|
||||
* Note: this actually hangs traffic at the present moment, so don't use it.
|
||||
* The firmware debug does indiciate it's sending and establishing a TX AMPDU
|
||||
* session, but then no traffic flows.
|
||||
*/
|
||||
static int
|
||||
rsu_ampdu_enable(struct ieee80211_node *ni, struct ieee80211_tx_ampdu *tap)
|
||||
{
|
||||
#if 0
|
||||
struct rsu_softc *sc = ni->ni_ic->ic_softc;
|
||||
struct r92s_add_ba_req req;
|
||||
|
||||
/* Firmware handles this; not our problem */
|
||||
/* Don't enable if it's requested or running */
|
||||
if (IEEE80211_AMPDU_REQUESTED(tap))
|
||||
return (0);
|
||||
if (IEEE80211_AMPDU_RUNNING(tap))
|
||||
return (0);
|
||||
|
||||
/* We've decided to send addba; so send it */
|
||||
req.tid = htole32(tap->txa_tid);
|
||||
|
||||
/* Attempt net80211 state */
|
||||
if (ieee80211_ampdu_tx_request_ext(ni, tap->txa_tid) != 1)
|
||||
return (0);
|
||||
|
||||
/* Send the firmware command */
|
||||
RSU_DPRINTF(sc, RSU_DEBUG_AMPDU, "%s: establishing AMPDU TX for TID %d\n",
|
||||
__func__,
|
||||
tap->txa_tid);
|
||||
|
||||
RSU_LOCK(sc);
|
||||
if (rsu_fw_cmd(sc, R92S_CMD_ADDBA_REQ, &req, sizeof(req)) != 1) {
|
||||
RSU_UNLOCK(sc);
|
||||
/* Mark failure */
|
||||
(void) ieee80211_ampdu_tx_request_active_ext(ni, tap->txa_tid, 0);
|
||||
return (0);
|
||||
}
|
||||
RSU_UNLOCK(sc);
|
||||
|
||||
/* Mark success; we don't get any further notifications */
|
||||
(void) ieee80211_ampdu_tx_request_active_ext(ni, tap->txa_tid, 1);
|
||||
#endif
|
||||
/* Return 0, we're driving this ourselves */
|
||||
return (0);
|
||||
}
|
||||
|
||||
@ -606,6 +647,7 @@ rsu_scan_start(struct ieee80211com *ic)
|
||||
|
||||
/* Scanning is done by the firmware. */
|
||||
RSU_LOCK(sc);
|
||||
/* XXX TODO: force awake if in in network-sleep? */
|
||||
error = rsu_site_survey(sc, TAILQ_FIRST(&ic->ic_vaps));
|
||||
RSU_UNLOCK(sc);
|
||||
if (error != 0)
|
||||
@ -965,7 +1007,11 @@ rsu_fw_cmd(struct rsu_softc *sc, uint8_t code, void *buf, int len)
|
||||
if (data == NULL)
|
||||
return (ENOMEM);
|
||||
|
||||
/* Blank the entire payload, just to be safe */
|
||||
memset(data->buf, '\0', RSU_TXBUFSZ);
|
||||
|
||||
/* Round-up command length to a multiple of 8 bytes. */
|
||||
/* XXX TODO: is this required? */
|
||||
cmdsz = (len + 7) & ~7;
|
||||
|
||||
xferlen = sizeof(*txd) + sizeof(*cmd) + cmdsz;
|
||||
@ -1042,6 +1088,66 @@ rsu_tx_task(void *arg, int pending __unused)
|
||||
RSU_UNLOCK(sc);
|
||||
}
|
||||
|
||||
#define RSU_PWR_ACTIVE 0x1
|
||||
#define RSU_PWR_OFF 0x2
|
||||
#define RSU_PWR_SLEEP 0x3
|
||||
|
||||
/*
|
||||
* Set the current power state.
|
||||
*
|
||||
* The rtlwifi code doesn't do this so aggressively; it
|
||||
* waits for an idle period after association with
|
||||
* no traffic before doing this.
|
||||
*
|
||||
* For now - it's on in all states except RUN, and
|
||||
* in RUN it'll transition to allow sleep.
|
||||
*/
|
||||
|
||||
struct r92s_pwr_cmd {
|
||||
uint8_t mode;
|
||||
uint8_t smart_ps;
|
||||
uint8_t bcn_pass_time;
|
||||
};
|
||||
|
||||
static int
|
||||
rsu_set_fw_power_state(struct rsu_softc *sc, int state)
|
||||
{
|
||||
struct r92s_set_pwr_mode cmd;
|
||||
//struct r92s_pwr_cmd cmd;
|
||||
int error;
|
||||
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
|
||||
/* XXX TODO: only change state if required */
|
||||
RSU_ASSERT_LOCKED(sc);
|
||||
|
||||
switch (state) {
|
||||
case RSU_PWR_ACTIVE:
|
||||
/* Force the hardware awake */
|
||||
rsu_write_1(sc, R92S_USB_HRPWM,
|
||||
R92S_USB_HRPWM_PS_ST_ACTIVE | R92S_USB_HRPWM_PS_ALL_ON);
|
||||
cmd.mode = R92S_PS_MODE_ACTIVE;
|
||||
break;
|
||||
case RSU_PWR_SLEEP:
|
||||
cmd.mode = R92S_PS_MODE_DTIM; /* XXX configurable? */
|
||||
cmd.smart_ps = 1; /* XXX 2 if doing p2p */
|
||||
cmd.bcn_pass_time = 5; /* in 100mS usb.c, linux/rtlwifi */
|
||||
break;
|
||||
default:
|
||||
device_printf(sc->sc_dev, "%s: unknown ps mode (%d)\n",
|
||||
__func__,
|
||||
state);
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
RSU_DPRINTF(sc, RSU_DEBUG_RESET,
|
||||
"%s: setting ps mode to %d (mode %d)\n",
|
||||
__func__, state, cmd.mode);
|
||||
error = rsu_fw_cmd(sc, R92S_CMD_SET_PWR_MODE, &cmd, sizeof(cmd));
|
||||
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
rsu_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
{
|
||||
@ -1074,9 +1180,11 @@ rsu_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
RSU_LOCK(sc);
|
||||
switch (nstate) {
|
||||
case IEEE80211_S_INIT:
|
||||
(void) rsu_set_fw_power_state(sc, RSU_PWR_ACTIVE);
|
||||
break;
|
||||
case IEEE80211_S_AUTH:
|
||||
ni = ieee80211_ref_node(vap->iv_bss);
|
||||
(void) rsu_set_fw_power_state(sc, RSU_PWR_ACTIVE);
|
||||
error = rsu_join_bss(sc, ni);
|
||||
ieee80211_free_node(ni);
|
||||
if (error != 0) {
|
||||
@ -1089,6 +1197,7 @@ rsu_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
||||
rs = &ni->ni_rates;
|
||||
/* Indicate highest supported rate. */
|
||||
ni->ni_txrate = rs->rs_rates[rs->rs_nrates - 1];
|
||||
(void) rsu_set_fw_power_state(sc, RSU_PWR_SLEEP);
|
||||
ieee80211_free_node(ni);
|
||||
startcal = 1;
|
||||
break;
|
||||
@ -1477,13 +1586,11 @@ rsu_rx_event(struct rsu_softc *sc, uint8_t code, uint8_t *buf, int len)
|
||||
buf[60] = '\0';
|
||||
RSU_DPRINTF(sc, RSU_DEBUG_FWDBG, "FWDBG: %s\n", (char *)buf);
|
||||
break;
|
||||
|
||||
case R92S_EVT_ADDBA_REQ_REPORT:
|
||||
rsu_event_addba_req_report(sc, buf, len);
|
||||
break;
|
||||
default:
|
||||
RSU_DPRINTF(sc, RSU_DEBUG_ANY, "%s: unhandled code (%d)\n",
|
||||
__func__, code);
|
||||
device_printf(sc->sc_dev, "%s: unhandled code (%d)\n", __func__, code);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -2403,7 +2510,7 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
int ntries, error;
|
||||
|
||||
if (rsu_read_1(sc, R92S_TCR) & R92S_TCR_FWRDY) {
|
||||
RSU_DPRINTF(sc, RSU_DEBUG_FW | RSU_DEBUG_RESET,
|
||||
RSU_DPRINTF(sc, RSU_DEBUG_ANY,
|
||||
"%s: Firmware already loaded\n",
|
||||
__func__);
|
||||
return (0);
|
||||
@ -2527,6 +2634,7 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
memset(dmem, 0, sizeof(*dmem));
|
||||
dmem->hci_sel = R92S_HCI_SEL_USB | R92S_HCI_SEL_8172;
|
||||
dmem->nendpoints = sc->sc_nendpoints;
|
||||
dmem->chip_version = sc->cut;
|
||||
/* XXX TODO: rf_config should come from ROM */
|
||||
dmem->rf_config = 0x11; /* 1T1R */
|
||||
dmem->vcs_type = R92S_VCS_TYPE_AUTO;
|
||||
@ -2537,6 +2645,8 @@ rsu_load_firmware(struct rsu_softc *sc)
|
||||
dmem->ampdu_en = !! (sc->sc_ht);
|
||||
dmem->agg_offload = !! (sc->sc_ht);
|
||||
dmem->qos_en = 1;
|
||||
dmem->ps_offload = 1;
|
||||
dmem->lowpower_mode = 1; /* XXX TODO: configurable? */
|
||||
/* Load DMEM section. */
|
||||
error = rsu_fw_loadsection(sc, (uint8_t *)dmem, sizeof(*dmem));
|
||||
if (error != 0) {
|
||||
@ -2613,7 +2723,6 @@ rsu_init(struct rsu_softc *sc)
|
||||
struct ieee80211com *ic = &sc->sc_ic;
|
||||
struct ieee80211vap *vap = TAILQ_FIRST(&ic->ic_vaps);
|
||||
uint8_t macaddr[IEEE80211_ADDR_LEN];
|
||||
struct r92s_set_pwr_mode cmd;
|
||||
int error;
|
||||
int i;
|
||||
|
||||
@ -2625,6 +2734,9 @@ rsu_init(struct rsu_softc *sc)
|
||||
/* Init host async commands ring. */
|
||||
sc->cmdq.cur = sc->cmdq.next = sc->cmdq.queued = 0;
|
||||
|
||||
/* Reset power management state. */
|
||||
rsu_write_1(sc, R92S_USB_HRPWM, 0);
|
||||
|
||||
/* Power on adapter. */
|
||||
if (sc->cut == 1)
|
||||
rsu_power_on_acut(sc);
|
||||
@ -2677,15 +2789,9 @@ rsu_init(struct rsu_softc *sc)
|
||||
goto fail;
|
||||
}
|
||||
|
||||
rsu_write_1(sc, R92S_USB_HRPWM,
|
||||
R92S_USB_HRPWM_PS_ST_ACTIVE | R92S_USB_HRPWM_PS_ALL_ON);
|
||||
|
||||
/* Set PS mode fully active */
|
||||
memset(&cmd, 0, sizeof(cmd));
|
||||
cmd.mode = R92S_PS_MODE_ACTIVE;
|
||||
RSU_DPRINTF(sc, RSU_DEBUG_RESET, "%s: setting ps mode to %d\n",
|
||||
__func__, cmd.mode);
|
||||
error = rsu_fw_cmd(sc, R92S_CMD_SET_PWR_MODE, &cmd, sizeof(cmd));
|
||||
error = rsu_set_fw_power_state(sc, RSU_PWR_ACTIVE);
|
||||
|
||||
if (error != 0) {
|
||||
device_printf(sc->sc_dev, "could not set PS mode\n");
|
||||
goto fail;
|
||||
|
@ -599,6 +599,10 @@ struct r92s_add_ba_event {
|
||||
uint8_t tid;
|
||||
};
|
||||
|
||||
struct r92s_add_ba_req {
|
||||
uint32_t tid;
|
||||
};
|
||||
|
||||
/*
|
||||
* Driver definitions.
|
||||
*/
|
||||
|
Loading…
Reference in New Issue
Block a user