These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / net / mac80211 / mesh.c
index 817098a..6f85b6a 100644 (file)
@@ -94,6 +94,9 @@ bool mesh_matches_local(struct ieee80211_sub_if_data *sdata,
        ieee80211_ht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan,
                                     ie->ht_operation, &sta_chan_def);
 
+       ieee80211_vht_oper_to_chandef(sdata->vif.bss_conf.chandef.chan,
+                                     ie->vht_operation, &sta_chan_def);
+
        if (!cfg80211_chandef_compatible(&sdata->vif.bss_conf.chandef,
                                         &sta_chan_def))
                return false;
@@ -158,7 +161,7 @@ void mesh_sta_cleanup(struct sta_info *sta)
        changed = mesh_accept_plinks_update(sdata);
        if (!sdata->u.mesh.user_mpm) {
                changed |= mesh_plink_deactivate(sta);
-               del_timer_sync(&sta->plink_timer);
+               del_timer_sync(&sta->mesh->plink_timer);
        }
 
        if (changed)
@@ -436,8 +439,6 @@ int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata,
        struct ieee80211_local *local = sdata->local;
        struct ieee80211_chanctx_conf *chanctx_conf;
        struct ieee80211_channel *channel;
-       enum nl80211_channel_type channel_type =
-               cfg80211_get_chandef_type(&sdata->vif.bss_conf.chandef);
        struct ieee80211_supported_band *sband;
        struct ieee80211_sta_ht_cap *ht_cap;
        u8 *pos;
@@ -454,7 +455,10 @@ int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata,
        sband = local->hw.wiphy->bands[channel->band];
        ht_cap = &sband->ht_cap;
 
-       if (!ht_cap->ht_supported || channel_type == NL80211_CHAN_NO_HT)
+       if (!ht_cap->ht_supported ||
+           sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
+           sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
+           sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
                return 0;
 
        if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_ht_operation))
@@ -462,7 +466,70 @@ int mesh_add_ht_oper_ie(struct ieee80211_sub_if_data *sdata,
 
        pos = skb_put(skb, 2 + sizeof(struct ieee80211_ht_operation));
        ieee80211_ie_build_ht_oper(pos, ht_cap, &sdata->vif.bss_conf.chandef,
-                                  sdata->vif.bss_conf.ht_operation_mode);
+                                  sdata->vif.bss_conf.ht_operation_mode,
+                                  false);
+
+       return 0;
+}
+
+int mesh_add_vht_cap_ie(struct ieee80211_sub_if_data *sdata,
+                       struct sk_buff *skb)
+{
+       struct ieee80211_local *local = sdata->local;
+       enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
+       struct ieee80211_supported_band *sband;
+       u8 *pos;
+
+       sband = local->hw.wiphy->bands[band];
+       if (!sband->vht_cap.vht_supported ||
+           sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
+           sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
+           sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
+               return 0;
+
+       if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_vht_cap))
+               return -ENOMEM;
+
+       pos = skb_put(skb, 2 + sizeof(struct ieee80211_vht_cap));
+       ieee80211_ie_build_vht_cap(pos, &sband->vht_cap, sband->vht_cap.cap);
+
+       return 0;
+}
+
+int mesh_add_vht_oper_ie(struct ieee80211_sub_if_data *sdata,
+                        struct sk_buff *skb)
+{
+       struct ieee80211_local *local = sdata->local;
+       struct ieee80211_chanctx_conf *chanctx_conf;
+       struct ieee80211_channel *channel;
+       struct ieee80211_supported_band *sband;
+       struct ieee80211_sta_vht_cap *vht_cap;
+       u8 *pos;
+
+       rcu_read_lock();
+       chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
+       if (WARN_ON(!chanctx_conf)) {
+               rcu_read_unlock();
+               return -EINVAL;
+       }
+       channel = chanctx_conf->def.chan;
+       rcu_read_unlock();
+
+       sband = local->hw.wiphy->bands[channel->band];
+       vht_cap = &sband->vht_cap;
+
+       if (!vht_cap->vht_supported ||
+           sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT ||
+           sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_5 ||
+           sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_10)
+               return 0;
+
+       if (skb_tailroom(skb) < 2 + sizeof(struct ieee80211_vht_operation))
+               return -ENOMEM;
+
+       pos = skb_put(skb, 2 + sizeof(struct ieee80211_vht_operation));
+       ieee80211_ie_build_vht_oper(pos, vht_cap,
+                                   &sdata->vif.bss_conf.chandef);
 
        return 0;
 }
@@ -540,9 +607,9 @@ int ieee80211_fill_mesh_addresses(struct ieee80211_hdr *hdr, __le16 *fc,
  *
  * Return the header length.
  */
-int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata,
-                             struct ieee80211s_hdr *meshhdr,
-                             const char *addr4or5, const char *addr6)
+unsigned int ieee80211_new_mesh_header(struct ieee80211_sub_if_data *sdata,
+                                      struct ieee80211s_hdr *meshhdr,
+                                      const char *addr4or5, const char *addr6)
 {
        if (WARN_ON(!addr4or5 && addr6))
                return 0;
@@ -637,6 +704,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
                   2 + ifmsh->mesh_id_len +
                   2 + sizeof(struct ieee80211_meshconf_ie) +
                   2 + sizeof(__le16) + /* awake window */
+                  2 + sizeof(struct ieee80211_vht_cap) +
+                  2 + sizeof(struct ieee80211_vht_operation) +
                   ifmsh->ie_len;
 
        bcn = kzalloc(sizeof(*bcn) + head_len + tail_len, GFP_KERNEL);
@@ -718,6 +787,8 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
            mesh_add_meshid_ie(sdata, skb) ||
            mesh_add_meshconf_ie(sdata, skb) ||
            mesh_add_awake_window_ie(sdata, skb) ||
+           mesh_add_vht_cap_ie(sdata, skb) ||
+           mesh_add_vht_oper_ie(sdata, skb) ||
            mesh_add_vendor_ies(sdata, skb))
                goto out_free;
 
@@ -1299,17 +1370,6 @@ out:
        sdata_unlock(sdata);
 }
 
-void ieee80211_mesh_notify_scan_completed(struct ieee80211_local *local)
-{
-       struct ieee80211_sub_if_data *sdata;
-
-       rcu_read_lock();
-       list_for_each_entry_rcu(sdata, &local->interfaces, list)
-               if (ieee80211_vif_is_mesh(&sdata->vif) &&
-                   ieee80211_sdata_running(sdata))
-                       ieee80211_queue_work(&local->hw, &sdata->work);
-       rcu_read_unlock();
-}
 
 void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
 {