LCOV - code coverage report
Current view: top level - net/mac80211 - util.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 207 1892 10.9 %
Date: 2022-03-28 13:20:08 Functions: 18 97 18.6 %
Branches: 89 1200 7.4 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * Copyright 2002-2005, Instant802 Networks, Inc.
       4                 :            :  * Copyright 2005-2006, Devicescape Software, Inc.
       5                 :            :  * Copyright 2006-2007  Jiri Benc <jbenc@suse.cz>
       6                 :            :  * Copyright 2007       Johannes Berg <johannes@sipsolutions.net>
       7                 :            :  * Copyright 2013-2014  Intel Mobile Communications GmbH
       8                 :            :  * Copyright (C) 2015-2017      Intel Deutschland GmbH
       9                 :            :  * Copyright (C) 2018-2019 Intel Corporation
      10                 :            :  *
      11                 :            :  * utilities for mac80211
      12                 :            :  */
      13                 :            : 
      14                 :            : #include <net/mac80211.h>
      15                 :            : #include <linux/netdevice.h>
      16                 :            : #include <linux/export.h>
      17                 :            : #include <linux/types.h>
      18                 :            : #include <linux/slab.h>
      19                 :            : #include <linux/skbuff.h>
      20                 :            : #include <linux/etherdevice.h>
      21                 :            : #include <linux/if_arp.h>
      22                 :            : #include <linux/bitmap.h>
      23                 :            : #include <linux/crc32.h>
      24                 :            : #include <net/net_namespace.h>
      25                 :            : #include <net/cfg80211.h>
      26                 :            : #include <net/rtnetlink.h>
      27                 :            : 
      28                 :            : #include "ieee80211_i.h"
      29                 :            : #include "driver-ops.h"
      30                 :            : #include "rate.h"
      31                 :            : #include "mesh.h"
      32                 :            : #include "wme.h"
      33                 :            : #include "led.h"
      34                 :            : #include "wep.h"
      35                 :            : 
      36                 :            : /* privid for wiphys to determine whether they belong to us or not */
      37                 :            : const void *const mac80211_wiphy_privid = &mac80211_wiphy_privid;
      38                 :            : 
      39                 :          6 : struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy)
      40                 :            : {
      41                 :          6 :         struct ieee80211_local *local;
      42         [ -  + ]:          6 :         BUG_ON(!wiphy);
      43                 :            : 
      44                 :          6 :         local = wiphy_priv(wiphy);
      45                 :          6 :         return &local->hw;
      46                 :            : }
      47                 :            : EXPORT_SYMBOL(wiphy_to_ieee80211_hw);
      48                 :            : 
      49                 :          0 : void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
      50                 :            : {
      51                 :          0 :         struct sk_buff *skb;
      52                 :          0 :         struct ieee80211_hdr *hdr;
      53                 :            : 
      54         [ #  # ]:          0 :         skb_queue_walk(&tx->skbs, skb) {
      55                 :          0 :                 hdr = (struct ieee80211_hdr *) skb->data;
      56                 :          0 :                 hdr->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
      57                 :            :         }
      58                 :          0 : }
      59                 :            : 
      60                 :          0 : int ieee80211_frame_duration(enum nl80211_band band, size_t len,
      61                 :            :                              int rate, int erp, int short_preamble,
      62                 :            :                              int shift)
      63                 :            : {
      64                 :          0 :         int dur;
      65                 :            : 
      66                 :            :         /* calculate duration (in microseconds, rounded up to next higher
      67                 :            :          * integer if it includes a fractional microsecond) to send frame of
      68                 :            :          * len bytes (does not include FCS) at the given rate. Duration will
      69                 :            :          * also include SIFS.
      70                 :            :          *
      71                 :            :          * rate is in 100 kbps, so divident is multiplied by 10 in the
      72                 :            :          * DIV_ROUND_UP() operations.
      73                 :            :          *
      74                 :            :          * shift may be 2 for 5 MHz channels or 1 for 10 MHz channels, and
      75                 :            :          * is assumed to be 0 otherwise.
      76                 :            :          */
      77                 :            : 
      78         [ #  # ]:          0 :         if (band == NL80211_BAND_5GHZ || erp) {
      79                 :            :                 /*
      80                 :            :                  * OFDM:
      81                 :            :                  *
      82                 :            :                  * N_DBPS = DATARATE x 4
      83                 :            :                  * N_SYM = Ceiling((16+8xLENGTH+6) / N_DBPS)
      84                 :            :                  *      (16 = SIGNAL time, 6 = tail bits)
      85                 :            :                  * TXTIME = T_PREAMBLE + T_SIGNAL + T_SYM x N_SYM + Signal Ext
      86                 :            :                  *
      87                 :            :                  * T_SYM = 4 usec
      88                 :            :                  * 802.11a - 18.5.2: aSIFSTime = 16 usec
      89                 :            :                  * 802.11g - 19.8.4: aSIFSTime = 10 usec +
      90                 :            :                  *      signal ext = 6 usec
      91                 :            :                  */
      92                 :          0 :                 dur = 16; /* SIFS + signal ext */
      93                 :          0 :                 dur += 16; /* IEEE 802.11-2012 18.3.2.4: T_PREAMBLE = 16 usec */
      94                 :          0 :                 dur += 4; /* IEEE 802.11-2012 18.3.2.4: T_SIGNAL = 4 usec */
      95                 :            : 
      96                 :            :                 /* IEEE 802.11-2012 18.3.2.4: all values above are:
      97                 :            :                  *  * times 4 for 5 MHz
      98                 :            :                  *  * times 2 for 10 MHz
      99                 :            :                  */
     100                 :          0 :                 dur *= 1 << shift;
     101                 :            : 
     102                 :            :                 /* rates should already consider the channel bandwidth,
     103                 :            :                  * don't apply divisor again.
     104                 :            :                  */
     105                 :          0 :                 dur += 4 * DIV_ROUND_UP((16 + 8 * (len + 4) + 6) * 10,
     106                 :            :                                         4 * rate); /* T_SYM x N_SYM */
     107                 :            :         } else {
     108                 :            :                 /*
     109                 :            :                  * 802.11b or 802.11g with 802.11b compatibility:
     110                 :            :                  * 18.3.4: TXTIME = PreambleLength + PLCPHeaderTime +
     111                 :            :                  * Ceiling(((LENGTH+PBCC)x8)/DATARATE). PBCC=0.
     112                 :            :                  *
     113                 :            :                  * 802.11 (DS): 15.3.3, 802.11b: 18.3.4
     114                 :            :                  * aSIFSTime = 10 usec
     115                 :            :                  * aPreambleLength = 144 usec or 72 usec with short preamble
     116                 :            :                  * aPLCPHeaderLength = 48 usec or 24 usec with short preamble
     117                 :            :                  */
     118                 :          0 :                 dur = 10; /* aSIFSTime = 10 usec */
     119   [ #  #  #  #  :          0 :                 dur += short_preamble ? (72 + 24) : (144 + 48);
          #  #  #  #  #  
                #  #  # ]
     120                 :            : 
     121                 :          0 :                 dur += DIV_ROUND_UP(8 * (len + 4) * 10, rate);
     122                 :            :         }
     123                 :            : 
     124                 :          0 :         return dur;
     125                 :            : }
     126                 :            : 
     127                 :            : /* Exported duration function for driver use */
     128                 :          0 : __le16 ieee80211_generic_frame_duration(struct ieee80211_hw *hw,
     129                 :            :                                         struct ieee80211_vif *vif,
     130                 :            :                                         enum nl80211_band band,
     131                 :            :                                         size_t frame_len,
     132                 :            :                                         struct ieee80211_rate *rate)
     133                 :            : {
     134                 :          0 :         struct ieee80211_sub_if_data *sdata;
     135                 :          0 :         u16 dur;
     136                 :          0 :         int erp, shift = 0;
     137                 :          0 :         bool short_preamble = false;
     138                 :            : 
     139                 :          0 :         erp = 0;
     140         [ #  # ]:          0 :         if (vif) {
     141         [ #  # ]:          0 :                 sdata = vif_to_sdata(vif);
     142                 :          0 :                 short_preamble = sdata->vif.bss_conf.use_short_preamble;
     143         [ #  # ]:          0 :                 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
     144                 :          0 :                         erp = rate->flags & IEEE80211_RATE_ERP_G;
     145                 :          0 :                 shift = ieee80211_vif_get_shift(vif);
     146                 :            :         }
     147                 :            : 
     148         [ #  # ]:          0 :         dur = ieee80211_frame_duration(band, frame_len, rate->bitrate, erp,
     149                 :            :                                        short_preamble, shift);
     150                 :            : 
     151                 :          0 :         return cpu_to_le16(dur);
     152                 :            : }
     153                 :            : EXPORT_SYMBOL(ieee80211_generic_frame_duration);
     154                 :            : 
     155                 :          0 : __le16 ieee80211_rts_duration(struct ieee80211_hw *hw,
     156                 :            :                               struct ieee80211_vif *vif, size_t frame_len,
     157                 :            :                               const struct ieee80211_tx_info *frame_txctl)
     158                 :            : {
     159         [ #  # ]:          0 :         struct ieee80211_local *local = hw_to_local(hw);
     160                 :          0 :         struct ieee80211_rate *rate;
     161                 :          0 :         struct ieee80211_sub_if_data *sdata;
     162                 :          0 :         bool short_preamble;
     163                 :          0 :         int erp, shift = 0, bitrate;
     164                 :          0 :         u16 dur;
     165                 :          0 :         struct ieee80211_supported_band *sband;
     166                 :            : 
     167                 :          0 :         sband = local->hw.wiphy->bands[frame_txctl->band];
     168                 :            : 
     169                 :          0 :         short_preamble = false;
     170                 :            : 
     171                 :          0 :         rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx];
     172                 :            : 
     173                 :          0 :         erp = 0;
     174         [ #  # ]:          0 :         if (vif) {
     175         [ #  # ]:          0 :                 sdata = vif_to_sdata(vif);
     176                 :          0 :                 short_preamble = sdata->vif.bss_conf.use_short_preamble;
     177         [ #  # ]:          0 :                 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
     178                 :          0 :                         erp = rate->flags & IEEE80211_RATE_ERP_G;
     179                 :          0 :                 shift = ieee80211_vif_get_shift(vif);
     180                 :            :         }
     181                 :            : 
     182                 :          0 :         bitrate = DIV_ROUND_UP(rate->bitrate, 1 << shift);
     183                 :            : 
     184                 :            :         /* CTS duration */
     185         [ #  # ]:          0 :         dur = ieee80211_frame_duration(sband->band, 10, bitrate,
     186                 :            :                                        erp, short_preamble, shift);
     187                 :            :         /* Data frame duration */
     188         [ #  # ]:          0 :         dur += ieee80211_frame_duration(sband->band, frame_len, bitrate,
     189                 :            :                                         erp, short_preamble, shift);
     190                 :            :         /* ACK duration */
     191                 :          0 :         dur += ieee80211_frame_duration(sband->band, 10, bitrate,
     192                 :            :                                         erp, short_preamble, shift);
     193                 :            : 
     194                 :          0 :         return cpu_to_le16(dur);
     195                 :            : }
     196                 :            : EXPORT_SYMBOL(ieee80211_rts_duration);
     197                 :            : 
     198                 :          0 : __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw,
     199                 :            :                                     struct ieee80211_vif *vif,
     200                 :            :                                     size_t frame_len,
     201                 :            :                                     const struct ieee80211_tx_info *frame_txctl)
     202                 :            : {
     203         [ #  # ]:          0 :         struct ieee80211_local *local = hw_to_local(hw);
     204                 :          0 :         struct ieee80211_rate *rate;
     205                 :          0 :         struct ieee80211_sub_if_data *sdata;
     206                 :          0 :         bool short_preamble;
     207                 :          0 :         int erp, shift = 0, bitrate;
     208                 :          0 :         u16 dur;
     209                 :          0 :         struct ieee80211_supported_band *sband;
     210                 :            : 
     211                 :          0 :         sband = local->hw.wiphy->bands[frame_txctl->band];
     212                 :            : 
     213                 :          0 :         short_preamble = false;
     214                 :            : 
     215                 :          0 :         rate = &sband->bitrates[frame_txctl->control.rts_cts_rate_idx];
     216                 :          0 :         erp = 0;
     217         [ #  # ]:          0 :         if (vif) {
     218         [ #  # ]:          0 :                 sdata = vif_to_sdata(vif);
     219                 :          0 :                 short_preamble = sdata->vif.bss_conf.use_short_preamble;
     220         [ #  # ]:          0 :                 if (sdata->flags & IEEE80211_SDATA_OPERATING_GMODE)
     221                 :          0 :                         erp = rate->flags & IEEE80211_RATE_ERP_G;
     222                 :          0 :                 shift = ieee80211_vif_get_shift(vif);
     223                 :            :         }
     224                 :            : 
     225                 :          0 :         bitrate = DIV_ROUND_UP(rate->bitrate, 1 << shift);
     226                 :            : 
     227                 :            :         /* Data frame duration */
     228         [ #  # ]:          0 :         dur = ieee80211_frame_duration(sband->band, frame_len, bitrate,
     229                 :            :                                        erp, short_preamble, shift);
     230         [ #  # ]:          0 :         if (!(frame_txctl->flags & IEEE80211_TX_CTL_NO_ACK)) {
     231                 :            :                 /* ACK duration */
     232         [ #  # ]:          0 :                 dur += ieee80211_frame_duration(sband->band, 10, bitrate,
     233                 :            :                                                 erp, short_preamble, shift);
     234                 :            :         }
     235                 :            : 
     236                 :          0 :         return cpu_to_le16(dur);
     237                 :            : }
     238                 :            : EXPORT_SYMBOL(ieee80211_ctstoself_duration);
     239                 :            : 
     240                 :        284 : static void __ieee80211_wake_txqs(struct ieee80211_sub_if_data *sdata, int ac)
     241                 :            : {
     242                 :        284 :         struct ieee80211_local *local = sdata->local;
     243                 :        284 :         struct ieee80211_vif *vif = &sdata->vif;
     244                 :        284 :         struct fq *fq = &local->fq;
     245                 :        284 :         struct ps_data *ps = NULL;
     246                 :        284 :         struct txq_info *txqi;
     247                 :        284 :         struct sta_info *sta;
     248                 :        284 :         int i;
     249                 :            : 
     250                 :        284 :         local_bh_disable();
     251                 :        284 :         spin_lock(&fq->lock);
     252                 :            : 
     253         [ -  + ]:        284 :         if (sdata->vif.type == NL80211_IFTYPE_AP)
     254                 :          0 :                 ps = &sdata->bss->ps;
     255                 :            : 
     256                 :        284 :         sdata->vif.txqs_stopped[ac] = false;
     257                 :            : 
     258         [ -  + ]:        284 :         list_for_each_entry_rcu(sta, &local->sta_list, list) {
     259         [ #  # ]:          0 :                 if (sdata != sta->sdata)
     260                 :          0 :                         continue;
     261                 :            : 
     262         [ #  # ]:          0 :                 for (i = 0; i < ARRAY_SIZE(sta->sta.txq); i++) {
     263                 :          0 :                         struct ieee80211_txq *txq = sta->sta.txq[i];
     264                 :            : 
     265         [ #  # ]:          0 :                         if (!txq)
     266                 :          0 :                                 continue;
     267                 :            : 
     268         [ #  # ]:          0 :                         txqi = to_txq_info(txq);
     269                 :            : 
     270         [ #  # ]:          0 :                         if (ac != txq->ac)
     271                 :          0 :                                 continue;
     272                 :            : 
     273         [ #  # ]:          0 :                         if (!test_and_clear_bit(IEEE80211_TXQ_STOP_NETIF_TX,
     274                 :          0 :                                                 &txqi->flags))
     275                 :          0 :                                 continue;
     276                 :            : 
     277                 :          0 :                         spin_unlock(&fq->lock);
     278                 :          0 :                         drv_wake_tx_queue(local, txqi);
     279                 :          0 :                         spin_lock(&fq->lock);
     280                 :            :                 }
     281                 :            :         }
     282                 :            : 
     283         [ -  + ]:        284 :         if (!vif->txq)
     284                 :          0 :                 goto out;
     285                 :            : 
     286                 :        284 :         txqi = to_txq_info(vif->txq);
     287                 :            : 
     288   [ -  +  -  - ]:        284 :         if (!test_and_clear_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags) ||
     289   [ #  #  #  # ]:          0 :             (ps && atomic_read(&ps->num_sta_ps)) || ac != vif->txq->ac)
     290                 :        284 :                 goto out;
     291                 :            : 
     292                 :          0 :         spin_unlock(&fq->lock);
     293                 :            : 
     294                 :          0 :         drv_wake_tx_queue(local, txqi);
     295                 :          0 :         local_bh_enable();
     296                 :            :         return;
     297                 :        284 : out:
     298                 :        284 :         spin_unlock(&fq->lock);
     299                 :        284 :         local_bh_enable();
     300                 :            : }
     301                 :            : 
     302                 :            : static void
     303                 :            : __releases(&local->queue_stop_reason_lock)
     304                 :            : __acquires(&local->queue_stop_reason_lock)
     305                 :         71 : _ieee80211_wake_txqs(struct ieee80211_local *local, unsigned long *flags)
     306                 :            : {
     307                 :         71 :         struct ieee80211_sub_if_data *sdata;
     308                 :         71 :         int n_acs = IEEE80211_NUM_ACS;
     309                 :         71 :         int i;
     310                 :            : 
     311                 :         71 :         rcu_read_lock();
     312                 :            : 
     313         [ -  + ]:         71 :         if (local->hw.queues < IEEE80211_NUM_ACS)
     314                 :          0 :                 n_acs = 1;
     315                 :            : 
     316         [ +  + ]:        355 :         for (i = 0; i < local->hw.queues; i++) {
     317         [ -  + ]:        284 :                 if (local->queue_stop_reasons[i])
     318                 :          0 :                         continue;
     319                 :            : 
     320                 :        284 :                 spin_unlock_irqrestore(&local->queue_stop_reason_lock, *flags);
     321         [ +  + ]:        568 :                 list_for_each_entry_rcu(sdata, &local->interfaces, list) {
     322                 :            :                         int ac;
     323                 :            : 
     324         [ +  + ]:       1420 :                         for (ac = 0; ac < n_acs; ac++) {
     325                 :       1136 :                                 int ac_queue = sdata->vif.hw_queue[ac];
     326                 :            : 
     327         [ +  + ]:       1136 :                                 if (ac_queue == i ||
     328         [ -  + ]:        852 :                                     sdata->vif.cab_queue == i)
     329                 :        284 :                                         __ieee80211_wake_txqs(sdata, ac);
     330                 :            :                         }
     331                 :            :                 }
     332                 :        284 :                 spin_lock_irqsave(&local->queue_stop_reason_lock, *flags);
     333                 :            :         }
     334                 :            : 
     335                 :         71 :         rcu_read_unlock();
     336                 :         71 : }
     337                 :            : 
     338                 :         71 : void ieee80211_wake_txqs(unsigned long data)
     339                 :            : {
     340                 :         71 :         struct ieee80211_local *local = (struct ieee80211_local *)data;
     341                 :         71 :         unsigned long flags;
     342                 :            : 
     343                 :         71 :         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
     344                 :         71 :         _ieee80211_wake_txqs(local, &flags);
     345                 :         71 :         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
     346                 :         71 : }
     347                 :            : 
     348                 :        284 : void ieee80211_propagate_queue_wake(struct ieee80211_local *local, int queue)
     349                 :            : {
     350                 :        284 :         struct ieee80211_sub_if_data *sdata;
     351                 :        284 :         int n_acs = IEEE80211_NUM_ACS;
     352                 :            : 
     353         [ -  + ]:        284 :         if (local->ops->wake_tx_queue)
     354                 :            :                 return;
     355                 :            : 
     356         [ #  # ]:          0 :         if (local->hw.queues < IEEE80211_NUM_ACS)
     357                 :          0 :                 n_acs = 1;
     358                 :            : 
     359         [ #  # ]:          0 :         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
     360                 :          0 :                 int ac;
     361                 :            : 
     362         [ #  # ]:          0 :                 if (!sdata->dev)
     363                 :          0 :                         continue;
     364                 :            : 
     365         [ #  # ]:          0 :                 if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE &&
     366         [ #  # ]:          0 :                     local->queue_stop_reasons[sdata->vif.cab_queue] != 0)
     367                 :          0 :                         continue;
     368                 :            : 
     369         [ #  # ]:          0 :                 for (ac = 0; ac < n_acs; ac++) {
     370                 :          0 :                         int ac_queue = sdata->vif.hw_queue[ac];
     371                 :            : 
     372         [ #  # ]:          0 :                         if (ac_queue == queue ||
     373         [ #  # ]:          0 :                             (sdata->vif.cab_queue == queue &&
     374   [ #  #  #  # ]:          0 :                              local->queue_stop_reasons[ac_queue] == 0 &&
     375         [ #  # ]:          0 :                              skb_queue_empty(&local->pending[ac_queue])))
     376                 :          0 :                                 netif_wake_subqueue(sdata->dev, ac);
     377                 :            :                 }
     378                 :            :         }
     379                 :            : }
     380                 :            : 
     381                 :        308 : static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
     382                 :            :                                    enum queue_stop_reason reason,
     383                 :            :                                    bool refcounted,
     384                 :            :                                    unsigned long *flags)
     385                 :            : {
     386                 :        308 :         struct ieee80211_local *local = hw_to_local(hw);
     387                 :            : 
     388                 :        308 :         trace_wake_queue(local, queue, reason);
     389                 :            : 
     390   [ -  +  +  - ]:        308 :         if (WARN_ON(queue >= hw->queues))
     391                 :            :                 return;
     392                 :            : 
     393         [ +  + ]:        308 :         if (!test_bit(reason, &local->queue_stop_reasons[queue]))
     394                 :            :                 return;
     395                 :            : 
     396         [ +  - ]:        284 :         if (!refcounted) {
     397                 :        284 :                 local->q_stop_reasons[queue][reason] = 0;
     398                 :            :         } else {
     399                 :          0 :                 local->q_stop_reasons[queue][reason]--;
     400   [ #  #  #  # ]:          0 :                 if (WARN_ON(local->q_stop_reasons[queue][reason] < 0))
     401                 :          0 :                         local->q_stop_reasons[queue][reason] = 0;
     402                 :            :         }
     403                 :            : 
     404         [ +  - ]:        284 :         if (local->q_stop_reasons[queue][reason] == 0)
     405                 :        284 :                 __clear_bit(reason, &local->queue_stop_reasons[queue]);
     406                 :            : 
     407         [ +  - ]:        284 :         if (local->queue_stop_reasons[queue] != 0)
     408                 :            :                 /* someone still has this queue stopped */
     409                 :            :                 return;
     410                 :            : 
     411         [ +  - ]:        284 :         if (skb_queue_empty(&local->pending[queue])) {
     412                 :        284 :                 rcu_read_lock();
     413                 :        284 :                 ieee80211_propagate_queue_wake(local, queue);
     414                 :        284 :                 rcu_read_unlock();
     415                 :            :         } else
     416                 :          0 :                 tasklet_schedule(&local->tx_pending_tasklet);
     417                 :            : 
     418                 :            :         /*
     419                 :            :          * Calling _ieee80211_wake_txqs here can be a problem because it may
     420                 :            :          * release queue_stop_reason_lock which has been taken by
     421                 :            :          * __ieee80211_wake_queue's caller. It is certainly not very nice to
     422                 :            :          * release someone's lock, but it is fine because all the callers of
     423                 :            :          * __ieee80211_wake_queue call it right before releasing the lock.
     424                 :            :          */
     425         [ +  - ]:        284 :         if (local->ops->wake_tx_queue) {
     426         [ +  - ]:        284 :                 if (reason == IEEE80211_QUEUE_STOP_REASON_DRIVER)
     427                 :        284 :                         tasklet_schedule(&local->wake_txqs_tasklet);
     428                 :            :                 else
     429                 :          0 :                         _ieee80211_wake_txqs(local, flags);
     430                 :            :         }
     431                 :            : }
     432                 :            : 
     433                 :          0 : void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue,
     434                 :            :                                     enum queue_stop_reason reason,
     435                 :            :                                     bool refcounted)
     436                 :            : {
     437                 :          0 :         struct ieee80211_local *local = hw_to_local(hw);
     438                 :          0 :         unsigned long flags;
     439                 :            : 
     440                 :          0 :         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
     441                 :          0 :         __ieee80211_wake_queue(hw, queue, reason, refcounted, &flags);
     442                 :          0 :         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
     443                 :          0 : }
     444                 :            : 
     445                 :          0 : void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue)
     446                 :            : {
     447                 :          0 :         ieee80211_wake_queue_by_reason(hw, queue,
     448                 :            :                                        IEEE80211_QUEUE_STOP_REASON_DRIVER,
     449                 :            :                                        false);
     450                 :          0 : }
     451                 :            : EXPORT_SYMBOL(ieee80211_wake_queue);
     452                 :            : 
     453                 :        284 : static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
     454                 :            :                                    enum queue_stop_reason reason,
     455                 :            :                                    bool refcounted)
     456                 :            : {
     457                 :        284 :         struct ieee80211_local *local = hw_to_local(hw);
     458                 :        284 :         struct ieee80211_sub_if_data *sdata;
     459                 :        284 :         int n_acs = IEEE80211_NUM_ACS;
     460                 :            : 
     461                 :        284 :         trace_stop_queue(local, queue, reason);
     462                 :            : 
     463   [ -  +  +  - ]:        284 :         if (WARN_ON(queue >= hw->queues))
     464                 :            :                 return;
     465                 :            : 
     466         [ +  - ]:        284 :         if (!refcounted)
     467                 :        284 :                 local->q_stop_reasons[queue][reason] = 1;
     468                 :            :         else
     469                 :          0 :                 local->q_stop_reasons[queue][reason]++;
     470                 :            : 
     471         [ +  - ]:        284 :         if (__test_and_set_bit(reason, &local->queue_stop_reasons[queue]))
     472                 :            :                 return;
     473                 :            : 
     474         [ -  + ]:        284 :         if (local->hw.queues < IEEE80211_NUM_ACS)
     475                 :          0 :                 n_acs = 1;
     476                 :            : 
     477                 :        284 :         rcu_read_lock();
     478         [ +  + ]:        568 :         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
     479                 :        284 :                 int ac;
     480                 :            : 
     481         [ -  + ]:        284 :                 if (!sdata->dev)
     482                 :          0 :                         continue;
     483                 :            : 
     484         [ +  + ]:       1420 :                 for (ac = 0; ac < n_acs; ac++) {
     485         [ +  + ]:       1136 :                         if (sdata->vif.hw_queue[ac] == queue ||
     486         [ -  + ]:        852 :                             sdata->vif.cab_queue == queue) {
     487         [ -  + ]:        284 :                                 if (!local->ops->wake_tx_queue) {
     488                 :          0 :                                         netif_stop_subqueue(sdata->dev, ac);
     489                 :          0 :                                         continue;
     490                 :            :                                 }
     491                 :        284 :                                 spin_lock(&local->fq.lock);
     492                 :        284 :                                 sdata->vif.txqs_stopped[ac] = true;
     493                 :        284 :                                 spin_unlock(&local->fq.lock);
     494                 :            :                         }
     495                 :            :                 }
     496                 :            :         }
     497                 :        284 :         rcu_read_unlock();
     498                 :            : }
     499                 :            : 
     500                 :          0 : void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
     501                 :            :                                     enum queue_stop_reason reason,
     502                 :            :                                     bool refcounted)
     503                 :            : {
     504                 :          0 :         struct ieee80211_local *local = hw_to_local(hw);
     505                 :          0 :         unsigned long flags;
     506                 :            : 
     507                 :          0 :         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
     508                 :          0 :         __ieee80211_stop_queue(hw, queue, reason, refcounted);
     509                 :          0 :         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
     510                 :          0 : }
     511                 :            : 
     512                 :          0 : void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
     513                 :            : {
     514                 :          0 :         ieee80211_stop_queue_by_reason(hw, queue,
     515                 :            :                                        IEEE80211_QUEUE_STOP_REASON_DRIVER,
     516                 :            :                                        false);
     517                 :          0 : }
     518                 :            : EXPORT_SYMBOL(ieee80211_stop_queue);
     519                 :            : 
     520                 :          0 : void ieee80211_add_pending_skb(struct ieee80211_local *local,
     521                 :            :                                struct sk_buff *skb)
     522                 :            : {
     523                 :          0 :         struct ieee80211_hw *hw = &local->hw;
     524                 :          0 :         unsigned long flags;
     525         [ #  # ]:          0 :         struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
     526                 :          0 :         int queue = info->hw_queue;
     527                 :            : 
     528   [ #  #  #  # ]:          0 :         if (WARN_ON(!info->control.vif)) {
     529                 :          0 :                 ieee80211_free_txskb(&local->hw, skb);
     530                 :          0 :                 return;
     531                 :            :         }
     532                 :            : 
     533                 :          0 :         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
     534                 :          0 :         __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
     535                 :            :                                false);
     536                 :          0 :         __skb_queue_tail(&local->pending[queue], skb);
     537                 :          0 :         __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
     538                 :            :                                false, &flags);
     539                 :          0 :         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
     540                 :            : }
     541                 :            : 
     542                 :          0 : void ieee80211_add_pending_skbs(struct ieee80211_local *local,
     543                 :            :                                 struct sk_buff_head *skbs)
     544                 :            : {
     545                 :          0 :         struct ieee80211_hw *hw = &local->hw;
     546                 :          0 :         struct sk_buff *skb;
     547                 :          0 :         unsigned long flags;
     548                 :          0 :         int queue, i;
     549                 :            : 
     550                 :          0 :         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
     551         [ #  # ]:          0 :         while ((skb = skb_dequeue(skbs))) {
     552         [ #  # ]:          0 :                 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
     553                 :            : 
     554   [ #  #  #  # ]:          0 :                 if (WARN_ON(!info->control.vif)) {
     555                 :          0 :                         ieee80211_free_txskb(&local->hw, skb);
     556                 :          0 :                         continue;
     557                 :            :                 }
     558                 :            : 
     559                 :          0 :                 queue = info->hw_queue;
     560                 :            : 
     561                 :          0 :                 __ieee80211_stop_queue(hw, queue,
     562                 :            :                                 IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
     563                 :            :                                 false);
     564                 :            : 
     565                 :          0 :                 __skb_queue_tail(&local->pending[queue], skb);
     566                 :            :         }
     567                 :            : 
     568         [ #  # ]:          0 :         for (i = 0; i < hw->queues; i++)
     569                 :          0 :                 __ieee80211_wake_queue(hw, i,
     570                 :            :                         IEEE80211_QUEUE_STOP_REASON_SKB_ADD,
     571                 :            :                         false, &flags);
     572                 :          0 :         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
     573                 :          0 : }
     574                 :            : 
     575                 :         71 : void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
     576                 :            :                                      unsigned long queues,
     577                 :            :                                      enum queue_stop_reason reason,
     578                 :            :                                      bool refcounted)
     579                 :            : {
     580                 :         71 :         struct ieee80211_local *local = hw_to_local(hw);
     581                 :         71 :         unsigned long flags;
     582                 :         71 :         int i;
     583                 :            : 
     584                 :         71 :         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
     585                 :            : 
     586         [ +  + ]:        355 :         for_each_set_bit(i, &queues, hw->queues)
     587                 :        284 :                 __ieee80211_stop_queue(hw, i, reason, refcounted);
     588                 :            : 
     589                 :         71 :         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
     590                 :         71 : }
     591                 :            : 
     592                 :         71 : void ieee80211_stop_queues(struct ieee80211_hw *hw)
     593                 :            : {
     594                 :         71 :         ieee80211_stop_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
     595                 :            :                                         IEEE80211_QUEUE_STOP_REASON_DRIVER,
     596                 :            :                                         false);
     597                 :         71 : }
     598                 :            : EXPORT_SYMBOL(ieee80211_stop_queues);
     599                 :            : 
     600                 :          0 : int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue)
     601                 :            : {
     602         [ #  # ]:          0 :         struct ieee80211_local *local = hw_to_local(hw);
     603                 :          0 :         unsigned long flags;
     604                 :          0 :         int ret;
     605                 :            : 
     606   [ #  #  #  # ]:          0 :         if (WARN_ON(queue >= hw->queues))
     607                 :            :                 return true;
     608                 :            : 
     609                 :          0 :         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
     610                 :          0 :         ret = test_bit(IEEE80211_QUEUE_STOP_REASON_DRIVER,
     611                 :          0 :                        &local->queue_stop_reasons[queue]);
     612                 :          0 :         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
     613                 :          0 :         return ret;
     614                 :            : }
     615                 :            : EXPORT_SYMBOL(ieee80211_queue_stopped);
     616                 :            : 
     617                 :         77 : void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw,
     618                 :            :                                      unsigned long queues,
     619                 :            :                                      enum queue_stop_reason reason,
     620                 :            :                                      bool refcounted)
     621                 :            : {
     622                 :         77 :         struct ieee80211_local *local = hw_to_local(hw);
     623                 :         77 :         unsigned long flags;
     624                 :         77 :         int i;
     625                 :            : 
     626                 :         77 :         spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
     627                 :            : 
     628         [ +  + ]:        385 :         for_each_set_bit(i, &queues, hw->queues)
     629                 :        308 :                 __ieee80211_wake_queue(hw, i, reason, refcounted, &flags);
     630                 :            : 
     631                 :         77 :         spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
     632                 :         77 : }
     633                 :            : 
     634                 :         77 : void ieee80211_wake_queues(struct ieee80211_hw *hw)
     635                 :            : {
     636                 :         77 :         ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
     637                 :            :                                         IEEE80211_QUEUE_STOP_REASON_DRIVER,
     638                 :            :                                         false);
     639                 :         77 : }
     640                 :            : EXPORT_SYMBOL(ieee80211_wake_queues);
     641                 :            : 
     642                 :            : static unsigned int
     643                 :          0 : ieee80211_get_vif_queues(struct ieee80211_local *local,
     644                 :            :                          struct ieee80211_sub_if_data *sdata)
     645                 :            : {
     646                 :          0 :         unsigned int queues;
     647                 :            : 
     648   [ #  #  #  # ]:          0 :         if (sdata && ieee80211_hw_check(&local->hw, QUEUE_CONTROL)) {
     649                 :            :                 int ac;
     650                 :            : 
     651                 :            :                 queues = 0;
     652                 :            : 
     653         [ #  # ]:          0 :                 for (ac = 0; ac < IEEE80211_NUM_ACS; ac++)
     654                 :          0 :                         queues |= BIT(sdata->vif.hw_queue[ac]);
     655         [ #  # ]:          0 :                 if (sdata->vif.cab_queue != IEEE80211_INVAL_HW_QUEUE)
     656                 :          0 :                         queues |= BIT(sdata->vif.cab_queue);
     657                 :            :         } else {
     658                 :            :                 /* all queues */
     659                 :          0 :                 queues = BIT(local->hw.queues) - 1;
     660                 :            :         }
     661                 :            : 
     662                 :          0 :         return queues;
     663                 :            : }
     664                 :            : 
     665                 :          0 : void __ieee80211_flush_queues(struct ieee80211_local *local,
     666                 :            :                               struct ieee80211_sub_if_data *sdata,
     667                 :            :                               unsigned int queues, bool drop)
     668                 :            : {
     669         [ #  # ]:          0 :         if (!local->ops->flush)
     670                 :            :                 return;
     671                 :            : 
     672                 :            :         /*
     673                 :            :          * If no queue was set, or if the HW doesn't support
     674                 :            :          * IEEE80211_HW_QUEUE_CONTROL - flush all queues
     675                 :            :          */
     676   [ #  #  #  # ]:          0 :         if (!queues || !ieee80211_hw_check(&local->hw, QUEUE_CONTROL))
     677                 :          0 :                 queues = ieee80211_get_vif_queues(local, sdata);
     678                 :            : 
     679                 :          0 :         ieee80211_stop_queues_by_reason(&local->hw, queues,
     680                 :            :                                         IEEE80211_QUEUE_STOP_REASON_FLUSH,
     681                 :            :                                         false);
     682                 :            : 
     683                 :          0 :         drv_flush(local, sdata, queues, drop);
     684                 :            : 
     685                 :          0 :         ieee80211_wake_queues_by_reason(&local->hw, queues,
     686                 :            :                                         IEEE80211_QUEUE_STOP_REASON_FLUSH,
     687                 :            :                                         false);
     688                 :            : }
     689                 :            : 
     690                 :          0 : void ieee80211_flush_queues(struct ieee80211_local *local,
     691                 :            :                             struct ieee80211_sub_if_data *sdata, bool drop)
     692                 :            : {
     693                 :          0 :         __ieee80211_flush_queues(local, sdata, 0, drop);
     694                 :          0 : }
     695                 :            : 
     696                 :          0 : void ieee80211_stop_vif_queues(struct ieee80211_local *local,
     697                 :            :                                struct ieee80211_sub_if_data *sdata,
     698                 :            :                                enum queue_stop_reason reason)
     699                 :            : {
     700                 :          0 :         ieee80211_stop_queues_by_reason(&local->hw,
     701                 :          0 :                                         ieee80211_get_vif_queues(local, sdata),
     702                 :            :                                         reason, true);
     703                 :          0 : }
     704                 :            : 
     705                 :          0 : void ieee80211_wake_vif_queues(struct ieee80211_local *local,
     706                 :            :                                struct ieee80211_sub_if_data *sdata,
     707                 :            :                                enum queue_stop_reason reason)
     708                 :            : {
     709                 :          0 :         ieee80211_wake_queues_by_reason(&local->hw,
     710                 :          0 :                                         ieee80211_get_vif_queues(local, sdata),
     711                 :            :                                         reason, true);
     712                 :          0 : }
     713                 :            : 
     714                 :          0 : static void __iterate_interfaces(struct ieee80211_local *local,
     715                 :            :                                  u32 iter_flags,
     716                 :            :                                  void (*iterator)(void *data, u8 *mac,
     717                 :            :                                                   struct ieee80211_vif *vif),
     718                 :            :                                  void *data)
     719                 :            : {
     720                 :          0 :         struct ieee80211_sub_if_data *sdata;
     721                 :          0 :         bool active_only = iter_flags & IEEE80211_IFACE_ITER_ACTIVE;
     722                 :            : 
     723         [ #  # ]:          0 :         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
     724      [ #  #  # ]:          0 :                 switch (sdata->vif.type) {
     725                 :          0 :                 case NL80211_IFTYPE_MONITOR:
     726         [ #  # ]:          0 :                         if (!(sdata->u.mntr.flags & MONITOR_FLAG_ACTIVE))
     727                 :          0 :                                 continue;
     728                 :            :                         break;
     729                 :          0 :                 case NL80211_IFTYPE_AP_VLAN:
     730                 :          0 :                         continue;
     731                 :            :                 default:
     732                 :            :                         break;
     733                 :            :                 }
     734   [ #  #  #  # ]:          0 :                 if (!(iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL) &&
     735         [ #  # ]:          0 :                     active_only && !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
     736                 :          0 :                         continue;
     737   [ #  #  #  # ]:          0 :                 if (ieee80211_sdata_running(sdata) || !active_only)
     738                 :          0 :                         iterator(data, sdata->vif.addr,
     739                 :            :                                  &sdata->vif);
     740                 :            :         }
     741                 :            : 
     742         [ #  # ]:          0 :         sdata = rcu_dereference_check(local->monitor_sdata,
     743                 :            :                                       lockdep_is_held(&local->iflist_mtx) ||
     744                 :            :                                       lockdep_rtnl_is_held());
     745         [ #  # ]:          0 :         if (sdata &&
     746   [ #  #  #  # ]:          0 :             (iter_flags & IEEE80211_IFACE_ITER_RESUME_ALL || !active_only ||
     747         [ #  # ]:          0 :              sdata->flags & IEEE80211_SDATA_IN_DRIVER))
     748                 :          0 :                 iterator(data, sdata->vif.addr, &sdata->vif);
     749                 :          0 : }
     750                 :            : 
     751                 :          0 : void ieee80211_iterate_interfaces(
     752                 :            :         struct ieee80211_hw *hw, u32 iter_flags,
     753                 :            :         void (*iterator)(void *data, u8 *mac,
     754                 :            :                          struct ieee80211_vif *vif),
     755                 :            :         void *data)
     756                 :            : {
     757                 :          0 :         struct ieee80211_local *local = hw_to_local(hw);
     758                 :            : 
     759                 :          0 :         mutex_lock(&local->iflist_mtx);
     760                 :          0 :         __iterate_interfaces(local, iter_flags, iterator, data);
     761                 :          0 :         mutex_unlock(&local->iflist_mtx);
     762                 :          0 : }
     763                 :            : EXPORT_SYMBOL_GPL(ieee80211_iterate_interfaces);
     764                 :            : 
     765                 :          0 : void ieee80211_iterate_active_interfaces_atomic(
     766                 :            :         struct ieee80211_hw *hw, u32 iter_flags,
     767                 :            :         void (*iterator)(void *data, u8 *mac,
     768                 :            :                          struct ieee80211_vif *vif),
     769                 :            :         void *data)
     770                 :            : {
     771                 :          0 :         struct ieee80211_local *local = hw_to_local(hw);
     772                 :            : 
     773                 :          0 :         rcu_read_lock();
     774                 :          0 :         __iterate_interfaces(local, iter_flags | IEEE80211_IFACE_ITER_ACTIVE,
     775                 :            :                              iterator, data);
     776                 :          0 :         rcu_read_unlock();
     777                 :          0 : }
     778                 :            : EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
     779                 :            : 
     780                 :          0 : void ieee80211_iterate_active_interfaces_rtnl(
     781                 :            :         struct ieee80211_hw *hw, u32 iter_flags,
     782                 :            :         void (*iterator)(void *data, u8 *mac,
     783                 :            :                          struct ieee80211_vif *vif),
     784                 :            :         void *data)
     785                 :            : {
     786                 :          0 :         struct ieee80211_local *local = hw_to_local(hw);
     787                 :            : 
     788   [ #  #  #  # ]:          0 :         ASSERT_RTNL();
     789                 :            : 
     790                 :          0 :         __iterate_interfaces(local, iter_flags | IEEE80211_IFACE_ITER_ACTIVE,
     791                 :            :                              iterator, data);
     792                 :          0 : }
     793                 :            : EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_rtnl);
     794                 :            : 
     795                 :          0 : static void __iterate_stations(struct ieee80211_local *local,
     796                 :            :                                void (*iterator)(void *data,
     797                 :            :                                                 struct ieee80211_sta *sta),
     798                 :            :                                void *data)
     799                 :            : {
     800                 :          0 :         struct sta_info *sta;
     801                 :            : 
     802         [ #  # ]:          0 :         list_for_each_entry_rcu(sta, &local->sta_list, list) {
     803         [ #  # ]:          0 :                 if (!sta->uploaded)
     804                 :          0 :                         continue;
     805                 :            : 
     806                 :          0 :                 iterator(data, &sta->sta);
     807                 :            :         }
     808                 :            : }
     809                 :            : 
     810                 :          0 : void ieee80211_iterate_stations_atomic(struct ieee80211_hw *hw,
     811                 :            :                         void (*iterator)(void *data,
     812                 :            :                                          struct ieee80211_sta *sta),
     813                 :            :                         void *data)
     814                 :            : {
     815                 :          0 :         struct ieee80211_local *local = hw_to_local(hw);
     816                 :            : 
     817                 :          0 :         rcu_read_lock();
     818                 :          0 :         __iterate_stations(local, iterator, data);
     819                 :          0 :         rcu_read_unlock();
     820                 :          0 : }
     821                 :            : EXPORT_SYMBOL_GPL(ieee80211_iterate_stations_atomic);
     822                 :            : 
     823                 :          0 : struct ieee80211_vif *wdev_to_ieee80211_vif(struct wireless_dev *wdev)
     824                 :            : {
     825                 :          0 :         struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
     826                 :            : 
     827         [ #  # ]:          0 :         if (!ieee80211_sdata_running(sdata) ||
     828         [ #  # ]:          0 :             !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
     829                 :            :                 return NULL;
     830                 :          0 :         return &sdata->vif;
     831                 :            : }
     832                 :            : EXPORT_SYMBOL_GPL(wdev_to_ieee80211_vif);
     833                 :            : 
     834                 :          0 : struct wireless_dev *ieee80211_vif_to_wdev(struct ieee80211_vif *vif)
     835                 :            : {
     836                 :          0 :         struct ieee80211_sub_if_data *sdata;
     837                 :            : 
     838         [ #  # ]:          0 :         if (!vif)
     839                 :            :                 return NULL;
     840                 :            : 
     841                 :          0 :         sdata = vif_to_sdata(vif);
     842                 :            : 
     843         [ #  # ]:          0 :         if (!ieee80211_sdata_running(sdata) ||
     844         [ #  # ]:          0 :             !(sdata->flags & IEEE80211_SDATA_IN_DRIVER))
     845                 :            :                 return NULL;
     846                 :            : 
     847                 :          0 :         return &sdata->wdev;
     848                 :            : }
     849                 :            : EXPORT_SYMBOL_GPL(ieee80211_vif_to_wdev);
     850                 :            : 
     851                 :            : /*
     852                 :            :  * Nothing should have been stuffed into the workqueue during
     853                 :            :  * the suspend->resume cycle. Since we can't check each caller
     854                 :            :  * of this function if we are already quiescing / suspended,
     855                 :            :  * check here and don't WARN since this can actually happen when
     856                 :            :  * the rx path (for example) is racing against __ieee80211_suspend
     857                 :            :  * and suspending / quiescing was set after the rx path checked
     858                 :            :  * them.
     859                 :            :  */
     860                 :        156 : static bool ieee80211_can_queue_work(struct ieee80211_local *local)
     861                 :            : {
     862   [ -  +  -  -  :        156 :         if (local->quiescing || (local->suspended && !local->resuming)) {
             -  +  -  - ]
     863                 :          0 :                 pr_warn("queueing ieee80211 work while going to suspend\n");
     864                 :          0 :                 return false;
     865                 :            :         }
     866                 :            : 
     867                 :            :         return true;
     868                 :            : }
     869                 :            : 
     870                 :         77 : void ieee80211_queue_work(struct ieee80211_hw *hw, struct work_struct *work)
     871                 :            : {
     872         [ +  - ]:         77 :         struct ieee80211_local *local = hw_to_local(hw);
     873                 :            : 
     874         [ +  - ]:         77 :         if (!ieee80211_can_queue_work(local))
     875                 :          0 :                 return;
     876                 :            : 
     877                 :         77 :         queue_work(local->workqueue, work);
     878                 :            : }
     879                 :            : EXPORT_SYMBOL(ieee80211_queue_work);
     880                 :            : 
     881                 :         79 : void ieee80211_queue_delayed_work(struct ieee80211_hw *hw,
     882                 :            :                                   struct delayed_work *dwork,
     883                 :            :                                   unsigned long delay)
     884                 :            : {
     885         [ +  - ]:         79 :         struct ieee80211_local *local = hw_to_local(hw);
     886                 :            : 
     887         [ +  - ]:         79 :         if (!ieee80211_can_queue_work(local))
     888                 :          0 :                 return;
     889                 :            : 
     890                 :         79 :         queue_delayed_work(local->workqueue, dwork, delay);
     891                 :            : }
     892                 :            : EXPORT_SYMBOL(ieee80211_queue_delayed_work);
     893                 :            : 
     894                 :            : static u32
     895                 :          0 : _ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
     896                 :            :                             struct ieee802_11_elems *elems,
     897                 :            :                             u64 filter, u32 crc,
     898                 :            :                             const struct element *check_inherit)
     899                 :            : {
     900                 :          0 :         const struct element *elem;
     901                 :          0 :         bool calc_crc = filter != 0;
     902                 :          0 :         DECLARE_BITMAP(seen_elems, 256);
     903                 :          0 :         const u8 *ie;
     904                 :            : 
     905                 :          0 :         bitmap_zero(seen_elems, 256);
     906                 :            : 
     907   [ #  #  #  # ]:          0 :         for_each_element(elem, start, len) {
     908                 :          0 :                 bool elem_parse_failed;
     909                 :          0 :                 u8 id = elem->id;
     910                 :          0 :                 u8 elen = elem->datalen;
     911                 :          0 :                 const u8 *pos = elem->data;
     912                 :            : 
     913   [ #  #  #  # ]:          0 :                 if (check_inherit &&
     914                 :          0 :                     !cfg80211_is_element_inherited(elem,
     915                 :            :                                                    check_inherit))
     916                 :          0 :                         continue;
     917                 :            : 
     918         [ #  # ]:          0 :                 switch (id) {
     919                 :          0 :                 case WLAN_EID_SSID:
     920                 :            :                 case WLAN_EID_SUPP_RATES:
     921                 :            :                 case WLAN_EID_FH_PARAMS:
     922                 :            :                 case WLAN_EID_DS_PARAMS:
     923                 :            :                 case WLAN_EID_CF_PARAMS:
     924                 :            :                 case WLAN_EID_TIM:
     925                 :            :                 case WLAN_EID_IBSS_PARAMS:
     926                 :            :                 case WLAN_EID_CHALLENGE:
     927                 :            :                 case WLAN_EID_RSN:
     928                 :            :                 case WLAN_EID_ERP_INFO:
     929                 :            :                 case WLAN_EID_EXT_SUPP_RATES:
     930                 :            :                 case WLAN_EID_HT_CAPABILITY:
     931                 :            :                 case WLAN_EID_HT_OPERATION:
     932                 :            :                 case WLAN_EID_VHT_CAPABILITY:
     933                 :            :                 case WLAN_EID_VHT_OPERATION:
     934                 :            :                 case WLAN_EID_MESH_ID:
     935                 :            :                 case WLAN_EID_MESH_CONFIG:
     936                 :            :                 case WLAN_EID_PEER_MGMT:
     937                 :            :                 case WLAN_EID_PREQ:
     938                 :            :                 case WLAN_EID_PREP:
     939                 :            :                 case WLAN_EID_PERR:
     940                 :            :                 case WLAN_EID_RANN:
     941                 :            :                 case WLAN_EID_CHANNEL_SWITCH:
     942                 :            :                 case WLAN_EID_EXT_CHANSWITCH_ANN:
     943                 :            :                 case WLAN_EID_COUNTRY:
     944                 :            :                 case WLAN_EID_PWR_CONSTRAINT:
     945                 :            :                 case WLAN_EID_TIMEOUT_INTERVAL:
     946                 :            :                 case WLAN_EID_SECONDARY_CHANNEL_OFFSET:
     947                 :            :                 case WLAN_EID_WIDE_BW_CHANNEL_SWITCH:
     948                 :            :                 case WLAN_EID_CHAN_SWITCH_PARAM:
     949                 :            :                 case WLAN_EID_EXT_CAPABILITY:
     950                 :            :                 case WLAN_EID_CHAN_SWITCH_TIMING:
     951                 :            :                 case WLAN_EID_LINK_ID:
     952                 :            :                 case WLAN_EID_BSS_MAX_IDLE_PERIOD:
     953                 :            :                 /*
     954                 :            :                  * not listing WLAN_EID_CHANNEL_SWITCH_WRAPPER -- it seems possible
     955                 :            :                  * that if the content gets bigger it might be needed more than once
     956                 :            :                  */
     957         [ #  # ]:          0 :                         if (test_bit(id, seen_elems)) {
     958                 :          0 :                                 elems->parse_error = true;
     959                 :          0 :                                 continue;
     960                 :            :                         }
     961                 :            :                         break;
     962                 :            :                 }
     963                 :            : 
     964   [ #  #  #  # ]:          0 :                 if (calc_crc && id < 64 && (filter & (1ULL << id)))
     965                 :          0 :                         crc = crc32_be(crc, pos - 2, elen + 2);
     966                 :            : 
     967                 :          0 :                 elem_parse_failed = false;
     968                 :            : 
     969   [ #  #  #  #  :          0 :                 switch (id) {
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
          #  #  #  #  #  
             #  #  #  #  
                      # ]
     970                 :          0 :                 case WLAN_EID_LINK_ID:
     971         [ #  # ]:          0 :                         if (elen + 2 != sizeof(struct ieee80211_tdls_lnkie)) {
     972                 :            :                                 elem_parse_failed = true;
     973                 :            :                                 break;
     974                 :            :                         }
     975                 :          0 :                         elems->lnk_id = (void *)(pos - 2);
     976                 :          0 :                         break;
     977                 :          0 :                 case WLAN_EID_CHAN_SWITCH_TIMING:
     978         [ #  # ]:          0 :                         if (elen != sizeof(struct ieee80211_ch_switch_timing)) {
     979                 :            :                                 elem_parse_failed = true;
     980                 :            :                                 break;
     981                 :            :                         }
     982                 :          0 :                         elems->ch_sw_timing = (void *)pos;
     983                 :          0 :                         break;
     984                 :          0 :                 case WLAN_EID_EXT_CAPABILITY:
     985                 :          0 :                         elems->ext_capab = pos;
     986                 :          0 :                         elems->ext_capab_len = elen;
     987                 :          0 :                         break;
     988                 :          0 :                 case WLAN_EID_SSID:
     989                 :          0 :                         elems->ssid = pos;
     990                 :          0 :                         elems->ssid_len = elen;
     991                 :          0 :                         break;
     992                 :          0 :                 case WLAN_EID_SUPP_RATES:
     993                 :          0 :                         elems->supp_rates = pos;
     994                 :          0 :                         elems->supp_rates_len = elen;
     995                 :          0 :                         break;
     996                 :          0 :                 case WLAN_EID_DS_PARAMS:
     997         [ #  # ]:          0 :                         if (elen >= 1)
     998                 :          0 :                                 elems->ds_params = pos;
     999                 :            :                         else
    1000                 :            :                                 elem_parse_failed = true;
    1001                 :            :                         break;
    1002                 :          0 :                 case WLAN_EID_TIM:
    1003         [ #  # ]:          0 :                         if (elen >= sizeof(struct ieee80211_tim_ie)) {
    1004                 :          0 :                                 elems->tim = (void *)pos;
    1005                 :          0 :                                 elems->tim_len = elen;
    1006                 :            :                         } else
    1007                 :            :                                 elem_parse_failed = true;
    1008                 :            :                         break;
    1009                 :          0 :                 case WLAN_EID_CHALLENGE:
    1010                 :          0 :                         elems->challenge = pos;
    1011                 :          0 :                         elems->challenge_len = elen;
    1012                 :          0 :                         break;
    1013                 :          0 :                 case WLAN_EID_VENDOR_SPECIFIC:
    1014   [ #  #  #  #  :          0 :                         if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
                   #  # ]
    1015         [ #  # ]:          0 :                             pos[2] == 0xf2) {
    1016                 :            :                                 /* Microsoft OUI (00:50:F2) */
    1017                 :            : 
    1018         [ #  # ]:          0 :                                 if (calc_crc)
    1019                 :          0 :                                         crc = crc32_be(crc, pos - 2, elen + 2);
    1020                 :            : 
    1021   [ #  #  #  # ]:          0 :                                 if (elen >= 5 && pos[3] == 2) {
    1022                 :            :                                         /* OUI Type 2 - WMM IE */
    1023         [ #  # ]:          0 :                                         if (pos[4] == 0) {
    1024                 :          0 :                                                 elems->wmm_info = pos;
    1025                 :          0 :                                                 elems->wmm_info_len = elen;
    1026         [ #  # ]:          0 :                                         } else if (pos[4] == 1) {
    1027                 :          0 :                                                 elems->wmm_param = pos;
    1028                 :          0 :                                                 elems->wmm_param_len = elen;
    1029                 :            :                                         }
    1030                 :            :                                 }
    1031                 :            :                         }
    1032                 :            :                         break;
    1033                 :          0 :                 case WLAN_EID_RSN:
    1034                 :          0 :                         elems->rsn = pos;
    1035                 :          0 :                         elems->rsn_len = elen;
    1036                 :          0 :                         break;
    1037                 :          0 :                 case WLAN_EID_ERP_INFO:
    1038         [ #  # ]:          0 :                         if (elen >= 1)
    1039                 :          0 :                                 elems->erp_info = pos;
    1040                 :            :                         else
    1041                 :            :                                 elem_parse_failed = true;
    1042                 :            :                         break;
    1043                 :          0 :                 case WLAN_EID_EXT_SUPP_RATES:
    1044                 :          0 :                         elems->ext_supp_rates = pos;
    1045                 :          0 :                         elems->ext_supp_rates_len = elen;
    1046                 :          0 :                         break;
    1047                 :          0 :                 case WLAN_EID_HT_CAPABILITY:
    1048         [ #  # ]:          0 :                         if (elen >= sizeof(struct ieee80211_ht_cap))
    1049                 :          0 :                                 elems->ht_cap_elem = (void *)pos;
    1050                 :            :                         else
    1051                 :            :                                 elem_parse_failed = true;
    1052                 :            :                         break;
    1053                 :          0 :                 case WLAN_EID_HT_OPERATION:
    1054         [ #  # ]:          0 :                         if (elen >= sizeof(struct ieee80211_ht_operation))
    1055                 :          0 :                                 elems->ht_operation = (void *)pos;
    1056                 :            :                         else
    1057                 :            :                                 elem_parse_failed = true;
    1058                 :            :                         break;
    1059                 :          0 :                 case WLAN_EID_VHT_CAPABILITY:
    1060         [ #  # ]:          0 :                         if (elen >= sizeof(struct ieee80211_vht_cap))
    1061                 :          0 :                                 elems->vht_cap_elem = (void *)pos;
    1062                 :            :                         else
    1063                 :            :                                 elem_parse_failed = true;
    1064                 :            :                         break;
    1065                 :          0 :                 case WLAN_EID_VHT_OPERATION:
    1066         [ #  # ]:          0 :                         if (elen >= sizeof(struct ieee80211_vht_operation)) {
    1067                 :          0 :                                 elems->vht_operation = (void *)pos;
    1068         [ #  # ]:          0 :                                 if (calc_crc)
    1069                 :          0 :                                         crc = crc32_be(crc, pos - 2, elen + 2);
    1070                 :            :                                 break;
    1071                 :            :                         }
    1072                 :            :                         elem_parse_failed = true;
    1073                 :            :                         break;
    1074                 :          0 :                 case WLAN_EID_OPMODE_NOTIF:
    1075         [ #  # ]:          0 :                         if (elen > 0) {
    1076                 :          0 :                                 elems->opmode_notif = pos;
    1077         [ #  # ]:          0 :                                 if (calc_crc)
    1078                 :          0 :                                         crc = crc32_be(crc, pos - 2, elen + 2);
    1079                 :            :                                 break;
    1080                 :            :                         }
    1081                 :            :                         elem_parse_failed = true;
    1082                 :            :                         break;
    1083                 :          0 :                 case WLAN_EID_MESH_ID:
    1084                 :          0 :                         elems->mesh_id = pos;
    1085                 :          0 :                         elems->mesh_id_len = elen;
    1086                 :          0 :                         break;
    1087                 :          0 :                 case WLAN_EID_MESH_CONFIG:
    1088         [ #  # ]:          0 :                         if (elen >= sizeof(struct ieee80211_meshconf_ie))
    1089                 :          0 :                                 elems->mesh_config = (void *)pos;
    1090                 :            :                         else
    1091                 :            :                                 elem_parse_failed = true;
    1092                 :            :                         break;
    1093                 :          0 :                 case WLAN_EID_PEER_MGMT:
    1094                 :          0 :                         elems->peering = pos;
    1095                 :          0 :                         elems->peering_len = elen;
    1096                 :          0 :                         break;
    1097                 :          0 :                 case WLAN_EID_MESH_AWAKE_WINDOW:
    1098         [ #  # ]:          0 :                         if (elen >= 2)
    1099                 :          0 :                                 elems->awake_window = (void *)pos;
    1100                 :            :                         break;
    1101                 :          0 :                 case WLAN_EID_PREQ:
    1102                 :          0 :                         elems->preq = pos;
    1103                 :          0 :                         elems->preq_len = elen;
    1104                 :          0 :                         break;
    1105                 :          0 :                 case WLAN_EID_PREP:
    1106                 :          0 :                         elems->prep = pos;
    1107                 :          0 :                         elems->prep_len = elen;
    1108                 :          0 :                         break;
    1109                 :          0 :                 case WLAN_EID_PERR:
    1110                 :          0 :                         elems->perr = pos;
    1111                 :          0 :                         elems->perr_len = elen;
    1112                 :          0 :                         break;
    1113                 :          0 :                 case WLAN_EID_RANN:
    1114         [ #  # ]:          0 :                         if (elen >= sizeof(struct ieee80211_rann_ie))
    1115                 :          0 :                                 elems->rann = (void *)pos;
    1116                 :            :                         else
    1117                 :            :                                 elem_parse_failed = true;
    1118                 :            :                         break;
    1119                 :          0 :                 case WLAN_EID_CHANNEL_SWITCH:
    1120         [ #  # ]:          0 :                         if (elen != sizeof(struct ieee80211_channel_sw_ie)) {
    1121                 :            :                                 elem_parse_failed = true;
    1122                 :            :                                 break;
    1123                 :            :                         }
    1124                 :          0 :                         elems->ch_switch_ie = (void *)pos;
    1125                 :          0 :                         break;
    1126                 :          0 :                 case WLAN_EID_EXT_CHANSWITCH_ANN:
    1127         [ #  # ]:          0 :                         if (elen != sizeof(struct ieee80211_ext_chansw_ie)) {
    1128                 :            :                                 elem_parse_failed = true;
    1129                 :            :                                 break;
    1130                 :            :                         }
    1131                 :          0 :                         elems->ext_chansw_ie = (void *)pos;
    1132                 :          0 :                         break;
    1133                 :          0 :                 case WLAN_EID_SECONDARY_CHANNEL_OFFSET:
    1134         [ #  # ]:          0 :                         if (elen != sizeof(struct ieee80211_sec_chan_offs_ie)) {
    1135                 :            :                                 elem_parse_failed = true;
    1136                 :            :                                 break;
    1137                 :            :                         }
    1138                 :          0 :                         elems->sec_chan_offs = (void *)pos;
    1139                 :          0 :                         break;
    1140                 :          0 :                 case WLAN_EID_CHAN_SWITCH_PARAM:
    1141         [ #  # ]:          0 :                         if (elen !=
    1142                 :            :                             sizeof(*elems->mesh_chansw_params_ie)) {
    1143                 :            :                                 elem_parse_failed = true;
    1144                 :            :                                 break;
    1145                 :            :                         }
    1146                 :          0 :                         elems->mesh_chansw_params_ie = (void *)pos;
    1147                 :          0 :                         break;
    1148                 :          0 :                 case WLAN_EID_WIDE_BW_CHANNEL_SWITCH:
    1149                 :          0 :                         if (!action ||
    1150         [ #  # ]:          0 :                             elen != sizeof(*elems->wide_bw_chansw_ie)) {
    1151                 :            :                                 elem_parse_failed = true;
    1152                 :            :                                 break;
    1153                 :            :                         }
    1154                 :          0 :                         elems->wide_bw_chansw_ie = (void *)pos;
    1155                 :          0 :                         break;
    1156                 :          0 :                 case WLAN_EID_CHANNEL_SWITCH_WRAPPER:
    1157         [ #  # ]:          0 :                         if (action) {
    1158                 :            :                                 elem_parse_failed = true;
    1159                 :            :                                 break;
    1160                 :            :                         }
    1161                 :            :                         /*
    1162                 :            :                          * This is a bit tricky, but as we only care about
    1163                 :            :                          * the wide bandwidth channel switch element, so
    1164                 :            :                          * just parse it out manually.
    1165                 :            :                          */
    1166                 :          0 :                         ie = cfg80211_find_ie(WLAN_EID_WIDE_BW_CHANNEL_SWITCH,
    1167                 :            :                                               pos, elen);
    1168         [ #  # ]:          0 :                         if (ie) {
    1169         [ #  # ]:          0 :                                 if (ie[1] == sizeof(*elems->wide_bw_chansw_ie))
    1170                 :          0 :                                         elems->wide_bw_chansw_ie =
    1171                 :          0 :                                                 (void *)(ie + 2);
    1172                 :            :                                 else
    1173                 :            :                                         elem_parse_failed = true;
    1174                 :            :                         }
    1175                 :            :                         break;
    1176                 :          0 :                 case WLAN_EID_COUNTRY:
    1177                 :          0 :                         elems->country_elem = pos;
    1178                 :          0 :                         elems->country_elem_len = elen;
    1179                 :          0 :                         break;
    1180                 :          0 :                 case WLAN_EID_PWR_CONSTRAINT:
    1181         [ #  # ]:          0 :                         if (elen != 1) {
    1182                 :            :                                 elem_parse_failed = true;
    1183                 :            :                                 break;
    1184                 :            :                         }
    1185                 :          0 :                         elems->pwr_constr_elem = pos;
    1186                 :          0 :                         break;
    1187                 :          0 :                 case WLAN_EID_CISCO_VENDOR_SPECIFIC:
    1188                 :            :                         /* Lots of different options exist, but we only care
    1189                 :            :                          * about the Dynamic Transmit Power Control element.
    1190                 :            :                          * First check for the Cisco OUI, then for the DTPC
    1191                 :            :                          * tag (0x00).
    1192                 :            :                          */
    1193         [ #  # ]:          0 :                         if (elen < 4) {
    1194                 :            :                                 elem_parse_failed = true;
    1195                 :            :                                 break;
    1196                 :            :                         }
    1197                 :            : 
    1198   [ #  #  #  # ]:          0 :                         if (pos[0] != 0x00 || pos[1] != 0x40 ||
    1199   [ #  #  #  # ]:          0 :                             pos[2] != 0x96 || pos[3] != 0x00)
    1200                 :            :                                 break;
    1201                 :            : 
    1202         [ #  # ]:          0 :                         if (elen != 6) {
    1203                 :            :                                 elem_parse_failed = true;
    1204                 :            :                                 break;
    1205                 :            :                         }
    1206                 :            : 
    1207         [ #  # ]:          0 :                         if (calc_crc)
    1208                 :          0 :                                 crc = crc32_be(crc, pos - 2, elen + 2);
    1209                 :            : 
    1210                 :          0 :                         elems->cisco_dtpc_elem = pos;
    1211                 :          0 :                         break;
    1212                 :          0 :                 case WLAN_EID_ADDBA_EXT:
    1213         [ #  # ]:          0 :                         if (elen != sizeof(struct ieee80211_addba_ext_ie)) {
    1214                 :            :                                 elem_parse_failed = true;
    1215                 :            :                                 break;
    1216                 :            :                         }
    1217                 :          0 :                         elems->addba_ext_ie = (void *)pos;
    1218                 :          0 :                         break;
    1219                 :          0 :                 case WLAN_EID_TIMEOUT_INTERVAL:
    1220         [ #  # ]:          0 :                         if (elen >= sizeof(struct ieee80211_timeout_interval_ie))
    1221                 :          0 :                                 elems->timeout_int = (void *)pos;
    1222                 :            :                         else
    1223                 :            :                                 elem_parse_failed = true;
    1224                 :            :                         break;
    1225                 :          0 :                 case WLAN_EID_BSS_MAX_IDLE_PERIOD:
    1226         [ #  # ]:          0 :                         if (elen >= sizeof(*elems->max_idle_period_ie))
    1227                 :          0 :                                 elems->max_idle_period_ie = (void *)pos;
    1228                 :            :                         break;
    1229                 :          0 :                 case WLAN_EID_EXTENSION:
    1230   [ #  #  #  # ]:          0 :                         if (pos[0] == WLAN_EID_EXT_HE_MU_EDCA &&
    1231                 :            :                             elen >= (sizeof(*elems->mu_edca_param_set) + 1)) {
    1232                 :          0 :                                 elems->mu_edca_param_set = (void *)&pos[1];
    1233         [ #  # ]:          0 :                                 if (calc_crc)
    1234                 :          0 :                                         crc = crc32_be(crc, pos - 2, elen + 2);
    1235         [ #  # ]:          0 :                         } else if (pos[0] == WLAN_EID_EXT_HE_CAPABILITY) {
    1236                 :          0 :                                 elems->he_cap = (void *)&pos[1];
    1237                 :          0 :                                 elems->he_cap_len = elen - 1;
    1238   [ #  #  #  # ]:          0 :                         } else if (pos[0] == WLAN_EID_EXT_HE_OPERATION &&
    1239         [ #  # ]:          0 :                                    elen >= sizeof(*elems->he_operation) &&
    1240         [ #  # ]:          0 :                                    elen >= ieee80211_he_oper_size(&pos[1])) {
    1241                 :          0 :                                 elems->he_operation = (void *)&pos[1];
    1242   [ #  #  #  # ]:          0 :                         } else if (pos[0] == WLAN_EID_EXT_UORA && elen >= 1) {
    1243                 :          0 :                                 elems->uora_element = (void *)&pos[1];
    1244         [ #  # ]:          0 :                         } else if (pos[0] ==
    1245         [ #  # ]:          0 :                                    WLAN_EID_EXT_MAX_CHANNEL_SWITCH_TIME &&
    1246                 :            :                                    elen == 4) {
    1247                 :          0 :                                 elems->max_channel_switch_time = pos + 1;
    1248         [ #  # ]:          0 :                         } else if (pos[0] ==
    1249         [ #  # ]:          0 :                                    WLAN_EID_EXT_MULTIPLE_BSSID_CONFIGURATION &&
    1250                 :            :                                    elen == 3) {
    1251                 :          0 :                                 elems->mbssid_config_ie = (void *)&pos[1];
    1252   [ #  #  #  # ]:          0 :                         } else if (pos[0] == WLAN_EID_EXT_HE_SPR &&
    1253         [ #  # ]:          0 :                                    elen >= sizeof(*elems->he_spr) &&
    1254         [ #  # ]:          0 :                                    elen >= ieee80211_he_spr_size(&pos[1])) {
    1255                 :          0 :                                 elems->he_spr = (void *)&pos[1];
    1256                 :            :                         }
    1257                 :            :                         break;
    1258                 :            :                 default:
    1259                 :            :                         break;
    1260                 :            :                 }
    1261                 :            : 
    1262         [ #  # ]:          0 :                 if (elem_parse_failed)
    1263                 :          0 :                         elems->parse_error = true;
    1264                 :            :                 else
    1265                 :          0 :                         __set_bit(id, seen_elems);
    1266                 :            :         }
    1267                 :            : 
    1268         [ #  # ]:          0 :         if (!for_each_element_completed(elem, start, len))
    1269                 :          0 :                 elems->parse_error = true;
    1270                 :            : 
    1271                 :          0 :         return crc;
    1272                 :            : }
    1273                 :            : 
    1274                 :            : static size_t ieee802_11_find_bssid_profile(const u8 *start, size_t len,
    1275                 :            :                                             struct ieee802_11_elems *elems,
    1276                 :            :                                             u8 *transmitter_bssid,
    1277                 :            :                                             u8 *bss_bssid,
    1278                 :            :                                             u8 *nontransmitted_profile)
    1279                 :            : {
    1280                 :            :         const struct element *elem, *sub;
    1281                 :            :         size_t profile_len = 0;
    1282                 :            :         bool found = false;
    1283                 :            : 
    1284                 :            :         if (!bss_bssid || !transmitter_bssid)
    1285                 :            :                 return profile_len;
    1286                 :            : 
    1287                 :            :         for_each_element_id(elem, WLAN_EID_MULTIPLE_BSSID, start, len) {
    1288                 :            :                 if (elem->datalen < 2)
    1289                 :            :                         continue;
    1290                 :            : 
    1291                 :            :                 for_each_element(sub, elem->data + 1, elem->datalen - 1) {
    1292                 :            :                         u8 new_bssid[ETH_ALEN];
    1293                 :            :                         const u8 *index;
    1294                 :            : 
    1295                 :            :                         if (sub->id != 0 || sub->datalen < 4) {
    1296                 :            :                                 /* not a valid BSS profile */
    1297                 :            :                                 continue;
    1298                 :            :                         }
    1299                 :            : 
    1300                 :            :                         if (sub->data[0] != WLAN_EID_NON_TX_BSSID_CAP ||
    1301                 :            :                             sub->data[1] != 2) {
    1302                 :            :                                 /* The first element of the
    1303                 :            :                                  * Nontransmitted BSSID Profile is not
    1304                 :            :                                  * the Nontransmitted BSSID Capability
    1305                 :            :                                  * element.
    1306                 :            :                                  */
    1307                 :            :                                 continue;
    1308                 :            :                         }
    1309                 :            : 
    1310                 :            :                         memset(nontransmitted_profile, 0, len);
    1311                 :            :                         profile_len = cfg80211_merge_profile(start, len,
    1312                 :            :                                                              elem,
    1313                 :            :                                                              sub,
    1314                 :            :                                                              nontransmitted_profile,
    1315                 :            :                                                              len);
    1316                 :            : 
    1317                 :            :                         /* found a Nontransmitted BSSID Profile */
    1318                 :            :                         index = cfg80211_find_ie(WLAN_EID_MULTI_BSSID_IDX,
    1319                 :            :                                                  nontransmitted_profile,
    1320                 :            :                                                  profile_len);
    1321                 :            :                         if (!index || index[1] < 1 || index[2] == 0) {
    1322                 :            :                                 /* Invalid MBSSID Index element */
    1323                 :            :                                 continue;
    1324                 :            :                         }
    1325                 :            : 
    1326                 :            :                         cfg80211_gen_new_bssid(transmitter_bssid,
    1327                 :            :                                                elem->data[0],
    1328                 :            :                                                index[2],
    1329                 :            :                                                new_bssid);
    1330                 :            :                         if (ether_addr_equal(new_bssid, bss_bssid)) {
    1331                 :            :                                 found = true;
    1332                 :            :                                 elems->bssid_index_len = index[1];
    1333                 :            :                                 elems->bssid_index = (void *)&index[2];
    1334                 :            :                                 break;
    1335                 :            :                         }
    1336                 :            :                 }
    1337                 :            :         }
    1338                 :            : 
    1339                 :            :         return found ? profile_len : 0;
    1340                 :            : }
    1341                 :            : 
    1342                 :          0 : u32 ieee802_11_parse_elems_crc(const u8 *start, size_t len, bool action,
    1343                 :            :                                struct ieee802_11_elems *elems,
    1344                 :            :                                u64 filter, u32 crc, u8 *transmitter_bssid,
    1345                 :            :                                u8 *bss_bssid)
    1346                 :            : {
    1347                 :          0 :         const struct element *non_inherit = NULL;
    1348                 :          0 :         u8 *nontransmitted_profile;
    1349                 :          0 :         int nontransmitted_profile_len = 0;
    1350                 :            : 
    1351                 :          0 :         memset(elems, 0, sizeof(*elems));
    1352                 :          0 :         elems->ie_start = start;
    1353                 :          0 :         elems->total_len = len;
    1354                 :            : 
    1355         [ #  # ]:          0 :         nontransmitted_profile = kmalloc(len, GFP_ATOMIC);
    1356         [ #  # ]:          0 :         if (nontransmitted_profile) {
    1357                 :          0 :                 nontransmitted_profile_len =
    1358                 :          0 :                         ieee802_11_find_bssid_profile(start, len, elems,
    1359                 :            :                                                       transmitter_bssid,
    1360                 :            :                                                       bss_bssid,
    1361                 :            :                                                       nontransmitted_profile);
    1362                 :          0 :                 non_inherit =
    1363                 :          0 :                         cfg80211_find_ext_elem(WLAN_EID_EXT_NON_INHERITANCE,
    1364                 :            :                                                nontransmitted_profile,
    1365                 :            :                                                nontransmitted_profile_len);
    1366                 :            :         }
    1367                 :            : 
    1368                 :          0 :         crc = _ieee802_11_parse_elems_crc(start, len, action, elems, filter,
    1369                 :            :                                           crc, non_inherit);
    1370                 :            : 
    1371                 :            :         /* Override with nontransmitted profile, if found */
    1372         [ #  # ]:          0 :         if (nontransmitted_profile_len)
    1373                 :          0 :                 _ieee802_11_parse_elems_crc(nontransmitted_profile,
    1374                 :            :                                             nontransmitted_profile_len,
    1375                 :            :                                             action, elems, 0, 0, NULL);
    1376                 :            : 
    1377   [ #  #  #  # ]:          0 :         if (elems->tim && !elems->parse_error) {
    1378                 :          0 :                 const struct ieee80211_tim_ie *tim_ie = elems->tim;
    1379                 :            : 
    1380                 :          0 :                 elems->dtim_period = tim_ie->dtim_period;
    1381                 :          0 :                 elems->dtim_count = tim_ie->dtim_count;
    1382                 :            :         }
    1383                 :            : 
    1384                 :            :         /* Override DTIM period and count if needed */
    1385         [ #  # ]:          0 :         if (elems->bssid_index &&
    1386         [ #  # ]:          0 :             elems->bssid_index_len >=
    1387                 :            :             offsetofend(struct ieee80211_bssid_index, dtim_period))
    1388                 :          0 :                 elems->dtim_period = elems->bssid_index->dtim_period;
    1389                 :            : 
    1390         [ #  # ]:          0 :         if (elems->bssid_index &&
    1391         [ #  # ]:          0 :             elems->bssid_index_len >=
    1392                 :            :             offsetofend(struct ieee80211_bssid_index, dtim_count))
    1393                 :          0 :                 elems->dtim_count = elems->bssid_index->dtim_count;
    1394                 :            : 
    1395                 :          0 :         kfree(nontransmitted_profile);
    1396                 :            : 
    1397                 :          0 :         return crc;
    1398                 :            : }
    1399                 :            : 
    1400                 :         24 : void ieee80211_regulatory_limit_wmm_params(struct ieee80211_sub_if_data *sdata,
    1401                 :            :                                            struct ieee80211_tx_queue_params
    1402                 :            :                                            *qparam, int ac)
    1403                 :            : {
    1404                 :         24 :         struct ieee80211_chanctx_conf *chanctx_conf;
    1405                 :         24 :         const struct ieee80211_reg_rule *rrule;
    1406                 :         24 :         const struct ieee80211_wmm_ac *wmm_ac;
    1407                 :         24 :         u16 center_freq = 0;
    1408                 :            : 
    1409         [ +  - ]:         24 :         if (sdata->vif.type != NL80211_IFTYPE_AP &&
    1410                 :            :             sdata->vif.type != NL80211_IFTYPE_STATION)
    1411                 :            :                 return;
    1412                 :            : 
    1413                 :         24 :         rcu_read_lock();
    1414         [ -  + ]:         24 :         chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
    1415         [ -  + ]:         24 :         if (chanctx_conf)
    1416                 :          0 :                 center_freq = chanctx_conf->def.chan->center_freq;
    1417                 :            : 
    1418         [ #  # ]:          0 :         if (!center_freq) {
    1419                 :         24 :                 rcu_read_unlock();
    1420                 :         24 :                 return;
    1421                 :            :         }
    1422                 :            : 
    1423                 :          0 :         rrule = freq_reg_info(sdata->wdev.wiphy, MHZ_TO_KHZ(center_freq));
    1424                 :            : 
    1425   [ #  #  #  #  :          0 :         if (IS_ERR_OR_NULL(rrule) || !rrule->has_wmm) {
                   #  # ]
    1426                 :          0 :                 rcu_read_unlock();
    1427                 :          0 :                 return;
    1428                 :            :         }
    1429                 :            : 
    1430         [ #  # ]:          0 :         if (sdata->vif.type == NL80211_IFTYPE_AP)
    1431                 :          0 :                 wmm_ac = &rrule->wmm_rule.ap[ac];
    1432                 :            :         else
    1433                 :          0 :                 wmm_ac = &rrule->wmm_rule.client[ac];
    1434                 :          0 :         qparam->cw_min = max_t(u16, qparam->cw_min, wmm_ac->cw_min);
    1435                 :          0 :         qparam->cw_max = max_t(u16, qparam->cw_max, wmm_ac->cw_max);
    1436                 :          0 :         qparam->aifs = max_t(u8, qparam->aifs, wmm_ac->aifsn);
    1437                 :          0 :         qparam->txop = min_t(u16, qparam->txop, wmm_ac->cot / 32);
    1438                 :          0 :         rcu_read_unlock();
    1439                 :            : }
    1440                 :            : 
    1441                 :          6 : void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata,
    1442                 :            :                                bool bss_notify, bool enable_qos)
    1443                 :            : {
    1444                 :          6 :         struct ieee80211_local *local = sdata->local;
    1445                 :          6 :         struct ieee80211_tx_queue_params qparam;
    1446                 :          6 :         struct ieee80211_chanctx_conf *chanctx_conf;
    1447                 :          6 :         int ac;
    1448                 :          6 :         bool use_11b;
    1449                 :          6 :         bool is_ocb; /* Use another EDCA parameters if dot11OCBActivated=true */
    1450                 :          6 :         int aCWmin, aCWmax;
    1451                 :            : 
    1452         [ +  - ]:          6 :         if (!local->ops->conf_tx)
    1453                 :          0 :                 return;
    1454                 :            : 
    1455         [ +  - ]:          6 :         if (local->hw.queues < IEEE80211_NUM_ACS)
    1456                 :            :                 return;
    1457                 :            : 
    1458                 :          6 :         memset(&qparam, 0, sizeof(qparam));
    1459                 :            : 
    1460                 :          6 :         rcu_read_lock();
    1461         [ -  + ]:          6 :         chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
    1462                 :         12 :         use_11b = (chanctx_conf &&
    1463   [ -  +  -  - ]:          6 :                    chanctx_conf->def.chan->band == NL80211_BAND_2GHZ) &&
    1464         [ #  # ]:          0 :                  !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE);
    1465                 :          6 :         rcu_read_unlock();
    1466                 :            : 
    1467                 :          6 :         is_ocb = (sdata->vif.type == NL80211_IFTYPE_OCB);
    1468                 :            : 
    1469                 :            :         /* Set defaults according to 802.11-2007 Table 7-37 */
    1470                 :          6 :         aCWmax = 1023;
    1471         [ +  - ]:          6 :         if (use_11b)
    1472                 :            :                 aCWmin = 31;
    1473                 :            :         else
    1474                 :          6 :                 aCWmin = 15;
    1475                 :            : 
    1476                 :            :         /* Confiure old 802.11b/g medium access rules. */
    1477                 :          6 :         qparam.cw_max = aCWmax;
    1478                 :          6 :         qparam.cw_min = aCWmin;
    1479                 :          6 :         qparam.txop = 0;
    1480                 :          6 :         qparam.aifs = 2;
    1481                 :            : 
    1482         [ +  + ]:         30 :         for (ac = 0; ac < IEEE80211_NUM_ACS; ac++) {
    1483                 :            :                 /* Update if QoS is enabled. */
    1484         [ +  - ]:         24 :                 if (enable_qos) {
    1485   [ #  #  #  # ]:          0 :                         switch (ac) {
    1486                 :          0 :                         case IEEE80211_AC_BK:
    1487                 :          0 :                                 qparam.cw_max = aCWmax;
    1488                 :          0 :                                 qparam.cw_min = aCWmin;
    1489                 :          0 :                                 qparam.txop = 0;
    1490         [ #  # ]:          0 :                                 if (is_ocb)
    1491                 :          0 :                                         qparam.aifs = 9;
    1492                 :            :                                 else
    1493                 :          0 :                                         qparam.aifs = 7;
    1494                 :            :                                 break;
    1495                 :            :                         /* never happens but let's not leave undefined */
    1496                 :          0 :                         default:
    1497                 :            :                         case IEEE80211_AC_BE:
    1498                 :          0 :                                 qparam.cw_max = aCWmax;
    1499                 :          0 :                                 qparam.cw_min = aCWmin;
    1500                 :          0 :                                 qparam.txop = 0;
    1501         [ #  # ]:          0 :                                 if (is_ocb)
    1502                 :          0 :                                         qparam.aifs = 6;
    1503                 :            :                                 else
    1504                 :          0 :                                         qparam.aifs = 3;
    1505                 :            :                                 break;
    1506                 :          0 :                         case IEEE80211_AC_VI:
    1507                 :          0 :                                 qparam.cw_max = aCWmin;
    1508                 :          0 :                                 qparam.cw_min = (aCWmin + 1) / 2 - 1;
    1509         [ #  # ]:          0 :                                 if (is_ocb)
    1510                 :          0 :                                         qparam.txop = 0;
    1511         [ #  # ]:          0 :                                 else if (use_11b)
    1512                 :          0 :                                         qparam.txop = 6016/32;
    1513                 :            :                                 else
    1514                 :          0 :                                         qparam.txop = 3008/32;
    1515                 :            : 
    1516         [ #  # ]:          0 :                                 if (is_ocb)
    1517                 :          0 :                                         qparam.aifs = 3;
    1518                 :            :                                 else
    1519                 :          0 :                                         qparam.aifs = 2;
    1520                 :            :                                 break;
    1521                 :          0 :                         case IEEE80211_AC_VO:
    1522                 :          0 :                                 qparam.cw_max = (aCWmin + 1) / 2 - 1;
    1523                 :          0 :                                 qparam.cw_min = (aCWmin + 1) / 4 - 1;
    1524         [ #  # ]:          0 :                                 if (is_ocb)
    1525                 :          0 :                                         qparam.txop = 0;
    1526         [ #  # ]:          0 :                                 else if (use_11b)
    1527                 :          0 :                                         qparam.txop = 3264/32;
    1528                 :            :                                 else
    1529                 :          0 :                                         qparam.txop = 1504/32;
    1530                 :          0 :                                 qparam.aifs = 2;
    1531                 :          0 :                                 break;
    1532                 :            :                         }
    1533                 :         24 :                 }
    1534                 :         24 :                 ieee80211_regulatory_limit_wmm_params(sdata, &qparam, ac);
    1535                 :            : 
    1536                 :         24 :                 qparam.uapsd = false;
    1537                 :            : 
    1538                 :         24 :                 sdata->tx_conf[ac] = qparam;
    1539                 :         24 :                 drv_conf_tx(local, sdata, ac, &qparam);
    1540                 :            :         }
    1541                 :            : 
    1542         [ +  - ]:          6 :         if (sdata->vif.type != NL80211_IFTYPE_MONITOR &&
    1543         [ +  - ]:          6 :             sdata->vif.type != NL80211_IFTYPE_P2P_DEVICE &&
    1544                 :            :             sdata->vif.type != NL80211_IFTYPE_NAN) {
    1545                 :          6 :                 sdata->vif.bss_conf.qos = enable_qos;
    1546         [ +  - ]:          6 :                 if (bss_notify)
    1547                 :          6 :                         ieee80211_bss_info_change_notify(sdata,
    1548                 :            :                                                          BSS_CHANGED_QOS);
    1549                 :            :         }
    1550                 :            : }
    1551                 :            : 
    1552                 :          0 : void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
    1553                 :            :                          u16 transaction, u16 auth_alg, u16 status,
    1554                 :            :                          const u8 *extra, size_t extra_len, const u8 *da,
    1555                 :            :                          const u8 *bssid, const u8 *key, u8 key_len, u8 key_idx,
    1556                 :            :                          u32 tx_flags)
    1557                 :            : {
    1558                 :          0 :         struct ieee80211_local *local = sdata->local;
    1559                 :          0 :         struct sk_buff *skb;
    1560                 :          0 :         struct ieee80211_mgmt *mgmt;
    1561                 :          0 :         int err;
    1562                 :            : 
    1563                 :            :         /* 24 + 6 = header + auth_algo + auth_transaction + status_code */
    1564                 :          0 :         skb = dev_alloc_skb(local->hw.extra_tx_headroom + IEEE80211_WEP_IV_LEN +
    1565                 :          0 :                             24 + 6 + extra_len + IEEE80211_WEP_ICV_LEN);
    1566         [ #  # ]:          0 :         if (!skb)
    1567                 :            :                 return;
    1568                 :            : 
    1569                 :          0 :         skb_reserve(skb, local->hw.extra_tx_headroom + IEEE80211_WEP_IV_LEN);
    1570                 :            : 
    1571                 :          0 :         mgmt = skb_put_zero(skb, 24 + 6);
    1572                 :          0 :         mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
    1573                 :            :                                           IEEE80211_STYPE_AUTH);
    1574                 :          0 :         memcpy(mgmt->da, da, ETH_ALEN);
    1575                 :          0 :         memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
    1576                 :          0 :         memcpy(mgmt->bssid, bssid, ETH_ALEN);
    1577                 :          0 :         mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg);
    1578                 :          0 :         mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
    1579                 :          0 :         mgmt->u.auth.status_code = cpu_to_le16(status);
    1580         [ #  # ]:          0 :         if (extra)
    1581                 :          0 :                 skb_put_data(skb, extra, extra_len);
    1582                 :            : 
    1583         [ #  # ]:          0 :         if (auth_alg == WLAN_AUTH_SHARED_KEY && transaction == 3) {
    1584                 :          0 :                 mgmt->frame_control |= cpu_to_le16(IEEE80211_FCTL_PROTECTED);
    1585                 :          0 :                 err = ieee80211_wep_encrypt(local, skb, key, key_len, key_idx);
    1586         [ #  # ]:          0 :                 WARN_ON(err);
    1587                 :            :         }
    1588                 :            : 
    1589                 :          0 :         IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT |
    1590                 :            :                                         tx_flags;
    1591                 :          0 :         ieee80211_tx_skb(sdata, skb);
    1592                 :            : }
    1593                 :            : 
    1594                 :          0 : void ieee80211_send_deauth_disassoc(struct ieee80211_sub_if_data *sdata,
    1595                 :            :                                     const u8 *da, const u8 *bssid,
    1596                 :            :                                     u16 stype, u16 reason,
    1597                 :            :                                     bool send_frame, u8 *frame_buf)
    1598                 :            : {
    1599                 :          0 :         struct ieee80211_local *local = sdata->local;
    1600                 :          0 :         struct sk_buff *skb;
    1601                 :          0 :         struct ieee80211_mgmt *mgmt = (void *)frame_buf;
    1602                 :            : 
    1603                 :            :         /* build frame */
    1604                 :          0 :         mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | stype);
    1605                 :          0 :         mgmt->duration = 0; /* initialize only */
    1606                 :          0 :         mgmt->seq_ctrl = 0; /* initialize only */
    1607                 :          0 :         memcpy(mgmt->da, da, ETH_ALEN);
    1608                 :          0 :         memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
    1609                 :          0 :         memcpy(mgmt->bssid, bssid, ETH_ALEN);
    1610                 :            :         /* u.deauth.reason_code == u.disassoc.reason_code */
    1611                 :          0 :         mgmt->u.deauth.reason_code = cpu_to_le16(reason);
    1612                 :            : 
    1613         [ #  # ]:          0 :         if (send_frame) {
    1614                 :          0 :                 skb = dev_alloc_skb(local->hw.extra_tx_headroom +
    1615                 :            :                                     IEEE80211_DEAUTH_FRAME_LEN);
    1616         [ #  # ]:          0 :                 if (!skb)
    1617                 :            :                         return;
    1618                 :            : 
    1619                 :          0 :                 skb_reserve(skb, local->hw.extra_tx_headroom);
    1620                 :            : 
    1621                 :            :                 /* copy in frame */
    1622                 :          0 :                 skb_put_data(skb, mgmt, IEEE80211_DEAUTH_FRAME_LEN);
    1623                 :            : 
    1624         [ #  # ]:          0 :                 if (sdata->vif.type != NL80211_IFTYPE_STATION ||
    1625         [ #  # ]:          0 :                     !(sdata->u.mgd.flags & IEEE80211_STA_MFP_ENABLED))
    1626                 :          0 :                         IEEE80211_SKB_CB(skb)->flags |=
    1627                 :            :                                 IEEE80211_TX_INTFL_DONT_ENCRYPT;
    1628                 :            : 
    1629                 :          0 :                 ieee80211_tx_skb(sdata, skb);
    1630                 :            :         }
    1631                 :            : }
    1632                 :            : 
    1633                 :            : static int ieee80211_build_preq_ies_band(struct ieee80211_local *local,
    1634                 :            :                                          u8 *buffer, size_t buffer_len,
    1635                 :            :                                          const u8 *ie, size_t ie_len,
    1636                 :            :                                          enum nl80211_band band,
    1637                 :            :                                          u32 rate_mask,
    1638                 :            :                                          struct cfg80211_chan_def *chandef,
    1639                 :            :                                          size_t *offset, u32 flags)
    1640                 :            : {
    1641                 :            :         struct ieee80211_supported_band *sband;
    1642                 :            :         const struct ieee80211_sta_he_cap *he_cap;
    1643                 :            :         u8 *pos = buffer, *end = buffer + buffer_len;
    1644                 :            :         size_t noffset;
    1645                 :            :         int supp_rates_len, i;
    1646                 :            :         u8 rates[32];
    1647                 :            :         int num_rates;
    1648                 :            :         int ext_rates_len;
    1649                 :            :         int shift;
    1650                 :            :         u32 rate_flags;
    1651                 :            :         bool have_80mhz = false;
    1652                 :            : 
    1653                 :            :         *offset = 0;
    1654                 :            : 
    1655                 :            :         sband = local->hw.wiphy->bands[band];
    1656                 :            :         if (WARN_ON_ONCE(!sband))
    1657                 :            :                 return 0;
    1658                 :            : 
    1659                 :            :         rate_flags = ieee80211_chandef_rate_flags(chandef);
    1660                 :            :         shift = ieee80211_chandef_get_shift(chandef);
    1661                 :            : 
    1662                 :            :         num_rates = 0;
    1663                 :            :         for (i = 0; i < sband->n_bitrates; i++) {
    1664                 :            :                 if ((BIT(i) & rate_mask) == 0)
    1665                 :            :                         continue; /* skip rate */
    1666                 :            :                 if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
    1667                 :            :                         continue;
    1668                 :            : 
    1669                 :            :                 rates[num_rates++] =
    1670                 :            :                         (u8) DIV_ROUND_UP(sband->bitrates[i].bitrate,
    1671                 :            :                                           (1 << shift) * 5);
    1672                 :            :         }
    1673                 :            : 
    1674                 :            :         supp_rates_len = min_t(int, num_rates, 8);
    1675                 :            : 
    1676                 :            :         if (end - pos < 2 + supp_rates_len)
    1677                 :            :                 goto out_err;
    1678                 :            :         *pos++ = WLAN_EID_SUPP_RATES;
    1679                 :            :         *pos++ = supp_rates_len;
    1680                 :            :         memcpy(pos, rates, supp_rates_len);
    1681                 :            :         pos += supp_rates_len;
    1682                 :            : 
    1683                 :            :         /* insert "request information" if in custom IEs */
    1684                 :            :         if (ie && ie_len) {
    1685                 :            :                 static const u8 before_extrates[] = {
    1686                 :            :                         WLAN_EID_SSID,
    1687                 :            :                         WLAN_EID_SUPP_RATES,
    1688                 :            :                         WLAN_EID_REQUEST,
    1689                 :            :                 };
    1690                 :            :                 noffset = ieee80211_ie_split(ie, ie_len,
    1691                 :            :                                              before_extrates,
    1692                 :            :                                              ARRAY_SIZE(before_extrates),
    1693                 :            :                                              *offset);
    1694                 :            :                 if (end - pos < noffset - *offset)
    1695                 :            :                         goto out_err;
    1696                 :            :                 memcpy(pos, ie + *offset, noffset - *offset);
    1697                 :            :                 pos += noffset - *offset;
    1698                 :            :                 *offset = noffset;
    1699                 :            :         }
    1700                 :            : 
    1701                 :            :         ext_rates_len = num_rates - supp_rates_len;
    1702                 :            :         if (ext_rates_len > 0) {
    1703                 :            :                 if (end - pos < 2 + ext_rates_len)
    1704                 :            :                         goto out_err;
    1705                 :            :                 *pos++ = WLAN_EID_EXT_SUPP_RATES;
    1706                 :            :                 *pos++ = ext_rates_len;
    1707                 :            :                 memcpy(pos, rates + supp_rates_len, ext_rates_len);
    1708                 :            :                 pos += ext_rates_len;
    1709                 :            :         }
    1710                 :            : 
    1711                 :            :         if (chandef->chan && sband->band == NL80211_BAND_2GHZ) {
    1712                 :            :                 if (end - pos < 3)
    1713                 :            :                         goto out_err;
    1714                 :            :                 *pos++ = WLAN_EID_DS_PARAMS;
    1715                 :            :                 *pos++ = 1;
    1716                 :            :                 *pos++ = ieee80211_frequency_to_channel(
    1717                 :            :                                 chandef->chan->center_freq);
    1718                 :            :         }
    1719                 :            : 
    1720                 :            :         if (flags & IEEE80211_PROBE_FLAG_MIN_CONTENT)
    1721                 :            :                 goto done;
    1722                 :            : 
    1723                 :            :         /* insert custom IEs that go before HT */
    1724                 :            :         if (ie && ie_len) {
    1725                 :            :                 static const u8 before_ht[] = {
    1726                 :            :                         /*
    1727                 :            :                          * no need to list the ones split off already
    1728                 :            :                          * (or generated here)
    1729                 :            :                          */
    1730                 :            :                         WLAN_EID_DS_PARAMS,
    1731                 :            :                         WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
    1732                 :            :                 };
    1733                 :            :                 noffset = ieee80211_ie_split(ie, ie_len,
    1734                 :            :                                              before_ht, ARRAY_SIZE(before_ht),
    1735                 :            :                                              *offset);
    1736                 :            :                 if (end - pos < noffset - *offset)
    1737                 :            :                         goto out_err;
    1738                 :            :                 memcpy(pos, ie + *offset, noffset - *offset);
    1739                 :            :                 pos += noffset - *offset;
    1740                 :            :                 *offset = noffset;
    1741                 :            :         }
    1742                 :            : 
    1743                 :            :         if (sband->ht_cap.ht_supported) {
    1744                 :            :                 if (end - pos < 2 + sizeof(struct ieee80211_ht_cap))
    1745                 :            :                         goto out_err;
    1746                 :            :                 pos = ieee80211_ie_build_ht_cap(pos, &sband->ht_cap,
    1747                 :            :                                                 sband->ht_cap.cap);
    1748                 :            :         }
    1749                 :            : 
    1750                 :            :         /* insert custom IEs that go before VHT */
    1751                 :            :         if (ie && ie_len) {
    1752                 :            :                 static const u8 before_vht[] = {
    1753                 :            :                         /*
    1754                 :            :                          * no need to list the ones split off already
    1755                 :            :                          * (or generated here)
    1756                 :            :                          */
    1757                 :            :                         WLAN_EID_BSS_COEX_2040,
    1758                 :            :                         WLAN_EID_EXT_CAPABILITY,
    1759                 :            :                         WLAN_EID_SSID_LIST,
    1760                 :            :                         WLAN_EID_CHANNEL_USAGE,
    1761                 :            :                         WLAN_EID_INTERWORKING,
    1762                 :            :                         WLAN_EID_MESH_ID,
    1763                 :            :                         /* 60 GHz (Multi-band, DMG, MMS) can't happen */
    1764                 :            :                 };
    1765                 :            :                 noffset = ieee80211_ie_split(ie, ie_len,
    1766                 :            :                                              before_vht, ARRAY_SIZE(before_vht),
    1767                 :            :                                              *offset);
    1768                 :            :                 if (end - pos < noffset - *offset)
    1769                 :            :                         goto out_err;
    1770                 :            :                 memcpy(pos, ie + *offset, noffset - *offset);
    1771                 :            :                 pos += noffset - *offset;
    1772                 :            :                 *offset = noffset;
    1773                 :            :         }
    1774                 :            : 
    1775                 :            :         /* Check if any channel in this sband supports at least 80 MHz */
    1776                 :            :         for (i = 0; i < sband->n_channels; i++) {
    1777                 :            :                 if (sband->channels[i].flags & (IEEE80211_CHAN_DISABLED |
    1778                 :            :                                                 IEEE80211_CHAN_NO_80MHZ))
    1779                 :            :                         continue;
    1780                 :            : 
    1781                 :            :                 have_80mhz = true;
    1782                 :            :                 break;
    1783                 :            :         }
    1784                 :            : 
    1785                 :            :         if (sband->vht_cap.vht_supported && have_80mhz) {
    1786                 :            :                 if (end - pos < 2 + sizeof(struct ieee80211_vht_cap))
    1787                 :            :                         goto out_err;
    1788                 :            :                 pos = ieee80211_ie_build_vht_cap(pos, &sband->vht_cap,
    1789                 :            :                                                  sband->vht_cap.cap);
    1790                 :            :         }
    1791                 :            : 
    1792                 :            :         /* insert custom IEs that go before HE */
    1793                 :            :         if (ie && ie_len) {
    1794                 :            :                 static const u8 before_he[] = {
    1795                 :            :                         /*
    1796                 :            :                          * no need to list the ones split off before VHT
    1797                 :            :                          * or generated here
    1798                 :            :                          */
    1799                 :            :                         WLAN_EID_EXTENSION, WLAN_EID_EXT_FILS_REQ_PARAMS,
    1800                 :            :                         WLAN_EID_AP_CSN,
    1801                 :            :                         /* TODO: add 11ah/11aj/11ak elements */
    1802                 :            :                 };
    1803                 :            :                 noffset = ieee80211_ie_split(ie, ie_len,
    1804                 :            :                                              before_he, ARRAY_SIZE(before_he),
    1805                 :            :                                              *offset);
    1806                 :            :                 if (end - pos < noffset - *offset)
    1807                 :            :                         goto out_err;
    1808                 :            :                 memcpy(pos, ie + *offset, noffset - *offset);
    1809                 :            :                 pos += noffset - *offset;
    1810                 :            :                 *offset = noffset;
    1811                 :            :         }
    1812                 :            : 
    1813                 :            :         he_cap = ieee80211_get_he_sta_cap(sband);
    1814                 :            :         if (he_cap) {
    1815                 :            :                 pos = ieee80211_ie_build_he_cap(pos, he_cap, end);
    1816                 :            :                 if (!pos)
    1817                 :            :                         goto out_err;
    1818                 :            :         }
    1819                 :            : 
    1820                 :            :         /*
    1821                 :            :          * If adding more here, adjust code in main.c
    1822                 :            :          * that calculates local->scan_ies_len.
    1823                 :            :          */
    1824                 :            : 
    1825                 :            :         return pos - buffer;
    1826                 :            :  out_err:
    1827                 :            :         WARN_ONCE(1, "not enough space for preq IEs\n");
    1828                 :            :  done:
    1829                 :            :         return pos - buffer;
    1830                 :            : }
    1831                 :            : 
    1832                 :          0 : int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
    1833                 :            :                              size_t buffer_len,
    1834                 :            :                              struct ieee80211_scan_ies *ie_desc,
    1835                 :            :                              const u8 *ie, size_t ie_len,
    1836                 :            :                              u8 bands_used, u32 *rate_masks,
    1837                 :            :                              struct cfg80211_chan_def *chandef,
    1838                 :            :                              u32 flags)
    1839                 :            : {
    1840                 :          0 :         size_t pos = 0, old_pos = 0, custom_ie_offset = 0;
    1841                 :          0 :         int i;
    1842                 :            : 
    1843                 :          0 :         memset(ie_desc, 0, sizeof(*ie_desc));
    1844                 :            : 
    1845         [ #  # ]:          0 :         for (i = 0; i < NUM_NL80211_BANDS; i++) {
    1846         [ #  # ]:          0 :                 if (bands_used & BIT(i)) {
    1847                 :          0 :                         pos += ieee80211_build_preq_ies_band(local,
    1848                 :            :                                                              buffer + pos,
    1849                 :            :                                                              buffer_len - pos,
    1850                 :            :                                                              ie, ie_len, i,
    1851                 :          0 :                                                              rate_masks[i],
    1852                 :            :                                                              chandef,
    1853                 :            :                                                              &custom_ie_offset,
    1854                 :            :                                                              flags);
    1855                 :          0 :                         ie_desc->ies[i] = buffer + old_pos;
    1856                 :          0 :                         ie_desc->len[i] = pos - old_pos;
    1857                 :          0 :                         old_pos = pos;
    1858                 :            :                 }
    1859                 :            :         }
    1860                 :            : 
    1861                 :            :         /* add any remaining custom IEs */
    1862         [ #  # ]:          0 :         if (ie && ie_len) {
    1863   [ #  #  #  #  :          0 :                 if (WARN_ONCE(buffer_len - pos < ie_len - custom_ie_offset,
                   #  # ]
    1864                 :            :                               "not enough space for preq custom IEs\n"))
    1865                 :          0 :                         return pos;
    1866                 :          0 :                 memcpy(buffer + pos, ie + custom_ie_offset,
    1867                 :            :                        ie_len - custom_ie_offset);
    1868                 :          0 :                 ie_desc->common_ies = buffer + pos;
    1869                 :          0 :                 ie_desc->common_ie_len = ie_len - custom_ie_offset;
    1870                 :          0 :                 pos += ie_len - custom_ie_offset;
    1871                 :            :         }
    1872                 :            : 
    1873                 :          0 :         return pos;
    1874                 :            : };
    1875                 :            : 
    1876                 :          0 : struct sk_buff *ieee80211_build_probe_req(struct ieee80211_sub_if_data *sdata,
    1877                 :            :                                           const u8 *src, const u8 *dst,
    1878                 :            :                                           u32 ratemask,
    1879                 :            :                                           struct ieee80211_channel *chan,
    1880                 :            :                                           const u8 *ssid, size_t ssid_len,
    1881                 :            :                                           const u8 *ie, size_t ie_len,
    1882                 :            :                                           u32 flags)
    1883                 :            : {
    1884                 :          0 :         struct ieee80211_local *local = sdata->local;
    1885                 :          0 :         struct cfg80211_chan_def chandef;
    1886                 :          0 :         struct sk_buff *skb;
    1887                 :          0 :         struct ieee80211_mgmt *mgmt;
    1888                 :          0 :         int ies_len;
    1889                 :          0 :         u32 rate_masks[NUM_NL80211_BANDS] = {};
    1890                 :          0 :         struct ieee80211_scan_ies dummy_ie_desc;
    1891                 :            : 
    1892                 :            :         /*
    1893                 :            :          * Do not send DS Channel parameter for directed probe requests
    1894                 :            :          * in order to maximize the chance that we get a response.  Some
    1895                 :            :          * badly-behaved APs don't respond when this parameter is included.
    1896                 :            :          */
    1897                 :          0 :         chandef.width = sdata->vif.bss_conf.chandef.width;
    1898         [ #  # ]:          0 :         if (flags & IEEE80211_PROBE_FLAG_DIRECTED)
    1899                 :          0 :                 chandef.chan = NULL;
    1900                 :            :         else
    1901                 :          0 :                 chandef.chan = chan;
    1902                 :            : 
    1903                 :          0 :         skb = ieee80211_probereq_get(&local->hw, src, ssid, ssid_len,
    1904                 :            :                                      100 + ie_len);
    1905         [ #  # ]:          0 :         if (!skb)
    1906                 :            :                 return NULL;
    1907                 :            : 
    1908                 :          0 :         rate_masks[chan->band] = ratemask;
    1909                 :          0 :         ies_len = ieee80211_build_preq_ies(local, skb_tail_pointer(skb),
    1910                 :            :                                            skb_tailroom(skb), &dummy_ie_desc,
    1911         [ #  # ]:          0 :                                            ie, ie_len, BIT(chan->band),
    1912                 :            :                                            rate_masks, &chandef, flags);
    1913                 :          0 :         skb_put(skb, ies_len);
    1914                 :            : 
    1915         [ #  # ]:          0 :         if (dst) {
    1916                 :          0 :                 mgmt = (struct ieee80211_mgmt *) skb->data;
    1917                 :          0 :                 memcpy(mgmt->da, dst, ETH_ALEN);
    1918                 :          0 :                 memcpy(mgmt->bssid, dst, ETH_ALEN);
    1919                 :            :         }
    1920                 :            : 
    1921                 :          0 :         IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
    1922                 :            : 
    1923                 :          0 :         return skb;
    1924                 :            : }
    1925                 :            : 
    1926                 :          0 : u32 ieee80211_sta_get_rates(struct ieee80211_sub_if_data *sdata,
    1927                 :            :                             struct ieee802_11_elems *elems,
    1928                 :            :                             enum nl80211_band band, u32 *basic_rates)
    1929                 :            : {
    1930                 :          0 :         struct ieee80211_supported_band *sband;
    1931                 :          0 :         size_t num_rates;
    1932                 :          0 :         u32 supp_rates, rate_flags;
    1933                 :          0 :         int i, j, shift;
    1934                 :            : 
    1935                 :          0 :         sband = sdata->local->hw.wiphy->bands[band];
    1936   [ #  #  #  # ]:          0 :         if (WARN_ON(!sband))
    1937                 :            :                 return 1;
    1938                 :            : 
    1939      [ #  #  # ]:          0 :         rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef);
    1940                 :          0 :         shift = ieee80211_vif_get_shift(&sdata->vif);
    1941                 :            : 
    1942                 :          0 :         num_rates = sband->n_bitrates;
    1943                 :          0 :         supp_rates = 0;
    1944                 :          0 :         for (i = 0; i < elems->supp_rates_len +
    1945         [ #  # ]:          0 :                      elems->ext_supp_rates_len; i++) {
    1946                 :          0 :                 u8 rate = 0;
    1947                 :          0 :                 int own_rate;
    1948                 :          0 :                 bool is_basic;
    1949         [ #  # ]:          0 :                 if (i < elems->supp_rates_len)
    1950                 :          0 :                         rate = elems->supp_rates[i];
    1951         [ #  # ]:          0 :                 else if (elems->ext_supp_rates)
    1952                 :          0 :                         rate = elems->ext_supp_rates
    1953                 :          0 :                                 [i - elems->supp_rates_len];
    1954                 :          0 :                 own_rate = 5 * (rate & 0x7f);
    1955                 :          0 :                 is_basic = !!(rate & 0x80);
    1956                 :            : 
    1957   [ #  #  #  # ]:          0 :                 if (is_basic && (rate & 0x7f) == BSS_MEMBERSHIP_SELECTOR_HT_PHY)
    1958                 :          0 :                         continue;
    1959                 :            : 
    1960         [ #  # ]:          0 :                 for (j = 0; j < num_rates; j++) {
    1961                 :          0 :                         int brate;
    1962         [ #  # ]:          0 :                         if ((rate_flags & sband->bitrates[j].flags)
    1963                 :            :                             != rate_flags)
    1964                 :          0 :                                 continue;
    1965                 :            : 
    1966                 :          0 :                         brate = DIV_ROUND_UP(sband->bitrates[j].bitrate,
    1967                 :            :                                              1 << shift);
    1968                 :            : 
    1969         [ #  # ]:          0 :                         if (brate == own_rate) {
    1970                 :          0 :                                 supp_rates |= BIT(j);
    1971         [ #  # ]:          0 :                                 if (basic_rates && is_basic)
    1972                 :          0 :                                         *basic_rates |= BIT(j);
    1973                 :            :                         }
    1974                 :            :                 }
    1975                 :            :         }
    1976                 :            :         return supp_rates;
    1977                 :            : }
    1978                 :            : 
    1979                 :          0 : void ieee80211_stop_device(struct ieee80211_local *local)
    1980                 :            : {
    1981                 :          0 :         ieee80211_led_radio(local, false);
    1982                 :          0 :         ieee80211_mod_tpt_led_trig(local, 0, IEEE80211_TPT_LEDTRIG_FL_RADIO);
    1983                 :            : 
    1984                 :          0 :         cancel_work_sync(&local->reconfig_filter);
    1985                 :            : 
    1986                 :          0 :         flush_workqueue(local->workqueue);
    1987                 :          0 :         drv_stop(local);
    1988                 :          0 : }
    1989                 :            : 
    1990                 :          0 : static void ieee80211_flush_completed_scan(struct ieee80211_local *local,
    1991                 :            :                                            bool aborted)
    1992                 :            : {
    1993                 :            :         /* It's possible that we don't handle the scan completion in
    1994                 :            :          * time during suspend, so if it's still marked as completed
    1995                 :            :          * here, queue the work and flush it to clean things up.
    1996                 :            :          * Instead of calling the worker function directly here, we
    1997                 :            :          * really queue it to avoid potential races with other flows
    1998                 :            :          * scheduling the same work.
    1999                 :            :          */
    2000         [ #  # ]:          0 :         if (test_bit(SCAN_COMPLETED, &local->scanning)) {
    2001                 :            :                 /* If coming from reconfiguration failure, abort the scan so
    2002                 :            :                  * we don't attempt to continue a partial HW scan - which is
    2003                 :            :                  * possible otherwise if (e.g.) the 2.4 GHz portion was the
    2004                 :            :                  * completed scan, and a 5 GHz portion is still pending.
    2005                 :            :                  */
    2006         [ #  # ]:          0 :                 if (aborted)
    2007                 :          0 :                         set_bit(SCAN_ABORTED, &local->scanning);
    2008                 :          0 :                 ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
    2009                 :          0 :                 flush_delayed_work(&local->scan_work);
    2010                 :            :         }
    2011                 :          0 : }
    2012                 :            : 
    2013                 :          0 : static void ieee80211_handle_reconfig_failure(struct ieee80211_local *local)
    2014                 :            : {
    2015                 :          0 :         struct ieee80211_sub_if_data *sdata;
    2016                 :          0 :         struct ieee80211_chanctx *ctx;
    2017                 :            : 
    2018                 :            :         /*
    2019                 :            :          * We get here if during resume the device can't be restarted properly.
    2020                 :            :          * We might also get here if this happens during HW reset, which is a
    2021                 :            :          * slightly different situation and we need to drop all connections in
    2022                 :            :          * the latter case.
    2023                 :            :          *
    2024                 :            :          * Ask cfg80211 to turn off all interfaces, this will result in more
    2025                 :            :          * warnings but at least we'll then get into a clean stopped state.
    2026                 :            :          */
    2027                 :            : 
    2028                 :          0 :         local->resuming = false;
    2029                 :          0 :         local->suspended = false;
    2030                 :          0 :         local->in_reconfig = false;
    2031                 :            : 
    2032                 :          0 :         ieee80211_flush_completed_scan(local, true);
    2033                 :            : 
    2034                 :            :         /* scheduled scan clearly can't be running any more, but tell
    2035                 :            :          * cfg80211 and clear local state
    2036                 :            :          */
    2037                 :          0 :         ieee80211_sched_scan_end(local);
    2038                 :            : 
    2039         [ #  # ]:          0 :         list_for_each_entry(sdata, &local->interfaces, list)
    2040                 :          0 :                 sdata->flags &= ~IEEE80211_SDATA_IN_DRIVER;
    2041                 :            : 
    2042                 :            :         /* Mark channel contexts as not being in the driver any more to avoid
    2043                 :            :          * removing them from the driver during the shutdown process...
    2044                 :            :          */
    2045                 :          0 :         mutex_lock(&local->chanctx_mtx);
    2046         [ #  # ]:          0 :         list_for_each_entry(ctx, &local->chanctx_list, list)
    2047                 :          0 :                 ctx->driver_present = false;
    2048                 :          0 :         mutex_unlock(&local->chanctx_mtx);
    2049                 :            : 
    2050                 :          0 :         cfg80211_shutdown_all_interfaces(local->hw.wiphy);
    2051                 :          0 : }
    2052                 :            : 
    2053                 :          0 : static void ieee80211_assign_chanctx(struct ieee80211_local *local,
    2054                 :            :                                      struct ieee80211_sub_if_data *sdata)
    2055                 :            : {
    2056                 :          0 :         struct ieee80211_chanctx_conf *conf;
    2057                 :          0 :         struct ieee80211_chanctx *ctx;
    2058                 :            : 
    2059         [ #  # ]:          0 :         if (!local->use_chanctx)
    2060                 :            :                 return;
    2061                 :            : 
    2062                 :          0 :         mutex_lock(&local->chanctx_mtx);
    2063                 :          0 :         conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
    2064                 :            :                                          lockdep_is_held(&local->chanctx_mtx));
    2065         [ #  # ]:          0 :         if (conf) {
    2066                 :          0 :                 ctx = container_of(conf, struct ieee80211_chanctx, conf);
    2067                 :          0 :                 drv_assign_vif_chanctx(local, sdata, ctx);
    2068                 :            :         }
    2069                 :          0 :         mutex_unlock(&local->chanctx_mtx);
    2070                 :            : }
    2071                 :            : 
    2072                 :          0 : static void ieee80211_reconfig_stations(struct ieee80211_sub_if_data *sdata)
    2073                 :            : {
    2074                 :          0 :         struct ieee80211_local *local = sdata->local;
    2075                 :          0 :         struct sta_info *sta;
    2076                 :            : 
    2077                 :            :         /* add STAs back */
    2078                 :          0 :         mutex_lock(&local->sta_mtx);
    2079         [ #  # ]:          0 :         list_for_each_entry(sta, &local->sta_list, list) {
    2080                 :          0 :                 enum ieee80211_sta_state state;
    2081                 :            : 
    2082   [ #  #  #  # ]:          0 :                 if (!sta->uploaded || sta->sdata != sdata)
    2083                 :          0 :                         continue;
    2084                 :            : 
    2085                 :          0 :                 for (state = IEEE80211_STA_NOTEXIST;
    2086         [ #  # ]:          0 :                      state < sta->sta_state; state++)
    2087         [ #  # ]:          0 :                         WARN_ON(drv_sta_state(local, sta->sdata, sta, state,
    2088                 :            :                                               state + 1));
    2089                 :            :         }
    2090                 :          0 :         mutex_unlock(&local->sta_mtx);
    2091                 :          0 : }
    2092                 :            : 
    2093                 :          0 : static int ieee80211_reconfig_nan(struct ieee80211_sub_if_data *sdata)
    2094                 :            : {
    2095                 :          0 :         struct cfg80211_nan_func *func, **funcs;
    2096                 :          0 :         int res, id, i = 0;
    2097                 :            : 
    2098                 :          0 :         res = drv_start_nan(sdata->local, sdata,
    2099                 :            :                             &sdata->u.nan.conf);
    2100   [ #  #  #  # ]:          0 :         if (WARN_ON(res))
    2101                 :            :                 return res;
    2102                 :            : 
    2103                 :          0 :         funcs = kcalloc(sdata->local->hw.max_nan_de_entries + 1,
    2104                 :            :                         sizeof(*funcs),
    2105                 :            :                         GFP_KERNEL);
    2106         [ #  # ]:          0 :         if (!funcs)
    2107                 :            :                 return -ENOMEM;
    2108                 :            : 
    2109                 :            :         /* Add all the functions:
    2110                 :            :          * This is a little bit ugly. We need to call a potentially sleeping
    2111                 :            :          * callback for each NAN function, so we can't hold the spinlock.
    2112                 :            :          */
    2113                 :          0 :         spin_lock_bh(&sdata->u.nan.func_lock);
    2114                 :            : 
    2115         [ #  # ]:          0 :         idr_for_each_entry(&sdata->u.nan.function_inst_ids, func, id)
    2116                 :          0 :                 funcs[i++] = func;
    2117                 :            : 
    2118                 :          0 :         spin_unlock_bh(&sdata->u.nan.func_lock);
    2119                 :            : 
    2120         [ #  # ]:          0 :         for (i = 0; funcs[i]; i++) {
    2121                 :          0 :                 res = drv_add_nan_func(sdata->local, sdata, funcs[i]);
    2122   [ #  #  #  # ]:          0 :                 if (WARN_ON(res))
    2123                 :          0 :                         ieee80211_nan_func_terminated(&sdata->vif,
    2124                 :          0 :                                                       funcs[i]->instance_id,
    2125                 :            :                                                       NL80211_NAN_FUNC_TERM_REASON_ERROR,
    2126                 :            :                                                       GFP_KERNEL);
    2127                 :            :         }
    2128                 :            : 
    2129                 :          0 :         kfree(funcs);
    2130                 :            : 
    2131                 :          0 :         return 0;
    2132                 :            : }
    2133                 :            : 
    2134                 :          0 : int ieee80211_reconfig(struct ieee80211_local *local)
    2135                 :            : {
    2136                 :          0 :         struct ieee80211_hw *hw = &local->hw;
    2137                 :          0 :         struct ieee80211_sub_if_data *sdata;
    2138                 :          0 :         struct ieee80211_chanctx *ctx;
    2139                 :          0 :         struct sta_info *sta;
    2140                 :          0 :         int res, i;
    2141                 :          0 :         bool reconfig_due_to_wowlan = false;
    2142                 :          0 :         struct ieee80211_sub_if_data *sched_scan_sdata;
    2143                 :          0 :         struct cfg80211_sched_scan_request *sched_scan_req;
    2144                 :          0 :         bool sched_scan_stopped = false;
    2145                 :          0 :         bool suspended = local->suspended;
    2146                 :            : 
    2147                 :            :         /* nothing to do if HW shouldn't run */
    2148         [ #  # ]:          0 :         if (!local->open_count)
    2149                 :          0 :                 goto wake_up;
    2150                 :            : 
    2151                 :            : #ifdef CONFIG_PM
    2152         [ #  # ]:          0 :         if (suspended)
    2153                 :          0 :                 local->resuming = true;
    2154                 :            : 
    2155         [ #  # ]:          0 :         if (local->wowlan) {
    2156                 :            :                 /*
    2157                 :            :                  * In the wowlan case, both mac80211 and the device
    2158                 :            :                  * are functional when the resume op is called, so
    2159                 :            :                  * clear local->suspended so the device could operate
    2160                 :            :                  * normally (e.g. pass rx frames).
    2161                 :            :                  */
    2162                 :          0 :                 local->suspended = false;
    2163                 :          0 :                 res = drv_resume(local);
    2164                 :          0 :                 local->wowlan = false;
    2165         [ #  # ]:          0 :                 if (res < 0) {
    2166                 :          0 :                         local->resuming = false;
    2167                 :          0 :                         return res;
    2168                 :            :                 }
    2169         [ #  # ]:          0 :                 if (res == 0)
    2170                 :          0 :                         goto wake_up;
    2171         [ #  # ]:          0 :                 WARN_ON(res > 1);
    2172                 :            :                 /*
    2173                 :            :                  * res is 1, which means the driver requested
    2174                 :            :                  * to go through a regular reset on wakeup.
    2175                 :            :                  * restore local->suspended in this case.
    2176                 :            :                  */
    2177                 :          0 :                 reconfig_due_to_wowlan = true;
    2178                 :          0 :                 local->suspended = true;
    2179                 :            :         }
    2180                 :            : #endif
    2181                 :            : 
    2182                 :            :         /*
    2183                 :            :          * In case of hw_restart during suspend (without wowlan),
    2184                 :            :          * cancel restart work, as we are reconfiguring the device
    2185                 :            :          * anyway.
    2186                 :            :          * Note that restart_work is scheduled on a frozen workqueue,
    2187                 :            :          * so we can't deadlock in this case.
    2188                 :            :          */
    2189   [ #  #  #  #  :          0 :         if (suspended && local->in_reconfig && !reconfig_due_to_wowlan)
                   #  # ]
    2190                 :          0 :                 cancel_work_sync(&local->restart_work);
    2191                 :            : 
    2192                 :          0 :         local->started = false;
    2193                 :            : 
    2194                 :            :         /*
    2195                 :            :          * Upon resume hardware can sometimes be goofy due to
    2196                 :            :          * various platform / driver / bus issues, so restarting
    2197                 :            :          * the device may at times not work immediately. Propagate
    2198                 :            :          * the error.
    2199                 :            :          */
    2200                 :          0 :         res = drv_start(local);
    2201         [ #  # ]:          0 :         if (res) {
    2202         [ #  # ]:          0 :                 if (suspended)
    2203                 :          0 :                         WARN(1, "Hardware became unavailable upon resume. This could be a software issue prior to suspend or a hardware issue.\n");
    2204                 :            :                 else
    2205                 :          0 :                         WARN(1, "Hardware became unavailable during restart.\n");
    2206                 :          0 :                 ieee80211_handle_reconfig_failure(local);
    2207                 :          0 :                 return res;
    2208                 :            :         }
    2209                 :            : 
    2210                 :            :         /* setup fragmentation threshold */
    2211                 :          0 :         drv_set_frag_threshold(local, hw->wiphy->frag_threshold);
    2212                 :            : 
    2213                 :            :         /* setup RTS threshold */
    2214                 :          0 :         drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
    2215                 :            : 
    2216                 :            :         /* reset coverage class */
    2217                 :          0 :         drv_set_coverage_class(local, hw->wiphy->coverage_class);
    2218                 :            : 
    2219                 :          0 :         ieee80211_led_radio(local, true);
    2220                 :          0 :         ieee80211_mod_tpt_led_trig(local,
    2221                 :            :                                    IEEE80211_TPT_LEDTRIG_FL_RADIO, 0);
    2222                 :            : 
    2223                 :            :         /* add interfaces */
    2224                 :          0 :         sdata = rtnl_dereference(local->monitor_sdata);
    2225         [ #  # ]:          0 :         if (sdata) {
    2226                 :            :                 /* in HW restart it exists already */
    2227         [ #  # ]:          0 :                 WARN_ON(local->resuming);
    2228                 :          0 :                 res = drv_add_interface(local, sdata);
    2229   [ #  #  #  # ]:          0 :                 if (WARN_ON(res)) {
    2230                 :          0 :                         RCU_INIT_POINTER(local->monitor_sdata, NULL);
    2231                 :          0 :                         synchronize_net();
    2232                 :          0 :                         kfree(sdata);
    2233                 :            :                 }
    2234                 :            :         }
    2235                 :            : 
    2236         [ #  # ]:          0 :         list_for_each_entry(sdata, &local->interfaces, list) {
    2237         [ #  # ]:          0 :                 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
    2238         [ #  # ]:          0 :                     sdata->vif.type != NL80211_IFTYPE_MONITOR &&
    2239                 :            :                     ieee80211_sdata_running(sdata)) {
    2240                 :          0 :                         res = drv_add_interface(local, sdata);
    2241   [ #  #  #  # ]:          0 :                         if (WARN_ON(res))
    2242                 :            :                                 break;
    2243                 :            :                 }
    2244                 :            :         }
    2245                 :            : 
    2246                 :            :         /* If adding any of the interfaces failed above, roll back and
    2247                 :            :          * report failure.
    2248                 :            :          */
    2249         [ #  # ]:          0 :         if (res) {
    2250         [ #  # ]:          0 :                 list_for_each_entry_continue_reverse(sdata, &local->interfaces,
    2251                 :            :                                                      list)
    2252         [ #  # ]:          0 :                         if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
    2253         [ #  # ]:          0 :                             sdata->vif.type != NL80211_IFTYPE_MONITOR &&
    2254                 :            :                             ieee80211_sdata_running(sdata))
    2255                 :          0 :                                 drv_remove_interface(local, sdata);
    2256                 :          0 :                 ieee80211_handle_reconfig_failure(local);
    2257                 :          0 :                 return res;
    2258                 :            :         }
    2259                 :            : 
    2260                 :            :         /* add channel contexts */
    2261         [ #  # ]:          0 :         if (local->use_chanctx) {
    2262                 :          0 :                 mutex_lock(&local->chanctx_mtx);
    2263         [ #  # ]:          0 :                 list_for_each_entry(ctx, &local->chanctx_list, list)
    2264         [ #  # ]:          0 :                         if (ctx->replace_state !=
    2265                 :            :                             IEEE80211_CHANCTX_REPLACES_OTHER)
    2266         [ #  # ]:          0 :                                 WARN_ON(drv_add_chanctx(local, ctx));
    2267                 :          0 :                 mutex_unlock(&local->chanctx_mtx);
    2268                 :            : 
    2269                 :          0 :                 sdata = rtnl_dereference(local->monitor_sdata);
    2270   [ #  #  #  # ]:          0 :                 if (sdata && ieee80211_sdata_running(sdata))
    2271                 :          0 :                         ieee80211_assign_chanctx(local, sdata);
    2272                 :            :         }
    2273                 :            : 
    2274                 :            :         /* reconfigure hardware */
    2275                 :          0 :         ieee80211_hw_config(local, ~0);
    2276                 :            : 
    2277                 :          0 :         ieee80211_configure_filter(local);
    2278                 :            : 
    2279                 :            :         /* Finally also reconfigure all the BSS information */
    2280         [ #  # ]:          0 :         list_for_each_entry(sdata, &local->interfaces, list) {
    2281                 :          0 :                 u32 changed;
    2282                 :            : 
    2283         [ #  # ]:          0 :                 if (!ieee80211_sdata_running(sdata))
    2284                 :          0 :                         continue;
    2285                 :            : 
    2286                 :          0 :                 ieee80211_assign_chanctx(local, sdata);
    2287                 :            : 
    2288   [ #  #  #  # ]:          0 :                 switch (sdata->vif.type) {
    2289                 :            :                 case NL80211_IFTYPE_AP_VLAN:
    2290                 :            :                 case NL80211_IFTYPE_MONITOR:
    2291                 :            :                         break;
    2292                 :          0 :                 case NL80211_IFTYPE_ADHOC:
    2293         [ #  # ]:          0 :                         if (sdata->vif.bss_conf.ibss_joined)
    2294         [ #  # ]:          0 :                                 WARN_ON(drv_join_ibss(local, sdata));
    2295                 :            :                         /* fall through */
    2296                 :            :                 default:
    2297                 :          0 :                         ieee80211_reconfig_stations(sdata);
    2298                 :            :                         /* fall through */
    2299                 :            :                 case NL80211_IFTYPE_AP: /* AP stations are handled later */
    2300         [ #  # ]:          0 :                         for (i = 0; i < IEEE80211_NUM_ACS; i++)
    2301                 :          0 :                                 drv_conf_tx(local, sdata, i,
    2302                 :          0 :                                             &sdata->tx_conf[i]);
    2303                 :            :                         break;
    2304                 :            :                 }
    2305                 :            : 
    2306                 :            :                 /* common change flags for all interface types */
    2307                 :          0 :                 changed = BSS_CHANGED_ERP_CTS_PROT |
    2308                 :            :                           BSS_CHANGED_ERP_PREAMBLE |
    2309                 :            :                           BSS_CHANGED_ERP_SLOT |
    2310                 :            :                           BSS_CHANGED_HT |
    2311                 :            :                           BSS_CHANGED_BASIC_RATES |
    2312                 :            :                           BSS_CHANGED_BEACON_INT |
    2313                 :            :                           BSS_CHANGED_BSSID |
    2314                 :            :                           BSS_CHANGED_CQM |
    2315                 :            :                           BSS_CHANGED_QOS |
    2316                 :            :                           BSS_CHANGED_IDLE |
    2317                 :            :                           BSS_CHANGED_TXPOWER |
    2318                 :            :                           BSS_CHANGED_MCAST_RATE;
    2319                 :            : 
    2320         [ #  # ]:          0 :                 if (sdata->vif.mu_mimo_owner)
    2321                 :          0 :                         changed |= BSS_CHANGED_MU_GROUPS;
    2322                 :            : 
    2323   [ #  #  #  #  :          0 :                 switch (sdata->vif.type) {
             #  #  #  # ]
    2324                 :          0 :                 case NL80211_IFTYPE_STATION:
    2325                 :          0 :                         changed |= BSS_CHANGED_ASSOC |
    2326                 :            :                                    BSS_CHANGED_ARP_FILTER |
    2327                 :            :                                    BSS_CHANGED_PS;
    2328                 :            : 
    2329                 :            :                         /* Re-send beacon info report to the driver */
    2330         [ #  # ]:          0 :                         if (sdata->u.mgd.have_beacon)
    2331                 :          0 :                                 changed |= BSS_CHANGED_BEACON_INFO;
    2332                 :            : 
    2333         [ #  # ]:          0 :                         if (sdata->vif.bss_conf.max_idle_period ||
    2334                 :            :                             sdata->vif.bss_conf.protected_keep_alive)
    2335                 :          0 :                                 changed |= BSS_CHANGED_KEEP_ALIVE;
    2336                 :            : 
    2337                 :          0 :                         sdata_lock(sdata);
    2338                 :          0 :                         ieee80211_bss_info_change_notify(sdata, changed);
    2339                 :          0 :                         sdata_unlock(sdata);
    2340                 :            :                         break;
    2341                 :          0 :                 case NL80211_IFTYPE_OCB:
    2342                 :          0 :                         changed |= BSS_CHANGED_OCB;
    2343                 :          0 :                         ieee80211_bss_info_change_notify(sdata, changed);
    2344                 :          0 :                         break;
    2345                 :          0 :                 case NL80211_IFTYPE_ADHOC:
    2346                 :          0 :                         changed |= BSS_CHANGED_IBSS;
    2347                 :            :                         /* fall through */
    2348                 :          0 :                 case NL80211_IFTYPE_AP:
    2349                 :          0 :                         changed |= BSS_CHANGED_SSID | BSS_CHANGED_P2P_PS;
    2350                 :            : 
    2351   [ #  #  #  # ]:          0 :                         if (sdata->vif.bss_conf.ftm_responder == 1 &&
    2352         [ #  # ]:          0 :                             wiphy_ext_feature_isset(sdata->local->hw.wiphy,
    2353                 :            :                                         NL80211_EXT_FEATURE_ENABLE_FTM_RESPONDER))
    2354                 :          0 :                                 changed |= BSS_CHANGED_FTM_RESPONDER;
    2355                 :            : 
    2356         [ #  # ]:          0 :                         if (sdata->vif.type == NL80211_IFTYPE_AP) {
    2357                 :          0 :                                 changed |= BSS_CHANGED_AP_PROBE_RESP;
    2358                 :            : 
    2359         [ #  # ]:          0 :                                 if (rcu_access_pointer(sdata->u.ap.beacon))
    2360                 :          0 :                                         drv_start_ap(local, sdata);
    2361                 :            :                         }
    2362                 :            : 
    2363                 :            :                         /* fall through */
    2364                 :            :                 case NL80211_IFTYPE_MESH_POINT:
    2365         [ #  # ]:          0 :                         if (sdata->vif.bss_conf.enable_beacon) {
    2366                 :          0 :                                 changed |= BSS_CHANGED_BEACON |
    2367                 :            :                                            BSS_CHANGED_BEACON_ENABLED;
    2368                 :          0 :                                 ieee80211_bss_info_change_notify(sdata, changed);
    2369                 :            :                         }
    2370                 :            :                         break;
    2371                 :          0 :                 case NL80211_IFTYPE_NAN:
    2372                 :          0 :                         res = ieee80211_reconfig_nan(sdata);
    2373         [ #  # ]:          0 :                         if (res < 0) {
    2374                 :          0 :                                 ieee80211_handle_reconfig_failure(local);
    2375                 :          0 :                                 return res;
    2376                 :            :                         }
    2377                 :            :                         break;
    2378                 :            :                 case NL80211_IFTYPE_WDS:
    2379                 :            :                 case NL80211_IFTYPE_AP_VLAN:
    2380                 :            :                 case NL80211_IFTYPE_MONITOR:
    2381                 :            :                 case NL80211_IFTYPE_P2P_DEVICE:
    2382                 :            :                         /* nothing to do */
    2383                 :            :                         break;
    2384                 :            :                 case NL80211_IFTYPE_UNSPECIFIED:
    2385                 :            :                 case NUM_NL80211_IFTYPES:
    2386                 :            :                 case NL80211_IFTYPE_P2P_CLIENT:
    2387                 :            :                 case NL80211_IFTYPE_P2P_GO:
    2388                 :          0 :                         WARN_ON(1);
    2389                 :          0 :                         break;
    2390                 :            :                 }
    2391                 :          0 :         }
    2392                 :            : 
    2393                 :          0 :         ieee80211_recalc_ps(local);
    2394                 :            : 
    2395                 :            :         /*
    2396                 :            :          * The sta might be in psm against the ap (e.g. because
    2397                 :            :          * this was the state before a hw restart), so we
    2398                 :            :          * explicitly send a null packet in order to make sure
    2399                 :            :          * it'll sync against the ap (and get out of psm).
    2400                 :            :          */
    2401         [ #  # ]:          0 :         if (!(local->hw.conf.flags & IEEE80211_CONF_PS)) {
    2402         [ #  # ]:          0 :                 list_for_each_entry(sdata, &local->interfaces, list) {
    2403         [ #  # ]:          0 :                         if (sdata->vif.type != NL80211_IFTYPE_STATION)
    2404                 :          0 :                                 continue;
    2405         [ #  # ]:          0 :                         if (!sdata->u.mgd.associated)
    2406                 :          0 :                                 continue;
    2407                 :            : 
    2408                 :          0 :                         ieee80211_send_nullfunc(local, sdata, false);
    2409                 :            :                 }
    2410                 :            :         }
    2411                 :            : 
    2412                 :            :         /* APs are now beaconing, add back stations */
    2413                 :          0 :         mutex_lock(&local->sta_mtx);
    2414         [ #  # ]:          0 :         list_for_each_entry(sta, &local->sta_list, list) {
    2415                 :          0 :                 enum ieee80211_sta_state state;
    2416                 :            : 
    2417         [ #  # ]:          0 :                 if (!sta->uploaded)
    2418                 :          0 :                         continue;
    2419                 :            : 
    2420         [ #  # ]:          0 :                 if (sta->sdata->vif.type != NL80211_IFTYPE_AP &&
    2421                 :            :                     sta->sdata->vif.type != NL80211_IFTYPE_AP_VLAN)
    2422                 :          0 :                         continue;
    2423                 :            : 
    2424                 :          0 :                 for (state = IEEE80211_STA_NOTEXIST;
    2425         [ #  # ]:          0 :                      state < sta->sta_state; state++)
    2426         [ #  # ]:          0 :                         WARN_ON(drv_sta_state(local, sta->sdata, sta, state,
    2427                 :            :                                               state + 1));
    2428                 :            :         }
    2429                 :          0 :         mutex_unlock(&local->sta_mtx);
    2430                 :            : 
    2431                 :            :         /* add back keys */
    2432         [ #  # ]:          0 :         list_for_each_entry(sdata, &local->interfaces, list)
    2433                 :          0 :                 ieee80211_reenable_keys(sdata);
    2434                 :            : 
    2435                 :            :         /* Reconfigure sched scan if it was interrupted by FW restart */
    2436                 :          0 :         mutex_lock(&local->mtx);
    2437                 :          0 :         sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
    2438                 :            :                                                 lockdep_is_held(&local->mtx));
    2439                 :          0 :         sched_scan_req = rcu_dereference_protected(local->sched_scan_req,
    2440                 :            :                                                 lockdep_is_held(&local->mtx));
    2441         [ #  # ]:          0 :         if (sched_scan_sdata && sched_scan_req)
    2442                 :            :                 /*
    2443                 :            :                  * Sched scan stopped, but we don't want to report it. Instead,
    2444                 :            :                  * we're trying to reschedule. However, if more than one scan
    2445                 :            :                  * plan was set, we cannot reschedule since we don't know which
    2446                 :            :                  * scan plan was currently running (and some scan plans may have
    2447                 :            :                  * already finished).
    2448                 :            :                  */
    2449   [ #  #  #  # ]:          0 :                 if (sched_scan_req->n_scan_plans > 1 ||
    2450                 :          0 :                     __ieee80211_request_sched_scan_start(sched_scan_sdata,
    2451                 :            :                                                          sched_scan_req)) {
    2452                 :          0 :                         RCU_INIT_POINTER(local->sched_scan_sdata, NULL);
    2453                 :          0 :                         RCU_INIT_POINTER(local->sched_scan_req, NULL);
    2454                 :          0 :                         sched_scan_stopped = true;
    2455                 :            :                 }
    2456                 :          0 :         mutex_unlock(&local->mtx);
    2457                 :            : 
    2458         [ #  # ]:          0 :         if (sched_scan_stopped)
    2459                 :          0 :                 cfg80211_sched_scan_stopped_rtnl(local->hw.wiphy, 0);
    2460                 :            : 
    2461                 :          0 :  wake_up:
    2462                 :            : 
    2463   [ #  #  #  # ]:          0 :         if (local->monitors == local->open_count && local->monitors > 0)
    2464                 :          0 :                 ieee80211_add_virtual_monitor(local);
    2465                 :            : 
    2466                 :            :         /*
    2467                 :            :          * Clear the WLAN_STA_BLOCK_BA flag so new aggregation
    2468                 :            :          * sessions can be established after a resume.
    2469                 :            :          *
    2470                 :            :          * Also tear down aggregation sessions since reconfiguring
    2471                 :            :          * them in a hardware restart scenario is not easily done
    2472                 :            :          * right now, and the hardware will have lost information
    2473                 :            :          * about the sessions, but we and the AP still think they
    2474                 :            :          * are active. This is really a workaround though.
    2475                 :            :          */
    2476         [ #  # ]:          0 :         if (ieee80211_hw_check(hw, AMPDU_AGGREGATION)) {
    2477                 :          0 :                 mutex_lock(&local->sta_mtx);
    2478                 :            : 
    2479         [ #  # ]:          0 :                 list_for_each_entry(sta, &local->sta_list, list) {
    2480         [ #  # ]:          0 :                         if (!local->resuming)
    2481                 :          0 :                                 ieee80211_sta_tear_down_BA_sessions(
    2482                 :            :                                                 sta, AGG_STOP_LOCAL_REQUEST);
    2483                 :          0 :                         clear_sta_flag(sta, WLAN_STA_BLOCK_BA);
    2484                 :            :                 }
    2485                 :            : 
    2486                 :          0 :                 mutex_unlock(&local->sta_mtx);
    2487                 :            :         }
    2488                 :            : 
    2489         [ #  # ]:          0 :         if (local->in_reconfig) {
    2490                 :          0 :                 local->in_reconfig = false;
    2491                 :          0 :                 barrier();
    2492                 :            : 
    2493                 :            :                 /* Restart deferred ROCs */
    2494                 :          0 :                 mutex_lock(&local->mtx);
    2495                 :          0 :                 ieee80211_start_next_roc(local);
    2496                 :          0 :                 mutex_unlock(&local->mtx);
    2497                 :            : 
    2498                 :            :                 /* Requeue all works */
    2499         [ #  # ]:          0 :                 list_for_each_entry(sdata, &local->interfaces, list)
    2500                 :          0 :                         ieee80211_queue_work(&local->hw, &sdata->work);
    2501                 :            :         }
    2502                 :            : 
    2503                 :          0 :         ieee80211_wake_queues_by_reason(hw, IEEE80211_MAX_QUEUE_MAP,
    2504                 :            :                                         IEEE80211_QUEUE_STOP_REASON_SUSPEND,
    2505                 :            :                                         false);
    2506                 :            : 
    2507                 :            :         /*
    2508                 :            :          * If this is for hw restart things are still running.
    2509                 :            :          * We may want to change that later, however.
    2510                 :            :          */
    2511   [ #  #  #  # ]:          0 :         if (local->open_count && (!suspended || reconfig_due_to_wowlan))
    2512                 :          0 :                 drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_RESTART);
    2513                 :            : 
    2514         [ #  # ]:          0 :         if (!suspended)
    2515                 :            :                 return 0;
    2516                 :            : 
    2517                 :            : #ifdef CONFIG_PM
    2518                 :            :         /* first set suspended false, then resuming */
    2519                 :          0 :         local->suspended = false;
    2520                 :          0 :         mb();
    2521                 :          0 :         local->resuming = false;
    2522                 :            : 
    2523                 :          0 :         ieee80211_flush_completed_scan(local, false);
    2524                 :            : 
    2525   [ #  #  #  # ]:          0 :         if (local->open_count && !reconfig_due_to_wowlan)
    2526                 :          0 :                 drv_reconfig_complete(local, IEEE80211_RECONFIG_TYPE_SUSPEND);
    2527                 :            : 
    2528         [ #  # ]:          0 :         list_for_each_entry(sdata, &local->interfaces, list) {
    2529         [ #  # ]:          0 :                 if (!ieee80211_sdata_running(sdata))
    2530                 :          0 :                         continue;
    2531         [ #  # ]:          0 :                 if (sdata->vif.type == NL80211_IFTYPE_STATION)
    2532                 :          0 :                         ieee80211_sta_restart(sdata);
    2533                 :            :         }
    2534                 :            : 
    2535                 :          0 :         mod_timer(&local->sta_cleanup, jiffies + 1);
    2536                 :            : #else
    2537                 :            :         WARN_ON(1);
    2538                 :            : #endif
    2539                 :            : 
    2540                 :          0 :         return 0;
    2541                 :            : }
    2542                 :            : 
    2543                 :          0 : void ieee80211_resume_disconnect(struct ieee80211_vif *vif)
    2544                 :            : {
    2545                 :          0 :         struct ieee80211_sub_if_data *sdata;
    2546                 :          0 :         struct ieee80211_local *local;
    2547                 :          0 :         struct ieee80211_key *key;
    2548                 :            : 
    2549   [ #  #  #  # ]:          0 :         if (WARN_ON(!vif))
    2550                 :            :                 return;
    2551                 :            : 
    2552         [ #  # ]:          0 :         sdata = vif_to_sdata(vif);
    2553                 :          0 :         local = sdata->local;
    2554                 :            : 
    2555   [ #  #  #  # ]:          0 :         if (WARN_ON(!local->resuming))
    2556                 :            :                 return;
    2557                 :            : 
    2558   [ #  #  #  # ]:          0 :         if (WARN_ON(vif->type != NL80211_IFTYPE_STATION))
    2559                 :            :                 return;
    2560                 :            : 
    2561                 :          0 :         sdata->flags |= IEEE80211_SDATA_DISCONNECT_RESUME;
    2562                 :            : 
    2563                 :          0 :         mutex_lock(&local->key_mtx);
    2564         [ #  # ]:          0 :         list_for_each_entry(key, &sdata->key_list, list)
    2565                 :          0 :                 key->flags |= KEY_FLAG_TAINTED;
    2566                 :          0 :         mutex_unlock(&local->key_mtx);
    2567                 :            : }
    2568                 :            : EXPORT_SYMBOL_GPL(ieee80211_resume_disconnect);
    2569                 :            : 
    2570                 :          0 : void ieee80211_recalc_smps(struct ieee80211_sub_if_data *sdata)
    2571                 :            : {
    2572                 :          0 :         struct ieee80211_local *local = sdata->local;
    2573                 :          0 :         struct ieee80211_chanctx_conf *chanctx_conf;
    2574                 :          0 :         struct ieee80211_chanctx *chanctx;
    2575                 :            : 
    2576                 :          0 :         mutex_lock(&local->chanctx_mtx);
    2577                 :            : 
    2578                 :          0 :         chanctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
    2579                 :            :                                         lockdep_is_held(&local->chanctx_mtx));
    2580                 :            : 
    2581                 :            :         /*
    2582                 :            :          * This function can be called from a work, thus it may be possible
    2583                 :            :          * that the chanctx_conf is removed (due to a disconnection, for
    2584                 :            :          * example).
    2585                 :            :          * So nothing should be done in such case.
    2586                 :            :          */
    2587         [ #  # ]:          0 :         if (!chanctx_conf)
    2588                 :          0 :                 goto unlock;
    2589                 :            : 
    2590                 :          0 :         chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
    2591                 :          0 :         ieee80211_recalc_smps_chanctx(local, chanctx);
    2592                 :          0 :  unlock:
    2593                 :          0 :         mutex_unlock(&local->chanctx_mtx);
    2594                 :          0 : }
    2595                 :            : 
    2596                 :          0 : void ieee80211_recalc_min_chandef(struct ieee80211_sub_if_data *sdata)
    2597                 :            : {
    2598                 :          0 :         struct ieee80211_local *local = sdata->local;
    2599                 :          0 :         struct ieee80211_chanctx_conf *chanctx_conf;
    2600                 :          0 :         struct ieee80211_chanctx *chanctx;
    2601                 :            : 
    2602                 :          0 :         mutex_lock(&local->chanctx_mtx);
    2603                 :            : 
    2604                 :          0 :         chanctx_conf = rcu_dereference_protected(sdata->vif.chanctx_conf,
    2605                 :            :                                         lockdep_is_held(&local->chanctx_mtx));
    2606                 :            : 
    2607   [ #  #  #  # ]:          0 :         if (WARN_ON_ONCE(!chanctx_conf))
    2608                 :          0 :                 goto unlock;
    2609                 :            : 
    2610                 :          0 :         chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
    2611                 :          0 :         ieee80211_recalc_chanctx_min_def(local, chanctx);
    2612                 :          0 :  unlock:
    2613                 :          0 :         mutex_unlock(&local->chanctx_mtx);
    2614                 :          0 : }
    2615                 :            : 
    2616                 :          0 : size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)
    2617                 :            : {
    2618                 :          0 :         size_t pos = offset;
    2619                 :            : 
    2620   [ #  #  #  # ]:          0 :         while (pos < ielen && ies[pos] != WLAN_EID_VENDOR_SPECIFIC)
    2621                 :          0 :                 pos += 2 + ies[pos + 1];
    2622                 :            : 
    2623                 :          0 :         return pos;
    2624                 :            : }
    2625                 :            : 
    2626                 :          0 : static void _ieee80211_enable_rssi_reports(struct ieee80211_sub_if_data *sdata,
    2627                 :            :                                             int rssi_min_thold,
    2628                 :            :                                             int rssi_max_thold)
    2629                 :            : {
    2630                 :          0 :         trace_api_enable_rssi_reports(sdata, rssi_min_thold, rssi_max_thold);
    2631                 :            : 
    2632   [ #  #  #  # ]:          0 :         if (WARN_ON(sdata->vif.type != NL80211_IFTYPE_STATION))
    2633                 :            :                 return;
    2634                 :            : 
    2635                 :            :         /*
    2636                 :            :          * Scale up threshold values before storing it, as the RSSI averaging
    2637                 :            :          * algorithm uses a scaled up value as well. Change this scaling
    2638                 :            :          * factor if the RSSI averaging algorithm changes.
    2639                 :            :          */
    2640                 :          0 :         sdata->u.mgd.rssi_min_thold = rssi_min_thold*16;
    2641                 :          0 :         sdata->u.mgd.rssi_max_thold = rssi_max_thold*16;
    2642                 :            : }
    2643                 :            : 
    2644                 :          0 : void ieee80211_enable_rssi_reports(struct ieee80211_vif *vif,
    2645                 :            :                                     int rssi_min_thold,
    2646                 :            :                                     int rssi_max_thold)
    2647                 :            : {
    2648         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
    2649                 :            : 
    2650         [ #  # ]:          0 :         WARN_ON(rssi_min_thold == rssi_max_thold ||
    2651                 :            :                 rssi_min_thold > rssi_max_thold);
    2652                 :            : 
    2653                 :          0 :         _ieee80211_enable_rssi_reports(sdata, rssi_min_thold,
    2654                 :            :                                        rssi_max_thold);
    2655                 :          0 : }
    2656                 :            : EXPORT_SYMBOL(ieee80211_enable_rssi_reports);
    2657                 :            : 
    2658                 :          0 : void ieee80211_disable_rssi_reports(struct ieee80211_vif *vif)
    2659                 :            : {
    2660                 :          0 :         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
    2661                 :            : 
    2662                 :          0 :         _ieee80211_enable_rssi_reports(sdata, 0, 0);
    2663                 :          0 : }
    2664                 :            : EXPORT_SYMBOL(ieee80211_disable_rssi_reports);
    2665                 :            : 
    2666                 :          0 : u8 *ieee80211_ie_build_ht_cap(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
    2667                 :            :                               u16 cap)
    2668                 :            : {
    2669                 :          0 :         __le16 tmp;
    2670                 :            : 
    2671                 :          0 :         *pos++ = WLAN_EID_HT_CAPABILITY;
    2672                 :          0 :         *pos++ = sizeof(struct ieee80211_ht_cap);
    2673                 :          0 :         memset(pos, 0, sizeof(struct ieee80211_ht_cap));
    2674                 :            : 
    2675                 :            :         /* capability flags */
    2676                 :          0 :         tmp = cpu_to_le16(cap);
    2677                 :          0 :         memcpy(pos, &tmp, sizeof(u16));
    2678                 :          0 :         pos += sizeof(u16);
    2679                 :            : 
    2680                 :            :         /* AMPDU parameters */
    2681                 :          0 :         *pos++ = ht_cap->ampdu_factor |
    2682                 :          0 :                  (ht_cap->ampdu_density <<
    2683                 :            :                         IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
    2684                 :            : 
    2685                 :            :         /* MCS set */
    2686                 :          0 :         memcpy(pos, &ht_cap->mcs, sizeof(ht_cap->mcs));
    2687                 :          0 :         pos += sizeof(ht_cap->mcs);
    2688                 :            : 
    2689                 :            :         /* extended capabilities */
    2690                 :          0 :         pos += sizeof(__le16);
    2691                 :            : 
    2692                 :            :         /* BF capabilities */
    2693                 :          0 :         pos += sizeof(__le32);
    2694                 :            : 
    2695                 :            :         /* antenna selection */
    2696                 :          0 :         pos += sizeof(u8);
    2697                 :            : 
    2698                 :          0 :         return pos;
    2699                 :            : }
    2700                 :            : 
    2701                 :          0 : u8 *ieee80211_ie_build_vht_cap(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
    2702                 :            :                                u32 cap)
    2703                 :            : {
    2704                 :          0 :         __le32 tmp;
    2705                 :            : 
    2706                 :          0 :         *pos++ = WLAN_EID_VHT_CAPABILITY;
    2707                 :          0 :         *pos++ = sizeof(struct ieee80211_vht_cap);
    2708                 :          0 :         memset(pos, 0, sizeof(struct ieee80211_vht_cap));
    2709                 :            : 
    2710                 :            :         /* capability flags */
    2711                 :          0 :         tmp = cpu_to_le32(cap);
    2712                 :          0 :         memcpy(pos, &tmp, sizeof(u32));
    2713                 :          0 :         pos += sizeof(u32);
    2714                 :            : 
    2715                 :            :         /* VHT MCS set */
    2716                 :          0 :         memcpy(pos, &vht_cap->vht_mcs, sizeof(vht_cap->vht_mcs));
    2717                 :          0 :         pos += sizeof(vht_cap->vht_mcs);
    2718                 :            : 
    2719                 :          0 :         return pos;
    2720                 :            : }
    2721                 :            : 
    2722                 :          0 : u8 ieee80211_ie_len_he_cap(struct ieee80211_sub_if_data *sdata, u8 iftype)
    2723                 :            : {
    2724                 :          0 :         const struct ieee80211_sta_he_cap *he_cap;
    2725                 :          0 :         struct ieee80211_supported_band *sband;
    2726                 :          0 :         u8 n;
    2727                 :            : 
    2728                 :          0 :         sband = ieee80211_get_sband(sdata);
    2729         [ #  # ]:          0 :         if (!sband)
    2730                 :            :                 return 0;
    2731                 :            : 
    2732                 :          0 :         he_cap = ieee80211_get_he_iftype_cap(sband, iftype);
    2733         [ #  # ]:          0 :         if (!he_cap)
    2734                 :            :                 return 0;
    2735                 :            : 
    2736         [ #  # ]:          0 :         n = ieee80211_he_mcs_nss_size(&he_cap->he_cap_elem);
    2737                 :          0 :         return 2 + 1 +
    2738                 :          0 :                sizeof(he_cap->he_cap_elem) + n +
    2739                 :          0 :                ieee80211_he_ppe_size(he_cap->ppe_thres[0],
    2740                 :          0 :                                      he_cap->he_cap_elem.phy_cap_info);
    2741                 :            : }
    2742                 :            : 
    2743                 :          0 : u8 *ieee80211_ie_build_he_cap(u8 *pos,
    2744                 :            :                               const struct ieee80211_sta_he_cap *he_cap,
    2745                 :            :                               u8 *end)
    2746                 :            : {
    2747                 :          0 :         u8 n;
    2748                 :          0 :         u8 ie_len;
    2749                 :          0 :         u8 *orig_pos = pos;
    2750                 :            : 
    2751                 :            :         /* Make sure we have place for the IE */
    2752                 :            :         /*
    2753                 :            :          * TODO: the 1 added is because this temporarily is under the EXTENSION
    2754                 :            :          * IE. Get rid of it when it moves.
    2755                 :            :          */
    2756         [ #  # ]:          0 :         if (!he_cap)
    2757                 :            :                 return orig_pos;
    2758                 :            : 
    2759         [ #  # ]:          0 :         n = ieee80211_he_mcs_nss_size(&he_cap->he_cap_elem);
    2760                 :          0 :         ie_len = 2 + 1 +
    2761                 :          0 :                  sizeof(he_cap->he_cap_elem) + n +
    2762                 :          0 :                  ieee80211_he_ppe_size(he_cap->ppe_thres[0],
    2763                 :          0 :                                        he_cap->he_cap_elem.phy_cap_info);
    2764                 :            : 
    2765         [ #  # ]:          0 :         if ((end - pos) < ie_len)
    2766                 :            :                 return orig_pos;
    2767                 :            : 
    2768                 :          0 :         *pos++ = WLAN_EID_EXTENSION;
    2769                 :          0 :         pos++; /* We'll set the size later below */
    2770                 :          0 :         *pos++ = WLAN_EID_EXT_HE_CAPABILITY;
    2771                 :            : 
    2772                 :            :         /* Fixed data */
    2773                 :          0 :         memcpy(pos, &he_cap->he_cap_elem, sizeof(he_cap->he_cap_elem));
    2774                 :          0 :         pos += sizeof(he_cap->he_cap_elem);
    2775                 :            : 
    2776                 :          0 :         memcpy(pos, &he_cap->he_mcs_nss_supp, n);
    2777                 :          0 :         pos += n;
    2778                 :            : 
    2779                 :            :         /* Check if PPE Threshold should be present */
    2780                 :          0 :         if ((he_cap->he_cap_elem.phy_cap_info[6] &
    2781         [ #  # ]:          0 :              IEEE80211_HE_PHY_CAP6_PPE_THRESHOLD_PRESENT) == 0)
    2782                 :          0 :                 goto end;
    2783                 :            : 
    2784                 :            :         /*
    2785                 :            :          * Calculate how many PPET16/PPET8 pairs are to come. Algorithm:
    2786                 :            :          * (NSS_M1 + 1) x (num of 1 bits in RU_INDEX_BITMASK)
    2787                 :            :          */
    2788         [ #  # ]:          0 :         n = hweight8(he_cap->ppe_thres[0] &
    2789                 :            :                      IEEE80211_PPE_THRES_RU_INDEX_BITMASK_MASK);
    2790                 :          0 :         n *= (1 + ((he_cap->ppe_thres[0] & IEEE80211_PPE_THRES_NSS_MASK) >>
    2791                 :            :                    IEEE80211_PPE_THRES_NSS_POS));
    2792                 :            : 
    2793                 :            :         /*
    2794                 :            :          * Each pair is 6 bits, and we need to add the 7 "header" bits to the
    2795                 :            :          * total size.
    2796                 :            :          */
    2797                 :          0 :         n = (n * IEEE80211_PPE_THRES_INFO_PPET_SIZE * 2) + 7;
    2798                 :          0 :         n = DIV_ROUND_UP(n, 8);
    2799                 :            : 
    2800                 :            :         /* Copy PPE Thresholds */
    2801                 :          0 :         memcpy(pos, &he_cap->ppe_thres, n);
    2802                 :          0 :         pos += n;
    2803                 :            : 
    2804                 :          0 : end:
    2805                 :          0 :         orig_pos[1] = (pos - orig_pos) - 2;
    2806                 :          0 :         return pos;
    2807                 :            : }
    2808                 :            : 
    2809                 :          0 : u8 *ieee80211_ie_build_ht_oper(u8 *pos, struct ieee80211_sta_ht_cap *ht_cap,
    2810                 :            :                                const struct cfg80211_chan_def *chandef,
    2811                 :            :                                u16 prot_mode, bool rifs_mode)
    2812                 :            : {
    2813                 :          0 :         struct ieee80211_ht_operation *ht_oper;
    2814                 :            :         /* Build HT Information */
    2815                 :          0 :         *pos++ = WLAN_EID_HT_OPERATION;
    2816                 :          0 :         *pos++ = sizeof(struct ieee80211_ht_operation);
    2817                 :          0 :         ht_oper = (struct ieee80211_ht_operation *)pos;
    2818                 :          0 :         ht_oper->primary_chan = ieee80211_frequency_to_channel(
    2819                 :          0 :                                         chandef->chan->center_freq);
    2820         [ #  # ]:          0 :         switch (chandef->width) {
    2821                 :          0 :         case NL80211_CHAN_WIDTH_160:
    2822                 :            :         case NL80211_CHAN_WIDTH_80P80:
    2823                 :            :         case NL80211_CHAN_WIDTH_80:
    2824                 :            :         case NL80211_CHAN_WIDTH_40:
    2825         [ #  # ]:          0 :                 if (chandef->center_freq1 > chandef->chan->center_freq)
    2826                 :          0 :                         ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
    2827                 :            :                 else
    2828                 :          0 :                         ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
    2829                 :            :                 break;
    2830                 :          0 :         default:
    2831                 :          0 :                 ht_oper->ht_param = IEEE80211_HT_PARAM_CHA_SEC_NONE;
    2832                 :          0 :                 break;
    2833                 :            :         }
    2834         [ #  # ]:          0 :         if (ht_cap->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 &&
    2835   [ #  #  #  # ]:          0 :             chandef->width != NL80211_CHAN_WIDTH_20_NOHT &&
    2836                 :            :             chandef->width != NL80211_CHAN_WIDTH_20)
    2837                 :          0 :                 ht_oper->ht_param |= IEEE80211_HT_PARAM_CHAN_WIDTH_ANY;
    2838                 :            : 
    2839         [ #  # ]:          0 :         if (rifs_mode)
    2840                 :          0 :                 ht_oper->ht_param |= IEEE80211_HT_PARAM_RIFS_MODE;
    2841                 :            : 
    2842                 :          0 :         ht_oper->operation_mode = cpu_to_le16(prot_mode);
    2843                 :          0 :         ht_oper->stbc_param = 0x0000;
    2844                 :            : 
    2845                 :            :         /* It seems that Basic MCS set and Supported MCS set
    2846                 :            :            are identical for the first 10 bytes */
    2847                 :          0 :         memset(&ht_oper->basic_set, 0, 16);
    2848                 :          0 :         memcpy(&ht_oper->basic_set, &ht_cap->mcs, 10);
    2849                 :            : 
    2850                 :          0 :         return pos + sizeof(struct ieee80211_ht_operation);
    2851                 :            : }
    2852                 :            : 
    2853                 :          0 : void ieee80211_ie_build_wide_bw_cs(u8 *pos,
    2854                 :            :                                    const struct cfg80211_chan_def *chandef)
    2855                 :            : {
    2856                 :          0 :         *pos++ = WLAN_EID_WIDE_BW_CHANNEL_SWITCH;       /* EID */
    2857                 :          0 :         *pos++ = 3;                                     /* IE length */
    2858                 :            :         /* New channel width */
    2859   [ #  #  #  # ]:          0 :         switch (chandef->width) {
    2860                 :          0 :         case NL80211_CHAN_WIDTH_80:
    2861                 :          0 :                 *pos++ = IEEE80211_VHT_CHANWIDTH_80MHZ;
    2862                 :          0 :                 break;
    2863                 :          0 :         case NL80211_CHAN_WIDTH_160:
    2864                 :          0 :                 *pos++ = IEEE80211_VHT_CHANWIDTH_160MHZ;
    2865                 :          0 :                 break;
    2866                 :          0 :         case NL80211_CHAN_WIDTH_80P80:
    2867                 :          0 :                 *pos++ = IEEE80211_VHT_CHANWIDTH_80P80MHZ;
    2868                 :          0 :                 break;
    2869                 :          0 :         default:
    2870                 :          0 :                 *pos++ = IEEE80211_VHT_CHANWIDTH_USE_HT;
    2871                 :            :         }
    2872                 :            : 
    2873                 :            :         /* new center frequency segment 0 */
    2874                 :          0 :         *pos++ = ieee80211_frequency_to_channel(chandef->center_freq1);
    2875                 :            :         /* new center frequency segment 1 */
    2876         [ #  # ]:          0 :         if (chandef->center_freq2)
    2877                 :          0 :                 *pos++ = ieee80211_frequency_to_channel(chandef->center_freq2);
    2878                 :            :         else
    2879                 :          0 :                 *pos++ = 0;
    2880                 :          0 : }
    2881                 :            : 
    2882                 :          0 : u8 *ieee80211_ie_build_vht_oper(u8 *pos, struct ieee80211_sta_vht_cap *vht_cap,
    2883                 :            :                                 const struct cfg80211_chan_def *chandef)
    2884                 :            : {
    2885                 :          0 :         struct ieee80211_vht_operation *vht_oper;
    2886                 :            : 
    2887                 :          0 :         *pos++ = WLAN_EID_VHT_OPERATION;
    2888                 :          0 :         *pos++ = sizeof(struct ieee80211_vht_operation);
    2889                 :          0 :         vht_oper = (struct ieee80211_vht_operation *)pos;
    2890                 :          0 :         vht_oper->center_freq_seg0_idx = ieee80211_frequency_to_channel(
    2891                 :          0 :                                                         chandef->center_freq1);
    2892         [ #  # ]:          0 :         if (chandef->center_freq2)
    2893                 :          0 :                 vht_oper->center_freq_seg1_idx =
    2894                 :          0 :                         ieee80211_frequency_to_channel(chandef->center_freq2);
    2895                 :            :         else
    2896                 :          0 :                 vht_oper->center_freq_seg1_idx = 0x00;
    2897                 :            : 
    2898   [ #  #  #  # ]:          0 :         switch (chandef->width) {
    2899                 :          0 :         case NL80211_CHAN_WIDTH_160:
    2900                 :            :                 /*
    2901                 :            :                  * Convert 160 MHz channel width to new style as interop
    2902                 :            :                  * workaround.
    2903                 :            :                  */
    2904                 :          0 :                 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
    2905                 :          0 :                 vht_oper->center_freq_seg1_idx = vht_oper->center_freq_seg0_idx;
    2906         [ #  # ]:          0 :                 if (chandef->chan->center_freq < chandef->center_freq1)
    2907                 :          0 :                         vht_oper->center_freq_seg0_idx -= 8;
    2908                 :            :                 else
    2909                 :          0 :                         vht_oper->center_freq_seg0_idx += 8;
    2910                 :            :                 break;
    2911                 :          0 :         case NL80211_CHAN_WIDTH_80P80:
    2912                 :            :                 /*
    2913                 :            :                  * Convert 80+80 MHz channel width to new style as interop
    2914                 :            :                  * workaround.
    2915                 :            :                  */
    2916                 :          0 :                 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
    2917                 :          0 :                 break;
    2918                 :          0 :         case NL80211_CHAN_WIDTH_80:
    2919                 :          0 :                 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ;
    2920                 :          0 :                 break;
    2921                 :          0 :         default:
    2922                 :          0 :                 vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT;
    2923                 :          0 :                 break;
    2924                 :            :         }
    2925                 :            : 
    2926                 :            :         /* don't require special VHT peer rates */
    2927                 :          0 :         vht_oper->basic_mcs_set = cpu_to_le16(0xffff);
    2928                 :            : 
    2929                 :          0 :         return pos + sizeof(struct ieee80211_vht_operation);
    2930                 :            : }
    2931                 :            : 
    2932                 :          0 : u8 *ieee80211_ie_build_he_oper(u8 *pos)
    2933                 :            : {
    2934                 :          0 :         struct ieee80211_he_operation *he_oper;
    2935                 :          0 :         u32 he_oper_params;
    2936                 :            : 
    2937                 :          0 :         *pos++ = WLAN_EID_EXTENSION;
    2938                 :          0 :         *pos++ = 1 + sizeof(struct ieee80211_he_operation);
    2939                 :          0 :         *pos++ = WLAN_EID_EXT_HE_OPERATION;
    2940                 :            : 
    2941                 :          0 :         he_oper_params = 0;
    2942                 :          0 :         he_oper_params |= u32_encode_bits(1023, /* disabled */
    2943                 :            :                                 IEEE80211_HE_OPERATION_RTS_THRESHOLD_MASK);
    2944                 :          0 :         he_oper_params |= u32_encode_bits(1,
    2945                 :            :                                 IEEE80211_HE_OPERATION_ER_SU_DISABLE);
    2946                 :          0 :         he_oper_params |= u32_encode_bits(1,
    2947                 :            :                                 IEEE80211_HE_OPERATION_BSS_COLOR_DISABLED);
    2948                 :            : 
    2949                 :          0 :         he_oper = (struct ieee80211_he_operation *)pos;
    2950                 :          0 :         he_oper->he_oper_params = cpu_to_le32(he_oper_params);
    2951                 :            : 
    2952                 :            :         /* don't require special HE peer rates */
    2953                 :          0 :         he_oper->he_mcs_nss_set = cpu_to_le16(0xffff);
    2954                 :            : 
    2955                 :            :         /* TODO add VHT operational and 6GHz operational subelement? */
    2956                 :            : 
    2957                 :          0 :         return pos + sizeof(struct ieee80211_vht_operation);
    2958                 :            : }
    2959                 :            : 
    2960                 :          0 : bool ieee80211_chandef_ht_oper(const struct ieee80211_ht_operation *ht_oper,
    2961                 :            :                                struct cfg80211_chan_def *chandef)
    2962                 :            : {
    2963                 :          0 :         enum nl80211_channel_type channel_type;
    2964                 :            : 
    2965         [ #  # ]:          0 :         if (!ht_oper)
    2966                 :            :                 return false;
    2967                 :            : 
    2968   [ #  #  #  # ]:          0 :         switch (ht_oper->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) {
    2969                 :            :         case IEEE80211_HT_PARAM_CHA_SEC_NONE:
    2970                 :            :                 channel_type = NL80211_CHAN_HT20;
    2971                 :            :                 break;
    2972                 :          0 :         case IEEE80211_HT_PARAM_CHA_SEC_ABOVE:
    2973                 :          0 :                 channel_type = NL80211_CHAN_HT40PLUS;
    2974                 :          0 :                 break;
    2975                 :          0 :         case IEEE80211_HT_PARAM_CHA_SEC_BELOW:
    2976                 :          0 :                 channel_type = NL80211_CHAN_HT40MINUS;
    2977                 :          0 :                 break;
    2978                 :            :         default:
    2979                 :            :                 channel_type = NL80211_CHAN_NO_HT;
    2980                 :            :                 return false;
    2981                 :            :         }
    2982                 :            : 
    2983                 :          0 :         cfg80211_chandef_create(chandef, chandef->chan, channel_type);
    2984                 :          0 :         return true;
    2985                 :            : }
    2986                 :            : 
    2987                 :          0 : bool ieee80211_chandef_vht_oper(struct ieee80211_hw *hw,
    2988                 :            :                                 const struct ieee80211_vht_operation *oper,
    2989                 :            :                                 const struct ieee80211_ht_operation *htop,
    2990                 :            :                                 struct cfg80211_chan_def *chandef)
    2991                 :            : {
    2992                 :          0 :         struct cfg80211_chan_def new = *chandef;
    2993                 :          0 :         int cf0, cf1;
    2994                 :          0 :         int ccfs0, ccfs1, ccfs2;
    2995                 :          0 :         int ccf0, ccf1;
    2996                 :          0 :         u32 vht_cap;
    2997                 :          0 :         bool support_80_80 = false;
    2998                 :          0 :         bool support_160 = false;
    2999                 :            : 
    3000         [ #  # ]:          0 :         if (!oper || !htop)
    3001                 :            :                 return false;
    3002                 :            : 
    3003                 :          0 :         vht_cap = hw->wiphy->bands[chandef->chan->band]->vht_cap.cap;
    3004                 :          0 :         support_160 = (vht_cap & (IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_MASK |
    3005                 :            :                                   IEEE80211_VHT_CAP_EXT_NSS_BW_MASK));
    3006                 :          0 :         support_80_80 = ((vht_cap &
    3007                 :          0 :                          IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160_80PLUS80MHZ) ||
    3008         [ #  # ]:          0 :                         (vht_cap & IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ &&
    3009   [ #  #  #  # ]:          0 :                          vht_cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) ||
    3010         [ #  # ]:          0 :                         ((vht_cap & IEEE80211_VHT_CAP_EXT_NSS_BW_MASK) >>
    3011                 :            :                                     IEEE80211_VHT_CAP_EXT_NSS_BW_SHIFT > 1));
    3012                 :          0 :         ccfs0 = oper->center_freq_seg0_idx;
    3013                 :          0 :         ccfs1 = oper->center_freq_seg1_idx;
    3014                 :          0 :         ccfs2 = (le16_to_cpu(htop->operation_mode) &
    3015                 :            :                                 IEEE80211_HT_OP_MODE_CCFS2_MASK)
    3016                 :          0 :                         >> IEEE80211_HT_OP_MODE_CCFS2_SHIFT;
    3017                 :            : 
    3018                 :            :         /* when parsing (and we know how to) CCFS1 and CCFS2 are equivalent */
    3019                 :          0 :         ccf0 = ccfs0;
    3020                 :          0 :         ccf1 = ccfs1;
    3021   [ #  #  #  # ]:          0 :         if (!ccfs1 && ieee80211_hw_check(hw, SUPPORTS_VHT_EXT_NSS_BW))
    3022                 :          0 :                 ccf1 = ccfs2;
    3023                 :            : 
    3024                 :          0 :         cf0 = ieee80211_channel_to_frequency(ccf0, chandef->chan->band);
    3025                 :          0 :         cf1 = ieee80211_channel_to_frequency(ccf1, chandef->chan->band);
    3026                 :            : 
    3027   [ #  #  #  #  :          0 :         switch (oper->chan_width) {
                      # ]
    3028                 :            :         case IEEE80211_VHT_CHANWIDTH_USE_HT:
    3029                 :            :                 /* just use HT information directly */
    3030                 :            :                 break;
    3031                 :          0 :         case IEEE80211_VHT_CHANWIDTH_80MHZ:
    3032                 :          0 :                 new.width = NL80211_CHAN_WIDTH_80;
    3033                 :          0 :                 new.center_freq1 = cf0;
    3034                 :            :                 /* If needed, adjust based on the newer interop workaround. */
    3035         [ #  # ]:          0 :                 if (ccf1) {
    3036                 :          0 :                         unsigned int diff;
    3037                 :            : 
    3038                 :          0 :                         diff = abs(ccf1 - ccf0);
    3039         [ #  # ]:          0 :                         if ((diff == 8) && support_160) {
    3040                 :          0 :                                 new.width = NL80211_CHAN_WIDTH_160;
    3041                 :          0 :                                 new.center_freq1 = cf1;
    3042         [ #  # ]:          0 :                         } else if ((diff > 8) && support_80_80) {
    3043                 :          0 :                                 new.width = NL80211_CHAN_WIDTH_80P80;
    3044                 :          0 :                                 new.center_freq2 = cf1;
    3045                 :            :                         }
    3046                 :            :                 }
    3047                 :            :                 break;
    3048                 :          0 :         case IEEE80211_VHT_CHANWIDTH_160MHZ:
    3049                 :            :                 /* deprecated encoding */
    3050                 :          0 :                 new.width = NL80211_CHAN_WIDTH_160;
    3051                 :          0 :                 new.center_freq1 = cf0;
    3052                 :          0 :                 break;
    3053                 :          0 :         case IEEE80211_VHT_CHANWIDTH_80P80MHZ:
    3054                 :            :                 /* deprecated encoding */
    3055                 :          0 :                 new.width = NL80211_CHAN_WIDTH_80P80;
    3056                 :          0 :                 new.center_freq1 = cf0;
    3057                 :          0 :                 new.center_freq2 = cf1;
    3058                 :          0 :                 break;
    3059                 :            :         default:
    3060                 :            :                 return false;
    3061                 :            :         }
    3062                 :            : 
    3063         [ #  # ]:          0 :         if (!cfg80211_chandef_valid(&new))
    3064                 :            :                 return false;
    3065                 :            : 
    3066                 :          0 :         *chandef = new;
    3067                 :          0 :         return true;
    3068                 :            : }
    3069                 :            : 
    3070                 :          0 : int ieee80211_parse_bitrates(struct cfg80211_chan_def *chandef,
    3071                 :            :                              const struct ieee80211_supported_band *sband,
    3072                 :            :                              const u8 *srates, int srates_len, u32 *rates)
    3073                 :            : {
    3074      [ #  #  # ]:          0 :         u32 rate_flags = ieee80211_chandef_rate_flags(chandef);
    3075      [ #  #  # ]:          0 :         int shift = ieee80211_chandef_get_shift(chandef);
    3076                 :          0 :         struct ieee80211_rate *br;
    3077                 :          0 :         int brate, rate, i, j, count = 0;
    3078                 :            : 
    3079                 :          0 :         *rates = 0;
    3080                 :            : 
    3081         [ #  # ]:          0 :         for (i = 0; i < srates_len; i++) {
    3082                 :          0 :                 rate = srates[i] & 0x7f;
    3083                 :            : 
    3084         [ #  # ]:          0 :                 for (j = 0; j < sband->n_bitrates; j++) {
    3085                 :          0 :                         br = &sband->bitrates[j];
    3086         [ #  # ]:          0 :                         if ((rate_flags & br->flags) != rate_flags)
    3087                 :          0 :                                 continue;
    3088                 :            : 
    3089                 :          0 :                         brate = DIV_ROUND_UP(br->bitrate, (1 << shift) * 5);
    3090         [ #  # ]:          0 :                         if (brate == rate) {
    3091                 :          0 :                                 *rates |= BIT(j);
    3092                 :          0 :                                 count++;
    3093                 :          0 :                                 break;
    3094                 :            :                         }
    3095                 :            :                 }
    3096                 :            :         }
    3097                 :          0 :         return count;
    3098                 :            : }
    3099                 :            : 
    3100                 :          0 : int ieee80211_add_srates_ie(struct ieee80211_sub_if_data *sdata,
    3101                 :            :                             struct sk_buff *skb, bool need_basic,
    3102                 :            :                             enum nl80211_band band)
    3103                 :            : {
    3104                 :          0 :         struct ieee80211_local *local = sdata->local;
    3105                 :          0 :         struct ieee80211_supported_band *sband;
    3106                 :          0 :         int rate, shift;
    3107                 :          0 :         u8 i, rates, *pos;
    3108                 :          0 :         u32 basic_rates = sdata->vif.bss_conf.basic_rates;
    3109                 :          0 :         u32 rate_flags;
    3110                 :            : 
    3111                 :          0 :         shift = ieee80211_vif_get_shift(&sdata->vif);
    3112      [ #  #  # ]:          0 :         rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef);
    3113                 :          0 :         sband = local->hw.wiphy->bands[band];
    3114                 :          0 :         rates = 0;
    3115         [ #  # ]:          0 :         for (i = 0; i < sband->n_bitrates; i++) {
    3116         [ #  # ]:          0 :                 if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
    3117                 :          0 :                         continue;
    3118                 :          0 :                 rates++;
    3119                 :            :         }
    3120                 :          0 :         if (rates > 8)
    3121                 :            :                 rates = 8;
    3122                 :            : 
    3123   [ #  #  #  # ]:          0 :         if (skb_tailroom(skb) < rates + 2)
    3124                 :            :                 return -ENOMEM;
    3125                 :            : 
    3126                 :          0 :         pos = skb_put(skb, rates + 2);
    3127                 :          0 :         *pos++ = WLAN_EID_SUPP_RATES;
    3128                 :          0 :         *pos++ = rates;
    3129         [ #  # ]:          0 :         for (i = 0; i < rates; i++) {
    3130                 :          0 :                 u8 basic = 0;
    3131         [ #  # ]:          0 :                 if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
    3132                 :          0 :                         continue;
    3133                 :            : 
    3134   [ #  #  #  # ]:          0 :                 if (need_basic && basic_rates & BIT(i))
    3135                 :          0 :                         basic = 0x80;
    3136                 :          0 :                 rate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
    3137                 :            :                                     5 * (1 << shift));
    3138                 :          0 :                 *pos++ = basic | (u8) rate;
    3139                 :            :         }
    3140                 :            : 
    3141                 :            :         return 0;
    3142                 :            : }
    3143                 :            : 
    3144                 :          0 : int ieee80211_add_ext_srates_ie(struct ieee80211_sub_if_data *sdata,
    3145                 :            :                                 struct sk_buff *skb, bool need_basic,
    3146                 :            :                                 enum nl80211_band band)
    3147                 :            : {
    3148                 :          0 :         struct ieee80211_local *local = sdata->local;
    3149                 :          0 :         struct ieee80211_supported_band *sband;
    3150                 :          0 :         int rate, shift;
    3151                 :          0 :         u8 i, exrates, *pos;
    3152                 :          0 :         u32 basic_rates = sdata->vif.bss_conf.basic_rates;
    3153                 :          0 :         u32 rate_flags;
    3154                 :            : 
    3155      [ #  #  # ]:          0 :         rate_flags = ieee80211_chandef_rate_flags(&sdata->vif.bss_conf.chandef);
    3156                 :          0 :         shift = ieee80211_vif_get_shift(&sdata->vif);
    3157                 :            : 
    3158                 :          0 :         sband = local->hw.wiphy->bands[band];
    3159                 :          0 :         exrates = 0;
    3160         [ #  # ]:          0 :         for (i = 0; i < sband->n_bitrates; i++) {
    3161         [ #  # ]:          0 :                 if ((rate_flags & sband->bitrates[i].flags) != rate_flags)
    3162                 :          0 :                         continue;
    3163                 :          0 :                 exrates++;
    3164                 :            :         }
    3165                 :            : 
    3166         [ #  # ]:          0 :         if (exrates > 8)
    3167                 :          0 :                 exrates -= 8;
    3168                 :            :         else
    3169                 :            :                 exrates = 0;
    3170                 :            : 
    3171   [ #  #  #  # ]:          0 :         if (skb_tailroom(skb) < exrates + 2)
    3172                 :            :                 return -ENOMEM;
    3173                 :            : 
    3174         [ #  # ]:          0 :         if (exrates) {
    3175                 :          0 :                 pos = skb_put(skb, exrates + 2);
    3176                 :          0 :                 *pos++ = WLAN_EID_EXT_SUPP_RATES;
    3177                 :          0 :                 *pos++ = exrates;
    3178         [ #  # ]:          0 :                 for (i = 8; i < sband->n_bitrates; i++) {
    3179                 :          0 :                         u8 basic = 0;
    3180         [ #  # ]:          0 :                         if ((rate_flags & sband->bitrates[i].flags)
    3181                 :            :                             != rate_flags)
    3182                 :          0 :                                 continue;
    3183   [ #  #  #  # ]:          0 :                         if (need_basic && basic_rates & BIT(i))
    3184                 :          0 :                                 basic = 0x80;
    3185                 :          0 :                         rate = DIV_ROUND_UP(sband->bitrates[i].bitrate,
    3186                 :            :                                             5 * (1 << shift));
    3187                 :          0 :                         *pos++ = basic | (u8) rate;
    3188                 :            :                 }
    3189                 :            :         }
    3190                 :            :         return 0;
    3191                 :            : }
    3192                 :            : 
    3193                 :          0 : int ieee80211_ave_rssi(struct ieee80211_vif *vif)
    3194                 :            : {
    3195         [ #  # ]:          0 :         struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
    3196                 :          0 :         struct ieee80211_if_managed *ifmgd = &sdata->u.mgd;
    3197                 :            : 
    3198   [ #  #  #  # ]:          0 :         if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION)) {
    3199                 :            :                 /* non-managed type inferfaces */
    3200                 :            :                 return 0;
    3201                 :            :         }
    3202                 :          0 :         return -ewma_beacon_signal_read(&ifmgd->ave_beacon_signal);
    3203                 :            : }
    3204                 :            : EXPORT_SYMBOL_GPL(ieee80211_ave_rssi);
    3205                 :            : 
    3206                 :         10 : u8 ieee80211_mcs_to_chains(const struct ieee80211_mcs_info *mcs)
    3207                 :            : {
    3208         [ +  - ]:         10 :         if (!mcs)
    3209                 :            :                 return 1;
    3210                 :            : 
    3211                 :            :         /* TODO: consider rx_highest */
    3212                 :            : 
    3213         [ +  - ]:         10 :         if (mcs->rx_mask[3])
    3214                 :            :                 return 4;
    3215         [ +  + ]:         10 :         if (mcs->rx_mask[2])
    3216                 :            :                 return 3;
    3217         [ +  - ]:          6 :         if (mcs->rx_mask[1])
    3218                 :          6 :                 return 2;
    3219                 :            :         return 1;
    3220                 :            : }
    3221                 :            : 
    3222                 :            : /**
    3223                 :            :  * ieee80211_calculate_rx_timestamp - calculate timestamp in frame
    3224                 :            :  * @local: mac80211 hw info struct
    3225                 :            :  * @status: RX status
    3226                 :            :  * @mpdu_len: total MPDU length (including FCS)
    3227                 :            :  * @mpdu_offset: offset into MPDU to calculate timestamp at
    3228                 :            :  *
    3229                 :            :  * This function calculates the RX timestamp at the given MPDU offset, taking
    3230                 :            :  * into account what the RX timestamp was. An offset of 0 will just normalize
    3231                 :            :  * the timestamp to TSF at beginning of MPDU reception.
    3232                 :            :  */
    3233                 :          0 : u64 ieee80211_calculate_rx_timestamp(struct ieee80211_local *local,
    3234                 :            :                                      struct ieee80211_rx_status *status,
    3235                 :            :                                      unsigned int mpdu_len,
    3236                 :            :                                      unsigned int mpdu_offset)
    3237                 :            : {
    3238                 :          0 :         u64 ts = status->mactime;
    3239                 :          0 :         struct rate_info ri;
    3240                 :          0 :         u16 rate;
    3241                 :            : 
    3242   [ #  #  #  #  :          0 :         if (WARN_ON(!ieee80211_have_rx_timestamp(status)))
                   #  # ]
    3243                 :            :                 return 0;
    3244                 :            : 
    3245                 :          0 :         memset(&ri, 0, sizeof(ri));
    3246                 :            : 
    3247                 :          0 :         ri.bw = status->bw;
    3248                 :            : 
    3249                 :            :         /* Fill cfg80211 rate info */
    3250   [ #  #  #  # ]:          0 :         switch (status->encoding) {
    3251                 :          0 :         case RX_ENC_HT:
    3252                 :          0 :                 ri.mcs = status->rate_idx;
    3253                 :          0 :                 ri.flags |= RATE_INFO_FLAGS_MCS;
    3254         [ #  # ]:          0 :                 if (status->enc_flags & RX_ENC_FLAG_SHORT_GI)
    3255                 :          0 :                         ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
    3256                 :            :                 break;
    3257                 :          0 :         case RX_ENC_VHT:
    3258                 :          0 :                 ri.flags |= RATE_INFO_FLAGS_VHT_MCS;
    3259                 :          0 :                 ri.mcs = status->rate_idx;
    3260                 :          0 :                 ri.nss = status->nss;
    3261         [ #  # ]:          0 :                 if (status->enc_flags & RX_ENC_FLAG_SHORT_GI)
    3262                 :          0 :                         ri.flags |= RATE_INFO_FLAGS_SHORT_GI;
    3263                 :            :                 break;
    3264                 :            :         default:
    3265                 :          0 :                 WARN_ON(1);
    3266                 :            :                 /* fall through */
    3267                 :          0 :         case RX_ENC_LEGACY: {
    3268                 :          0 :                 struct ieee80211_supported_band *sband;
    3269                 :          0 :                 int shift = 0;
    3270                 :          0 :                 int bitrate;
    3271                 :            : 
    3272      [ #  #  # ]:          0 :                 switch (status->bw) {
    3273                 :          0 :                 case RATE_INFO_BW_10:
    3274                 :          0 :                         shift = 1;
    3275                 :          0 :                         break;
    3276                 :          0 :                 case RATE_INFO_BW_5:
    3277                 :          0 :                         shift = 2;
    3278                 :          0 :                         break;
    3279                 :            :                 }
    3280                 :            : 
    3281                 :          0 :                 sband = local->hw.wiphy->bands[status->band];
    3282                 :          0 :                 bitrate = sband->bitrates[status->rate_idx].bitrate;
    3283                 :          0 :                 ri.legacy = DIV_ROUND_UP(bitrate, (1 << shift));
    3284                 :            : 
    3285         [ #  # ]:          0 :                 if (status->flag & RX_FLAG_MACTIME_PLCP_START) {
    3286                 :            :                         /* TODO: handle HT/VHT preambles */
    3287         [ #  # ]:          0 :                         if (status->band == NL80211_BAND_5GHZ) {
    3288                 :          0 :                                 ts += 20 << shift;
    3289                 :          0 :                                 mpdu_offset += 2;
    3290         [ #  # ]:          0 :                         } else if (status->enc_flags & RX_ENC_FLAG_SHORTPRE) {
    3291                 :          0 :                                 ts += 96;
    3292                 :            :                         } else {
    3293                 :          0 :                                 ts += 192;
    3294                 :            :                         }
    3295                 :            :                 }
    3296                 :            :                 break;
    3297                 :            :                 }
    3298                 :            :         }
    3299                 :            : 
    3300                 :          0 :         rate = cfg80211_calculate_bitrate(&ri);
    3301   [ #  #  #  #  :          0 :         if (WARN_ONCE(!rate,
                   #  # ]
    3302                 :            :                       "Invalid bitrate: flags=0x%llx, idx=%d, vht_nss=%d\n",
    3303                 :            :                       (unsigned long long)status->flag, status->rate_idx,
    3304                 :            :                       status->nss))
    3305                 :            :                 return 0;
    3306                 :            : 
    3307                 :            :         /* rewind from end of MPDU */
    3308         [ #  # ]:          0 :         if (status->flag & RX_FLAG_MACTIME_END)
    3309                 :          0 :                 ts -= mpdu_len * 8 * 10 / rate;
    3310                 :            : 
    3311                 :          0 :         ts += mpdu_offset * 8 * 10 / rate;
    3312                 :            : 
    3313                 :          0 :         return ts;
    3314                 :            : }
    3315                 :            : 
    3316                 :          0 : void ieee80211_dfs_cac_cancel(struct ieee80211_local *local)
    3317                 :            : {
    3318                 :          0 :         struct ieee80211_sub_if_data *sdata;
    3319                 :          0 :         struct cfg80211_chan_def chandef;
    3320                 :            : 
    3321                 :            :         /* for interface list, to avoid linking iflist_mtx and chanctx_mtx */
    3322   [ #  #  #  # ]:          0 :         ASSERT_RTNL();
    3323                 :            : 
    3324                 :          0 :         mutex_lock(&local->mtx);
    3325         [ #  # ]:          0 :         list_for_each_entry(sdata, &local->interfaces, list) {
    3326                 :            :                 /* it might be waiting for the local->mtx, but then
    3327                 :            :                  * by the time it gets it, sdata->wdev.cac_started
    3328                 :            :                  * will no longer be true
    3329                 :            :                  */
    3330                 :          0 :                 cancel_delayed_work(&sdata->dfs_cac_timer_work);
    3331                 :            : 
    3332         [ #  # ]:          0 :                 if (sdata->wdev.cac_started) {
    3333                 :          0 :                         chandef = sdata->vif.bss_conf.chandef;
    3334                 :          0 :                         ieee80211_vif_release_channel(sdata);
    3335                 :          0 :                         cfg80211_cac_event(sdata->dev,
    3336                 :            :                                            &chandef,
    3337                 :            :                                            NL80211_RADAR_CAC_ABORTED,
    3338                 :            :                                            GFP_KERNEL);
    3339                 :            :                 }
    3340                 :            :         }
    3341                 :          0 :         mutex_unlock(&local->mtx);
    3342                 :          0 : }
    3343                 :            : 
    3344                 :          0 : void ieee80211_dfs_radar_detected_work(struct work_struct *work)
    3345                 :            : {
    3346                 :          0 :         struct ieee80211_local *local =
    3347                 :          0 :                 container_of(work, struct ieee80211_local, radar_detected_work);
    3348                 :          0 :         struct cfg80211_chan_def chandef = local->hw.conf.chandef;
    3349                 :          0 :         struct ieee80211_chanctx *ctx;
    3350                 :          0 :         int num_chanctx = 0;
    3351                 :            : 
    3352                 :          0 :         mutex_lock(&local->chanctx_mtx);
    3353         [ #  # ]:          0 :         list_for_each_entry(ctx, &local->chanctx_list, list) {
    3354         [ #  # ]:          0 :                 if (ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER)
    3355                 :          0 :                         continue;
    3356                 :            : 
    3357                 :          0 :                 num_chanctx++;
    3358                 :          0 :                 chandef = ctx->conf.def;
    3359                 :            :         }
    3360                 :          0 :         mutex_unlock(&local->chanctx_mtx);
    3361                 :            : 
    3362                 :          0 :         rtnl_lock();
    3363                 :          0 :         ieee80211_dfs_cac_cancel(local);
    3364                 :          0 :         rtnl_unlock();
    3365                 :            : 
    3366         [ #  # ]:          0 :         if (num_chanctx > 1)
    3367                 :            :                 /* XXX: multi-channel is not supported yet */
    3368                 :          0 :                 WARN_ON(1);
    3369                 :            :         else
    3370                 :          0 :                 cfg80211_radar_event(local->hw.wiphy, &chandef, GFP_KERNEL);
    3371                 :          0 : }
    3372                 :            : 
    3373                 :          0 : void ieee80211_radar_detected(struct ieee80211_hw *hw)
    3374                 :            : {
    3375                 :          0 :         struct ieee80211_local *local = hw_to_local(hw);
    3376                 :            : 
    3377                 :          0 :         trace_api_radar_detected(local);
    3378                 :            : 
    3379                 :          0 :         schedule_work(&local->radar_detected_work);
    3380                 :          0 : }
    3381                 :            : EXPORT_SYMBOL(ieee80211_radar_detected);
    3382                 :            : 
    3383                 :          0 : u32 ieee80211_chandef_downgrade(struct cfg80211_chan_def *c)
    3384                 :            : {
    3385                 :          0 :         u32 ret;
    3386                 :          0 :         int tmp;
    3387                 :            : 
    3388   [ #  #  #  #  :          0 :         switch (c->width) {
                #  #  # ]
    3389                 :          0 :         case NL80211_CHAN_WIDTH_20:
    3390                 :          0 :                 c->width = NL80211_CHAN_WIDTH_20_NOHT;
    3391                 :          0 :                 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
    3392                 :          0 :                 break;
    3393                 :          0 :         case NL80211_CHAN_WIDTH_40:
    3394                 :          0 :                 c->width = NL80211_CHAN_WIDTH_20;
    3395                 :          0 :                 c->center_freq1 = c->chan->center_freq;
    3396                 :          0 :                 ret = IEEE80211_STA_DISABLE_40MHZ |
    3397                 :            :                       IEEE80211_STA_DISABLE_VHT;
    3398                 :          0 :                 break;
    3399                 :          0 :         case NL80211_CHAN_WIDTH_80:
    3400                 :          0 :                 tmp = (30 + c->chan->center_freq - c->center_freq1)/20;
    3401                 :            :                 /* n_P40 */
    3402                 :          0 :                 tmp /= 2;
    3403                 :            :                 /* freq_P40 */
    3404                 :          0 :                 c->center_freq1 = c->center_freq1 - 20 + 40 * tmp;
    3405                 :          0 :                 c->width = NL80211_CHAN_WIDTH_40;
    3406                 :          0 :                 ret = IEEE80211_STA_DISABLE_VHT;
    3407                 :          0 :                 break;
    3408                 :          0 :         case NL80211_CHAN_WIDTH_80P80:
    3409                 :          0 :                 c->center_freq2 = 0;
    3410                 :          0 :                 c->width = NL80211_CHAN_WIDTH_80;
    3411                 :          0 :                 ret = IEEE80211_STA_DISABLE_80P80MHZ |
    3412                 :            :                       IEEE80211_STA_DISABLE_160MHZ;
    3413                 :          0 :                 break;
    3414                 :          0 :         case NL80211_CHAN_WIDTH_160:
    3415                 :            :                 /* n_P20 */
    3416                 :          0 :                 tmp = (70 + c->chan->center_freq - c->center_freq1)/20;
    3417                 :            :                 /* n_P80 */
    3418                 :          0 :                 tmp /= 4;
    3419                 :          0 :                 c->center_freq1 = c->center_freq1 - 40 + 80 * tmp;
    3420                 :          0 :                 c->width = NL80211_CHAN_WIDTH_80;
    3421                 :          0 :                 ret = IEEE80211_STA_DISABLE_80P80MHZ |
    3422                 :            :                       IEEE80211_STA_DISABLE_160MHZ;
    3423                 :          0 :                 break;
    3424                 :            :         default:
    3425                 :            :         case NL80211_CHAN_WIDTH_20_NOHT:
    3426                 :          0 :                 WARN_ON_ONCE(1);
    3427                 :          0 :                 c->width = NL80211_CHAN_WIDTH_20_NOHT;
    3428                 :          0 :                 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
    3429                 :          0 :                 break;
    3430                 :            :         case NL80211_CHAN_WIDTH_5:
    3431                 :            :         case NL80211_CHAN_WIDTH_10:
    3432                 :          0 :                 WARN_ON_ONCE(1);
    3433                 :            :                 /* keep c->width */
    3434                 :          0 :                 ret = IEEE80211_STA_DISABLE_HT | IEEE80211_STA_DISABLE_VHT;
    3435                 :          0 :                 break;
    3436                 :            :         }
    3437                 :            : 
    3438         [ #  # ]:          0 :         WARN_ON_ONCE(!cfg80211_chandef_valid(c));
    3439                 :            : 
    3440                 :          0 :         return ret;
    3441                 :            : }
    3442                 :            : 
    3443                 :            : /*
    3444                 :            :  * Returns true if smps_mode_new is strictly more restrictive than
    3445                 :            :  * smps_mode_old.
    3446                 :            :  */
    3447                 :          0 : bool ieee80211_smps_is_restrictive(enum ieee80211_smps_mode smps_mode_old,
    3448                 :            :                                    enum ieee80211_smps_mode smps_mode_new)
    3449                 :            : {
    3450   [ #  #  #  # ]:          0 :         if (WARN_ON_ONCE(smps_mode_old == IEEE80211_SMPS_AUTOMATIC ||
    3451                 :            :                          smps_mode_new == IEEE80211_SMPS_AUTOMATIC))
    3452                 :            :                 return false;
    3453                 :            : 
    3454   [ #  #  #  # ]:          0 :         switch (smps_mode_old) {
    3455                 :            :         case IEEE80211_SMPS_STATIC:
    3456                 :            :                 return false;
    3457                 :          0 :         case IEEE80211_SMPS_DYNAMIC:
    3458                 :          0 :                 return smps_mode_new == IEEE80211_SMPS_STATIC;
    3459                 :          0 :         case IEEE80211_SMPS_OFF:
    3460                 :          0 :                 return smps_mode_new != IEEE80211_SMPS_OFF;
    3461                 :            :         default:
    3462                 :          0 :                 WARN_ON(1);
    3463                 :            :         }
    3464                 :            : 
    3465                 :          0 :         return false;
    3466                 :            : }
    3467                 :            : 
    3468                 :          0 : int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata,
    3469                 :            :                               struct cfg80211_csa_settings *csa_settings)
    3470                 :            : {
    3471                 :          0 :         struct sk_buff *skb;
    3472                 :          0 :         struct ieee80211_mgmt *mgmt;
    3473                 :          0 :         struct ieee80211_local *local = sdata->local;
    3474                 :          0 :         int freq;
    3475                 :          0 :         int hdr_len = offsetofend(struct ieee80211_mgmt,
    3476                 :            :                                   u.action.u.chan_switch);
    3477                 :          0 :         u8 *pos;
    3478                 :            : 
    3479         [ #  # ]:          0 :         if (sdata->vif.type != NL80211_IFTYPE_ADHOC &&
    3480                 :            :             sdata->vif.type != NL80211_IFTYPE_MESH_POINT)
    3481                 :            :                 return -EOPNOTSUPP;
    3482                 :            : 
    3483                 :          0 :         skb = dev_alloc_skb(local->tx_headroom + hdr_len +
    3484                 :            :                             5 + /* channel switch announcement element */
    3485                 :            :                             3 + /* secondary channel offset element */
    3486                 :          0 :                             5 + /* wide bandwidth channel switch announcement */
    3487                 :            :                             8); /* mesh channel switch parameters element */
    3488         [ #  # ]:          0 :         if (!skb)
    3489                 :            :                 return -ENOMEM;
    3490                 :            : 
    3491                 :          0 :         skb_reserve(skb, local->tx_headroom);
    3492                 :          0 :         mgmt = skb_put_zero(skb, hdr_len);
    3493                 :          0 :         mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
    3494                 :            :                                           IEEE80211_STYPE_ACTION);
    3495                 :            : 
    3496                 :          0 :         eth_broadcast_addr(mgmt->da);
    3497                 :          0 :         memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
    3498                 :          0 :         if (ieee80211_vif_is_mesh(&sdata->vif)) {
    3499                 :            :                 memcpy(mgmt->bssid, sdata->vif.addr, ETH_ALEN);
    3500                 :            :         } else {
    3501                 :          0 :                 struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
    3502                 :          0 :                 memcpy(mgmt->bssid, ifibss->bssid, ETH_ALEN);
    3503                 :            :         }
    3504                 :          0 :         mgmt->u.action.category = WLAN_CATEGORY_SPECTRUM_MGMT;
    3505                 :          0 :         mgmt->u.action.u.chan_switch.action_code = WLAN_ACTION_SPCT_CHL_SWITCH;
    3506                 :          0 :         pos = skb_put(skb, 5);
    3507                 :          0 :         *pos++ = WLAN_EID_CHANNEL_SWITCH;                       /* EID */
    3508                 :          0 :         *pos++ = 3;                                             /* IE length */
    3509                 :          0 :         *pos++ = csa_settings->block_tx ? 1 : 0;             /* CSA mode */
    3510                 :          0 :         freq = csa_settings->chandef.chan->center_freq;
    3511                 :          0 :         *pos++ = ieee80211_frequency_to_channel(freq);          /* channel */
    3512                 :          0 :         *pos++ = csa_settings->count;                                /* count */
    3513                 :            : 
    3514         [ #  # ]:          0 :         if (csa_settings->chandef.width == NL80211_CHAN_WIDTH_40) {
    3515                 :          0 :                 enum nl80211_channel_type ch_type;
    3516                 :            : 
    3517                 :          0 :                 skb_put(skb, 3);
    3518                 :          0 :                 *pos++ = WLAN_EID_SECONDARY_CHANNEL_OFFSET;     /* EID */
    3519                 :          0 :                 *pos++ = 1;                                     /* IE length */
    3520                 :          0 :                 ch_type = cfg80211_get_chandef_type(&csa_settings->chandef);
    3521         [ #  # ]:          0 :                 if (ch_type == NL80211_CHAN_HT40PLUS)
    3522                 :          0 :                         *pos++ = IEEE80211_HT_PARAM_CHA_SEC_ABOVE;
    3523                 :            :                 else
    3524                 :          0 :                         *pos++ = IEEE80211_HT_PARAM_CHA_SEC_BELOW;
    3525                 :            :         }
    3526                 :            : 
    3527         [ #  # ]:          0 :         if (ieee80211_vif_is_mesh(&sdata->vif)) {
    3528                 :            :                 struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
    3529                 :            : 
    3530                 :            :                 skb_put(skb, 8);
    3531                 :            :                 *pos++ = WLAN_EID_CHAN_SWITCH_PARAM;            /* EID */
    3532                 :            :                 *pos++ = 6;                                     /* IE length */
    3533                 :            :                 *pos++ = sdata->u.mesh.mshcfg.dot11MeshTTL;  /* Mesh TTL */
    3534                 :            :                 *pos = 0x00;    /* Mesh Flag: Tx Restrict, Initiator, Reason */
    3535                 :            :                 *pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
    3536                 :            :                 *pos++ |= csa_settings->block_tx ?
    3537                 :            :                           WLAN_EID_CHAN_SWITCH_PARAM_TX_RESTRICT : 0x00;
    3538                 :            :                 put_unaligned_le16(WLAN_REASON_MESH_CHAN, pos); /* Reason Cd */
    3539                 :            :                 pos += 2;
    3540                 :            :                 put_unaligned_le16(ifmsh->pre_value, pos);/* Precedence Value */
    3541                 :            :                 pos += 2;
    3542                 :            :         }
    3543                 :            : 
    3544                 :          0 :         if (csa_settings->chandef.width == NL80211_CHAN_WIDTH_80 ||
    3545         [ #  # ]:          0 :             csa_settings->chandef.width == NL80211_CHAN_WIDTH_80P80 ||
    3546                 :            :             csa_settings->chandef.width == NL80211_CHAN_WIDTH_160) {
    3547                 :          0 :                 skb_put(skb, 5);
    3548                 :          0 :                 ieee80211_ie_build_wide_bw_cs(pos, &csa_settings->chandef);
    3549                 :            :         }
    3550                 :            : 
    3551                 :          0 :         ieee80211_tx_skb(sdata, skb);
    3552                 :          0 :         return 0;
    3553                 :            : }
    3554                 :            : 
    3555                 :          0 : bool ieee80211_cs_valid(const struct ieee80211_cipher_scheme *cs)
    3556                 :            : {
    3557   [ #  #  #  #  :          0 :         return !(cs == NULL || cs->cipher == 0 ||
                   #  # ]
    3558   [ #  #  #  # ]:          0 :                  cs->hdr_len < cs->pn_len + cs->pn_off ||
    3559   [ #  #  #  # ]:          0 :                  cs->hdr_len <= cs->key_idx_off ||
    3560   [ #  #  #  # ]:          0 :                  cs->key_idx_shift > 7 ||
    3561   [ #  #  #  # ]:          0 :                  cs->key_idx_mask == 0);
    3562                 :            : }
    3563                 :            : 
    3564                 :          6 : bool ieee80211_cs_list_valid(const struct ieee80211_cipher_scheme *cs, int n)
    3565                 :            : {
    3566                 :          6 :         int i;
    3567                 :            : 
    3568                 :            :         /* Ensure we have enough iftype bitmap space for all iftype values */
    3569                 :          6 :         WARN_ON((NUM_NL80211_IFTYPES / 8 + 1) > sizeof(cs[0].iftype));
    3570                 :            : 
    3571         [ -  + ]:          6 :         for (i = 0; i < n; i++)
    3572   [ #  #  #  # ]:          0 :                 if (!ieee80211_cs_valid(&cs[i]))
    3573                 :            :                         return false;
    3574                 :            : 
    3575                 :            :         return true;
    3576                 :            : }
    3577                 :            : 
    3578                 :            : const struct ieee80211_cipher_scheme *
    3579                 :          0 : ieee80211_cs_get(struct ieee80211_local *local, u32 cipher,
    3580                 :            :                  enum nl80211_iftype iftype)
    3581                 :            : {
    3582                 :          0 :         const struct ieee80211_cipher_scheme *l = local->hw.cipher_schemes;
    3583                 :          0 :         int n = local->hw.n_cipher_schemes;
    3584                 :          0 :         int i;
    3585                 :          0 :         const struct ieee80211_cipher_scheme *cs = NULL;
    3586                 :            : 
    3587   [ #  #  #  #  :          0 :         for (i = 0; i < n; i++) {
                   #  # ]
    3588   [ #  #  #  #  :          0 :                 if (l[i].cipher == cipher) {
                   #  # ]
    3589                 :            :                         cs = &l[i];
    3590                 :            :                         break;
    3591                 :            :                 }
    3592                 :            :         }
    3593                 :            : 
    3594   [ #  #  #  #  :          0 :         if (!cs || !(cs->iftype & BIT(iftype)))
          #  #  #  #  #  
                #  #  # ]
    3595                 :          0 :                 return NULL;
    3596                 :            : 
    3597                 :            :         return cs;
    3598                 :            : }
    3599                 :            : 
    3600                 :          0 : int ieee80211_cs_headroom(struct ieee80211_local *local,
    3601                 :            :                           struct cfg80211_crypto_settings *crypto,
    3602                 :            :                           enum nl80211_iftype iftype)
    3603                 :            : {
    3604                 :          0 :         const struct ieee80211_cipher_scheme *cs;
    3605                 :          0 :         int headroom = IEEE80211_ENCRYPT_HEADROOM;
    3606                 :          0 :         int i;
    3607                 :            : 
    3608         [ #  # ]:          0 :         for (i = 0; i < crypto->n_ciphers_pairwise; i++) {
    3609                 :          0 :                 cs = ieee80211_cs_get(local, crypto->ciphers_pairwise[i],
    3610                 :            :                                       iftype);
    3611                 :            : 
    3612                 :          0 :                 if (cs && headroom < cs->hdr_len)
    3613                 :            :                         headroom = cs->hdr_len;
    3614                 :            :         }
    3615                 :            : 
    3616                 :          0 :         cs = ieee80211_cs_get(local, crypto->cipher_group, iftype);
    3617                 :          0 :         if (cs && headroom < cs->hdr_len)
    3618                 :            :                 headroom = cs->hdr_len;
    3619                 :            : 
    3620                 :          0 :         return headroom;
    3621                 :            : }
    3622                 :            : 
    3623                 :            : static bool
    3624                 :          0 : ieee80211_extend_noa_desc(struct ieee80211_noa_data *data, u32 tsf, int i)
    3625                 :            : {
    3626                 :          0 :         s32 end = data->desc[i].start + data->desc[i].duration - (tsf + 1);
    3627                 :          0 :         int skip;
    3628                 :            : 
    3629         [ #  # ]:          0 :         if (end > 0)
    3630                 :            :                 return false;
    3631                 :            : 
    3632                 :            :         /* One shot NOA  */
    3633         [ #  # ]:          0 :         if (data->count[i] == 1)
    3634                 :            :                 return false;
    3635                 :            : 
    3636         [ #  # ]:          0 :         if (data->desc[i].interval == 0)
    3637                 :            :                 return false;
    3638                 :            : 
    3639                 :            :         /* End time is in the past, check for repetitions */
    3640                 :          0 :         skip = DIV_ROUND_UP(-end, data->desc[i].interval);
    3641         [ #  # ]:          0 :         if (data->count[i] < 255) {
    3642         [ #  # ]:          0 :                 if (data->count[i] <= skip) {
    3643                 :          0 :                         data->count[i] = 0;
    3644                 :          0 :                         return false;
    3645                 :            :                 }
    3646                 :            : 
    3647                 :          0 :                 data->count[i] -= skip;
    3648                 :            :         }
    3649                 :            : 
    3650                 :          0 :         data->desc[i].start += skip * data->desc[i].interval;
    3651                 :            : 
    3652                 :          0 :         return true;
    3653                 :            : }
    3654                 :            : 
    3655                 :            : static bool
    3656                 :          0 : ieee80211_extend_absent_time(struct ieee80211_noa_data *data, u32 tsf,
    3657                 :            :                              s32 *offset)
    3658                 :            : {
    3659                 :          0 :         bool ret = false;
    3660                 :          0 :         int i;
    3661                 :            : 
    3662         [ #  # ]:          0 :         for (i = 0; i < IEEE80211_P2P_NOA_DESC_MAX; i++) {
    3663                 :          0 :                 s32 cur;
    3664                 :            : 
    3665         [ #  # ]:          0 :                 if (!data->count[i])
    3666                 :          0 :                         continue;
    3667                 :            : 
    3668         [ #  # ]:          0 :                 if (ieee80211_extend_noa_desc(data, tsf + *offset, i))
    3669                 :          0 :                         ret = true;
    3670                 :            : 
    3671                 :          0 :                 cur = data->desc[i].start - tsf;
    3672         [ #  # ]:          0 :                 if (cur > *offset)
    3673                 :          0 :                         continue;
    3674                 :            : 
    3675                 :          0 :                 cur = data->desc[i].start + data->desc[i].duration - tsf;
    3676         [ #  # ]:          0 :                 if (cur > *offset)
    3677                 :          0 :                         *offset = cur;
    3678                 :            :         }
    3679                 :            : 
    3680                 :          0 :         return ret;
    3681                 :            : }
    3682                 :            : 
    3683                 :            : static u32
    3684                 :          0 : ieee80211_get_noa_absent_time(struct ieee80211_noa_data *data, u32 tsf)
    3685                 :            : {
    3686                 :          0 :         s32 offset = 0;
    3687                 :          0 :         int tries = 0;
    3688                 :            :         /*
    3689                 :            :          * arbitrary limit, used to avoid infinite loops when combined NoA
    3690                 :            :          * descriptors cover the full time period.
    3691                 :            :          */
    3692                 :          0 :         int max_tries = 5;
    3693                 :            : 
    3694                 :          0 :         ieee80211_extend_absent_time(data, tsf, &offset);
    3695                 :          0 :         do {
    3696         [ #  # ]:          0 :                 if (!ieee80211_extend_absent_time(data, tsf, &offset))
    3697                 :            :                         break;
    3698                 :            : 
    3699                 :          0 :                 tries++;
    3700         [ #  # ]:          0 :         } while (tries < max_tries);
    3701                 :            : 
    3702                 :          0 :         return offset;
    3703                 :            : }
    3704                 :            : 
    3705                 :          0 : void ieee80211_update_p2p_noa(struct ieee80211_noa_data *data, u32 tsf)
    3706                 :            : {
    3707                 :          0 :         u32 next_offset = BIT(31) - 1;
    3708                 :          0 :         int i;
    3709                 :            : 
    3710                 :          0 :         data->absent = 0;
    3711                 :          0 :         data->has_next_tsf = false;
    3712         [ #  # ]:          0 :         for (i = 0; i < IEEE80211_P2P_NOA_DESC_MAX; i++) {
    3713                 :          0 :                 s32 start;
    3714                 :            : 
    3715         [ #  # ]:          0 :                 if (!data->count[i])
    3716                 :          0 :                         continue;
    3717                 :            : 
    3718                 :          0 :                 ieee80211_extend_noa_desc(data, tsf, i);
    3719                 :          0 :                 start = data->desc[i].start - tsf;
    3720         [ #  # ]:          0 :                 if (start <= 0)
    3721                 :          0 :                         data->absent |= BIT(i);
    3722                 :            : 
    3723                 :          0 :                 if (next_offset > start)
    3724                 :            :                         next_offset = start;
    3725                 :            : 
    3726                 :          0 :                 data->has_next_tsf = true;
    3727                 :            :         }
    3728                 :            : 
    3729         [ #  # ]:          0 :         if (data->absent)
    3730                 :          0 :                 next_offset = ieee80211_get_noa_absent_time(data, tsf);
    3731                 :            : 
    3732                 :          0 :         data->next_tsf = tsf + next_offset;
    3733                 :          0 : }
    3734                 :            : EXPORT_SYMBOL(ieee80211_update_p2p_noa);
    3735                 :            : 
    3736                 :          0 : int ieee80211_parse_p2p_noa(const struct ieee80211_p2p_noa_attr *attr,
    3737                 :            :                             struct ieee80211_noa_data *data, u32 tsf)
    3738                 :            : {
    3739                 :          0 :         int ret = 0;
    3740                 :          0 :         int i;
    3741                 :            : 
    3742                 :          0 :         memset(data, 0, sizeof(*data));
    3743                 :            : 
    3744         [ #  # ]:          0 :         for (i = 0; i < IEEE80211_P2P_NOA_DESC_MAX; i++) {
    3745                 :          0 :                 const struct ieee80211_p2p_noa_desc *desc = &attr->desc[i];
    3746                 :            : 
    3747   [ #  #  #  # ]:          0 :                 if (!desc->count || !desc->duration)
    3748                 :          0 :                         continue;
    3749                 :            : 
    3750                 :          0 :                 data->count[i] = desc->count;
    3751                 :          0 :                 data->desc[i].start = le32_to_cpu(desc->start_time);
    3752                 :          0 :                 data->desc[i].duration = le32_to_cpu(desc->duration);
    3753                 :          0 :                 data->desc[i].interval = le32_to_cpu(desc->interval);
    3754                 :            : 
    3755         [ #  # ]:          0 :                 if (data->count[i] > 1 &&
    3756         [ #  # ]:          0 :                     data->desc[i].interval < data->desc[i].duration)
    3757                 :          0 :                         continue;
    3758                 :            : 
    3759                 :          0 :                 ieee80211_extend_noa_desc(data, tsf, i);
    3760                 :          0 :                 ret++;
    3761                 :            :         }
    3762                 :            : 
    3763         [ #  # ]:          0 :         if (ret)
    3764                 :          0 :                 ieee80211_update_p2p_noa(data, tsf);
    3765                 :            : 
    3766                 :          0 :         return ret;
    3767                 :            : }
    3768                 :            : EXPORT_SYMBOL(ieee80211_parse_p2p_noa);
    3769                 :            : 
    3770                 :          0 : void ieee80211_recalc_dtim(struct ieee80211_local *local,
    3771                 :            :                            struct ieee80211_sub_if_data *sdata)
    3772                 :            : {
    3773                 :          0 :         u64 tsf = drv_get_tsf(local, sdata);
    3774                 :          0 :         u64 dtim_count = 0;
    3775                 :          0 :         u16 beacon_int = sdata->vif.bss_conf.beacon_int * 1024;
    3776                 :          0 :         u8 dtim_period = sdata->vif.bss_conf.dtim_period;
    3777                 :          0 :         struct ps_data *ps;
    3778                 :          0 :         u8 bcns_from_dtim;
    3779                 :            : 
    3780   [ #  #  #  # ]:          0 :         if (tsf == -1ULL || !beacon_int || !dtim_period)
    3781                 :            :                 return;
    3782                 :            : 
    3783         [ #  # ]:          0 :         if (sdata->vif.type == NL80211_IFTYPE_AP ||
    3784                 :            :             sdata->vif.type == NL80211_IFTYPE_AP_VLAN) {
    3785         [ #  # ]:          0 :                 if (!sdata->bss)
    3786                 :            :                         return;
    3787                 :            : 
    3788                 :          0 :                 ps = &sdata->bss->ps;
    3789                 :            :         } else if (ieee80211_vif_is_mesh(&sdata->vif)) {
    3790                 :            :                 ps = &sdata->u.mesh.ps;
    3791                 :            :         } else {
    3792                 :            :                 return;
    3793                 :            :         }
    3794                 :            : 
    3795                 :            :         /*
    3796                 :            :          * actually finds last dtim_count, mac80211 will update in
    3797                 :            :          * __beacon_add_tim().
    3798                 :            :          * dtim_count = dtim_period - (tsf / bcn_int) % dtim_period
    3799                 :            :          */
    3800                 :          0 :         do_div(tsf, beacon_int);
    3801                 :          0 :         bcns_from_dtim = do_div(tsf, dtim_period);
    3802                 :            :         /* just had a DTIM */
    3803         [ #  # ]:          0 :         if (!bcns_from_dtim)
    3804                 :            :                 dtim_count = 0;
    3805                 :            :         else
    3806                 :          0 :                 dtim_count = dtim_period - bcns_from_dtim;
    3807                 :            : 
    3808                 :          0 :         ps->dtim_count = dtim_count;
    3809                 :            : }
    3810                 :            : 
    3811                 :            : static u8 ieee80211_chanctx_radar_detect(struct ieee80211_local *local,
    3812                 :            :                                          struct ieee80211_chanctx *ctx)
    3813                 :            : {
    3814                 :            :         struct ieee80211_sub_if_data *sdata;
    3815                 :            :         u8 radar_detect = 0;
    3816                 :            : 
    3817                 :            :         lockdep_assert_held(&local->chanctx_mtx);
    3818                 :            : 
    3819                 :            :         if (WARN_ON(ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED))
    3820                 :            :                 return 0;
    3821                 :            : 
    3822                 :            :         list_for_each_entry(sdata, &ctx->reserved_vifs, reserved_chanctx_list)
    3823                 :            :                 if (sdata->reserved_radar_required)
    3824                 :            :                         radar_detect |= BIT(sdata->reserved_chandef.width);
    3825                 :            : 
    3826                 :            :         /*
    3827                 :            :          * An in-place reservation context should not have any assigned vifs
    3828                 :            :          * until it replaces the other context.
    3829                 :            :          */
    3830                 :            :         WARN_ON(ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER &&
    3831                 :            :                 !list_empty(&ctx->assigned_vifs));
    3832                 :            : 
    3833                 :            :         list_for_each_entry(sdata, &ctx->assigned_vifs, assigned_chanctx_list)
    3834                 :            :                 if (sdata->radar_required)
    3835                 :            :                         radar_detect |= BIT(sdata->vif.bss_conf.chandef.width);
    3836                 :            : 
    3837                 :            :         return radar_detect;
    3838                 :            : }
    3839                 :            : 
    3840                 :          6 : int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
    3841                 :            :                                  const struct cfg80211_chan_def *chandef,
    3842                 :            :                                  enum ieee80211_chanctx_mode chanmode,
    3843                 :            :                                  u8 radar_detect)
    3844                 :            : {
    3845                 :          6 :         struct ieee80211_local *local = sdata->local;
    3846                 :          6 :         struct ieee80211_sub_if_data *sdata_iter;
    3847                 :          6 :         enum nl80211_iftype iftype = sdata->wdev.iftype;
    3848                 :          6 :         struct ieee80211_chanctx *ctx;
    3849                 :          6 :         int total = 1;
    3850                 :          6 :         struct iface_combination_params params = {
    3851                 :            :                 .radar_detect = radar_detect,
    3852                 :            :         };
    3853                 :            : 
    3854                 :          6 :         lockdep_assert_held(&local->chanctx_mtx);
    3855                 :            : 
    3856   [ -  +  -  +  :          6 :         if (WARN_ON(hweight32(radar_detect) > 1))
                   +  - ]
    3857                 :            :                 return -EINVAL;
    3858                 :            : 
    3859   [ -  +  -  -  :         12 :         if (WARN_ON(chandef && chanmode == IEEE80211_CHANCTX_SHARED &&
             -  +  +  - ]
    3860                 :            :                     !chandef->chan))
    3861                 :            :                 return -EINVAL;
    3862                 :            : 
    3863   [ -  +  +  - ]:          6 :         if (WARN_ON(iftype >= NUM_NL80211_IFTYPES))
    3864                 :            :                 return -EINVAL;
    3865                 :            : 
    3866         [ -  + ]:          6 :         if (sdata->vif.type == NL80211_IFTYPE_AP ||
    3867                 :            :             sdata->vif.type == NL80211_IFTYPE_MESH_POINT) {
    3868                 :            :                 /*
    3869                 :            :                  * always passing this is harmless, since it'll be the
    3870                 :            :                  * same value that cfg80211 finds if it finds the same
    3871                 :            :                  * interface ... and that's always allowed
    3872                 :            :                  */
    3873                 :          0 :                 params.new_beacon_int = sdata->vif.bss_conf.beacon_int;
    3874                 :            :         }
    3875                 :            : 
    3876                 :            :         /* Always allow software iftypes */
    3877         [ -  + ]:          6 :         if (cfg80211_iftype_allowed(local->hw.wiphy, iftype, 0, 1)) {
    3878         [ #  # ]:          0 :                 if (radar_detect)
    3879                 :            :                         return -EINVAL;
    3880                 :          0 :                 return 0;
    3881                 :            :         }
    3882                 :            : 
    3883         [ -  + ]:          6 :         if (chandef)
    3884                 :          0 :                 params.num_different_channels = 1;
    3885                 :            : 
    3886         [ +  - ]:          6 :         if (iftype != NL80211_IFTYPE_UNSPECIFIED)
    3887                 :          6 :                 params.iftype_num[iftype] = 1;
    3888                 :            : 
    3889         [ -  + ]:          6 :         list_for_each_entry(ctx, &local->chanctx_list, list) {
    3890         [ #  # ]:          0 :                 if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
    3891                 :          0 :                         continue;
    3892                 :          0 :                 params.radar_detect |=
    3893                 :          0 :                         ieee80211_chanctx_radar_detect(local, ctx);
    3894         [ #  # ]:          0 :                 if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) {
    3895                 :          0 :                         params.num_different_channels++;
    3896                 :          0 :                         continue;
    3897                 :            :                 }
    3898   [ #  #  #  # ]:          0 :                 if (chandef && chanmode == IEEE80211_CHANCTX_SHARED &&
    3899                 :          0 :                     cfg80211_chandef_compatible(chandef,
    3900                 :          0 :                                                 &ctx->conf.def))
    3901                 :          0 :                         continue;
    3902                 :          0 :                 params.num_different_channels++;
    3903                 :            :         }
    3904                 :            : 
    3905         [ +  + ]:         12 :         list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) {
    3906                 :          6 :                 struct wireless_dev *wdev_iter;
    3907                 :            : 
    3908                 :          6 :                 wdev_iter = &sdata_iter->wdev;
    3909                 :            : 
    3910   [ -  +  -  - ]:          6 :                 if (sdata_iter == sdata ||
    3911         [ #  # ]:          0 :                     !ieee80211_sdata_running(sdata_iter) ||
    3912                 :          0 :                     cfg80211_iftype_allowed(local->hw.wiphy,
    3913                 :            :                                             wdev_iter->iftype, 0, 1))
    3914                 :          6 :                         continue;
    3915                 :            : 
    3916                 :          0 :                 params.iftype_num[wdev_iter->iftype]++;
    3917                 :          0 :                 total++;
    3918                 :            :         }
    3919                 :            : 
    3920   [ +  -  -  + ]:          6 :         if (total == 1 && !params.radar_detect)
    3921                 :            :                 return 0;
    3922                 :            : 
    3923                 :          0 :         return cfg80211_check_combinations(local->hw.wiphy, &params);
    3924                 :            : }
    3925                 :            : 
    3926                 :            : static void
    3927                 :          0 : ieee80211_iter_max_chans(const struct ieee80211_iface_combination *c,
    3928                 :            :                          void *data)
    3929                 :            : {
    3930                 :          0 :         u32 *max_num_different_channels = data;
    3931                 :            : 
    3932                 :          0 :         *max_num_different_channels = max(*max_num_different_channels,
    3933                 :            :                                           c->num_different_channels);
    3934                 :          0 : }
    3935                 :            : 
    3936                 :          0 : int ieee80211_max_num_channels(struct ieee80211_local *local)
    3937                 :            : {
    3938                 :          0 :         struct ieee80211_sub_if_data *sdata;
    3939                 :          0 :         struct ieee80211_chanctx *ctx;
    3940                 :          0 :         u32 max_num_different_channels = 1;
    3941                 :          0 :         int err;
    3942                 :          0 :         struct iface_combination_params params = {0};
    3943                 :            : 
    3944                 :          0 :         lockdep_assert_held(&local->chanctx_mtx);
    3945                 :            : 
    3946         [ #  # ]:          0 :         list_for_each_entry(ctx, &local->chanctx_list, list) {
    3947         [ #  # ]:          0 :                 if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
    3948                 :          0 :                         continue;
    3949                 :            : 
    3950                 :          0 :                 params.num_different_channels++;
    3951                 :            : 
    3952                 :          0 :                 params.radar_detect |=
    3953                 :          0 :                         ieee80211_chanctx_radar_detect(local, ctx);
    3954                 :            :         }
    3955                 :            : 
    3956         [ #  # ]:          0 :         list_for_each_entry_rcu(sdata, &local->interfaces, list)
    3957                 :          0 :                 params.iftype_num[sdata->wdev.iftype]++;
    3958                 :            : 
    3959                 :          0 :         err = cfg80211_iter_combinations(local->hw.wiphy, &params,
    3960                 :            :                                          ieee80211_iter_max_chans,
    3961                 :            :                                          &max_num_different_channels);
    3962         [ #  # ]:          0 :         if (err < 0)
    3963                 :            :                 return err;
    3964                 :            : 
    3965                 :          0 :         return max_num_different_channels;
    3966                 :            : }
    3967                 :            : 
    3968                 :          0 : u8 *ieee80211_add_wmm_info_ie(u8 *buf, u8 qosinfo)
    3969                 :            : {
    3970                 :          0 :         *buf++ = WLAN_EID_VENDOR_SPECIFIC;
    3971                 :          0 :         *buf++ = 7; /* len */
    3972                 :          0 :         *buf++ = 0x00; /* Microsoft OUI 00:50:F2 */
    3973                 :          0 :         *buf++ = 0x50;
    3974                 :          0 :         *buf++ = 0xf2;
    3975                 :          0 :         *buf++ = 2; /* WME */
    3976                 :          0 :         *buf++ = 0; /* WME info */
    3977                 :          0 :         *buf++ = 1; /* WME ver */
    3978                 :          0 :         *buf++ = qosinfo; /* U-APSD no in use */
    3979                 :            : 
    3980                 :          0 :         return buf;
    3981                 :            : }
    3982                 :            : 
    3983                 :          0 : void ieee80211_txq_get_depth(struct ieee80211_txq *txq,
    3984                 :            :                              unsigned long *frame_cnt,
    3985                 :            :                              unsigned long *byte_cnt)
    3986                 :            : {
    3987                 :          0 :         struct txq_info *txqi = to_txq_info(txq);
    3988                 :          0 :         u32 frag_cnt = 0, frag_bytes = 0;
    3989                 :          0 :         struct sk_buff *skb;
    3990                 :            : 
    3991         [ #  # ]:          0 :         skb_queue_walk(&txqi->frags, skb) {
    3992                 :          0 :                 frag_cnt++;
    3993                 :          0 :                 frag_bytes += skb->len;
    3994                 :            :         }
    3995                 :            : 
    3996         [ #  # ]:          0 :         if (frame_cnt)
    3997                 :          0 :                 *frame_cnt = txqi->tin.backlog_packets + frag_cnt;
    3998                 :            : 
    3999         [ #  # ]:          0 :         if (byte_cnt)
    4000                 :          0 :                 *byte_cnt = txqi->tin.backlog_bytes + frag_bytes;
    4001                 :          0 : }
    4002                 :            : EXPORT_SYMBOL(ieee80211_txq_get_depth);
    4003                 :            : 
    4004                 :            : const u8 ieee80211_ac_to_qos_mask[IEEE80211_NUM_ACS] = {
    4005                 :            :         IEEE80211_WMM_IE_STA_QOSINFO_AC_VO,
    4006                 :            :         IEEE80211_WMM_IE_STA_QOSINFO_AC_VI,
    4007                 :            :         IEEE80211_WMM_IE_STA_QOSINFO_AC_BE,
    4008                 :            :         IEEE80211_WMM_IE_STA_QOSINFO_AC_BK
    4009                 :            : };

Generated by: LCOV version 1.14