LCOV - code coverage report
Current view: top level - net/mac80211 - cfg.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 1630 0.0 %
Date: 2022-04-01 14:35:51 Functions: 0 93 0.0 %
Branches: 0 981 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * mac80211 configuration hooks for cfg80211
       4                 :            :  *
       5                 :            :  * Copyright 2006-2010  Johannes Berg <johannes@sipsolutions.net>
       6                 :            :  * Copyright 2013-2015  Intel Mobile Communications GmbH
       7                 :            :  * Copyright (C) 2015-2017 Intel Deutschland GmbH
       8                 :            :  * Copyright (C) 2018-2019 Intel Corporation
       9                 :            :  * Copyright (C) 2018 Intel Corporation
      10                 :            :  */
      11                 :            : 
      12                 :            : #include <linux/ieee80211.h>
      13                 :            : #include <linux/nl80211.h>
      14                 :            : #include <linux/rtnetlink.h>
      15                 :            : #include <linux/slab.h>
      16                 :            : #include <net/net_namespace.h>
      17                 :            : #include <linux/rcupdate.h>
      18                 :            : #include <linux/fips.h>
      19                 :            : #include <linux/if_ether.h>
      20                 :            : #include <net/cfg80211.h>
      21                 :            : #include "ieee80211_i.h"
      22                 :            : #include "driver-ops.h"
      23                 :            : #include "rate.h"
      24                 :            : #include "mesh.h"
      25                 :            : #include "wme.h"
      26                 :            : 
      27                 :            : static void ieee80211_set_mu_mimo_follow(struct ieee80211_sub_if_data *sdata,
      28                 :            :                                          struct vif_params *params)
      29                 :            : {
      30                 :            :         bool mu_mimo_groups = false;
      31                 :            :         bool mu_mimo_follow = false;
      32                 :            : 
      33                 :            :         if (params->vht_mumimo_groups) {
      34                 :            :                 u64 membership;
      35                 :            : 
      36                 :            :                 BUILD_BUG_ON(sizeof(membership) != WLAN_MEMBERSHIP_LEN);
      37                 :            : 
      38                 :            :                 memcpy(sdata->vif.bss_conf.mu_group.membership,
      39                 :            :                        params->vht_mumimo_groups, WLAN_MEMBERSHIP_LEN);
      40                 :            :                 memcpy(sdata->vif.bss_conf.mu_group.position,
      41                 :            :                        params->vht_mumimo_groups + WLAN_MEMBERSHIP_LEN,
      42                 :            :                        WLAN_USER_POSITION_LEN);
      43                 :            :                 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_MU_GROUPS);
      44                 :            :                 /* don't care about endianness - just check for 0 */
      45                 :            :                 memcpy(&membership, params->vht_mumimo_groups,
      46                 :            :                        WLAN_MEMBERSHIP_LEN);
      47                 :            :                 mu_mimo_groups = membership != 0;
      48                 :            :         }
      49                 :            : 
      50                 :            :         if (params->vht_mumimo_follow_addr) {
      51                 :            :                 mu_mimo_follow =
      52                 :            :                         is_valid_ether_addr(params->vht_mumimo_follow_addr);
      53                 :            :                 ether_addr_copy(sdata->u.mntr.mu_follow_addr,
      54                 :            :                                 params->vht_mumimo_follow_addr);
      55                 :            :         }
      56                 :            : 
      57                 :            :         sdata->vif.mu_mimo_owner = mu_mimo_groups || mu_mimo_follow;
      58                 :            : }
      59                 :            : 
      60                 :          0 : static int ieee80211_set_mon_options(struct ieee80211_sub_if_data *sdata,
      61                 :            :                                      struct vif_params *params)
      62                 :            : {
      63                 :          0 :         struct ieee80211_local *local = sdata->local;
      64                 :          0 :         struct ieee80211_sub_if_data *monitor_sdata;
      65                 :            : 
      66                 :            :         /* check flags first */
      67   [ #  #  #  # ]:          0 :         if (params->flags && ieee80211_sdata_running(sdata)) {
      68                 :          0 :                 u32 mask = MONITOR_FLAG_COOK_FRAMES | MONITOR_FLAG_ACTIVE;
      69                 :            : 
      70                 :            :                 /*
      71                 :            :                  * Prohibit MONITOR_FLAG_COOK_FRAMES and
      72                 :            :                  * MONITOR_FLAG_ACTIVE to be changed while the
      73                 :            :                  * interface is up.
      74                 :            :                  * Else we would need to add a lot of cruft
      75                 :            :                  * to update everything:
      76                 :            :                  *      cooked_mntrs, monitor and all fif_* counters
      77                 :            :                  *      reconfigure hardware
      78                 :            :                  */
      79         [ #  # ]:          0 :                 if ((params->flags & mask) != (sdata->u.mntr.flags & mask))
      80                 :            :                         return -EBUSY;
      81                 :            :         }
      82                 :            : 
      83                 :            :         /* also validate MU-MIMO change */
      84                 :          0 :         monitor_sdata = rtnl_dereference(local->monitor_sdata);
      85                 :            : 
      86         [ #  # ]:          0 :         if (!monitor_sdata &&
      87   [ #  #  #  # ]:          0 :             (params->vht_mumimo_groups || params->vht_mumimo_follow_addr))
      88                 :            :                 return -EOPNOTSUPP;
      89                 :            : 
      90                 :            :         /* apply all changes now - no failures allowed */
      91                 :            : 
      92         [ #  # ]:          0 :         if (monitor_sdata)
      93                 :          0 :                 ieee80211_set_mu_mimo_follow(monitor_sdata, params);
      94                 :            : 
      95         [ #  # ]:          0 :         if (params->flags) {
      96         [ #  # ]:          0 :                 if (ieee80211_sdata_running(sdata)) {
      97                 :          0 :                         ieee80211_adjust_monitor_flags(sdata, -1);
      98                 :          0 :                         sdata->u.mntr.flags = params->flags;
      99                 :          0 :                         ieee80211_adjust_monitor_flags(sdata, 1);
     100                 :            : 
     101                 :          0 :                         ieee80211_configure_filter(local);
     102                 :            :                 } else {
     103                 :            :                         /*
     104                 :            :                          * Because the interface is down, ieee80211_do_stop
     105                 :            :                          * and ieee80211_do_open take care of "everything"
     106                 :            :                          * mentioned in the comment above.
     107                 :            :                          */
     108                 :          0 :                         sdata->u.mntr.flags = params->flags;
     109                 :            :                 }
     110                 :            :         }
     111                 :            : 
     112                 :            :         return 0;
     113                 :            : }
     114                 :            : 
     115                 :          0 : static struct wireless_dev *ieee80211_add_iface(struct wiphy *wiphy,
     116                 :            :                                                 const char *name,
     117                 :            :                                                 unsigned char name_assign_type,
     118                 :            :                                                 enum nl80211_iftype type,
     119                 :            :                                                 struct vif_params *params)
     120                 :            : {
     121         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
     122                 :          0 :         struct wireless_dev *wdev;
     123                 :          0 :         struct ieee80211_sub_if_data *sdata;
     124                 :          0 :         int err;
     125                 :            : 
     126                 :          0 :         err = ieee80211_if_add(local, name, name_assign_type, &wdev, type, params);
     127         [ #  # ]:          0 :         if (err)
     128                 :          0 :                 return ERR_PTR(err);
     129                 :            : 
     130         [ #  # ]:          0 :         sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
     131                 :            : 
     132         [ #  # ]:          0 :         if (type == NL80211_IFTYPE_MONITOR) {
     133                 :          0 :                 err = ieee80211_set_mon_options(sdata, params);
     134         [ #  # ]:          0 :                 if (err) {
     135                 :          0 :                         ieee80211_if_remove(sdata);
     136                 :          0 :                         return NULL;
     137                 :            :                 }
     138                 :            :         }
     139                 :            : 
     140                 :          0 :         return wdev;
     141                 :            : }
     142                 :            : 
     143                 :          0 : static int ieee80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
     144                 :            : {
     145                 :          0 :         ieee80211_if_remove(IEEE80211_WDEV_TO_SUB_IF(wdev));
     146                 :            : 
     147                 :          0 :         return 0;
     148                 :            : }
     149                 :            : 
     150                 :          0 : static int ieee80211_change_iface(struct wiphy *wiphy,
     151                 :            :                                   struct net_device *dev,
     152                 :            :                                   enum nl80211_iftype type,
     153                 :            :                                   struct vif_params *params)
     154                 :            : {
     155                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
     156                 :          0 :         int ret;
     157                 :            : 
     158                 :          0 :         ret = ieee80211_if_change_type(sdata, type);
     159         [ #  # ]:          0 :         if (ret)
     160                 :            :                 return ret;
     161                 :            : 
     162   [ #  #  #  # ]:          0 :         if (type == NL80211_IFTYPE_AP_VLAN && params->use_4addr == 0) {
     163                 :          0 :                 RCU_INIT_POINTER(sdata->u.vlan.sta, NULL);
     164                 :          0 :                 ieee80211_check_fast_rx_iface(sdata);
     165   [ #  #  #  # ]:          0 :         } else if (type == NL80211_IFTYPE_STATION && params->use_4addr >= 0) {
     166                 :          0 :                 sdata->u.mgd.use_4addr = params->use_4addr;
     167                 :            :         }
     168                 :            : 
     169         [ #  # ]:          0 :         if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
     170                 :          0 :                 ret = ieee80211_set_mon_options(sdata, params);
     171         [ #  # ]:          0 :                 if (ret)
     172                 :          0 :                         return ret;
     173                 :            :         }
     174                 :            : 
     175                 :            :         return 0;
     176                 :            : }
     177                 :            : 
     178                 :          0 : static int ieee80211_start_p2p_device(struct wiphy *wiphy,
     179                 :            :                                       struct wireless_dev *wdev)
     180                 :            : {
     181                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
     182                 :          0 :         int ret;
     183                 :            : 
     184                 :          0 :         mutex_lock(&sdata->local->chanctx_mtx);
     185                 :          0 :         ret = ieee80211_check_combinations(sdata, NULL, 0, 0);
     186                 :          0 :         mutex_unlock(&sdata->local->chanctx_mtx);
     187         [ #  # ]:          0 :         if (ret < 0)
     188                 :            :                 return ret;
     189                 :            : 
     190                 :          0 :         return ieee80211_do_open(wdev, true);
     191                 :            : }
     192                 :            : 
     193                 :          0 : static void ieee80211_stop_p2p_device(struct wiphy *wiphy,
     194                 :            :                                       struct wireless_dev *wdev)
     195                 :            : {
     196                 :          0 :         ieee80211_sdata_stop(IEEE80211_WDEV_TO_SUB_IF(wdev));
     197                 :          0 : }
     198                 :            : 
     199                 :          0 : static int ieee80211_start_nan(struct wiphy *wiphy,
     200                 :            :                                struct wireless_dev *wdev,
     201                 :            :                                struct cfg80211_nan_conf *conf)
     202                 :            : {
     203                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
     204                 :          0 :         int ret;
     205                 :            : 
     206                 :          0 :         mutex_lock(&sdata->local->chanctx_mtx);
     207                 :          0 :         ret = ieee80211_check_combinations(sdata, NULL, 0, 0);
     208                 :          0 :         mutex_unlock(&sdata->local->chanctx_mtx);
     209         [ #  # ]:          0 :         if (ret < 0)
     210                 :            :                 return ret;
     211                 :            : 
     212                 :          0 :         ret = ieee80211_do_open(wdev, true);
     213         [ #  # ]:          0 :         if (ret)
     214                 :            :                 return ret;
     215                 :            : 
     216                 :          0 :         ret = drv_start_nan(sdata->local, sdata, conf);
     217         [ #  # ]:          0 :         if (ret)
     218                 :          0 :                 ieee80211_sdata_stop(sdata);
     219                 :            : 
     220                 :          0 :         sdata->u.nan.conf = *conf;
     221                 :            : 
     222                 :          0 :         return ret;
     223                 :            : }
     224                 :            : 
     225                 :          0 : static void ieee80211_stop_nan(struct wiphy *wiphy,
     226                 :            :                                struct wireless_dev *wdev)
     227                 :            : {
     228                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
     229                 :            : 
     230                 :          0 :         drv_stop_nan(sdata->local, sdata);
     231                 :          0 :         ieee80211_sdata_stop(sdata);
     232                 :          0 : }
     233                 :            : 
     234                 :          0 : static int ieee80211_nan_change_conf(struct wiphy *wiphy,
     235                 :            :                                      struct wireless_dev *wdev,
     236                 :            :                                      struct cfg80211_nan_conf *conf,
     237                 :            :                                      u32 changes)
     238                 :            : {
     239         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
     240                 :          0 :         struct cfg80211_nan_conf new_conf;
     241                 :          0 :         int ret = 0;
     242                 :            : 
     243         [ #  # ]:          0 :         if (sdata->vif.type != NL80211_IFTYPE_NAN)
     244                 :            :                 return -EOPNOTSUPP;
     245                 :            : 
     246         [ #  # ]:          0 :         if (!ieee80211_sdata_running(sdata))
     247                 :            :                 return -ENETDOWN;
     248                 :            : 
     249                 :          0 :         new_conf = sdata->u.nan.conf;
     250                 :            : 
     251         [ #  # ]:          0 :         if (changes & CFG80211_NAN_CONF_CHANGED_PREF)
     252                 :          0 :                 new_conf.master_pref = conf->master_pref;
     253                 :            : 
     254         [ #  # ]:          0 :         if (changes & CFG80211_NAN_CONF_CHANGED_BANDS)
     255                 :          0 :                 new_conf.bands = conf->bands;
     256                 :            : 
     257                 :          0 :         ret = drv_nan_change_conf(sdata->local, sdata, &new_conf, changes);
     258         [ #  # ]:          0 :         if (!ret)
     259                 :          0 :                 sdata->u.nan.conf = new_conf;
     260                 :            : 
     261                 :            :         return ret;
     262                 :            : }
     263                 :            : 
     264                 :          0 : static int ieee80211_add_nan_func(struct wiphy *wiphy,
     265                 :            :                                   struct wireless_dev *wdev,
     266                 :            :                                   struct cfg80211_nan_func *nan_func)
     267                 :            : {
     268         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
     269                 :          0 :         int ret;
     270                 :            : 
     271         [ #  # ]:          0 :         if (sdata->vif.type != NL80211_IFTYPE_NAN)
     272                 :            :                 return -EOPNOTSUPP;
     273                 :            : 
     274         [ #  # ]:          0 :         if (!ieee80211_sdata_running(sdata))
     275                 :            :                 return -ENETDOWN;
     276                 :            : 
     277                 :          0 :         spin_lock_bh(&sdata->u.nan.func_lock);
     278                 :            : 
     279                 :          0 :         ret = idr_alloc(&sdata->u.nan.function_inst_ids,
     280                 :          0 :                         nan_func, 1, sdata->local->hw.max_nan_de_entries + 1,
     281                 :            :                         GFP_ATOMIC);
     282                 :          0 :         spin_unlock_bh(&sdata->u.nan.func_lock);
     283                 :            : 
     284         [ #  # ]:          0 :         if (ret < 0)
     285                 :            :                 return ret;
     286                 :            : 
     287                 :          0 :         nan_func->instance_id = ret;
     288                 :            : 
     289         [ #  # ]:          0 :         WARN_ON(nan_func->instance_id == 0);
     290                 :            : 
     291                 :          0 :         ret = drv_add_nan_func(sdata->local, sdata, nan_func);
     292         [ #  # ]:          0 :         if (ret) {
     293                 :          0 :                 spin_lock_bh(&sdata->u.nan.func_lock);
     294                 :          0 :                 idr_remove(&sdata->u.nan.function_inst_ids,
     295                 :          0 :                            nan_func->instance_id);
     296                 :          0 :                 spin_unlock_bh(&sdata->u.nan.func_lock);
     297                 :            :         }
     298                 :            : 
     299                 :            :         return ret;
     300                 :            : }
     301                 :            : 
     302                 :            : static struct cfg80211_nan_func *
     303                 :          0 : ieee80211_find_nan_func_by_cookie(struct ieee80211_sub_if_data *sdata,
     304                 :            :                                   u64 cookie)
     305                 :            : {
     306                 :          0 :         struct cfg80211_nan_func *func;
     307                 :          0 :         int id;
     308                 :            : 
     309                 :          0 :         lockdep_assert_held(&sdata->u.nan.func_lock);
     310                 :            : 
     311         [ #  # ]:          0 :         idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, id) {
     312         [ #  # ]:          0 :                 if (func->cookie == cookie)
     313                 :          0 :                         return func;
     314                 :            :         }
     315                 :            : 
     316                 :            :         return NULL;
     317                 :            : }
     318                 :            : 
     319                 :          0 : static void ieee80211_del_nan_func(struct wiphy *wiphy,
     320                 :            :                                   struct wireless_dev *wdev, u64 cookie)
     321                 :            : {
     322         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
     323                 :          0 :         struct cfg80211_nan_func *func;
     324                 :          0 :         u8 instance_id = 0;
     325                 :            : 
     326   [ #  #  #  # ]:          0 :         if (sdata->vif.type != NL80211_IFTYPE_NAN ||
     327                 :            :             !ieee80211_sdata_running(sdata))
     328                 :          0 :                 return;
     329                 :            : 
     330                 :          0 :         spin_lock_bh(&sdata->u.nan.func_lock);
     331                 :            : 
     332                 :          0 :         func = ieee80211_find_nan_func_by_cookie(sdata, cookie);
     333         [ #  # ]:          0 :         if (func)
     334                 :          0 :                 instance_id = func->instance_id;
     335                 :            : 
     336                 :          0 :         spin_unlock_bh(&sdata->u.nan.func_lock);
     337                 :            : 
     338         [ #  # ]:          0 :         if (instance_id)
     339                 :          0 :                 drv_del_nan_func(sdata->local, sdata, instance_id);
     340                 :            : }
     341                 :            : 
     342                 :          0 : static int ieee80211_set_noack_map(struct wiphy *wiphy,
     343                 :            :                                   struct net_device *dev,
     344                 :            :                                   u16 noack_map)
     345                 :            : {
     346                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
     347                 :            : 
     348                 :          0 :         sdata->noack_map = noack_map;
     349                 :            : 
     350                 :          0 :         ieee80211_check_fast_xmit_iface(sdata);
     351                 :            : 
     352                 :          0 :         return 0;
     353                 :            : }
     354                 :            : 
     355                 :          0 : static int ieee80211_set_tx(struct ieee80211_sub_if_data *sdata,
     356                 :            :                             const u8 *mac_addr, u8 key_idx)
     357                 :            : {
     358                 :          0 :         struct ieee80211_local *local = sdata->local;
     359                 :          0 :         struct ieee80211_key *key;
     360                 :          0 :         struct sta_info *sta;
     361                 :          0 :         int ret = -EINVAL;
     362                 :            : 
     363         [ #  # ]:          0 :         if (!wiphy_ext_feature_isset(local->hw.wiphy,
     364                 :            :                                      NL80211_EXT_FEATURE_EXT_KEY_ID))
     365                 :            :                 return -EINVAL;
     366                 :            : 
     367                 :          0 :         sta = sta_info_get_bss(sdata, mac_addr);
     368                 :            : 
     369         [ #  # ]:          0 :         if (!sta)
     370                 :            :                 return -EINVAL;
     371                 :            : 
     372         [ #  # ]:          0 :         if (sta->ptk_idx == key_idx)
     373                 :            :                 return 0;
     374                 :            : 
     375                 :          0 :         mutex_lock(&local->key_mtx);
     376                 :          0 :         key = key_mtx_dereference(local, sta->ptk[key_idx]);
     377                 :            : 
     378   [ #  #  #  # ]:          0 :         if (key && key->conf.flags & IEEE80211_KEY_FLAG_NO_AUTO_TX)
     379                 :          0 :                 ret = ieee80211_set_tx_key(key);
     380                 :            : 
     381                 :          0 :         mutex_unlock(&local->key_mtx);
     382                 :          0 :         return ret;
     383                 :            : }
     384                 :            : 
     385                 :          0 : static int ieee80211_add_key(struct wiphy *wiphy, struct net_device *dev,
     386                 :            :                              u8 key_idx, bool pairwise, const u8 *mac_addr,
     387                 :            :                              struct key_params *params)
     388                 :            : {
     389                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
     390                 :          0 :         struct ieee80211_local *local = sdata->local;
     391                 :          0 :         struct sta_info *sta = NULL;
     392                 :          0 :         const struct ieee80211_cipher_scheme *cs = NULL;
     393                 :          0 :         struct ieee80211_key *key;
     394                 :          0 :         int err;
     395                 :            : 
     396         [ #  # ]:          0 :         if (!ieee80211_sdata_running(sdata))
     397                 :            :                 return -ENETDOWN;
     398                 :            : 
     399   [ #  #  #  # ]:          0 :         if (pairwise && params->mode == NL80211_KEY_SET_TX)
     400                 :          0 :                 return ieee80211_set_tx(sdata, mac_addr, key_idx);
     401                 :            : 
     402                 :            :         /* reject WEP and TKIP keys if WEP failed to initialize */
     403         [ #  # ]:          0 :         switch (params->cipher) {
     404                 :            :         case WLAN_CIPHER_SUITE_WEP40:
     405                 :            :         case WLAN_CIPHER_SUITE_TKIP:
     406                 :            :         case WLAN_CIPHER_SUITE_WEP104:
     407                 :            :                 if (WARN_ON_ONCE(fips_enabled))
     408                 :            :                         return -EINVAL;
     409                 :            :         case WLAN_CIPHER_SUITE_CCMP:
     410                 :            :         case WLAN_CIPHER_SUITE_CCMP_256:
     411                 :            :         case WLAN_CIPHER_SUITE_AES_CMAC:
     412                 :            :         case WLAN_CIPHER_SUITE_BIP_CMAC_256:
     413                 :            :         case WLAN_CIPHER_SUITE_BIP_GMAC_128:
     414                 :            :         case WLAN_CIPHER_SUITE_BIP_GMAC_256:
     415                 :            :         case WLAN_CIPHER_SUITE_GCMP:
     416                 :            :         case WLAN_CIPHER_SUITE_GCMP_256:
     417                 :            :                 break;
     418                 :          0 :         default:
     419                 :          0 :                 cs = ieee80211_cs_get(local, params->cipher, sdata->vif.type);
     420                 :          0 :                 break;
     421                 :            :         }
     422                 :            : 
     423                 :          0 :         key = ieee80211_key_alloc(params->cipher, key_idx, params->key_len,
     424                 :          0 :                                   params->key, params->seq_len, params->seq,
     425                 :            :                                   cs);
     426         [ #  # ]:          0 :         if (IS_ERR(key))
     427                 :          0 :                 return PTR_ERR(key);
     428                 :            : 
     429         [ #  # ]:          0 :         if (pairwise)
     430                 :          0 :                 key->conf.flags |= IEEE80211_KEY_FLAG_PAIRWISE;
     431                 :            : 
     432         [ #  # ]:          0 :         if (params->mode == NL80211_KEY_NO_TX)
     433                 :          0 :                 key->conf.flags |= IEEE80211_KEY_FLAG_NO_AUTO_TX;
     434                 :            : 
     435                 :          0 :         mutex_lock(&local->sta_mtx);
     436                 :            : 
     437         [ #  # ]:          0 :         if (mac_addr) {
     438                 :          0 :                 sta = sta_info_get_bss(sdata, mac_addr);
     439                 :            :                 /*
     440                 :            :                  * The ASSOC test makes sure the driver is ready to
     441                 :            :                  * receive the key. When wpa_supplicant has roamed
     442                 :            :                  * using FT, it attempts to set the key before
     443                 :            :                  * association has completed, this rejects that attempt
     444                 :            :                  * so it will set the key again after association.
     445                 :            :                  *
     446                 :            :                  * TODO: accept the key if we have a station entry and
     447                 :            :                  *       add it to the device after the station.
     448                 :            :                  */
     449   [ #  #  #  # ]:          0 :                 if (!sta || !test_sta_flag(sta, WLAN_STA_ASSOC)) {
     450                 :          0 :                         ieee80211_key_free_unused(key);
     451                 :          0 :                         err = -ENOENT;
     452                 :          0 :                         goto out_unlock;
     453                 :            :                 }
     454                 :            :         }
     455                 :            : 
     456   [ #  #  #  # ]:          0 :         switch (sdata->vif.type) {
     457                 :          0 :         case NL80211_IFTYPE_STATION:
     458         [ #  # ]:          0 :                 if (sdata->u.mgd.mfp != IEEE80211_MFP_DISABLED)
     459                 :          0 :                         key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT;
     460                 :            :                 break;
     461                 :          0 :         case NL80211_IFTYPE_AP:
     462                 :            :         case NL80211_IFTYPE_AP_VLAN:
     463                 :            :                 /* Keys without a station are used for TX only */
     464   [ #  #  #  # ]:          0 :                 if (sta && test_sta_flag(sta, WLAN_STA_MFP))
     465                 :          0 :                         key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT;
     466                 :            :                 break;
     467                 :            :         case NL80211_IFTYPE_ADHOC:
     468                 :            :                 /* no MFP (yet) */
     469                 :            :                 break;
     470                 :            :         case NL80211_IFTYPE_MESH_POINT:
     471                 :            : #ifdef CONFIG_MAC80211_MESH
     472                 :            :                 if (sdata->u.mesh.security != IEEE80211_MESH_SEC_NONE)
     473                 :            :                         key->conf.flags |= IEEE80211_KEY_FLAG_RX_MGMT;
     474                 :            :                 break;
     475                 :            : #endif
     476                 :            :         case NL80211_IFTYPE_WDS:
     477                 :            :         case NL80211_IFTYPE_MONITOR:
     478                 :            :         case NL80211_IFTYPE_P2P_DEVICE:
     479                 :            :         case NL80211_IFTYPE_NAN:
     480                 :            :         case NL80211_IFTYPE_UNSPECIFIED:
     481                 :            :         case NUM_NL80211_IFTYPES:
     482                 :            :         case NL80211_IFTYPE_P2P_CLIENT:
     483                 :            :         case NL80211_IFTYPE_P2P_GO:
     484                 :            :         case NL80211_IFTYPE_OCB:
     485                 :            :                 /* shouldn't happen */
     486                 :          0 :                 WARN_ON_ONCE(1);
     487                 :          0 :                 break;
     488                 :            :         }
     489                 :            : 
     490         [ #  # ]:          0 :         if (sta)
     491                 :          0 :                 sta->cipher_scheme = cs;
     492                 :            : 
     493                 :          0 :         err = ieee80211_key_link(key, sdata, sta);
     494                 :            : 
     495                 :          0 :  out_unlock:
     496                 :          0 :         mutex_unlock(&local->sta_mtx);
     497                 :            : 
     498                 :          0 :         return err;
     499                 :            : }
     500                 :            : 
     501                 :          0 : static int ieee80211_del_key(struct wiphy *wiphy, struct net_device *dev,
     502                 :            :                              u8 key_idx, bool pairwise, const u8 *mac_addr)
     503                 :            : {
     504                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
     505                 :          0 :         struct ieee80211_local *local = sdata->local;
     506                 :          0 :         struct sta_info *sta;
     507                 :          0 :         struct ieee80211_key *key = NULL;
     508                 :          0 :         int ret;
     509                 :            : 
     510                 :          0 :         mutex_lock(&local->sta_mtx);
     511                 :          0 :         mutex_lock(&local->key_mtx);
     512                 :            : 
     513         [ #  # ]:          0 :         if (mac_addr) {
     514                 :          0 :                 ret = -ENOENT;
     515                 :            : 
     516                 :          0 :                 sta = sta_info_get_bss(sdata, mac_addr);
     517         [ #  # ]:          0 :                 if (!sta)
     518                 :          0 :                         goto out_unlock;
     519                 :            : 
     520         [ #  # ]:          0 :                 if (pairwise)
     521                 :          0 :                         key = key_mtx_dereference(local, sta->ptk[key_idx]);
     522                 :            :                 else
     523                 :          0 :                         key = key_mtx_dereference(local, sta->gtk[key_idx]);
     524                 :            :         } else
     525                 :          0 :                 key = key_mtx_dereference(local, sdata->keys[key_idx]);
     526                 :            : 
     527         [ #  # ]:          0 :         if (!key) {
     528                 :          0 :                 ret = -ENOENT;
     529                 :          0 :                 goto out_unlock;
     530                 :            :         }
     531                 :            : 
     532                 :          0 :         ieee80211_key_free(key, sdata->vif.type == NL80211_IFTYPE_STATION);
     533                 :            : 
     534                 :          0 :         ret = 0;
     535                 :          0 :  out_unlock:
     536                 :          0 :         mutex_unlock(&local->key_mtx);
     537                 :          0 :         mutex_unlock(&local->sta_mtx);
     538                 :            : 
     539                 :          0 :         return ret;
     540                 :            : }
     541                 :            : 
     542                 :          0 : static int ieee80211_get_key(struct wiphy *wiphy, struct net_device *dev,
     543                 :            :                              u8 key_idx, bool pairwise, const u8 *mac_addr,
     544                 :            :                              void *cookie,
     545                 :            :                              void (*callback)(void *cookie,
     546                 :            :                                               struct key_params *params))
     547                 :            : {
     548                 :          0 :         struct ieee80211_sub_if_data *sdata;
     549                 :          0 :         struct sta_info *sta = NULL;
     550                 :          0 :         u8 seq[6] = {0};
     551                 :          0 :         struct key_params params;
     552                 :          0 :         struct ieee80211_key *key = NULL;
     553                 :          0 :         u64 pn64;
     554                 :          0 :         u32 iv32;
     555                 :          0 :         u16 iv16;
     556                 :          0 :         int err = -ENOENT;
     557                 :          0 :         struct ieee80211_key_seq kseq = {};
     558                 :            : 
     559                 :          0 :         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
     560                 :            : 
     561                 :          0 :         rcu_read_lock();
     562                 :            : 
     563         [ #  # ]:          0 :         if (mac_addr) {
     564                 :          0 :                 sta = sta_info_get_bss(sdata, mac_addr);
     565         [ #  # ]:          0 :                 if (!sta)
     566                 :          0 :                         goto out;
     567                 :            : 
     568         [ #  # ]:          0 :                 if (pairwise && key_idx < NUM_DEFAULT_KEYS)
     569                 :          0 :                         key = rcu_dereference(sta->ptk[key_idx]);
     570                 :          0 :                 else if (!pairwise &&
     571         [ #  # ]:          0 :                          key_idx < NUM_DEFAULT_KEYS + NUM_DEFAULT_MGMT_KEYS)
     572                 :          0 :                         key = rcu_dereference(sta->gtk[key_idx]);
     573                 :            :         } else
     574                 :          0 :                 key = rcu_dereference(sdata->keys[key_idx]);
     575                 :            : 
     576         [ #  # ]:          0 :         if (!key)
     577                 :          0 :                 goto out;
     578                 :            : 
     579                 :          0 :         memset(&params, 0, sizeof(params));
     580                 :            : 
     581                 :          0 :         params.cipher = key->conf.cipher;
     582                 :            : 
     583      [ #  #  # ]:          0 :         switch (key->conf.cipher) {
     584                 :          0 :         case WLAN_CIPHER_SUITE_TKIP:
     585                 :          0 :                 pn64 = atomic64_read(&key->conf.tx_pn);
     586                 :          0 :                 iv32 = TKIP_PN_TO_IV32(pn64);
     587                 :          0 :                 iv16 = TKIP_PN_TO_IV16(pn64);
     588                 :            : 
     589         [ #  # ]:          0 :                 if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
     590         [ #  # ]:          0 :                     !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
     591                 :          0 :                         drv_get_key_seq(sdata->local, key, &kseq);
     592                 :          0 :                         iv32 = kseq.tkip.iv32;
     593                 :          0 :                         iv16 = kseq.tkip.iv16;
     594                 :            :                 }
     595                 :            : 
     596                 :          0 :                 seq[0] = iv16 & 0xff;
     597                 :          0 :                 seq[1] = (iv16 >> 8) & 0xff;
     598                 :          0 :                 seq[2] = iv32 & 0xff;
     599                 :          0 :                 seq[3] = (iv32 >> 8) & 0xff;
     600                 :          0 :                 seq[4] = (iv32 >> 16) & 0xff;
     601                 :          0 :                 seq[5] = (iv32 >> 24) & 0xff;
     602                 :          0 :                 params.seq = seq;
     603                 :          0 :                 params.seq_len = 6;
     604                 :          0 :                 break;
     605                 :            :         case WLAN_CIPHER_SUITE_CCMP:
     606                 :            :         case WLAN_CIPHER_SUITE_CCMP_256:
     607                 :            :         case WLAN_CIPHER_SUITE_AES_CMAC:
     608                 :            :         case WLAN_CIPHER_SUITE_BIP_CMAC_256:
     609                 :            :                 BUILD_BUG_ON(offsetof(typeof(kseq), ccmp) !=
     610                 :            :                              offsetof(typeof(kseq), aes_cmac));
     611                 :            :                 /* fall through */
     612                 :            :         case WLAN_CIPHER_SUITE_BIP_GMAC_128:
     613                 :            :         case WLAN_CIPHER_SUITE_BIP_GMAC_256:
     614                 :          0 :                 BUILD_BUG_ON(offsetof(typeof(kseq), ccmp) !=
     615                 :            :                              offsetof(typeof(kseq), aes_gmac));
     616                 :            :                 /* fall through */
     617                 :            :         case WLAN_CIPHER_SUITE_GCMP:
     618                 :            :         case WLAN_CIPHER_SUITE_GCMP_256:
     619                 :          0 :                 BUILD_BUG_ON(offsetof(typeof(kseq), ccmp) !=
     620                 :            :                              offsetof(typeof(kseq), gcmp));
     621                 :            : 
     622         [ #  # ]:          0 :                 if (key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE &&
     623         [ #  # ]:          0 :                     !(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV)) {
     624                 :          0 :                         drv_get_key_seq(sdata->local, key, &kseq);
     625                 :          0 :                         memcpy(seq, kseq.ccmp.pn, 6);
     626                 :            :                 } else {
     627                 :          0 :                         pn64 = atomic64_read(&key->conf.tx_pn);
     628                 :          0 :                         seq[0] = pn64;
     629                 :          0 :                         seq[1] = pn64 >> 8;
     630                 :          0 :                         seq[2] = pn64 >> 16;
     631                 :          0 :                         seq[3] = pn64 >> 24;
     632                 :          0 :                         seq[4] = pn64 >> 32;
     633                 :          0 :                         seq[5] = pn64 >> 40;
     634                 :            :                 }
     635                 :          0 :                 params.seq = seq;
     636                 :          0 :                 params.seq_len = 6;
     637                 :          0 :                 break;
     638                 :          0 :         default:
     639         [ #  # ]:          0 :                 if (!(key->flags & KEY_FLAG_UPLOADED_TO_HARDWARE))
     640                 :            :                         break;
     641   [ #  #  #  # ]:          0 :                 if (WARN_ON(key->conf.flags & IEEE80211_KEY_FLAG_GENERATE_IV))
     642                 :            :                         break;
     643                 :          0 :                 drv_get_key_seq(sdata->local, key, &kseq);
     644                 :          0 :                 params.seq = kseq.hw.seq;
     645                 :          0 :                 params.seq_len = kseq.hw.seq_len;
     646                 :          0 :                 break;
     647                 :            :         }
     648                 :            : 
     649                 :          0 :         params.key = key->conf.key;
     650                 :          0 :         params.key_len = key->conf.keylen;
     651                 :            : 
     652                 :          0 :         callback(cookie, &params);
     653                 :          0 :         err = 0;
     654                 :            : 
     655                 :          0 :  out:
     656                 :          0 :         rcu_read_unlock();
     657                 :          0 :         return err;
     658                 :            : }
     659                 :            : 
     660                 :          0 : static int ieee80211_config_default_key(struct wiphy *wiphy,
     661                 :            :                                         struct net_device *dev,
     662                 :            :                                         u8 key_idx, bool uni,
     663                 :            :                                         bool multi)
     664                 :            : {
     665                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
     666                 :            : 
     667                 :          0 :         ieee80211_set_default_key(sdata, key_idx, uni, multi);
     668                 :            : 
     669                 :          0 :         return 0;
     670                 :            : }
     671                 :            : 
     672                 :          0 : static int ieee80211_config_default_mgmt_key(struct wiphy *wiphy,
     673                 :            :                                              struct net_device *dev,
     674                 :            :                                              u8 key_idx)
     675                 :            : {
     676                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
     677                 :            : 
     678                 :          0 :         ieee80211_set_default_mgmt_key(sdata, key_idx);
     679                 :            : 
     680                 :          0 :         return 0;
     681                 :            : }
     682                 :            : 
     683                 :          0 : void sta_set_rate_info_tx(struct sta_info *sta,
     684                 :            :                           const struct ieee80211_tx_rate *rate,
     685                 :            :                           struct rate_info *rinfo)
     686                 :            : {
     687                 :          0 :         rinfo->flags = 0;
     688         [ #  # ]:          0 :         if (rate->flags & IEEE80211_TX_RC_MCS) {
     689                 :          0 :                 rinfo->flags |= RATE_INFO_FLAGS_MCS;
     690                 :          0 :                 rinfo->mcs = rate->idx;
     691         [ #  # ]:          0 :         } else if (rate->flags & IEEE80211_TX_RC_VHT_MCS) {
     692                 :          0 :                 rinfo->flags |= RATE_INFO_FLAGS_VHT_MCS;
     693                 :          0 :                 rinfo->mcs = ieee80211_rate_get_vht_mcs(rate);
     694                 :          0 :                 rinfo->nss = ieee80211_rate_get_vht_nss(rate);
     695                 :            :         } else {
     696                 :          0 :                 struct ieee80211_supported_band *sband;
     697                 :          0 :                 int shift = ieee80211_vif_get_shift(&sta->sdata->vif);
     698                 :          0 :                 u16 brate;
     699                 :            : 
     700                 :          0 :                 sband = ieee80211_get_sband(sta->sdata);
     701         [ #  # ]:          0 :                 if (sband) {
     702                 :          0 :                         brate = sband->bitrates[rate->idx].bitrate;
     703                 :          0 :                         rinfo->legacy = DIV_ROUND_UP(brate, 1 << shift);
     704                 :            :                 }
     705                 :            :         }
     706         [ #  # ]:          0 :         if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
     707                 :          0 :                 rinfo->bw = RATE_INFO_BW_40;
     708         [ #  # ]:          0 :         else if (rate->flags & IEEE80211_TX_RC_80_MHZ_WIDTH)
     709                 :          0 :                 rinfo->bw = RATE_INFO_BW_80;
     710         [ #  # ]:          0 :         else if (rate->flags & IEEE80211_TX_RC_160_MHZ_WIDTH)
     711                 :          0 :                 rinfo->bw = RATE_INFO_BW_160;
     712                 :            :         else
     713                 :          0 :                 rinfo->bw = RATE_INFO_BW_20;
     714         [ #  # ]:          0 :         if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
     715                 :          0 :                 rinfo->flags |= RATE_INFO_FLAGS_SHORT_GI;
     716                 :          0 : }
     717                 :            : 
     718                 :          0 : static int ieee80211_dump_station(struct wiphy *wiphy, struct net_device *dev,
     719                 :            :                                   int idx, u8 *mac, struct station_info *sinfo)
     720                 :            : {
     721                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
     722                 :          0 :         struct ieee80211_local *local = sdata->local;
     723                 :          0 :         struct sta_info *sta;
     724                 :          0 :         int ret = -ENOENT;
     725                 :            : 
     726                 :          0 :         mutex_lock(&local->sta_mtx);
     727                 :            : 
     728                 :          0 :         sta = sta_info_get_by_idx(sdata, idx);
     729         [ #  # ]:          0 :         if (sta) {
     730                 :          0 :                 ret = 0;
     731                 :          0 :                 memcpy(mac, sta->sta.addr, ETH_ALEN);
     732                 :          0 :                 sta_set_sinfo(sta, sinfo, true);
     733                 :            :         }
     734                 :            : 
     735                 :          0 :         mutex_unlock(&local->sta_mtx);
     736                 :            : 
     737                 :          0 :         return ret;
     738                 :            : }
     739                 :            : 
     740                 :          0 : static int ieee80211_dump_survey(struct wiphy *wiphy, struct net_device *dev,
     741                 :            :                                  int idx, struct survey_info *survey)
     742                 :            : {
     743                 :          0 :         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
     744                 :            : 
     745                 :          0 :         return drv_get_survey(local, idx, survey);
     746                 :            : }
     747                 :            : 
     748                 :          0 : static int ieee80211_get_station(struct wiphy *wiphy, struct net_device *dev,
     749                 :            :                                  const u8 *mac, struct station_info *sinfo)
     750                 :            : {
     751                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
     752                 :          0 :         struct ieee80211_local *local = sdata->local;
     753                 :          0 :         struct sta_info *sta;
     754                 :          0 :         int ret = -ENOENT;
     755                 :            : 
     756                 :          0 :         mutex_lock(&local->sta_mtx);
     757                 :            : 
     758                 :          0 :         sta = sta_info_get_bss(sdata, mac);
     759         [ #  # ]:          0 :         if (sta) {
     760                 :          0 :                 ret = 0;
     761                 :          0 :                 sta_set_sinfo(sta, sinfo, true);
     762                 :            :         }
     763                 :            : 
     764                 :          0 :         mutex_unlock(&local->sta_mtx);
     765                 :            : 
     766                 :          0 :         return ret;
     767                 :            : }
     768                 :            : 
     769                 :          0 : static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
     770                 :            :                                          struct cfg80211_chan_def *chandef)
     771                 :            : {
     772         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
     773                 :          0 :         struct ieee80211_sub_if_data *sdata;
     774                 :          0 :         int ret = 0;
     775                 :            : 
     776   [ #  #  #  # ]:          0 :         if (cfg80211_chandef_identical(&local->monitor_chandef, chandef))
     777                 :            :                 return 0;
     778                 :            : 
     779                 :          0 :         mutex_lock(&local->mtx);
     780         [ #  # ]:          0 :         if (local->use_chanctx) {
     781                 :          0 :                 sdata = rtnl_dereference(local->monitor_sdata);
     782         [ #  # ]:          0 :                 if (sdata) {
     783                 :          0 :                         ieee80211_vif_release_channel(sdata);
     784                 :          0 :                         ret = ieee80211_vif_use_channel(sdata, chandef,
     785                 :            :                                         IEEE80211_CHANCTX_EXCLUSIVE);
     786                 :            :                 }
     787         [ #  # ]:          0 :         } else if (local->open_count == local->monitors) {
     788                 :          0 :                 local->_oper_chandef = *chandef;
     789                 :          0 :                 ieee80211_hw_config(local, 0);
     790                 :            :         }
     791                 :            : 
     792         [ #  # ]:          0 :         if (ret == 0)
     793                 :          0 :                 local->monitor_chandef = *chandef;
     794                 :          0 :         mutex_unlock(&local->mtx);
     795                 :            : 
     796                 :          0 :         return ret;
     797                 :            : }
     798                 :            : 
     799                 :          0 : static int ieee80211_set_probe_resp(struct ieee80211_sub_if_data *sdata,
     800                 :            :                                     const u8 *resp, size_t resp_len,
     801                 :            :                                     const struct ieee80211_csa_settings *csa)
     802                 :            : {
     803                 :          0 :         struct probe_resp *new, *old;
     804                 :            : 
     805         [ #  # ]:          0 :         if (!resp || !resp_len)
     806                 :            :                 return 1;
     807                 :            : 
     808                 :          0 :         old = sdata_dereference(sdata->u.ap.probe_resp, sdata);
     809                 :            : 
     810                 :          0 :         new = kzalloc(sizeof(struct probe_resp) + resp_len, GFP_KERNEL);
     811         [ #  # ]:          0 :         if (!new)
     812                 :            :                 return -ENOMEM;
     813                 :            : 
     814                 :          0 :         new->len = resp_len;
     815                 :          0 :         memcpy(new->data, resp, resp_len);
     816                 :            : 
     817         [ #  # ]:          0 :         if (csa)
     818                 :          0 :                 memcpy(new->csa_counter_offsets, csa->counter_offsets_presp,
     819                 :          0 :                        csa->n_counter_offsets_presp *
     820                 :            :                        sizeof(new->csa_counter_offsets[0]));
     821                 :            : 
     822         [ #  # ]:          0 :         rcu_assign_pointer(sdata->u.ap.probe_resp, new);
     823         [ #  # ]:          0 :         if (old)
     824                 :          0 :                 kfree_rcu(old, rcu_head);
     825                 :            : 
     826                 :            :         return 0;
     827                 :            : }
     828                 :            : 
     829                 :          0 : static int ieee80211_set_ftm_responder_params(
     830                 :            :                                 struct ieee80211_sub_if_data *sdata,
     831                 :            :                                 const u8 *lci, size_t lci_len,
     832                 :            :                                 const u8 *civicloc, size_t civicloc_len)
     833                 :            : {
     834                 :          0 :         struct ieee80211_ftm_responder_params *new, *old;
     835                 :          0 :         struct ieee80211_bss_conf *bss_conf;
     836                 :          0 :         u8 *pos;
     837                 :          0 :         int len;
     838                 :            : 
     839         [ #  # ]:          0 :         if (!lci_len && !civicloc_len)
     840                 :            :                 return 0;
     841                 :            : 
     842                 :          0 :         bss_conf = &sdata->vif.bss_conf;
     843                 :          0 :         old = bss_conf->ftmr_params;
     844                 :          0 :         len = lci_len + civicloc_len;
     845                 :            : 
     846                 :          0 :         new = kzalloc(sizeof(*new) + len, GFP_KERNEL);
     847         [ #  # ]:          0 :         if (!new)
     848                 :            :                 return -ENOMEM;
     849                 :            : 
     850                 :          0 :         pos = (u8 *)(new + 1);
     851         [ #  # ]:          0 :         if (lci_len) {
     852                 :          0 :                 new->lci_len = lci_len;
     853                 :          0 :                 new->lci = pos;
     854                 :          0 :                 memcpy(pos, lci, lci_len);
     855                 :          0 :                 pos += lci_len;
     856                 :            :         }
     857                 :            : 
     858         [ #  # ]:          0 :         if (civicloc_len) {
     859                 :          0 :                 new->civicloc_len = civicloc_len;
     860                 :          0 :                 new->civicloc = pos;
     861                 :          0 :                 memcpy(pos, civicloc, civicloc_len);
     862                 :          0 :                 pos += civicloc_len;
     863                 :            :         }
     864                 :            : 
     865                 :          0 :         bss_conf->ftmr_params = new;
     866                 :          0 :         kfree(old);
     867                 :            : 
     868                 :          0 :         return 0;
     869                 :            : }
     870                 :            : 
     871                 :          0 : static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
     872                 :            :                                    struct cfg80211_beacon_data *params,
     873                 :            :                                    const struct ieee80211_csa_settings *csa)
     874                 :            : {
     875                 :          0 :         struct beacon_data *new, *old;
     876                 :          0 :         int new_head_len, new_tail_len;
     877                 :          0 :         int size, err;
     878                 :          0 :         u32 changed = BSS_CHANGED_BEACON;
     879                 :            : 
     880                 :          0 :         old = sdata_dereference(sdata->u.ap.beacon, sdata);
     881                 :            : 
     882                 :            : 
     883                 :            :         /* Need to have a beacon head if we don't have one yet */
     884   [ #  #  #  # ]:          0 :         if (!params->head && !old)
     885                 :            :                 return -EINVAL;
     886                 :            : 
     887                 :            :         /* new or old head? */
     888         [ #  # ]:          0 :         if (params->head)
     889                 :          0 :                 new_head_len = params->head_len;
     890                 :            :         else
     891                 :          0 :                 new_head_len = old->head_len;
     892                 :            : 
     893                 :            :         /* new or old tail? */
     894   [ #  #  #  # ]:          0 :         if (params->tail || !old)
     895                 :            :                 /* params->tail_len will be zero for !params->tail */
     896                 :          0 :                 new_tail_len = params->tail_len;
     897                 :            :         else
     898                 :          0 :                 new_tail_len = old->tail_len;
     899                 :            : 
     900                 :          0 :         size = sizeof(*new) + new_head_len + new_tail_len;
     901                 :            : 
     902                 :          0 :         new = kzalloc(size, GFP_KERNEL);
     903         [ #  # ]:          0 :         if (!new)
     904                 :            :                 return -ENOMEM;
     905                 :            : 
     906                 :            :         /* start filling the new info now */
     907                 :            : 
     908                 :            :         /*
     909                 :            :          * pointers go into the block we allocated,
     910                 :            :          * memory is | beacon_data | head | tail |
     911                 :            :          */
     912                 :          0 :         new->head = ((u8 *) new) + sizeof(*new);
     913                 :          0 :         new->tail = new->head + new_head_len;
     914                 :          0 :         new->head_len = new_head_len;
     915                 :          0 :         new->tail_len = new_tail_len;
     916                 :            : 
     917         [ #  # ]:          0 :         if (csa) {
     918                 :          0 :                 new->csa_current_counter = csa->count;
     919                 :          0 :                 memcpy(new->csa_counter_offsets, csa->counter_offsets_beacon,
     920                 :          0 :                        csa->n_counter_offsets_beacon *
     921                 :            :                        sizeof(new->csa_counter_offsets[0]));
     922                 :            :         }
     923                 :            : 
     924                 :            :         /* copy in head */
     925         [ #  # ]:          0 :         if (params->head)
     926                 :          0 :                 memcpy(new->head, params->head, new_head_len);
     927                 :            :         else
     928                 :          0 :                 memcpy(new->head, old->head, new_head_len);
     929                 :            : 
     930                 :            :         /* copy in optional tail */
     931         [ #  # ]:          0 :         if (params->tail)
     932                 :          0 :                 memcpy(new->tail, params->tail, new_tail_len);
     933                 :            :         else
     934         [ #  # ]:          0 :                 if (old)
     935                 :          0 :                         memcpy(new->tail, old->tail, new_tail_len);
     936                 :            : 
     937                 :          0 :         err = ieee80211_set_probe_resp(sdata, params->probe_resp,
     938                 :            :                                        params->probe_resp_len, csa);
     939         [ #  # ]:          0 :         if (err < 0) {
     940                 :          0 :                 kfree(new);
     941                 :          0 :                 return err;
     942                 :            :         }
     943         [ #  # ]:          0 :         if (err == 0)
     944                 :          0 :                 changed |= BSS_CHANGED_AP_PROBE_RESP;
     945                 :            : 
     946         [ #  # ]:          0 :         if (params->ftm_responder != -1) {
     947                 :          0 :                 sdata->vif.bss_conf.ftm_responder = params->ftm_responder;
     948                 :          0 :                 err = ieee80211_set_ftm_responder_params(sdata,
     949                 :            :                                                          params->lci,
     950                 :            :                                                          params->lci_len,
     951                 :            :                                                          params->civicloc,
     952                 :            :                                                          params->civicloc_len);
     953                 :            : 
     954         [ #  # ]:          0 :                 if (err < 0) {
     955                 :          0 :                         kfree(new);
     956                 :          0 :                         return err;
     957                 :            :                 }
     958                 :            : 
     959                 :          0 :                 changed |= BSS_CHANGED_FTM_RESPONDER;
     960                 :            :         }
     961                 :            : 
     962         [ #  # ]:          0 :         rcu_assign_pointer(sdata->u.ap.beacon, new);
     963                 :            : 
     964         [ #  # ]:          0 :         if (old)
     965                 :          0 :                 kfree_rcu(old, rcu_head);
     966                 :            : 
     967                 :          0 :         return changed;
     968                 :            : }
     969                 :            : 
     970                 :          0 : static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
     971                 :            :                               struct cfg80211_ap_settings *params)
     972                 :            : {
     973         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
     974                 :          0 :         struct ieee80211_local *local = sdata->local;
     975                 :          0 :         struct beacon_data *old;
     976                 :          0 :         struct ieee80211_sub_if_data *vlan;
     977                 :          0 :         u32 changed = BSS_CHANGED_BEACON_INT |
     978                 :            :                       BSS_CHANGED_BEACON_ENABLED |
     979                 :            :                       BSS_CHANGED_BEACON |
     980                 :            :                       BSS_CHANGED_SSID |
     981                 :            :                       BSS_CHANGED_P2P_PS |
     982                 :            :                       BSS_CHANGED_TXPOWER |
     983                 :            :                       BSS_CHANGED_TWT |
     984                 :            :                       BSS_CHANGED_HE_OBSS_PD;
     985                 :          0 :         int err;
     986                 :          0 :         int prev_beacon_int;
     987                 :            : 
     988                 :          0 :         old = sdata_dereference(sdata->u.ap.beacon, sdata);
     989         [ #  # ]:          0 :         if (old)
     990                 :            :                 return -EALREADY;
     991                 :            : 
     992   [ #  #  #  # ]:          0 :         switch (params->smps_mode) {
     993                 :          0 :         case NL80211_SMPS_OFF:
     994                 :          0 :                 sdata->smps_mode = IEEE80211_SMPS_OFF;
     995                 :          0 :                 break;
     996                 :          0 :         case NL80211_SMPS_STATIC:
     997                 :          0 :                 sdata->smps_mode = IEEE80211_SMPS_STATIC;
     998                 :          0 :                 break;
     999                 :          0 :         case NL80211_SMPS_DYNAMIC:
    1000                 :          0 :                 sdata->smps_mode = IEEE80211_SMPS_DYNAMIC;
    1001                 :          0 :                 break;
    1002                 :            :         default:
    1003                 :            :                 return -EINVAL;
    1004                 :            :         }
    1005                 :          0 :         sdata->u.ap.req_smps = sdata->smps_mode;
    1006                 :            : 
    1007                 :          0 :         sdata->needed_rx_chains = sdata->local->rx_chains;
    1008                 :            : 
    1009                 :          0 :         prev_beacon_int = sdata->vif.bss_conf.beacon_int;
    1010                 :          0 :         sdata->vif.bss_conf.beacon_int = params->beacon_interval;
    1011                 :            : 
    1012         [ #  # ]:          0 :         if (params->he_cap)
    1013                 :          0 :                 sdata->vif.bss_conf.he_support = true;
    1014                 :            : 
    1015                 :          0 :         mutex_lock(&local->mtx);
    1016                 :          0 :         err = ieee80211_vif_use_channel(sdata, &params->chandef,
    1017                 :            :                                         IEEE80211_CHANCTX_SHARED);
    1018         [ #  # ]:          0 :         if (!err)
    1019                 :          0 :                 ieee80211_vif_copy_chanctx_to_vlans(sdata, false);
    1020                 :          0 :         mutex_unlock(&local->mtx);
    1021         [ #  # ]:          0 :         if (err) {
    1022                 :          0 :                 sdata->vif.bss_conf.beacon_int = prev_beacon_int;
    1023                 :          0 :                 return err;
    1024                 :            :         }
    1025                 :            : 
    1026                 :            :         /*
    1027                 :            :          * Apply control port protocol, this allows us to
    1028                 :            :          * not encrypt dynamic WEP control frames.
    1029                 :            :          */
    1030                 :          0 :         sdata->control_port_protocol = params->crypto.control_port_ethertype;
    1031                 :          0 :         sdata->control_port_no_encrypt = params->crypto.control_port_no_encrypt;
    1032                 :          0 :         sdata->control_port_over_nl80211 =
    1033                 :          0 :                                 params->crypto.control_port_over_nl80211;
    1034                 :          0 :         sdata->encrypt_headroom = ieee80211_cs_headroom(sdata->local,
    1035                 :            :                                                         &params->crypto,
    1036                 :            :                                                         sdata->vif.type);
    1037                 :            : 
    1038         [ #  # ]:          0 :         list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
    1039                 :          0 :                 vlan->control_port_protocol =
    1040                 :          0 :                         params->crypto.control_port_ethertype;
    1041                 :          0 :                 vlan->control_port_no_encrypt =
    1042                 :          0 :                         params->crypto.control_port_no_encrypt;
    1043                 :          0 :                 vlan->control_port_over_nl80211 =
    1044                 :          0 :                         params->crypto.control_port_over_nl80211;
    1045                 :          0 :                 vlan->encrypt_headroom =
    1046                 :          0 :                         ieee80211_cs_headroom(sdata->local,
    1047                 :            :                                               &params->crypto,
    1048                 :            :                                               vlan->vif.type);
    1049                 :            :         }
    1050                 :            : 
    1051                 :          0 :         sdata->vif.bss_conf.dtim_period = params->dtim_period;
    1052                 :          0 :         sdata->vif.bss_conf.enable_beacon = true;
    1053                 :          0 :         sdata->vif.bss_conf.allow_p2p_go_ps = sdata->vif.p2p;
    1054                 :          0 :         sdata->vif.bss_conf.twt_responder = params->twt_responder;
    1055                 :          0 :         memcpy(&sdata->vif.bss_conf.he_obss_pd, &params->he_obss_pd,
    1056                 :            :                sizeof(struct ieee80211_he_obss_pd));
    1057                 :            : 
    1058                 :          0 :         sdata->vif.bss_conf.ssid_len = params->ssid_len;
    1059         [ #  # ]:          0 :         if (params->ssid_len)
    1060                 :          0 :                 memcpy(sdata->vif.bss_conf.ssid, params->ssid,
    1061                 :            :                        params->ssid_len);
    1062                 :          0 :         sdata->vif.bss_conf.hidden_ssid =
    1063                 :          0 :                 (params->hidden_ssid != NL80211_HIDDEN_SSID_NOT_IN_USE);
    1064                 :            : 
    1065                 :          0 :         memset(&sdata->vif.bss_conf.p2p_noa_attr, 0,
    1066                 :            :                sizeof(sdata->vif.bss_conf.p2p_noa_attr));
    1067                 :          0 :         sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow =
    1068                 :          0 :                 params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
    1069         [ #  # ]:          0 :         if (params->p2p_opp_ps)
    1070                 :          0 :                 sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
    1071                 :            :                                         IEEE80211_P2P_OPPPS_ENABLE_BIT;
    1072                 :            : 
    1073                 :          0 :         err = ieee80211_assign_beacon(sdata, &params->beacon, NULL);
    1074         [ #  # ]:          0 :         if (err < 0) {
    1075                 :          0 :                 ieee80211_vif_release_channel(sdata);
    1076                 :          0 :                 return err;
    1077                 :            :         }
    1078                 :          0 :         changed |= err;
    1079                 :            : 
    1080                 :          0 :         err = drv_start_ap(sdata->local, sdata);
    1081         [ #  # ]:          0 :         if (err) {
    1082                 :          0 :                 old = sdata_dereference(sdata->u.ap.beacon, sdata);
    1083                 :            : 
    1084         [ #  # ]:          0 :                 if (old)
    1085                 :          0 :                         kfree_rcu(old, rcu_head);
    1086                 :          0 :                 RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
    1087                 :          0 :                 ieee80211_vif_release_channel(sdata);
    1088                 :          0 :                 return err;
    1089                 :            :         }
    1090                 :            : 
    1091                 :          0 :         ieee80211_recalc_dtim(local, sdata);
    1092                 :          0 :         ieee80211_bss_info_change_notify(sdata, changed);
    1093                 :            : 
    1094                 :          0 :         netif_carrier_on(dev);
    1095         [ #  # ]:          0 :         list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
    1096                 :          0 :                 netif_carrier_on(vlan->dev);
    1097                 :            : 
    1098                 :            :         return 0;
    1099                 :            : }
    1100                 :            : 
    1101                 :          0 : static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
    1102                 :            :                                    struct cfg80211_beacon_data *params)
    1103                 :            : {
    1104                 :          0 :         struct ieee80211_sub_if_data *sdata;
    1105                 :          0 :         struct beacon_data *old;
    1106                 :          0 :         int err;
    1107                 :            : 
    1108         [ #  # ]:          0 :         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    1109         [ #  # ]:          0 :         sdata_assert_lock(sdata);
    1110                 :            : 
    1111                 :            :         /* don't allow changing the beacon while CSA is in place - offset
    1112                 :            :          * of channel switch counter may change
    1113                 :            :          */
    1114         [ #  # ]:          0 :         if (sdata->vif.csa_active)
    1115                 :            :                 return -EBUSY;
    1116                 :            : 
    1117                 :          0 :         old = sdata_dereference(sdata->u.ap.beacon, sdata);
    1118         [ #  # ]:          0 :         if (!old)
    1119                 :            :                 return -ENOENT;
    1120                 :            : 
    1121                 :          0 :         err = ieee80211_assign_beacon(sdata, params, NULL);
    1122         [ #  # ]:          0 :         if (err < 0)
    1123                 :            :                 return err;
    1124                 :          0 :         ieee80211_bss_info_change_notify(sdata, err);
    1125                 :          0 :         return 0;
    1126                 :            : }
    1127                 :            : 
    1128                 :          0 : static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
    1129                 :            : {
    1130         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    1131                 :          0 :         struct ieee80211_sub_if_data *vlan;
    1132                 :          0 :         struct ieee80211_local *local = sdata->local;
    1133                 :          0 :         struct beacon_data *old_beacon;
    1134                 :          0 :         struct probe_resp *old_probe_resp;
    1135                 :          0 :         struct cfg80211_chan_def chandef;
    1136                 :            : 
    1137         [ #  # ]:          0 :         sdata_assert_lock(sdata);
    1138                 :            : 
    1139                 :          0 :         old_beacon = sdata_dereference(sdata->u.ap.beacon, sdata);
    1140         [ #  # ]:          0 :         if (!old_beacon)
    1141                 :            :                 return -ENOENT;
    1142                 :          0 :         old_probe_resp = sdata_dereference(sdata->u.ap.probe_resp, sdata);
    1143                 :            : 
    1144                 :            :         /* abort any running channel switch */
    1145                 :          0 :         mutex_lock(&local->mtx);
    1146                 :          0 :         sdata->vif.csa_active = false;
    1147         [ #  # ]:          0 :         if (sdata->csa_block_tx) {
    1148                 :          0 :                 ieee80211_wake_vif_queues(local, sdata,
    1149                 :            :                                           IEEE80211_QUEUE_STOP_REASON_CSA);
    1150                 :          0 :                 sdata->csa_block_tx = false;
    1151                 :            :         }
    1152                 :            : 
    1153                 :          0 :         mutex_unlock(&local->mtx);
    1154                 :            : 
    1155                 :          0 :         kfree(sdata->u.ap.next_beacon);
    1156                 :          0 :         sdata->u.ap.next_beacon = NULL;
    1157                 :            : 
    1158                 :            :         /* turn off carrier for this interface and dependent VLANs */
    1159         [ #  # ]:          0 :         list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
    1160                 :          0 :                 netif_carrier_off(vlan->dev);
    1161                 :          0 :         netif_carrier_off(dev);
    1162                 :            : 
    1163                 :            :         /* remove beacon and probe response */
    1164                 :          0 :         RCU_INIT_POINTER(sdata->u.ap.beacon, NULL);
    1165                 :          0 :         RCU_INIT_POINTER(sdata->u.ap.probe_resp, NULL);
    1166                 :          0 :         kfree_rcu(old_beacon, rcu_head);
    1167         [ #  # ]:          0 :         if (old_probe_resp)
    1168                 :          0 :                 kfree_rcu(old_probe_resp, rcu_head);
    1169                 :          0 :         sdata->u.ap.driver_smps_mode = IEEE80211_SMPS_OFF;
    1170                 :            : 
    1171                 :          0 :         kfree(sdata->vif.bss_conf.ftmr_params);
    1172                 :          0 :         sdata->vif.bss_conf.ftmr_params = NULL;
    1173                 :            : 
    1174                 :          0 :         __sta_info_flush(sdata, true);
    1175                 :          0 :         ieee80211_free_keys(sdata, true);
    1176                 :            : 
    1177                 :          0 :         sdata->vif.bss_conf.enable_beacon = false;
    1178                 :          0 :         sdata->vif.bss_conf.ssid_len = 0;
    1179                 :          0 :         clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
    1180                 :          0 :         ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON_ENABLED);
    1181                 :            : 
    1182         [ #  # ]:          0 :         if (sdata->wdev.cac_started) {
    1183                 :          0 :                 chandef = sdata->vif.bss_conf.chandef;
    1184                 :          0 :                 cancel_delayed_work_sync(&sdata->dfs_cac_timer_work);
    1185                 :          0 :                 cfg80211_cac_event(sdata->dev, &chandef,
    1186                 :            :                                    NL80211_RADAR_CAC_ABORTED,
    1187                 :            :                                    GFP_KERNEL);
    1188                 :            :         }
    1189                 :            : 
    1190                 :          0 :         drv_stop_ap(sdata->local, sdata);
    1191                 :            : 
    1192                 :            :         /* free all potentially still buffered bcast frames */
    1193                 :          0 :         local->total_ps_buffered -= skb_queue_len(&sdata->u.ap.ps.bc_buf);
    1194                 :          0 :         ieee80211_purge_tx_queue(&local->hw, &sdata->u.ap.ps.bc_buf);
    1195                 :            : 
    1196                 :          0 :         mutex_lock(&local->mtx);
    1197                 :          0 :         ieee80211_vif_copy_chanctx_to_vlans(sdata, true);
    1198                 :          0 :         ieee80211_vif_release_channel(sdata);
    1199                 :          0 :         mutex_unlock(&local->mtx);
    1200                 :            : 
    1201                 :          0 :         return 0;
    1202                 :            : }
    1203                 :            : 
    1204                 :            : static int sta_apply_auth_flags(struct ieee80211_local *local,
    1205                 :            :                                 struct sta_info *sta,
    1206                 :            :                                 u32 mask, u32 set)
    1207                 :            : {
    1208                 :            :         int ret;
    1209                 :            : 
    1210                 :            :         if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
    1211                 :            :             set & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
    1212                 :            :             !test_sta_flag(sta, WLAN_STA_AUTH)) {
    1213                 :            :                 ret = sta_info_move_state(sta, IEEE80211_STA_AUTH);
    1214                 :            :                 if (ret)
    1215                 :            :                         return ret;
    1216                 :            :         }
    1217                 :            : 
    1218                 :            :         if (mask & BIT(NL80211_STA_FLAG_ASSOCIATED) &&
    1219                 :            :             set & BIT(NL80211_STA_FLAG_ASSOCIATED) &&
    1220                 :            :             !test_sta_flag(sta, WLAN_STA_ASSOC)) {
    1221                 :            :                 /*
    1222                 :            :                  * When peer becomes associated, init rate control as
    1223                 :            :                  * well. Some drivers require rate control initialized
    1224                 :            :                  * before drv_sta_state() is called.
    1225                 :            :                  */
    1226                 :            :                 if (!test_sta_flag(sta, WLAN_STA_RATE_CONTROL))
    1227                 :            :                         rate_control_rate_init(sta);
    1228                 :            : 
    1229                 :            :                 ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
    1230                 :            :                 if (ret)
    1231                 :            :                         return ret;
    1232                 :            :         }
    1233                 :            : 
    1234                 :            :         if (mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
    1235                 :            :                 if (set & BIT(NL80211_STA_FLAG_AUTHORIZED))
    1236                 :            :                         ret = sta_info_move_state(sta, IEEE80211_STA_AUTHORIZED);
    1237                 :            :                 else if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
    1238                 :            :                         ret = sta_info_move_state(sta, IEEE80211_STA_ASSOC);
    1239                 :            :                 else
    1240                 :            :                         ret = 0;
    1241                 :            :                 if (ret)
    1242                 :            :                         return ret;
    1243                 :            :         }
    1244                 :            : 
    1245                 :            :         if (mask & BIT(NL80211_STA_FLAG_ASSOCIATED) &&
    1246                 :            :             !(set & BIT(NL80211_STA_FLAG_ASSOCIATED)) &&
    1247                 :            :             test_sta_flag(sta, WLAN_STA_ASSOC)) {
    1248                 :            :                 ret = sta_info_move_state(sta, IEEE80211_STA_AUTH);
    1249                 :            :                 if (ret)
    1250                 :            :                         return ret;
    1251                 :            :         }
    1252                 :            : 
    1253                 :            :         if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED) &&
    1254                 :            :             !(set & BIT(NL80211_STA_FLAG_AUTHENTICATED)) &&
    1255                 :            :             test_sta_flag(sta, WLAN_STA_AUTH)) {
    1256                 :            :                 ret = sta_info_move_state(sta, IEEE80211_STA_NONE);
    1257                 :            :                 if (ret)
    1258                 :            :                         return ret;
    1259                 :            :         }
    1260                 :            : 
    1261                 :            :         return 0;
    1262                 :            : }
    1263                 :            : 
    1264                 :            : static void sta_apply_mesh_params(struct ieee80211_local *local,
    1265                 :            :                                   struct sta_info *sta,
    1266                 :            :                                   struct station_parameters *params)
    1267                 :            : {
    1268                 :            : #ifdef CONFIG_MAC80211_MESH
    1269                 :            :         struct ieee80211_sub_if_data *sdata = sta->sdata;
    1270                 :            :         u32 changed = 0;
    1271                 :            : 
    1272                 :            :         if (params->sta_modify_mask & STATION_PARAM_APPLY_PLINK_STATE) {
    1273                 :            :                 switch (params->plink_state) {
    1274                 :            :                 case NL80211_PLINK_ESTAB:
    1275                 :            :                         if (sta->mesh->plink_state != NL80211_PLINK_ESTAB)
    1276                 :            :                                 changed = mesh_plink_inc_estab_count(sdata);
    1277                 :            :                         sta->mesh->plink_state = params->plink_state;
    1278                 :            :                         sta->mesh->aid = params->peer_aid;
    1279                 :            : 
    1280                 :            :                         ieee80211_mps_sta_status_update(sta);
    1281                 :            :                         changed |= ieee80211_mps_set_sta_local_pm(sta,
    1282                 :            :                                       sdata->u.mesh.mshcfg.power_mode);
    1283                 :            : 
    1284                 :            :                         ewma_mesh_tx_rate_avg_init(&sta->mesh->tx_rate_avg);
    1285                 :            :                         /* init at low value */
    1286                 :            :                         ewma_mesh_tx_rate_avg_add(&sta->mesh->tx_rate_avg, 10);
    1287                 :            : 
    1288                 :            :                         break;
    1289                 :            :                 case NL80211_PLINK_LISTEN:
    1290                 :            :                 case NL80211_PLINK_BLOCKED:
    1291                 :            :                 case NL80211_PLINK_OPN_SNT:
    1292                 :            :                 case NL80211_PLINK_OPN_RCVD:
    1293                 :            :                 case NL80211_PLINK_CNF_RCVD:
    1294                 :            :                 case NL80211_PLINK_HOLDING:
    1295                 :            :                         if (sta->mesh->plink_state == NL80211_PLINK_ESTAB)
    1296                 :            :                                 changed = mesh_plink_dec_estab_count(sdata);
    1297                 :            :                         sta->mesh->plink_state = params->plink_state;
    1298                 :            : 
    1299                 :            :                         ieee80211_mps_sta_status_update(sta);
    1300                 :            :                         changed |= ieee80211_mps_set_sta_local_pm(sta,
    1301                 :            :                                         NL80211_MESH_POWER_UNKNOWN);
    1302                 :            :                         break;
    1303                 :            :                 default:
    1304                 :            :                         /*  nothing  */
    1305                 :            :                         break;
    1306                 :            :                 }
    1307                 :            :         }
    1308                 :            : 
    1309                 :            :         switch (params->plink_action) {
    1310                 :            :         case NL80211_PLINK_ACTION_NO_ACTION:
    1311                 :            :                 /* nothing */
    1312                 :            :                 break;
    1313                 :            :         case NL80211_PLINK_ACTION_OPEN:
    1314                 :            :                 changed |= mesh_plink_open(sta);
    1315                 :            :                 break;
    1316                 :            :         case NL80211_PLINK_ACTION_BLOCK:
    1317                 :            :                 changed |= mesh_plink_block(sta);
    1318                 :            :                 break;
    1319                 :            :         }
    1320                 :            : 
    1321                 :            :         if (params->local_pm)
    1322                 :            :                 changed |= ieee80211_mps_set_sta_local_pm(sta,
    1323                 :            :                                                           params->local_pm);
    1324                 :            : 
    1325                 :            :         ieee80211_mbss_info_change_notify(sdata, changed);
    1326                 :            : #endif
    1327                 :            : }
    1328                 :            : 
    1329                 :          0 : static int sta_apply_parameters(struct ieee80211_local *local,
    1330                 :            :                                 struct sta_info *sta,
    1331                 :            :                                 struct station_parameters *params)
    1332                 :            : {
    1333                 :          0 :         int ret = 0;
    1334                 :          0 :         struct ieee80211_supported_band *sband;
    1335                 :          0 :         struct ieee80211_sub_if_data *sdata = sta->sdata;
    1336                 :          0 :         u32 mask, set;
    1337                 :            : 
    1338                 :          0 :         sband = ieee80211_get_sband(sdata);
    1339         [ #  # ]:          0 :         if (!sband)
    1340                 :            :                 return -EINVAL;
    1341                 :            : 
    1342                 :          0 :         mask = params->sta_flags_mask;
    1343                 :          0 :         set = params->sta_flags_set;
    1344                 :            : 
    1345                 :          0 :         if (ieee80211_vif_is_mesh(&sdata->vif)) {
    1346                 :            :                 /*
    1347                 :            :                  * In mesh mode, ASSOCIATED isn't part of the nl80211
    1348                 :            :                  * API but must follow AUTHENTICATED for driver state.
    1349                 :            :                  */
    1350                 :            :                 if (mask & BIT(NL80211_STA_FLAG_AUTHENTICATED))
    1351                 :            :                         mask |= BIT(NL80211_STA_FLAG_ASSOCIATED);
    1352                 :            :                 if (set & BIT(NL80211_STA_FLAG_AUTHENTICATED))
    1353                 :            :                         set |= BIT(NL80211_STA_FLAG_ASSOCIATED);
    1354         [ #  # ]:          0 :         } else if (test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
    1355                 :            :                 /*
    1356                 :            :                  * TDLS -- everything follows authorized, but
    1357                 :            :                  * only becoming authorized is possible, not
    1358                 :            :                  * going back
    1359                 :            :                  */
    1360         [ #  # ]:          0 :                 if (set & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
    1361                 :          0 :                         set |= BIT(NL80211_STA_FLAG_AUTHENTICATED) |
    1362                 :            :                                BIT(NL80211_STA_FLAG_ASSOCIATED);
    1363                 :          0 :                         mask |= BIT(NL80211_STA_FLAG_AUTHENTICATED) |
    1364                 :            :                                 BIT(NL80211_STA_FLAG_ASSOCIATED);
    1365                 :            :                 }
    1366                 :            :         }
    1367                 :            : 
    1368         [ #  # ]:          0 :         if (mask & BIT(NL80211_STA_FLAG_WME) &&
    1369         [ #  # ]:          0 :             local->hw.queues >= IEEE80211_NUM_ACS)
    1370                 :          0 :                 sta->sta.wme = set & BIT(NL80211_STA_FLAG_WME);
    1371                 :            : 
    1372                 :            :         /* auth flags will be set later for TDLS,
    1373                 :            :          * and for unassociated stations that move to assocaited */
    1374   [ #  #  #  # ]:          0 :         if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
    1375         [ #  # ]:          0 :             !((mask & BIT(NL80211_STA_FLAG_ASSOCIATED)) &&
    1376                 :            :               (set & BIT(NL80211_STA_FLAG_ASSOCIATED)))) {
    1377                 :          0 :                 ret = sta_apply_auth_flags(local, sta, mask, set);
    1378         [ #  # ]:          0 :                 if (ret)
    1379                 :            :                         return ret;
    1380                 :            :         }
    1381                 :            : 
    1382         [ #  # ]:          0 :         if (mask & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE)) {
    1383         [ #  # ]:          0 :                 if (set & BIT(NL80211_STA_FLAG_SHORT_PREAMBLE))
    1384                 :          0 :                         set_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE);
    1385                 :            :                 else
    1386                 :          0 :                         clear_sta_flag(sta, WLAN_STA_SHORT_PREAMBLE);
    1387                 :            :         }
    1388                 :            : 
    1389         [ #  # ]:          0 :         if (mask & BIT(NL80211_STA_FLAG_MFP)) {
    1390                 :          0 :                 sta->sta.mfp = !!(set & BIT(NL80211_STA_FLAG_MFP));
    1391         [ #  # ]:          0 :                 if (set & BIT(NL80211_STA_FLAG_MFP))
    1392                 :          0 :                         set_sta_flag(sta, WLAN_STA_MFP);
    1393                 :            :                 else
    1394                 :          0 :                         clear_sta_flag(sta, WLAN_STA_MFP);
    1395                 :            :         }
    1396                 :            : 
    1397         [ #  # ]:          0 :         if (mask & BIT(NL80211_STA_FLAG_TDLS_PEER)) {
    1398         [ #  # ]:          0 :                 if (set & BIT(NL80211_STA_FLAG_TDLS_PEER))
    1399                 :          0 :                         set_sta_flag(sta, WLAN_STA_TDLS_PEER);
    1400                 :            :                 else
    1401                 :          0 :                         clear_sta_flag(sta, WLAN_STA_TDLS_PEER);
    1402                 :            :         }
    1403                 :            : 
    1404                 :            :         /* mark TDLS channel switch support, if the AP allows it */
    1405         [ #  # ]:          0 :         if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
    1406         [ #  # ]:          0 :             !sdata->u.mgd.tdls_chan_switch_prohibited &&
    1407         [ #  # ]:          0 :             params->ext_capab_len >= 4 &&
    1408         [ #  # ]:          0 :             params->ext_capab[3] & WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)
    1409                 :          0 :                 set_sta_flag(sta, WLAN_STA_TDLS_CHAN_SWITCH);
    1410                 :            : 
    1411         [ #  # ]:          0 :         if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
    1412   [ #  #  #  # ]:          0 :             !sdata->u.mgd.tdls_wider_bw_prohibited &&
    1413                 :          0 :             ieee80211_hw_check(&local->hw, TDLS_WIDER_BW) &&
    1414         [ #  # ]:          0 :             params->ext_capab_len >= 8 &&
    1415         [ #  # ]:          0 :             params->ext_capab[7] & WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED)
    1416                 :          0 :                 set_sta_flag(sta, WLAN_STA_TDLS_WIDER_BW);
    1417                 :            : 
    1418         [ #  # ]:          0 :         if (params->sta_modify_mask & STATION_PARAM_APPLY_UAPSD) {
    1419                 :          0 :                 sta->sta.uapsd_queues = params->uapsd_queues;
    1420                 :          0 :                 sta->sta.max_sp = params->max_sp;
    1421                 :            :         }
    1422                 :            : 
    1423                 :            :         /* The sender might not have sent the last bit, consider it to be 0 */
    1424         [ #  # ]:          0 :         if (params->ext_capab_len >= 8) {
    1425                 :          0 :                 u8 val = (params->ext_capab[7] &
    1426                 :            :                           WLAN_EXT_CAPA8_MAX_MSDU_IN_AMSDU_LSB) >> 7;
    1427                 :            : 
    1428                 :            :                 /* we did get all the bits, take the MSB as well */
    1429         [ #  # ]:          0 :                 if (params->ext_capab_len >= 9) {
    1430                 :          0 :                         u8 val_msb = params->ext_capab[8] &
    1431                 :            :                                 WLAN_EXT_CAPA9_MAX_MSDU_IN_AMSDU_MSB;
    1432                 :          0 :                         val_msb <<= 1;
    1433                 :          0 :                         val |= val_msb;
    1434                 :            :                 }
    1435                 :            : 
    1436   [ #  #  #  # ]:          0 :                 switch (val) {
    1437                 :          0 :                 case 1:
    1438                 :          0 :                         sta->sta.max_amsdu_subframes = 32;
    1439                 :          0 :                         break;
    1440                 :          0 :                 case 2:
    1441                 :          0 :                         sta->sta.max_amsdu_subframes = 16;
    1442                 :          0 :                         break;
    1443                 :          0 :                 case 3:
    1444                 :          0 :                         sta->sta.max_amsdu_subframes = 8;
    1445                 :          0 :                         break;
    1446                 :          0 :                 default:
    1447                 :          0 :                         sta->sta.max_amsdu_subframes = 0;
    1448                 :            :                 }
    1449                 :          0 :         }
    1450                 :            : 
    1451                 :            :         /*
    1452                 :            :          * cfg80211 validates this (1-2007) and allows setting the AID
    1453                 :            :          * only when creating a new station entry
    1454                 :            :          */
    1455         [ #  # ]:          0 :         if (params->aid)
    1456                 :          0 :                 sta->sta.aid = params->aid;
    1457                 :            : 
    1458                 :            :         /*
    1459                 :            :          * Some of the following updates would be racy if called on an
    1460                 :            :          * existing station, via ieee80211_change_station(). However,
    1461                 :            :          * all such changes are rejected by cfg80211 except for updates
    1462                 :            :          * changing the supported rates on an existing but not yet used
    1463                 :            :          * TDLS peer.
    1464                 :            :          */
    1465                 :            : 
    1466         [ #  # ]:          0 :         if (params->listen_interval >= 0)
    1467                 :          0 :                 sta->listen_interval = params->listen_interval;
    1468                 :            : 
    1469         [ #  # ]:          0 :         if (params->sta_modify_mask & STATION_PARAM_APPLY_STA_TXPOWER) {
    1470                 :          0 :                 sta->sta.txpwr.type = params->txpwr.type;
    1471         [ #  # ]:          0 :                 if (params->txpwr.type == NL80211_TX_POWER_LIMITED)
    1472                 :          0 :                         sta->sta.txpwr.power = params->txpwr.power;
    1473                 :          0 :                 ret = drv_sta_set_txpwr(local, sdata, sta);
    1474         [ #  # ]:          0 :                 if (ret)
    1475                 :            :                         return ret;
    1476                 :            :         }
    1477                 :            : 
    1478   [ #  #  #  # ]:          0 :         if (params->supported_rates && params->supported_rates_len) {
    1479                 :          0 :                 ieee80211_parse_bitrates(&sdata->vif.bss_conf.chandef,
    1480                 :            :                                          sband, params->supported_rates,
    1481                 :            :                                          params->supported_rates_len,
    1482                 :          0 :                                          &sta->sta.supp_rates[sband->band]);
    1483                 :            :         }
    1484                 :            : 
    1485         [ #  # ]:          0 :         if (params->ht_capa)
    1486                 :          0 :                 ieee80211_ht_cap_ie_to_sta_ht_cap(sdata, sband,
    1487                 :            :                                                   params->ht_capa, sta);
    1488                 :            : 
    1489                 :            :         /* VHT can override some HT caps such as the A-MSDU max length */
    1490         [ #  # ]:          0 :         if (params->vht_capa)
    1491                 :          0 :                 ieee80211_vht_cap_ie_to_sta_vht_cap(sdata, sband,
    1492                 :            :                                                     params->vht_capa, sta);
    1493                 :            : 
    1494         [ #  # ]:          0 :         if (params->he_capa)
    1495                 :          0 :                 ieee80211_he_cap_ie_to_sta_he_cap(sdata, sband,
    1496                 :            :                                                   (void *)params->he_capa,
    1497                 :          0 :                                                   params->he_capa_len, sta);
    1498                 :            : 
    1499         [ #  # ]:          0 :         if (params->opmode_notif_used) {
    1500                 :            :                 /* returned value is only needed for rc update, but the
    1501                 :            :                  * rc isn't initialized here yet, so ignore it
    1502                 :            :                  */
    1503                 :          0 :                 __ieee80211_vht_handle_opmode(sdata, sta, params->opmode_notif,
    1504                 :            :                                               sband->band);
    1505                 :            :         }
    1506                 :            : 
    1507         [ #  # ]:          0 :         if (params->support_p2p_ps >= 0)
    1508                 :          0 :                 sta->sta.support_p2p_ps = params->support_p2p_ps;
    1509                 :            : 
    1510         [ #  # ]:          0 :         if (ieee80211_vif_is_mesh(&sdata->vif))
    1511                 :            :                 sta_apply_mesh_params(local, sta, params);
    1512                 :            : 
    1513         [ #  # ]:          0 :         if (params->airtime_weight)
    1514                 :          0 :                 sta->airtime_weight = params->airtime_weight;
    1515                 :            : 
    1516                 :            :         /* set the STA state after all sta info from usermode has been set */
    1517   [ #  #  #  # ]:          0 :         if (test_sta_flag(sta, WLAN_STA_TDLS_PEER) ||
    1518                 :            :             set & BIT(NL80211_STA_FLAG_ASSOCIATED)) {
    1519                 :          0 :                 ret = sta_apply_auth_flags(local, sta, mask, set);
    1520         [ #  # ]:          0 :                 if (ret)
    1521                 :          0 :                         return ret;
    1522                 :            :         }
    1523                 :            : 
    1524                 :            :         return 0;
    1525                 :            : }
    1526                 :            : 
    1527                 :          0 : static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
    1528                 :            :                                  const u8 *mac,
    1529                 :            :                                  struct station_parameters *params)
    1530                 :            : {
    1531         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    1532                 :          0 :         struct sta_info *sta;
    1533                 :          0 :         struct ieee80211_sub_if_data *sdata;
    1534                 :          0 :         int err;
    1535                 :            : 
    1536         [ #  # ]:          0 :         if (params->vlan) {
    1537         [ #  # ]:          0 :                 sdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
    1538                 :            : 
    1539         [ #  # ]:          0 :                 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
    1540                 :            :                     sdata->vif.type != NL80211_IFTYPE_AP)
    1541                 :            :                         return -EINVAL;
    1542                 :            :         } else
    1543                 :          0 :                 sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    1544                 :            : 
    1545         [ #  # ]:          0 :         if (ether_addr_equal(mac, sdata->vif.addr))
    1546                 :            :                 return -EINVAL;
    1547                 :            : 
    1548   [ #  #  #  # ]:          0 :         if (!is_valid_ether_addr(mac))
    1549                 :            :                 return -EINVAL;
    1550                 :            : 
    1551         [ #  # ]:          0 :         if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER) &&
    1552         [ #  # ]:          0 :             sdata->vif.type == NL80211_IFTYPE_STATION &&
    1553         [ #  # ]:          0 :             !sdata->u.mgd.associated)
    1554                 :            :                 return -EINVAL;
    1555                 :            : 
    1556                 :          0 :         sta = sta_info_alloc(sdata, mac, GFP_KERNEL);
    1557         [ #  # ]:          0 :         if (!sta)
    1558                 :            :                 return -ENOMEM;
    1559                 :            : 
    1560         [ #  # ]:          0 :         if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
    1561                 :          0 :                 sta->sta.tdls = true;
    1562                 :            : 
    1563                 :          0 :         err = sta_apply_parameters(local, sta, params);
    1564         [ #  # ]:          0 :         if (err) {
    1565                 :          0 :                 sta_info_free(local, sta);
    1566                 :          0 :                 return err;
    1567                 :            :         }
    1568                 :            : 
    1569                 :            :         /*
    1570                 :            :          * for TDLS and for unassociated station, rate control should be
    1571                 :            :          * initialized only when rates are known and station is marked
    1572                 :            :          * authorized/associated
    1573                 :            :          */
    1574   [ #  #  #  # ]:          0 :         if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER) &&
    1575                 :            :             test_sta_flag(sta, WLAN_STA_ASSOC))
    1576                 :          0 :                 rate_control_rate_init(sta);
    1577                 :            : 
    1578                 :          0 :         err = sta_info_insert_rcu(sta);
    1579         [ #  # ]:          0 :         if (err) {
    1580                 :          0 :                 rcu_read_unlock();
    1581                 :          0 :                 return err;
    1582                 :            :         }
    1583                 :            : 
    1584                 :          0 :         rcu_read_unlock();
    1585                 :            : 
    1586                 :          0 :         return 0;
    1587                 :            : }
    1588                 :            : 
    1589                 :          0 : static int ieee80211_del_station(struct wiphy *wiphy, struct net_device *dev,
    1590                 :            :                                  struct station_del_parameters *params)
    1591                 :            : {
    1592                 :          0 :         struct ieee80211_sub_if_data *sdata;
    1593                 :            : 
    1594         [ #  # ]:          0 :         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    1595                 :            : 
    1596         [ #  # ]:          0 :         if (params->mac)
    1597                 :          0 :                 return sta_info_destroy_addr_bss(sdata, params->mac);
    1598                 :            : 
    1599                 :          0 :         sta_info_flush(sdata);
    1600                 :          0 :         return 0;
    1601                 :            : }
    1602                 :            : 
    1603                 :          0 : static int ieee80211_change_station(struct wiphy *wiphy,
    1604                 :            :                                     struct net_device *dev, const u8 *mac,
    1605                 :            :                                     struct station_parameters *params)
    1606                 :            : {
    1607         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    1608         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    1609                 :          0 :         struct sta_info *sta;
    1610                 :          0 :         struct ieee80211_sub_if_data *vlansdata;
    1611                 :          0 :         enum cfg80211_station_type statype;
    1612                 :          0 :         int err;
    1613                 :            : 
    1614                 :          0 :         mutex_lock(&local->sta_mtx);
    1615                 :            : 
    1616                 :          0 :         sta = sta_info_get_bss(sdata, mac);
    1617         [ #  # ]:          0 :         if (!sta) {
    1618                 :          0 :                 err = -ENOENT;
    1619                 :          0 :                 goto out_err;
    1620                 :            :         }
    1621                 :            : 
    1622   [ #  #  #  #  :          0 :         switch (sdata->vif.type) {
                      # ]
    1623                 :          0 :         case NL80211_IFTYPE_MESH_POINT:
    1624         [ #  # ]:          0 :                 if (sdata->u.mesh.user_mpm)
    1625                 :            :                         statype = CFG80211_STA_MESH_PEER_USER;
    1626                 :            :                 else
    1627                 :          0 :                         statype = CFG80211_STA_MESH_PEER_KERNEL;
    1628                 :            :                 break;
    1629                 :            :         case NL80211_IFTYPE_ADHOC:
    1630                 :            :                 statype = CFG80211_STA_IBSS;
    1631                 :            :                 break;
    1632                 :            :         case NL80211_IFTYPE_STATION:
    1633         [ #  # ]:          0 :                 if (!test_sta_flag(sta, WLAN_STA_TDLS_PEER)) {
    1634                 :            :                         statype = CFG80211_STA_AP_STA;
    1635                 :            :                         break;
    1636                 :            :                 }
    1637         [ #  # ]:          0 :                 if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
    1638                 :            :                         statype = CFG80211_STA_TDLS_PEER_ACTIVE;
    1639                 :            :                 else
    1640                 :          0 :                         statype = CFG80211_STA_TDLS_PEER_SETUP;
    1641                 :            :                 break;
    1642                 :            :         case NL80211_IFTYPE_AP:
    1643                 :            :         case NL80211_IFTYPE_AP_VLAN:
    1644         [ #  # ]:          0 :                 if (test_sta_flag(sta, WLAN_STA_ASSOC))
    1645                 :            :                         statype = CFG80211_STA_AP_CLIENT;
    1646                 :            :                 else
    1647                 :          0 :                         statype = CFG80211_STA_AP_CLIENT_UNASSOC;
    1648                 :            :                 break;
    1649                 :          0 :         default:
    1650                 :          0 :                 err = -EOPNOTSUPP;
    1651                 :          0 :                 goto out_err;
    1652                 :            :         }
    1653                 :            : 
    1654                 :          0 :         err = cfg80211_check_station_change(wiphy, params, statype);
    1655         [ #  # ]:          0 :         if (err)
    1656                 :          0 :                 goto out_err;
    1657                 :            : 
    1658   [ #  #  #  # ]:          0 :         if (params->vlan && params->vlan != sta->sdata->dev) {
    1659         [ #  # ]:          0 :                 vlansdata = IEEE80211_DEV_TO_SUB_IF(params->vlan);
    1660                 :            : 
    1661         [ #  # ]:          0 :                 if (params->vlan->ieee80211_ptr->use_4addr) {
    1662         [ #  # ]:          0 :                         if (vlansdata->u.vlan.sta) {
    1663                 :          0 :                                 err = -EBUSY;
    1664                 :          0 :                                 goto out_err;
    1665                 :            :                         }
    1666                 :            : 
    1667                 :          0 :                         rcu_assign_pointer(vlansdata->u.vlan.sta, sta);
    1668                 :          0 :                         __ieee80211_check_fast_rx_iface(vlansdata);
    1669                 :            :                 }
    1670                 :            : 
    1671         [ #  # ]:          0 :                 if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN &&
    1672         [ #  # ]:          0 :                     sta->sdata->u.vlan.sta)
    1673                 :          0 :                         RCU_INIT_POINTER(sta->sdata->u.vlan.sta, NULL);
    1674                 :            : 
    1675         [ #  # ]:          0 :                 if (test_sta_flag(sta, WLAN_STA_AUTHORIZED))
    1676                 :          0 :                         ieee80211_vif_dec_num_mcast(sta->sdata);
    1677                 :            : 
    1678                 :          0 :                 sta->sdata = vlansdata;
    1679                 :          0 :                 ieee80211_check_fast_xmit(sta);
    1680                 :            : 
    1681         [ #  # ]:          0 :                 if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) {
    1682                 :          0 :                         ieee80211_vif_inc_num_mcast(sta->sdata);
    1683                 :          0 :                         cfg80211_send_layer2_update(sta->sdata->dev,
    1684                 :          0 :                                                     sta->sta.addr);
    1685                 :            :                 }
    1686                 :            :         }
    1687                 :            : 
    1688                 :          0 :         err = sta_apply_parameters(local, sta, params);
    1689         [ #  # ]:          0 :         if (err)
    1690                 :          0 :                 goto out_err;
    1691                 :            : 
    1692                 :          0 :         mutex_unlock(&local->sta_mtx);
    1693                 :            : 
    1694         [ #  # ]:          0 :         if ((sdata->vif.type == NL80211_IFTYPE_AP ||
    1695                 :          0 :              sdata->vif.type == NL80211_IFTYPE_AP_VLAN) &&
    1696   [ #  #  #  # ]:          0 :             sta->known_smps_mode != sta->sdata->bss->req_smps &&
    1697         [ #  # ]:          0 :             test_sta_flag(sta, WLAN_STA_AUTHORIZED) &&
    1698                 :          0 :             sta_info_tx_streams(sta) != 1) {
    1699                 :          0 :                 ht_dbg(sta->sdata,
    1700                 :            :                        "%pM just authorized and MIMO capable - update SMPS\n",
    1701                 :            :                        sta->sta.addr);
    1702                 :          0 :                 ieee80211_send_smps_action(sta->sdata,
    1703                 :          0 :                         sta->sdata->bss->req_smps,
    1704                 :          0 :                         sta->sta.addr,
    1705                 :          0 :                         sta->sdata->vif.bss_conf.bssid);
    1706                 :            :         }
    1707                 :            : 
    1708         [ #  # ]:          0 :         if (sdata->vif.type == NL80211_IFTYPE_STATION &&
    1709         [ #  # ]:          0 :             params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED)) {
    1710                 :          0 :                 ieee80211_recalc_ps(local);
    1711                 :          0 :                 ieee80211_recalc_ps_vif(sdata);
    1712                 :            :         }
    1713                 :            : 
    1714                 :            :         return 0;
    1715                 :          0 : out_err:
    1716                 :          0 :         mutex_unlock(&local->sta_mtx);
    1717                 :          0 :         return err;
    1718                 :            : }
    1719                 :            : 
    1720                 :            : #ifdef CONFIG_MAC80211_MESH
    1721                 :            : static int ieee80211_add_mpath(struct wiphy *wiphy, struct net_device *dev,
    1722                 :            :                                const u8 *dst, const u8 *next_hop)
    1723                 :            : {
    1724                 :            :         struct ieee80211_sub_if_data *sdata;
    1725                 :            :         struct mesh_path *mpath;
    1726                 :            :         struct sta_info *sta;
    1727                 :            : 
    1728                 :            :         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    1729                 :            : 
    1730                 :            :         rcu_read_lock();
    1731                 :            :         sta = sta_info_get(sdata, next_hop);
    1732                 :            :         if (!sta) {
    1733                 :            :                 rcu_read_unlock();
    1734                 :            :                 return -ENOENT;
    1735                 :            :         }
    1736                 :            : 
    1737                 :            :         mpath = mesh_path_add(sdata, dst);
    1738                 :            :         if (IS_ERR(mpath)) {
    1739                 :            :                 rcu_read_unlock();
    1740                 :            :                 return PTR_ERR(mpath);
    1741                 :            :         }
    1742                 :            : 
    1743                 :            :         mesh_path_fix_nexthop(mpath, sta);
    1744                 :            : 
    1745                 :            :         rcu_read_unlock();
    1746                 :            :         return 0;
    1747                 :            : }
    1748                 :            : 
    1749                 :            : static int ieee80211_del_mpath(struct wiphy *wiphy, struct net_device *dev,
    1750                 :            :                                const u8 *dst)
    1751                 :            : {
    1752                 :            :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    1753                 :            : 
    1754                 :            :         if (dst)
    1755                 :            :                 return mesh_path_del(sdata, dst);
    1756                 :            : 
    1757                 :            :         mesh_path_flush_by_iface(sdata);
    1758                 :            :         return 0;
    1759                 :            : }
    1760                 :            : 
    1761                 :            : static int ieee80211_change_mpath(struct wiphy *wiphy, struct net_device *dev,
    1762                 :            :                                   const u8 *dst, const u8 *next_hop)
    1763                 :            : {
    1764                 :            :         struct ieee80211_sub_if_data *sdata;
    1765                 :            :         struct mesh_path *mpath;
    1766                 :            :         struct sta_info *sta;
    1767                 :            : 
    1768                 :            :         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    1769                 :            : 
    1770                 :            :         rcu_read_lock();
    1771                 :            : 
    1772                 :            :         sta = sta_info_get(sdata, next_hop);
    1773                 :            :         if (!sta) {
    1774                 :            :                 rcu_read_unlock();
    1775                 :            :                 return -ENOENT;
    1776                 :            :         }
    1777                 :            : 
    1778                 :            :         mpath = mesh_path_lookup(sdata, dst);
    1779                 :            :         if (!mpath) {
    1780                 :            :                 rcu_read_unlock();
    1781                 :            :                 return -ENOENT;
    1782                 :            :         }
    1783                 :            : 
    1784                 :            :         mesh_path_fix_nexthop(mpath, sta);
    1785                 :            : 
    1786                 :            :         rcu_read_unlock();
    1787                 :            :         return 0;
    1788                 :            : }
    1789                 :            : 
    1790                 :            : static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
    1791                 :            :                             struct mpath_info *pinfo)
    1792                 :            : {
    1793                 :            :         struct sta_info *next_hop_sta = rcu_dereference(mpath->next_hop);
    1794                 :            : 
    1795                 :            :         if (next_hop_sta)
    1796                 :            :                 memcpy(next_hop, next_hop_sta->sta.addr, ETH_ALEN);
    1797                 :            :         else
    1798                 :            :                 eth_zero_addr(next_hop);
    1799                 :            : 
    1800                 :            :         memset(pinfo, 0, sizeof(*pinfo));
    1801                 :            : 
    1802                 :            :         pinfo->generation = mpath->sdata->u.mesh.mesh_paths_generation;
    1803                 :            : 
    1804                 :            :         pinfo->filled = MPATH_INFO_FRAME_QLEN |
    1805                 :            :                         MPATH_INFO_SN |
    1806                 :            :                         MPATH_INFO_METRIC |
    1807                 :            :                         MPATH_INFO_EXPTIME |
    1808                 :            :                         MPATH_INFO_DISCOVERY_TIMEOUT |
    1809                 :            :                         MPATH_INFO_DISCOVERY_RETRIES |
    1810                 :            :                         MPATH_INFO_FLAGS |
    1811                 :            :                         MPATH_INFO_HOP_COUNT |
    1812                 :            :                         MPATH_INFO_PATH_CHANGE;
    1813                 :            : 
    1814                 :            :         pinfo->frame_qlen = mpath->frame_queue.qlen;
    1815                 :            :         pinfo->sn = mpath->sn;
    1816                 :            :         pinfo->metric = mpath->metric;
    1817                 :            :         if (time_before(jiffies, mpath->exp_time))
    1818                 :            :                 pinfo->exptime = jiffies_to_msecs(mpath->exp_time - jiffies);
    1819                 :            :         pinfo->discovery_timeout =
    1820                 :            :                         jiffies_to_msecs(mpath->discovery_timeout);
    1821                 :            :         pinfo->discovery_retries = mpath->discovery_retries;
    1822                 :            :         if (mpath->flags & MESH_PATH_ACTIVE)
    1823                 :            :                 pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
    1824                 :            :         if (mpath->flags & MESH_PATH_RESOLVING)
    1825                 :            :                 pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
    1826                 :            :         if (mpath->flags & MESH_PATH_SN_VALID)
    1827                 :            :                 pinfo->flags |= NL80211_MPATH_FLAG_SN_VALID;
    1828                 :            :         if (mpath->flags & MESH_PATH_FIXED)
    1829                 :            :                 pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
    1830                 :            :         if (mpath->flags & MESH_PATH_RESOLVED)
    1831                 :            :                 pinfo->flags |= NL80211_MPATH_FLAG_RESOLVED;
    1832                 :            :         pinfo->hop_count = mpath->hop_count;
    1833                 :            :         pinfo->path_change_count = mpath->path_change_count;
    1834                 :            : }
    1835                 :            : 
    1836                 :            : static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
    1837                 :            :                                u8 *dst, u8 *next_hop, struct mpath_info *pinfo)
    1838                 :            : 
    1839                 :            : {
    1840                 :            :         struct ieee80211_sub_if_data *sdata;
    1841                 :            :         struct mesh_path *mpath;
    1842                 :            : 
    1843                 :            :         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    1844                 :            : 
    1845                 :            :         rcu_read_lock();
    1846                 :            :         mpath = mesh_path_lookup(sdata, dst);
    1847                 :            :         if (!mpath) {
    1848                 :            :                 rcu_read_unlock();
    1849                 :            :                 return -ENOENT;
    1850                 :            :         }
    1851                 :            :         memcpy(dst, mpath->dst, ETH_ALEN);
    1852                 :            :         mpath_set_pinfo(mpath, next_hop, pinfo);
    1853                 :            :         rcu_read_unlock();
    1854                 :            :         return 0;
    1855                 :            : }
    1856                 :            : 
    1857                 :            : static int ieee80211_dump_mpath(struct wiphy *wiphy, struct net_device *dev,
    1858                 :            :                                 int idx, u8 *dst, u8 *next_hop,
    1859                 :            :                                 struct mpath_info *pinfo)
    1860                 :            : {
    1861                 :            :         struct ieee80211_sub_if_data *sdata;
    1862                 :            :         struct mesh_path *mpath;
    1863                 :            : 
    1864                 :            :         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    1865                 :            : 
    1866                 :            :         rcu_read_lock();
    1867                 :            :         mpath = mesh_path_lookup_by_idx(sdata, idx);
    1868                 :            :         if (!mpath) {
    1869                 :            :                 rcu_read_unlock();
    1870                 :            :                 return -ENOENT;
    1871                 :            :         }
    1872                 :            :         memcpy(dst, mpath->dst, ETH_ALEN);
    1873                 :            :         mpath_set_pinfo(mpath, next_hop, pinfo);
    1874                 :            :         rcu_read_unlock();
    1875                 :            :         return 0;
    1876                 :            : }
    1877                 :            : 
    1878                 :            : static void mpp_set_pinfo(struct mesh_path *mpath, u8 *mpp,
    1879                 :            :                           struct mpath_info *pinfo)
    1880                 :            : {
    1881                 :            :         memset(pinfo, 0, sizeof(*pinfo));
    1882                 :            :         memcpy(mpp, mpath->mpp, ETH_ALEN);
    1883                 :            : 
    1884                 :            :         pinfo->generation = mpath->sdata->u.mesh.mpp_paths_generation;
    1885                 :            : }
    1886                 :            : 
    1887                 :            : static int ieee80211_get_mpp(struct wiphy *wiphy, struct net_device *dev,
    1888                 :            :                              u8 *dst, u8 *mpp, struct mpath_info *pinfo)
    1889                 :            : 
    1890                 :            : {
    1891                 :            :         struct ieee80211_sub_if_data *sdata;
    1892                 :            :         struct mesh_path *mpath;
    1893                 :            : 
    1894                 :            :         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    1895                 :            : 
    1896                 :            :         rcu_read_lock();
    1897                 :            :         mpath = mpp_path_lookup(sdata, dst);
    1898                 :            :         if (!mpath) {
    1899                 :            :                 rcu_read_unlock();
    1900                 :            :                 return -ENOENT;
    1901                 :            :         }
    1902                 :            :         memcpy(dst, mpath->dst, ETH_ALEN);
    1903                 :            :         mpp_set_pinfo(mpath, mpp, pinfo);
    1904                 :            :         rcu_read_unlock();
    1905                 :            :         return 0;
    1906                 :            : }
    1907                 :            : 
    1908                 :            : static int ieee80211_dump_mpp(struct wiphy *wiphy, struct net_device *dev,
    1909                 :            :                               int idx, u8 *dst, u8 *mpp,
    1910                 :            :                               struct mpath_info *pinfo)
    1911                 :            : {
    1912                 :            :         struct ieee80211_sub_if_data *sdata;
    1913                 :            :         struct mesh_path *mpath;
    1914                 :            : 
    1915                 :            :         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    1916                 :            : 
    1917                 :            :         rcu_read_lock();
    1918                 :            :         mpath = mpp_path_lookup_by_idx(sdata, idx);
    1919                 :            :         if (!mpath) {
    1920                 :            :                 rcu_read_unlock();
    1921                 :            :                 return -ENOENT;
    1922                 :            :         }
    1923                 :            :         memcpy(dst, mpath->dst, ETH_ALEN);
    1924                 :            :         mpp_set_pinfo(mpath, mpp, pinfo);
    1925                 :            :         rcu_read_unlock();
    1926                 :            :         return 0;
    1927                 :            : }
    1928                 :            : 
    1929                 :            : static int ieee80211_get_mesh_config(struct wiphy *wiphy,
    1930                 :            :                                 struct net_device *dev,
    1931                 :            :                                 struct mesh_config *conf)
    1932                 :            : {
    1933                 :            :         struct ieee80211_sub_if_data *sdata;
    1934                 :            :         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    1935                 :            : 
    1936                 :            :         memcpy(conf, &(sdata->u.mesh.mshcfg), sizeof(struct mesh_config));
    1937                 :            :         return 0;
    1938                 :            : }
    1939                 :            : 
    1940                 :            : static inline bool _chg_mesh_attr(enum nl80211_meshconf_params parm, u32 mask)
    1941                 :            : {
    1942                 :            :         return (mask >> (parm-1)) & 0x1;
    1943                 :            : }
    1944                 :            : 
    1945                 :            : static int copy_mesh_setup(struct ieee80211_if_mesh *ifmsh,
    1946                 :            :                 const struct mesh_setup *setup)
    1947                 :            : {
    1948                 :            :         u8 *new_ie;
    1949                 :            :         const u8 *old_ie;
    1950                 :            :         struct ieee80211_sub_if_data *sdata = container_of(ifmsh,
    1951                 :            :                                         struct ieee80211_sub_if_data, u.mesh);
    1952                 :            : 
    1953                 :            :         /* allocate information elements */
    1954                 :            :         new_ie = NULL;
    1955                 :            :         old_ie = ifmsh->ie;
    1956                 :            : 
    1957                 :            :         if (setup->ie_len) {
    1958                 :            :                 new_ie = kmemdup(setup->ie, setup->ie_len,
    1959                 :            :                                 GFP_KERNEL);
    1960                 :            :                 if (!new_ie)
    1961                 :            :                         return -ENOMEM;
    1962                 :            :         }
    1963                 :            :         ifmsh->ie_len = setup->ie_len;
    1964                 :            :         ifmsh->ie = new_ie;
    1965                 :            :         kfree(old_ie);
    1966                 :            : 
    1967                 :            :         /* now copy the rest of the setup parameters */
    1968                 :            :         ifmsh->mesh_id_len = setup->mesh_id_len;
    1969                 :            :         memcpy(ifmsh->mesh_id, setup->mesh_id, ifmsh->mesh_id_len);
    1970                 :            :         ifmsh->mesh_sp_id = setup->sync_method;
    1971                 :            :         ifmsh->mesh_pp_id = setup->path_sel_proto;
    1972                 :            :         ifmsh->mesh_pm_id = setup->path_metric;
    1973                 :            :         ifmsh->user_mpm = setup->user_mpm;
    1974                 :            :         ifmsh->mesh_auth_id = setup->auth_id;
    1975                 :            :         ifmsh->security = IEEE80211_MESH_SEC_NONE;
    1976                 :            :         ifmsh->userspace_handles_dfs = setup->userspace_handles_dfs;
    1977                 :            :         if (setup->is_authenticated)
    1978                 :            :                 ifmsh->security |= IEEE80211_MESH_SEC_AUTHED;
    1979                 :            :         if (setup->is_secure)
    1980                 :            :                 ifmsh->security |= IEEE80211_MESH_SEC_SECURED;
    1981                 :            : 
    1982                 :            :         /* mcast rate setting in Mesh Node */
    1983                 :            :         memcpy(sdata->vif.bss_conf.mcast_rate, setup->mcast_rate,
    1984                 :            :                                                 sizeof(setup->mcast_rate));
    1985                 :            :         sdata->vif.bss_conf.basic_rates = setup->basic_rates;
    1986                 :            : 
    1987                 :            :         sdata->vif.bss_conf.beacon_int = setup->beacon_interval;
    1988                 :            :         sdata->vif.bss_conf.dtim_period = setup->dtim_period;
    1989                 :            : 
    1990                 :            :         return 0;
    1991                 :            : }
    1992                 :            : 
    1993                 :            : static int ieee80211_update_mesh_config(struct wiphy *wiphy,
    1994                 :            :                                         struct net_device *dev, u32 mask,
    1995                 :            :                                         const struct mesh_config *nconf)
    1996                 :            : {
    1997                 :            :         struct mesh_config *conf;
    1998                 :            :         struct ieee80211_sub_if_data *sdata;
    1999                 :            :         struct ieee80211_if_mesh *ifmsh;
    2000                 :            : 
    2001                 :            :         sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    2002                 :            :         ifmsh = &sdata->u.mesh;
    2003                 :            : 
    2004                 :            :         /* Set the config options which we are interested in setting */
    2005                 :            :         conf = &(sdata->u.mesh.mshcfg);
    2006                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_RETRY_TIMEOUT, mask))
    2007                 :            :                 conf->dot11MeshRetryTimeout = nconf->dot11MeshRetryTimeout;
    2008                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_CONFIRM_TIMEOUT, mask))
    2009                 :            :                 conf->dot11MeshConfirmTimeout = nconf->dot11MeshConfirmTimeout;
    2010                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_HOLDING_TIMEOUT, mask))
    2011                 :            :                 conf->dot11MeshHoldingTimeout = nconf->dot11MeshHoldingTimeout;
    2012                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_MAX_PEER_LINKS, mask))
    2013                 :            :                 conf->dot11MeshMaxPeerLinks = nconf->dot11MeshMaxPeerLinks;
    2014                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_MAX_RETRIES, mask))
    2015                 :            :                 conf->dot11MeshMaxRetries = nconf->dot11MeshMaxRetries;
    2016                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_TTL, mask))
    2017                 :            :                 conf->dot11MeshTTL = nconf->dot11MeshTTL;
    2018                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_ELEMENT_TTL, mask))
    2019                 :            :                 conf->element_ttl = nconf->element_ttl;
    2020                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_AUTO_OPEN_PLINKS, mask)) {
    2021                 :            :                 if (ifmsh->user_mpm)
    2022                 :            :                         return -EBUSY;
    2023                 :            :                 conf->auto_open_plinks = nconf->auto_open_plinks;
    2024                 :            :         }
    2025                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_SYNC_OFFSET_MAX_NEIGHBOR, mask))
    2026                 :            :                 conf->dot11MeshNbrOffsetMaxNeighbor =
    2027                 :            :                         nconf->dot11MeshNbrOffsetMaxNeighbor;
    2028                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_MAX_PREQ_RETRIES, mask))
    2029                 :            :                 conf->dot11MeshHWMPmaxPREQretries =
    2030                 :            :                         nconf->dot11MeshHWMPmaxPREQretries;
    2031                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_PATH_REFRESH_TIME, mask))
    2032                 :            :                 conf->path_refresh_time = nconf->path_refresh_time;
    2033                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_MIN_DISCOVERY_TIMEOUT, mask))
    2034                 :            :                 conf->min_discovery_timeout = nconf->min_discovery_timeout;
    2035                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ACTIVE_PATH_TIMEOUT, mask))
    2036                 :            :                 conf->dot11MeshHWMPactivePathTimeout =
    2037                 :            :                         nconf->dot11MeshHWMPactivePathTimeout;
    2038                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PREQ_MIN_INTERVAL, mask))
    2039                 :            :                 conf->dot11MeshHWMPpreqMinInterval =
    2040                 :            :                         nconf->dot11MeshHWMPpreqMinInterval;
    2041                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PERR_MIN_INTERVAL, mask))
    2042                 :            :                 conf->dot11MeshHWMPperrMinInterval =
    2043                 :            :                         nconf->dot11MeshHWMPperrMinInterval;
    2044                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_NET_DIAM_TRVS_TIME,
    2045                 :            :                            mask))
    2046                 :            :                 conf->dot11MeshHWMPnetDiameterTraversalTime =
    2047                 :            :                         nconf->dot11MeshHWMPnetDiameterTraversalTime;
    2048                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ROOTMODE, mask)) {
    2049                 :            :                 conf->dot11MeshHWMPRootMode = nconf->dot11MeshHWMPRootMode;
    2050                 :            :                 ieee80211_mesh_root_setup(ifmsh);
    2051                 :            :         }
    2052                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_GATE_ANNOUNCEMENTS, mask)) {
    2053                 :            :                 /* our current gate announcement implementation rides on root
    2054                 :            :                  * announcements, so require this ifmsh to also be a root node
    2055                 :            :                  * */
    2056                 :            :                 if (nconf->dot11MeshGateAnnouncementProtocol &&
    2057                 :            :                     !(conf->dot11MeshHWMPRootMode > IEEE80211_ROOTMODE_ROOT)) {
    2058                 :            :                         conf->dot11MeshHWMPRootMode = IEEE80211_PROACTIVE_RANN;
    2059                 :            :                         ieee80211_mesh_root_setup(ifmsh);
    2060                 :            :                 }
    2061                 :            :                 conf->dot11MeshGateAnnouncementProtocol =
    2062                 :            :                         nconf->dot11MeshGateAnnouncementProtocol;
    2063                 :            :         }
    2064                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_RANN_INTERVAL, mask))
    2065                 :            :                 conf->dot11MeshHWMPRannInterval =
    2066                 :            :                         nconf->dot11MeshHWMPRannInterval;
    2067                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_FORWARDING, mask))
    2068                 :            :                 conf->dot11MeshForwarding = nconf->dot11MeshForwarding;
    2069                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_RSSI_THRESHOLD, mask)) {
    2070                 :            :                 /* our RSSI threshold implementation is supported only for
    2071                 :            :                  * devices that report signal in dBm.
    2072                 :            :                  */
    2073                 :            :                 if (!ieee80211_hw_check(&sdata->local->hw, SIGNAL_DBM))
    2074                 :            :                         return -ENOTSUPP;
    2075                 :            :                 conf->rssi_threshold = nconf->rssi_threshold;
    2076                 :            :         }
    2077                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_HT_OPMODE, mask)) {
    2078                 :            :                 conf->ht_opmode = nconf->ht_opmode;
    2079                 :            :                 sdata->vif.bss_conf.ht_operation_mode = nconf->ht_opmode;
    2080                 :            :                 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_HT);
    2081                 :            :         }
    2082                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, mask))
    2083                 :            :                 conf->dot11MeshHWMPactivePathToRootTimeout =
    2084                 :            :                         nconf->dot11MeshHWMPactivePathToRootTimeout;
    2085                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_ROOT_INTERVAL, mask))
    2086                 :            :                 conf->dot11MeshHWMProotInterval =
    2087                 :            :                         nconf->dot11MeshHWMProotInterval;
    2088                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_CONFIRMATION_INTERVAL, mask))
    2089                 :            :                 conf->dot11MeshHWMPconfirmationInterval =
    2090                 :            :                         nconf->dot11MeshHWMPconfirmationInterval;
    2091                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_POWER_MODE, mask)) {
    2092                 :            :                 conf->power_mode = nconf->power_mode;
    2093                 :            :                 ieee80211_mps_local_status_update(sdata);
    2094                 :            :         }
    2095                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_AWAKE_WINDOW, mask))
    2096                 :            :                 conf->dot11MeshAwakeWindowDuration =
    2097                 :            :                         nconf->dot11MeshAwakeWindowDuration;
    2098                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_PLINK_TIMEOUT, mask))
    2099                 :            :                 conf->plink_timeout = nconf->plink_timeout;
    2100                 :            :         if (_chg_mesh_attr(NL80211_MESHCONF_CONNECTED_TO_GATE, mask))
    2101                 :            :                 conf->dot11MeshConnectedToMeshGate =
    2102                 :            :                         nconf->dot11MeshConnectedToMeshGate;
    2103                 :            :         ieee80211_mbss_info_change_notify(sdata, BSS_CHANGED_BEACON);
    2104                 :            :         return 0;
    2105                 :            : }
    2106                 :            : 
    2107                 :            : static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
    2108                 :            :                                const struct mesh_config *conf,
    2109                 :            :                                const struct mesh_setup *setup)
    2110                 :            : {
    2111                 :            :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    2112                 :            :         struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
    2113                 :            :         int err;
    2114                 :            : 
    2115                 :            :         memcpy(&ifmsh->mshcfg, conf, sizeof(struct mesh_config));
    2116                 :            :         err = copy_mesh_setup(ifmsh, setup);
    2117                 :            :         if (err)
    2118                 :            :                 return err;
    2119                 :            : 
    2120                 :            :         sdata->control_port_over_nl80211 = setup->control_port_over_nl80211;
    2121                 :            : 
    2122                 :            :         /* can mesh use other SMPS modes? */
    2123                 :            :         sdata->smps_mode = IEEE80211_SMPS_OFF;
    2124                 :            :         sdata->needed_rx_chains = sdata->local->rx_chains;
    2125                 :            : 
    2126                 :            :         mutex_lock(&sdata->local->mtx);
    2127                 :            :         err = ieee80211_vif_use_channel(sdata, &setup->chandef,
    2128                 :            :                                         IEEE80211_CHANCTX_SHARED);
    2129                 :            :         mutex_unlock(&sdata->local->mtx);
    2130                 :            :         if (err)
    2131                 :            :                 return err;
    2132                 :            : 
    2133                 :            :         return ieee80211_start_mesh(sdata);
    2134                 :            : }
    2135                 :            : 
    2136                 :            : static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)
    2137                 :            : {
    2138                 :            :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    2139                 :            : 
    2140                 :            :         ieee80211_stop_mesh(sdata);
    2141                 :            :         mutex_lock(&sdata->local->mtx);
    2142                 :            :         ieee80211_vif_release_channel(sdata);
    2143                 :            :         mutex_unlock(&sdata->local->mtx);
    2144                 :            : 
    2145                 :            :         return 0;
    2146                 :            : }
    2147                 :            : #endif
    2148                 :            : 
    2149                 :          0 : static int ieee80211_change_bss(struct wiphy *wiphy,
    2150                 :            :                                 struct net_device *dev,
    2151                 :            :                                 struct bss_parameters *params)
    2152                 :            : {
    2153         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    2154                 :          0 :         struct ieee80211_supported_band *sband;
    2155                 :          0 :         u32 changed = 0;
    2156                 :            : 
    2157         [ #  # ]:          0 :         if (!sdata_dereference(sdata->u.ap.beacon, sdata))
    2158                 :            :                 return -ENOENT;
    2159                 :            : 
    2160                 :          0 :         sband = ieee80211_get_sband(sdata);
    2161         [ #  # ]:          0 :         if (!sband)
    2162                 :            :                 return -EINVAL;
    2163                 :            : 
    2164         [ #  # ]:          0 :         if (params->use_cts_prot >= 0) {
    2165                 :          0 :                 sdata->vif.bss_conf.use_cts_prot = params->use_cts_prot;
    2166                 :          0 :                 changed |= BSS_CHANGED_ERP_CTS_PROT;
    2167                 :            :         }
    2168         [ #  # ]:          0 :         if (params->use_short_preamble >= 0) {
    2169                 :          0 :                 sdata->vif.bss_conf.use_short_preamble =
    2170                 :          0 :                         params->use_short_preamble;
    2171                 :          0 :                 changed |= BSS_CHANGED_ERP_PREAMBLE;
    2172                 :            :         }
    2173                 :            : 
    2174         [ #  # ]:          0 :         if (!sdata->vif.bss_conf.use_short_slot &&
    2175         [ #  # ]:          0 :             sband->band == NL80211_BAND_5GHZ) {
    2176                 :          0 :                 sdata->vif.bss_conf.use_short_slot = true;
    2177                 :          0 :                 changed |= BSS_CHANGED_ERP_SLOT;
    2178                 :            :         }
    2179                 :            : 
    2180         [ #  # ]:          0 :         if (params->use_short_slot_time >= 0) {
    2181                 :          0 :                 sdata->vif.bss_conf.use_short_slot =
    2182                 :          0 :                         params->use_short_slot_time;
    2183                 :          0 :                 changed |= BSS_CHANGED_ERP_SLOT;
    2184                 :            :         }
    2185                 :            : 
    2186         [ #  # ]:          0 :         if (params->basic_rates) {
    2187                 :          0 :                 ieee80211_parse_bitrates(&sdata->vif.bss_conf.chandef,
    2188                 :          0 :                                          wiphy->bands[sband->band],
    2189                 :            :                                          params->basic_rates,
    2190                 :          0 :                                          params->basic_rates_len,
    2191                 :            :                                          &sdata->vif.bss_conf.basic_rates);
    2192                 :          0 :                 changed |= BSS_CHANGED_BASIC_RATES;
    2193                 :          0 :                 ieee80211_check_rate_mask(sdata);
    2194                 :            :         }
    2195                 :            : 
    2196         [ #  # ]:          0 :         if (params->ap_isolate >= 0) {
    2197         [ #  # ]:          0 :                 if (params->ap_isolate)
    2198                 :          0 :                         sdata->flags |= IEEE80211_SDATA_DONT_BRIDGE_PACKETS;
    2199                 :            :                 else
    2200                 :          0 :                         sdata->flags &= ~IEEE80211_SDATA_DONT_BRIDGE_PACKETS;
    2201                 :          0 :                 ieee80211_check_fast_rx_iface(sdata);
    2202                 :            :         }
    2203                 :            : 
    2204         [ #  # ]:          0 :         if (params->ht_opmode >= 0) {
    2205                 :          0 :                 sdata->vif.bss_conf.ht_operation_mode =
    2206                 :          0 :                         (u16) params->ht_opmode;
    2207                 :          0 :                 changed |= BSS_CHANGED_HT;
    2208                 :            :         }
    2209                 :            : 
    2210         [ #  # ]:          0 :         if (params->p2p_ctwindow >= 0) {
    2211                 :          0 :                 sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &=
    2212                 :            :                                         ~IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
    2213                 :          0 :                 sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
    2214                 :          0 :                         params->p2p_ctwindow & IEEE80211_P2P_OPPPS_CTWINDOW_MASK;
    2215                 :          0 :                 changed |= BSS_CHANGED_P2P_PS;
    2216                 :            :         }
    2217                 :            : 
    2218         [ #  # ]:          0 :         if (params->p2p_opp_ps > 0) {
    2219                 :          0 :                 sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow |=
    2220                 :            :                                         IEEE80211_P2P_OPPPS_ENABLE_BIT;
    2221                 :          0 :                 changed |= BSS_CHANGED_P2P_PS;
    2222         [ #  # ]:          0 :         } else if (params->p2p_opp_ps == 0) {
    2223                 :          0 :                 sdata->vif.bss_conf.p2p_noa_attr.oppps_ctwindow &=
    2224                 :            :                                         ~IEEE80211_P2P_OPPPS_ENABLE_BIT;
    2225                 :          0 :                 changed |= BSS_CHANGED_P2P_PS;
    2226                 :            :         }
    2227                 :            : 
    2228                 :          0 :         ieee80211_bss_info_change_notify(sdata, changed);
    2229                 :            : 
    2230                 :          0 :         return 0;
    2231                 :            : }
    2232                 :            : 
    2233                 :          0 : static int ieee80211_set_txq_params(struct wiphy *wiphy,
    2234                 :            :                                     struct net_device *dev,
    2235                 :            :                                     struct ieee80211_txq_params *params)
    2236                 :            : {
    2237         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    2238         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    2239                 :            :         struct ieee80211_tx_queue_params p;
    2240                 :            : 
    2241         [ #  # ]:          0 :         if (!local->ops->conf_tx)
    2242                 :            :                 return -EOPNOTSUPP;
    2243                 :            : 
    2244         [ #  # ]:          0 :         if (local->hw.queues < IEEE80211_NUM_ACS)
    2245                 :            :                 return -EOPNOTSUPP;
    2246                 :            : 
    2247                 :          0 :         memset(&p, 0, sizeof(p));
    2248                 :          0 :         p.aifs = params->aifs;
    2249                 :          0 :         p.cw_max = params->cwmax;
    2250                 :          0 :         p.cw_min = params->cwmin;
    2251                 :          0 :         p.txop = params->txop;
    2252                 :            : 
    2253                 :            :         /*
    2254                 :            :          * Setting tx queue params disables u-apsd because it's only
    2255                 :            :          * called in master mode.
    2256                 :            :          */
    2257                 :          0 :         p.uapsd = false;
    2258                 :            : 
    2259                 :          0 :         ieee80211_regulatory_limit_wmm_params(sdata, &p, params->ac);
    2260                 :            : 
    2261                 :          0 :         sdata->tx_conf[params->ac] = p;
    2262         [ #  # ]:          0 :         if (drv_conf_tx(local, sdata, params->ac, &p)) {
    2263                 :          0 :                 wiphy_debug(local->hw.wiphy,
    2264                 :            :                             "failed to set TX queue parameters for AC %d\n",
    2265                 :            :                             params->ac);
    2266                 :          0 :                 return -EINVAL;
    2267                 :            :         }
    2268                 :            : 
    2269                 :          0 :         ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_QOS);
    2270                 :            : 
    2271                 :          0 :         return 0;
    2272                 :            : }
    2273                 :            : 
    2274                 :            : #ifdef CONFIG_PM
    2275                 :          0 : static int ieee80211_suspend(struct wiphy *wiphy,
    2276                 :            :                              struct cfg80211_wowlan *wowlan)
    2277                 :            : {
    2278         [ #  # ]:          0 :         return __ieee80211_suspend(wiphy_priv(wiphy), wowlan);
    2279                 :            : }
    2280                 :            : 
    2281                 :          0 : static int ieee80211_resume(struct wiphy *wiphy)
    2282                 :            : {
    2283         [ #  # ]:          0 :         return __ieee80211_resume(wiphy_priv(wiphy));
    2284                 :            : }
    2285                 :            : #else
    2286                 :            : #define ieee80211_suspend NULL
    2287                 :            : #define ieee80211_resume NULL
    2288                 :            : #endif
    2289                 :            : 
    2290                 :          0 : static int ieee80211_scan(struct wiphy *wiphy,
    2291                 :            :                           struct cfg80211_scan_request *req)
    2292                 :            : {
    2293                 :          0 :         struct ieee80211_sub_if_data *sdata;
    2294                 :            : 
    2295         [ #  # ]:          0 :         sdata = IEEE80211_WDEV_TO_SUB_IF(req->wdev);
    2296                 :            : 
    2297   [ #  #  #  #  :          0 :         switch (ieee80211_vif_type_p2p(&sdata->vif)) {
                   #  # ]
    2298                 :            :         case NL80211_IFTYPE_STATION:
    2299                 :            :         case NL80211_IFTYPE_ADHOC:
    2300                 :            :         case NL80211_IFTYPE_MESH_POINT:
    2301                 :            :         case NL80211_IFTYPE_P2P_CLIENT:
    2302                 :            :         case NL80211_IFTYPE_P2P_DEVICE:
    2303                 :            :                 break;
    2304                 :          0 :         case NL80211_IFTYPE_P2P_GO:
    2305         [ #  # ]:          0 :                 if (sdata->local->ops->hw_scan)
    2306                 :            :                         break;
    2307                 :            :                 /*
    2308                 :            :                  * FIXME: implement NoA while scanning in software,
    2309                 :            :                  * for now fall through to allow scanning only when
    2310                 :            :                  * beaconing hasn't been configured yet
    2311                 :            :                  */
    2312                 :            :                 /* fall through */
    2313                 :            :         case NL80211_IFTYPE_AP:
    2314                 :            :                 /*
    2315                 :            :                  * If the scan has been forced (and the driver supports
    2316                 :            :                  * forcing), don't care about being beaconing already.
    2317                 :            :                  * This will create problems to the attached stations (e.g. all
    2318                 :            :                  * the  frames sent while scanning on other channel will be
    2319                 :            :                  * lost)
    2320                 :            :                  */
    2321         [ #  # ]:          0 :                 if (sdata->u.ap.beacon &&
    2322         [ #  # ]:          0 :                     (!(wiphy->features & NL80211_FEATURE_AP_SCAN) ||
    2323         [ #  # ]:          0 :                      !(req->flags & NL80211_SCAN_FLAG_AP)))
    2324                 :            :                         return -EOPNOTSUPP;
    2325                 :            :                 break;
    2326                 :            :         case NL80211_IFTYPE_NAN:
    2327                 :            :         default:
    2328                 :            :                 return -EOPNOTSUPP;
    2329                 :            :         }
    2330                 :            : 
    2331                 :          0 :         return ieee80211_request_scan(sdata, req);
    2332                 :            : }
    2333                 :            : 
    2334                 :          0 : static void ieee80211_abort_scan(struct wiphy *wiphy, struct wireless_dev *wdev)
    2335                 :            : {
    2336         [ #  # ]:          0 :         ieee80211_scan_cancel(wiphy_priv(wiphy));
    2337                 :          0 : }
    2338                 :            : 
    2339                 :            : static int
    2340                 :          0 : ieee80211_sched_scan_start(struct wiphy *wiphy,
    2341                 :            :                            struct net_device *dev,
    2342                 :            :                            struct cfg80211_sched_scan_request *req)
    2343                 :            : {
    2344         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    2345                 :            : 
    2346         [ #  # ]:          0 :         if (!sdata->local->ops->sched_scan_start)
    2347                 :            :                 return -EOPNOTSUPP;
    2348                 :            : 
    2349                 :          0 :         return ieee80211_request_sched_scan_start(sdata, req);
    2350                 :            : }
    2351                 :            : 
    2352                 :            : static int
    2353                 :          0 : ieee80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev,
    2354                 :            :                           u64 reqid)
    2355                 :            : {
    2356         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    2357                 :            : 
    2358         [ #  # ]:          0 :         if (!local->ops->sched_scan_stop)
    2359                 :            :                 return -EOPNOTSUPP;
    2360                 :            : 
    2361                 :          0 :         return ieee80211_request_sched_scan_stop(local);
    2362                 :            : }
    2363                 :            : 
    2364                 :          0 : static int ieee80211_auth(struct wiphy *wiphy, struct net_device *dev,
    2365                 :            :                           struct cfg80211_auth_request *req)
    2366                 :            : {
    2367                 :          0 :         return ieee80211_mgd_auth(IEEE80211_DEV_TO_SUB_IF(dev), req);
    2368                 :            : }
    2369                 :            : 
    2370                 :          0 : static int ieee80211_assoc(struct wiphy *wiphy, struct net_device *dev,
    2371                 :            :                            struct cfg80211_assoc_request *req)
    2372                 :            : {
    2373                 :          0 :         return ieee80211_mgd_assoc(IEEE80211_DEV_TO_SUB_IF(dev), req);
    2374                 :            : }
    2375                 :            : 
    2376                 :          0 : static int ieee80211_deauth(struct wiphy *wiphy, struct net_device *dev,
    2377                 :            :                             struct cfg80211_deauth_request *req)
    2378                 :            : {
    2379                 :          0 :         return ieee80211_mgd_deauth(IEEE80211_DEV_TO_SUB_IF(dev), req);
    2380                 :            : }
    2381                 :            : 
    2382                 :          0 : static int ieee80211_disassoc(struct wiphy *wiphy, struct net_device *dev,
    2383                 :            :                               struct cfg80211_disassoc_request *req)
    2384                 :            : {
    2385                 :          0 :         return ieee80211_mgd_disassoc(IEEE80211_DEV_TO_SUB_IF(dev), req);
    2386                 :            : }
    2387                 :            : 
    2388                 :          0 : static int ieee80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
    2389                 :            :                                struct cfg80211_ibss_params *params)
    2390                 :            : {
    2391                 :          0 :         return ieee80211_ibss_join(IEEE80211_DEV_TO_SUB_IF(dev), params);
    2392                 :            : }
    2393                 :            : 
    2394                 :          0 : static int ieee80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
    2395                 :            : {
    2396                 :          0 :         return ieee80211_ibss_leave(IEEE80211_DEV_TO_SUB_IF(dev));
    2397                 :            : }
    2398                 :            : 
    2399                 :          0 : static int ieee80211_join_ocb(struct wiphy *wiphy, struct net_device *dev,
    2400                 :            :                               struct ocb_setup *setup)
    2401                 :            : {
    2402                 :          0 :         return ieee80211_ocb_join(IEEE80211_DEV_TO_SUB_IF(dev), setup);
    2403                 :            : }
    2404                 :            : 
    2405                 :          0 : static int ieee80211_leave_ocb(struct wiphy *wiphy, struct net_device *dev)
    2406                 :            : {
    2407                 :          0 :         return ieee80211_ocb_leave(IEEE80211_DEV_TO_SUB_IF(dev));
    2408                 :            : }
    2409                 :            : 
    2410                 :          0 : static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev,
    2411                 :            :                                     int rate[NUM_NL80211_BANDS])
    2412                 :            : {
    2413                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    2414                 :            : 
    2415                 :          0 :         memcpy(sdata->vif.bss_conf.mcast_rate, rate,
    2416                 :            :                sizeof(int) * NUM_NL80211_BANDS);
    2417                 :            : 
    2418                 :          0 :         ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_MCAST_RATE);
    2419                 :            : 
    2420                 :          0 :         return 0;
    2421                 :            : }
    2422                 :            : 
    2423                 :          0 : static int ieee80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
    2424                 :            : {
    2425         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    2426                 :          0 :         int err;
    2427                 :            : 
    2428         [ #  # ]:          0 :         if (changed & WIPHY_PARAM_FRAG_THRESHOLD) {
    2429                 :          0 :                 ieee80211_check_fast_xmit_all(local);
    2430                 :            : 
    2431                 :          0 :                 err = drv_set_frag_threshold(local, wiphy->frag_threshold);
    2432                 :            : 
    2433         [ #  # ]:          0 :                 if (err) {
    2434                 :          0 :                         ieee80211_check_fast_xmit_all(local);
    2435                 :          0 :                         return err;
    2436                 :            :                 }
    2437                 :            :         }
    2438                 :            : 
    2439         [ #  # ]:          0 :         if ((changed & WIPHY_PARAM_COVERAGE_CLASS) ||
    2440                 :            :             (changed & WIPHY_PARAM_DYN_ACK)) {
    2441                 :          0 :                 s16 coverage_class;
    2442                 :            : 
    2443         [ #  # ]:          0 :                 coverage_class = changed & WIPHY_PARAM_COVERAGE_CLASS ?
    2444                 :          0 :                                         wiphy->coverage_class : -1;
    2445                 :          0 :                 err = drv_set_coverage_class(local, coverage_class);
    2446                 :            : 
    2447         [ #  # ]:          0 :                 if (err)
    2448                 :            :                         return err;
    2449                 :            :         }
    2450                 :            : 
    2451         [ #  # ]:          0 :         if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
    2452                 :          0 :                 err = drv_set_rts_threshold(local, wiphy->rts_threshold);
    2453                 :            : 
    2454         [ #  # ]:          0 :                 if (err)
    2455                 :            :                         return err;
    2456                 :            :         }
    2457                 :            : 
    2458         [ #  # ]:          0 :         if (changed & WIPHY_PARAM_RETRY_SHORT) {
    2459         [ #  # ]:          0 :                 if (wiphy->retry_short > IEEE80211_MAX_TX_RETRY)
    2460                 :            :                         return -EINVAL;
    2461                 :          0 :                 local->hw.conf.short_frame_max_tx_count = wiphy->retry_short;
    2462                 :            :         }
    2463         [ #  # ]:          0 :         if (changed & WIPHY_PARAM_RETRY_LONG) {
    2464         [ #  # ]:          0 :                 if (wiphy->retry_long > IEEE80211_MAX_TX_RETRY)
    2465                 :            :                         return -EINVAL;
    2466                 :          0 :                 local->hw.conf.long_frame_max_tx_count = wiphy->retry_long;
    2467                 :            :         }
    2468         [ #  # ]:          0 :         if (changed &
    2469                 :            :             (WIPHY_PARAM_RETRY_SHORT | WIPHY_PARAM_RETRY_LONG))
    2470                 :          0 :                 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_RETRY_LIMITS);
    2471                 :            : 
    2472         [ #  # ]:          0 :         if (changed & (WIPHY_PARAM_TXQ_LIMIT |
    2473                 :            :                        WIPHY_PARAM_TXQ_MEMORY_LIMIT |
    2474                 :            :                        WIPHY_PARAM_TXQ_QUANTUM))
    2475                 :          0 :                 ieee80211_txq_set_params(local);
    2476                 :            : 
    2477                 :            :         return 0;
    2478                 :            : }
    2479                 :            : 
    2480                 :          0 : static int ieee80211_set_tx_power(struct wiphy *wiphy,
    2481                 :            :                                   struct wireless_dev *wdev,
    2482                 :            :                                   enum nl80211_tx_power_setting type, int mbm)
    2483                 :            : {
    2484         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    2485                 :          0 :         struct ieee80211_sub_if_data *sdata;
    2486                 :          0 :         enum nl80211_tx_power_setting txp_type = type;
    2487                 :          0 :         bool update_txp_type = false;
    2488                 :          0 :         bool has_monitor = false;
    2489                 :            : 
    2490         [ #  # ]:          0 :         if (wdev) {
    2491         [ #  # ]:          0 :                 sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
    2492                 :            : 
    2493         [ #  # ]:          0 :                 if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
    2494                 :          0 :                         sdata = rtnl_dereference(local->monitor_sdata);
    2495         [ #  # ]:          0 :                         if (!sdata)
    2496                 :            :                                 return -EOPNOTSUPP;
    2497                 :            :                 }
    2498                 :            : 
    2499      [ #  #  # ]:          0 :                 switch (type) {
    2500                 :          0 :                 case NL80211_TX_POWER_AUTOMATIC:
    2501                 :          0 :                         sdata->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
    2502                 :          0 :                         txp_type = NL80211_TX_POWER_LIMITED;
    2503                 :          0 :                         break;
    2504                 :          0 :                 case NL80211_TX_POWER_LIMITED:
    2505                 :            :                 case NL80211_TX_POWER_FIXED:
    2506   [ #  #  #  # ]:          0 :                         if (mbm < 0 || (mbm % 100))
    2507                 :            :                                 return -EOPNOTSUPP;
    2508                 :          0 :                         sdata->user_power_level = MBM_TO_DBM(mbm);
    2509                 :          0 :                         break;
    2510                 :            :                 }
    2511                 :            : 
    2512         [ #  # ]:          0 :                 if (txp_type != sdata->vif.bss_conf.txpower_type) {
    2513                 :          0 :                         update_txp_type = true;
    2514                 :          0 :                         sdata->vif.bss_conf.txpower_type = txp_type;
    2515                 :            :                 }
    2516                 :            : 
    2517                 :          0 :                 ieee80211_recalc_txpower(sdata, update_txp_type);
    2518                 :            : 
    2519                 :          0 :                 return 0;
    2520                 :            :         }
    2521                 :            : 
    2522      [ #  #  # ]:          0 :         switch (type) {
    2523                 :          0 :         case NL80211_TX_POWER_AUTOMATIC:
    2524                 :          0 :                 local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
    2525                 :          0 :                 txp_type = NL80211_TX_POWER_LIMITED;
    2526                 :          0 :                 break;
    2527                 :          0 :         case NL80211_TX_POWER_LIMITED:
    2528                 :            :         case NL80211_TX_POWER_FIXED:
    2529   [ #  #  #  # ]:          0 :                 if (mbm < 0 || (mbm % 100))
    2530                 :            :                         return -EOPNOTSUPP;
    2531                 :          0 :                 local->user_power_level = MBM_TO_DBM(mbm);
    2532                 :          0 :                 break;
    2533                 :            :         }
    2534                 :            : 
    2535                 :          0 :         mutex_lock(&local->iflist_mtx);
    2536         [ #  # ]:          0 :         list_for_each_entry(sdata, &local->interfaces, list) {
    2537         [ #  # ]:          0 :                 if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
    2538                 :          0 :                         has_monitor = true;
    2539                 :          0 :                         continue;
    2540                 :            :                 }
    2541                 :          0 :                 sdata->user_power_level = local->user_power_level;
    2542         [ #  # ]:          0 :                 if (txp_type != sdata->vif.bss_conf.txpower_type)
    2543                 :          0 :                         update_txp_type = true;
    2544                 :          0 :                 sdata->vif.bss_conf.txpower_type = txp_type;
    2545                 :            :         }
    2546         [ #  # ]:          0 :         list_for_each_entry(sdata, &local->interfaces, list) {
    2547         [ #  # ]:          0 :                 if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
    2548                 :          0 :                         continue;
    2549                 :          0 :                 ieee80211_recalc_txpower(sdata, update_txp_type);
    2550                 :            :         }
    2551                 :          0 :         mutex_unlock(&local->iflist_mtx);
    2552                 :            : 
    2553         [ #  # ]:          0 :         if (has_monitor) {
    2554                 :          0 :                 sdata = rtnl_dereference(local->monitor_sdata);
    2555         [ #  # ]:          0 :                 if (sdata) {
    2556                 :          0 :                         sdata->user_power_level = local->user_power_level;
    2557         [ #  # ]:          0 :                         if (txp_type != sdata->vif.bss_conf.txpower_type)
    2558                 :          0 :                                 update_txp_type = true;
    2559                 :          0 :                         sdata->vif.bss_conf.txpower_type = txp_type;
    2560                 :            : 
    2561                 :          0 :                         ieee80211_recalc_txpower(sdata, update_txp_type);
    2562                 :            :                 }
    2563                 :            :         }
    2564                 :            : 
    2565                 :            :         return 0;
    2566                 :            : }
    2567                 :            : 
    2568                 :          0 : static int ieee80211_get_tx_power(struct wiphy *wiphy,
    2569                 :            :                                   struct wireless_dev *wdev,
    2570                 :            :                                   int *dbm)
    2571                 :            : {
    2572         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    2573         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
    2574                 :            : 
    2575         [ #  # ]:          0 :         if (local->ops->get_txpower)
    2576                 :          0 :                 return drv_get_txpower(local, sdata, dbm);
    2577                 :            : 
    2578         [ #  # ]:          0 :         if (!local->use_chanctx)
    2579                 :          0 :                 *dbm = local->hw.conf.power_level;
    2580                 :            :         else
    2581                 :          0 :                 *dbm = sdata->vif.bss_conf.txpower;
    2582                 :            : 
    2583                 :            :         return 0;
    2584                 :            : }
    2585                 :            : 
    2586                 :          0 : static int ieee80211_set_wds_peer(struct wiphy *wiphy, struct net_device *dev,
    2587                 :            :                                   const u8 *addr)
    2588                 :            : {
    2589                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    2590                 :            : 
    2591                 :          0 :         memcpy(&sdata->u.wds.remote_addr, addr, ETH_ALEN);
    2592                 :            : 
    2593                 :          0 :         return 0;
    2594                 :            : }
    2595                 :            : 
    2596                 :          0 : static void ieee80211_rfkill_poll(struct wiphy *wiphy)
    2597                 :            : {
    2598         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    2599                 :            : 
    2600                 :          0 :         drv_rfkill_poll(local);
    2601                 :          0 : }
    2602                 :            : 
    2603                 :            : #ifdef CONFIG_NL80211_TESTMODE
    2604                 :            : static int ieee80211_testmode_cmd(struct wiphy *wiphy,
    2605                 :            :                                   struct wireless_dev *wdev,
    2606                 :            :                                   void *data, int len)
    2607                 :            : {
    2608                 :            :         struct ieee80211_local *local = wiphy_priv(wiphy);
    2609                 :            :         struct ieee80211_vif *vif = NULL;
    2610                 :            : 
    2611                 :            :         if (!local->ops->testmode_cmd)
    2612                 :            :                 return -EOPNOTSUPP;
    2613                 :            : 
    2614                 :            :         if (wdev) {
    2615                 :            :                 struct ieee80211_sub_if_data *sdata;
    2616                 :            : 
    2617                 :            :                 sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
    2618                 :            :                 if (sdata->flags & IEEE80211_SDATA_IN_DRIVER)
    2619                 :            :                         vif = &sdata->vif;
    2620                 :            :         }
    2621                 :            : 
    2622                 :            :         return local->ops->testmode_cmd(&local->hw, vif, data, len);
    2623                 :            : }
    2624                 :            : 
    2625                 :            : static int ieee80211_testmode_dump(struct wiphy *wiphy,
    2626                 :            :                                    struct sk_buff *skb,
    2627                 :            :                                    struct netlink_callback *cb,
    2628                 :            :                                    void *data, int len)
    2629                 :            : {
    2630                 :            :         struct ieee80211_local *local = wiphy_priv(wiphy);
    2631                 :            : 
    2632                 :            :         if (!local->ops->testmode_dump)
    2633                 :            :                 return -EOPNOTSUPP;
    2634                 :            : 
    2635                 :            :         return local->ops->testmode_dump(&local->hw, skb, cb, data, len);
    2636                 :            : }
    2637                 :            : #endif
    2638                 :            : 
    2639                 :          0 : int __ieee80211_request_smps_ap(struct ieee80211_sub_if_data *sdata,
    2640                 :            :                                 enum ieee80211_smps_mode smps_mode)
    2641                 :            : {
    2642                 :          0 :         struct sta_info *sta;
    2643                 :          0 :         enum ieee80211_smps_mode old_req;
    2644                 :            : 
    2645   [ #  #  #  # ]:          0 :         if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_AP))
    2646                 :            :                 return -EINVAL;
    2647                 :            : 
    2648         [ #  # ]:          0 :         if (sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
    2649                 :            :                 return 0;
    2650                 :            : 
    2651                 :          0 :         old_req = sdata->u.ap.req_smps;
    2652                 :          0 :         sdata->u.ap.req_smps = smps_mode;
    2653                 :            : 
    2654                 :            :         /* AUTOMATIC doesn't mean much for AP - don't allow it */
    2655                 :          0 :         if (old_req == smps_mode ||
    2656         [ #  # ]:          0 :             smps_mode == IEEE80211_SMPS_AUTOMATIC)
    2657                 :            :                 return 0;
    2658                 :            : 
    2659                 :          0 :         ht_dbg(sdata,
    2660                 :            :                "SMPS %d requested in AP mode, sending Action frame to %d stations\n",
    2661                 :            :                smps_mode, atomic_read(&sdata->u.ap.num_mcast_sta));
    2662                 :            : 
    2663                 :          0 :         mutex_lock(&sdata->local->sta_mtx);
    2664         [ #  # ]:          0 :         list_for_each_entry(sta, &sdata->local->sta_list, list) {
    2665                 :            :                 /*
    2666                 :            :                  * Only stations associated to our AP and
    2667                 :            :                  * associated VLANs
    2668                 :            :                  */
    2669         [ #  # ]:          0 :                 if (sta->sdata->bss != &sdata->u.ap)
    2670                 :          0 :                         continue;
    2671                 :            : 
    2672                 :            :                 /* This station doesn't support MIMO - skip it */
    2673         [ #  # ]:          0 :                 if (sta_info_tx_streams(sta) == 1)
    2674                 :          0 :                         continue;
    2675                 :            : 
    2676                 :            :                 /*
    2677                 :            :                  * Don't wake up a STA just to send the action frame
    2678                 :            :                  * unless we are getting more restrictive.
    2679                 :            :                  */
    2680   [ #  #  #  # ]:          0 :                 if (test_sta_flag(sta, WLAN_STA_PS_STA) &&
    2681                 :          0 :                     !ieee80211_smps_is_restrictive(sta->known_smps_mode,
    2682                 :            :                                                    smps_mode)) {
    2683                 :          0 :                         ht_dbg(sdata, "Won't send SMPS to sleeping STA %pM\n",
    2684                 :            :                                sta->sta.addr);
    2685                 :          0 :                         continue;
    2686                 :            :                 }
    2687                 :            : 
    2688                 :            :                 /*
    2689                 :            :                  * If the STA is not authorized, wait until it gets
    2690                 :            :                  * authorized and the action frame will be sent then.
    2691                 :            :                  */
    2692         [ #  # ]:          0 :                 if (!test_sta_flag(sta, WLAN_STA_AUTHORIZED))
    2693                 :          0 :                         continue;
    2694                 :            : 
    2695                 :          0 :                 ht_dbg(sdata, "Sending SMPS to %pM\n", sta->sta.addr);
    2696                 :          0 :                 ieee80211_send_smps_action(sdata, smps_mode, sta->sta.addr,
    2697                 :            :                                            sdata->vif.bss_conf.bssid);
    2698                 :            :         }
    2699                 :          0 :         mutex_unlock(&sdata->local->sta_mtx);
    2700                 :            : 
    2701                 :          0 :         sdata->smps_mode = smps_mode;
    2702                 :          0 :         ieee80211_queue_work(&sdata->local->hw, &sdata->recalc_smps);
    2703                 :            : 
    2704                 :          0 :         return 0;
    2705                 :            : }
    2706                 :            : 
    2707                 :          0 : int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
    2708                 :            :                                  enum ieee80211_smps_mode smps_mode)
    2709                 :            : {
    2710                 :          0 :         const u8 *ap;
    2711                 :          0 :         enum ieee80211_smps_mode old_req;
    2712                 :          0 :         int err;
    2713                 :          0 :         struct sta_info *sta;
    2714                 :          0 :         bool tdls_peer_found = false;
    2715                 :            : 
    2716                 :          0 :         lockdep_assert_held(&sdata->wdev.mtx);
    2717                 :            : 
    2718   [ #  #  #  # ]:          0 :         if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION))
    2719                 :            :                 return -EINVAL;
    2720                 :            : 
    2721                 :          0 :         old_req = sdata->u.mgd.req_smps;
    2722                 :          0 :         sdata->u.mgd.req_smps = smps_mode;
    2723                 :            : 
    2724                 :          0 :         if (old_req == smps_mode &&
    2725         [ #  # ]:          0 :             smps_mode != IEEE80211_SMPS_AUTOMATIC)
    2726                 :            :                 return 0;
    2727                 :            : 
    2728                 :            :         /*
    2729                 :            :          * If not associated, or current association is not an HT
    2730                 :            :          * association, there's no need to do anything, just store
    2731                 :            :          * the new value until we associate.
    2732                 :            :          */
    2733         [ #  # ]:          0 :         if (!sdata->u.mgd.associated ||
    2734         [ #  # ]:          0 :             sdata->vif.bss_conf.chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
    2735                 :            :                 return 0;
    2736                 :            : 
    2737                 :          0 :         ap = sdata->u.mgd.associated->bssid;
    2738                 :            : 
    2739                 :          0 :         rcu_read_lock();
    2740         [ #  # ]:          0 :         list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
    2741   [ #  #  #  #  :          0 :                 if (!sta->sta.tdls || sta->sdata != sdata || !sta->uploaded ||
             #  #  #  # ]
    2742                 :            :                     !test_sta_flag(sta, WLAN_STA_AUTHORIZED))
    2743                 :          0 :                         continue;
    2744                 :            : 
    2745                 :            :                 tdls_peer_found = true;
    2746                 :            :                 break;
    2747                 :            :         }
    2748                 :          0 :         rcu_read_unlock();
    2749                 :            : 
    2750         [ #  # ]:          0 :         if (smps_mode == IEEE80211_SMPS_AUTOMATIC) {
    2751   [ #  #  #  # ]:          0 :                 if (tdls_peer_found || !sdata->u.mgd.powersave)
    2752                 :            :                         smps_mode = IEEE80211_SMPS_OFF;
    2753                 :            :                 else
    2754                 :          0 :                         smps_mode = IEEE80211_SMPS_DYNAMIC;
    2755                 :            :         }
    2756                 :            : 
    2757                 :            :         /* send SM PS frame to AP */
    2758                 :          0 :         err = ieee80211_send_smps_action(sdata, smps_mode,
    2759                 :            :                                          ap, ap);
    2760         [ #  # ]:          0 :         if (err)
    2761                 :          0 :                 sdata->u.mgd.req_smps = old_req;
    2762         [ #  # ]:          0 :         else if (smps_mode != IEEE80211_SMPS_OFF && tdls_peer_found)
    2763                 :          0 :                 ieee80211_teardown_tdls_peers(sdata);
    2764                 :            : 
    2765                 :            :         return err;
    2766                 :            : }
    2767                 :            : 
    2768                 :          0 : static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
    2769                 :            :                                     bool enabled, int timeout)
    2770                 :            : {
    2771                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    2772                 :          0 :         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
    2773                 :            : 
    2774         [ #  # ]:          0 :         if (sdata->vif.type != NL80211_IFTYPE_STATION)
    2775                 :            :                 return -EOPNOTSUPP;
    2776                 :            : 
    2777         [ #  # ]:          0 :         if (!ieee80211_hw_check(&local->hw, SUPPORTS_PS))
    2778                 :            :                 return -EOPNOTSUPP;
    2779                 :            : 
    2780         [ #  # ]:          0 :         if (enabled == sdata->u.mgd.powersave &&
    2781         [ #  # ]:          0 :             timeout == local->dynamic_ps_forced_timeout)
    2782                 :            :                 return 0;
    2783                 :            : 
    2784                 :          0 :         sdata->u.mgd.powersave = enabled;
    2785                 :          0 :         local->dynamic_ps_forced_timeout = timeout;
    2786                 :            : 
    2787                 :            :         /* no change, but if automatic follow powersave */
    2788                 :          0 :         sdata_lock(sdata);
    2789                 :          0 :         __ieee80211_request_smps_mgd(sdata, sdata->u.mgd.req_smps);
    2790                 :          0 :         sdata_unlock(sdata);
    2791                 :            : 
    2792         [ #  # ]:          0 :         if (ieee80211_hw_check(&local->hw, SUPPORTS_DYNAMIC_PS))
    2793                 :          0 :                 ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS);
    2794                 :            : 
    2795                 :          0 :         ieee80211_recalc_ps(local);
    2796                 :          0 :         ieee80211_recalc_ps_vif(sdata);
    2797                 :          0 :         ieee80211_check_fast_rx_iface(sdata);
    2798                 :            : 
    2799                 :          0 :         return 0;
    2800                 :            : }
    2801                 :            : 
    2802                 :          0 : static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy,
    2803                 :            :                                          struct net_device *dev,
    2804                 :            :                                          s32 rssi_thold, u32 rssi_hyst)
    2805                 :            : {
    2806         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    2807                 :          0 :         struct ieee80211_vif *vif = &sdata->vif;
    2808                 :          0 :         struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
    2809                 :            : 
    2810         [ #  # ]:          0 :         if (rssi_thold == bss_conf->cqm_rssi_thold &&
    2811         [ #  # ]:          0 :             rssi_hyst == bss_conf->cqm_rssi_hyst)
    2812                 :            :                 return 0;
    2813                 :            : 
    2814         [ #  # ]:          0 :         if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER &&
    2815                 :            :             !(sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI))
    2816                 :            :                 return -EOPNOTSUPP;
    2817                 :            : 
    2818                 :          0 :         bss_conf->cqm_rssi_thold = rssi_thold;
    2819                 :          0 :         bss_conf->cqm_rssi_hyst = rssi_hyst;
    2820                 :          0 :         bss_conf->cqm_rssi_low = 0;
    2821                 :          0 :         bss_conf->cqm_rssi_high = 0;
    2822                 :          0 :         sdata->u.mgd.last_cqm_event_signal = 0;
    2823                 :            : 
    2824                 :            :         /* tell the driver upon association, unless already associated */
    2825         [ #  # ]:          0 :         if (sdata->u.mgd.associated &&
    2826         [ #  # ]:          0 :             sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)
    2827                 :          0 :                 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
    2828                 :            : 
    2829                 :            :         return 0;
    2830                 :            : }
    2831                 :            : 
    2832                 :          0 : static int ieee80211_set_cqm_rssi_range_config(struct wiphy *wiphy,
    2833                 :            :                                                struct net_device *dev,
    2834                 :            :                                                s32 rssi_low, s32 rssi_high)
    2835                 :            : {
    2836         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    2837                 :          0 :         struct ieee80211_vif *vif = &sdata->vif;
    2838                 :          0 :         struct ieee80211_bss_conf *bss_conf = &vif->bss_conf;
    2839                 :            : 
    2840         [ #  # ]:          0 :         if (sdata->vif.driver_flags & IEEE80211_VIF_BEACON_FILTER)
    2841                 :            :                 return -EOPNOTSUPP;
    2842                 :            : 
    2843                 :          0 :         bss_conf->cqm_rssi_low = rssi_low;
    2844                 :          0 :         bss_conf->cqm_rssi_high = rssi_high;
    2845                 :          0 :         bss_conf->cqm_rssi_thold = 0;
    2846                 :          0 :         bss_conf->cqm_rssi_hyst = 0;
    2847                 :          0 :         sdata->u.mgd.last_cqm_event_signal = 0;
    2848                 :            : 
    2849                 :            :         /* tell the driver upon association, unless already associated */
    2850         [ #  # ]:          0 :         if (sdata->u.mgd.associated &&
    2851         [ #  # ]:          0 :             sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)
    2852                 :          0 :                 ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_CQM);
    2853                 :            : 
    2854                 :            :         return 0;
    2855                 :            : }
    2856                 :            : 
    2857                 :          0 : static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
    2858                 :            :                                       struct net_device *dev,
    2859                 :            :                                       const u8 *addr,
    2860                 :            :                                       const struct cfg80211_bitrate_mask *mask)
    2861                 :            : {
    2862                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    2863                 :          0 :         struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr);
    2864                 :          0 :         int i, ret;
    2865                 :            : 
    2866         [ #  # ]:          0 :         if (!ieee80211_sdata_running(sdata))
    2867                 :            :                 return -ENETDOWN;
    2868                 :            : 
    2869                 :            :         /*
    2870                 :            :          * If active validate the setting and reject it if it doesn't leave
    2871                 :            :          * at least one basic rate usable, since we really have to be able
    2872                 :            :          * to send something, and if we're an AP we have to be able to do
    2873                 :            :          * so at a basic rate so that all clients can receive it.
    2874                 :            :          */
    2875         [ #  # ]:          0 :         if (rcu_access_pointer(sdata->vif.chanctx_conf) &&
    2876         [ #  # ]:          0 :             sdata->vif.bss_conf.chandef.chan) {
    2877                 :          0 :                 u32 basic_rates = sdata->vif.bss_conf.basic_rates;
    2878                 :          0 :                 enum nl80211_band band = sdata->vif.bss_conf.chandef.chan->band;
    2879                 :            : 
    2880         [ #  # ]:          0 :                 if (!(mask->control[band].legacy & basic_rates))
    2881                 :            :                         return -EINVAL;
    2882                 :            :         }
    2883                 :            : 
    2884         [ #  # ]:          0 :         if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) {
    2885                 :          0 :                 ret = drv_set_bitrate_mask(local, sdata, mask);
    2886         [ #  # ]:          0 :                 if (ret)
    2887                 :            :                         return ret;
    2888                 :            :         }
    2889                 :            : 
    2890         [ #  # ]:          0 :         for (i = 0; i < NUM_NL80211_BANDS; i++) {
    2891                 :          0 :                 struct ieee80211_supported_band *sband = wiphy->bands[i];
    2892                 :          0 :                 int j;
    2893                 :            : 
    2894                 :          0 :                 sdata->rc_rateidx_mask[i] = mask->control[i].legacy;
    2895                 :          0 :                 memcpy(sdata->rc_rateidx_mcs_mask[i], mask->control[i].ht_mcs,
    2896                 :            :                        sizeof(mask->control[i].ht_mcs));
    2897                 :          0 :                 memcpy(sdata->rc_rateidx_vht_mcs_mask[i],
    2898                 :          0 :                        mask->control[i].vht_mcs,
    2899                 :            :                        sizeof(mask->control[i].vht_mcs));
    2900                 :            : 
    2901                 :          0 :                 sdata->rc_has_mcs_mask[i] = false;
    2902                 :          0 :                 sdata->rc_has_vht_mcs_mask[i] = false;
    2903         [ #  # ]:          0 :                 if (!sband)
    2904                 :          0 :                         continue;
    2905                 :            : 
    2906                 :          0 :                 for (j = 0; j < IEEE80211_HT_MCS_MASK_LEN; j++) {
    2907                 :          0 :                         if (~sdata->rc_rateidx_mcs_mask[i][j]) {
    2908                 :          0 :                                 sdata->rc_has_mcs_mask[i] = true;
    2909                 :          0 :                                 break;
    2910                 :            :                         }
    2911                 :            :                 }
    2912                 :            : 
    2913                 :          0 :                 for (j = 0; j < NL80211_VHT_NSS_MAX; j++) {
    2914                 :          0 :                         if (~sdata->rc_rateidx_vht_mcs_mask[i][j]) {
    2915                 :          0 :                                 sdata->rc_has_vht_mcs_mask[i] = true;
    2916                 :          0 :                                 break;
    2917                 :            :                         }
    2918                 :            :                 }
    2919                 :            :         }
    2920                 :            : 
    2921                 :            :         return 0;
    2922                 :            : }
    2923                 :            : 
    2924                 :          0 : static int ieee80211_start_radar_detection(struct wiphy *wiphy,
    2925                 :            :                                            struct net_device *dev,
    2926                 :            :                                            struct cfg80211_chan_def *chandef,
    2927                 :            :                                            u32 cac_time_ms)
    2928                 :            : {
    2929                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    2930                 :          0 :         struct ieee80211_local *local = sdata->local;
    2931                 :          0 :         int err;
    2932                 :            : 
    2933                 :          0 :         mutex_lock(&local->mtx);
    2934   [ #  #  #  # ]:          0 :         if (!list_empty(&local->roc_list) || local->scanning) {
    2935                 :          0 :                 err = -EBUSY;
    2936                 :          0 :                 goto out_unlock;
    2937                 :            :         }
    2938                 :            : 
    2939                 :            :         /* whatever, but channel contexts should not complain about that one */
    2940                 :          0 :         sdata->smps_mode = IEEE80211_SMPS_OFF;
    2941                 :          0 :         sdata->needed_rx_chains = local->rx_chains;
    2942                 :            : 
    2943                 :          0 :         err = ieee80211_vif_use_channel(sdata, chandef,
    2944                 :            :                                         IEEE80211_CHANCTX_SHARED);
    2945         [ #  # ]:          0 :         if (err)
    2946                 :          0 :                 goto out_unlock;
    2947                 :            : 
    2948         [ #  # ]:          0 :         ieee80211_queue_delayed_work(&sdata->local->hw,
    2949                 :            :                                      &sdata->dfs_cac_timer_work,
    2950                 :            :                                      msecs_to_jiffies(cac_time_ms));
    2951                 :            : 
    2952                 :          0 :  out_unlock:
    2953                 :          0 :         mutex_unlock(&local->mtx);
    2954                 :          0 :         return err;
    2955                 :            : }
    2956                 :            : 
    2957                 :          0 : static void ieee80211_end_cac(struct wiphy *wiphy,
    2958                 :            :                               struct net_device *dev)
    2959                 :            : {
    2960                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    2961                 :          0 :         struct ieee80211_local *local = sdata->local;
    2962                 :            : 
    2963                 :          0 :         mutex_lock(&local->mtx);
    2964         [ #  # ]:          0 :         list_for_each_entry(sdata, &local->interfaces, list) {
    2965                 :            :                 /* it might be waiting for the local->mtx, but then
    2966                 :            :                  * by the time it gets it, sdata->wdev.cac_started
    2967                 :            :                  * will no longer be true
    2968                 :            :                  */
    2969                 :          0 :                 cancel_delayed_work(&sdata->dfs_cac_timer_work);
    2970                 :            : 
    2971         [ #  # ]:          0 :                 if (sdata->wdev.cac_started) {
    2972                 :          0 :                         ieee80211_vif_release_channel(sdata);
    2973                 :          0 :                         sdata->wdev.cac_started = false;
    2974                 :            :                 }
    2975                 :            :         }
    2976                 :          0 :         mutex_unlock(&local->mtx);
    2977                 :          0 : }
    2978                 :            : 
    2979                 :            : static struct cfg80211_beacon_data *
    2980                 :          0 : cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon)
    2981                 :            : {
    2982                 :          0 :         struct cfg80211_beacon_data *new_beacon;
    2983                 :          0 :         u8 *pos;
    2984                 :          0 :         int len;
    2985                 :            : 
    2986                 :          0 :         len = beacon->head_len + beacon->tail_len + beacon->beacon_ies_len +
    2987                 :          0 :               beacon->proberesp_ies_len + beacon->assocresp_ies_len +
    2988                 :          0 :               beacon->probe_resp_len + beacon->lci_len + beacon->civicloc_len;
    2989                 :            : 
    2990                 :          0 :         new_beacon = kzalloc(sizeof(*new_beacon) + len, GFP_KERNEL);
    2991         [ #  # ]:          0 :         if (!new_beacon)
    2992                 :            :                 return NULL;
    2993                 :            : 
    2994                 :          0 :         pos = (u8 *)(new_beacon + 1);
    2995         [ #  # ]:          0 :         if (beacon->head_len) {
    2996                 :          0 :                 new_beacon->head_len = beacon->head_len;
    2997                 :          0 :                 new_beacon->head = pos;
    2998                 :          0 :                 memcpy(pos, beacon->head, beacon->head_len);
    2999                 :          0 :                 pos += beacon->head_len;
    3000                 :            :         }
    3001         [ #  # ]:          0 :         if (beacon->tail_len) {
    3002                 :          0 :                 new_beacon->tail_len = beacon->tail_len;
    3003                 :          0 :                 new_beacon->tail = pos;
    3004                 :          0 :                 memcpy(pos, beacon->tail, beacon->tail_len);
    3005                 :          0 :                 pos += beacon->tail_len;
    3006                 :            :         }
    3007         [ #  # ]:          0 :         if (beacon->beacon_ies_len) {
    3008                 :          0 :                 new_beacon->beacon_ies_len = beacon->beacon_ies_len;
    3009                 :          0 :                 new_beacon->beacon_ies = pos;
    3010                 :          0 :                 memcpy(pos, beacon->beacon_ies, beacon->beacon_ies_len);
    3011                 :          0 :                 pos += beacon->beacon_ies_len;
    3012                 :            :         }
    3013         [ #  # ]:          0 :         if (beacon->proberesp_ies_len) {
    3014                 :          0 :                 new_beacon->proberesp_ies_len = beacon->proberesp_ies_len;
    3015                 :          0 :                 new_beacon->proberesp_ies = pos;
    3016                 :          0 :                 memcpy(pos, beacon->proberesp_ies, beacon->proberesp_ies_len);
    3017                 :          0 :                 pos += beacon->proberesp_ies_len;
    3018                 :            :         }
    3019         [ #  # ]:          0 :         if (beacon->assocresp_ies_len) {
    3020                 :          0 :                 new_beacon->assocresp_ies_len = beacon->assocresp_ies_len;
    3021                 :          0 :                 new_beacon->assocresp_ies = pos;
    3022                 :          0 :                 memcpy(pos, beacon->assocresp_ies, beacon->assocresp_ies_len);
    3023                 :          0 :                 pos += beacon->assocresp_ies_len;
    3024                 :            :         }
    3025         [ #  # ]:          0 :         if (beacon->probe_resp_len) {
    3026                 :          0 :                 new_beacon->probe_resp_len = beacon->probe_resp_len;
    3027                 :          0 :                 new_beacon->probe_resp = pos;
    3028                 :          0 :                 memcpy(pos, beacon->probe_resp, beacon->probe_resp_len);
    3029                 :          0 :                 pos += beacon->probe_resp_len;
    3030                 :            :         }
    3031                 :            : 
    3032                 :            :         /* might copy -1, meaning no changes requested */
    3033                 :          0 :         new_beacon->ftm_responder = beacon->ftm_responder;
    3034         [ #  # ]:          0 :         if (beacon->lci) {
    3035                 :          0 :                 new_beacon->lci_len = beacon->lci_len;
    3036                 :          0 :                 new_beacon->lci = pos;
    3037                 :          0 :                 memcpy(pos, beacon->lci, beacon->lci_len);
    3038                 :          0 :                 pos += beacon->lci_len;
    3039                 :            :         }
    3040         [ #  # ]:          0 :         if (beacon->civicloc) {
    3041                 :          0 :                 new_beacon->civicloc_len = beacon->civicloc_len;
    3042                 :          0 :                 new_beacon->civicloc = pos;
    3043                 :          0 :                 memcpy(pos, beacon->civicloc, beacon->civicloc_len);
    3044                 :          0 :                 pos += beacon->civicloc_len;
    3045                 :            :         }
    3046                 :            : 
    3047                 :            :         return new_beacon;
    3048                 :            : }
    3049                 :            : 
    3050                 :          0 : void ieee80211_csa_finish(struct ieee80211_vif *vif)
    3051                 :            : {
    3052                 :          0 :         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
    3053                 :            : 
    3054                 :          0 :         ieee80211_queue_work(&sdata->local->hw,
    3055                 :            :                              &sdata->csa_finalize_work);
    3056                 :          0 : }
    3057                 :            : EXPORT_SYMBOL(ieee80211_csa_finish);
    3058                 :            : 
    3059                 :          0 : static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
    3060                 :            :                                           u32 *changed)
    3061                 :            : {
    3062                 :          0 :         int err;
    3063                 :            : 
    3064      [ #  #  # ]:          0 :         switch (sdata->vif.type) {
    3065                 :          0 :         case NL80211_IFTYPE_AP:
    3066                 :          0 :                 err = ieee80211_assign_beacon(sdata, sdata->u.ap.next_beacon,
    3067                 :            :                                               NULL);
    3068                 :          0 :                 kfree(sdata->u.ap.next_beacon);
    3069                 :          0 :                 sdata->u.ap.next_beacon = NULL;
    3070                 :            : 
    3071         [ #  # ]:          0 :                 if (err < 0)
    3072                 :            :                         return err;
    3073                 :          0 :                 *changed |= err;
    3074                 :          0 :                 break;
    3075                 :          0 :         case NL80211_IFTYPE_ADHOC:
    3076                 :          0 :                 err = ieee80211_ibss_finish_csa(sdata);
    3077         [ #  # ]:          0 :                 if (err < 0)
    3078                 :            :                         return err;
    3079                 :          0 :                 *changed |= err;
    3080                 :          0 :                 break;
    3081                 :            : #ifdef CONFIG_MAC80211_MESH
    3082                 :            :         case NL80211_IFTYPE_MESH_POINT:
    3083                 :            :                 err = ieee80211_mesh_finish_csa(sdata);
    3084                 :            :                 if (err < 0)
    3085                 :            :                         return err;
    3086                 :            :                 *changed |= err;
    3087                 :            :                 break;
    3088                 :            : #endif
    3089                 :            :         default:
    3090                 :          0 :                 WARN_ON(1);
    3091                 :          0 :                 return -EINVAL;
    3092                 :            :         }
    3093                 :            : 
    3094                 :            :         return 0;
    3095                 :            : }
    3096                 :            : 
    3097                 :          0 : static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
    3098                 :            : {
    3099                 :          0 :         struct ieee80211_local *local = sdata->local;
    3100                 :          0 :         u32 changed = 0;
    3101                 :          0 :         int err;
    3102                 :            : 
    3103         [ #  # ]:          0 :         sdata_assert_lock(sdata);
    3104                 :          0 :         lockdep_assert_held(&local->mtx);
    3105                 :          0 :         lockdep_assert_held(&local->chanctx_mtx);
    3106                 :            : 
    3107                 :            :         /*
    3108                 :            :          * using reservation isn't immediate as it may be deferred until later
    3109                 :            :          * with multi-vif. once reservation is complete it will re-schedule the
    3110                 :            :          * work with no reserved_chanctx so verify chandef to check if it
    3111                 :            :          * completed successfully
    3112                 :            :          */
    3113                 :            : 
    3114         [ #  # ]:          0 :         if (sdata->reserved_chanctx) {
    3115                 :            :                 /*
    3116                 :            :                  * with multi-vif csa driver may call ieee80211_csa_finish()
    3117                 :            :                  * many times while waiting for other interfaces to use their
    3118                 :            :                  * reservations
    3119                 :            :                  */
    3120         [ #  # ]:          0 :                 if (sdata->reserved_ready)
    3121                 :            :                         return 0;
    3122                 :            : 
    3123                 :          0 :                 return ieee80211_vif_use_reserved_context(sdata);
    3124                 :            :         }
    3125                 :            : 
    3126   [ #  #  #  # ]:          0 :         if (!cfg80211_chandef_identical(&sdata->vif.bss_conf.chandef,
    3127                 :            :                                         &sdata->csa_chandef))
    3128                 :            :                 return -EINVAL;
    3129                 :            : 
    3130                 :          0 :         sdata->vif.csa_active = false;
    3131                 :            : 
    3132                 :          0 :         err = ieee80211_set_after_csa_beacon(sdata, &changed);
    3133         [ #  # ]:          0 :         if (err)
    3134                 :            :                 return err;
    3135                 :            : 
    3136                 :          0 :         ieee80211_bss_info_change_notify(sdata, changed);
    3137                 :            : 
    3138         [ #  # ]:          0 :         if (sdata->csa_block_tx) {
    3139                 :          0 :                 ieee80211_wake_vif_queues(local, sdata,
    3140                 :            :                                           IEEE80211_QUEUE_STOP_REASON_CSA);
    3141                 :          0 :                 sdata->csa_block_tx = false;
    3142                 :            :         }
    3143                 :            : 
    3144                 :          0 :         err = drv_post_channel_switch(sdata);
    3145         [ #  # ]:          0 :         if (err)
    3146                 :            :                 return err;
    3147                 :            : 
    3148                 :          0 :         cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
    3149                 :            : 
    3150                 :          0 :         return 0;
    3151                 :            : }
    3152                 :            : 
    3153                 :          0 : static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
    3154                 :            : {
    3155         [ #  # ]:          0 :         if (__ieee80211_csa_finalize(sdata)) {
    3156                 :          0 :                 sdata_info(sdata, "failed to finalize CSA, disconnecting\n");
    3157                 :          0 :                 cfg80211_stop_iface(sdata->local->hw.wiphy, &sdata->wdev,
    3158                 :            :                                     GFP_KERNEL);
    3159                 :            :         }
    3160                 :          0 : }
    3161                 :            : 
    3162                 :          0 : void ieee80211_csa_finalize_work(struct work_struct *work)
    3163                 :            : {
    3164                 :          0 :         struct ieee80211_sub_if_data *sdata =
    3165                 :          0 :                 container_of(work, struct ieee80211_sub_if_data,
    3166                 :            :                              csa_finalize_work);
    3167                 :          0 :         struct ieee80211_local *local = sdata->local;
    3168                 :            : 
    3169                 :          0 :         sdata_lock(sdata);
    3170                 :          0 :         mutex_lock(&local->mtx);
    3171                 :          0 :         mutex_lock(&local->chanctx_mtx);
    3172                 :            : 
    3173                 :            :         /* AP might have been stopped while waiting for the lock. */
    3174         [ #  # ]:          0 :         if (!sdata->vif.csa_active)
    3175                 :          0 :                 goto unlock;
    3176                 :            : 
    3177         [ #  # ]:          0 :         if (!ieee80211_sdata_running(sdata))
    3178                 :          0 :                 goto unlock;
    3179                 :            : 
    3180                 :          0 :         ieee80211_csa_finalize(sdata);
    3181                 :            : 
    3182                 :          0 : unlock:
    3183                 :          0 :         mutex_unlock(&local->chanctx_mtx);
    3184                 :          0 :         mutex_unlock(&local->mtx);
    3185                 :          0 :         sdata_unlock(sdata);
    3186                 :          0 : }
    3187                 :            : 
    3188                 :          0 : static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
    3189                 :            :                                     struct cfg80211_csa_settings *params,
    3190                 :            :                                     u32 *changed)
    3191                 :            : {
    3192                 :          0 :         struct ieee80211_csa_settings csa = {};
    3193                 :          0 :         int err;
    3194                 :            : 
    3195      [ #  #  # ]:          0 :         switch (sdata->vif.type) {
    3196                 :          0 :         case NL80211_IFTYPE_AP:
    3197                 :          0 :                 sdata->u.ap.next_beacon =
    3198                 :          0 :                         cfg80211_beacon_dup(&params->beacon_after);
    3199         [ #  # ]:          0 :                 if (!sdata->u.ap.next_beacon)
    3200                 :            :                         return -ENOMEM;
    3201                 :            : 
    3202                 :            :                 /*
    3203                 :            :                  * With a count of 0, we don't have to wait for any
    3204                 :            :                  * TBTT before switching, so complete the CSA
    3205                 :            :                  * immediately.  In theory, with a count == 1 we
    3206                 :            :                  * should delay the switch until just before the next
    3207                 :            :                  * TBTT, but that would complicate things so we switch
    3208                 :            :                  * immediately too.  If we would delay the switch
    3209                 :            :                  * until the next TBTT, we would have to set the probe
    3210                 :            :                  * response here.
    3211                 :            :                  *
    3212                 :            :                  * TODO: A channel switch with count <= 1 without
    3213                 :            :                  * sending a CSA action frame is kind of useless,
    3214                 :            :                  * because the clients won't know we're changing
    3215                 :            :                  * channels.  The action frame must be implemented
    3216                 :            :                  * either here or in the userspace.
    3217                 :            :                  */
    3218         [ #  # ]:          0 :                 if (params->count <= 1)
    3219                 :            :                         break;
    3220                 :            : 
    3221         [ #  # ]:          0 :                 if ((params->n_counter_offsets_beacon >
    3222                 :          0 :                      IEEE80211_MAX_CSA_COUNTERS_NUM) ||
    3223         [ #  # ]:          0 :                     (params->n_counter_offsets_presp >
    3224                 :            :                      IEEE80211_MAX_CSA_COUNTERS_NUM))
    3225                 :            :                         return -EINVAL;
    3226                 :            : 
    3227                 :          0 :                 csa.counter_offsets_beacon = params->counter_offsets_beacon;
    3228                 :          0 :                 csa.counter_offsets_presp = params->counter_offsets_presp;
    3229                 :          0 :                 csa.n_counter_offsets_beacon = params->n_counter_offsets_beacon;
    3230                 :          0 :                 csa.n_counter_offsets_presp = params->n_counter_offsets_presp;
    3231                 :          0 :                 csa.count = params->count;
    3232                 :            : 
    3233                 :          0 :                 err = ieee80211_assign_beacon(sdata, &params->beacon_csa, &csa);
    3234         [ #  # ]:          0 :                 if (err < 0) {
    3235                 :          0 :                         kfree(sdata->u.ap.next_beacon);
    3236                 :          0 :                         return err;
    3237                 :            :                 }
    3238                 :          0 :                 *changed |= err;
    3239                 :            : 
    3240                 :          0 :                 break;
    3241                 :          0 :         case NL80211_IFTYPE_ADHOC:
    3242         [ #  # ]:          0 :                 if (!sdata->vif.bss_conf.ibss_joined)
    3243                 :            :                         return -EINVAL;
    3244                 :            : 
    3245         [ #  # ]:          0 :                 if (params->chandef.width != sdata->u.ibss.chandef.width)
    3246                 :            :                         return -EINVAL;
    3247                 :            : 
    3248      [ #  #  # ]:          0 :                 switch (params->chandef.width) {
    3249                 :          0 :                 case NL80211_CHAN_WIDTH_40:
    3250         [ #  # ]:          0 :                         if (cfg80211_get_chandef_type(&params->chandef) !=
    3251                 :          0 :                             cfg80211_get_chandef_type(&sdata->u.ibss.chandef))
    3252                 :            :                                 return -EINVAL;
    3253                 :            :                 case NL80211_CHAN_WIDTH_5:
    3254                 :            :                 case NL80211_CHAN_WIDTH_10:
    3255                 :            :                 case NL80211_CHAN_WIDTH_20_NOHT:
    3256                 :            :                 case NL80211_CHAN_WIDTH_20:
    3257                 :          0 :                         break;
    3258                 :            :                 default:
    3259                 :            :                         return -EINVAL;
    3260                 :            :                 }
    3261                 :            : 
    3262                 :            :                 /* changes into another band are not supported */
    3263                 :          0 :                 if (sdata->u.ibss.chandef.chan->band !=
    3264         [ #  # ]:          0 :                     params->chandef.chan->band)
    3265                 :            :                         return -EINVAL;
    3266                 :            : 
    3267                 :            :                 /* see comments in the NL80211_IFTYPE_AP block */
    3268         [ #  # ]:          0 :                 if (params->count > 1) {
    3269                 :          0 :                         err = ieee80211_ibss_csa_beacon(sdata, params);
    3270         [ #  # ]:          0 :                         if (err < 0)
    3271                 :            :                                 return err;
    3272                 :          0 :                         *changed |= err;
    3273                 :            :                 }
    3274                 :            : 
    3275                 :          0 :                 ieee80211_send_action_csa(sdata, params);
    3276                 :            : 
    3277                 :          0 :                 break;
    3278                 :            : #ifdef CONFIG_MAC80211_MESH
    3279                 :            :         case NL80211_IFTYPE_MESH_POINT: {
    3280                 :            :                 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
    3281                 :            : 
    3282                 :            :                 if (params->chandef.width != sdata->vif.bss_conf.chandef.width)
    3283                 :            :                         return -EINVAL;
    3284                 :            : 
    3285                 :            :                 /* changes into another band are not supported */
    3286                 :            :                 if (sdata->vif.bss_conf.chandef.chan->band !=
    3287                 :            :                     params->chandef.chan->band)
    3288                 :            :                         return -EINVAL;
    3289                 :            : 
    3290                 :            :                 if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_NONE) {
    3291                 :            :                         ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_INIT;
    3292                 :            :                         if (!ifmsh->pre_value)
    3293                 :            :                                 ifmsh->pre_value = 1;
    3294                 :            :                         else
    3295                 :            :                                 ifmsh->pre_value++;
    3296                 :            :                 }
    3297                 :            : 
    3298                 :            :                 /* see comments in the NL80211_IFTYPE_AP block */
    3299                 :            :                 if (params->count > 1) {
    3300                 :            :                         err = ieee80211_mesh_csa_beacon(sdata, params);
    3301                 :            :                         if (err < 0) {
    3302                 :            :                                 ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
    3303                 :            :                                 return err;
    3304                 :            :                         }
    3305                 :            :                         *changed |= err;
    3306                 :            :                 }
    3307                 :            : 
    3308                 :            :                 if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT)
    3309                 :            :                         ieee80211_send_action_csa(sdata, params);
    3310                 :            : 
    3311                 :            :                 break;
    3312                 :            :                 }
    3313                 :            : #endif
    3314                 :            :         default:
    3315                 :            :                 return -EOPNOTSUPP;
    3316                 :            :         }
    3317                 :            : 
    3318                 :          0 :         return 0;
    3319                 :            : }
    3320                 :            : 
    3321                 :            : static int
    3322                 :            : __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
    3323                 :            :                            struct cfg80211_csa_settings *params)
    3324                 :            : {
    3325                 :            :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    3326                 :            :         struct ieee80211_local *local = sdata->local;
    3327                 :            :         struct ieee80211_channel_switch ch_switch;
    3328                 :            :         struct ieee80211_chanctx_conf *conf;
    3329                 :            :         struct ieee80211_chanctx *chanctx;
    3330                 :            :         u32 changed = 0;
    3331                 :            :         int err;
    3332                 :            : 
    3333                 :            :         sdata_assert_lock(sdata);
    3334                 :            :         lockdep_assert_held(&local->mtx);
    3335                 :            : 
    3336                 :            :         if (!list_empty(&local->roc_list) || local->scanning)
    3337                 :            :                 return -EBUSY;
    3338                 :            : 
    3339                 :            :         if (sdata->wdev.cac_started)
    3340                 :            :                 return -EBUSY;
    3341                 :            : 
    3342                 :            :         if (cfg80211_chandef_identical(&params->chandef,
    3343                 :            :                                        &sdata->vif.bss_conf.chandef))
    3344                 :            :                 return -EINVAL;
    3345                 :            : 
    3346                 :            :         /* don't allow another channel switch if one is already active. */
    3347                 :            :         if (sdata->vif.csa_active)
    3348                 :            :                 return -EBUSY;
    3349                 :            : 
    3350                 :            :         mutex_lock(&local->chanctx_mtx);
    3351                 :            :         conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
    3352                 :            :                                          lockdep_is_held(&local->chanctx_mtx));
    3353                 :            :         if (!conf) {
    3354                 :            :                 err = -EBUSY;
    3355                 :            :                 goto out;
    3356                 :            :         }
    3357                 :            : 
    3358                 :            :         chanctx = container_of(conf, struct ieee80211_chanctx, conf);
    3359                 :            : 
    3360                 :            :         ch_switch.timestamp = 0;
    3361                 :            :         ch_switch.device_timestamp = 0;
    3362                 :            :         ch_switch.block_tx = params->block_tx;
    3363                 :            :         ch_switch.chandef = params->chandef;
    3364                 :            :         ch_switch.count = params->count;
    3365                 :            : 
    3366                 :            :         err = drv_pre_channel_switch(sdata, &ch_switch);
    3367                 :            :         if (err)
    3368                 :            :                 goto out;
    3369                 :            : 
    3370                 :            :         err = ieee80211_vif_reserve_chanctx(sdata, &params->chandef,
    3371                 :            :                                             chanctx->mode,
    3372                 :            :                                             params->radar_required);
    3373                 :            :         if (err)
    3374                 :            :                 goto out;
    3375                 :            : 
    3376                 :            :         /* if reservation is invalid then this will fail */
    3377                 :            :         err = ieee80211_check_combinations(sdata, NULL, chanctx->mode, 0);
    3378                 :            :         if (err) {
    3379                 :            :                 ieee80211_vif_unreserve_chanctx(sdata);
    3380                 :            :                 goto out;
    3381                 :            :         }
    3382                 :            : 
    3383                 :            :         err = ieee80211_set_csa_beacon(sdata, params, &changed);
    3384                 :            :         if (err) {
    3385                 :            :                 ieee80211_vif_unreserve_chanctx(sdata);
    3386                 :            :                 goto out;
    3387                 :            :         }
    3388                 :            : 
    3389                 :            :         sdata->csa_chandef = params->chandef;
    3390                 :            :         sdata->csa_block_tx = params->block_tx;
    3391                 :            :         sdata->vif.csa_active = true;
    3392                 :            : 
    3393                 :            :         if (sdata->csa_block_tx)
    3394                 :            :                 ieee80211_stop_vif_queues(local, sdata,
    3395                 :            :                                           IEEE80211_QUEUE_STOP_REASON_CSA);
    3396                 :            : 
    3397                 :            :         cfg80211_ch_switch_started_notify(sdata->dev, &sdata->csa_chandef,
    3398                 :            :                                           params->count);
    3399                 :            : 
    3400                 :            :         if (changed) {
    3401                 :            :                 ieee80211_bss_info_change_notify(sdata, changed);
    3402                 :            :                 drv_channel_switch_beacon(sdata, &params->chandef);
    3403                 :            :         } else {
    3404                 :            :                 /* if the beacon didn't change, we can finalize immediately */
    3405                 :            :                 ieee80211_csa_finalize(sdata);
    3406                 :            :         }
    3407                 :            : 
    3408                 :            : out:
    3409                 :            :         mutex_unlock(&local->chanctx_mtx);
    3410                 :            :         return err;
    3411                 :            : }
    3412                 :            : 
    3413                 :          0 : int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
    3414                 :            :                              struct cfg80211_csa_settings *params)
    3415                 :            : {
    3416                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    3417                 :          0 :         struct ieee80211_local *local = sdata->local;
    3418                 :          0 :         int err;
    3419                 :            : 
    3420                 :          0 :         mutex_lock(&local->mtx);
    3421                 :          0 :         err = __ieee80211_channel_switch(wiphy, dev, params);
    3422                 :          0 :         mutex_unlock(&local->mtx);
    3423                 :            : 
    3424                 :          0 :         return err;
    3425                 :            : }
    3426                 :            : 
    3427                 :          0 : u64 ieee80211_mgmt_tx_cookie(struct ieee80211_local *local)
    3428                 :            : {
    3429                 :          0 :         lockdep_assert_held(&local->mtx);
    3430                 :            : 
    3431                 :          0 :         local->roc_cookie_counter++;
    3432                 :            : 
    3433                 :            :         /* wow, you wrapped 64 bits ... more likely a bug */
    3434   [ #  #  #  #  :          0 :         if (WARN_ON(local->roc_cookie_counter == 0))
                   #  # ]
    3435                 :          0 :                 local->roc_cookie_counter++;
    3436                 :            : 
    3437                 :          0 :         return local->roc_cookie_counter;
    3438                 :            : }
    3439                 :            : 
    3440                 :          0 : int ieee80211_attach_ack_skb(struct ieee80211_local *local, struct sk_buff *skb,
    3441                 :            :                              u64 *cookie, gfp_t gfp)
    3442                 :            : {
    3443                 :          0 :         unsigned long spin_flags;
    3444                 :          0 :         struct sk_buff *ack_skb;
    3445                 :          0 :         int id;
    3446                 :            : 
    3447                 :          0 :         ack_skb = skb_copy(skb, gfp);
    3448         [ #  # ]:          0 :         if (!ack_skb)
    3449                 :            :                 return -ENOMEM;
    3450                 :            : 
    3451                 :          0 :         spin_lock_irqsave(&local->ack_status_lock, spin_flags);
    3452                 :          0 :         id = idr_alloc(&local->ack_status_frames, ack_skb,
    3453                 :            :                        1, 0x2000, GFP_ATOMIC);
    3454                 :          0 :         spin_unlock_irqrestore(&local->ack_status_lock, spin_flags);
    3455                 :            : 
    3456         [ #  # ]:          0 :         if (id < 0) {
    3457                 :          0 :                 kfree_skb(ack_skb);
    3458                 :          0 :                 return -ENOMEM;
    3459                 :            :         }
    3460                 :            : 
    3461         [ #  # ]:          0 :         IEEE80211_SKB_CB(skb)->ack_frame_id = id;
    3462                 :            : 
    3463         [ #  # ]:          0 :         *cookie = ieee80211_mgmt_tx_cookie(local);
    3464                 :          0 :         IEEE80211_SKB_CB(ack_skb)->ack.cookie = *cookie;
    3465                 :            : 
    3466                 :          0 :         return 0;
    3467                 :            : }
    3468                 :            : 
    3469                 :          0 : static void ieee80211_mgmt_frame_register(struct wiphy *wiphy,
    3470                 :            :                                           struct wireless_dev *wdev,
    3471                 :            :                                           u16 frame_type, bool reg)
    3472                 :            : {
    3473         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    3474         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
    3475                 :            : 
    3476         [ #  # ]:          0 :         switch (frame_type) {
    3477                 :          0 :         case IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ:
    3478         [ #  # ]:          0 :                 if (reg) {
    3479                 :          0 :                         local->probe_req_reg++;
    3480                 :          0 :                         sdata->vif.probe_req_reg++;
    3481                 :            :                 } else {
    3482         [ #  # ]:          0 :                         if (local->probe_req_reg)
    3483                 :          0 :                                 local->probe_req_reg--;
    3484                 :            : 
    3485         [ #  # ]:          0 :                         if (sdata->vif.probe_req_reg)
    3486                 :          0 :                                 sdata->vif.probe_req_reg--;
    3487                 :            :                 }
    3488                 :            : 
    3489         [ #  # ]:          0 :                 if (!local->open_count)
    3490                 :            :                         break;
    3491                 :            : 
    3492         [ #  # ]:          0 :                 if (sdata->vif.probe_req_reg == 1)
    3493                 :          0 :                         drv_config_iface_filter(local, sdata, FIF_PROBE_REQ,
    3494                 :            :                                                 FIF_PROBE_REQ);
    3495         [ #  # ]:          0 :                 else if (sdata->vif.probe_req_reg == 0)
    3496                 :          0 :                         drv_config_iface_filter(local, sdata, 0,
    3497                 :            :                                                 FIF_PROBE_REQ);
    3498                 :            : 
    3499                 :          0 :                 ieee80211_configure_filter(local);
    3500                 :          0 :                 break;
    3501                 :            :         default:
    3502                 :            :                 break;
    3503                 :            :         }
    3504                 :          0 : }
    3505                 :            : 
    3506                 :          0 : static int ieee80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant)
    3507                 :            : {
    3508         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    3509                 :            : 
    3510         [ #  # ]:          0 :         if (local->started)
    3511                 :            :                 return -EOPNOTSUPP;
    3512                 :            : 
    3513                 :          0 :         return drv_set_antenna(local, tx_ant, rx_ant);
    3514                 :            : }
    3515                 :            : 
    3516                 :          0 : static int ieee80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant)
    3517                 :            : {
    3518         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    3519                 :            : 
    3520                 :          0 :         return drv_get_antenna(local, tx_ant, rx_ant);
    3521                 :            : }
    3522                 :            : 
    3523                 :          0 : static int ieee80211_set_rekey_data(struct wiphy *wiphy,
    3524                 :            :                                     struct net_device *dev,
    3525                 :            :                                     struct cfg80211_gtk_rekey_data *data)
    3526                 :            : {
    3527         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    3528         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    3529                 :            : 
    3530         [ #  # ]:          0 :         if (!local->ops->set_rekey_data)
    3531                 :            :                 return -EOPNOTSUPP;
    3532                 :            : 
    3533                 :          0 :         drv_set_rekey_data(local, sdata, data);
    3534                 :            : 
    3535                 :          0 :         return 0;
    3536                 :            : }
    3537                 :            : 
    3538                 :          0 : static int ieee80211_probe_client(struct wiphy *wiphy, struct net_device *dev,
    3539                 :            :                                   const u8 *peer, u64 *cookie)
    3540                 :            : {
    3541                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    3542                 :          0 :         struct ieee80211_local *local = sdata->local;
    3543                 :          0 :         struct ieee80211_qos_hdr *nullfunc;
    3544                 :          0 :         struct sk_buff *skb;
    3545                 :          0 :         int size = sizeof(*nullfunc);
    3546                 :          0 :         __le16 fc;
    3547                 :          0 :         bool qos;
    3548                 :          0 :         struct ieee80211_tx_info *info;
    3549                 :          0 :         struct sta_info *sta;
    3550                 :          0 :         struct ieee80211_chanctx_conf *chanctx_conf;
    3551                 :          0 :         enum nl80211_band band;
    3552                 :          0 :         int ret;
    3553                 :            : 
    3554                 :            :         /* the lock is needed to assign the cookie later */
    3555                 :          0 :         mutex_lock(&local->mtx);
    3556                 :            : 
    3557                 :          0 :         rcu_read_lock();
    3558         [ #  # ]:          0 :         chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
    3559   [ #  #  #  # ]:          0 :         if (WARN_ON(!chanctx_conf)) {
    3560                 :          0 :                 ret = -EINVAL;
    3561                 :          0 :                 goto unlock;
    3562                 :            :         }
    3563                 :          0 :         band = chanctx_conf->def.chan->band;
    3564                 :          0 :         sta = sta_info_get_bss(sdata, peer);
    3565         [ #  # ]:          0 :         if (sta) {
    3566                 :          0 :                 qos = sta->sta.wme;
    3567                 :            :         } else {
    3568                 :          0 :                 ret = -ENOLINK;
    3569                 :          0 :                 goto unlock;
    3570                 :            :         }
    3571                 :            : 
    3572         [ #  # ]:          0 :         if (qos) {
    3573                 :            :                 fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
    3574                 :            :                                  IEEE80211_STYPE_QOS_NULLFUNC |
    3575                 :            :                                  IEEE80211_FCTL_FROMDS);
    3576                 :            :         } else {
    3577                 :          0 :                 size -= 2;
    3578                 :          0 :                 fc = cpu_to_le16(IEEE80211_FTYPE_DATA |
    3579                 :            :                                  IEEE80211_STYPE_NULLFUNC |
    3580                 :            :                                  IEEE80211_FCTL_FROMDS);
    3581                 :            :         }
    3582                 :            : 
    3583                 :          0 :         skb = dev_alloc_skb(local->hw.extra_tx_headroom + size);
    3584         [ #  # ]:          0 :         if (!skb) {
    3585                 :          0 :                 ret = -ENOMEM;
    3586                 :          0 :                 goto unlock;
    3587                 :            :         }
    3588                 :            : 
    3589                 :          0 :         skb->dev = dev;
    3590                 :            : 
    3591                 :          0 :         skb_reserve(skb, local->hw.extra_tx_headroom);
    3592                 :            : 
    3593                 :          0 :         nullfunc = skb_put(skb, size);
    3594                 :          0 :         nullfunc->frame_control = fc;
    3595                 :          0 :         nullfunc->duration_id = 0;
    3596                 :          0 :         memcpy(nullfunc->addr1, sta->sta.addr, ETH_ALEN);
    3597                 :          0 :         memcpy(nullfunc->addr2, sdata->vif.addr, ETH_ALEN);
    3598                 :          0 :         memcpy(nullfunc->addr3, sdata->vif.addr, ETH_ALEN);
    3599                 :          0 :         nullfunc->seq_ctrl = 0;
    3600                 :            : 
    3601         [ #  # ]:          0 :         info = IEEE80211_SKB_CB(skb);
    3602                 :            : 
    3603                 :          0 :         info->flags |= IEEE80211_TX_CTL_REQ_TX_STATUS |
    3604                 :            :                        IEEE80211_TX_INTFL_NL80211_FRAME_TX;
    3605                 :          0 :         info->band = band;
    3606                 :            : 
    3607         [ #  # ]:          0 :         skb_set_queue_mapping(skb, IEEE80211_AC_VO);
    3608                 :          0 :         skb->priority = 7;
    3609         [ #  # ]:          0 :         if (qos)
    3610                 :          0 :                 nullfunc->qos_ctrl = cpu_to_le16(7);
    3611                 :            : 
    3612                 :          0 :         ret = ieee80211_attach_ack_skb(local, skb, cookie, GFP_ATOMIC);
    3613         [ #  # ]:          0 :         if (ret) {
    3614                 :          0 :                 kfree_skb(skb);
    3615                 :          0 :                 goto unlock;
    3616                 :            :         }
    3617                 :            : 
    3618                 :          0 :         local_bh_disable();
    3619                 :          0 :         ieee80211_xmit(sdata, sta, skb, 0);
    3620                 :          0 :         local_bh_enable();
    3621                 :            : 
    3622                 :          0 :         ret = 0;
    3623                 :          0 : unlock:
    3624                 :          0 :         rcu_read_unlock();
    3625                 :          0 :         mutex_unlock(&local->mtx);
    3626                 :            : 
    3627                 :          0 :         return ret;
    3628                 :            : }
    3629                 :            : 
    3630                 :          0 : static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
    3631                 :            :                                      struct wireless_dev *wdev,
    3632                 :            :                                      struct cfg80211_chan_def *chandef)
    3633                 :            : {
    3634         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
    3635         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    3636                 :          0 :         struct ieee80211_chanctx_conf *chanctx_conf;
    3637                 :          0 :         int ret = -ENODATA;
    3638                 :            : 
    3639                 :          0 :         rcu_read_lock();
    3640         [ #  # ]:          0 :         chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
    3641         [ #  # ]:          0 :         if (chanctx_conf) {
    3642                 :          0 :                 *chandef = sdata->vif.bss_conf.chandef;
    3643                 :          0 :                 ret = 0;
    3644         [ #  # ]:          0 :         } else if (local->open_count > 0 &&
    3645         [ #  # ]:          0 :                    local->open_count == local->monitors &&
    3646         [ #  # ]:          0 :                    sdata->vif.type == NL80211_IFTYPE_MONITOR) {
    3647         [ #  # ]:          0 :                 if (local->use_chanctx)
    3648                 :          0 :                         *chandef = local->monitor_chandef;
    3649                 :            :                 else
    3650                 :          0 :                         *chandef = local->_oper_chandef;
    3651                 :            :                 ret = 0;
    3652                 :            :         }
    3653                 :          0 :         rcu_read_unlock();
    3654                 :            : 
    3655                 :          0 :         return ret;
    3656                 :            : }
    3657                 :            : 
    3658                 :            : #ifdef CONFIG_PM
    3659                 :          0 : static void ieee80211_set_wakeup(struct wiphy *wiphy, bool enabled)
    3660                 :            : {
    3661         [ #  # ]:          0 :         drv_set_wakeup(wiphy_priv(wiphy), enabled);
    3662                 :          0 : }
    3663                 :            : #endif
    3664                 :            : 
    3665                 :          0 : static int ieee80211_set_qos_map(struct wiphy *wiphy,
    3666                 :            :                                  struct net_device *dev,
    3667                 :            :                                  struct cfg80211_qos_map *qos_map)
    3668                 :            : {
    3669         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    3670                 :          0 :         struct mac80211_qos_map *new_qos_map, *old_qos_map;
    3671                 :            : 
    3672         [ #  # ]:          0 :         if (qos_map) {
    3673                 :          0 :                 new_qos_map = kzalloc(sizeof(*new_qos_map), GFP_KERNEL);
    3674         [ #  # ]:          0 :                 if (!new_qos_map)
    3675                 :            :                         return -ENOMEM;
    3676                 :          0 :                 memcpy(&new_qos_map->qos_map, qos_map, sizeof(*qos_map));
    3677                 :            :         } else {
    3678                 :            :                 /* A NULL qos_map was passed to disable QoS mapping */
    3679                 :            :                 new_qos_map = NULL;
    3680                 :            :         }
    3681                 :            : 
    3682                 :          0 :         old_qos_map = sdata_dereference(sdata->qos_map, sdata);
    3683         [ #  # ]:          0 :         rcu_assign_pointer(sdata->qos_map, new_qos_map);
    3684         [ #  # ]:          0 :         if (old_qos_map)
    3685                 :          0 :                 kfree_rcu(old_qos_map, rcu_head);
    3686                 :            : 
    3687                 :            :         return 0;
    3688                 :            : }
    3689                 :            : 
    3690                 :          0 : static int ieee80211_set_ap_chanwidth(struct wiphy *wiphy,
    3691                 :            :                                       struct net_device *dev,
    3692                 :            :                                       struct cfg80211_chan_def *chandef)
    3693                 :            : {
    3694                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    3695                 :          0 :         int ret;
    3696                 :          0 :         u32 changed = 0;
    3697                 :            : 
    3698                 :          0 :         ret = ieee80211_vif_change_bandwidth(sdata, chandef, &changed);
    3699         [ #  # ]:          0 :         if (ret == 0)
    3700                 :          0 :                 ieee80211_bss_info_change_notify(sdata, changed);
    3701                 :            : 
    3702                 :          0 :         return ret;
    3703                 :            : }
    3704                 :            : 
    3705                 :          0 : static int ieee80211_add_tx_ts(struct wiphy *wiphy, struct net_device *dev,
    3706                 :            :                                u8 tsid, const u8 *peer, u8 up,
    3707                 :            :                                u16 admitted_time)
    3708                 :            : {
    3709         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    3710                 :          0 :         struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
    3711                 :          0 :         int ac = ieee802_1d_to_ac[up];
    3712                 :            : 
    3713         [ #  # ]:          0 :         if (sdata->vif.type != NL80211_IFTYPE_STATION)
    3714                 :            :                 return -EOPNOTSUPP;
    3715                 :            : 
    3716         [ #  # ]:          0 :         if (!(sdata->wmm_acm & BIT(up)))
    3717                 :            :                 return -EINVAL;
    3718                 :            : 
    3719         [ #  # ]:          0 :         if (ifmgd->tx_tspec[ac].admitted_time)
    3720                 :            :                 return -EBUSY;
    3721                 :            : 
    3722         [ #  # ]:          0 :         if (admitted_time) {
    3723                 :          0 :                 ifmgd->tx_tspec[ac].admitted_time = 32 * admitted_time;
    3724                 :          0 :                 ifmgd->tx_tspec[ac].tsid = tsid;
    3725                 :          0 :                 ifmgd->tx_tspec[ac].up = up;
    3726                 :            :         }
    3727                 :            : 
    3728                 :            :         return 0;
    3729                 :            : }
    3730                 :            : 
    3731                 :          0 : static int ieee80211_del_tx_ts(struct wiphy *wiphy, struct net_device *dev,
    3732                 :            :                                u8 tsid, const u8 *peer)
    3733                 :            : {
    3734         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    3735                 :          0 :         struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
    3736         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    3737                 :          0 :         int ac;
    3738                 :            : 
    3739         [ #  # ]:          0 :         for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
    3740                 :          0 :                 struct ieee80211_sta_tx_tspec *tx_tspec = &ifmgd->tx_tspec[ac];
    3741                 :            : 
    3742                 :            :                 /* skip unused entries */
    3743         [ #  # ]:          0 :                 if (!tx_tspec->admitted_time)
    3744                 :          0 :                         continue;
    3745                 :            : 
    3746         [ #  # ]:          0 :                 if (tx_tspec->tsid != tsid)
    3747                 :          0 :                         continue;
    3748                 :            : 
    3749                 :            :                 /* due to this new packets will be reassigned to non-ACM ACs */
    3750                 :          0 :                 tx_tspec->up = -1;
    3751                 :            : 
    3752                 :            :                 /* Make sure that all packets have been sent to avoid to
    3753                 :            :                  * restore the QoS params on packets that are still on the
    3754                 :            :                  * queues.
    3755                 :            :                  */
    3756                 :          0 :                 synchronize_net();
    3757                 :          0 :                 ieee80211_flush_queues(local, sdata, false);
    3758                 :            : 
    3759                 :            :                 /* restore the normal QoS parameters
    3760                 :            :                  * (unconditionally to avoid races)
    3761                 :            :                  */
    3762                 :          0 :                 tx_tspec->action = TX_TSPEC_ACTION_STOP_DOWNGRADE;
    3763                 :          0 :                 tx_tspec->downgraded = false;
    3764                 :          0 :                 ieee80211_sta_handle_tspec_ac_params(sdata);
    3765                 :            : 
    3766                 :            :                 /* finally clear all the data */
    3767                 :          0 :                 memset(tx_tspec, 0, sizeof(*tx_tspec));
    3768                 :            : 
    3769                 :          0 :                 return 0;
    3770                 :            :         }
    3771                 :            : 
    3772                 :            :         return -ENOENT;
    3773                 :            : }
    3774                 :            : 
    3775                 :          0 : void ieee80211_nan_func_terminated(struct ieee80211_vif *vif,
    3776                 :            :                                    u8 inst_id,
    3777                 :            :                                    enum nl80211_nan_func_term_reason reason,
    3778                 :            :                                    gfp_t gfp)
    3779                 :            : {
    3780         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
    3781                 :          0 :         struct cfg80211_nan_func *func;
    3782                 :          0 :         u64 cookie;
    3783                 :            : 
    3784   [ #  #  #  # ]:          0 :         if (WARN_ON(vif->type != NL80211_IFTYPE_NAN))
    3785                 :            :                 return;
    3786                 :            : 
    3787                 :          0 :         spin_lock_bh(&sdata->u.nan.func_lock);
    3788                 :            : 
    3789                 :          0 :         func = idr_find(&sdata->u.nan.function_inst_ids, inst_id);
    3790   [ #  #  #  # ]:          0 :         if (WARN_ON(!func)) {
    3791                 :          0 :                 spin_unlock_bh(&sdata->u.nan.func_lock);
    3792                 :          0 :                 return;
    3793                 :            :         }
    3794                 :            : 
    3795                 :          0 :         cookie = func->cookie;
    3796                 :          0 :         idr_remove(&sdata->u.nan.function_inst_ids, inst_id);
    3797                 :            : 
    3798                 :          0 :         spin_unlock_bh(&sdata->u.nan.func_lock);
    3799                 :            : 
    3800                 :          0 :         cfg80211_free_nan_func(func);
    3801                 :            : 
    3802                 :          0 :         cfg80211_nan_func_terminated(ieee80211_vif_to_wdev(vif), inst_id,
    3803                 :            :                                      reason, cookie, gfp);
    3804                 :            : }
    3805                 :            : EXPORT_SYMBOL(ieee80211_nan_func_terminated);
    3806                 :            : 
    3807                 :          0 : void ieee80211_nan_func_match(struct ieee80211_vif *vif,
    3808                 :            :                               struct cfg80211_nan_match_params *match,
    3809                 :            :                               gfp_t gfp)
    3810                 :            : {
    3811         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
    3812                 :          0 :         struct cfg80211_nan_func *func;
    3813                 :            : 
    3814   [ #  #  #  # ]:          0 :         if (WARN_ON(vif->type != NL80211_IFTYPE_NAN))
    3815                 :            :                 return;
    3816                 :            : 
    3817                 :          0 :         spin_lock_bh(&sdata->u.nan.func_lock);
    3818                 :            : 
    3819                 :          0 :         func = idr_find(&sdata->u.nan.function_inst_ids,  match->inst_id);
    3820   [ #  #  #  # ]:          0 :         if (WARN_ON(!func)) {
    3821                 :          0 :                 spin_unlock_bh(&sdata->u.nan.func_lock);
    3822                 :          0 :                 return;
    3823                 :            :         }
    3824                 :          0 :         match->cookie = func->cookie;
    3825                 :            : 
    3826                 :          0 :         spin_unlock_bh(&sdata->u.nan.func_lock);
    3827                 :            : 
    3828                 :          0 :         cfg80211_nan_match(ieee80211_vif_to_wdev(vif), match, gfp);
    3829                 :            : }
    3830                 :            : EXPORT_SYMBOL(ieee80211_nan_func_match);
    3831                 :            : 
    3832                 :          0 : static int ieee80211_set_multicast_to_unicast(struct wiphy *wiphy,
    3833                 :            :                                               struct net_device *dev,
    3834                 :            :                                               const bool enabled)
    3835                 :            : {
    3836                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    3837                 :            : 
    3838                 :          0 :         sdata->u.ap.multicast_to_unicast = enabled;
    3839                 :            : 
    3840                 :          0 :         return 0;
    3841                 :            : }
    3842                 :            : 
    3843                 :          0 : void ieee80211_fill_txq_stats(struct cfg80211_txq_stats *txqstats,
    3844                 :            :                               struct txq_info *txqi)
    3845                 :            : {
    3846         [ #  # ]:          0 :         if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_BACKLOG_BYTES))) {
    3847                 :          0 :                 txqstats->filled |= BIT(NL80211_TXQ_STATS_BACKLOG_BYTES);
    3848                 :          0 :                 txqstats->backlog_bytes = txqi->tin.backlog_bytes;
    3849                 :            :         }
    3850                 :            : 
    3851         [ #  # ]:          0 :         if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_BACKLOG_PACKETS))) {
    3852                 :          0 :                 txqstats->filled |= BIT(NL80211_TXQ_STATS_BACKLOG_PACKETS);
    3853                 :          0 :                 txqstats->backlog_packets = txqi->tin.backlog_packets;
    3854                 :            :         }
    3855                 :            : 
    3856         [ #  # ]:          0 :         if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_FLOWS))) {
    3857                 :          0 :                 txqstats->filled |= BIT(NL80211_TXQ_STATS_FLOWS);
    3858                 :          0 :                 txqstats->flows = txqi->tin.flows;
    3859                 :            :         }
    3860                 :            : 
    3861         [ #  # ]:          0 :         if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_DROPS))) {
    3862                 :          0 :                 txqstats->filled |= BIT(NL80211_TXQ_STATS_DROPS);
    3863                 :          0 :                 txqstats->drops = txqi->cstats.drop_count;
    3864                 :            :         }
    3865                 :            : 
    3866         [ #  # ]:          0 :         if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_ECN_MARKS))) {
    3867                 :          0 :                 txqstats->filled |= BIT(NL80211_TXQ_STATS_ECN_MARKS);
    3868                 :          0 :                 txqstats->ecn_marks = txqi->cstats.ecn_mark;
    3869                 :            :         }
    3870                 :            : 
    3871         [ #  # ]:          0 :         if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_OVERLIMIT))) {
    3872                 :          0 :                 txqstats->filled |= BIT(NL80211_TXQ_STATS_OVERLIMIT);
    3873                 :          0 :                 txqstats->overlimit = txqi->tin.overlimit;
    3874                 :            :         }
    3875                 :            : 
    3876         [ #  # ]:          0 :         if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_COLLISIONS))) {
    3877                 :          0 :                 txqstats->filled |= BIT(NL80211_TXQ_STATS_COLLISIONS);
    3878                 :          0 :                 txqstats->collisions = txqi->tin.collisions;
    3879                 :            :         }
    3880                 :            : 
    3881         [ #  # ]:          0 :         if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_TX_BYTES))) {
    3882                 :          0 :                 txqstats->filled |= BIT(NL80211_TXQ_STATS_TX_BYTES);
    3883                 :          0 :                 txqstats->tx_bytes = txqi->tin.tx_bytes;
    3884                 :            :         }
    3885                 :            : 
    3886         [ #  # ]:          0 :         if (!(txqstats->filled & BIT(NL80211_TXQ_STATS_TX_PACKETS))) {
    3887                 :          0 :                 txqstats->filled |= BIT(NL80211_TXQ_STATS_TX_PACKETS);
    3888                 :          0 :                 txqstats->tx_packets = txqi->tin.tx_packets;
    3889                 :            :         }
    3890                 :          0 : }
    3891                 :            : 
    3892                 :          0 : static int ieee80211_get_txq_stats(struct wiphy *wiphy,
    3893                 :            :                                    struct wireless_dev *wdev,
    3894                 :            :                                    struct cfg80211_txq_stats *txqstats)
    3895                 :            : {
    3896         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    3897                 :          0 :         struct ieee80211_sub_if_data *sdata;
    3898                 :          0 :         int ret = 0;
    3899                 :            : 
    3900         [ #  # ]:          0 :         if (!local->ops->wake_tx_queue)
    3901                 :            :                 return 1;
    3902                 :            : 
    3903                 :          0 :         spin_lock_bh(&local->fq.lock);
    3904                 :          0 :         rcu_read_lock();
    3905                 :            : 
    3906         [ #  # ]:          0 :         if (wdev) {
    3907         [ #  # ]:          0 :                 sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
    3908         [ #  # ]:          0 :                 if (!sdata->vif.txq) {
    3909                 :          0 :                         ret = 1;
    3910                 :          0 :                         goto out;
    3911                 :            :                 }
    3912                 :          0 :                 ieee80211_fill_txq_stats(txqstats, to_txq_info(sdata->vif.txq));
    3913                 :            :         } else {
    3914                 :            :                 /* phy stats */
    3915                 :          0 :                 txqstats->filled |= BIT(NL80211_TXQ_STATS_BACKLOG_PACKETS) |
    3916                 :            :                                     BIT(NL80211_TXQ_STATS_BACKLOG_BYTES) |
    3917                 :            :                                     BIT(NL80211_TXQ_STATS_OVERLIMIT) |
    3918                 :            :                                     BIT(NL80211_TXQ_STATS_OVERMEMORY) |
    3919                 :            :                                     BIT(NL80211_TXQ_STATS_COLLISIONS) |
    3920                 :            :                                     BIT(NL80211_TXQ_STATS_MAX_FLOWS);
    3921                 :          0 :                 txqstats->backlog_packets = local->fq.backlog;
    3922                 :          0 :                 txqstats->backlog_bytes = local->fq.memory_usage;
    3923                 :          0 :                 txqstats->overlimit = local->fq.overlimit;
    3924                 :          0 :                 txqstats->overmemory = local->fq.overmemory;
    3925                 :          0 :                 txqstats->collisions = local->fq.collisions;
    3926                 :          0 :                 txqstats->max_flows = local->fq.flows_cnt;
    3927                 :            :         }
    3928                 :            : 
    3929                 :          0 : out:
    3930                 :          0 :         rcu_read_unlock();
    3931                 :          0 :         spin_unlock_bh(&local->fq.lock);
    3932                 :            : 
    3933                 :          0 :         return ret;
    3934                 :            : }
    3935                 :            : 
    3936                 :            : static int
    3937                 :          0 : ieee80211_get_ftm_responder_stats(struct wiphy *wiphy,
    3938                 :            :                                   struct net_device *dev,
    3939                 :            :                                   struct cfg80211_ftm_responder_stats *ftm_stats)
    3940                 :            : {
    3941         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    3942                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
    3943                 :            : 
    3944                 :          0 :         return drv_get_ftm_responder_stats(local, sdata, ftm_stats);
    3945                 :            : }
    3946                 :            : 
    3947                 :            : static int
    3948                 :          0 : ieee80211_start_pmsr(struct wiphy *wiphy, struct wireless_dev *dev,
    3949                 :            :                      struct cfg80211_pmsr_request *request)
    3950                 :            : {
    3951         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    3952                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(dev);
    3953                 :            : 
    3954                 :          0 :         return drv_start_pmsr(local, sdata, request);
    3955                 :            : }
    3956                 :            : 
    3957                 :            : static void
    3958                 :          0 : ieee80211_abort_pmsr(struct wiphy *wiphy, struct wireless_dev *dev,
    3959                 :            :                      struct cfg80211_pmsr_request *request)
    3960                 :            : {
    3961         [ #  # ]:          0 :         struct ieee80211_local *local = wiphy_priv(wiphy);
    3962                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(dev);
    3963                 :            : 
    3964                 :          0 :         return drv_abort_pmsr(local, sdata, request);
    3965                 :            : }
    3966                 :            : 
    3967                 :            : const struct cfg80211_ops mac80211_config_ops = {
    3968                 :            :         .add_virtual_intf = ieee80211_add_iface,
    3969                 :            :         .del_virtual_intf = ieee80211_del_iface,
    3970                 :            :         .change_virtual_intf = ieee80211_change_iface,
    3971                 :            :         .start_p2p_device = ieee80211_start_p2p_device,
    3972                 :            :         .stop_p2p_device = ieee80211_stop_p2p_device,
    3973                 :            :         .add_key = ieee80211_add_key,
    3974                 :            :         .del_key = ieee80211_del_key,
    3975                 :            :         .get_key = ieee80211_get_key,
    3976                 :            :         .set_default_key = ieee80211_config_default_key,
    3977                 :            :         .set_default_mgmt_key = ieee80211_config_default_mgmt_key,
    3978                 :            :         .start_ap = ieee80211_start_ap,
    3979                 :            :         .change_beacon = ieee80211_change_beacon,
    3980                 :            :         .stop_ap = ieee80211_stop_ap,
    3981                 :            :         .add_station = ieee80211_add_station,
    3982                 :            :         .del_station = ieee80211_del_station,
    3983                 :            :         .change_station = ieee80211_change_station,
    3984                 :            :         .get_station = ieee80211_get_station,
    3985                 :            :         .dump_station = ieee80211_dump_station,
    3986                 :            :         .dump_survey = ieee80211_dump_survey,
    3987                 :            : #ifdef CONFIG_MAC80211_MESH
    3988                 :            :         .add_mpath = ieee80211_add_mpath,
    3989                 :            :         .del_mpath = ieee80211_del_mpath,
    3990                 :            :         .change_mpath = ieee80211_change_mpath,
    3991                 :            :         .get_mpath = ieee80211_get_mpath,
    3992                 :            :         .dump_mpath = ieee80211_dump_mpath,
    3993                 :            :         .get_mpp = ieee80211_get_mpp,
    3994                 :            :         .dump_mpp = ieee80211_dump_mpp,
    3995                 :            :         .update_mesh_config = ieee80211_update_mesh_config,
    3996                 :            :         .get_mesh_config = ieee80211_get_mesh_config,
    3997                 :            :         .join_mesh = ieee80211_join_mesh,
    3998                 :            :         .leave_mesh = ieee80211_leave_mesh,
    3999                 :            : #endif
    4000                 :            :         .join_ocb = ieee80211_join_ocb,
    4001                 :            :         .leave_ocb = ieee80211_leave_ocb,
    4002                 :            :         .change_bss = ieee80211_change_bss,
    4003                 :            :         .set_txq_params = ieee80211_set_txq_params,
    4004                 :            :         .set_monitor_channel = ieee80211_set_monitor_channel,
    4005                 :            :         .suspend = ieee80211_suspend,
    4006                 :            :         .resume = ieee80211_resume,
    4007                 :            :         .scan = ieee80211_scan,
    4008                 :            :         .abort_scan = ieee80211_abort_scan,
    4009                 :            :         .sched_scan_start = ieee80211_sched_scan_start,
    4010                 :            :         .sched_scan_stop = ieee80211_sched_scan_stop,
    4011                 :            :         .auth = ieee80211_auth,
    4012                 :            :         .assoc = ieee80211_assoc,
    4013                 :            :         .deauth = ieee80211_deauth,
    4014                 :            :         .disassoc = ieee80211_disassoc,
    4015                 :            :         .join_ibss = ieee80211_join_ibss,
    4016                 :            :         .leave_ibss = ieee80211_leave_ibss,
    4017                 :            :         .set_mcast_rate = ieee80211_set_mcast_rate,
    4018                 :            :         .set_wiphy_params = ieee80211_set_wiphy_params,
    4019                 :            :         .set_tx_power = ieee80211_set_tx_power,
    4020                 :            :         .get_tx_power = ieee80211_get_tx_power,
    4021                 :            :         .set_wds_peer = ieee80211_set_wds_peer,
    4022                 :            :         .rfkill_poll = ieee80211_rfkill_poll,
    4023                 :            :         CFG80211_TESTMODE_CMD(ieee80211_testmode_cmd)
    4024                 :            :         CFG80211_TESTMODE_DUMP(ieee80211_testmode_dump)
    4025                 :            :         .set_power_mgmt = ieee80211_set_power_mgmt,
    4026                 :            :         .set_bitrate_mask = ieee80211_set_bitrate_mask,
    4027                 :            :         .remain_on_channel = ieee80211_remain_on_channel,
    4028                 :            :         .cancel_remain_on_channel = ieee80211_cancel_remain_on_channel,
    4029                 :            :         .mgmt_tx = ieee80211_mgmt_tx,
    4030                 :            :         .mgmt_tx_cancel_wait = ieee80211_mgmt_tx_cancel_wait,
    4031                 :            :         .set_cqm_rssi_config = ieee80211_set_cqm_rssi_config,
    4032                 :            :         .set_cqm_rssi_range_config = ieee80211_set_cqm_rssi_range_config,
    4033                 :            :         .mgmt_frame_register = ieee80211_mgmt_frame_register,
    4034                 :            :         .set_antenna = ieee80211_set_antenna,
    4035                 :            :         .get_antenna = ieee80211_get_antenna,
    4036                 :            :         .set_rekey_data = ieee80211_set_rekey_data,
    4037                 :            :         .tdls_oper = ieee80211_tdls_oper,
    4038                 :            :         .tdls_mgmt = ieee80211_tdls_mgmt,
    4039                 :            :         .tdls_channel_switch = ieee80211_tdls_channel_switch,
    4040                 :            :         .tdls_cancel_channel_switch = ieee80211_tdls_cancel_channel_switch,
    4041                 :            :         .probe_client = ieee80211_probe_client,
    4042                 :            :         .set_noack_map = ieee80211_set_noack_map,
    4043                 :            : #ifdef CONFIG_PM
    4044                 :            :         .set_wakeup = ieee80211_set_wakeup,
    4045                 :            : #endif
    4046                 :            :         .get_channel = ieee80211_cfg_get_channel,
    4047                 :            :         .start_radar_detection = ieee80211_start_radar_detection,
    4048                 :            :         .end_cac = ieee80211_end_cac,
    4049                 :            :         .channel_switch = ieee80211_channel_switch,
    4050                 :            :         .set_qos_map = ieee80211_set_qos_map,
    4051                 :            :         .set_ap_chanwidth = ieee80211_set_ap_chanwidth,
    4052                 :            :         .add_tx_ts = ieee80211_add_tx_ts,
    4053                 :            :         .del_tx_ts = ieee80211_del_tx_ts,
    4054                 :            :         .start_nan = ieee80211_start_nan,
    4055                 :            :         .stop_nan = ieee80211_stop_nan,
    4056                 :            :         .nan_change_conf = ieee80211_nan_change_conf,
    4057                 :            :         .add_nan_func = ieee80211_add_nan_func,
    4058                 :            :         .del_nan_func = ieee80211_del_nan_func,
    4059                 :            :         .set_multicast_to_unicast = ieee80211_set_multicast_to_unicast,
    4060                 :            :         .tx_control_port = ieee80211_tx_control_port,
    4061                 :            :         .get_txq_stats = ieee80211_get_txq_stats,
    4062                 :            :         .get_ftm_responder_stats = ieee80211_get_ftm_responder_stats,
    4063                 :            :         .start_pmsr = ieee80211_start_pmsr,
    4064                 :            :         .abort_pmsr = ieee80211_abort_pmsr,
    4065                 :            :         .probe_mesh_link = ieee80211_probe_mesh_link,
    4066                 :            : };

Generated by: LCOV version 1.14