LCOV - code coverage report
Current view: top level - net/mac80211 - scan.c (source / functions) Hit Total Coverage
Test: combined.info Lines: 0 686 0.0 %
Date: 2022-04-01 13:59:58 Functions: 0 30 0.0 %
Branches: 0 379 0.0 %

           Branch data     Line data    Source code
       1                 :            : // SPDX-License-Identifier: GPL-2.0-only
       2                 :            : /*
       3                 :            :  * Scanning implementation
       4                 :            :  *
       5                 :            :  * Copyright 2003, Jouni Malinen <jkmaline@cc.hut.fi>
       6                 :            :  * Copyright 2004, Instant802 Networks, Inc.
       7                 :            :  * Copyright 2005, Devicescape Software, Inc.
       8                 :            :  * Copyright 2006-2007  Jiri Benc <jbenc@suse.cz>
       9                 :            :  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
      10                 :            :  * Copyright 2013-2015  Intel Mobile Communications GmbH
      11                 :            :  * Copyright 2016-2017  Intel Deutschland GmbH
      12                 :            :  * Copyright (C) 2018-2019 Intel Corporation
      13                 :            :  */
      14                 :            : 
      15                 :            : #include <linux/if_arp.h>
      16                 :            : #include <linux/etherdevice.h>
      17                 :            : #include <linux/rtnetlink.h>
      18                 :            : #include <net/sch_generic.h>
      19                 :            : #include <linux/slab.h>
      20                 :            : #include <linux/export.h>
      21                 :            : #include <linux/random.h>
      22                 :            : #include <net/mac80211.h>
      23                 :            : 
      24                 :            : #include "ieee80211_i.h"
      25                 :            : #include "driver-ops.h"
      26                 :            : #include "mesh.h"
      27                 :            : 
      28                 :            : #define IEEE80211_PROBE_DELAY (HZ / 33)
      29                 :            : #define IEEE80211_CHANNEL_TIME (HZ / 33)
      30                 :            : #define IEEE80211_PASSIVE_CHANNEL_TIME (HZ / 9)
      31                 :            : 
      32                 :          0 : void ieee80211_rx_bss_put(struct ieee80211_local *local,
      33                 :            :                           struct ieee80211_bss *bss)
      34                 :            : {
      35         [ #  # ]:          0 :         if (!bss)
      36                 :            :                 return;
      37                 :          0 :         cfg80211_put_bss(local->hw.wiphy,
      38                 :          0 :                          container_of((void *)bss, struct cfg80211_bss, priv));
      39                 :            : }
      40                 :            : 
      41                 :          0 : static bool is_uapsd_supported(struct ieee802_11_elems *elems)
      42                 :            : {
      43                 :          0 :         u8 qos_info;
      44                 :            : 
      45   [ #  #  #  # ]:          0 :         if (elems->wmm_info && elems->wmm_info_len == 7
      46         [ #  # ]:          0 :             && elems->wmm_info[5] == 1)
      47                 :          0 :                 qos_info = elems->wmm_info[6];
      48   [ #  #  #  # ]:          0 :         else if (elems->wmm_param && elems->wmm_param_len == 24
      49         [ #  # ]:          0 :                  && elems->wmm_param[5] == 1)
      50                 :          0 :                 qos_info = elems->wmm_param[6];
      51                 :            :         else
      52                 :            :                 /* no valid wmm information or parameter element found */
      53                 :            :                 return false;
      54                 :            : 
      55                 :          0 :         return qos_info & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD;
      56                 :            : }
      57                 :            : 
      58                 :            : static void
      59                 :          0 : ieee80211_update_bss_from_elems(struct ieee80211_local *local,
      60                 :            :                                 struct ieee80211_bss *bss,
      61                 :            :                                 struct ieee802_11_elems *elems,
      62                 :            :                                 struct ieee80211_rx_status *rx_status,
      63                 :            :                                 bool beacon)
      64                 :            : {
      65                 :          0 :         int clen, srlen;
      66                 :            : 
      67         [ #  # ]:          0 :         if (beacon)
      68                 :          0 :                 bss->device_ts_beacon = rx_status->device_timestamp;
      69                 :            :         else
      70                 :          0 :                 bss->device_ts_presp = rx_status->device_timestamp;
      71                 :            : 
      72         [ #  # ]:          0 :         if (elems->parse_error) {
      73         [ #  # ]:          0 :                 if (beacon)
      74                 :          0 :                         bss->corrupt_data |= IEEE80211_BSS_CORRUPT_BEACON;
      75                 :            :                 else
      76                 :          0 :                         bss->corrupt_data |= IEEE80211_BSS_CORRUPT_PROBE_RESP;
      77                 :            :         } else {
      78         [ #  # ]:          0 :                 if (beacon)
      79                 :          0 :                         bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_BEACON;
      80                 :            :                 else
      81                 :          0 :                         bss->corrupt_data &= ~IEEE80211_BSS_CORRUPT_PROBE_RESP;
      82                 :            :         }
      83                 :            : 
      84                 :            :         /* save the ERP value so that it is available at association time */
      85   [ #  #  #  # ]:          0 :         if (elems->erp_info && (!elems->parse_error ||
      86         [ #  # ]:          0 :                                 !(bss->valid_data & IEEE80211_BSS_VALID_ERP))) {
      87                 :          0 :                 bss->erp_value = elems->erp_info[0];
      88                 :          0 :                 bss->has_erp_value = true;
      89         [ #  # ]:          0 :                 if (!elems->parse_error)
      90                 :          0 :                         bss->valid_data |= IEEE80211_BSS_VALID_ERP;
      91                 :            :         }
      92                 :            : 
      93                 :            :         /* replace old supported rates if we get new values */
      94         [ #  # ]:          0 :         if (!elems->parse_error ||
      95         [ #  # ]:          0 :             !(bss->valid_data & IEEE80211_BSS_VALID_RATES)) {
      96                 :          0 :                 srlen = 0;
      97         [ #  # ]:          0 :                 if (elems->supp_rates) {
      98                 :          0 :                         clen = IEEE80211_MAX_SUPP_RATES;
      99         [ #  # ]:          0 :                         if (clen > elems->supp_rates_len)
     100                 :          0 :                                 clen = elems->supp_rates_len;
     101                 :          0 :                         memcpy(bss->supp_rates, elems->supp_rates, clen);
     102                 :          0 :                         srlen += clen;
     103                 :            :                 }
     104         [ #  # ]:          0 :                 if (elems->ext_supp_rates) {
     105                 :          0 :                         clen = IEEE80211_MAX_SUPP_RATES - srlen;
     106                 :          0 :                         if (clen > elems->ext_supp_rates_len)
     107                 :            :                                 clen = elems->ext_supp_rates_len;
     108                 :          0 :                         memcpy(bss->supp_rates + srlen, elems->ext_supp_rates,
     109                 :            :                                clen);
     110                 :          0 :                         srlen += clen;
     111                 :            :                 }
     112         [ #  # ]:          0 :                 if (srlen) {
     113                 :          0 :                         bss->supp_rates_len = srlen;
     114         [ #  # ]:          0 :                         if (!elems->parse_error)
     115                 :          0 :                                 bss->valid_data |= IEEE80211_BSS_VALID_RATES;
     116                 :            :                 }
     117                 :            :         }
     118                 :            : 
     119         [ #  # ]:          0 :         if (!elems->parse_error ||
     120         [ #  # ]:          0 :             !(bss->valid_data & IEEE80211_BSS_VALID_WMM)) {
     121   [ #  #  #  # ]:          0 :                 bss->wmm_used = elems->wmm_param || elems->wmm_info;
     122                 :          0 :                 bss->uapsd_supported = is_uapsd_supported(elems);
     123         [ #  # ]:          0 :                 if (!elems->parse_error)
     124                 :          0 :                         bss->valid_data |= IEEE80211_BSS_VALID_WMM;
     125                 :            :         }
     126                 :            : 
     127         [ #  # ]:          0 :         if (beacon) {
     128                 :          0 :                 struct ieee80211_supported_band *sband =
     129                 :          0 :                         local->hw.wiphy->bands[rx_status->band];
     130         [ #  # ]:          0 :                 if (!(rx_status->encoding == RX_ENC_HT) &&
     131                 :            :                     !(rx_status->encoding == RX_ENC_VHT))
     132                 :          0 :                         bss->beacon_rate =
     133                 :          0 :                                 &sband->bitrates[rx_status->rate_idx];
     134                 :            :         }
     135                 :          0 : }
     136                 :            : 
     137                 :            : struct ieee80211_bss *
     138                 :          0 : ieee80211_bss_info_update(struct ieee80211_local *local,
     139                 :            :                           struct ieee80211_rx_status *rx_status,
     140                 :            :                           struct ieee80211_mgmt *mgmt, size_t len,
     141                 :            :                           struct ieee80211_channel *channel)
     142                 :            : {
     143         [ #  # ]:          0 :         bool beacon = ieee80211_is_beacon(mgmt->frame_control);
     144                 :          0 :         struct cfg80211_bss *cbss, *non_tx_cbss;
     145                 :          0 :         struct ieee80211_bss *bss, *non_tx_bss;
     146                 :          0 :         struct cfg80211_inform_bss bss_meta = {
     147                 :          0 :                 .boottime_ns = rx_status->boottime_ns,
     148                 :            :         };
     149                 :          0 :         bool signal_valid;
     150                 :          0 :         struct ieee80211_sub_if_data *scan_sdata;
     151                 :          0 :         struct ieee802_11_elems elems;
     152                 :          0 :         size_t baselen;
     153                 :          0 :         u8 *elements;
     154                 :            : 
     155         [ #  # ]:          0 :         if (rx_status->flag & RX_FLAG_NO_SIGNAL_VAL)
     156                 :          0 :                 bss_meta.signal = 0; /* invalid signal indication */
     157         [ #  # ]:          0 :         else if (ieee80211_hw_check(&local->hw, SIGNAL_DBM))
     158                 :          0 :                 bss_meta.signal = rx_status->signal * 100;
     159         [ #  # ]:          0 :         else if (ieee80211_hw_check(&local->hw, SIGNAL_UNSPEC))
     160                 :          0 :                 bss_meta.signal = (rx_status->signal * 100) / local->hw.max_signal;
     161                 :            : 
     162                 :          0 :         bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_20;
     163         [ #  # ]:          0 :         if (rx_status->bw == RATE_INFO_BW_5)
     164                 :          0 :                 bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_5;
     165         [ #  # ]:          0 :         else if (rx_status->bw == RATE_INFO_BW_10)
     166                 :          0 :                 bss_meta.scan_width = NL80211_BSS_CHAN_WIDTH_10;
     167                 :            : 
     168                 :          0 :         bss_meta.chan = channel;
     169                 :            : 
     170                 :          0 :         rcu_read_lock();
     171         [ #  # ]:          0 :         scan_sdata = rcu_dereference(local->scan_sdata);
     172   [ #  #  #  # ]:          0 :         if (scan_sdata && scan_sdata->vif.type == NL80211_IFTYPE_STATION &&
     173         [ #  # ]:          0 :             scan_sdata->vif.bss_conf.assoc &&
     174                 :            :             ieee80211_have_rx_timestamp(rx_status)) {
     175                 :          0 :                 bss_meta.parent_tsf =
     176                 :          0 :                         ieee80211_calculate_rx_timestamp(local, rx_status,
     177                 :            :                                                          len + FCS_LEN, 24);
     178                 :          0 :                 ether_addr_copy(bss_meta.parent_bssid,
     179                 :            :                                 scan_sdata->vif.bss_conf.bssid);
     180                 :            :         }
     181                 :          0 :         rcu_read_unlock();
     182                 :            : 
     183                 :          0 :         cbss = cfg80211_inform_bss_frame_data(local->hw.wiphy, &bss_meta,
     184                 :            :                                               mgmt, len, GFP_ATOMIC);
     185         [ #  # ]:          0 :         if (!cbss)
     186                 :            :                 return NULL;
     187                 :            : 
     188         [ #  # ]:          0 :         if (ieee80211_is_probe_resp(mgmt->frame_control)) {
     189                 :          0 :                 elements = mgmt->u.probe_resp.variable;
     190                 :          0 :                 baselen = offsetof(struct ieee80211_mgmt,
     191                 :            :                                    u.probe_resp.variable);
     192                 :            :         } else {
     193                 :          0 :                 baselen = offsetof(struct ieee80211_mgmt, u.beacon.variable);
     194                 :          0 :                 elements = mgmt->u.beacon.variable;
     195                 :            :         }
     196                 :            : 
     197         [ #  # ]:          0 :         if (baselen > len)
     198                 :            :                 return NULL;
     199                 :            : 
     200                 :          0 :         ieee802_11_parse_elems(elements, len - baselen, false, &elems,
     201                 :          0 :                                mgmt->bssid, cbss->bssid);
     202                 :            : 
     203                 :            :         /* In case the signal is invalid update the status */
     204                 :          0 :         signal_valid = abs(channel->center_freq - cbss->channel->center_freq)
     205                 :          0 :                 <= local->hw.wiphy->max_adj_channel_rssi_comp;
     206         [ #  # ]:          0 :         if (!signal_valid)
     207                 :          0 :                 rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
     208                 :            : 
     209                 :          0 :         bss = (void *)cbss->priv;
     210                 :          0 :         ieee80211_update_bss_from_elems(local, bss, &elems, rx_status, beacon);
     211                 :            : 
     212         [ #  # ]:          0 :         list_for_each_entry(non_tx_cbss, &cbss->nontrans_list, nontrans_list) {
     213                 :          0 :                 non_tx_bss = (void *)non_tx_cbss->priv;
     214                 :            : 
     215                 :          0 :                 ieee80211_update_bss_from_elems(local, non_tx_bss, &elems,
     216                 :            :                                                 rx_status, beacon);
     217                 :            :         }
     218                 :            : 
     219                 :            :         return bss;
     220                 :            : }
     221                 :            : 
     222                 :          0 : static bool ieee80211_scan_accept_presp(struct ieee80211_sub_if_data *sdata,
     223                 :            :                                         u32 scan_flags, const u8 *da)
     224                 :            : {
     225         [ #  # ]:          0 :         if (!sdata)
     226                 :            :                 return false;
     227                 :            :         /* accept broadcast for OCE */
     228   [ #  #  #  # ]:          0 :         if (scan_flags & NL80211_SCAN_FLAG_ACCEPT_BCAST_PROBE_RESP &&
     229                 :            :             is_broadcast_ether_addr(da))
     230                 :            :                 return true;
     231         [ #  # ]:          0 :         if (scan_flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
     232                 :            :                 return true;
     233                 :          0 :         return ether_addr_equal(da, sdata->vif.addr);
     234                 :            : }
     235                 :            : 
     236                 :          0 : void ieee80211_scan_rx(struct ieee80211_local *local, struct sk_buff *skb)
     237                 :            : {
     238         [ #  # ]:          0 :         struct ieee80211_rx_status *rx_status = IEEE80211_SKB_RXCB(skb);
     239                 :          0 :         struct ieee80211_sub_if_data *sdata1, *sdata2;
     240                 :          0 :         struct ieee80211_mgmt *mgmt = (void *)skb->data;
     241                 :          0 :         struct ieee80211_bss *bss;
     242                 :          0 :         struct ieee80211_channel *channel;
     243                 :            : 
     244   [ #  #  #  # ]:          0 :         if (skb->len < 24 ||
     245   [ #  #  #  # ]:          0 :             (!ieee80211_is_probe_resp(mgmt->frame_control) &&
     246                 :            :              !ieee80211_is_beacon(mgmt->frame_control)))
     247                 :            :                 return;
     248                 :            : 
     249         [ #  # ]:          0 :         sdata1 = rcu_dereference(local->scan_sdata);
     250                 :          0 :         sdata2 = rcu_dereference(local->sched_scan_sdata);
     251                 :            : 
     252         [ #  # ]:          0 :         if (likely(!sdata1 && !sdata2))
     253                 :            :                 return;
     254                 :            : 
     255         [ #  # ]:          0 :         if (ieee80211_is_probe_resp(mgmt->frame_control)) {
     256                 :          0 :                 struct cfg80211_scan_request *scan_req;
     257                 :          0 :                 struct cfg80211_sched_scan_request *sched_scan_req;
     258                 :          0 :                 u32 scan_req_flags = 0, sched_scan_req_flags = 0;
     259                 :            : 
     260         [ #  # ]:          0 :                 scan_req = rcu_dereference(local->scan_req);
     261                 :          0 :                 sched_scan_req = rcu_dereference(local->sched_scan_req);
     262                 :            : 
     263         [ #  # ]:          0 :                 if (scan_req)
     264                 :          0 :                         scan_req_flags = scan_req->flags;
     265                 :            : 
     266         [ #  # ]:          0 :                 if (sched_scan_req)
     267                 :          0 :                         sched_scan_req_flags = sched_scan_req->flags;
     268                 :            : 
     269                 :            :                 /* ignore ProbeResp to foreign address or non-bcast (OCE)
     270                 :            :                  * unless scanning with randomised address
     271                 :            :                  */
     272                 :          0 :                 if (!ieee80211_scan_accept_presp(sdata1, scan_req_flags,
     273         [ #  # ]:          0 :                                                  mgmt->da) &&
     274         [ #  # ]:          0 :                     !ieee80211_scan_accept_presp(sdata2, sched_scan_req_flags,
     275                 :            :                                                  mgmt->da))
     276                 :            :                         return;
     277                 :            :         }
     278                 :            : 
     279                 :          0 :         channel = ieee80211_get_channel(local->hw.wiphy, rx_status->freq);
     280                 :            : 
     281   [ #  #  #  # ]:          0 :         if (!channel || channel->flags & IEEE80211_CHAN_DISABLED)
     282                 :            :                 return;
     283                 :            : 
     284                 :          0 :         bss = ieee80211_bss_info_update(local, rx_status,
     285                 :          0 :                                         mgmt, skb->len,
     286                 :            :                                         channel);
     287         [ #  # ]:          0 :         if (bss)
     288                 :          0 :                 ieee80211_rx_bss_put(local, bss);
     289                 :            : }
     290                 :            : 
     291                 :            : static void
     292                 :          0 : ieee80211_prepare_scan_chandef(struct cfg80211_chan_def *chandef,
     293                 :            :                                enum nl80211_bss_scan_width scan_width)
     294                 :            : {
     295                 :          0 :         memset(chandef, 0, sizeof(*chandef));
     296      [ #  #  # ]:          0 :         switch (scan_width) {
     297                 :          0 :         case NL80211_BSS_CHAN_WIDTH_5:
     298                 :          0 :                 chandef->width = NL80211_CHAN_WIDTH_5;
     299                 :          0 :                 break;
     300                 :          0 :         case NL80211_BSS_CHAN_WIDTH_10:
     301                 :          0 :                 chandef->width = NL80211_CHAN_WIDTH_10;
     302                 :          0 :                 break;
     303                 :          0 :         default:
     304                 :          0 :                 chandef->width = NL80211_CHAN_WIDTH_20_NOHT;
     305                 :          0 :                 break;
     306                 :            :         }
     307                 :          0 : }
     308                 :            : 
     309                 :            : /* return false if no more work */
     310                 :          0 : static bool ieee80211_prep_hw_scan(struct ieee80211_local *local)
     311                 :            : {
     312                 :          0 :         struct cfg80211_scan_request *req;
     313                 :          0 :         struct cfg80211_chan_def chandef;
     314                 :          0 :         u8 bands_used = 0;
     315                 :          0 :         int i, ielen, n_chans;
     316                 :          0 :         u32 flags = 0;
     317                 :            : 
     318                 :          0 :         req = rcu_dereference_protected(local->scan_req,
     319                 :            :                                         lockdep_is_held(&local->mtx));
     320                 :            : 
     321         [ #  # ]:          0 :         if (test_bit(SCAN_HW_CANCELLED, &local->scanning))
     322                 :            :                 return false;
     323                 :            : 
     324         [ #  # ]:          0 :         if (ieee80211_hw_check(&local->hw, SINGLE_SCAN_ON_ALL_BANDS)) {
     325         [ #  # ]:          0 :                 for (i = 0; i < req->n_channels; i++) {
     326                 :          0 :                         local->hw_scan_req->req.channels[i] = req->channels[i];
     327                 :          0 :                         bands_used |= BIT(req->channels[i]->band);
     328                 :            :                 }
     329                 :            : 
     330                 :          0 :                 n_chans = req->n_channels;
     331                 :            :         } else {
     332                 :          0 :                 do {
     333         [ #  # ]:          0 :                         if (local->hw_scan_band == NUM_NL80211_BANDS)
     334                 :            :                                 return false;
     335                 :            : 
     336                 :            :                         n_chans = 0;
     337                 :            : 
     338         [ #  # ]:          0 :                         for (i = 0; i < req->n_channels; i++) {
     339                 :          0 :                                 if (req->channels[i]->band !=
     340         [ #  # ]:          0 :                                     local->hw_scan_band)
     341                 :          0 :                                         continue;
     342                 :          0 :                                 local->hw_scan_req->req.channels[n_chans] =
     343                 :            :                                                         req->channels[i];
     344                 :          0 :                                 n_chans++;
     345                 :          0 :                                 bands_used |= BIT(req->channels[i]->band);
     346                 :            :                         }
     347                 :            : 
     348                 :          0 :                         local->hw_scan_band++;
     349         [ #  # ]:          0 :                 } while (!n_chans);
     350                 :            :         }
     351                 :            : 
     352                 :          0 :         local->hw_scan_req->req.n_channels = n_chans;
     353                 :          0 :         ieee80211_prepare_scan_chandef(&chandef, req->scan_width);
     354                 :            : 
     355         [ #  # ]:          0 :         if (req->flags & NL80211_SCAN_FLAG_MIN_PREQ_CONTENT)
     356                 :          0 :                 flags |= IEEE80211_PROBE_FLAG_MIN_CONTENT;
     357                 :            : 
     358                 :          0 :         ielen = ieee80211_build_preq_ies(local,
     359                 :          0 :                                          (u8 *)local->hw_scan_req->req.ie,
     360                 :          0 :                                          local->hw_scan_ies_bufsize,
     361                 :          0 :                                          &local->hw_scan_req->ies,
     362                 :            :                                          req->ie, req->ie_len,
     363                 :          0 :                                          bands_used, req->rates, &chandef,
     364                 :            :                                          flags);
     365                 :          0 :         local->hw_scan_req->req.ie_len = ielen;
     366                 :          0 :         local->hw_scan_req->req.no_cck = req->no_cck;
     367                 :          0 :         ether_addr_copy(local->hw_scan_req->req.mac_addr, req->mac_addr);
     368                 :          0 :         ether_addr_copy(local->hw_scan_req->req.mac_addr_mask,
     369                 :            :                         req->mac_addr_mask);
     370                 :          0 :         ether_addr_copy(local->hw_scan_req->req.bssid, req->bssid);
     371                 :            : 
     372                 :          0 :         return true;
     373                 :            : }
     374                 :            : 
     375                 :          0 : static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
     376                 :            : {
     377                 :          0 :         struct ieee80211_local *local = hw_to_local(hw);
     378                 :          0 :         bool hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
     379                 :          0 :         bool was_scanning = local->scanning;
     380                 :          0 :         struct cfg80211_scan_request *scan_req;
     381                 :          0 :         struct ieee80211_sub_if_data *scan_sdata;
     382                 :          0 :         struct ieee80211_sub_if_data *sdata;
     383                 :            : 
     384                 :          0 :         lockdep_assert_held(&local->mtx);
     385                 :            : 
     386                 :            :         /*
     387                 :            :          * It's ok to abort a not-yet-running scan (that
     388                 :            :          * we have one at all will be verified by checking
     389                 :            :          * local->scan_req next), but not to complete it
     390                 :            :          * successfully.
     391                 :            :          */
     392   [ #  #  #  #  :          0 :         if (WARN_ON(!local->scanning && !aborted))
             #  #  #  # ]
     393                 :          0 :                 aborted = true;
     394                 :            : 
     395   [ #  #  #  # ]:          0 :         if (WARN_ON(!local->scan_req))
     396                 :            :                 return;
     397                 :            : 
     398   [ #  #  #  # ]:          0 :         if (hw_scan && !aborted &&
     399         [ #  # ]:          0 :             !ieee80211_hw_check(&local->hw, SINGLE_SCAN_ON_ALL_BANDS) &&
     400                 :          0 :             ieee80211_prep_hw_scan(local)) {
     401                 :          0 :                 int rc;
     402                 :            : 
     403                 :          0 :                 rc = drv_hw_scan(local,
     404                 :          0 :                         rcu_dereference_protected(local->scan_sdata,
     405                 :            :                                                   lockdep_is_held(&local->mtx)),
     406                 :            :                         local->hw_scan_req);
     407                 :            : 
     408         [ #  # ]:          0 :                 if (rc == 0)
     409                 :            :                         return;
     410                 :            : 
     411                 :            :                 /* HW scan failed and is going to be reported as aborted,
     412                 :            :                  * so clear old scan info.
     413                 :            :                  */
     414                 :          0 :                 memset(&local->scan_info, 0, sizeof(local->scan_info));
     415                 :          0 :                 aborted = true;
     416                 :            :         }
     417                 :            : 
     418                 :          0 :         kfree(local->hw_scan_req);
     419                 :          0 :         local->hw_scan_req = NULL;
     420                 :            : 
     421                 :          0 :         scan_req = rcu_dereference_protected(local->scan_req,
     422                 :            :                                              lockdep_is_held(&local->mtx));
     423                 :            : 
     424         [ #  # ]:          0 :         if (scan_req != local->int_scan_req) {
     425                 :          0 :                 local->scan_info.aborted = aborted;
     426                 :          0 :                 cfg80211_scan_done(scan_req, &local->scan_info);
     427                 :            :         }
     428                 :          0 :         RCU_INIT_POINTER(local->scan_req, NULL);
     429                 :            : 
     430                 :          0 :         scan_sdata = rcu_dereference_protected(local->scan_sdata,
     431                 :            :                                                lockdep_is_held(&local->mtx));
     432                 :          0 :         RCU_INIT_POINTER(local->scan_sdata, NULL);
     433                 :            : 
     434                 :          0 :         local->scanning = 0;
     435                 :          0 :         local->scan_chandef.chan = NULL;
     436                 :            : 
     437                 :            :         /* Set power back to normal operating levels. */
     438                 :          0 :         ieee80211_hw_config(local, 0);
     439                 :            : 
     440         [ #  # ]:          0 :         if (!hw_scan) {
     441                 :          0 :                 ieee80211_configure_filter(local);
     442                 :          0 :                 drv_sw_scan_complete(local, scan_sdata);
     443                 :          0 :                 ieee80211_offchannel_return(local);
     444                 :            :         }
     445                 :            : 
     446                 :          0 :         ieee80211_recalc_idle(local);
     447                 :            : 
     448                 :          0 :         ieee80211_mlme_notify_scan_completed(local);
     449                 :          0 :         ieee80211_ibss_notify_scan_completed(local);
     450                 :            : 
     451                 :            :         /* Requeue all the work that might have been ignored while
     452                 :            :          * the scan was in progress; if there was none this will
     453                 :            :          * just be a no-op for the particular interface.
     454                 :            :          */
     455         [ #  # ]:          0 :         list_for_each_entry_rcu(sdata, &local->interfaces, list) {
     456         [ #  # ]:          0 :                 if (ieee80211_sdata_running(sdata))
     457                 :          0 :                         ieee80211_queue_work(&sdata->local->hw, &sdata->work);
     458                 :            :         }
     459                 :            : 
     460         [ #  # ]:          0 :         if (was_scanning)
     461                 :          0 :                 ieee80211_start_next_roc(local);
     462                 :            : }
     463                 :            : 
     464                 :          0 : void ieee80211_scan_completed(struct ieee80211_hw *hw,
     465                 :            :                               struct cfg80211_scan_info *info)
     466                 :            : {
     467                 :          0 :         struct ieee80211_local *local = hw_to_local(hw);
     468                 :            : 
     469                 :          0 :         trace_api_scan_completed(local, info->aborted);
     470                 :            : 
     471                 :          0 :         set_bit(SCAN_COMPLETED, &local->scanning);
     472         [ #  # ]:          0 :         if (info->aborted)
     473                 :          0 :                 set_bit(SCAN_ABORTED, &local->scanning);
     474                 :            : 
     475                 :          0 :         memcpy(&local->scan_info, info, sizeof(*info));
     476                 :            : 
     477                 :          0 :         ieee80211_queue_delayed_work(&local->hw, &local->scan_work, 0);
     478                 :          0 : }
     479                 :            : EXPORT_SYMBOL(ieee80211_scan_completed);
     480                 :            : 
     481                 :          0 : static int ieee80211_start_sw_scan(struct ieee80211_local *local,
     482                 :            :                                    struct ieee80211_sub_if_data *sdata)
     483                 :            : {
     484                 :            :         /* Software scan is not supported in multi-channel cases */
     485         [ #  # ]:          0 :         if (local->use_chanctx)
     486                 :            :                 return -EOPNOTSUPP;
     487                 :            : 
     488                 :            :         /*
     489                 :            :          * Hardware/driver doesn't support hw_scan, so use software
     490                 :            :          * scanning instead. First send a nullfunc frame with power save
     491                 :            :          * bit on so that AP will buffer the frames for us while we are not
     492                 :            :          * listening, then send probe requests to each channel and wait for
     493                 :            :          * the responses. After all channels are scanned, tune back to the
     494                 :            :          * original channel and send a nullfunc frame with power save bit
     495                 :            :          * off to trigger the AP to send us all the buffered frames.
     496                 :            :          *
     497                 :            :          * Note that while local->sw_scanning is true everything else but
     498                 :            :          * nullfunc frames and probe requests will be dropped in
     499                 :            :          * ieee80211_tx_h_check_assoc().
     500                 :            :          */
     501                 :          0 :         drv_sw_scan_start(local, sdata, local->scan_addr);
     502                 :            : 
     503                 :          0 :         local->leave_oper_channel_time = jiffies;
     504                 :          0 :         local->next_scan_state = SCAN_DECISION;
     505                 :          0 :         local->scan_channel_idx = 0;
     506                 :            : 
     507                 :          0 :         ieee80211_offchannel_stop_vifs(local);
     508                 :            : 
     509                 :            :         /* ensure nullfunc is transmitted before leaving operating channel */
     510                 :          0 :         ieee80211_flush_queues(local, NULL, false);
     511                 :            : 
     512                 :          0 :         ieee80211_configure_filter(local);
     513                 :            : 
     514                 :            :         /* We need to set power level at maximum rate for scanning. */
     515                 :          0 :         ieee80211_hw_config(local, 0);
     516                 :            : 
     517                 :          0 :         ieee80211_queue_delayed_work(&local->hw,
     518                 :            :                                      &local->scan_work, 0);
     519                 :            : 
     520                 :          0 :         return 0;
     521                 :            : }
     522                 :            : 
     523                 :            : static bool __ieee80211_can_leave_ch(struct ieee80211_sub_if_data *sdata)
     524                 :            : {
     525                 :            :         struct ieee80211_local *local = sdata->local;
     526                 :            :         struct ieee80211_sub_if_data *sdata_iter;
     527                 :            : 
     528                 :            :         if (!ieee80211_is_radar_required(local))
     529                 :            :                 return true;
     530                 :            : 
     531                 :            :         if (!regulatory_pre_cac_allowed(local->hw.wiphy))
     532                 :            :                 return false;
     533                 :            : 
     534                 :            :         mutex_lock(&local->iflist_mtx);
     535                 :            :         list_for_each_entry(sdata_iter, &local->interfaces, list) {
     536                 :            :                 if (sdata_iter->wdev.cac_started) {
     537                 :            :                         mutex_unlock(&local->iflist_mtx);
     538                 :            :                         return false;
     539                 :            :                 }
     540                 :            :         }
     541                 :            :         mutex_unlock(&local->iflist_mtx);
     542                 :            : 
     543                 :            :         return true;
     544                 :            : }
     545                 :            : 
     546                 :          0 : static bool ieee80211_can_scan(struct ieee80211_local *local,
     547                 :            :                                struct ieee80211_sub_if_data *sdata)
     548                 :            : {
     549         [ #  # ]:          0 :         if (!__ieee80211_can_leave_ch(sdata))
     550                 :            :                 return false;
     551                 :            : 
     552         [ #  # ]:          0 :         if (!list_empty(&local->roc_list))
     553                 :            :                 return false;
     554                 :            : 
     555         [ #  # ]:          0 :         if (sdata->vif.type == NL80211_IFTYPE_STATION &&
     556         [ #  # ]:          0 :             sdata->u.mgd.flags & IEEE80211_STA_CONNECTION_POLL)
     557                 :          0 :                 return false;
     558                 :            : 
     559                 :            :         return true;
     560                 :            : }
     561                 :            : 
     562                 :          0 : void ieee80211_run_deferred_scan(struct ieee80211_local *local)
     563                 :            : {
     564                 :          0 :         lockdep_assert_held(&local->mtx);
     565                 :            : 
     566   [ #  #  #  # ]:          0 :         if (!local->scan_req || local->scanning)
     567                 :            :                 return;
     568                 :            : 
     569         [ #  # ]:          0 :         if (!ieee80211_can_scan(local,
     570                 :          0 :                                 rcu_dereference_protected(
     571                 :            :                                         local->scan_sdata,
     572                 :            :                                         lockdep_is_held(&local->mtx))))
     573                 :            :                 return;
     574                 :            : 
     575                 :          0 :         ieee80211_queue_delayed_work(&local->hw, &local->scan_work,
     576                 :            :                                      round_jiffies_relative(0));
     577                 :            : }
     578                 :            : 
     579                 :          0 : static void ieee80211_send_scan_probe_req(struct ieee80211_sub_if_data *sdata,
     580                 :            :                                           const u8 *src, const u8 *dst,
     581                 :            :                                           const u8 *ssid, size_t ssid_len,
     582                 :            :                                           const u8 *ie, size_t ie_len,
     583                 :            :                                           u32 ratemask, u32 flags, u32 tx_flags,
     584                 :            :                                           struct ieee80211_channel *channel)
     585                 :            : {
     586                 :          0 :         struct sk_buff *skb;
     587                 :          0 :         u32 txdata_flags = 0;
     588                 :            : 
     589                 :          0 :         skb = ieee80211_build_probe_req(sdata, src, dst, ratemask, channel,
     590                 :            :                                         ssid, ssid_len,
     591                 :            :                                         ie, ie_len, flags);
     592                 :            : 
     593         [ #  # ]:          0 :         if (skb) {
     594         [ #  # ]:          0 :                 if (flags & IEEE80211_PROBE_FLAG_RANDOM_SN) {
     595                 :          0 :                         struct ieee80211_hdr *hdr = (void *)skb->data;
     596                 :          0 :                         u16 sn = get_random_u32();
     597                 :            : 
     598                 :          0 :                         txdata_flags |= IEEE80211_TX_NO_SEQNO;
     599                 :          0 :                         hdr->seq_ctrl =
     600                 :          0 :                                 cpu_to_le16(IEEE80211_SN_TO_SEQ(sn));
     601                 :            :                 }
     602                 :          0 :                 IEEE80211_SKB_CB(skb)->flags |= tx_flags;
     603                 :          0 :                 ieee80211_tx_skb_tid_band(sdata, skb, 7, channel->band,
     604                 :            :                                           txdata_flags);
     605                 :            :         }
     606                 :          0 : }
     607                 :            : 
     608                 :          0 : static void ieee80211_scan_state_send_probe(struct ieee80211_local *local,
     609                 :            :                                             unsigned long *next_delay)
     610                 :            : {
     611                 :          0 :         int i;
     612                 :          0 :         struct ieee80211_sub_if_data *sdata;
     613                 :          0 :         struct cfg80211_scan_request *scan_req;
     614                 :          0 :         enum nl80211_band band = local->hw.conf.chandef.chan->band;
     615                 :          0 :         u32 flags = 0, tx_flags;
     616                 :            : 
     617                 :          0 :         scan_req = rcu_dereference_protected(local->scan_req,
     618                 :            :                                              lockdep_is_held(&local->mtx));
     619                 :            : 
     620                 :          0 :         tx_flags = IEEE80211_TX_INTFL_OFFCHAN_TX_OK;
     621         [ #  # ]:          0 :         if (scan_req->no_cck)
     622                 :          0 :                 tx_flags |= IEEE80211_TX_CTL_NO_CCK_RATE;
     623         [ #  # ]:          0 :         if (scan_req->flags & NL80211_SCAN_FLAG_MIN_PREQ_CONTENT)
     624                 :          0 :                 flags |= IEEE80211_PROBE_FLAG_MIN_CONTENT;
     625         [ #  # ]:          0 :         if (scan_req->flags & NL80211_SCAN_FLAG_RANDOM_SN)
     626                 :          0 :                 flags |= IEEE80211_PROBE_FLAG_RANDOM_SN;
     627                 :            : 
     628                 :          0 :         sdata = rcu_dereference_protected(local->scan_sdata,
     629                 :            :                                           lockdep_is_held(&local->mtx));
     630                 :            : 
     631         [ #  # ]:          0 :         for (i = 0; i < scan_req->n_ssids; i++)
     632                 :          0 :                 ieee80211_send_scan_probe_req(
     633                 :          0 :                         sdata, local->scan_addr, scan_req->bssid,
     634                 :          0 :                         scan_req->ssids[i].ssid, scan_req->ssids[i].ssid_len,
     635                 :            :                         scan_req->ie, scan_req->ie_len,
     636                 :            :                         scan_req->rates[band], flags,
     637                 :            :                         tx_flags, local->hw.conf.chandef.chan);
     638                 :            : 
     639                 :            :         /*
     640                 :            :          * After sending probe requests, wait for probe responses
     641                 :            :          * on the channel.
     642                 :            :          */
     643                 :          0 :         *next_delay = IEEE80211_CHANNEL_TIME;
     644                 :          0 :         local->next_scan_state = SCAN_DECISION;
     645                 :          0 : }
     646                 :            : 
     647                 :          0 : static int __ieee80211_start_scan(struct ieee80211_sub_if_data *sdata,
     648                 :            :                                   struct cfg80211_scan_request *req)
     649                 :            : {
     650                 :          0 :         struct ieee80211_local *local = sdata->local;
     651                 :          0 :         bool hw_scan = local->ops->hw_scan;
     652                 :          0 :         int rc;
     653                 :            : 
     654                 :          0 :         lockdep_assert_held(&local->mtx);
     655                 :            : 
     656         [ #  # ]:          0 :         if (local->scan_req)
     657                 :            :                 return -EBUSY;
     658                 :            : 
     659         [ #  # ]:          0 :         if (!__ieee80211_can_leave_ch(sdata))
     660                 :            :                 return -EBUSY;
     661                 :            : 
     662         [ #  # ]:          0 :         if (!ieee80211_can_scan(local, sdata)) {
     663                 :            :                 /* wait for the work to finish/time out */
     664                 :          0 :                 rcu_assign_pointer(local->scan_req, req);
     665                 :          0 :                 rcu_assign_pointer(local->scan_sdata, sdata);
     666                 :          0 :                 return 0;
     667                 :            :         }
     668                 :            : 
     669                 :          0 :  again:
     670         [ #  # ]:          0 :         if (hw_scan) {
     671                 :          0 :                 u8 *ies;
     672                 :            : 
     673                 :          0 :                 local->hw_scan_ies_bufsize = local->scan_ies_len + req->ie_len;
     674                 :            : 
     675         [ #  # ]:          0 :                 if (ieee80211_hw_check(&local->hw, SINGLE_SCAN_ON_ALL_BANDS)) {
     676                 :            :                         int i, n_bands = 0;
     677                 :            :                         u8 bands_counted = 0;
     678                 :            : 
     679         [ #  # ]:          0 :                         for (i = 0; i < req->n_channels; i++) {
     680         [ #  # ]:          0 :                                 if (bands_counted & BIT(req->channels[i]->band))
     681                 :          0 :                                         continue;
     682                 :          0 :                                 bands_counted |= BIT(req->channels[i]->band);
     683                 :          0 :                                 n_bands++;
     684                 :            :                         }
     685                 :            : 
     686                 :          0 :                         local->hw_scan_ies_bufsize *= n_bands;
     687                 :            :                 }
     688                 :            : 
     689                 :          0 :                 local->hw_scan_req = kmalloc(
     690                 :          0 :                                 sizeof(*local->hw_scan_req) +
     691                 :          0 :                                 req->n_channels * sizeof(req->channels[0]) +
     692         [ #  # ]:          0 :                                 local->hw_scan_ies_bufsize, GFP_KERNEL);
     693         [ #  # ]:          0 :                 if (!local->hw_scan_req)
     694                 :            :                         return -ENOMEM;
     695                 :            : 
     696                 :          0 :                 local->hw_scan_req->req.ssids = req->ssids;
     697                 :          0 :                 local->hw_scan_req->req.n_ssids = req->n_ssids;
     698                 :          0 :                 ies = (u8 *)local->hw_scan_req +
     699                 :          0 :                         sizeof(*local->hw_scan_req) +
     700                 :          0 :                         req->n_channels * sizeof(req->channels[0]);
     701                 :          0 :                 local->hw_scan_req->req.ie = ies;
     702                 :          0 :                 local->hw_scan_req->req.flags = req->flags;
     703                 :          0 :                 eth_broadcast_addr(local->hw_scan_req->req.bssid);
     704                 :          0 :                 local->hw_scan_req->req.duration = req->duration;
     705                 :          0 :                 local->hw_scan_req->req.duration_mandatory =
     706                 :          0 :                         req->duration_mandatory;
     707                 :            : 
     708                 :          0 :                 local->hw_scan_band = 0;
     709                 :            : 
     710                 :            :                 /*
     711                 :            :                  * After allocating local->hw_scan_req, we must
     712                 :            :                  * go through until ieee80211_prep_hw_scan(), so
     713                 :            :                  * anything that might be changed here and leave
     714                 :            :                  * this function early must not go after this
     715                 :            :                  * allocation.
     716                 :            :                  */
     717                 :            :         }
     718                 :            : 
     719                 :          0 :         rcu_assign_pointer(local->scan_req, req);
     720         [ #  # ]:          0 :         rcu_assign_pointer(local->scan_sdata, sdata);
     721                 :            : 
     722         [ #  # ]:          0 :         if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR)
     723                 :          0 :                 get_random_mask_addr(local->scan_addr,
     724                 :          0 :                                      req->mac_addr,
     725                 :          0 :                                      req->mac_addr_mask);
     726                 :            :         else
     727                 :          0 :                 memcpy(local->scan_addr, sdata->vif.addr, ETH_ALEN);
     728                 :            : 
     729         [ #  # ]:          0 :         if (hw_scan) {
     730                 :          0 :                 __set_bit(SCAN_HW_SCANNING, &local->scanning);
     731         [ #  # ]:          0 :         } else if ((req->n_channels == 1) &&
     732         [ #  # ]:          0 :                    (req->channels[0] == local->_oper_chandef.chan)) {
     733                 :            :                 /*
     734                 :            :                  * If we are scanning only on the operating channel
     735                 :            :                  * then we do not need to stop normal activities
     736                 :            :                  */
     737                 :          0 :                 unsigned long next_delay;
     738                 :            : 
     739                 :          0 :                 __set_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning);
     740                 :            : 
     741                 :          0 :                 ieee80211_recalc_idle(local);
     742                 :            : 
     743                 :            :                 /* Notify driver scan is starting, keep order of operations
     744                 :            :                  * same as normal software scan, in case that matters. */
     745                 :          0 :                 drv_sw_scan_start(local, sdata, local->scan_addr);
     746                 :            : 
     747                 :          0 :                 ieee80211_configure_filter(local); /* accept probe-responses */
     748                 :            : 
     749                 :            :                 /* We need to ensure power level is at max for scanning. */
     750                 :          0 :                 ieee80211_hw_config(local, 0);
     751                 :            : 
     752         [ #  # ]:          0 :                 if ((req->channels[0]->flags & (IEEE80211_CHAN_NO_IR |
     753                 :          0 :                                                 IEEE80211_CHAN_RADAR)) ||
     754         [ #  # ]:          0 :                     !req->n_ssids) {
     755                 :          0 :                         next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
     756                 :            :                 } else {
     757                 :          0 :                         ieee80211_scan_state_send_probe(local, &next_delay);
     758                 :          0 :                         next_delay = IEEE80211_CHANNEL_TIME;
     759                 :            :                 }
     760                 :            : 
     761                 :            :                 /* Now, just wait a bit and we are all done! */
     762                 :          0 :                 ieee80211_queue_delayed_work(&local->hw, &local->scan_work,
     763                 :            :                                              next_delay);
     764                 :          0 :                 return 0;
     765                 :            :         } else {
     766                 :            :                 /* Do normal software scan */
     767                 :          0 :                 __set_bit(SCAN_SW_SCANNING, &local->scanning);
     768                 :            :         }
     769                 :            : 
     770                 :          0 :         ieee80211_recalc_idle(local);
     771                 :            : 
     772         [ #  # ]:          0 :         if (hw_scan) {
     773         [ #  # ]:          0 :                 WARN_ON(!ieee80211_prep_hw_scan(local));
     774                 :          0 :                 rc = drv_hw_scan(local, sdata, local->hw_scan_req);
     775                 :            :         } else {
     776                 :          0 :                 rc = ieee80211_start_sw_scan(local, sdata);
     777                 :            :         }
     778                 :            : 
     779         [ #  # ]:          0 :         if (rc) {
     780                 :          0 :                 kfree(local->hw_scan_req);
     781                 :          0 :                 local->hw_scan_req = NULL;
     782                 :          0 :                 local->scanning = 0;
     783                 :            : 
     784                 :          0 :                 ieee80211_recalc_idle(local);
     785                 :            : 
     786                 :          0 :                 local->scan_req = NULL;
     787                 :          0 :                 RCU_INIT_POINTER(local->scan_sdata, NULL);
     788                 :            :         }
     789                 :            : 
     790         [ #  # ]:          0 :         if (hw_scan && rc == 1) {
     791                 :            :                 /*
     792                 :            :                  * we can't fall back to software for P2P-GO
     793                 :            :                  * as it must update NoA etc.
     794                 :            :                  */
     795   [ #  #  #  # ]:          0 :                 if (ieee80211_vif_type_p2p(&sdata->vif) ==
     796                 :            :                                 NL80211_IFTYPE_P2P_GO)
     797                 :            :                         return -EOPNOTSUPP;
     798                 :          0 :                 hw_scan = false;
     799                 :          0 :                 goto again;
     800                 :            :         }
     801                 :            : 
     802                 :            :         return rc;
     803                 :            : }
     804                 :            : 
     805                 :            : static unsigned long
     806                 :          0 : ieee80211_scan_get_channel_time(struct ieee80211_channel *chan)
     807                 :            : {
     808                 :            :         /*
     809                 :            :          * TODO: channel switching also consumes quite some time,
     810                 :            :          * add that delay as well to get a better estimation
     811                 :            :          */
     812                 :          0 :         if (chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR))
     813                 :          0 :                 return IEEE80211_PASSIVE_CHANNEL_TIME;
     814                 :            :         return IEEE80211_PROBE_DELAY + IEEE80211_CHANNEL_TIME;
     815                 :            : }
     816                 :            : 
     817                 :          0 : static void ieee80211_scan_state_decision(struct ieee80211_local *local,
     818                 :            :                                           unsigned long *next_delay)
     819                 :            : {
     820                 :          0 :         bool associated = false;
     821                 :          0 :         bool tx_empty = true;
     822                 :          0 :         bool bad_latency;
     823                 :          0 :         struct ieee80211_sub_if_data *sdata;
     824                 :          0 :         struct ieee80211_channel *next_chan;
     825                 :          0 :         enum mac80211_scan_state next_scan_state;
     826                 :          0 :         struct cfg80211_scan_request *scan_req;
     827                 :            : 
     828                 :            :         /*
     829                 :            :          * check if at least one STA interface is associated,
     830                 :            :          * check if at least one STA interface has pending tx frames
     831                 :            :          * and grab the lowest used beacon interval
     832                 :            :          */
     833                 :          0 :         mutex_lock(&local->iflist_mtx);
     834         [ #  # ]:          0 :         list_for_each_entry(sdata, &local->interfaces, list) {
     835         [ #  # ]:          0 :                 if (!ieee80211_sdata_running(sdata))
     836                 :          0 :                         continue;
     837                 :            : 
     838         [ #  # ]:          0 :                 if (sdata->vif.type == NL80211_IFTYPE_STATION) {
     839         [ #  # ]:          0 :                         if (sdata->u.mgd.associated) {
     840                 :          0 :                                 associated = true;
     841                 :            : 
     842         [ #  # ]:          0 :                                 if (!qdisc_all_tx_empty(sdata->dev)) {
     843                 :            :                                         tx_empty = false;
     844                 :            :                                         break;
     845                 :            :                                 }
     846                 :            :                         }
     847                 :            :                 }
     848                 :            :         }
     849                 :          0 :         mutex_unlock(&local->iflist_mtx);
     850                 :            : 
     851                 :          0 :         scan_req = rcu_dereference_protected(local->scan_req,
     852                 :            :                                              lockdep_is_held(&local->mtx));
     853                 :            : 
     854                 :          0 :         next_chan = scan_req->channels[local->scan_channel_idx];
     855                 :            : 
     856                 :            :         /*
     857                 :            :          * we're currently scanning a different channel, let's
     858                 :            :          * see if we can scan another channel without interfering
     859                 :            :          * with the current traffic situation.
     860                 :            :          *
     861                 :            :          * Keep good latency, do not stay off-channel more than 125 ms.
     862                 :            :          */
     863                 :            : 
     864   [ #  #  #  # ]:          0 :         bad_latency = time_after(jiffies +
     865                 :            :                                  ieee80211_scan_get_channel_time(next_chan),
     866                 :            :                                  local->leave_oper_channel_time + HZ / 8);
     867                 :            : 
     868         [ #  # ]:          0 :         if (associated && !tx_empty) {
     869         [ #  # ]:          0 :                 if (scan_req->flags & NL80211_SCAN_FLAG_LOW_PRIORITY)
     870                 :            :                         next_scan_state = SCAN_ABORT;
     871                 :            :                 else
     872                 :          0 :                         next_scan_state = SCAN_SUSPEND;
     873         [ #  # ]:          0 :         } else if (associated && bad_latency) {
     874                 :            :                 next_scan_state = SCAN_SUSPEND;
     875                 :            :         } else {
     876                 :          0 :                 next_scan_state = SCAN_SET_CHANNEL;
     877                 :            :         }
     878                 :            : 
     879                 :          0 :         local->next_scan_state = next_scan_state;
     880                 :            : 
     881                 :          0 :         *next_delay = 0;
     882                 :          0 : }
     883                 :            : 
     884                 :          0 : static void ieee80211_scan_state_set_channel(struct ieee80211_local *local,
     885                 :            :                                              unsigned long *next_delay)
     886                 :            : {
     887                 :          0 :         int skip;
     888                 :          0 :         struct ieee80211_channel *chan;
     889                 :          0 :         enum nl80211_bss_scan_width oper_scan_width;
     890                 :          0 :         struct cfg80211_scan_request *scan_req;
     891                 :            : 
     892                 :          0 :         scan_req = rcu_dereference_protected(local->scan_req,
     893                 :            :                                              lockdep_is_held(&local->mtx));
     894                 :            : 
     895                 :          0 :         skip = 0;
     896                 :          0 :         chan = scan_req->channels[local->scan_channel_idx];
     897                 :            : 
     898                 :          0 :         local->scan_chandef.chan = chan;
     899                 :          0 :         local->scan_chandef.center_freq1 = chan->center_freq;
     900                 :          0 :         local->scan_chandef.center_freq2 = 0;
     901   [ #  #  #  # ]:          0 :         switch (scan_req->scan_width) {
     902                 :          0 :         case NL80211_BSS_CHAN_WIDTH_5:
     903                 :          0 :                 local->scan_chandef.width = NL80211_CHAN_WIDTH_5;
     904                 :          0 :                 break;
     905                 :          0 :         case NL80211_BSS_CHAN_WIDTH_10:
     906                 :          0 :                 local->scan_chandef.width = NL80211_CHAN_WIDTH_10;
     907                 :          0 :                 break;
     908                 :          0 :         case NL80211_BSS_CHAN_WIDTH_20:
     909                 :            :                 /* If scanning on oper channel, use whatever channel-type
     910                 :            :                  * is currently in use.
     911                 :            :                  */
     912      [ #  #  # ]:          0 :                 oper_scan_width = cfg80211_chandef_to_scan_width(
     913                 :            :                                         &local->_oper_chandef);
     914   [ #  #  #  # ]:          0 :                 if (chan == local->_oper_chandef.chan &&
     915                 :            :                     oper_scan_width == scan_req->scan_width)
     916                 :          0 :                         local->scan_chandef = local->_oper_chandef;
     917                 :            :                 else
     918                 :          0 :                         local->scan_chandef.width = NL80211_CHAN_WIDTH_20_NOHT;
     919                 :            :                 break;
     920                 :            :         }
     921                 :            : 
     922         [ #  # ]:          0 :         if (ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL))
     923                 :          0 :                 skip = 1;
     924                 :            : 
     925                 :            :         /* advance state machine to next channel/band */
     926                 :          0 :         local->scan_channel_idx++;
     927                 :            : 
     928         [ #  # ]:          0 :         if (skip) {
     929                 :            :                 /* if we skip this channel return to the decision state */
     930                 :          0 :                 local->next_scan_state = SCAN_DECISION;
     931                 :          0 :                 return;
     932                 :            :         }
     933                 :            : 
     934                 :            :         /*
     935                 :            :          * Probe delay is used to update the NAV, cf. 11.1.3.2.2
     936                 :            :          * (which unfortunately doesn't say _why_ step a) is done,
     937                 :            :          * but it waits for the probe delay or until a frame is
     938                 :            :          * received - and the received frame would update the NAV).
     939                 :            :          * For now, we do not support waiting until a frame is
     940                 :            :          * received.
     941                 :            :          *
     942                 :            :          * In any case, it is not necessary for a passive scan.
     943                 :            :          */
     944         [ #  # ]:          0 :         if ((chan->flags & (IEEE80211_CHAN_NO_IR | IEEE80211_CHAN_RADAR)) ||
     945         [ #  # ]:          0 :             !scan_req->n_ssids) {
     946                 :          0 :                 *next_delay = IEEE80211_PASSIVE_CHANNEL_TIME;
     947                 :          0 :                 local->next_scan_state = SCAN_DECISION;
     948                 :          0 :                 return;
     949                 :            :         }
     950                 :            : 
     951                 :            :         /* active scan, send probes */
     952                 :          0 :         *next_delay = IEEE80211_PROBE_DELAY;
     953                 :          0 :         local->next_scan_state = SCAN_SEND_PROBE;
     954                 :            : }
     955                 :            : 
     956                 :          0 : static void ieee80211_scan_state_suspend(struct ieee80211_local *local,
     957                 :            :                                          unsigned long *next_delay)
     958                 :            : {
     959                 :            :         /* switch back to the operating channel */
     960                 :          0 :         local->scan_chandef.chan = NULL;
     961                 :          0 :         ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
     962                 :            : 
     963                 :            :         /* disable PS */
     964                 :          0 :         ieee80211_offchannel_return(local);
     965                 :            : 
     966                 :          0 :         *next_delay = HZ / 5;
     967                 :            :         /* afterwards, resume scan & go to next channel */
     968                 :          0 :         local->next_scan_state = SCAN_RESUME;
     969                 :          0 : }
     970                 :            : 
     971                 :          0 : static void ieee80211_scan_state_resume(struct ieee80211_local *local,
     972                 :            :                                         unsigned long *next_delay)
     973                 :            : {
     974                 :          0 :         ieee80211_offchannel_stop_vifs(local);
     975                 :            : 
     976         [ #  # ]:          0 :         if (local->ops->flush) {
     977                 :          0 :                 ieee80211_flush_queues(local, NULL, false);
     978                 :          0 :                 *next_delay = 0;
     979                 :            :         } else
     980                 :          0 :                 *next_delay = HZ / 10;
     981                 :            : 
     982                 :            :         /* remember when we left the operating channel */
     983                 :          0 :         local->leave_oper_channel_time = jiffies;
     984                 :            : 
     985                 :            :         /* advance to the next channel to be scanned */
     986                 :          0 :         local->next_scan_state = SCAN_SET_CHANNEL;
     987                 :          0 : }
     988                 :            : 
     989                 :          0 : void ieee80211_scan_work(struct work_struct *work)
     990                 :            : {
     991                 :          0 :         struct ieee80211_local *local =
     992                 :          0 :                 container_of(work, struct ieee80211_local, scan_work.work);
     993                 :          0 :         struct ieee80211_sub_if_data *sdata;
     994                 :          0 :         struct cfg80211_scan_request *scan_req;
     995                 :          0 :         unsigned long next_delay = 0;
     996                 :          0 :         bool aborted;
     997                 :            : 
     998                 :          0 :         mutex_lock(&local->mtx);
     999                 :            : 
    1000         [ #  # ]:          0 :         if (!ieee80211_can_run_worker(local)) {
    1001                 :          0 :                 aborted = true;
    1002                 :          0 :                 goto out_complete;
    1003                 :            :         }
    1004                 :            : 
    1005                 :          0 :         sdata = rcu_dereference_protected(local->scan_sdata,
    1006                 :            :                                           lockdep_is_held(&local->mtx));
    1007                 :          0 :         scan_req = rcu_dereference_protected(local->scan_req,
    1008                 :            :                                              lockdep_is_held(&local->mtx));
    1009                 :            : 
    1010                 :            :         /* When scanning on-channel, the first-callback means completed. */
    1011         [ #  # ]:          0 :         if (test_bit(SCAN_ONCHANNEL_SCANNING, &local->scanning)) {
    1012                 :          0 :                 aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);
    1013                 :          0 :                 goto out_complete;
    1014                 :            :         }
    1015                 :            : 
    1016         [ #  # ]:          0 :         if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) {
    1017                 :          0 :                 aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);
    1018                 :          0 :                 goto out_complete;
    1019                 :            :         }
    1020                 :            : 
    1021         [ #  # ]:          0 :         if (!sdata || !scan_req)
    1022                 :          0 :                 goto out;
    1023                 :            : 
    1024         [ #  # ]:          0 :         if (!local->scanning) {
    1025                 :          0 :                 int rc;
    1026                 :            : 
    1027                 :          0 :                 RCU_INIT_POINTER(local->scan_req, NULL);
    1028                 :          0 :                 RCU_INIT_POINTER(local->scan_sdata, NULL);
    1029                 :            : 
    1030                 :          0 :                 rc = __ieee80211_start_scan(sdata, scan_req);
    1031         [ #  # ]:          0 :                 if (rc) {
    1032                 :            :                         /* need to complete scan in cfg80211 */
    1033                 :          0 :                         rcu_assign_pointer(local->scan_req, scan_req);
    1034                 :          0 :                         aborted = true;
    1035                 :          0 :                         goto out_complete;
    1036                 :            :                 } else
    1037                 :          0 :                         goto out;
    1038                 :            :         }
    1039                 :            : 
    1040                 :            :         /*
    1041                 :            :          * as long as no delay is required advance immediately
    1042                 :            :          * without scheduling a new work
    1043                 :            :          */
    1044                 :          0 :         do {
    1045         [ #  # ]:          0 :                 if (!ieee80211_sdata_running(sdata)) {
    1046                 :          0 :                         aborted = true;
    1047                 :          0 :                         goto out_complete;
    1048                 :            :                 }
    1049                 :            : 
    1050   [ #  #  #  #  :          0 :                 switch (local->next_scan_state) {
                #  #  # ]
    1051                 :          0 :                 case SCAN_DECISION:
    1052                 :            :                         /* if no more bands/channels left, complete scan */
    1053         [ #  # ]:          0 :                         if (local->scan_channel_idx >= scan_req->n_channels) {
    1054                 :          0 :                                 aborted = false;
    1055                 :          0 :                                 goto out_complete;
    1056                 :            :                         }
    1057                 :          0 :                         ieee80211_scan_state_decision(local, &next_delay);
    1058                 :          0 :                         break;
    1059                 :          0 :                 case SCAN_SET_CHANNEL:
    1060                 :          0 :                         ieee80211_scan_state_set_channel(local, &next_delay);
    1061                 :          0 :                         break;
    1062                 :          0 :                 case SCAN_SEND_PROBE:
    1063                 :          0 :                         ieee80211_scan_state_send_probe(local, &next_delay);
    1064                 :          0 :                         break;
    1065                 :            :                 case SCAN_SUSPEND:
    1066                 :          0 :                         ieee80211_scan_state_suspend(local, &next_delay);
    1067                 :            :                         break;
    1068                 :          0 :                 case SCAN_RESUME:
    1069                 :          0 :                         ieee80211_scan_state_resume(local, &next_delay);
    1070                 :          0 :                         break;
    1071                 :          0 :                 case SCAN_ABORT:
    1072                 :          0 :                         aborted = true;
    1073                 :          0 :                         goto out_complete;
    1074                 :            :                 }
    1075         [ #  # ]:          0 :         } while (next_delay == 0);
    1076                 :            : 
    1077                 :          0 :         ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay);
    1078                 :          0 :         goto out;
    1079                 :            : 
    1080                 :          0 : out_complete:
    1081                 :          0 :         __ieee80211_scan_completed(&local->hw, aborted);
    1082                 :          0 : out:
    1083                 :          0 :         mutex_unlock(&local->mtx);
    1084                 :          0 : }
    1085                 :            : 
    1086                 :          0 : int ieee80211_request_scan(struct ieee80211_sub_if_data *sdata,
    1087                 :            :                            struct cfg80211_scan_request *req)
    1088                 :            : {
    1089                 :          0 :         int res;
    1090                 :            : 
    1091                 :          0 :         mutex_lock(&sdata->local->mtx);
    1092                 :          0 :         res = __ieee80211_start_scan(sdata, req);
    1093                 :          0 :         mutex_unlock(&sdata->local->mtx);
    1094                 :            : 
    1095                 :          0 :         return res;
    1096                 :            : }
    1097                 :            : 
    1098                 :          0 : int ieee80211_request_ibss_scan(struct ieee80211_sub_if_data *sdata,
    1099                 :            :                                 const u8 *ssid, u8 ssid_len,
    1100                 :            :                                 struct ieee80211_channel **channels,
    1101                 :            :                                 unsigned int n_channels,
    1102                 :            :                                 enum nl80211_bss_scan_width scan_width)
    1103                 :            : {
    1104                 :          0 :         struct ieee80211_local *local = sdata->local;
    1105                 :          0 :         int ret = -EBUSY, i, n_ch = 0;
    1106                 :          0 :         enum nl80211_band band;
    1107                 :            : 
    1108                 :          0 :         mutex_lock(&local->mtx);
    1109                 :            : 
    1110                 :            :         /* busy scanning */
    1111         [ #  # ]:          0 :         if (local->scan_req)
    1112                 :          0 :                 goto unlock;
    1113                 :            : 
    1114                 :            :         /* fill internal scan request */
    1115         [ #  # ]:          0 :         if (!channels) {
    1116                 :            :                 int max_n;
    1117                 :            : 
    1118         [ #  # ]:          0 :                 for (band = 0; band < NUM_NL80211_BANDS; band++) {
    1119         [ #  # ]:          0 :                         if (!local->hw.wiphy->bands[band])
    1120                 :          0 :                                 continue;
    1121                 :            : 
    1122                 :          0 :                         max_n = local->hw.wiphy->bands[band]->n_channels;
    1123         [ #  # ]:          0 :                         for (i = 0; i < max_n; i++) {
    1124                 :          0 :                                 struct ieee80211_channel *tmp_ch =
    1125                 :          0 :                                     &local->hw.wiphy->bands[band]->channels[i];
    1126                 :            : 
    1127         [ #  # ]:          0 :                                 if (tmp_ch->flags & (IEEE80211_CHAN_NO_IR |
    1128                 :            :                                                      IEEE80211_CHAN_DISABLED))
    1129                 :          0 :                                         continue;
    1130                 :            : 
    1131                 :          0 :                                 local->int_scan_req->channels[n_ch] = tmp_ch;
    1132                 :          0 :                                 n_ch++;
    1133                 :            :                         }
    1134                 :            :                 }
    1135                 :            : 
    1136   [ #  #  #  # ]:          0 :                 if (WARN_ON_ONCE(n_ch == 0))
    1137                 :          0 :                         goto unlock;
    1138                 :            : 
    1139                 :          0 :                 local->int_scan_req->n_channels = n_ch;
    1140                 :            :         } else {
    1141         [ #  # ]:          0 :                 for (i = 0; i < n_channels; i++) {
    1142         [ #  # ]:          0 :                         if (channels[i]->flags & (IEEE80211_CHAN_NO_IR |
    1143                 :            :                                                   IEEE80211_CHAN_DISABLED))
    1144                 :          0 :                                 continue;
    1145                 :            : 
    1146                 :          0 :                         local->int_scan_req->channels[n_ch] = channels[i];
    1147                 :          0 :                         n_ch++;
    1148                 :            :                 }
    1149                 :            : 
    1150   [ #  #  #  # ]:          0 :                 if (WARN_ON_ONCE(n_ch == 0))
    1151                 :          0 :                         goto unlock;
    1152                 :            : 
    1153                 :          0 :                 local->int_scan_req->n_channels = n_ch;
    1154                 :            :         }
    1155                 :            : 
    1156                 :          0 :         local->int_scan_req->ssids = &local->scan_ssid;
    1157                 :          0 :         local->int_scan_req->n_ssids = 1;
    1158                 :          0 :         local->int_scan_req->scan_width = scan_width;
    1159                 :          0 :         memcpy(local->int_scan_req->ssids[0].ssid, ssid, IEEE80211_MAX_SSID_LEN);
    1160                 :          0 :         local->int_scan_req->ssids[0].ssid_len = ssid_len;
    1161                 :            : 
    1162                 :          0 :         ret = __ieee80211_start_scan(sdata, sdata->local->int_scan_req);
    1163                 :          0 :  unlock:
    1164                 :          0 :         mutex_unlock(&local->mtx);
    1165                 :          0 :         return ret;
    1166                 :            : }
    1167                 :            : 
    1168                 :            : /*
    1169                 :            :  * Only call this function when a scan can't be queued -- under RTNL.
    1170                 :            :  */
    1171                 :          0 : void ieee80211_scan_cancel(struct ieee80211_local *local)
    1172                 :            : {
    1173                 :            :         /*
    1174                 :            :          * We are canceling software scan, or deferred scan that was not
    1175                 :            :          * yet really started (see __ieee80211_start_scan ).
    1176                 :            :          *
    1177                 :            :          * Regarding hardware scan:
    1178                 :            :          * - we can not call  __ieee80211_scan_completed() as when
    1179                 :            :          *   SCAN_HW_SCANNING bit is set this function change
    1180                 :            :          *   local->hw_scan_req to operate on 5G band, what race with
    1181                 :            :          *   driver which can use local->hw_scan_req
    1182                 :            :          *
    1183                 :            :          * - we can not cancel scan_work since driver can schedule it
    1184                 :            :          *   by ieee80211_scan_completed(..., true) to finish scan
    1185                 :            :          *
    1186                 :            :          * Hence we only call the cancel_hw_scan() callback, but the low-level
    1187                 :            :          * driver is still responsible for calling ieee80211_scan_completed()
    1188                 :            :          * after the scan was completed/aborted.
    1189                 :            :          */
    1190                 :            : 
    1191                 :          0 :         mutex_lock(&local->mtx);
    1192         [ #  # ]:          0 :         if (!local->scan_req)
    1193                 :          0 :                 goto out;
    1194                 :            : 
    1195                 :            :         /*
    1196                 :            :          * We have a scan running and the driver already reported completion,
    1197                 :            :          * but the worker hasn't run yet or is stuck on the mutex - mark it as
    1198                 :            :          * cancelled.
    1199                 :            :          */
    1200   [ #  #  #  # ]:          0 :         if (test_bit(SCAN_HW_SCANNING, &local->scanning) &&
    1201                 :            :             test_bit(SCAN_COMPLETED, &local->scanning)) {
    1202                 :          0 :                 set_bit(SCAN_HW_CANCELLED, &local->scanning);
    1203                 :          0 :                 goto out;
    1204                 :            :         }
    1205                 :            : 
    1206         [ #  # ]:          0 :         if (test_bit(SCAN_HW_SCANNING, &local->scanning)) {
    1207                 :            :                 /*
    1208                 :            :                  * Make sure that __ieee80211_scan_completed doesn't trigger a
    1209                 :            :                  * scan on another band.
    1210                 :            :                  */
    1211                 :          0 :                 set_bit(SCAN_HW_CANCELLED, &local->scanning);
    1212         [ #  # ]:          0 :                 if (local->ops->cancel_hw_scan)
    1213                 :          0 :                         drv_cancel_hw_scan(local,
    1214                 :          0 :                                 rcu_dereference_protected(local->scan_sdata,
    1215                 :            :                                                 lockdep_is_held(&local->mtx)));
    1216                 :          0 :                 goto out;
    1217                 :            :         }
    1218                 :            : 
    1219                 :            :         /*
    1220                 :            :          * If the work is currently running, it must be blocked on
    1221                 :            :          * the mutex, but we'll set scan_sdata = NULL and it'll
    1222                 :            :          * simply exit once it acquires the mutex.
    1223                 :            :          */
    1224                 :          0 :         cancel_delayed_work(&local->scan_work);
    1225                 :            :         /* and clean up */
    1226                 :          0 :         memset(&local->scan_info, 0, sizeof(local->scan_info));
    1227                 :          0 :         __ieee80211_scan_completed(&local->hw, true);
    1228                 :          0 : out:
    1229                 :          0 :         mutex_unlock(&local->mtx);
    1230                 :          0 : }
    1231                 :            : 
    1232                 :          0 : int __ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
    1233                 :            :                                         struct cfg80211_sched_scan_request *req)
    1234                 :            : {
    1235                 :          0 :         struct ieee80211_local *local = sdata->local;
    1236                 :          0 :         struct ieee80211_scan_ies sched_scan_ies = {};
    1237                 :          0 :         struct cfg80211_chan_def chandef;
    1238                 :          0 :         int ret, i, iebufsz, num_bands = 0;
    1239                 :          0 :         u32 rate_masks[NUM_NL80211_BANDS] = {};
    1240                 :          0 :         u8 bands_used = 0;
    1241                 :          0 :         u8 *ie;
    1242                 :          0 :         u32 flags = 0;
    1243                 :            : 
    1244                 :          0 :         iebufsz = local->scan_ies_len + req->ie_len;
    1245                 :            : 
    1246                 :          0 :         lockdep_assert_held(&local->mtx);
    1247                 :            : 
    1248         [ #  # ]:          0 :         if (!local->ops->sched_scan_start)
    1249                 :            :                 return -ENOTSUPP;
    1250                 :            : 
    1251         [ #  # ]:          0 :         for (i = 0; i < NUM_NL80211_BANDS; i++) {
    1252         [ #  # ]:          0 :                 if (local->hw.wiphy->bands[i]) {
    1253                 :          0 :                         bands_used |= BIT(i);
    1254                 :          0 :                         rate_masks[i] = (u32) -1;
    1255                 :          0 :                         num_bands++;
    1256                 :            :                 }
    1257                 :            :         }
    1258                 :            : 
    1259         [ #  # ]:          0 :         if (req->flags & NL80211_SCAN_FLAG_MIN_PREQ_CONTENT)
    1260                 :          0 :                 flags |= IEEE80211_PROBE_FLAG_MIN_CONTENT;
    1261                 :            : 
    1262                 :          0 :         ie = kcalloc(iebufsz, num_bands, GFP_KERNEL);
    1263         [ #  # ]:          0 :         if (!ie) {
    1264                 :          0 :                 ret = -ENOMEM;
    1265                 :          0 :                 goto out;
    1266                 :            :         }
    1267                 :            : 
    1268                 :          0 :         ieee80211_prepare_scan_chandef(&chandef, req->scan_width);
    1269                 :            : 
    1270                 :          0 :         ieee80211_build_preq_ies(local, ie, num_bands * iebufsz,
    1271                 :            :                                  &sched_scan_ies, req->ie,
    1272                 :            :                                  req->ie_len, bands_used, rate_masks, &chandef,
    1273                 :            :                                  flags);
    1274                 :            : 
    1275                 :          0 :         ret = drv_sched_scan_start(local, sdata, req, &sched_scan_ies);
    1276         [ #  # ]:          0 :         if (ret == 0) {
    1277                 :          0 :                 rcu_assign_pointer(local->sched_scan_sdata, sdata);
    1278                 :          0 :                 rcu_assign_pointer(local->sched_scan_req, req);
    1279                 :            :         }
    1280                 :            : 
    1281                 :          0 :         kfree(ie);
    1282                 :            : 
    1283                 :            : out:
    1284         [ #  # ]:          0 :         if (ret) {
    1285                 :            :                 /* Clean in case of failure after HW restart or upon resume. */
    1286                 :          0 :                 RCU_INIT_POINTER(local->sched_scan_sdata, NULL);
    1287                 :          0 :                 RCU_INIT_POINTER(local->sched_scan_req, NULL);
    1288                 :            :         }
    1289                 :            : 
    1290                 :            :         return ret;
    1291                 :            : }
    1292                 :            : 
    1293                 :          0 : int ieee80211_request_sched_scan_start(struct ieee80211_sub_if_data *sdata,
    1294                 :            :                                        struct cfg80211_sched_scan_request *req)
    1295                 :            : {
    1296                 :          0 :         struct ieee80211_local *local = sdata->local;
    1297                 :          0 :         int ret;
    1298                 :            : 
    1299                 :          0 :         mutex_lock(&local->mtx);
    1300                 :            : 
    1301         [ #  # ]:          0 :         if (rcu_access_pointer(local->sched_scan_sdata)) {
    1302                 :          0 :                 mutex_unlock(&local->mtx);
    1303                 :          0 :                 return -EBUSY;
    1304                 :            :         }
    1305                 :            : 
    1306                 :          0 :         ret = __ieee80211_request_sched_scan_start(sdata, req);
    1307                 :            : 
    1308                 :          0 :         mutex_unlock(&local->mtx);
    1309                 :          0 :         return ret;
    1310                 :            : }
    1311                 :            : 
    1312                 :          0 : int ieee80211_request_sched_scan_stop(struct ieee80211_local *local)
    1313                 :            : {
    1314                 :          0 :         struct ieee80211_sub_if_data *sched_scan_sdata;
    1315                 :          0 :         int ret = -ENOENT;
    1316                 :            : 
    1317                 :          0 :         mutex_lock(&local->mtx);
    1318                 :            : 
    1319         [ #  # ]:          0 :         if (!local->ops->sched_scan_stop) {
    1320                 :          0 :                 ret = -ENOTSUPP;
    1321                 :          0 :                 goto out;
    1322                 :            :         }
    1323                 :            : 
    1324                 :            :         /* We don't want to restart sched scan anymore. */
    1325         [ #  # ]:          0 :         RCU_INIT_POINTER(local->sched_scan_req, NULL);
    1326                 :            : 
    1327                 :          0 :         sched_scan_sdata = rcu_dereference_protected(local->sched_scan_sdata,
    1328                 :            :                                                 lockdep_is_held(&local->mtx));
    1329         [ #  # ]:          0 :         if (sched_scan_sdata) {
    1330                 :          0 :                 ret = drv_sched_scan_stop(local, sched_scan_sdata);
    1331         [ #  # ]:          0 :                 if (!ret)
    1332                 :          0 :                         RCU_INIT_POINTER(local->sched_scan_sdata, NULL);
    1333                 :            :         }
    1334                 :          0 : out:
    1335                 :          0 :         mutex_unlock(&local->mtx);
    1336                 :            : 
    1337                 :          0 :         return ret;
    1338                 :            : }
    1339                 :            : 
    1340                 :          0 : void ieee80211_sched_scan_results(struct ieee80211_hw *hw)
    1341                 :            : {
    1342                 :          0 :         struct ieee80211_local *local = hw_to_local(hw);
    1343                 :            : 
    1344                 :          0 :         trace_api_sched_scan_results(local);
    1345                 :            : 
    1346                 :          0 :         cfg80211_sched_scan_results(hw->wiphy, 0);
    1347                 :          0 : }
    1348                 :            : EXPORT_SYMBOL(ieee80211_sched_scan_results);
    1349                 :            : 
    1350                 :          0 : void ieee80211_sched_scan_end(struct ieee80211_local *local)
    1351                 :            : {
    1352                 :          0 :         mutex_lock(&local->mtx);
    1353                 :            : 
    1354         [ #  # ]:          0 :         if (!rcu_access_pointer(local->sched_scan_sdata)) {
    1355                 :          0 :                 mutex_unlock(&local->mtx);
    1356                 :          0 :                 return;
    1357                 :            :         }
    1358                 :            : 
    1359                 :          0 :         RCU_INIT_POINTER(local->sched_scan_sdata, NULL);
    1360                 :            : 
    1361                 :            :         /* If sched scan was aborted by the driver. */
    1362                 :          0 :         RCU_INIT_POINTER(local->sched_scan_req, NULL);
    1363                 :            : 
    1364                 :          0 :         mutex_unlock(&local->mtx);
    1365                 :            : 
    1366                 :          0 :         cfg80211_sched_scan_stopped(local->hw.wiphy, 0);
    1367                 :            : }
    1368                 :            : 
    1369                 :          0 : void ieee80211_sched_scan_stopped_work(struct work_struct *work)
    1370                 :            : {
    1371                 :          0 :         struct ieee80211_local *local =
    1372                 :          0 :                 container_of(work, struct ieee80211_local,
    1373                 :            :                              sched_scan_stopped_work);
    1374                 :            : 
    1375                 :          0 :         ieee80211_sched_scan_end(local);
    1376                 :          0 : }
    1377                 :            : 
    1378                 :          0 : void ieee80211_sched_scan_stopped(struct ieee80211_hw *hw)
    1379                 :            : {
    1380                 :          0 :         struct ieee80211_local *local = hw_to_local(hw);
    1381                 :            : 
    1382                 :          0 :         trace_api_sched_scan_stopped(local);
    1383                 :            : 
    1384                 :            :         /*
    1385                 :            :          * this shouldn't really happen, so for simplicity
    1386                 :            :          * simply ignore it, and let mac80211 reconfigure
    1387                 :            :          * the sched scan later on.
    1388                 :            :          */
    1389         [ #  # ]:          0 :         if (local->in_reconfig)
    1390                 :            :                 return;
    1391                 :            : 
    1392                 :          0 :         schedule_work(&local->sched_scan_stopped_work);
    1393                 :            : }
    1394                 :            : EXPORT_SYMBOL(ieee80211_sched_scan_stopped);

Generated by: LCOV version 1.14