MIMO power save support; still needs callbacks for notifying drivers

of dynamic state change in station mode.
This commit is contained in:
Sam Leffler 2008-09-21 23:59:14 +00:00
parent fdabd982e7
commit 8c070d69c7
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=183255
8 changed files with 88 additions and 6 deletions

View File

@ -90,7 +90,7 @@ __FBSDID("$FreeBSD$");
#define IEEE80211_NODE_BITS \
"\20\1AUTH\2QOS\3ERP\5PWR_MGT\6AREF\7HT\10HTCOMPAT\11WPS\12TSN" \
"\13AMPDU_RX\14AMPDU_TX"
"\13AMPDU_RX\14AMPDU_TX\15MIMO_PS\16MIMO_RTS"
#define IEEE80211_ERP_BITS \
"\20\1NON_ERP_PRESENT\2USE_PROTECTION\3LONG_PREAMBLE"

View File

@ -1236,6 +1236,32 @@ htinfo_update_chw(struct ieee80211_node *ni, int htflags)
ni->ni_chw = IEEE80211_IS_CHAN_HT40(ni->ni_chan)? 40 : 20;
}
/*
* Update 11n MIMO PS state according to received htcap.
*/
static __inline int
htcap_update_mimo_ps(struct ieee80211_node *ni)
{
uint16_t oflags = ni->ni_flags;
switch (ni->ni_htcap & IEEE80211_HTCAP_SMPS) {
case IEEE80211_HTCAP_SMPS_DYNAMIC:
ni->ni_flags |= IEEE80211_NODE_MIMO_PS;
ni->ni_flags |= IEEE80211_NODE_MIMO_RTS;
break;
case IEEE80211_HTCAP_SMPS_ENA:
ni->ni_flags |= IEEE80211_NODE_MIMO_PS;
ni->ni_flags &= ~IEEE80211_NODE_MIMO_RTS;
break;
case IEEE80211_HTCAP_SMPS_OFF:
default: /* disable on rx of reserved value */
ni->ni_flags &= ~IEEE80211_NODE_MIMO_PS;
ni->ni_flags &= ~IEEE80211_NODE_MIMO_RTS;
break;
}
return (oflags ^ ni->ni_flags);
}
/*
* Parse and update HT-related state extracted from
* the HT cap and info ie's.
@ -1249,6 +1275,8 @@ ieee80211_ht_updateparams(struct ieee80211_node *ni,
int htflags;
ieee80211_parse_htcap(ni, htcapie);
if (vap->iv_htcaps & IEEE80211_HTCAP_SMPS)
htcap_update_mimo_ps(ni);
if (htinfoie[0] == IEEE80211_ELEMID_VENDOR)
htinfoie += 4;
@ -1279,6 +1307,8 @@ ieee80211_ht_updatehtcap(struct ieee80211_node *ni, const uint8_t *htcapie)
int htflags;
ieee80211_parse_htcap(ni, htcapie);
if (vap->iv_htcaps & IEEE80211_HTCAP_SMPS)
htcap_update_mimo_ps(ni);
/* NB: honor operating mode constraint */
/* XXX 40 MHZ intolerant */
@ -1660,11 +1690,29 @@ ieee80211_recv_action(struct ieee80211_node *ni,
/* XXX notify on change */
}
break;
case IEEE80211_ACTION_HT_MIMOPWRSAVE:
case IEEE80211_ACTION_HT_MIMOPWRSAVE: {
const struct ieee80211_action_ht_mimopowersave *mps =
(const struct ieee80211_action_ht_mimopowersave *) ia;
/* XXX check iv_htcaps */
if (mps->am_control & IEEE80211_A_HT_MIMOPWRSAVE_ENA)
ni->ni_flags |= IEEE80211_NODE_MIMO_PS;
else
ni->ni_flags &= ~IEEE80211_NODE_MIMO_PS;
if (mps->am_control & IEEE80211_A_HT_MIMOPWRSAVE_MODE)
ni->ni_flags |= IEEE80211_NODE_MIMO_RTS;
else
ni->ni_flags &= ~IEEE80211_NODE_MIMO_RTS;
/* XXX notify on change */
IEEE80211_NOTE(vap,
IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,
"%s: HT MIMO PS", __func__);
"%s: HT MIMO PS (%s%s)", __func__,
(ni->ni_flags & IEEE80211_NODE_MIMO_PS) ?
"on" : "off",
(ni->ni_flags & IEEE80211_NODE_MIMO_RTS) ?
"+rts" : ""
);
break;
}
default:
IEEE80211_NOTE(vap,
IEEE80211_MSG_ACTION | IEEE80211_MSG_11N, ni,

View File

@ -1068,6 +1068,18 @@ ieee80211_ioctl_get80211(struct ieee80211vap *vap, u_long cmd,
case IEEE80211_IOC_STA_VLAN:
error = ieee80211_ioctl_getstavlan(vap, ireq);
break;
case IEEE80211_IOC_SMPS:
if (vap->iv_opmode == IEEE80211_M_STA &&
vap->iv_state == IEEE80211_S_RUN) {
if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_RTS)
ireq->i_val = IEEE80211_HTCAP_SMPS_DYNAMIC;
else if (vap->iv_bss->ni_flags & IEEE80211_NODE_MIMO_PS)
ireq->i_val = IEEE80211_HTCAP_SMPS_ENA;
else
ireq->i_val = IEEE80211_HTCAP_SMPS_OFF;
} else
ireq->i_val = vap->iv_htcaps & IEEE80211_HTCAP_SMPS;
break;
default:
error = EINVAL;
break;
@ -3068,6 +3080,19 @@ ieee80211_ioctl_set80211(struct ieee80211vap *vap, u_long cmd, struct ieee80211r
case IEEE80211_IOC_STA_VLAN:
error = ieee80211_ioctl_setstavlan(vap, ireq);
break;
case IEEE80211_IOC_SMPS:
if ((ireq->i_val &~ IEEE80211_HTCAP_SMPS) != 0 ||
ireq->i_val == 0x0008) /* value of 2 is reserved */
return EINVAL;
if (ireq->i_val != IEEE80211_HTCAP_SMPS_OFF &&
(vap->iv_htcaps & IEEE80211_HTC_SMPS) == 0)
return EOPNOTSUPP;
vap->iv_htcaps = (vap->iv_htcaps &~ IEEE80211_HTCAP_SMPS) |
ireq->i_val;
/* NB: if not operating in 11n this can wait */
if (isvapht(vap))
error = ERESTART;
break;
default:
error = EINVAL;
break;

View File

@ -609,6 +609,7 @@ struct ieee80211req {
#define IEEE80211_IOC_ROAM 107 /* roaming params en masse */
#define IEEE80211_IOC_TXPARAMS 108 /* tx parameters */
#define IEEE80211_IOC_STA_VLAN 109 /* per-station vlan tag */
#define IEEE80211_IOC_SMPS 110 /* MIMO power save */
/*
* Parameters for controlling a scan requested with

View File

@ -2264,7 +2264,7 @@ ieee80211_node_join(struct ieee80211_node *ni, int resp)
newassoc = 0;
IEEE80211_NOTE(vap, IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, ni,
"station associated at aid %d: %s preamble, %s slot time%s%s%s%s%s%s",
"station associated at aid %d: %s preamble, %s slot time%s%s%s%s%s%s%s",
IEEE80211_NODE_AID(ni),
ic->ic_flags & IEEE80211_F_SHPREAMBLE ? "short" : "long",
ic->ic_flags & IEEE80211_F_SHSLOT ? "short" : "long",
@ -2273,6 +2273,8 @@ ieee80211_node_join(struct ieee80211_node *ni, int resp)
ni->ni_flags & IEEE80211_NODE_HT ?
(ni->ni_chw == 40 ? ", HT40" : ", HT20") : "",
ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "",
ni->ni_flags & IEEE80211_NODE_MIMO_RTS ? " (+SMPS-DYN)" :
ni->ni_flags & IEEE80211_NODE_MIMO_PS ? " (+SMPS)" : "",
IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF) ?
", fast-frames" : "",
IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_TURBOP) ?

View File

@ -112,6 +112,8 @@ struct ieee80211_node {
#define IEEE80211_NODE_TSN 0x000200 /* TSN association */
#define IEEE80211_NODE_AMPDU_RX 0x000400 /* AMPDU rx enabled */
#define IEEE80211_NODE_AMPDU_TX 0x000800 /* AMPDU tx enabled */
#define IEEE80211_NODE_MIMO_PS 0x001000 /* MIMO power save enabled */
#define IEEE80211_NODE_MIMO_RTS 0x002000 /* send RTS in MIMO PS */
uint16_t ni_associd; /* association ID */
uint16_t ni_vlan; /* vlan tag */
uint16_t ni_txpower; /* current transmit power */
@ -195,7 +197,8 @@ MALLOC_DECLARE(M_80211_NODE_IE);
(IEEE80211_NODE_AMPDU_RX | IEEE80211_NODE_AMPDU_TX)
#define IEEE80211_NODE_HT_ALL \
(IEEE80211_NODE_HT | IEEE80211_NODE_HTCOMPAT | \
IEEE80211_NODE_AMPDU)
IEEE80211_NODE_AMPDU | IEEE80211_NODE_MIMO_PS | \
IEEE80211_NODE_MIMO_RTS)
#define IEEE80211_NODE_AID(ni) IEEE80211_AID(ni->ni_associd)

View File

@ -1538,7 +1538,7 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
ic->ic_flags &= ~IEEE80211_F_USEPROT;
IEEE80211_NOTE_MAC(vap,
IEEE80211_MSG_ASSOC | IEEE80211_MSG_DEBUG, wh->i_addr2,
"%sassoc success at aid %d: %s preamble, %s slot time%s%s%s%s%s%s",
"%sassoc success at aid %d: %s preamble, %s slot time%s%s%s%s%s%s%s",
ISREASSOC(subtype) ? "re" : "",
IEEE80211_NODE_AID(ni),
ic->ic_flags&IEEE80211_F_SHPREAMBLE ? "short" : "long",
@ -1548,6 +1548,8 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
ni->ni_flags & IEEE80211_NODE_HT ?
(ni->ni_chw == 40 ? ", HT40" : ", HT20") : "",
ni->ni_flags & IEEE80211_NODE_AMPDU ? " (+AMPDU)" : "",
ni->ni_flags & IEEE80211_NODE_MIMO_RTS ? " (+SMPS-DYN)" :
ni->ni_flags & IEEE80211_NODE_MIMO_PS ? " (+SMPS)" : "",
IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_FF) ?
", fast-frames" : "",
IEEE80211_ATH_CAP(vap, ni, IEEE80211_NODE_TURBOP) ?

View File

@ -534,6 +534,7 @@ MALLOC_DECLARE(M_80211_VAP);
#define IEEE80211_HTC_AMSDU 0x00020000 /* CAPABILITY: A-MSDU tx */
/* NB: HT40 is implied by IEEE80211_HTCAP_CHWIDTH40 */
#define IEEE80211_HTC_HT 0x00040000 /* CAPABILITY: HT operation */
#define IEEE80211_HTC_SMPS 0x00080000 /* CAPABILITY: MIMO power save*/
void ieee80211_ifattach(struct ieee80211com *);
void ieee80211_ifdetach(struct ieee80211com *);