summaryrefslogtreecommitdiffstats
path: root/sys/net80211
diff options
context:
space:
mode:
authorsam <sam@FreeBSD.org>2008-09-21 23:59:14 +0000
committersam <sam@FreeBSD.org>2008-09-21 23:59:14 +0000
commit7b36216c91f1e4ec39b40c68ee415df5c327919c (patch)
tree7bd20b90da680e15e9b19b05542ecd4a6abe71ad /sys/net80211
parentb823d18ca491ab2a0d4996a20a7368650e7d7715 (diff)
downloadFreeBSD-src-7b36216c91f1e4ec39b40c68ee415df5c327919c.zip
FreeBSD-src-7b36216c91f1e4ec39b40c68ee415df5c327919c.tar.gz
MIMO power save support; still needs callbacks for notifying drivers
of dynamic state change in station mode.
Diffstat (limited to 'sys/net80211')
-rw-r--r--sys/net80211/ieee80211_ddb.c2
-rw-r--r--sys/net80211/ieee80211_ht.c52
-rw-r--r--sys/net80211/ieee80211_ioctl.c25
-rw-r--r--sys/net80211/ieee80211_ioctl.h1
-rw-r--r--sys/net80211/ieee80211_node.c4
-rw-r--r--sys/net80211/ieee80211_node.h5
-rw-r--r--sys/net80211/ieee80211_sta.c4
-rw-r--r--sys/net80211/ieee80211_var.h1
8 files changed, 88 insertions, 6 deletions
diff --git a/sys/net80211/ieee80211_ddb.c b/sys/net80211/ieee80211_ddb.c
index 9dcb7ed..2b49004 100644
--- a/sys/net80211/ieee80211_ddb.c
+++ b/sys/net80211/ieee80211_ddb.c
@@ -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"
diff --git a/sys/net80211/ieee80211_ht.c b/sys/net80211/ieee80211_ht.c
index 827336b..1f0ad17 100644
--- a/sys/net80211/ieee80211_ht.c
+++ b/sys/net80211/ieee80211_ht.c
@@ -1237,6 +1237,32 @@ htinfo_update_chw(struct ieee80211_node *ni, int htflags)
}
/*
+ * 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,
diff --git a/sys/net80211/ieee80211_ioctl.c b/sys/net80211/ieee80211_ioctl.c
index 3d2697c..8bfcdb8 100644
--- a/sys/net80211/ieee80211_ioctl.c
+++ b/sys/net80211/ieee80211_ioctl.c
@@ -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;
diff --git a/sys/net80211/ieee80211_ioctl.h b/sys/net80211/ieee80211_ioctl.h
index f5eef26..0efd180 100644
--- a/sys/net80211/ieee80211_ioctl.h
+++ b/sys/net80211/ieee80211_ioctl.h
@@ -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
diff --git a/sys/net80211/ieee80211_node.c b/sys/net80211/ieee80211_node.c
index eb607c6..790c383 100644
--- a/sys/net80211/ieee80211_node.c
+++ b/sys/net80211/ieee80211_node.c
@@ -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) ?
diff --git a/sys/net80211/ieee80211_node.h b/sys/net80211/ieee80211_node.h
index fb74736..1d104d1 100644
--- a/sys/net80211/ieee80211_node.h
+++ b/sys/net80211/ieee80211_node.h
@@ -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)
diff --git a/sys/net80211/ieee80211_sta.c b/sys/net80211/ieee80211_sta.c
index 3010965..232e67a 100644
--- a/sys/net80211/ieee80211_sta.c
+++ b/sys/net80211/ieee80211_sta.c
@@ -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) ?
diff --git a/sys/net80211/ieee80211_var.h b/sys/net80211/ieee80211_var.h
index 5334d1e..ab2cbe4 100644
--- a/sys/net80211/ieee80211_var.h
+++ b/sys/net80211/ieee80211_var.h
@@ -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 *);
OpenPOWER on IntegriCloud