mac80211: replace restart_complete() with reconfig_complete()
[cascardo/linux.git] / net / mac80211 / util.c
index 9247a96..f9319a5 100644 (file)
@@ -693,6 +693,34 @@ void ieee80211_iterate_active_interfaces_rtnl(
 }
 EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl);
 
+static void __iterate_stations(struct ieee80211_local *local,
+                              void (*iterator)(void *data,
+                                               struct ieee80211_sta *sta),
+                              void *data)
+{
+       struct sta_info *sta;
+
+       list_for_each_entry_rcu(sta, &local->sta_list, list) {
+               if (!sta->uploaded)
+                       continue;
+
+               iterator(data, &sta->sta);
+       }
+}
+
+void ieee80211_iterate_stations_atomic(struct ieee80211_hw *hw,
+                       void (*iterator)(void *data,
+                                        struct ieee80211_sta *sta),
+                       void *data)
+{
+       struct ieee80211_local *local = hw_to_local(hw);
+
+       rcu_read_lock();
+       __iterate_stations(local, iterator, data);
+       rcu_read_unlock();
+}
+EXPORT_SYMBOL_GPL(ieee80211_iterate_stations_atomic);
+
 struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev)
 {
        struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
@@ -1073,6 +1101,7 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_chanctx_conf *chanctx_conf;
        int ac;
        bool use_11b, enable_qos;
+       bool is_ocb; /* Use another EDCA parameters if dot11OCBActivated=true */
        int aCWmin, aCWmax;
 
        if (!local->ops->conf_tx)
@@ -1097,6 +1126,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
         */
        enable_qos = (sdata->vif.type != NL80211_IFTYPE_STATION);
 
+       is_ocb = (sdata->vif.type == NL80211_IFTYPE_OCB);
+
        /* Set defaults according to 802.11-2007 Table 7-37 */
        aCWmax = 1023;
        if (use_11b)
@@ -1118,7 +1149,10 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
                                qparam.cw_max = aCWmax;
                                qparam.cw_min = aCWmin;
                                qparam.txop = 0;
-                               qparam.aifs = 7;
+                               if (is_ocb)
+                                       qparam.aifs = 9;
+                               else
+                                       qparam.aifs = 7;
                                break;
                        /* never happens but let's not leave undefined */
                        default:
@@ -1126,21 +1160,32 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
                                qparam.cw_max = aCWmax;
                                qparam.cw_min = aCWmin;
                                qparam.txop = 0;
-                               qparam.aifs = 3;
+                               if (is_ocb)
+                                       qparam.aifs = 6;
+                               else
+                                       qparam.aifs = 3;
                                break;
                        case IEEE80211_AC_VI:
                                qparam.cw_max = aCWmin;
                                qparam.cw_min = (aCWmin + 1) / 2 - 1;
-                               if (use_11b)
+                               if (is_ocb)
+                                       qparam.txop = 0;
+                               else if (use_11b)
                                        qparam.txop = 6016/32;
                                else
                                        qparam.txop = 3008/32;
-                               qparam.aifs = 2;
+
+                               if (is_ocb)
+                                       qparam.aifs = 3;
+                               else
+                                       qparam.aifs = 2;
                                break;
                        case IEEE80211_AC_VO:
                                qparam.cw_max = (aCWmin + 1) / 2 - 1;
                                qparam.cw_min = (aCWmin + 1) / 4 - 1;
-                               if (use_11b)
+                               if (is_ocb)
+                                       qparam.txop = 0;
+                               else if (use_11b)
                                        qparam.txop = 3264/32;
                                else
                                        qparam.txop = 1504/32;
@@ -1813,6 +1858,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                        ieee80211_bss_info_change_notify(sdata, changed);
                        sdata_unlock(sdata);
                        break;
+               case NL80211_IFTYPE_OCB:
+                       changed |= BSS_CHANGED_OCB;
+                       ieee80211_bss_info_change_notify(sdata, changed);
+                       break;
                case NL80211_IFTYPE_ADHOC:
                        changed |= BSS_CHANGED_IBSS;
                        /* fall through */
@@ -1949,7 +1998,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
         * We may want to change that later, however.
         */
        if (!local->suspended || reconfig_due_to_wowlan)
-               drv_restart_complete(local);
+               drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART);
 
        if (!local->suspended)
                return 0;
@@ -1960,6 +2009,9 @@ int ieee80211_reconfig(struct ieee80211_local *local)
        mb();
        local->resuming = false;
 
+       if (!reconfig_due_to_wowlan)
+               drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND);
+
        list_for_each_entry(sdata, &local->interfaces, list) {
                if (!ieee80211_sdata_running(sdata))
                        continue;
@@ -2052,16 +2104,34 @@ static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
        return false;
 }
 
-size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
-                         const u8 *ids, int n_ids, size_t offset)
+size_t ieee80211_ie_split_ric(const u8 *ies, size_t ielen,
+                             const u8 *ids, int n_ids,
+                             const u8 *after_ric, int n_after_ric,
+                             size_t offset)
 {
        size_t pos = offset;
 
-       while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos]))
-               pos += 2 + ies[pos + 1];
+       while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos])) {
+               if (ies[pos] == WLAN_EID_RIC_DATA && n_after_ric) {
+                       pos += 2 + ies[pos + 1];
+
+                       while (pos < ielen &&
+                              !ieee80211_id_in_list(after_ric, n_after_ric,
+                                                    ies[pos]))
+                               pos += 2 + ies[pos + 1];
+               } else {
+                       pos += 2 + ies[pos + 1];
+               }
+       }
 
        return pos;
 }
+
+size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
+                         const u8 *ids, int n_ids, size_t offset)
+{
+       return ieee80211_ie_split_ric(ies, ielen, ids, n_ids, NULL, 0, offset);
+}
 EXPORT_SYMBOL(ieee80211_ie_split);
 
 size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)