mac80211: add P2P NoA settings
authorJanusz Dziedzic <janusz.dziedzic@gmail.com>
Thu, 21 Mar 2013 14:47:56 +0000 (15:47 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Fri, 22 Mar 2013 13:13:42 +0000 (14:13 +0100)
Add P2P NoA settings for STA mode.

Signed-off-by: Janusz Dziedzic <janusz.dziedzic@tieto.com>
[fix docs]
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
include/net/mac80211.h
net/mac80211/cfg.c
net/mac80211/ieee80211_i.h
net/mac80211/mlme.c
net/mac80211/trace.h

index 341dbc0..1d20287 100644 (file)
@@ -662,6 +662,7 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm *mvm,
                                           u32 action)
 {
        struct iwl_mac_ctx_cmd cmd = {};
+       struct ieee80211_p2p_noa_attr *noa = &vif->bss_conf.p2p_noa_attr;
 
        WARN_ON(vif->type != NL80211_IFTYPE_STATION || !vif->p2p);
 
@@ -671,7 +672,8 @@ static int iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm *mvm,
        /* Fill the data specific for station mode */
        iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta);
 
-       cmd.p2p_sta.ctwin = cpu_to_le32(vif->bss_conf.p2p_ctwindow);
+       cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow &
+                                       IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
 
        return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
 }
@@ -892,6 +894,7 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
                                   u32 action)
 {
        struct iwl_mac_ctx_cmd cmd = {};
+       struct ieee80211_p2p_noa_attr *noa = &vif->bss_conf.p2p_noa_attr;
 
        WARN_ON(vif->type != NL80211_IFTYPE_AP || !vif->p2p);
 
@@ -901,8 +904,11 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
        /* Fill the data specific for GO mode */
        iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap);
 
-       cmd.go.ctwin = cpu_to_le32(vif->bss_conf.p2p_ctwindow);
-       cmd.go.opp_ps_enabled = cpu_to_le32(!!vif->bss_conf.p2p_oppps);
+       cmd.go.ctwin = cpu_to_le32(noa->oppps_ctwindow &
+                                       IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
+       cmd.go.opp_ps_enabled =
+                       cpu_to_le32(!!(noa->oppps_ctwindow &
+                                       IEEE80211_P2P_OPPPS_ENABLE_BIT));
 
        return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
 }
