1 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause 2 /* 3 * Copyright (C) 2015-2017 Intel Deutschland GmbH 4 * Copyright (C) 2018-2022 Intel Corporation 5 */ 6 #include <linux/etherdevice.h> 7 #include <linux/math64.h> 8 #include <net/cfg80211.h> 9 #include "mvm.h" 10 #include "iwl-io.h" 11 #include "iwl-prph.h" 12 #include "constants.h" 13 14 struct iwl_mvm_loc_entry { 15 struct list_head list; 16 u8 addr[ETH_ALEN]; 17 u8 lci_len, civic_len; 18 u8 buf[]; 19 }; 20 21 struct iwl_mvm_smooth_entry { 22 struct list_head list; 23 u8 addr[ETH_ALEN]; 24 s64 rtt_avg; 25 u64 host_time; 26 }; 27 28 enum iwl_mvm_pasn_flags { 29 IWL_MVM_PASN_FLAG_HAS_HLTK = BIT(0), 30 }; 31 32 struct iwl_mvm_ftm_pasn_entry { 33 struct list_head list; 34 u8 addr[ETH_ALEN]; 35 u8 hltk[HLTK_11AZ_LEN]; 36 u8 tk[TK_11AZ_LEN]; 37 u8 cipher; 38 u8 tx_pn[IEEE80211_CCMP_PN_LEN]; 39 u8 rx_pn[IEEE80211_CCMP_PN_LEN]; 40 u32 flags; 41 }; 42 43 int iwl_mvm_ftm_add_pasn_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 44 u8 *addr, u32 cipher, u8 *tk, u32 tk_len, 45 u8 *hltk, u32 hltk_len) 46 { 47 struct iwl_mvm_ftm_pasn_entry *pasn = kzalloc(sizeof(*pasn), 48 GFP_KERNEL); 49 u32 expected_tk_len; 50 51 lockdep_assert_held(&mvm->mutex); 52 53 if (!pasn) 54 return -ENOBUFS; 55 56 pasn->cipher = iwl_mvm_cipher_to_location_cipher(cipher); 57 58 switch (pasn->cipher) { 59 case IWL_LOCATION_CIPHER_CCMP_128: 60 case IWL_LOCATION_CIPHER_GCMP_128: 61 expected_tk_len = WLAN_KEY_LEN_CCMP; 62 break; 63 case IWL_LOCATION_CIPHER_GCMP_256: 64 expected_tk_len = WLAN_KEY_LEN_GCMP_256; 65 break; 66 default: 67 goto out; 68 } 69 70 /* 71 * If associated to this AP and already have security context, 72 * the TK is already configured for this station, so it 73 * shouldn't be set again here. 74 */ 75 if (vif->cfg.assoc) { 76 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 77 struct ieee80211_bss_conf *link_conf; 78 unsigned int link_id; 79 struct ieee80211_sta *sta; 80 u8 sta_id; 81 82 rcu_read_lock(); 83 for_each_vif_active_link(vif, link_conf, link_id) { 84 if (memcmp(addr, link_conf->bssid, ETH_ALEN)) 85 continue; 86 87 sta_id = mvmvif->link[link_id]->ap_sta_id; 88 sta = rcu_dereference(mvm->fw_id_to_mac_id[sta_id]); 89 if (!IS_ERR_OR_NULL(sta) && sta->mfp) 90 expected_tk_len = 0; 91 break; 92 } 93 rcu_read_unlock(); 94 } 95 96 if (tk_len != expected_tk_len || 97 (hltk_len && hltk_len != sizeof(pasn->hltk))) { 98 IWL_ERR(mvm, "Invalid key length: tk_len=%u hltk_len=%u\n", 99 tk_len, hltk_len); 100 goto out; 101 } 102 103 if (!expected_tk_len && !hltk_len) { 104 IWL_ERR(mvm, "TK and HLTK not set\n"); 105 goto out; 106 } 107 108 memcpy(pasn->addr, addr, sizeof(pasn->addr)); 109 110 if (hltk_len) { 111 memcpy(pasn->hltk, hltk, sizeof(pasn->hltk)); 112 pasn->flags |= IWL_MVM_PASN_FLAG_HAS_HLTK; 113 } 114 115 if (tk && tk_len) 116 memcpy(pasn->tk, tk, sizeof(pasn->tk)); 117 118 list_add_tail(&pasn->list, &mvm->ftm_initiator.pasn_list); 119 return 0; 120 out: 121 kfree(pasn); 122 return -EINVAL; 123 } 124 125 void iwl_mvm_ftm_remove_pasn_sta(struct iwl_mvm *mvm, u8 *addr) 126 { 127 struct iwl_mvm_ftm_pasn_entry *entry, *prev; 128 129 lockdep_assert_held(&mvm->mutex); 130 131 list_for_each_entry_safe(entry, prev, &mvm->ftm_initiator.pasn_list, 132 list) { 133 if (memcmp(entry->addr, addr, sizeof(entry->addr))) 134 continue; 135 136 list_del(&entry->list); 137 kfree(entry); 138 return; 139 } 140 } 141 142 static void iwl_mvm_ftm_reset(struct iwl_mvm *mvm) 143 { 144 struct iwl_mvm_loc_entry *e, *t; 145 146 mvm->ftm_initiator.req = NULL; 147 mvm->ftm_initiator.req_wdev = NULL; 148 memset(mvm->ftm_initiator.responses, 0, 149 sizeof(mvm->ftm_initiator.responses)); 150 151 list_for_each_entry_safe(e, t, &mvm->ftm_initiator.loc_list, list) { 152 list_del(&e->list); 153 kfree(e); 154 } 155 } 156 157 void iwl_mvm_ftm_restart(struct iwl_mvm *mvm) 158 { 159 struct cfg80211_pmsr_result result = { 160 .status = NL80211_PMSR_STATUS_FAILURE, 161 .final = 1, 162 .host_time = ktime_get_boottime_ns(), 163 .type = NL80211_PMSR_TYPE_FTM, 164 }; 165 int i; 166 167 lockdep_assert_held(&mvm->mutex); 168 169 if (!mvm->ftm_initiator.req) 170 return; 171 172 for (i = 0; i < mvm->ftm_initiator.req->n_peers; i++) { 173 memcpy(result.addr, mvm->ftm_initiator.req->peers[i].addr, 174 ETH_ALEN); 175 result.ftm.burst_index = mvm->ftm_initiator.responses[i]; 176 177 cfg80211_pmsr_report(mvm->ftm_initiator.req_wdev, 178 mvm->ftm_initiator.req, 179 &result, GFP_KERNEL); 180 } 181 182 cfg80211_pmsr_complete(mvm->ftm_initiator.req_wdev, 183 mvm->ftm_initiator.req, GFP_KERNEL); 184 iwl_mvm_ftm_reset(mvm); 185 } 186 187 void iwl_mvm_ftm_initiator_smooth_config(struct iwl_mvm *mvm) 188 { 189 INIT_LIST_HEAD(&mvm->ftm_initiator.smooth.resp); 190 191 IWL_DEBUG_INFO(mvm, 192 "enable=%u, alpha=%u, age_jiffies=%u, thresh=(%u:%u)\n", 193 IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH, 194 IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA, 195 IWL_MVM_FTM_INITIATOR_SMOOTH_AGE_SEC * HZ, 196 IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT, 197 IWL_MVM_FTM_INITIATOR_SMOOTH_UNDERSHOOT); 198 } 199 200 void iwl_mvm_ftm_initiator_smooth_stop(struct iwl_mvm *mvm) 201 { 202 struct iwl_mvm_smooth_entry *se, *st; 203 204 list_for_each_entry_safe(se, st, &mvm->ftm_initiator.smooth.resp, 205 list) { 206 list_del(&se->list); 207 kfree(se); 208 } 209 } 210 211 static int 212 iwl_ftm_range_request_status_to_err(enum iwl_tof_range_request_status s) 213 { 214 switch (s) { 215 case IWL_TOF_RANGE_REQUEST_STATUS_SUCCESS: 216 return 0; 217 case IWL_TOF_RANGE_REQUEST_STATUS_BUSY: 218 return -EBUSY; 219 default: 220 WARN_ON_ONCE(1); 221 return -EIO; 222 } 223 } 224 225 static void iwl_mvm_ftm_cmd_v5(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 226 struct iwl_tof_range_req_cmd_v5 *cmd, 227 struct cfg80211_pmsr_request *req) 228 { 229 int i; 230 231 cmd->request_id = req->cookie; 232 cmd->num_of_ap = req->n_peers; 233 234 /* use maximum for "no timeout" or bigger than what we can do */ 235 if (!req->timeout || req->timeout > 255 * 100) 236 cmd->req_timeout = 255; 237 else 238 cmd->req_timeout = DIV_ROUND_UP(req->timeout, 100); 239 240 /* 241 * We treat it always as random, since if not we'll 242 * have filled our local address there instead. 243 */ 244 cmd->macaddr_random = 1; 245 memcpy(cmd->macaddr_template, req->mac_addr, ETH_ALEN); 246 for (i = 0; i < ETH_ALEN; i++) 247 cmd->macaddr_mask[i] = ~req->mac_addr_mask[i]; 248 249 if (vif->cfg.assoc) 250 memcpy(cmd->range_req_bssid, vif->bss_conf.bssid, ETH_ALEN); 251 else 252 eth_broadcast_addr(cmd->range_req_bssid); 253 } 254 255 static void iwl_mvm_ftm_cmd_common(struct iwl_mvm *mvm, 256 struct ieee80211_vif *vif, 257 #if defined(__linux__) 258 struct iwl_tof_range_req_cmd_v9 *cmd, 259 #elif defined(__FreeBSD__) 260 struct iwl_tof_range_req_cmd_v9 *cmd, /* XXX-BZ Probably better solved by a common struct in fw for top parts of the struct. */ 261 #endif 262 struct cfg80211_pmsr_request *req) 263 { 264 int i; 265 266 cmd->initiator_flags = 267 cpu_to_le32(IWL_TOF_INITIATOR_FLAGS_MACADDR_RANDOM | 268 IWL_TOF_INITIATOR_FLAGS_NON_ASAP_SUPPORT); 269 cmd->request_id = req->cookie; 270 cmd->num_of_ap = req->n_peers; 271 272 /* 273 * Use a large value for "no timeout". Don't use the maximum value 274 * because of fw limitations. 275 */ 276 if (req->timeout) 277 cmd->req_timeout_ms = cpu_to_le32(req->timeout); 278 else 279 cmd->req_timeout_ms = cpu_to_le32(0xfffff); 280 281 memcpy(cmd->macaddr_template, req->mac_addr, ETH_ALEN); 282 for (i = 0; i < ETH_ALEN; i++) 283 cmd->macaddr_mask[i] = ~req->mac_addr_mask[i]; 284 285 if (vif->cfg.assoc) { 286 memcpy(cmd->range_req_bssid, vif->bss_conf.bssid, ETH_ALEN); 287 288 /* AP's TSF is only relevant if associated */ 289 for (i = 0; i < req->n_peers; i++) { 290 if (req->peers[i].report_ap_tsf) { 291 struct iwl_mvm_vif *mvmvif = 292 iwl_mvm_vif_from_mac80211(vif); 293 294 cmd->tsf_mac_id = cpu_to_le32(mvmvif->id); 295 return; 296 } 297 } 298 } else { 299 eth_broadcast_addr(cmd->range_req_bssid); 300 } 301 302 /* Don't report AP's TSF */ 303 cmd->tsf_mac_id = cpu_to_le32(0xff); 304 } 305 306 static void iwl_mvm_ftm_cmd_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 307 struct iwl_tof_range_req_cmd_v8 *cmd, 308 struct cfg80211_pmsr_request *req) 309 { 310 iwl_mvm_ftm_cmd_common(mvm, vif, (void *)cmd, req); 311 } 312 313 static int 314 iwl_mvm_ftm_target_chandef_v1(struct iwl_mvm *mvm, 315 struct cfg80211_pmsr_request_peer *peer, 316 u8 *channel, u8 *bandwidth, 317 u8 *ctrl_ch_position) 318 { 319 u32 freq = peer->chandef.chan->center_freq; 320 321 *channel = ieee80211_frequency_to_channel(freq); 322 323 switch (peer->chandef.width) { 324 case NL80211_CHAN_WIDTH_20_NOHT: 325 *bandwidth = IWL_TOF_BW_20_LEGACY; 326 break; 327 case NL80211_CHAN_WIDTH_20: 328 *bandwidth = IWL_TOF_BW_20_HT; 329 break; 330 case NL80211_CHAN_WIDTH_40: 331 *bandwidth = IWL_TOF_BW_40; 332 break; 333 case NL80211_CHAN_WIDTH_80: 334 *bandwidth = IWL_TOF_BW_80; 335 break; 336 default: 337 IWL_ERR(mvm, "Unsupported BW in FTM request (%d)\n", 338 peer->chandef.width); 339 return -EINVAL; 340 } 341 342 *ctrl_ch_position = (peer->chandef.width > NL80211_CHAN_WIDTH_20) ? 343 iwl_mvm_get_ctrl_pos(&peer->chandef) : 0; 344 345 return 0; 346 } 347 348 static int 349 iwl_mvm_ftm_target_chandef_v2(struct iwl_mvm *mvm, 350 struct cfg80211_pmsr_request_peer *peer, 351 u8 *channel, u8 *format_bw, 352 u8 *ctrl_ch_position) 353 { 354 u32 freq = peer->chandef.chan->center_freq; 355 u8 cmd_ver; 356 357 *channel = ieee80211_frequency_to_channel(freq); 358 359 switch (peer->chandef.width) { 360 case NL80211_CHAN_WIDTH_20_NOHT: 361 *format_bw = IWL_LOCATION_FRAME_FORMAT_LEGACY; 362 *format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS; 363 break; 364 case NL80211_CHAN_WIDTH_20: 365 *format_bw = IWL_LOCATION_FRAME_FORMAT_HT; 366 *format_bw |= IWL_LOCATION_BW_20MHZ << LOCATION_BW_POS; 367 break; 368 case NL80211_CHAN_WIDTH_40: 369 *format_bw = IWL_LOCATION_FRAME_FORMAT_HT; 370 *format_bw |= IWL_LOCATION_BW_40MHZ << LOCATION_BW_POS; 371 break; 372 case NL80211_CHAN_WIDTH_80: 373 *format_bw = IWL_LOCATION_FRAME_FORMAT_VHT; 374 *format_bw |= IWL_LOCATION_BW_80MHZ << LOCATION_BW_POS; 375 break; 376 case NL80211_CHAN_WIDTH_160: 377 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, 378 WIDE_ID(LOCATION_GROUP, TOF_RANGE_REQ_CMD), 379 IWL_FW_CMD_VER_UNKNOWN); 380 381 if (cmd_ver >= 13) { 382 *format_bw = IWL_LOCATION_FRAME_FORMAT_HE; 383 *format_bw |= IWL_LOCATION_BW_160MHZ << LOCATION_BW_POS; 384 break; 385 } 386 fallthrough; 387 default: 388 IWL_ERR(mvm, "Unsupported BW in FTM request (%d)\n", 389 peer->chandef.width); 390 return -EINVAL; 391 } 392 393 /* non EDCA based measurement must use HE preamble */ 394 if (peer->ftm.trigger_based || peer->ftm.non_trigger_based) 395 *format_bw |= IWL_LOCATION_FRAME_FORMAT_HE; 396 397 *ctrl_ch_position = (peer->chandef.width > NL80211_CHAN_WIDTH_20) ? 398 iwl_mvm_get_ctrl_pos(&peer->chandef) : 0; 399 400 return 0; 401 } 402 403 static int 404 iwl_mvm_ftm_put_target_v2(struct iwl_mvm *mvm, 405 struct cfg80211_pmsr_request_peer *peer, 406 struct iwl_tof_range_req_ap_entry_v2 *target) 407 { 408 int ret; 409 410 ret = iwl_mvm_ftm_target_chandef_v1(mvm, peer, &target->channel_num, 411 &target->bandwidth, 412 &target->ctrl_ch_position); 413 if (ret) 414 return ret; 415 416 memcpy(target->bssid, peer->addr, ETH_ALEN); 417 target->burst_period = 418 cpu_to_le16(peer->ftm.burst_period); 419 target->samples_per_burst = peer->ftm.ftms_per_burst; 420 target->num_of_bursts = peer->ftm.num_bursts_exp; 421 target->measure_type = 0; /* regular two-sided FTM */ 422 target->retries_per_sample = peer->ftm.ftmr_retries; 423 target->asap_mode = peer->ftm.asap; 424 target->enable_dyn_ack = IWL_MVM_FTM_INITIATOR_DYNACK; 425 426 if (peer->ftm.request_lci) 427 target->location_req |= IWL_TOF_LOC_LCI; 428 if (peer->ftm.request_civicloc) 429 target->location_req |= IWL_TOF_LOC_CIVIC; 430 431 target->algo_type = IWL_MVM_FTM_INITIATOR_ALGO; 432 433 return 0; 434 } 435 436 #define FTM_PUT_FLAG(flag) (target->initiator_ap_flags |= \ 437 cpu_to_le32(IWL_INITIATOR_AP_FLAGS_##flag)) 438 439 static void 440 iwl_mvm_ftm_put_target_common(struct iwl_mvm *mvm, 441 struct cfg80211_pmsr_request_peer *peer, 442 struct iwl_tof_range_req_ap_entry_v6 *target) 443 { 444 memcpy(target->bssid, peer->addr, ETH_ALEN); 445 target->burst_period = 446 cpu_to_le16(peer->ftm.burst_period); 447 target->samples_per_burst = peer->ftm.ftms_per_burst; 448 target->num_of_bursts = peer->ftm.num_bursts_exp; 449 target->ftmr_max_retries = peer->ftm.ftmr_retries; 450 target->initiator_ap_flags = cpu_to_le32(0); 451 452 if (peer->ftm.asap) 453 FTM_PUT_FLAG(ASAP); 454 455 if (peer->ftm.request_lci) 456 FTM_PUT_FLAG(LCI_REQUEST); 457 458 if (peer->ftm.request_civicloc) 459 FTM_PUT_FLAG(CIVIC_REQUEST); 460 461 if (IWL_MVM_FTM_INITIATOR_DYNACK) 462 FTM_PUT_FLAG(DYN_ACK); 463 464 if (IWL_MVM_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_LINEAR_REG) 465 FTM_PUT_FLAG(ALGO_LR); 466 else if (IWL_MVM_FTM_INITIATOR_ALGO == IWL_TOF_ALGO_TYPE_FFT) 467 FTM_PUT_FLAG(ALGO_FFT); 468 469 if (peer->ftm.trigger_based) 470 FTM_PUT_FLAG(TB); 471 else if (peer->ftm.non_trigger_based) 472 FTM_PUT_FLAG(NON_TB); 473 474 if ((peer->ftm.trigger_based || peer->ftm.non_trigger_based) && 475 peer->ftm.lmr_feedback) 476 FTM_PUT_FLAG(LMR_FEEDBACK); 477 } 478 479 static int 480 iwl_mvm_ftm_put_target_v3(struct iwl_mvm *mvm, 481 struct cfg80211_pmsr_request_peer *peer, 482 struct iwl_tof_range_req_ap_entry_v3 *target) 483 { 484 int ret; 485 486 ret = iwl_mvm_ftm_target_chandef_v1(mvm, peer, &target->channel_num, 487 &target->bandwidth, 488 &target->ctrl_ch_position); 489 if (ret) 490 return ret; 491 492 /* 493 * Versions 3 and 4 has some common fields, so 494 * iwl_mvm_ftm_put_target_common() can be used for version 7 too. 495 */ 496 iwl_mvm_ftm_put_target_common(mvm, peer, (void *)target); 497 498 return 0; 499 } 500 501 static int 502 iwl_mvm_ftm_put_target_v4(struct iwl_mvm *mvm, 503 struct cfg80211_pmsr_request_peer *peer, 504 struct iwl_tof_range_req_ap_entry_v4 *target) 505 { 506 int ret; 507 508 ret = iwl_mvm_ftm_target_chandef_v2(mvm, peer, &target->channel_num, 509 &target->format_bw, 510 &target->ctrl_ch_position); 511 if (ret) 512 return ret; 513 514 iwl_mvm_ftm_put_target_common(mvm, peer, (void *)target); 515 516 return 0; 517 } 518 519 static int 520 iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 521 struct cfg80211_pmsr_request_peer *peer, 522 struct iwl_tof_range_req_ap_entry_v6 *target) 523 { 524 int ret; 525 526 ret = iwl_mvm_ftm_target_chandef_v2(mvm, peer, &target->channel_num, 527 &target->format_bw, 528 &target->ctrl_ch_position); 529 if (ret) 530 return ret; 531 532 iwl_mvm_ftm_put_target_common(mvm, peer, target); 533 534 if (vif->cfg.assoc) { 535 struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); 536 struct ieee80211_sta *sta; 537 struct ieee80211_bss_conf *link_conf; 538 unsigned int link_id; 539 540 rcu_read_lock(); 541 for_each_vif_active_link(vif, link_conf, link_id) { 542 if (memcmp(peer->addr, link_conf->bssid, ETH_ALEN)) 543 continue; 544 545 target->sta_id = mvmvif->link[link_id]->ap_sta_id; 546 sta = rcu_dereference(mvm->fw_id_to_mac_id[target->sta_id]); 547 if (WARN_ON_ONCE(IS_ERR_OR_NULL(sta))) { 548 rcu_read_unlock(); 549 return PTR_ERR_OR_ZERO(sta); 550 } 551 552 if (sta->mfp && (peer->ftm.trigger_based || 553 peer->ftm.non_trigger_based)) 554 FTM_PUT_FLAG(PMF); 555 break; 556 } 557 rcu_read_unlock(); 558 } else { 559 target->sta_id = IWL_MVM_INVALID_STA; 560 } 561 562 /* 563 * TODO: Beacon interval is currently unknown, so use the common value 564 * of 100 TUs. 565 */ 566 target->beacon_interval = cpu_to_le16(100); 567 return 0; 568 } 569 570 static int iwl_mvm_ftm_send_cmd(struct iwl_mvm *mvm, struct iwl_host_cmd *hcmd) 571 { 572 u32 status; 573 int err = iwl_mvm_send_cmd_status(mvm, hcmd, &status); 574 575 if (!err && status) { 576 IWL_ERR(mvm, "FTM range request command failure, status: %u\n", 577 status); 578 err = iwl_ftm_range_request_status_to_err(status); 579 } 580 581 return err; 582 } 583 584 static int iwl_mvm_ftm_start_v5(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 585 struct cfg80211_pmsr_request *req) 586 { 587 struct iwl_tof_range_req_cmd_v5 cmd_v5; 588 struct iwl_host_cmd hcmd = { 589 .id = WIDE_ID(LOCATION_GROUP, TOF_RANGE_REQ_CMD), 590 .dataflags[0] = IWL_HCMD_DFL_DUP, 591 .data[0] = &cmd_v5, 592 .len[0] = sizeof(cmd_v5), 593 }; 594 u8 i; 595 int err; 596 597 iwl_mvm_ftm_cmd_v5(mvm, vif, &cmd_v5, req); 598 599 for (i = 0; i < cmd_v5.num_of_ap; i++) { 600 struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; 601 602 err = iwl_mvm_ftm_put_target_v2(mvm, peer, &cmd_v5.ap[i]); 603 if (err) 604 return err; 605 } 606 607 return iwl_mvm_ftm_send_cmd(mvm, &hcmd); 608 } 609 610 static int iwl_mvm_ftm_start_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 611 struct cfg80211_pmsr_request *req) 612 { 613 struct iwl_tof_range_req_cmd_v7 cmd_v7; 614 struct iwl_host_cmd hcmd = { 615 .id = WIDE_ID(LOCATION_GROUP, TOF_RANGE_REQ_CMD), 616 .dataflags[0] = IWL_HCMD_DFL_DUP, 617 .data[0] = &cmd_v7, 618 .len[0] = sizeof(cmd_v7), 619 }; 620 u8 i; 621 int err; 622 623 /* 624 * Versions 7 and 8 has the same structure except from the responders 625 * list, so iwl_mvm_ftm_cmd() can be used for version 7 too. 626 */ 627 iwl_mvm_ftm_cmd_v8(mvm, vif, (void *)&cmd_v7, req); 628 629 for (i = 0; i < cmd_v7.num_of_ap; i++) { 630 struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; 631 632 err = iwl_mvm_ftm_put_target_v3(mvm, peer, &cmd_v7.ap[i]); 633 if (err) 634 return err; 635 } 636 637 return iwl_mvm_ftm_send_cmd(mvm, &hcmd); 638 } 639 640 static int iwl_mvm_ftm_start_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 641 struct cfg80211_pmsr_request *req) 642 { 643 struct iwl_tof_range_req_cmd_v8 cmd; 644 struct iwl_host_cmd hcmd = { 645 .id = WIDE_ID(LOCATION_GROUP, TOF_RANGE_REQ_CMD), 646 .dataflags[0] = IWL_HCMD_DFL_DUP, 647 .data[0] = &cmd, 648 .len[0] = sizeof(cmd), 649 }; 650 u8 i; 651 int err; 652 653 iwl_mvm_ftm_cmd_v8(mvm, vif, (void *)&cmd, req); 654 655 for (i = 0; i < cmd.num_of_ap; i++) { 656 struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; 657 658 err = iwl_mvm_ftm_put_target_v4(mvm, peer, &cmd.ap[i]); 659 if (err) 660 return err; 661 } 662 663 return iwl_mvm_ftm_send_cmd(mvm, &hcmd); 664 } 665 666 static int iwl_mvm_ftm_start_v9(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 667 struct cfg80211_pmsr_request *req) 668 { 669 struct iwl_tof_range_req_cmd_v9 cmd; 670 struct iwl_host_cmd hcmd = { 671 .id = WIDE_ID(LOCATION_GROUP, TOF_RANGE_REQ_CMD), 672 .dataflags[0] = IWL_HCMD_DFL_DUP, 673 .data[0] = &cmd, 674 .len[0] = sizeof(cmd), 675 }; 676 u8 i; 677 int err; 678 679 iwl_mvm_ftm_cmd_common(mvm, vif, &cmd, req); 680 681 for (i = 0; i < cmd.num_of_ap; i++) { 682 struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; 683 struct iwl_tof_range_req_ap_entry_v6 *target = &cmd.ap[i]; 684 685 err = iwl_mvm_ftm_put_target(mvm, vif, peer, target); 686 if (err) 687 return err; 688 } 689 690 return iwl_mvm_ftm_send_cmd(mvm, &hcmd); 691 } 692 693 static void iter(struct ieee80211_hw *hw, 694 struct ieee80211_vif *vif, 695 struct ieee80211_sta *sta, 696 struct ieee80211_key_conf *key, 697 void *data) 698 { 699 struct iwl_tof_range_req_ap_entry_v6 *target = data; 700 701 if (!sta || memcmp(sta->addr, target->bssid, ETH_ALEN)) 702 return; 703 704 WARN_ON(!sta->mfp); 705 706 if (WARN_ON(key->keylen > sizeof(target->tk))) 707 return; 708 709 memcpy(target->tk, key->key, key->keylen); 710 target->cipher = iwl_mvm_cipher_to_location_cipher(key->cipher); 711 WARN_ON(target->cipher == IWL_LOCATION_CIPHER_INVALID); 712 } 713 714 static void 715 iwl_mvm_ftm_set_secured_ranging(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 716 struct iwl_tof_range_req_ap_entry_v7 *target) 717 { 718 struct iwl_mvm_ftm_pasn_entry *entry; 719 u32 flags = le32_to_cpu(target->initiator_ap_flags); 720 721 if (!(flags & (IWL_INITIATOR_AP_FLAGS_NON_TB | 722 IWL_INITIATOR_AP_FLAGS_TB))) 723 return; 724 725 lockdep_assert_held(&mvm->mutex); 726 727 list_for_each_entry(entry, &mvm->ftm_initiator.pasn_list, list) { 728 if (memcmp(entry->addr, target->bssid, sizeof(entry->addr))) 729 continue; 730 731 target->cipher = entry->cipher; 732 733 if (entry->flags & IWL_MVM_PASN_FLAG_HAS_HLTK) 734 memcpy(target->hltk, entry->hltk, sizeof(target->hltk)); 735 else 736 memset(target->hltk, 0, sizeof(target->hltk)); 737 738 if (vif->cfg.assoc && 739 !memcmp(vif->bss_conf.bssid, target->bssid, 740 sizeof(target->bssid))) 741 ieee80211_iter_keys(mvm->hw, vif, iter, target); 742 else 743 memcpy(target->tk, entry->tk, sizeof(target->tk)); 744 745 memcpy(target->rx_pn, entry->rx_pn, sizeof(target->rx_pn)); 746 memcpy(target->tx_pn, entry->tx_pn, sizeof(target->tx_pn)); 747 748 target->initiator_ap_flags |= 749 cpu_to_le32(IWL_INITIATOR_AP_FLAGS_SECURED); 750 return; 751 } 752 } 753 754 static int 755 iwl_mvm_ftm_put_target_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 756 struct cfg80211_pmsr_request_peer *peer, 757 struct iwl_tof_range_req_ap_entry_v7 *target) 758 { 759 int err = iwl_mvm_ftm_put_target(mvm, vif, peer, (void *)target); 760 if (err) 761 return err; 762 763 iwl_mvm_ftm_set_secured_ranging(mvm, vif, target); 764 return err; 765 } 766 767 static int iwl_mvm_ftm_start_v11(struct iwl_mvm *mvm, 768 struct ieee80211_vif *vif, 769 struct cfg80211_pmsr_request *req) 770 { 771 struct iwl_tof_range_req_cmd_v11 cmd; 772 struct iwl_host_cmd hcmd = { 773 .id = WIDE_ID(LOCATION_GROUP, TOF_RANGE_REQ_CMD), 774 .dataflags[0] = IWL_HCMD_DFL_DUP, 775 .data[0] = &cmd, 776 .len[0] = sizeof(cmd), 777 }; 778 u8 i; 779 int err; 780 781 iwl_mvm_ftm_cmd_common(mvm, vif, (void *)&cmd, req); 782 783 for (i = 0; i < cmd.num_of_ap; i++) { 784 struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; 785 struct iwl_tof_range_req_ap_entry_v7 *target = &cmd.ap[i]; 786 787 err = iwl_mvm_ftm_put_target_v7(mvm, vif, peer, target); 788 if (err) 789 return err; 790 } 791 792 return iwl_mvm_ftm_send_cmd(mvm, &hcmd); 793 } 794 795 static void 796 iwl_mvm_ftm_set_ndp_params(struct iwl_mvm *mvm, 797 struct iwl_tof_range_req_ap_entry_v8 *target) 798 { 799 /* Only 2 STS are supported on Tx */ 800 u32 i2r_max_sts = IWL_MVM_FTM_I2R_MAX_STS > 1 ? 1 : 801 IWL_MVM_FTM_I2R_MAX_STS; 802 803 target->r2i_ndp_params = IWL_MVM_FTM_R2I_MAX_REP | 804 (IWL_MVM_FTM_R2I_MAX_STS << IWL_LOCATION_MAX_STS_POS); 805 target->i2r_ndp_params = IWL_MVM_FTM_I2R_MAX_REP | 806 (i2r_max_sts << IWL_LOCATION_MAX_STS_POS); 807 target->r2i_max_total_ltf = IWL_MVM_FTM_R2I_MAX_TOTAL_LTF; 808 target->i2r_max_total_ltf = IWL_MVM_FTM_I2R_MAX_TOTAL_LTF; 809 } 810 811 static int 812 iwl_mvm_ftm_put_target_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 813 struct cfg80211_pmsr_request_peer *peer, 814 struct iwl_tof_range_req_ap_entry_v8 *target) 815 { 816 u32 flags; 817 int ret = iwl_mvm_ftm_put_target_v7(mvm, vif, peer, (void *)target); 818 819 if (ret) 820 return ret; 821 822 iwl_mvm_ftm_set_ndp_params(mvm, target); 823 824 /* 825 * If secure LTF is turned off, replace the flag with PMF only 826 */ 827 flags = le32_to_cpu(target->initiator_ap_flags); 828 if ((flags & IWL_INITIATOR_AP_FLAGS_SECURED) && 829 !IWL_MVM_FTM_INITIATOR_SECURE_LTF) { 830 flags &= ~IWL_INITIATOR_AP_FLAGS_SECURED; 831 flags |= IWL_INITIATOR_AP_FLAGS_PMF; 832 target->initiator_ap_flags = cpu_to_le32(flags); 833 } 834 835 return 0; 836 } 837 838 static int iwl_mvm_ftm_start_v12(struct iwl_mvm *mvm, 839 struct ieee80211_vif *vif, 840 struct cfg80211_pmsr_request *req) 841 { 842 struct iwl_tof_range_req_cmd_v12 cmd; 843 struct iwl_host_cmd hcmd = { 844 .id = WIDE_ID(LOCATION_GROUP, TOF_RANGE_REQ_CMD), 845 .dataflags[0] = IWL_HCMD_DFL_DUP, 846 .data[0] = &cmd, 847 .len[0] = sizeof(cmd), 848 }; 849 u8 i; 850 int err; 851 852 iwl_mvm_ftm_cmd_common(mvm, vif, (void *)&cmd, req); 853 854 for (i = 0; i < cmd.num_of_ap; i++) { 855 struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; 856 struct iwl_tof_range_req_ap_entry_v8 *target = &cmd.ap[i]; 857 858 err = iwl_mvm_ftm_put_target_v8(mvm, vif, peer, target); 859 if (err) 860 return err; 861 } 862 863 return iwl_mvm_ftm_send_cmd(mvm, &hcmd); 864 } 865 866 static int iwl_mvm_ftm_start_v13(struct iwl_mvm *mvm, 867 struct ieee80211_vif *vif, 868 struct cfg80211_pmsr_request *req) 869 { 870 struct iwl_tof_range_req_cmd_v13 cmd; 871 struct iwl_host_cmd hcmd = { 872 .id = WIDE_ID(LOCATION_GROUP, TOF_RANGE_REQ_CMD), 873 .dataflags[0] = IWL_HCMD_DFL_DUP, 874 .data[0] = &cmd, 875 .len[0] = sizeof(cmd), 876 }; 877 u8 i; 878 int err; 879 880 iwl_mvm_ftm_cmd_common(mvm, vif, (void *)&cmd, req); 881 882 for (i = 0; i < cmd.num_of_ap; i++) { 883 struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; 884 struct iwl_tof_range_req_ap_entry_v9 *target = &cmd.ap[i]; 885 886 err = iwl_mvm_ftm_put_target_v8(mvm, vif, peer, (void *)target); 887 if (err) 888 return err; 889 890 if (peer->ftm.trigger_based || peer->ftm.non_trigger_based) 891 target->bss_color = peer->ftm.bss_color; 892 893 if (peer->ftm.non_trigger_based) { 894 target->min_time_between_msr = 895 cpu_to_le16(IWL_MVM_FTM_NON_TB_MIN_TIME_BETWEEN_MSR); 896 target->burst_period = 897 cpu_to_le16(IWL_MVM_FTM_NON_TB_MAX_TIME_BETWEEN_MSR); 898 } else { 899 target->min_time_between_msr = cpu_to_le16(0); 900 } 901 902 target->band = 903 iwl_mvm_phy_band_from_nl80211(peer->chandef.chan->band); 904 } 905 906 return iwl_mvm_ftm_send_cmd(mvm, &hcmd); 907 } 908 909 int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, 910 struct cfg80211_pmsr_request *req) 911 { 912 bool new_api = fw_has_api(&mvm->fw->ucode_capa, 913 IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ); 914 int err; 915 916 lockdep_assert_held(&mvm->mutex); 917 918 if (mvm->ftm_initiator.req) 919 return -EBUSY; 920 921 if (new_api) { 922 u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, 923 WIDE_ID(LOCATION_GROUP, TOF_RANGE_REQ_CMD), 924 IWL_FW_CMD_VER_UNKNOWN); 925 926 switch (cmd_ver) { 927 case 13: 928 err = iwl_mvm_ftm_start_v13(mvm, vif, req); 929 break; 930 case 12: 931 err = iwl_mvm_ftm_start_v12(mvm, vif, req); 932 break; 933 case 11: 934 err = iwl_mvm_ftm_start_v11(mvm, vif, req); 935 break; 936 case 9: 937 case 10: 938 err = iwl_mvm_ftm_start_v9(mvm, vif, req); 939 break; 940 case 8: 941 err = iwl_mvm_ftm_start_v8(mvm, vif, req); 942 break; 943 default: 944 err = iwl_mvm_ftm_start_v7(mvm, vif, req); 945 break; 946 } 947 } else { 948 err = iwl_mvm_ftm_start_v5(mvm, vif, req); 949 } 950 951 if (!err) { 952 mvm->ftm_initiator.req = req; 953 mvm->ftm_initiator.req_wdev = ieee80211_vif_to_wdev(vif); 954 } 955 956 return err; 957 } 958 959 void iwl_mvm_ftm_abort(struct iwl_mvm *mvm, struct cfg80211_pmsr_request *req) 960 { 961 struct iwl_tof_range_abort_cmd cmd = { 962 .request_id = req->cookie, 963 }; 964 965 lockdep_assert_held(&mvm->mutex); 966 967 if (req != mvm->ftm_initiator.req) 968 return; 969 970 iwl_mvm_ftm_reset(mvm); 971 972 if (iwl_mvm_send_cmd_pdu(mvm, WIDE_ID(LOCATION_GROUP, TOF_RANGE_ABORT_CMD), 973 0, sizeof(cmd), &cmd)) 974 IWL_ERR(mvm, "failed to abort FTM process\n"); 975 } 976 977 static int iwl_mvm_ftm_find_peer(struct cfg80211_pmsr_request *req, 978 const u8 *addr) 979 { 980 int i; 981 982 for (i = 0; i < req->n_peers; i++) { 983 struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; 984 985 if (ether_addr_equal_unaligned(peer->addr, addr)) 986 return i; 987 } 988 989 return -ENOENT; 990 } 991 992 static u64 iwl_mvm_ftm_get_host_time(struct iwl_mvm *mvm, __le32 fw_gp2_ts) 993 { 994 u32 gp2_ts = le32_to_cpu(fw_gp2_ts); 995 u32 curr_gp2, diff; 996 u64 now_from_boot_ns; 997 998 iwl_mvm_get_sync_time(mvm, CLOCK_BOOTTIME, &curr_gp2, 999 &now_from_boot_ns, NULL); 1000 1001 if (curr_gp2 >= gp2_ts) 1002 diff = curr_gp2 - gp2_ts; 1003 else 1004 diff = curr_gp2 + (U32_MAX - gp2_ts + 1); 1005 1006 return now_from_boot_ns - (u64)diff * 1000; 1007 } 1008 1009 static void iwl_mvm_ftm_get_lci_civic(struct iwl_mvm *mvm, 1010 struct cfg80211_pmsr_result *res) 1011 { 1012 struct iwl_mvm_loc_entry *entry; 1013 1014 list_for_each_entry(entry, &mvm->ftm_initiator.loc_list, list) { 1015 if (!ether_addr_equal_unaligned(res->addr, entry->addr)) 1016 continue; 1017 1018 if (entry->lci_len) { 1019 res->ftm.lci_len = entry->lci_len; 1020 res->ftm.lci = entry->buf; 1021 } 1022 1023 if (entry->civic_len) { 1024 res->ftm.civicloc_len = entry->civic_len; 1025 res->ftm.civicloc = entry->buf + entry->lci_len; 1026 } 1027 1028 /* we found the entry we needed */ 1029 break; 1030 } 1031 } 1032 1033 static int iwl_mvm_ftm_range_resp_valid(struct iwl_mvm *mvm, u8 request_id, 1034 u8 num_of_aps) 1035 { 1036 lockdep_assert_held(&mvm->mutex); 1037 1038 if (request_id != (u8)mvm->ftm_initiator.req->cookie) { 1039 IWL_ERR(mvm, "Request ID mismatch, got %u, active %u\n", 1040 request_id, (u8)mvm->ftm_initiator.req->cookie); 1041 return -EINVAL; 1042 } 1043 1044 if (num_of_aps > mvm->ftm_initiator.req->n_peers) { 1045 IWL_ERR(mvm, "FTM range response invalid\n"); 1046 return -EINVAL; 1047 } 1048 1049 return 0; 1050 } 1051 1052 static void iwl_mvm_ftm_rtt_smoothing(struct iwl_mvm *mvm, 1053 struct cfg80211_pmsr_result *res) 1054 { 1055 struct iwl_mvm_smooth_entry *resp = NULL, *iter; 1056 s64 rtt_avg, rtt = res->ftm.rtt_avg; 1057 u32 undershoot, overshoot; 1058 u8 alpha; 1059 1060 if (!IWL_MVM_FTM_INITIATOR_ENABLE_SMOOTH) 1061 return; 1062 1063 WARN_ON(rtt < 0); 1064 1065 if (res->status != NL80211_PMSR_STATUS_SUCCESS) { 1066 IWL_DEBUG_INFO(mvm, 1067 ": %pM: ignore failed measurement. Status=%u\n", 1068 res->addr, res->status); 1069 return; 1070 } 1071 1072 list_for_each_entry(iter, &mvm->ftm_initiator.smooth.resp, list) { 1073 if (!memcmp(res->addr, iter->addr, ETH_ALEN)) { 1074 resp = iter; 1075 break; 1076 } 1077 } 1078 1079 if (!resp) { 1080 resp = kzalloc(sizeof(*resp), GFP_KERNEL); 1081 if (!resp) 1082 return; 1083 1084 memcpy(resp->addr, res->addr, ETH_ALEN); 1085 list_add_tail(&resp->list, &mvm->ftm_initiator.smooth.resp); 1086 1087 resp->rtt_avg = rtt; 1088 1089 IWL_DEBUG_INFO(mvm, "new: %pM: rtt_avg=%lld\n", 1090 resp->addr, resp->rtt_avg); 1091 goto update_time; 1092 } 1093 1094 if (res->host_time - resp->host_time > 1095 IWL_MVM_FTM_INITIATOR_SMOOTH_AGE_SEC * 1000000000) { 1096 resp->rtt_avg = rtt; 1097 1098 IWL_DEBUG_INFO(mvm, "expired: %pM: rtt_avg=%lld\n", 1099 resp->addr, resp->rtt_avg); 1100 goto update_time; 1101 } 1102 1103 /* Smooth the results based on the tracked RTT average */ 1104 undershoot = IWL_MVM_FTM_INITIATOR_SMOOTH_UNDERSHOOT; 1105 overshoot = IWL_MVM_FTM_INITIATOR_SMOOTH_OVERSHOOT; 1106 alpha = IWL_MVM_FTM_INITIATOR_SMOOTH_ALPHA; 1107 1108 rtt_avg = div_s64(alpha * rtt + (100 - alpha) * resp->rtt_avg, 100); 1109 1110 IWL_DEBUG_INFO(mvm, 1111 "%pM: prev rtt_avg=%lld, new rtt_avg=%lld, rtt=%lld\n", 1112 resp->addr, resp->rtt_avg, rtt_avg, rtt); 1113 1114 /* 1115 * update the responder's average RTT results regardless of 1116 * the under/over shoot logic below 1117 */ 1118 resp->rtt_avg = rtt_avg; 1119 1120 /* smooth the results */ 1121 if (rtt_avg > rtt && (rtt_avg - rtt) > undershoot) { 1122 res->ftm.rtt_avg = rtt_avg; 1123 1124 IWL_DEBUG_INFO(mvm, 1125 "undershoot: val=%lld\n", 1126 (rtt_avg - rtt)); 1127 } else if (rtt_avg < rtt && (rtt - rtt_avg) > 1128 overshoot) { 1129 res->ftm.rtt_avg = rtt_avg; 1130 IWL_DEBUG_INFO(mvm, 1131 "overshoot: val=%lld\n", 1132 (rtt - rtt_avg)); 1133 } 1134 1135 update_time: 1136 resp->host_time = res->host_time; 1137 } 1138 1139 static void iwl_mvm_debug_range_resp(struct iwl_mvm *mvm, u8 index, 1140 struct cfg80211_pmsr_result *res) 1141 { 1142 s64 rtt_avg = div_s64(res->ftm.rtt_avg * 100, 6666); 1143 1144 IWL_DEBUG_INFO(mvm, "entry %d\n", index); 1145 IWL_DEBUG_INFO(mvm, "\tstatus: %d\n", res->status); 1146 IWL_DEBUG_INFO(mvm, "\tBSSID: %pM\n", res->addr); 1147 IWL_DEBUG_INFO(mvm, "\thost time: %llu\n", res->host_time); 1148 IWL_DEBUG_INFO(mvm, "\tburst index: %d\n", res->ftm.burst_index); 1149 IWL_DEBUG_INFO(mvm, "\tsuccess num: %u\n", res->ftm.num_ftmr_successes); 1150 IWL_DEBUG_INFO(mvm, "\trssi: %d\n", res->ftm.rssi_avg); 1151 IWL_DEBUG_INFO(mvm, "\trssi spread: %d\n", res->ftm.rssi_spread); 1152 IWL_DEBUG_INFO(mvm, "\trtt: %lld\n", res->ftm.rtt_avg); 1153 IWL_DEBUG_INFO(mvm, "\trtt var: %llu\n", res->ftm.rtt_variance); 1154 IWL_DEBUG_INFO(mvm, "\trtt spread: %llu\n", res->ftm.rtt_spread); 1155 IWL_DEBUG_INFO(mvm, "\tdistance: %lld\n", rtt_avg); 1156 } 1157 1158 static void 1159 iwl_mvm_ftm_pasn_update_pn(struct iwl_mvm *mvm, 1160 struct iwl_tof_range_rsp_ap_entry_ntfy_v6 *fw_ap) 1161 { 1162 struct iwl_mvm_ftm_pasn_entry *entry; 1163 1164 lockdep_assert_held(&mvm->mutex); 1165 1166 list_for_each_entry(entry, &mvm->ftm_initiator.pasn_list, list) { 1167 if (memcmp(fw_ap->bssid, entry->addr, sizeof(entry->addr))) 1168 continue; 1169 1170 memcpy(entry->rx_pn, fw_ap->rx_pn, sizeof(entry->rx_pn)); 1171 memcpy(entry->tx_pn, fw_ap->tx_pn, sizeof(entry->tx_pn)); 1172 return; 1173 } 1174 } 1175 1176 static u8 iwl_mvm_ftm_get_range_resp_ver(struct iwl_mvm *mvm) 1177 { 1178 if (!fw_has_api(&mvm->fw->ucode_capa, 1179 IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ)) 1180 return 5; 1181 1182 /* Starting from version 8, the FW advertises the version */ 1183 if (mvm->cmd_ver.range_resp >= 8) 1184 return mvm->cmd_ver.range_resp; 1185 else if (fw_has_api(&mvm->fw->ucode_capa, 1186 IWL_UCODE_TLV_API_FTM_RTT_ACCURACY)) 1187 return 7; 1188 1189 /* The first version of the new range request API */ 1190 return 6; 1191 } 1192 1193 static bool iwl_mvm_ftm_resp_size_validation(u8 ver, unsigned int pkt_len) 1194 { 1195 switch (ver) { 1196 case 9: 1197 case 8: 1198 return pkt_len == sizeof(struct iwl_tof_range_rsp_ntfy_v8); 1199 case 7: 1200 return pkt_len == sizeof(struct iwl_tof_range_rsp_ntfy_v7); 1201 case 6: 1202 return pkt_len == sizeof(struct iwl_tof_range_rsp_ntfy_v6); 1203 case 5: 1204 return pkt_len == sizeof(struct iwl_tof_range_rsp_ntfy_v5); 1205 default: 1206 WARN_ONCE(1, "FTM: unsupported range response version %u", ver); 1207 return false; 1208 } 1209 } 1210 1211 void iwl_mvm_ftm_range_resp(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) 1212 { 1213 struct iwl_rx_packet *pkt = rxb_addr(rxb); 1214 unsigned int pkt_len = iwl_rx_packet_payload_len(pkt); 1215 struct iwl_tof_range_rsp_ntfy_v5 *fw_resp_v5 = (void *)pkt->data; 1216 struct iwl_tof_range_rsp_ntfy_v6 *fw_resp_v6 = (void *)pkt->data; 1217 struct iwl_tof_range_rsp_ntfy_v7 *fw_resp_v7 = (void *)pkt->data; 1218 struct iwl_tof_range_rsp_ntfy_v8 *fw_resp_v8 = (void *)pkt->data; 1219 int i; 1220 bool new_api = fw_has_api(&mvm->fw->ucode_capa, 1221 IWL_UCODE_TLV_API_FTM_NEW_RANGE_REQ); 1222 u8 num_of_aps, last_in_batch; 1223 u8 notif_ver = iwl_mvm_ftm_get_range_resp_ver(mvm); 1224 1225 lockdep_assert_held(&mvm->mutex); 1226 1227 if (!mvm->ftm_initiator.req) { 1228 return; 1229 } 1230 1231 if (unlikely(!iwl_mvm_ftm_resp_size_validation(notif_ver, pkt_len))) 1232 return; 1233 1234 if (new_api) { 1235 if (iwl_mvm_ftm_range_resp_valid(mvm, fw_resp_v8->request_id, 1236 fw_resp_v8->num_of_aps)) 1237 return; 1238 1239 num_of_aps = fw_resp_v8->num_of_aps; 1240 last_in_batch = fw_resp_v8->last_report; 1241 } else { 1242 if (iwl_mvm_ftm_range_resp_valid(mvm, fw_resp_v5->request_id, 1243 fw_resp_v5->num_of_aps)) 1244 return; 1245 1246 num_of_aps = fw_resp_v5->num_of_aps; 1247 last_in_batch = fw_resp_v5->last_in_batch; 1248 } 1249 1250 IWL_DEBUG_INFO(mvm, "Range response received\n"); 1251 IWL_DEBUG_INFO(mvm, "request id: %lld, num of entries: %u\n", 1252 mvm->ftm_initiator.req->cookie, num_of_aps); 1253 1254 for (i = 0; i < num_of_aps && i < IWL_MVM_TOF_MAX_APS; i++) { 1255 struct cfg80211_pmsr_result result = {}; 1256 struct iwl_tof_range_rsp_ap_entry_ntfy_v6 *fw_ap; 1257 int peer_idx; 1258 1259 if (new_api) { 1260 if (notif_ver >= 8) { 1261 fw_ap = &fw_resp_v8->ap[i]; 1262 iwl_mvm_ftm_pasn_update_pn(mvm, fw_ap); 1263 } else if (notif_ver == 7) { 1264 fw_ap = (void *)&fw_resp_v7->ap[i]; 1265 } else { 1266 fw_ap = (void *)&fw_resp_v6->ap[i]; 1267 } 1268 1269 result.final = fw_ap->last_burst; 1270 result.ap_tsf = le32_to_cpu(fw_ap->start_tsf); 1271 result.ap_tsf_valid = 1; 1272 } else { 1273 /* the first part is the same for old and new APIs */ 1274 fw_ap = (void *)&fw_resp_v5->ap[i]; 1275 /* 1276 * FIXME: the firmware needs to report this, we don't 1277 * even know the number of bursts the responder picked 1278 * (if we asked it to) 1279 */ 1280 result.final = 0; 1281 } 1282 1283 peer_idx = iwl_mvm_ftm_find_peer(mvm->ftm_initiator.req, 1284 fw_ap->bssid); 1285 if (peer_idx < 0) { 1286 IWL_WARN(mvm, 1287 "Unknown address (%pM, target #%d) in FTM response\n", 1288 fw_ap->bssid, i); 1289 continue; 1290 } 1291 1292 switch (fw_ap->measure_status) { 1293 case IWL_TOF_ENTRY_SUCCESS: 1294 result.status = NL80211_PMSR_STATUS_SUCCESS; 1295 break; 1296 case IWL_TOF_ENTRY_TIMING_MEASURE_TIMEOUT: 1297 result.status = NL80211_PMSR_STATUS_TIMEOUT; 1298 break; 1299 case IWL_TOF_ENTRY_NO_RESPONSE: 1300 result.status = NL80211_PMSR_STATUS_FAILURE; 1301 result.ftm.failure_reason = 1302 NL80211_PMSR_FTM_FAILURE_NO_RESPONSE; 1303 break; 1304 case IWL_TOF_ENTRY_REQUEST_REJECTED: 1305 result.status = NL80211_PMSR_STATUS_FAILURE; 1306 result.ftm.failure_reason = 1307 NL80211_PMSR_FTM_FAILURE_PEER_BUSY; 1308 result.ftm.busy_retry_time = fw_ap->refusal_period; 1309 break; 1310 default: 1311 result.status = NL80211_PMSR_STATUS_FAILURE; 1312 result.ftm.failure_reason = 1313 NL80211_PMSR_FTM_FAILURE_UNSPECIFIED; 1314 break; 1315 } 1316 memcpy(result.addr, fw_ap->bssid, ETH_ALEN); 1317 result.host_time = iwl_mvm_ftm_get_host_time(mvm, 1318 fw_ap->timestamp); 1319 result.type = NL80211_PMSR_TYPE_FTM; 1320 result.ftm.burst_index = mvm->ftm_initiator.responses[peer_idx]; 1321 mvm->ftm_initiator.responses[peer_idx]++; 1322 result.ftm.rssi_avg = fw_ap->rssi; 1323 result.ftm.rssi_avg_valid = 1; 1324 result.ftm.rssi_spread = fw_ap->rssi_spread; 1325 result.ftm.rssi_spread_valid = 1; 1326 result.ftm.rtt_avg = (s32)le32_to_cpu(fw_ap->rtt); 1327 result.ftm.rtt_avg_valid = 1; 1328 result.ftm.rtt_variance = le32_to_cpu(fw_ap->rtt_variance); 1329 result.ftm.rtt_variance_valid = 1; 1330 result.ftm.rtt_spread = le32_to_cpu(fw_ap->rtt_spread); 1331 result.ftm.rtt_spread_valid = 1; 1332 1333 iwl_mvm_ftm_get_lci_civic(mvm, &result); 1334 1335 iwl_mvm_ftm_rtt_smoothing(mvm, &result); 1336 1337 cfg80211_pmsr_report(mvm->ftm_initiator.req_wdev, 1338 mvm->ftm_initiator.req, 1339 &result, GFP_KERNEL); 1340 1341 if (fw_has_api(&mvm->fw->ucode_capa, 1342 IWL_UCODE_TLV_API_FTM_RTT_ACCURACY)) 1343 IWL_DEBUG_INFO(mvm, "RTT confidence: %u\n", 1344 fw_ap->rttConfidence); 1345 1346 iwl_mvm_debug_range_resp(mvm, i, &result); 1347 } 1348 1349 if (last_in_batch) { 1350 cfg80211_pmsr_complete(mvm->ftm_initiator.req_wdev, 1351 mvm->ftm_initiator.req, 1352 GFP_KERNEL); 1353 iwl_mvm_ftm_reset(mvm); 1354 } 1355 } 1356 1357 void iwl_mvm_ftm_lc_notif(struct iwl_mvm *mvm, struct iwl_rx_cmd_buffer *rxb) 1358 { 1359 struct iwl_rx_packet *pkt = rxb_addr(rxb); 1360 const struct ieee80211_mgmt *mgmt = (void *)pkt->data; 1361 size_t len = iwl_rx_packet_payload_len(pkt); 1362 struct iwl_mvm_loc_entry *entry; 1363 const u8 *ies, *lci, *civic, *msr_ie; 1364 size_t ies_len, lci_len = 0, civic_len = 0; 1365 size_t baselen = IEEE80211_MIN_ACTION_SIZE + 1366 sizeof(mgmt->u.action.u.ftm); 1367 static const u8 rprt_type_lci = IEEE80211_SPCT_MSR_RPRT_TYPE_LCI; 1368 static const u8 rprt_type_civic = IEEE80211_SPCT_MSR_RPRT_TYPE_CIVIC; 1369 1370 if (len <= baselen) 1371 return; 1372 1373 lockdep_assert_held(&mvm->mutex); 1374 1375 ies = mgmt->u.action.u.ftm.variable; 1376 ies_len = len - baselen; 1377 1378 msr_ie = cfg80211_find_ie_match(WLAN_EID_MEASURE_REPORT, ies, ies_len, 1379 &rprt_type_lci, 1, 4); 1380 if (msr_ie) { 1381 lci = msr_ie + 2; 1382 lci_len = msr_ie[1]; 1383 } 1384 1385 msr_ie = cfg80211_find_ie_match(WLAN_EID_MEASURE_REPORT, ies, ies_len, 1386 &rprt_type_civic, 1, 4); 1387 if (msr_ie) { 1388 civic = msr_ie + 2; 1389 civic_len = msr_ie[1]; 1390 } 1391 1392 entry = kmalloc(sizeof(*entry) + lci_len + civic_len, GFP_KERNEL); 1393 if (!entry) 1394 return; 1395 1396 memcpy(entry->addr, mgmt->bssid, ETH_ALEN); 1397 1398 entry->lci_len = lci_len; 1399 if (lci_len) 1400 memcpy(entry->buf, lci, lci_len); 1401 1402 entry->civic_len = civic_len; 1403 if (civic_len) 1404 memcpy(entry->buf + lci_len, civic, civic_len); 1405 1406 list_add_tail(&entry->list, &mvm->ftm_initiator.loc_list); 1407 } 1408