* @NL80211_STA_FLAG_WME: station is WME/QoS capable
  * @NL80211_STA_FLAG_MFP: station uses management frame protection
  * @NL80211_STA_FLAG_AUTHENTICATED: station is authenticated
+ * @NL80211_STA_FLAG_TDLS_PEER: station is a TDLS peer
  * @NL80211_STA_FLAG_MAX: highest station flag number currently defined
  * @__NL80211_STA_FLAG_AFTER_LAST: internal use
  */
        NL80211_STA_FLAG_WME,
        NL80211_STA_FLAG_MFP,
        NL80211_STA_FLAG_AUTHENTICATED,
+       NL80211_STA_FLAG_TDLS_PEER,
 
        /* keep last */
        __NL80211_STA_FLAG_AFTER_LAST,
 
                if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
                        sta->flags |= WLAN_STA_AUTH;
        }
+
+       if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
+               sta->flags &= ~WLAN_STA_TDLS_PEER;
+               if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
+                       sta->flags |= WLAN_STA_TDLS_PEER;
+       }
        spin_unlock_irqrestore(&sta->flaglock, flags);
 
        if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) {
 
        sta_apply_parameters(local, sta, params);
 
+       /* Only TDLS-supporting stations can add TDLS peers */
+       if ((sta->flags & WLAN_STA_TDLS_PEER) &&
+           !((wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
+             sdata->vif.type == NL80211_IFTYPE_STATION))
+               return -ENOTSUPP;
+
        rate_control_rate_init(sta);
 
        layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN ||
                return -ENOENT;
        }
 
+       /* The TDLS bit cannot be toggled after the STA was added */
+       if ((params->sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
+           !!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) !=
+           !!test_sta_flags(sta, WLAN_STA_TDLS_PEER)) {
+               rcu_read_unlock();
+               return -EINVAL;
+       }
+
        if (params->vlan && params->vlan != sta->sdata->dev) {
                vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
 
 
        changed |= BSS_CHANGED_BSSID | BSS_CHANGED_HT;
        ieee80211_bss_info_change_notify(sdata, changed);
 
+       /* remove AP and TDLS peers */
        if (remove_sta)
-               sta_info_destroy_addr(sdata, bssid);
+               sta_info_flush(local, sdata);
 
        del_timer_sync(&sdata->u.mgd.conn_mon_timer);
        del_timer_sync(&sdata->u.mgd.bcn_mon_timer);
                                       req->reason_code, cookie,
                                       !req->local_state_change);
        if (assoc_bss)
-               sta_info_destroy_addr(sdata, bssid);
+               sta_info_flush(sdata->local, sdata);
 
        mutex_lock(&sdata->local->mtx);
        ieee80211_recalc_idle(sdata->local);
        ieee80211_send_deauth_disassoc(sdata, req->bss->bssid,
                        IEEE80211_STYPE_DISASSOC, req->reason_code,
                        cookie, !req->local_state_change);
-       sta_info_destroy_addr(sdata, bssid);
+       sta_info_flush(sdata->local, sdata);
 
        mutex_lock(&sdata->local->mtx);
        ieee80211_recalc_idle(sdata->local);
 
  *     station in power-save mode, reply when the driver unblocks.
  * @WLAN_STA_PS_DRIVER_BUF: Station has frames pending in driver internal
  *     buffers. Automatically cleared on station wake-up.
+ * @WLAN_STA_TDLS_PEER: station is a TDLS peer.
  */
 enum ieee80211_sta_info_flags {
        WLAN_STA_AUTH           = 1<<0,
        WLAN_STA_PS_DRIVER      = 1<<12,
        WLAN_STA_PSPOLL         = 1<<13,
        WLAN_STA_PS_DRIVER_BUF  = 1<<14,
+       WLAN_STA_TDLS_PEER      = 1<<15,
 };
 
 #define STA_TID_NUM 16
 
                break;
        case NL80211_IFTYPE_P2P_CLIENT:
        case NL80211_IFTYPE_STATION:
-               /* disallow everything but AUTHORIZED flag */
+               /* disallow things sta doesn't support */
                if (params.plink_action)
                        err = -EINVAL;
                if (params.vlan)
                        err = -EINVAL;
-               if (params.supported_rates)
+               if (params.supported_rates &&
+                   !(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)))
                        err = -EINVAL;
                if (params.ht_capa)
                        err = -EINVAL;
                if (params.listen_interval >= 0)
                        err = -EINVAL;
-               if (params.sta_flags_mask & ~BIT(NL80211_STA_FLAG_AUTHORIZED))
+               if (params.sta_flags_mask &
+                               ~(BIT(NL80211_STA_FLAG_AUTHORIZED) |
+                                 BIT(NL80211_STA_FLAG_TDLS_PEER)))
+                       err = -EINVAL;
+               /* can't change the TDLS bit */
+               if (!(params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
+                   (params.sta_flags_mask & BIT(NL80211_STA_FLAG_TDLS_PEER)))
                        err = -EINVAL;
                break;
        case NL80211_IFTYPE_MESH_POINT:
        if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP &&
            dev->ieee80211_ptr->iftype != NL80211_IFTYPE_AP_VLAN &&
            dev->ieee80211_ptr->iftype != NL80211_IFTYPE_MESH_POINT &&
-           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO)
+           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_P2P_GO &&
+           dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION)
+               return -EINVAL;
+
+       /*
+        * Only managed stations can add TDLS peers, and only when the
+        * wiphy supports external TDLS setup.
+        */
+       if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION &&
+           !((params.sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER)) &&
+             (rdev->wiphy.flags & WIPHY_FLAG_SUPPORTS_TDLS) &&
+             (rdev->wiphy.flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)))
                return -EINVAL;
 
        err = get_vlan(info, rdev, ¶ms.vlan);