1 // SPDX-License-Identifier: BSD-3-Clause-Clear 2 /* 3 * Copyright (c) 2020-2021 The Linux Foundation. All rights reserved. 4 * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries. 5 */ 6 7 #include <linux/relay.h> 8 #include "core.h" 9 #include "debug.h" 10 11 struct ath11k_dbring *ath11k_cfr_get_dbring(struct ath11k *ar) 12 { 13 if (ar->cfr_enabled) 14 return &ar->cfr.rx_ring; 15 16 return NULL; 17 } 18 19 static int ath11k_cfr_calculate_tones_from_dma_hdr(struct ath11k_cfr_dma_hdr *hdr) 20 { 21 u8 bw = FIELD_GET(CFIR_DMA_HDR_INFO1_UPLOAD_PKT_BW, hdr->info1); 22 u8 preamble = FIELD_GET(CFIR_DMA_HDR_INFO1_PREAMBLE_TYPE, hdr->info1); 23 24 switch (preamble) { 25 case ATH11K_CFR_PREAMBLE_TYPE_LEGACY: 26 fallthrough; 27 case ATH11K_CFR_PREAMBLE_TYPE_VHT: 28 switch (bw) { 29 case 0: 30 return TONES_IN_20MHZ; 31 case 1: /* DUP40/VHT40 */ 32 return TONES_IN_40MHZ; 33 case 2: /* DUP80/VHT80 */ 34 return TONES_IN_80MHZ; 35 case 3: /* DUP160/VHT160 */ 36 return TONES_IN_160MHZ; 37 default: 38 return TONES_INVALID; 39 } 40 case ATH11K_CFR_PREAMBLE_TYPE_HT: 41 switch (bw) { 42 case 0: 43 return TONES_IN_20MHZ; 44 case 1: 45 return TONES_IN_40MHZ; 46 default: 47 return TONES_INVALID; 48 } 49 default: 50 return TONES_INVALID; 51 } 52 } 53 54 void ath11k_cfr_release_lut_entry(struct ath11k_look_up_table *lut) 55 { 56 memset(lut, 0, sizeof(*lut)); 57 } 58 59 static void ath11k_cfr_rfs_write(struct ath11k *ar, const void *head, 60 u32 head_len, const void *data, u32 data_len, 61 const void *tail, int tail_data) 62 { 63 struct ath11k_cfr *cfr = &ar->cfr; 64 65 if (!cfr->rfs_cfr_capture) 66 return; 67 68 relay_write(cfr->rfs_cfr_capture, head, head_len); 69 relay_write(cfr->rfs_cfr_capture, data, data_len); 70 relay_write(cfr->rfs_cfr_capture, tail, tail_data); 71 relay_flush(cfr->rfs_cfr_capture); 72 } 73 74 static void ath11k_cfr_free_pending_dbr_events(struct ath11k *ar) 75 { 76 struct ath11k_cfr *cfr = &ar->cfr; 77 struct ath11k_look_up_table *lut; 78 int i; 79 80 if (!cfr->lut) 81 return; 82 83 for (i = 0; i < cfr->lut_num; i++) { 84 lut = &cfr->lut[i]; 85 if (lut->dbr_recv && !lut->tx_recv && 86 lut->dbr_tstamp < cfr->last_success_tstamp) { 87 ath11k_dbring_bufs_replenish(ar, &cfr->rx_ring, lut->buff, 88 WMI_DIRECT_BUF_CFR); 89 ath11k_cfr_release_lut_entry(lut); 90 cfr->flush_dbr_cnt++; 91 } 92 } 93 } 94 95 /** 96 * ath11k_cfr_correlate_and_relay() - Correlate and relay CFR events 97 * @ar: Pointer to ath11k structure 98 * @lut: Lookup table for correlation 99 * @event_type: Type of event received (TX or DBR) 100 * 101 * Correlates WMI_PDEV_DMA_RING_BUF_RELEASE_EVENT (DBR) and 102 * WMI_PEER_CFR_CAPTURE_EVENT (TX capture) by PPDU ID. If both events 103 * are present and the PPDU IDs match, returns CORRELATE_STATUS_RELEASE 104 * to relay thecorrelated data to userspace. Otherwise returns 105 * CORRELATE_STATUS_HOLD to wait for the other event. 106 * 107 * Also checks pending DBR events and clears them when no corresponding TX 108 * capture event is received for the PPDU. 109 * 110 * Return: CORRELATE_STATUS_RELEASE or CORRELATE_STATUS_HOLD 111 */ 112 113 static enum ath11k_cfr_correlate_status 114 ath11k_cfr_correlate_and_relay(struct ath11k *ar, 115 struct ath11k_look_up_table *lut, 116 u8 event_type) 117 { 118 enum ath11k_cfr_correlate_status status; 119 struct ath11k_cfr *cfr = &ar->cfr; 120 u64 diff; 121 122 if (event_type == ATH11K_CORRELATE_TX_EVENT) { 123 if (lut->tx_recv) 124 cfr->cfr_dma_aborts++; 125 cfr->tx_evt_cnt++; 126 lut->tx_recv = true; 127 } else if (event_type == ATH11K_CORRELATE_DBR_EVENT) { 128 cfr->dbr_evt_cnt++; 129 lut->dbr_recv = true; 130 } 131 132 if (lut->dbr_recv && lut->tx_recv) { 133 if (lut->dbr_ppdu_id == lut->tx_ppdu_id) { 134 /* 135 * 64-bit counters make wraparound highly improbable, 136 * wraparound handling is omitted. 137 */ 138 cfr->last_success_tstamp = lut->dbr_tstamp; 139 if (lut->dbr_tstamp > lut->txrx_tstamp) { 140 diff = lut->dbr_tstamp - lut->txrx_tstamp; 141 ath11k_dbg(ar->ab, ATH11K_DBG_CFR, 142 "txrx event -> dbr event delay = %u ms", 143 jiffies_to_msecs(diff)); 144 } else if (lut->txrx_tstamp > lut->dbr_tstamp) { 145 diff = lut->txrx_tstamp - lut->dbr_tstamp; 146 ath11k_dbg(ar->ab, ATH11K_DBG_CFR, 147 "dbr event -> txrx event delay = %u ms", 148 jiffies_to_msecs(diff)); 149 } 150 151 ath11k_cfr_free_pending_dbr_events(ar); 152 153 cfr->release_cnt++; 154 status = ATH11K_CORRELATE_STATUS_RELEASE; 155 } else { 156 /* 157 * Discard TXRX event on PPDU ID mismatch because multiple PPDUs 158 * may share the same DMA address due to ucode aborts. 159 */ 160 161 ath11k_dbg(ar->ab, ATH11K_DBG_CFR, 162 "Received dbr event twice for the same lut entry"); 163 lut->tx_recv = false; 164 lut->tx_ppdu_id = 0; 165 cfr->clear_txrx_event++; 166 cfr->cfr_dma_aborts++; 167 status = ATH11K_CORRELATE_STATUS_HOLD; 168 } 169 } else { 170 status = ATH11K_CORRELATE_STATUS_HOLD; 171 } 172 173 return status; 174 } 175 176 static int ath11k_cfr_process_data(struct ath11k *ar, 177 struct ath11k_dbring_data *param) 178 { 179 u32 end_magic = ATH11K_CFR_END_MAGIC; 180 struct ath11k_csi_cfr_header *header; 181 struct ath11k_cfr_dma_hdr *dma_hdr; 182 struct ath11k_cfr *cfr = &ar->cfr; 183 struct ath11k_look_up_table *lut; 184 struct ath11k_base *ab = ar->ab; 185 u32 buf_id, tones, length; 186 u8 num_chains; 187 int status; 188 u8 *data; 189 190 data = param->data; 191 buf_id = param->buf_id; 192 193 if (param->data_sz < sizeof(*dma_hdr)) 194 return -EINVAL; 195 196 dma_hdr = (struct ath11k_cfr_dma_hdr *)data; 197 198 tones = ath11k_cfr_calculate_tones_from_dma_hdr(dma_hdr); 199 if (tones == TONES_INVALID) { 200 ath11k_warn(ar->ab, "Number of tones received is invalid\n"); 201 return -EINVAL; 202 } 203 204 num_chains = FIELD_GET(CFIR_DMA_HDR_INFO1_NUM_CHAINS, 205 dma_hdr->info1); 206 207 length = sizeof(*dma_hdr); 208 length += tones * (num_chains + 1); 209 210 spin_lock_bh(&cfr->lut_lock); 211 212 if (!cfr->lut) { 213 spin_unlock_bh(&cfr->lut_lock); 214 return -EINVAL; 215 } 216 217 lut = &cfr->lut[buf_id]; 218 219 ath11k_dbg_dump(ab, ATH11K_DBG_CFR_DUMP, "data_from_buf_rel:", "", 220 data, length); 221 222 lut->buff = param->buff; 223 lut->data = data; 224 lut->data_len = length; 225 lut->dbr_ppdu_id = dma_hdr->phy_ppdu_id; 226 lut->dbr_tstamp = jiffies; 227 228 memcpy(&lut->hdr, dma_hdr, sizeof(*dma_hdr)); 229 230 header = &lut->header; 231 header->meta_data.channel_bw = FIELD_GET(CFIR_DMA_HDR_INFO1_UPLOAD_PKT_BW, 232 dma_hdr->info1); 233 header->meta_data.length = length; 234 235 status = ath11k_cfr_correlate_and_relay(ar, lut, 236 ATH11K_CORRELATE_DBR_EVENT); 237 if (status == ATH11K_CORRELATE_STATUS_RELEASE) { 238 ath11k_dbg(ab, ATH11K_DBG_CFR, 239 "releasing CFR data to user space"); 240 ath11k_cfr_rfs_write(ar, &lut->header, 241 sizeof(struct ath11k_csi_cfr_header), 242 lut->data, lut->data_len, 243 &end_magic, sizeof(u32)); 244 ath11k_cfr_release_lut_entry(lut); 245 } else if (status == ATH11K_CORRELATE_STATUS_HOLD) { 246 ath11k_dbg(ab, ATH11K_DBG_CFR, 247 "tx event is not yet received holding the buf"); 248 } 249 250 spin_unlock_bh(&cfr->lut_lock); 251 252 return status; 253 } 254 255 static void ath11k_cfr_fill_hdr_info(struct ath11k *ar, 256 struct ath11k_csi_cfr_header *header, 257 struct ath11k_cfr_peer_tx_param *params) 258 { 259 struct ath11k_cfr *cfr; 260 261 cfr = &ar->cfr; 262 header->cfr_metadata_version = ATH11K_CFR_META_VERSION_4; 263 header->cfr_data_version = ATH11K_CFR_DATA_VERSION_1; 264 header->cfr_metadata_len = sizeof(struct cfr_metadata); 265 header->chip_type = ar->ab->hw_rev; 266 header->meta_data.status = FIELD_GET(WMI_CFR_PEER_CAPTURE_STATUS, 267 params->status); 268 header->meta_data.capture_bw = params->bandwidth; 269 270 /* 271 * FW reports phymode will always be HE mode. 272 * Replace it with cached phy mode during peer assoc 273 */ 274 header->meta_data.phy_mode = cfr->phymode; 275 276 header->meta_data.prim20_chan = params->primary_20mhz_chan; 277 header->meta_data.center_freq1 = params->band_center_freq1; 278 header->meta_data.center_freq2 = params->band_center_freq2; 279 280 /* 281 * CFR capture is triggered by the ACK of a QoS Null frame: 282 * - 20 MHz: Legacy ACK 283 * - 40/80/160 MHz: DUP Legacy ACK 284 */ 285 header->meta_data.capture_mode = params->bandwidth ? 286 ATH11K_CFR_CAPTURE_DUP_LEGACY_ACK : ATH11K_CFR_CAPTURE_LEGACY_ACK; 287 header->meta_data.capture_type = params->capture_method; 288 header->meta_data.num_rx_chain = ar->num_rx_chains; 289 header->meta_data.sts_count = params->spatial_streams; 290 header->meta_data.timestamp = params->timestamp_us; 291 ether_addr_copy(header->meta_data.peer_addr, params->peer_mac_addr); 292 memcpy(header->meta_data.chain_rssi, params->chain_rssi, 293 sizeof(params->chain_rssi)); 294 memcpy(header->meta_data.chain_phase, params->chain_phase, 295 sizeof(params->chain_phase)); 296 memcpy(header->meta_data.agc_gain, params->agc_gain, 297 sizeof(params->agc_gain)); 298 } 299 300 int ath11k_process_cfr_capture_event(struct ath11k_base *ab, 301 struct ath11k_cfr_peer_tx_param *params) 302 { 303 struct ath11k_look_up_table *lut = NULL; 304 u32 end_magic = ATH11K_CFR_END_MAGIC; 305 struct ath11k_csi_cfr_header *header; 306 struct ath11k_dbring_element *buff; 307 struct ath11k_cfr *cfr; 308 dma_addr_t buf_addr; 309 struct ath11k *ar; 310 u8 tx_status; 311 int status; 312 int i; 313 314 rcu_read_lock(); 315 ar = ath11k_mac_get_ar_by_vdev_id(ab, params->vdev_id); 316 if (!ar) { 317 rcu_read_unlock(); 318 ath11k_warn(ab, "Failed to get ar for vdev id %d\n", 319 params->vdev_id); 320 return -ENOENT; 321 } 322 323 cfr = &ar->cfr; 324 rcu_read_unlock(); 325 326 if (WMI_CFR_CAPTURE_STATUS_PEER_PS & params->status) { 327 ath11k_warn(ab, "CFR capture failed as peer %pM is in powersave", 328 params->peer_mac_addr); 329 return -EINVAL; 330 } 331 332 if (!(WMI_CFR_PEER_CAPTURE_STATUS & params->status)) { 333 ath11k_warn(ab, "CFR capture failed for the peer : %pM", 334 params->peer_mac_addr); 335 cfr->tx_peer_status_cfr_fail++; 336 return -EINVAL; 337 } 338 339 tx_status = FIELD_GET(WMI_CFR_FRAME_TX_STATUS, params->status); 340 if (tx_status != WMI_FRAME_TX_STATUS_OK) { 341 ath11k_warn(ab, "WMI tx status %d for the peer %pM", 342 tx_status, params->peer_mac_addr); 343 cfr->tx_evt_status_cfr_fail++; 344 return -EINVAL; 345 } 346 347 buf_addr = (((u64)FIELD_GET(WMI_CFR_CORRELATION_INFO2_BUF_ADDR_HIGH, 348 params->correlation_info_2)) << 32) | 349 params->correlation_info_1; 350 351 spin_lock_bh(&cfr->lut_lock); 352 353 if (!cfr->lut) { 354 spin_unlock_bh(&cfr->lut_lock); 355 return -EINVAL; 356 } 357 358 for (i = 0; i < cfr->lut_num; i++) { 359 struct ath11k_look_up_table *temp = &cfr->lut[i]; 360 361 if (temp->dbr_address == buf_addr) { 362 lut = &cfr->lut[i]; 363 break; 364 } 365 } 366 367 if (!lut) { 368 spin_unlock_bh(&cfr->lut_lock); 369 ath11k_warn(ab, "lut failure to process tx event\n"); 370 cfr->tx_dbr_lookup_fail++; 371 return -EINVAL; 372 } 373 374 lut->tx_ppdu_id = FIELD_GET(WMI_CFR_CORRELATION_INFO2_PPDU_ID, 375 params->correlation_info_2); 376 lut->txrx_tstamp = jiffies; 377 378 header = &lut->header; 379 header->start_magic_num = ATH11K_CFR_START_MAGIC; 380 header->vendorid = VENDOR_QCA; 381 header->platform_type = PLATFORM_TYPE_ARM; 382 383 ath11k_cfr_fill_hdr_info(ar, header, params); 384 385 status = ath11k_cfr_correlate_and_relay(ar, lut, 386 ATH11K_CORRELATE_TX_EVENT); 387 if (status == ATH11K_CORRELATE_STATUS_RELEASE) { 388 ath11k_dbg(ab, ATH11K_DBG_CFR, 389 "Releasing CFR data to user space"); 390 ath11k_cfr_rfs_write(ar, &lut->header, 391 sizeof(struct ath11k_csi_cfr_header), 392 lut->data, lut->data_len, 393 &end_magic, sizeof(u32)); 394 buff = lut->buff; 395 ath11k_cfr_release_lut_entry(lut); 396 397 ath11k_dbring_bufs_replenish(ar, &cfr->rx_ring, buff, 398 WMI_DIRECT_BUF_CFR); 399 } else if (status == ATH11K_CORRELATE_STATUS_HOLD) { 400 ath11k_dbg(ab, ATH11K_DBG_CFR, 401 "dbr event is not yet received holding buf\n"); 402 } 403 404 spin_unlock_bh(&cfr->lut_lock); 405 406 return 0; 407 } 408 409 /* Helper function to check whether the given peer mac address 410 * is in unassociated peer pool or not. 411 */ 412 bool ath11k_cfr_peer_is_in_cfr_unassoc_pool(struct ath11k *ar, const u8 *peer_mac) 413 { 414 struct ath11k_cfr *cfr = &ar->cfr; 415 struct cfr_unassoc_pool_entry *entry; 416 int i; 417 418 if (!ar->cfr_enabled) 419 return false; 420 421 spin_lock_bh(&cfr->lock); 422 for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) { 423 entry = &cfr->unassoc_pool[i]; 424 if (!entry->is_valid) 425 continue; 426 427 if (ether_addr_equal(peer_mac, entry->peer_mac)) { 428 spin_unlock_bh(&cfr->lock); 429 return true; 430 } 431 } 432 433 spin_unlock_bh(&cfr->lock); 434 435 return false; 436 } 437 438 void ath11k_cfr_update_unassoc_pool_entry(struct ath11k *ar, 439 const u8 *peer_mac) 440 { 441 struct ath11k_cfr *cfr = &ar->cfr; 442 struct cfr_unassoc_pool_entry *entry; 443 int i; 444 445 spin_lock_bh(&cfr->lock); 446 for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) { 447 entry = &cfr->unassoc_pool[i]; 448 if (!entry->is_valid) 449 continue; 450 451 if (ether_addr_equal(peer_mac, entry->peer_mac) && 452 entry->period == 0) { 453 memset(entry->peer_mac, 0, ETH_ALEN); 454 entry->is_valid = false; 455 cfr->cfr_enabled_peer_cnt--; 456 break; 457 } 458 } 459 460 spin_unlock_bh(&cfr->lock); 461 } 462 463 void ath11k_cfr_decrement_peer_count(struct ath11k *ar, 464 struct ath11k_sta *arsta) 465 { 466 struct ath11k_cfr *cfr = &ar->cfr; 467 468 spin_lock_bh(&cfr->lock); 469 470 if (arsta->cfr_capture.cfr_enable) 471 cfr->cfr_enabled_peer_cnt--; 472 473 spin_unlock_bh(&cfr->lock); 474 } 475 476 static enum ath11k_wmi_cfr_capture_bw 477 ath11k_cfr_bw_to_fw_cfr_bw(enum ath11k_cfr_capture_bw bw) 478 { 479 switch (bw) { 480 case ATH11K_CFR_CAPTURE_BW_20: 481 return WMI_PEER_CFR_CAPTURE_BW_20; 482 case ATH11K_CFR_CAPTURE_BW_40: 483 return WMI_PEER_CFR_CAPTURE_BW_40; 484 case ATH11K_CFR_CAPTURE_BW_80: 485 return WMI_PEER_CFR_CAPTURE_BW_80; 486 default: 487 return WMI_PEER_CFR_CAPTURE_BW_MAX; 488 } 489 } 490 491 static enum ath11k_wmi_cfr_capture_method 492 ath11k_cfr_method_to_fw_cfr_method(enum ath11k_cfr_capture_method method) 493 { 494 switch (method) { 495 case ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME: 496 return WMI_CFR_CAPTURE_METHOD_NULL_FRAME; 497 case ATH11K_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE: 498 return WMI_CFR_CAPTURE_METHOD_NULL_FRAME_WITH_PHASE; 499 case ATH11K_CFR_CAPTURE_METHOD_PROBE_RESP: 500 return WMI_CFR_CAPTURE_METHOD_PROBE_RESP; 501 default: 502 return WMI_CFR_CAPTURE_METHOD_MAX; 503 } 504 } 505 506 int ath11k_cfr_send_peer_cfr_capture_cmd(struct ath11k *ar, 507 struct ath11k_sta *arsta, 508 struct ath11k_per_peer_cfr_capture *params, 509 const u8 *peer_mac) 510 { 511 struct ath11k_cfr *cfr = &ar->cfr; 512 struct wmi_peer_cfr_capture_conf_arg arg; 513 enum ath11k_wmi_cfr_capture_bw bw; 514 enum ath11k_wmi_cfr_capture_method method; 515 int ret = 0; 516 517 if (cfr->cfr_enabled_peer_cnt >= ATH11K_MAX_CFR_ENABLED_CLIENTS && 518 !arsta->cfr_capture.cfr_enable) { 519 ath11k_err(ar->ab, "CFR enable peer threshold reached %u\n", 520 cfr->cfr_enabled_peer_cnt); 521 return -ENOSPC; 522 } 523 524 if (params->cfr_enable == arsta->cfr_capture.cfr_enable && 525 params->cfr_period == arsta->cfr_capture.cfr_period && 526 params->cfr_method == arsta->cfr_capture.cfr_method && 527 params->cfr_bw == arsta->cfr_capture.cfr_bw) 528 return ret; 529 530 if (!params->cfr_enable && !arsta->cfr_capture.cfr_enable) 531 return ret; 532 533 bw = ath11k_cfr_bw_to_fw_cfr_bw(params->cfr_bw); 534 if (bw >= WMI_PEER_CFR_CAPTURE_BW_MAX) { 535 ath11k_warn(ar->ab, "FW doesn't support configured bw %d\n", 536 params->cfr_bw); 537 return -EINVAL; 538 } 539 540 method = ath11k_cfr_method_to_fw_cfr_method(params->cfr_method); 541 if (method >= WMI_CFR_CAPTURE_METHOD_MAX) { 542 ath11k_warn(ar->ab, "FW doesn't support configured method %d\n", 543 params->cfr_method); 544 return -EINVAL; 545 } 546 547 arg.request = params->cfr_enable; 548 arg.periodicity = params->cfr_period; 549 arg.bw = bw; 550 arg.method = method; 551 552 ret = ath11k_wmi_peer_set_cfr_capture_conf(ar, arsta->arvif->vdev_id, 553 peer_mac, &arg); 554 if (ret) { 555 ath11k_warn(ar->ab, 556 "failed to send cfr capture info: vdev_id %u peer %pM: %d\n", 557 arsta->arvif->vdev_id, peer_mac, ret); 558 return ret; 559 } 560 561 spin_lock_bh(&cfr->lock); 562 563 if (params->cfr_enable && 564 params->cfr_enable != arsta->cfr_capture.cfr_enable) 565 cfr->cfr_enabled_peer_cnt++; 566 else if (!params->cfr_enable) 567 cfr->cfr_enabled_peer_cnt--; 568 569 spin_unlock_bh(&cfr->lock); 570 571 arsta->cfr_capture.cfr_enable = params->cfr_enable; 572 arsta->cfr_capture.cfr_period = params->cfr_period; 573 arsta->cfr_capture.cfr_method = params->cfr_method; 574 arsta->cfr_capture.cfr_bw = params->cfr_bw; 575 576 return ret; 577 } 578 579 void ath11k_cfr_update_unassoc_pool(struct ath11k *ar, 580 struct ath11k_per_peer_cfr_capture *params, 581 u8 *peer_mac) 582 { 583 struct ath11k_cfr *cfr = &ar->cfr; 584 struct cfr_unassoc_pool_entry *entry; 585 int available_idx = -1; 586 int i; 587 588 guard(spinlock_bh)(&cfr->lock); 589 590 if (!params->cfr_enable) { 591 for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) { 592 entry = &cfr->unassoc_pool[i]; 593 if (ether_addr_equal(peer_mac, entry->peer_mac)) { 594 memset(entry->peer_mac, 0, ETH_ALEN); 595 entry->is_valid = false; 596 cfr->cfr_enabled_peer_cnt--; 597 break; 598 } 599 } 600 return; 601 } 602 603 if (cfr->cfr_enabled_peer_cnt >= ATH11K_MAX_CFR_ENABLED_CLIENTS) { 604 ath11k_info(ar->ab, "Max cfr peer threshold reached\n"); 605 return; 606 } 607 608 for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) { 609 entry = &cfr->unassoc_pool[i]; 610 611 if (ether_addr_equal(peer_mac, entry->peer_mac)) { 612 ath11k_info(ar->ab, 613 "peer entry already present updating params\n"); 614 entry->period = params->cfr_period; 615 available_idx = -1; 616 break; 617 } 618 619 if (available_idx < 0 && !entry->is_valid) 620 available_idx = i; 621 } 622 623 if (available_idx >= 0) { 624 entry = &cfr->unassoc_pool[available_idx]; 625 ether_addr_copy(entry->peer_mac, peer_mac); 626 entry->period = params->cfr_period; 627 entry->is_valid = true; 628 cfr->cfr_enabled_peer_cnt++; 629 } 630 } 631 632 static ssize_t ath11k_read_file_enable_cfr(struct file *file, 633 char __user *user_buf, 634 size_t count, loff_t *ppos) 635 { 636 struct ath11k *ar = file->private_data; 637 char buf[32] = {}; 638 size_t len; 639 640 mutex_lock(&ar->conf_mutex); 641 len = scnprintf(buf, sizeof(buf), "%d\n", ar->cfr_enabled); 642 mutex_unlock(&ar->conf_mutex); 643 644 return simple_read_from_buffer(user_buf, count, ppos, buf, len); 645 } 646 647 static ssize_t ath11k_write_file_enable_cfr(struct file *file, 648 const char __user *ubuf, 649 size_t count, loff_t *ppos) 650 { 651 struct ath11k *ar = file->private_data; 652 u32 enable_cfr; 653 int ret; 654 655 if (kstrtouint_from_user(ubuf, count, 0, &enable_cfr)) 656 return -EINVAL; 657 658 guard(mutex)(&ar->conf_mutex); 659 660 if (ar->state != ATH11K_STATE_ON) 661 return -ENETDOWN; 662 663 if (enable_cfr > 1) 664 return -EINVAL; 665 666 if (ar->cfr_enabled == enable_cfr) 667 return count; 668 669 ret = ath11k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PER_PEER_CFR_ENABLE, 670 enable_cfr, ar->pdev->pdev_id); 671 if (ret) { 672 ath11k_warn(ar->ab, 673 "Failed to enable/disable per peer cfr %d\n", ret); 674 return ret; 675 } 676 677 ar->cfr_enabled = enable_cfr; 678 679 return count; 680 } 681 682 static const struct file_operations fops_enable_cfr = { 683 .read = ath11k_read_file_enable_cfr, 684 .write = ath11k_write_file_enable_cfr, 685 .open = simple_open, 686 .owner = THIS_MODULE, 687 .llseek = default_llseek, 688 }; 689 690 static ssize_t ath11k_write_file_cfr_unassoc(struct file *file, 691 const char __user *ubuf, 692 size_t count, loff_t *ppos) 693 { 694 struct ath11k *ar = file->private_data; 695 struct ath11k_cfr *cfr = &ar->cfr; 696 struct cfr_unassoc_pool_entry *entry; 697 char buf[64] = {}; 698 u8 peer_mac[6]; 699 u32 cfr_capture_enable; 700 u32 cfr_capture_period; 701 int available_idx = -1; 702 int ret, i; 703 704 simple_write_to_buffer(buf, sizeof(buf) - 1, ppos, ubuf, count); 705 706 guard(mutex)(&ar->conf_mutex); 707 guard(spinlock_bh)(&cfr->lock); 708 709 if (ar->state != ATH11K_STATE_ON) 710 return -ENETDOWN; 711 712 if (!ar->cfr_enabled) { 713 ath11k_err(ar->ab, "CFR is not enabled on this pdev %d\n", 714 ar->pdev_idx); 715 return -EINVAL; 716 } 717 718 ret = sscanf(buf, "%hhx:%hhx:%hhx:%hhx:%hhx:%hhx %u %u", 719 &peer_mac[0], &peer_mac[1], &peer_mac[2], &peer_mac[3], 720 &peer_mac[4], &peer_mac[5], &cfr_capture_enable, 721 &cfr_capture_period); 722 723 if (ret < 1) 724 return -EINVAL; 725 726 if (cfr_capture_enable && ret != 8) 727 return -EINVAL; 728 729 if (!cfr_capture_enable) { 730 for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) { 731 entry = &cfr->unassoc_pool[i]; 732 if (ether_addr_equal(peer_mac, entry->peer_mac)) { 733 memset(entry->peer_mac, 0, ETH_ALEN); 734 entry->is_valid = false; 735 cfr->cfr_enabled_peer_cnt--; 736 } 737 } 738 739 return count; 740 } 741 742 if (cfr->cfr_enabled_peer_cnt >= ATH11K_MAX_CFR_ENABLED_CLIENTS) { 743 ath11k_info(ar->ab, "Max cfr peer threshold reached\n"); 744 return count; 745 } 746 747 for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) { 748 entry = &cfr->unassoc_pool[i]; 749 750 if (available_idx < 0 && !entry->is_valid) 751 available_idx = i; 752 753 if (ether_addr_equal(peer_mac, entry->peer_mac)) { 754 ath11k_info(ar->ab, 755 "peer entry already present updating params\n"); 756 entry->period = cfr_capture_period; 757 return count; 758 } 759 } 760 761 if (available_idx >= 0) { 762 entry = &cfr->unassoc_pool[available_idx]; 763 ether_addr_copy(entry->peer_mac, peer_mac); 764 entry->period = cfr_capture_period; 765 entry->is_valid = true; 766 cfr->cfr_enabled_peer_cnt++; 767 } 768 769 return count; 770 } 771 772 static ssize_t ath11k_read_file_cfr_unassoc(struct file *file, 773 char __user *ubuf, 774 size_t count, loff_t *ppos) 775 { 776 struct ath11k *ar = file->private_data; 777 struct ath11k_cfr *cfr = &ar->cfr; 778 struct cfr_unassoc_pool_entry *entry; 779 char buf[512] = {}; 780 int len = 0, i; 781 782 spin_lock_bh(&cfr->lock); 783 784 for (i = 0; i < ATH11K_MAX_CFR_ENABLED_CLIENTS; i++) { 785 entry = &cfr->unassoc_pool[i]; 786 if (entry->is_valid) 787 len += scnprintf(buf + len, sizeof(buf) - len, 788 "peer: %pM period: %u\n", 789 entry->peer_mac, entry->period); 790 } 791 792 spin_unlock_bh(&cfr->lock); 793 794 return simple_read_from_buffer(ubuf, count, ppos, buf, len); 795 } 796 797 static const struct file_operations fops_configure_cfr_unassoc = { 798 .write = ath11k_write_file_cfr_unassoc, 799 .read = ath11k_read_file_cfr_unassoc, 800 .open = simple_open, 801 .owner = THIS_MODULE, 802 .llseek = default_llseek, 803 }; 804 805 static void ath11k_cfr_debug_unregister(struct ath11k *ar) 806 { 807 debugfs_remove(ar->cfr.enable_cfr); 808 ar->cfr.enable_cfr = NULL; 809 debugfs_remove(ar->cfr.cfr_unassoc); 810 ar->cfr.cfr_unassoc = NULL; 811 812 relay_close(ar->cfr.rfs_cfr_capture); 813 ar->cfr.rfs_cfr_capture = NULL; 814 } 815 816 static struct dentry *ath11k_cfr_create_buf_file_handler(const char *filename, 817 struct dentry *parent, 818 umode_t mode, 819 struct rchan_buf *buf, 820 int *is_global) 821 { 822 struct dentry *buf_file; 823 824 buf_file = debugfs_create_file(filename, mode, parent, buf, 825 &relay_file_operations); 826 *is_global = 1; 827 return buf_file; 828 } 829 830 static int ath11k_cfr_remove_buf_file_handler(struct dentry *dentry) 831 { 832 debugfs_remove(dentry); 833 834 return 0; 835 } 836 837 static const struct rchan_callbacks rfs_cfr_capture_cb = { 838 .create_buf_file = ath11k_cfr_create_buf_file_handler, 839 .remove_buf_file = ath11k_cfr_remove_buf_file_handler, 840 }; 841 842 static void ath11k_cfr_debug_register(struct ath11k *ar) 843 { 844 ar->cfr.rfs_cfr_capture = relay_open("cfr_capture", 845 ar->debug.debugfs_pdev, 846 ar->ab->hw_params.cfr_stream_buf_size, 847 ar->ab->hw_params.cfr_num_stream_bufs, 848 &rfs_cfr_capture_cb, NULL); 849 850 ar->cfr.enable_cfr = debugfs_create_file("enable_cfr", 0600, 851 ar->debug.debugfs_pdev, ar, 852 &fops_enable_cfr); 853 854 ar->cfr.cfr_unassoc = debugfs_create_file("cfr_unassoc", 0600, 855 ar->debug.debugfs_pdev, ar, 856 &fops_configure_cfr_unassoc); 857 } 858 859 void ath11k_cfr_lut_update_paddr(struct ath11k *ar, dma_addr_t paddr, 860 u32 buf_id) 861 { 862 struct ath11k_cfr *cfr = &ar->cfr; 863 864 if (cfr->lut) 865 cfr->lut[buf_id].dbr_address = paddr; 866 } 867 868 void ath11k_cfr_update_phymode(struct ath11k *ar, enum wmi_phy_mode phymode) 869 { 870 struct ath11k_cfr *cfr = &ar->cfr; 871 872 cfr->phymode = phymode; 873 } 874 875 static void ath11k_cfr_ring_free(struct ath11k *ar) 876 { 877 struct ath11k_cfr *cfr = &ar->cfr; 878 879 ath11k_dbring_buf_cleanup(ar, &cfr->rx_ring); 880 ath11k_dbring_srng_cleanup(ar, &cfr->rx_ring); 881 } 882 883 static int ath11k_cfr_ring_alloc(struct ath11k *ar, 884 struct ath11k_dbring_cap *db_cap) 885 { 886 struct ath11k_cfr *cfr = &ar->cfr; 887 int ret; 888 889 ret = ath11k_dbring_srng_setup(ar, &cfr->rx_ring, 890 ATH11K_CFR_NUM_RING_ENTRIES, 891 db_cap->min_elem); 892 if (ret) { 893 ath11k_warn(ar->ab, "failed to setup db ring: %d\n", ret); 894 return ret; 895 } 896 897 ath11k_dbring_set_cfg(ar, &cfr->rx_ring, 898 ATH11K_CFR_NUM_RESP_PER_EVENT, 899 ATH11K_CFR_EVENT_TIMEOUT_MS, 900 ath11k_cfr_process_data); 901 902 ret = ath11k_dbring_buf_setup(ar, &cfr->rx_ring, db_cap); 903 if (ret) { 904 ath11k_warn(ar->ab, "failed to setup db ring buffer: %d\n", ret); 905 goto srng_cleanup; 906 } 907 908 ret = ath11k_dbring_wmi_cfg_setup(ar, &cfr->rx_ring, WMI_DIRECT_BUF_CFR); 909 if (ret) { 910 ath11k_warn(ar->ab, "failed to setup db ring cfg: %d\n", ret); 911 goto buffer_cleanup; 912 } 913 914 return 0; 915 916 buffer_cleanup: 917 ath11k_dbring_buf_cleanup(ar, &cfr->rx_ring); 918 srng_cleanup: 919 ath11k_dbring_srng_cleanup(ar, &cfr->rx_ring); 920 return ret; 921 } 922 923 void ath11k_cfr_deinit(struct ath11k_base *ab) 924 { 925 struct ath11k_cfr *cfr; 926 struct ath11k *ar; 927 int i; 928 929 if (!test_bit(WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT, ab->wmi_ab.svc_map) || 930 !ab->hw_params.cfr_support) 931 return; 932 933 for (i = 0; i < ab->num_radios; i++) { 934 ar = ab->pdevs[i].ar; 935 cfr = &ar->cfr; 936 937 if (!cfr->enabled) 938 continue; 939 940 ath11k_cfr_debug_unregister(ar); 941 ath11k_cfr_ring_free(ar); 942 943 spin_lock_bh(&cfr->lut_lock); 944 kfree(cfr->lut); 945 cfr->lut = NULL; 946 cfr->enabled = false; 947 spin_unlock_bh(&cfr->lut_lock); 948 } 949 } 950 951 int ath11k_cfr_init(struct ath11k_base *ab) 952 { 953 struct ath11k_dbring_cap db_cap; 954 struct ath11k_cfr *cfr; 955 u32 num_lut_entries; 956 struct ath11k *ar; 957 int i, ret; 958 959 if (!test_bit(WMI_TLV_SERVICE_CFR_CAPTURE_SUPPORT, ab->wmi_ab.svc_map) || 960 !ab->hw_params.cfr_support) 961 return 0; 962 963 for (i = 0; i < ab->num_radios; i++) { 964 ar = ab->pdevs[i].ar; 965 cfr = &ar->cfr; 966 967 ret = ath11k_dbring_get_cap(ar->ab, ar->pdev_idx, 968 WMI_DIRECT_BUF_CFR, &db_cap); 969 if (ret) 970 continue; 971 972 idr_init(&cfr->rx_ring.bufs_idr); 973 spin_lock_init(&cfr->rx_ring.idr_lock); 974 spin_lock_init(&cfr->lock); 975 spin_lock_init(&cfr->lut_lock); 976 977 num_lut_entries = min_t(u32, CFR_MAX_LUT_ENTRIES, db_cap.min_elem); 978 cfr->lut = kzalloc_objs(*cfr->lut, num_lut_entries); 979 if (!cfr->lut) { 980 ret = -ENOMEM; 981 goto err; 982 } 983 984 ret = ath11k_cfr_ring_alloc(ar, &db_cap); 985 if (ret) { 986 ath11k_warn(ab, "failed to init cfr ring for pdev %d: %d\n", 987 i, ret); 988 spin_lock_bh(&cfr->lut_lock); 989 kfree(cfr->lut); 990 cfr->lut = NULL; 991 cfr->enabled = false; 992 spin_unlock_bh(&cfr->lut_lock); 993 goto err; 994 } 995 996 cfr->lut_num = num_lut_entries; 997 cfr->enabled = true; 998 999 ath11k_cfr_debug_register(ar); 1000 } 1001 1002 return 0; 1003 1004 err: 1005 for (i = i - 1; i >= 0; i--) { 1006 ar = ab->pdevs[i].ar; 1007 cfr = &ar->cfr; 1008 1009 if (!cfr->enabled) 1010 continue; 1011 1012 ath11k_cfr_debug_unregister(ar); 1013 ath11k_cfr_ring_free(ar); 1014 1015 spin_lock_bh(&cfr->lut_lock); 1016 kfree(cfr->lut); 1017 cfr->lut = NULL; 1018 cfr->enabled = false; 1019 spin_unlock_bh(&cfr->lut_lock); 1020 } 1021 return ret; 1022 } 1023