root/drivers/net/wireless/intel/iwlwifi/mvm/ftm-responder.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. iwl_mvm_ftm_responder_cmd
  2. iwl_mvm_ftm_responder_dyn_cfg_cmd
  3. iwl_mvm_ftm_start_responder
  4. iwl_mvm_ftm_restart_responder
  5. iwl_mvm_ftm_responder_stats

   1 /******************************************************************************
   2  *
   3  * This file is provided under a dual BSD/GPLv2 license.  When using or
   4  * redistributing this file, you may do so under either license.
   5  *
   6  * GPL LICENSE SUMMARY
   7  *
   8  * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
   9  * Copyright (C) 2018 Intel Corporation
  10  *
  11  * This program is free software; you can redistribute it and/or modify
  12  * it under the terms of version 2 of the GNU General Public License as
  13  * published by the Free Software Foundation.
  14  *
  15  * This program is distributed in the hope that it will be useful, but
  16  * WITHOUT ANY WARRANTY; without even the implied warranty of
  17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  18  * General Public License for more details.
  19  *
  20  * The full GNU General Public License is included in this distribution
  21  * in the file called COPYING.
  22  *
  23  * Contact Information:
  24  * Intel Linux Wireless <linuxwifi@intel.com>
  25  * Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
  26  *
  27  * BSD LICENSE
  28  *
  29  * Copyright(c) 2015 - 2017 Intel Deutschland GmbH
  30  * Copyright (C) 2018 Intel Corporation
  31  * All rights reserved.
  32  *
  33  * Redistribution and use in source and binary forms, with or without
  34  * modification, are permitted provided that the following conditions
  35  * are met:
  36  *
  37  *  * Redistributions of source code must retain the above copyright
  38  *    notice, this list of conditions and the following disclaimer.
  39  *  * Redistributions in binary form must reproduce the above copyright
  40  *    notice, this list of conditions and the following disclaimer in
  41  *    the documentation and/or other materials provided with the
  42  *    distribution.
  43  *  * Neither the name Intel Corporation nor the names of its
  44  *    contributors may be used to endorse or promote products derived
  45  *    from this software without specific prior written permission.
  46  *
  47  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  48  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  49  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  50  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  51  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  52  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  53  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  54  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  55  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  56  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  57  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  58  *
  59  *****************************************************************************/
  60 #include <net/cfg80211.h>
  61 #include <linux/etherdevice.h>
  62 #include "mvm.h"
  63 #include "constants.h"
  64 
  65 static int
  66 iwl_mvm_ftm_responder_cmd(struct iwl_mvm *mvm,
  67                           struct ieee80211_vif *vif,
  68                           struct cfg80211_chan_def *chandef)
  69 {
  70         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
  71         struct iwl_tof_responder_config_cmd cmd = {
  72                 .channel_num = chandef->chan->hw_value,
  73                 .cmd_valid_fields =
  74                         cpu_to_le32(IWL_TOF_RESPONDER_CMD_VALID_CHAN_INFO |
  75                                     IWL_TOF_RESPONDER_CMD_VALID_BSSID |
  76                                     IWL_TOF_RESPONDER_CMD_VALID_STA_ID),
  77                 .sta_id = mvmvif->bcast_sta.sta_id,
  78         };
  79 
  80         lockdep_assert_held(&mvm->mutex);
  81 
  82         switch (chandef->width) {
  83         case NL80211_CHAN_WIDTH_20_NOHT:
  84                 cmd.bandwidth = IWL_TOF_BW_20_LEGACY;
  85                 break;
  86         case NL80211_CHAN_WIDTH_20:
  87                 cmd.bandwidth = IWL_TOF_BW_20_HT;
  88                 break;
  89         case NL80211_CHAN_WIDTH_40:
  90                 cmd.bandwidth = IWL_TOF_BW_40;
  91                 cmd.ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
  92                 break;
  93         case NL80211_CHAN_WIDTH_80:
  94                 cmd.bandwidth = IWL_TOF_BW_80;
  95                 cmd.ctrl_ch_position = iwl_mvm_get_ctrl_pos(chandef);
  96                 break;
  97         default:
  98                 WARN_ON(1);
  99                 return -EINVAL;
 100         }
 101 
 102         memcpy(cmd.bssid, vif->addr, ETH_ALEN);
 103 
 104         return iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(TOF_RESPONDER_CONFIG_CMD,
 105                                                     LOCATION_GROUP, 0),
 106                                     0, sizeof(cmd), &cmd);
 107 }
 108 
 109 static int
 110 iwl_mvm_ftm_responder_dyn_cfg_cmd(struct iwl_mvm *mvm,
 111                                   struct ieee80211_vif *vif,
 112                                   struct ieee80211_ftm_responder_params *params)
 113 {
 114         struct iwl_tof_responder_dyn_config_cmd cmd = {
 115                 .lci_len = cpu_to_le32(params->lci_len + 2),
 116                 .civic_len = cpu_to_le32(params->civicloc_len + 2),
 117         };
 118         u8 data[IWL_LCI_CIVIC_IE_MAX_SIZE] = {0};
 119         struct iwl_host_cmd hcmd = {
 120                 .id = iwl_cmd_id(TOF_RESPONDER_DYN_CONFIG_CMD,
 121                                  LOCATION_GROUP, 0),
 122                 .data[0] = &cmd,
 123                 .len[0] = sizeof(cmd),
 124                 .data[1] = &data,
 125                 /* .len[1] set later */
 126                 /* may not be able to DMA from stack */
 127                 .dataflags[1] = IWL_HCMD_DFL_DUP,
 128         };
 129         u32 aligned_lci_len = ALIGN(params->lci_len + 2, 4);
 130         u32 aligned_civicloc_len = ALIGN(params->civicloc_len + 2, 4);
 131         u8 *pos = data;
 132 
 133         lockdep_assert_held(&mvm->mutex);
 134 
 135         if (aligned_lci_len + aligned_civicloc_len > sizeof(data)) {
 136                 IWL_ERR(mvm, "LCI/civicloc data too big (%zd + %zd)\n",
 137                         params->lci_len, params->civicloc_len);
 138                 return -ENOBUFS;
 139         }
 140 
 141         pos[0] = WLAN_EID_MEASURE_REPORT;
 142         pos[1] = params->lci_len;
 143         memcpy(pos + 2, params->lci, params->lci_len);
 144 
 145         pos += aligned_lci_len;
 146         pos[0] = WLAN_EID_MEASURE_REPORT;
 147         pos[1] = params->civicloc_len;
 148         memcpy(pos + 2, params->civicloc, params->civicloc_len);
 149 
 150         hcmd.len[1] = aligned_lci_len + aligned_civicloc_len;
 151 
 152         return iwl_mvm_send_cmd(mvm, &hcmd);
 153 }
 154 
 155 int iwl_mvm_ftm_start_responder(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
 156 {
 157         struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
 158         struct ieee80211_ftm_responder_params *params;
 159         struct ieee80211_chanctx_conf ctx, *pctx;
 160         u16 *phy_ctxt_id;
 161         struct iwl_mvm_phy_ctxt *phy_ctxt;
 162         int ret;
 163 
 164         params = vif->bss_conf.ftmr_params;
 165 
 166         lockdep_assert_held(&mvm->mutex);
 167 
 168         if (WARN_ON_ONCE(!vif->bss_conf.ftm_responder))
 169                 return -EINVAL;
 170 
 171         if (vif->p2p || vif->type != NL80211_IFTYPE_AP ||
 172             !mvmvif->ap_ibss_active) {
 173                 IWL_ERR(mvm, "Cannot start responder, not in AP mode\n");
 174                 return -EIO;
 175         }
 176 
 177         rcu_read_lock();
 178         pctx = rcu_dereference(vif->chanctx_conf);
 179         /* Copy the ctx to unlock the rcu and send the phy ctxt. We don't care
 180          * about changes in the ctx after releasing the lock because the driver
 181          * is still protected by the mutex. */
 182         ctx = *pctx;
 183         phy_ctxt_id  = (u16 *)pctx->drv_priv;
 184         rcu_read_unlock();
 185 
 186         phy_ctxt = &mvm->phy_ctxts[*phy_ctxt_id];
 187         ret = iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx.def,
 188                                        ctx.rx_chains_static,
 189                                        ctx.rx_chains_dynamic);
 190         if (ret)
 191                 return ret;
 192 
 193         ret = iwl_mvm_ftm_responder_cmd(mvm, vif, &ctx.def);
 194         if (ret)
 195                 return ret;
 196 
 197         if (params)
 198                 ret = iwl_mvm_ftm_responder_dyn_cfg_cmd(mvm, vif, params);
 199 
 200         return ret;
 201 }
 202 
 203 void iwl_mvm_ftm_restart_responder(struct iwl_mvm *mvm,
 204                                    struct ieee80211_vif *vif)
 205 {
 206         if (!vif->bss_conf.ftm_responder)
 207                 return;
 208 
 209         iwl_mvm_ftm_start_responder(mvm, vif);
 210 }
 211 
 212 void iwl_mvm_ftm_responder_stats(struct iwl_mvm *mvm,
 213                                  struct iwl_rx_cmd_buffer *rxb)
 214 {
 215         struct iwl_rx_packet *pkt = rxb_addr(rxb);
 216         struct iwl_ftm_responder_stats *resp = (void *)pkt->data;
 217         struct cfg80211_ftm_responder_stats *stats = &mvm->ftm_resp_stats;
 218         u32 flags = le32_to_cpu(resp->flags);
 219 
 220         if (resp->success_ftm == resp->ftm_per_burst)
 221                 stats->success_num++;
 222         else if (resp->success_ftm >= 2)
 223                 stats->partial_num++;
 224         else
 225                 stats->failed_num++;
 226 
 227         if ((flags & FTM_RESP_STAT_ASAP_REQ) &&
 228             (flags & FTM_RESP_STAT_ASAP_RESP))
 229                 stats->asap_num++;
 230 
 231         if (flags & FTM_RESP_STAT_NON_ASAP_RESP)
 232                 stats->non_asap_num++;
 233 
 234         stats->total_duration_ms += le32_to_cpu(resp->duration) / USEC_PER_MSEC;
 235 
 236         if (flags & FTM_RESP_STAT_TRIGGER_UNKNOWN)
 237                 stats->unknown_triggers_num++;
 238 
 239         if (flags & FTM_RESP_STAT_DUP)
 240                 stats->reschedule_requests_num++;
 241 
 242         if (flags & FTM_RESP_STAT_NON_ASAP_OUT_WIN)
 243                 stats->out_of_window_triggers_num++;
 244 }

/* [<][>][^][v][top][bottom][index][help] */