index dd73b8c..9b53617 100644 (file)
@@ -330,8 +330,7 @@ enum ieee80211_rssi_event {
  * @ssid_len: Length of SSID given in @ssid.
  * @hidden_ssid: The SSID of the current vif is hidden. Only valid in AP-mode.
  * @txpower: TX power in dBm
- * @p2p_ctwindow: P2P CTWindow, only for P2P client interfaces
- * @p2p_oppps: P2P opportunistic PS is enabled
+ * @p2p_noa_attr: P2P NoA attribute for P2P powersave
  */
 struct ieee80211_bss_conf {
        const u8 *bssid;
@@ -365,8 +364,7 @@ struct ieee80211_bss_conf {
        size_t ssid_len;
        bool hidden_ssid;
        int txpower;
-       u8 p2p_ctwindow;
-       bool p2p_oppps;
+       struct ieee80211_p2p_noa_attr p2p_noa_attr;
 };
 
 /**
index e5c1441..50aaf25 100644 (file)
@@ -965,8 +965,13 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
        sdata->vif.bss_conf.hidden_ssid =
                (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE);
 
-       sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow;
-       sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps;
+       memset(&sdata->vif.bss_conf.p2p_noa_attr, 0,
+              sizeof(sdata->vif.bss_conf.p2p_noa_attr));
+       sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow =
+               params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
+       if (params->p2p_opp_ps)
+               sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
+                                       IEEE80211_P2P_OPPPS_ENABLE_BIT;
 
        err = ieee80211_assign_beacon(sdata, &params->beacon);
        if (err < 0)
@@ -1961,12 +1966,20 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
        }
 
        if (params->p2p_ctwindow >= 0) {
-               sdata->vif.bss_conf.p2p_ctwindow = params->p2p_ctwindow;
+               sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &=
+                                       ~IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
+               sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
+                       params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
                changed |= BSS_CHANGED_P2P_PS;
        }
 
-       if (params->p2p_opp_ps >= 0) {
-               sdata->vif.bss_conf.p2p_oppps = params->p2p_opp_ps;
+       if (params->p2p_opp_ps > 0) {
+               sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
+                                       IEEE80211_P2P_OPPPS_ENABLE_BIT;
+               changed |= BSS_CHANGED_P2P_PS;
+       } else if (params->p2p_opp_ps == 0) {
+               sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &=
+                                       ~IEEE80211_P2P_OPPPS_ENABLE_BIT;
                changed |= BSS_CHANGED_P2P_PS;
        }
 
index ae2d175..55155e3 100644 (file)
@@ -442,7 +442,7 @@ struct ieee80211_if_managed {
 
        u8 use_4addr;
 
-       u8 p2p_noa_index;
+       s16 p2p_noa_index;
 
        /* Signal strength from the last Beacon frame in the current BSS. */
        int last_beacon_signal;
index f925870..8b3e852 100644 (file)
@@ -1661,20 +1661,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
                rcu_read_lock();
                ies = rcu_dereference(cbss->ies);
                if (ies) {
-                       struct ieee80211_p2p_noa_attr noa;
                        int ret;
 
                        ret = cfg80211_get_p2p_attr(
                                        ies->data, ies->len,
                                        IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
-                                       (u8 *) &noa, sizeof(noa));
+                                       (u8 *) &bss_conf->p2p_noa_attr,
+                                       sizeof(bss_conf->p2p_noa_attr));
                        if (ret >= 2) {
-                               bss_conf->p2p_oppps = noa.oppps_ctwindow &
-                                               IEEE80211_P2P_OPPPS_ENABLE_BIT;
-                               bss_conf->p2p_ctwindow = noa.oppps_ctwindow &
-                                               IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
+                               sdata->u.mgd.p2p_noa_index =
+                                       bss_conf->p2p_noa_attr.index;
                                bss_info_changed |= BSS_CHANGED_P2P_PS;
-                               sdata->u.mgd.p2p_noa_index = noa.index;
                        }
                }
                rcu_read_unlock();
@@ -1799,8 +1796,9 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
        changed |= BSS_CHANGED_ASSOC;
        sdata->vif.bss_conf.assoc = false;
 
-       sdata->vif.bss_conf.p2p_ctwindow = 0;
-       sdata->vif.bss_conf.p2p_oppps = false;
+       ifmgd->p2p_noa_index = -1;
+       memset(&sdata->vif.bss_conf.p2p_noa_attr, 0,
+              sizeof(sdata->vif.bss_conf.p2p_noa_attr));
 
        /* on the next assoc, re-program HT/VHT parameters */
        memset(&ifmgd->ht_capa, 0, sizeof(ifmgd->ht_capa));
@@ -2963,24 +2961,30 @@ ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata,
        }
 
        if (sdata->vif.p2p) {
-               struct ieee80211_p2p_noa_attr noa;
+               struct ieee80211_p2p_noa_attr noa = {};
                int ret;
 
                ret = cfg80211_get_p2p_attr(mgmt->u.beacon.variable,
                                            len - baselen,
                                            IEEE80211_P2P_ATTR_ABSENCE_NOTICE,
                                            (u8 *) &noa, sizeof(noa));
-               if (ret >= 2 && sdata->u.mgd.p2p_noa_index != noa.index) {
-                       bss_conf->p2p_oppps = noa.oppps_ctwindow &
-                                               IEEE80211_P2P_OPPPS_ENABLE_BIT;
-                       bss_conf->p2p_ctwindow = noa.oppps_ctwindow &
-                                               IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
+               if (ret >= 2) {
+                       if (sdata->u.mgd.p2p_noa_index != noa.index) {
+                               /* valid noa_attr and index changed */
+                               sdata->u.mgd.p2p_noa_index = noa.index;
+                               memcpy(&bss_conf->p2p_noa_attr, &noa, sizeof(noa));
+                               changed |= BSS_CHANGED_P2P_PS;
+                               /*
+                                * make sure we update all information, the CRC
+                                * mechanism doesn't look at P2P attributes.
+                                */
+                               ifmgd->beacon_crc_valid = false;
+                       }
+               } else if (sdata->u.mgd.p2p_noa_index != -1) {
+                       /* noa_attr not found and we had valid noa_attr before */
+                       sdata->u.mgd.p2p_noa_index = -1;
+                       memset(&bss_conf->p2p_noa_attr, 0, sizeof(bss_conf->p2p_noa_attr));
                        changed |= BSS_CHANGED_P2P_PS;
-                       sdata->u.mgd.p2p_noa_index = noa.index;
-                       /*
-                        * make sure we update all information, the CRC
-                        * mechanism doesn't look at P2P attributes.
-                        */
                        ifmgd->beacon_crc_valid = false;
                }
        }
@@ -3523,6 +3527,7 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata)
        ifmgd->powersave = sdata->wdev.ps;
        ifmgd->uapsd_queues = IEEE80211_DEFAULT_UAPSD_QUEUES;
        ifmgd->uapsd_max_sp_len = IEEE80211_DEFAULT_MAX_SP_LEN;
+       ifmgd->p2p_noa_index = -1;
 
        mutex_init(&ifmgd->mtx);
 
index c589979..d79e374 100644 (file)
@@ -359,8 +359,7 @@ TRACE_EVENT(drv_bss_info_changed,
                __dynamic_array(u8, ssid, info->ssid_len);
                __field(bool, hidden_ssid);
                __field(int, txpower)
-               __field(u8, p2p_ctwindow)
-               __field(bool, p2p_oppps)
+               __field(u8, p2p_oppps_ctwindow)
        ),
 
        TP_fast_assign(
@@ -400,8 +399,7 @@ TRACE_EVENT(drv_bss_info_changed,
                memcpy(__get_dynamic_array(ssid), info->ssid, info->ssid_len);
                __entry->hidden_ssid = info->hidden_ssid;
                __entry->txpower = info->txpower;
-               __entry->p2p_ctwindow = info->p2p_ctwindow;
-               __entry->p2p_oppps = info->p2p_oppps;
+               __entry->p2p_oppps_ctwindow = info->p2p_noa_attr.oppps_ctwindow;
        ),
 
        TP_printk(