1 /* 2 * Copyright (c) 2011,2017-2020 The Linux Foundation. All rights reserved. 3 * 4 * 5 * Permission to use, copy, modify, and/or distribute this software for 6 * any purpose with or without fee is hereby granted, provided that the 7 * above copyright notice and this permission notice appear in all 8 * copies. 9 * 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL 11 * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED 12 * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE 13 * AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL 14 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 15 * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER 16 * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR 17 * PERFORMANCE OF THIS SOFTWARE. 18 */ 19 20 #include <osdep.h> 21 #include <qdf_types.h> 22 #include <qdf_module.h> 23 #include <wlan_tgt_def_config.h> 24 #include <hif.h> 25 #include <hif_hw_version.h> 26 #include <wmi_unified_api.h> 27 #include <target_if_spectral.h> 28 #include <wlan_lmac_if_def.h> 29 #include <wlan_osif_priv.h> 30 #include <reg_services_public_struct.h> 31 #include <target_if.h> 32 #ifdef DIRECT_BUF_RX_ENABLE 33 #include <target_if_direct_buf_rx_api.h> 34 #endif 35 extern int spectral_debug_level; 36 37 #ifdef WLAN_CONV_SPECTRAL_ENABLE 38 39 #define SPECTRAL_HEXDUMP_OCTET_PRINT_SIZE (3) 40 #define SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE (16) 41 #define SPECTRAL_HEXDUMP_EXTRA_BUFFER_PER_LINE (16) 42 43 /* 44 * Provision for the expected hexdump line size as follows: 45 * 46 * Size per octet multiplied by number of octets per line 47 * + 48 * ASCII representation which is equivalent in print size to number of octets 49 * per line 50 * + 51 * Some extra buffer 52 */ 53 #define SPECTRAL_HEXDUMP_LINESIZE \ 54 ((SPECTRAL_HEXDUMP_OCTET_PRINT_SIZE * \ 55 SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE) + \ 56 SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE + \ 57 SPECTRAL_HEXDUMP_EXTRA_BUFFER_PER_LINE) 58 59 /** 60 * target_if_spectral_hexdump() - Print hexdump of the given buffer 61 * @_buf: Pointer to buffer 62 * @_len: Length of the buffer 63 * 64 * Print the hexdump of buffer upto given length. Print upto 65 * SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE per line, followed by the ASCII 66 * representation of these octets. 67 */ 68 static inline void target_if_spectral_hexdump(unsigned char *_buf, int _len) 69 { 70 int i, mod; 71 unsigned char ascii[SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE + 1]; 72 unsigned char *pc = (_buf); 73 char hexdump_line[SPECTRAL_HEXDUMP_LINESIZE + 1]; 74 int loc = 0; 75 76 qdf_mem_zero(hexdump_line, sizeof(hexdump_line)); 77 78 if (_len <= 0) { 79 spectral_err("buffer len is %d, too short", _len); 80 return; 81 } 82 83 for (i = 0; i < _len; i++) { 84 mod = i % SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE; 85 86 if (!mod) { 87 if (i) { 88 qdf_assert_always(loc < sizeof(hexdump_line)); 89 loc += snprintf(&hexdump_line[loc], 90 sizeof(hexdump_line) - loc, 91 " %s", ascii); 92 spectral_debug("%s", hexdump_line); 93 qdf_mem_zero(hexdump_line, 94 sizeof(hexdump_line)); 95 loc = 0; 96 } 97 } 98 99 qdf_assert_always(loc < sizeof(hexdump_line)); 100 loc += snprintf(&hexdump_line[loc], sizeof(hexdump_line) - loc, 101 " %02x", pc[i]); 102 103 if ((pc[i] < 0x20) || (pc[i] > 0x7e)) 104 ascii[mod] = '.'; 105 else 106 ascii[mod] = pc[i]; 107 ascii[(mod) + 1] = '\0'; 108 } 109 110 while ((i % SPECTRAL_HEXDUMP_NUM_OCTETS_PER_LINE) != 0) { 111 qdf_assert_always(loc < sizeof(hexdump_line)); 112 loc += snprintf(&hexdump_line[loc], sizeof(hexdump_line) - loc, 113 " "); 114 i++; 115 } 116 117 qdf_assert_always(loc < sizeof(hexdump_line)); 118 snprintf(&hexdump_line[loc], sizeof(hexdump_line) - loc, " %s", ascii); 119 spectral_debug("%s", hexdump_line); 120 } 121 122 /** 123 * target_if_print_buf() - Prints given buffer for given length 124 * @pbuf: Pointer to buffer 125 * @len: length 126 * 127 * Prints given buffer for given length 128 * 129 * Return: void 130 */ 131 static void 132 target_if_print_buf(uint8_t *pbuf, int len) 133 { 134 int i = 0; 135 136 for (i = 0; i < len; i++) { 137 spectral_debug("%02X ", pbuf[i]); 138 if (i % 32 == 31) 139 spectral_debug("\n"); 140 } 141 } 142 143 int 144 target_if_spectral_dump_fft(uint8_t *pfft, int fftlen) 145 { 146 int i = 0; 147 148 /* 149 * TODO : Do not delete the following print 150 * The scripts used to validate Spectral depend on this Print 151 */ 152 spectral_debug("SPECTRAL : FFT Length is 0x%x (%d)", fftlen, fftlen); 153 154 spectral_debug("fft_data # "); 155 for (i = 0; i < fftlen; i++) 156 spectral_debug("%d ", pfft[i]); 157 spectral_debug("\n"); 158 return 0; 159 } 160 161 QDF_STATUS target_if_spectral_fw_hang(struct target_if_spectral *spectral) 162 { 163 struct crash_inject param; 164 struct wlan_objmgr_pdev *pdev; 165 struct wlan_objmgr_psoc *psoc; 166 struct target_if_psoc_spectral *psoc_spectral; 167 168 if (!spectral) { 169 spectral_err("Spectral LMAC object is null"); 170 return QDF_STATUS_E_INVAL; 171 } 172 173 pdev = spectral->pdev_obj; 174 if (!pdev) { 175 spectral_err("pdev is null"); 176 return QDF_STATUS_E_FAILURE; 177 } 178 179 psoc = wlan_pdev_get_psoc(pdev); 180 if (!psoc) { 181 spectral_err("psoc is null"); 182 return QDF_STATUS_E_FAILURE; 183 } 184 185 psoc_spectral = get_target_if_spectral_handle_from_psoc(psoc); 186 if (!psoc_spectral) { 187 spectral_err("spectral psoc object is null"); 188 return QDF_STATUS_E_FAILURE; 189 } 190 191 qdf_mem_set(¶m, sizeof(param), 0); 192 param.type = 1; //RECOVERY_SIM_ASSERT 193 194 return psoc_spectral->wmi_ops.wmi_spectral_crash_inject( 195 GET_WMI_HDL_FROM_PDEV(spectral->pdev_obj), ¶m); 196 } 197 198 void 199 target_if_dbg_print_samp_param(struct target_if_samp_msg_params *p) 200 { 201 spectral_debug("\nSAMP Packet : -------------------- START --------------------"); 202 spectral_debug("Freq = %d", p->freq); 203 spectral_debug("RSSI = %d", p->rssi); 204 spectral_debug("Bin Count = %d", p->pwr_count); 205 spectral_debug("Timestamp = %d", p->tstamp); 206 spectral_debug("SAMP Packet : -------------------- END -----------------------"); 207 } 208 209 void 210 target_if_dbg_print_samp_msg(struct spectral_samp_msg *ss_msg) 211 { 212 int i = 0; 213 214 struct spectral_samp_data *p = &ss_msg->samp_data; 215 struct spectral_classifier_params *pc = &p->classifier_params; 216 struct interf_src_rsp *pi = &p->interf_list; 217 218 spectral_dbg_line(); 219 spectral_debug("Spectral Message"); 220 spectral_dbg_line(); 221 spectral_debug("Signature : 0x%x", ss_msg->signature); 222 spectral_debug("Freq : %d", ss_msg->freq); 223 spectral_debug("Freq load : %d", ss_msg->freq_loading); 224 spectral_debug("Intfnc type : %d", ss_msg->int_type); 225 spectral_dbg_line(); 226 spectral_debug("Spectral Data info"); 227 spectral_dbg_line(); 228 spectral_debug("data length : %d", p->spectral_data_len); 229 spectral_debug("rssi : %d", p->spectral_rssi); 230 spectral_debug("combined rssi : %d", p->spectral_combined_rssi); 231 spectral_debug("upper rssi : %d", p->spectral_upper_rssi); 232 spectral_debug("lower rssi : %d", p->spectral_lower_rssi); 233 spectral_debug("bw info : %d", p->spectral_bwinfo); 234 spectral_debug("timestamp : %d", p->spectral_tstamp); 235 spectral_debug("max index : %d", p->spectral_max_index); 236 spectral_debug("max exp : %d", p->spectral_max_exp); 237 spectral_debug("max mag : %d", p->spectral_max_mag); 238 spectral_debug("last timstamp : %d", p->spectral_last_tstamp); 239 spectral_debug("upper max idx : %d", p->spectral_upper_max_index); 240 spectral_debug("lower max idx : %d", p->spectral_lower_max_index); 241 spectral_debug("bin power count : %d", p->bin_pwr_count); 242 spectral_dbg_line(); 243 spectral_debug("Classifier info"); 244 spectral_dbg_line(); 245 spectral_debug("20/40 Mode : %d", pc->spectral_20_40_mode); 246 spectral_debug("dc index : %d", pc->spectral_dc_index); 247 spectral_debug("dc in MHz : %d", pc->spectral_dc_in_mhz); 248 spectral_debug("upper channel : %d", pc->upper_chan_in_mhz); 249 spectral_debug("lower channel : %d", pc->lower_chan_in_mhz); 250 spectral_dbg_line(); 251 spectral_debug("Interference info"); 252 spectral_dbg_line(); 253 spectral_debug("inter count : %d", pi->count); 254 255 for (i = 0; i < pi->count; i++) { 256 spectral_debug("inter type : %d", 257 pi->interf[i].interf_type); 258 spectral_debug("min freq : %d", 259 pi->interf[i].interf_min_freq); 260 spectral_debug("max freq : %d", 261 pi->interf[i].interf_max_freq); 262 } 263 } 264 265 uint32_t 266 target_if_get_offset_swar_sec80(uint32_t channel_width) 267 { 268 uint32_t offset = 0; 269 270 switch (channel_width) { 271 case CH_WIDTH_20MHZ: 272 offset = OFFSET_CH_WIDTH_20; 273 break; 274 case CH_WIDTH_40MHZ: 275 offset = OFFSET_CH_WIDTH_40; 276 break; 277 case CH_WIDTH_80MHZ: 278 offset = OFFSET_CH_WIDTH_80; 279 break; 280 case CH_WIDTH_160MHZ: 281 case CH_WIDTH_80P80MHZ: 282 offset = OFFSET_CH_WIDTH_160; 283 break; 284 default: 285 offset = OFFSET_CH_WIDTH_80; 286 break; 287 } 288 return offset; 289 } 290 291 /** 292 * target_if_dump_summary_report_gen2() - Dump Spectral Summary Report for gen2 293 * @ptlv: Pointer to Spectral Phyerr TLV 294 * @tlvlen: length 295 * @is_160_format: Indicates whether information provided by HW is in altered 296 * format for 802.11ac 160/80+80 MHz support (QCA9984 onwards) 297 * 298 * Dump Spectral Summary Report for gen2 299 * 300 * Return: Success/Failure 301 */ 302 static int 303 target_if_dump_summary_report_gen2(struct spectral_phyerr_tlv_gen2 *ptlv, 304 int tlvlen, bool is_160_format) 305 { 306 /* 307 * For simplicity, everything is defined as uint32_t (except one). 308 * Proper code will later use the right sizes. 309 */ 310 311 /* 312 * For easy comparision between MDK team and OS team, the MDK script 313 * variable names have been used 314 */ 315 316 uint32_t agc_mb_gain; 317 uint32_t sscan_gidx; 318 uint32_t agc_total_gain; 319 uint32_t recent_rfsat; 320 uint32_t ob_flag; 321 uint32_t nb_mask; 322 uint32_t peak_mag; 323 int16_t peak_inx; 324 325 uint32_t ss_summary_A = 0; 326 uint32_t ss_summary_B = 0; 327 uint32_t ss_summary_C = 0; 328 uint32_t ss_summary_D = 0; 329 uint32_t ss_summary_E = 0; 330 struct spectral_phyerr_hdr_gen2 *phdr = 331 (struct spectral_phyerr_hdr_gen2 *)( 332 (uint8_t *)ptlv + 333 sizeof(struct spectral_phyerr_tlv_gen2)); 334 335 spectral_debug("SPECTRAL : SPECTRAL SUMMARY REPORT"); 336 337 if (is_160_format) { 338 if (tlvlen != 20) { 339 spectral_err("Unexpected TLV length %d for Spectral Summary Report! Hexdump follows", 340 tlvlen); 341 target_if_print_buf((uint8_t *)ptlv, tlvlen + 4); 342 return -EPERM; 343 } 344 345 /* Doing copy as the contents may not be aligned */ 346 qdf_mem_copy(&ss_summary_A, (uint8_t *)phdr, sizeof(int)); 347 qdf_mem_copy(&ss_summary_B, 348 (uint8_t *)((uint8_t *)phdr + sizeof(int)), 349 sizeof(int)); 350 qdf_mem_copy(&ss_summary_C, 351 (uint8_t *)((uint8_t *)phdr + 2 * sizeof(int)), 352 sizeof(int)); 353 qdf_mem_copy(&ss_summary_D, 354 (uint8_t *)((uint8_t *)phdr + 3 * sizeof(int)), 355 sizeof(int)); 356 qdf_mem_copy(&ss_summary_E, 357 (uint8_t *)((uint8_t *)phdr + 4 * sizeof(int)), 358 sizeof(int)); 359 360 /* 361 * The following is adapted from MDK scripts for 362 * easier comparability 363 */ 364 365 recent_rfsat = ((ss_summary_A >> 8) & 0x1); 366 sscan_gidx = (ss_summary_A & 0xff); 367 spectral_debug("sscan_gidx=%d, is_recent_rfsat=%d", 368 sscan_gidx, recent_rfsat); 369 370 /* First segment */ 371 agc_mb_gain = ((ss_summary_B >> 10) & 0x7f); 372 agc_total_gain = (ss_summary_B & 0x3ff); 373 nb_mask = ((ss_summary_C >> 22) & 0xff); 374 ob_flag = ((ss_summary_B >> 17) & 0x1); 375 peak_inx = (ss_summary_C & 0xfff); 376 if (peak_inx > 2047) 377 peak_inx = peak_inx - 4096; 378 peak_mag = ((ss_summary_C >> 12) & 0x3ff); 379 380 spectral_debug("agc_total_gain_segid0 = 0x%.2x, agc_mb_gain_segid0=%d", 381 agc_total_gain, agc_mb_gain); 382 spectral_debug("nb_mask_segid0 = 0x%.2x, ob_flag_segid0=%d, peak_index_segid0=%d, peak_mag_segid0=%d", 383 nb_mask, ob_flag, peak_inx, peak_mag); 384 385 /* Second segment */ 386 agc_mb_gain = ((ss_summary_D >> 10) & 0x7f); 387 agc_total_gain = (ss_summary_D & 0x3ff); 388 nb_mask = ((ss_summary_E >> 22) & 0xff); 389 ob_flag = ((ss_summary_D >> 17) & 0x1); 390 peak_inx = (ss_summary_E & 0xfff); 391 if (peak_inx > 2047) 392 peak_inx = peak_inx - 4096; 393 peak_mag = ((ss_summary_E >> 12) & 0x3ff); 394 395 spectral_debug("agc_total_gain_segid1 = 0x%.2x, agc_mb_gain_segid1=%d", 396 agc_total_gain, agc_mb_gain); 397 spectral_debug("nb_mask_segid1 = 0x%.2x, ob_flag_segid1=%d, peak_index_segid1=%d, peak_mag_segid1=%d", 398 nb_mask, ob_flag, peak_inx, peak_mag); 399 } else { 400 if (tlvlen != 8) { 401 spectral_err("Unexpected TLV length %d for Spectral Summary Report! Hexdump follows", 402 tlvlen); 403 target_if_print_buf((uint8_t *)ptlv, tlvlen + 4); 404 return -EPERM; 405 } 406 407 /* Doing copy as the contents may not be aligned */ 408 qdf_mem_copy(&ss_summary_A, (uint8_t *)phdr, sizeof(int)); 409 qdf_mem_copy(&ss_summary_B, 410 (uint8_t *)((uint8_t *)phdr + sizeof(int)), 411 sizeof(int)); 412 413 nb_mask = ((ss_summary_B >> 22) & 0xff); 414 ob_flag = ((ss_summary_B >> 30) & 0x1); 415 peak_inx = (ss_summary_B & 0xfff); 416 417 if (peak_inx > 2047) 418 peak_inx = peak_inx - 4096; 419 420 peak_mag = ((ss_summary_B >> 12) & 0x3ff); 421 agc_mb_gain = ((ss_summary_A >> 24) & 0x7f); 422 agc_total_gain = (ss_summary_A & 0x3ff); 423 sscan_gidx = ((ss_summary_A >> 16) & 0xff); 424 recent_rfsat = ((ss_summary_B >> 31) & 0x1); 425 426 spectral_debug("nb_mask = 0x%.2x, ob_flag=%d, peak_index=%d, peak_mag=%d, agc_mb_gain=%d, agc_total_gain=%d, sscan_gidx=%d, recent_rfsat=%d", 427 nb_mask, ob_flag, peak_inx, peak_mag, 428 agc_mb_gain, agc_total_gain, sscan_gidx, 429 recent_rfsat); 430 } 431 432 return 0; 433 } 434 435 /** 436 * target_if_process_sfft_report_gen2() - Process Search FFT Report 437 * @ptlv: Pointer to Spectral Phyerr TLV 438 * @tlvlen: length 439 * @p_fft_info: Pointer to search fft info 440 * 441 * Dump Spectral Summary Report for gen2 442 * 443 * Return: Success/Failure 444 */ 445 static int 446 target_if_process_sfft_report_gen2( 447 struct spectral_phyerr_tlv_gen2 *ptlv, 448 int tlvlen, 449 struct spectral_search_fft_info_gen2 *p_fft_info) 450 { 451 /* 452 * For simplicity, everything is defined as uint32_t (except one). 453 * Proper code will later use the right sizes. 454 */ 455 /* 456 * For easy comparision between MDK team and OS team, the MDK script 457 * variable names have been used 458 */ 459 uint32_t relpwr_db; 460 uint32_t num_str_bins_ib; 461 uint32_t base_pwr; 462 uint32_t total_gain_info; 463 464 uint32_t fft_chn_idx; 465 int16_t peak_inx; 466 uint32_t avgpwr_db; 467 uint32_t peak_mag; 468 469 uint32_t fft_summary_A = 0; 470 uint32_t fft_summary_B = 0; 471 uint8_t *tmp = (uint8_t *)ptlv; 472 struct spectral_phyerr_hdr_gen2 *phdr = 473 (struct spectral_phyerr_hdr_gen2 *)( 474 tmp + 475 sizeof(struct spectral_phyerr_tlv_gen2)); 476 477 /* Relook this */ 478 if (tlvlen < 8) { 479 spectral_err("Unexpected TLV length %d for Spectral Summary Report! Hexdump follows", 480 tlvlen); 481 target_if_print_buf((uint8_t *)ptlv, tlvlen + 4); 482 return -EPERM; 483 } 484 485 /* Doing copy as the contents may not be aligned */ 486 qdf_mem_copy(&fft_summary_A, (uint8_t *)phdr, sizeof(int)); 487 qdf_mem_copy(&fft_summary_B, 488 (uint8_t *)((uint8_t *)phdr + sizeof(int)), 489 sizeof(int)); 490 491 relpwr_db = ((fft_summary_B >> 26) & 0x3f); 492 num_str_bins_ib = fft_summary_B & 0xff; 493 base_pwr = ((fft_summary_A >> 14) & 0x1ff); 494 total_gain_info = ((fft_summary_A >> 23) & 0x1ff); 495 496 fft_chn_idx = ((fft_summary_A >> 12) & 0x3); 497 peak_inx = fft_summary_A & 0xfff; 498 499 if (peak_inx > 2047) 500 peak_inx = peak_inx - 4096; 501 502 avgpwr_db = ((fft_summary_B >> 18) & 0xff); 503 peak_mag = ((fft_summary_B >> 8) & 0x3ff); 504 505 /* Populate the Search FFT Info */ 506 if (p_fft_info) { 507 p_fft_info->relpwr_db = relpwr_db; 508 p_fft_info->num_str_bins_ib = num_str_bins_ib; 509 p_fft_info->base_pwr = base_pwr; 510 p_fft_info->total_gain_info = total_gain_info; 511 p_fft_info->fft_chn_idx = fft_chn_idx; 512 p_fft_info->peak_inx = peak_inx; 513 p_fft_info->avgpwr_db = avgpwr_db; 514 p_fft_info->peak_mag = peak_mag; 515 } 516 517 return 0; 518 } 519 520 /** 521 * target_if_dump_adc_report_gen2() - Dump ADC Reports for gen2 522 * @ptlv: Pointer to Spectral Phyerr TLV 523 * @tlvlen: length 524 * 525 * Dump ADC Reports for gen2 526 * 527 * Return: Success/Failure 528 */ 529 static int 530 target_if_dump_adc_report_gen2( 531 struct spectral_phyerr_tlv_gen2 *ptlv, int tlvlen) 532 { 533 int i; 534 uint32_t *pdata; 535 uint32_t data; 536 537 /* 538 * For simplicity, everything is defined as uint32_t (except one). 539 * Proper code will later use the right sizes. 540 */ 541 uint32_t samp_fmt; 542 uint32_t chn_idx; 543 uint32_t recent_rfsat; 544 uint32_t agc_mb_gain; 545 uint32_t agc_total_gain; 546 547 uint32_t adc_summary = 0; 548 549 uint8_t *ptmp = (uint8_t *)ptlv; 550 551 spectral_debug("SPECTRAL : ADC REPORT"); 552 553 /* Relook this */ 554 if (tlvlen < 4) { 555 spectral_err("Unexpected TLV length %d for ADC Report! Hexdump follows", 556 tlvlen); 557 target_if_print_buf((uint8_t *)ptlv, tlvlen + 4); 558 return -EPERM; 559 } 560 561 qdf_mem_copy(&adc_summary, (uint8_t *)(ptlv + 4), sizeof(int)); 562 563 samp_fmt = ((adc_summary >> 28) & 0x1); 564 chn_idx = ((adc_summary >> 24) & 0x3); 565 recent_rfsat = ((adc_summary >> 23) & 0x1); 566 agc_mb_gain = ((adc_summary >> 16) & 0x7f); 567 agc_total_gain = adc_summary & 0x3ff; 568 569 spectral_debug("samp_fmt= %u, chn_idx= %u, recent_rfsat= %u, agc_mb_gain=%u agc_total_gain=%u", 570 samp_fmt, chn_idx, recent_rfsat, agc_mb_gain, 571 agc_total_gain); 572 573 for (i = 0; i < (tlvlen / 4); i++) { 574 pdata = (uint32_t *)(ptmp + 4 + i * 4); 575 data = *pdata; 576 577 /* Interpreting capture format 1 */ 578 if (1) { 579 uint8_t i1; 580 uint8_t q1; 581 uint8_t i2; 582 uint8_t q2; 583 int8_t si1; 584 int8_t sq1; 585 int8_t si2; 586 int8_t sq2; 587 588 i1 = data & 0xff; 589 q1 = (data >> 8) & 0xff; 590 i2 = (data >> 16) & 0xff; 591 q2 = (data >> 24) & 0xff; 592 593 if (i1 > 127) 594 si1 = i1 - 256; 595 else 596 si1 = i1; 597 598 if (q1 > 127) 599 sq1 = q1 - 256; 600 else 601 sq1 = q1; 602 603 if (i2 > 127) 604 si2 = i2 - 256; 605 else 606 si2 = i2; 607 608 if (q2 > 127) 609 sq2 = q2 - 256; 610 else 611 sq2 = q2; 612 613 spectral_debug("SPECTRAL ADC : Interpreting capture format 1"); 614 spectral_debug("adc_data_format_1 # %d %d %d", 615 2 * i, si1, sq1); 616 spectral_debug("adc_data_format_1 # %d %d %d", 617 2 * i + 1, si2, sq2); 618 } 619 620 /* Interpreting capture format 0 */ 621 if (1) { 622 uint16_t i1; 623 uint16_t q1; 624 int16_t si1; 625 int16_t sq1; 626 627 i1 = data & 0xffff; 628 q1 = (data >> 16) & 0xffff; 629 if (i1 > 32767) 630 si1 = i1 - 65536; 631 else 632 si1 = i1; 633 634 if (q1 > 32767) 635 sq1 = q1 - 65536; 636 else 637 sq1 = q1; 638 spectral_debug("SPECTRAL ADC : Interpreting capture format 0"); 639 spectral_debug("adc_data_format_2 # %d %d %d", 640 i, si1, sq1); 641 } 642 } 643 644 spectral_debug("\n"); 645 646 return 0; 647 } 648 649 /** 650 * target_if_dump_sfft_report_gen2() - Process Search FFT Report for gen2 651 * @ptlv: Pointer to Spectral Phyerr TLV 652 * @tlvlen: length 653 * @is_160_format: Indicates 160 format 654 * 655 * Process Search FFT Report for gen2 656 * 657 * Return: Success/Failure 658 */ 659 static int 660 target_if_dump_sfft_report_gen2(struct spectral_phyerr_tlv_gen2 *ptlv, 661 int tlvlen, bool is_160_format) 662 { 663 int i; 664 uint32_t fft_mag; 665 666 /* 667 * For simplicity, everything is defined as uint32_t (except one). 668 * Proper code will later use the right sizes. 669 */ 670 /* 671 * For easy comparision between MDK team and OS team, the MDK script 672 * variable names have been used 673 */ 674 uint32_t relpwr_db; 675 uint32_t num_str_bins_ib; 676 uint32_t base_pwr; 677 uint32_t total_gain_info; 678 679 uint32_t fft_chn_idx; 680 int16_t peak_inx; 681 uint32_t avgpwr_db; 682 uint32_t peak_mag; 683 uint8_t segid; 684 685 uint32_t fft_summary_A = 0; 686 uint32_t fft_summary_B = 0; 687 uint32_t fft_summary_C = 0; 688 uint8_t *tmp = (uint8_t *)ptlv; 689 struct spectral_phyerr_hdr_gen2 *phdr = 690 (struct spectral_phyerr_hdr_gen2 *)( 691 tmp + 692 sizeof(struct spectral_phyerr_tlv_gen2)); 693 uint32_t segid_skiplen = 0; 694 695 if (is_160_format) 696 segid_skiplen = sizeof(SPECTRAL_SEGID_INFO); 697 698 spectral_debug("SPECTRAL : SEARCH FFT REPORT"); 699 700 /* Relook this */ 701 if (tlvlen < (8 + segid_skiplen)) { 702 spectral_err("Unexpected TLV length %d for Spectral Summary Report! Hexdump follows", 703 tlvlen); 704 target_if_print_buf((uint8_t *)ptlv, tlvlen + 4); 705 return -EPERM; 706 } 707 708 /* Doing copy as the contents may not be aligned */ 709 qdf_mem_copy(&fft_summary_A, (uint8_t *)phdr, sizeof(int)); 710 qdf_mem_copy(&fft_summary_B, 711 (uint8_t *)((uint8_t *)phdr + sizeof(int)), 712 sizeof(int)); 713 if (is_160_format) 714 qdf_mem_copy(&fft_summary_C, 715 (uint8_t *)((uint8_t *)phdr + 2 * sizeof(int)), 716 sizeof(int)); 717 718 relpwr_db = ((fft_summary_B >> 26) & 0x3f); 719 num_str_bins_ib = fft_summary_B & 0xff; 720 base_pwr = ((fft_summary_A >> 14) & 0x1ff); 721 total_gain_info = ((fft_summary_A >> 23) & 0x1ff); 722 723 fft_chn_idx = ((fft_summary_A >> 12) & 0x3); 724 peak_inx = fft_summary_A & 0xfff; 725 726 if (peak_inx > 2047) 727 peak_inx = peak_inx - 4096; 728 729 avgpwr_db = ((fft_summary_B >> 18) & 0xff); 730 peak_mag = ((fft_summary_B >> 8) & 0x3ff); 731 732 spectral_debug("Header A = 0x%x Header B = 0x%x", 733 phdr->hdr_a, phdr->hdr_b); 734 spectral_debug("Base Power= 0x%x, Total Gain= %d, relpwr_db=%d, num_str_bins_ib=%d fft_chn_idx=%d peak_inx=%d avgpwr_db=%d peak_mag=%d", 735 base_pwr, total_gain_info, relpwr_db, num_str_bins_ib, 736 fft_chn_idx, peak_inx, avgpwr_db, peak_mag); 737 if (is_160_format) { 738 segid = fft_summary_C & 0x1; 739 spectral_debug("Segment ID: %hhu", segid); 740 } 741 742 spectral_debug("FFT bins:"); 743 for (i = 0; i < (tlvlen - 8 - segid_skiplen); i++) { 744 fft_mag = ((uint8_t *)ptlv)[12 + segid_skiplen + i]; 745 spectral_debug("%d %d, ", i, fft_mag); 746 } 747 748 spectral_debug("\n"); 749 750 return 0; 751 } 752 753 #ifdef SPECTRAL_DEBUG_SAMP_MSG 754 /** 755 * target_if_spectral_log_SAMP_param() - Log SAMP parameters 756 * @params: Reference to target_if_samp_msg_params 757 * 758 * API to log spectral SAMP message parameters 759 * 760 * Return: None 761 */ 762 static void 763 target_if_spectral_log_SAMP_param(struct target_if_samp_msg_params *params) 764 { 765 target_if_dbg_print_samp_param(params); 766 } 767 768 #else 769 static void 770 target_if_spectral_log_SAMP_param(struct target_if_samp_msg_params *params) 771 { 772 } 773 #endif 774 775 int 776 target_if_process_phyerr_gen2(struct target_if_spectral *spectral, 777 uint8_t *data, 778 uint32_t datalen, 779 struct target_if_spectral_rfqual_info *p_rfqual, 780 struct target_if_spectral_chan_info *p_chaninfo, 781 uint64_t tsf64, 782 struct target_if_spectral_acs_stats *acs_stats) 783 { 784 /* 785 * XXX : The classifier do not use all the members of the SAMP 786 * message data format. 787 * The classifier only depends upon the following parameters 788 * 789 * 1. Frequency (freq, msg->freq) 790 * 2. Spectral RSSI (spectral_rssi, 791 * msg->samp_data.spectral_rssi) 792 * 3. Bin Power Count (bin_pwr_count, 793 * msg->samp_data.bin_pwr_count) 794 * 4. Bin Power values (bin_pwr, msg->samp_data.bin_pwr[0] 795 * 5. Spectral Timestamp (spectral_tstamp, 796 * msg->samp_data.spectral_tstamp) 797 * 6. MAC Address (macaddr, msg->macaddr) 798 * 799 * This function prepares the params structure and populates it 800 * with 801 * relevant values, this is in turn passed to 802 * spectral_create_samp_msg() 803 * to prepare fully formatted Spectral SAMP message 804 * 805 * XXX : Need to verify 806 * 1. Order of FFT bin values 807 * 808 */ 809 810 struct target_if_samp_msg_params params; 811 struct spectral_search_fft_info_gen2 search_fft_info; 812 struct spectral_search_fft_info_gen2 *p_sfft = &search_fft_info; 813 struct spectral_search_fft_info_gen2 search_fft_info_sec80; 814 struct spectral_search_fft_info_gen2 *p_sfft_sec80 = 815 &search_fft_info_sec80; 816 uint32_t segid_skiplen = 0; 817 818 int8_t rssi_up = 0; 819 int8_t rssi_low = 0; 820 821 int8_t chn_idx_highest_enabled = 0; 822 int8_t chn_idx_lowest_enabled = 0; 823 824 uint8_t control_rssi = 0; 825 uint8_t extension_rssi = 0; 826 uint8_t combined_rssi = 0; 827 828 uint32_t tstamp = 0; 829 830 struct target_if_spectral_ops *p_sops = 831 GET_TARGET_IF_SPECTRAL_OPS(spectral); 832 833 struct spectral_phyerr_tlv_gen2 *ptlv = 834 (struct spectral_phyerr_tlv_gen2 *)data; 835 struct spectral_phyerr_tlv_gen2 *ptlv_sec80 = NULL; 836 struct spectral_phyerr_fft_gen2 *pfft = NULL; 837 struct spectral_phyerr_fft_gen2 *pfft_sec80 = NULL; 838 839 uint8_t segid = 0; 840 uint8_t segid_sec80 = 0; 841 enum phy_ch_width ch_width = 842 spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL]; 843 844 if (spectral->is_160_format) 845 segid_skiplen = sizeof(SPECTRAL_SEGID_INFO); 846 847 pfft = (struct spectral_phyerr_fft_gen2 *)( 848 data + 849 sizeof(struct spectral_phyerr_tlv_gen2) + 850 sizeof(struct spectral_phyerr_hdr_gen2) + 851 segid_skiplen); 852 853 /* 854 * XXX Extend SPECTRAL_DPRINTK() to use spectral_debug_level, 855 * and use this facility inside spectral_dump_phyerr_data() 856 * and supporting functions. 857 */ 858 if (spectral_debug_level & DEBUG_SPECTRAL2) 859 target_if_spectral_dump_phyerr_data_gen2( 860 data, datalen, 861 spectral->is_160_format); 862 863 if (spectral_debug_level & DEBUG_SPECTRAL4) { 864 target_if_spectral_dump_phyerr_data_gen2( 865 data, datalen, 866 spectral->is_160_format); 867 spectral_debug_level = DEBUG_SPECTRAL; 868 } 869 870 if (ptlv->signature != SPECTRAL_PHYERR_SIGNATURE_GEN2) { 871 /* 872 * EV# 118023: We tentatively disable the below print 873 * and provide stats instead. 874 */ 875 spectral->diag_stats.spectral_mismatch++; 876 return -EPERM; 877 } 878 879 OS_MEMZERO(¶ms, sizeof(params)); 880 /* Gen 2 only supports normal Spectral scan currently */ 881 params.smode = SPECTRAL_SCAN_MODE_NORMAL; 882 883 if (ptlv->tag == TLV_TAG_SEARCH_FFT_REPORT_GEN2) { 884 if (spectral->is_160_format) { 885 segid = *((SPECTRAL_SEGID_INFO *)( 886 (uint8_t *)ptlv + 887 sizeof(struct spectral_phyerr_tlv_gen2) + 888 sizeof(struct spectral_phyerr_hdr_gen2))); 889 890 if (segid != 0) { 891 struct spectral_diag_stats *p_diag_stats = 892 &spectral->diag_stats; 893 p_diag_stats->spectral_vhtseg1id_mismatch++; 894 return -EPERM; 895 } 896 } 897 898 target_if_process_sfft_report_gen2(ptlv, ptlv->length, 899 &search_fft_info); 900 901 tstamp = p_sops->get_tsf64(spectral) & SPECTRAL_TSMASK; 902 903 combined_rssi = p_rfqual->rssi_comb; 904 905 if (spectral->upper_is_control) 906 rssi_up = control_rssi; 907 else 908 rssi_up = extension_rssi; 909 910 if (spectral->lower_is_control) 911 rssi_low = control_rssi; 912 else 913 rssi_low = extension_rssi; 914 915 params.rssi = p_rfqual->rssi_comb; 916 params.lower_rssi = rssi_low; 917 params.upper_rssi = rssi_up; 918 919 if (spectral->sc_spectral_noise_pwr_cal) { 920 params.chain_ctl_rssi[0] = 921 p_rfqual->pc_rssi_info[0].rssi_pri20; 922 params.chain_ctl_rssi[1] = 923 p_rfqual->pc_rssi_info[1].rssi_pri20; 924 params.chain_ctl_rssi[2] = 925 p_rfqual->pc_rssi_info[2].rssi_pri20; 926 params.chain_ext_rssi[0] = 927 p_rfqual->pc_rssi_info[0].rssi_sec20; 928 params.chain_ext_rssi[1] = 929 p_rfqual->pc_rssi_info[1].rssi_sec20; 930 params.chain_ext_rssi[2] = 931 p_rfqual->pc_rssi_info[2].rssi_sec20; 932 } 933 934 /* 935 * XXX : This actually depends on the programmed chain mask 936 * This value decides the per-chain enable mask to select 937 * the input ADC for search FTT. 938 * For modes upto VHT80, if more than one chain is 939 * enabled, the max valid chain 940 * is used. LSB corresponds to chain zero. 941 * For VHT80_80 and VHT160, the lowest enabled chain is 942 * used for primary 943 * detection and highest enabled chain is used for 944 * secondary detection. 945 * 946 * XXX : The current algorithm do not use these control and 947 * extension channel 948 * Instead, it just relies on the combined RSSI values 949 * only. 950 * For fool-proof detection algorithm, we should take 951 * these RSSI values in to account. 952 * This is marked for future enhancements. 953 */ 954 chn_idx_highest_enabled = 955 ((spectral->params[params.smode].ss_chn_mask & 0x8) ? 3 : 956 (spectral->params[params.smode].ss_chn_mask & 0x4) ? 2 : 957 (spectral->params[params.smode].ss_chn_mask & 0x2) ? 1 : 0); 958 chn_idx_lowest_enabled = 959 ((spectral->params[params.smode].ss_chn_mask & 0x1) ? 0 : 960 (spectral->params[params.smode].ss_chn_mask & 0x2) ? 1 : 961 (spectral->params[params.smode].ss_chn_mask & 0x4) ? 2 : 3); 962 control_rssi = (uint8_t) 963 p_rfqual->pc_rssi_info[chn_idx_highest_enabled].rssi_pri20; 964 extension_rssi = (uint8_t) 965 p_rfqual->pc_rssi_info[chn_idx_highest_enabled].rssi_sec20; 966 967 params.bwinfo = 0; 968 params.tstamp = 0; 969 params.max_mag = p_sfft->peak_mag; 970 971 params.max_index = p_sfft->peak_inx; 972 params.max_exp = 0; 973 params.peak = 0; 974 params.bin_pwr_data = (uint8_t *)pfft; 975 params.freq = p_sops->get_current_channel(spectral, 976 params.smode); 977 params.freq_loading = 0; 978 979 params.interf_list.count = 0; 980 params.max_lower_index = 0; 981 params.max_upper_index = 0; 982 params.nb_lower = 0; 983 params.nb_upper = 0; 984 /* 985 * For modes upto VHT80, the noise floor is populated with the 986 * one corresponding 987 * to the highest enabled antenna chain 988 */ 989 params.noise_floor = 990 p_rfqual->noise_floor[chn_idx_highest_enabled]; 991 params.datalen = ptlv->length; 992 params.pwr_count = ptlv->length - 993 sizeof(struct spectral_phyerr_hdr_gen2) - segid_skiplen; 994 params.tstamp = (tsf64 & SPECTRAL_TSMASK); 995 996 acs_stats->ctrl_nf = params.noise_floor; 997 acs_stats->ext_nf = params.noise_floor; 998 acs_stats->nfc_ctl_rssi = control_rssi; 999 acs_stats->nfc_ext_rssi = extension_rssi; 1000 1001 if (spectral->is_160_format && 1002 is_ch_width_160_or_80p80(ch_width)) { 1003 /* 1004 * We expect to see one more Search FFT report, and it 1005 * should be equal in size to the current one. 1006 */ 1007 if (datalen < ( 1008 2 * ( 1009 sizeof(struct spectral_phyerr_tlv_gen2) + 1010 ptlv->length))) { 1011 struct spectral_diag_stats *p_diag_stats = 1012 &spectral->diag_stats; 1013 p_diag_stats->spectral_sec80_sfft_insufflen++; 1014 return -EPERM; 1015 } 1016 1017 ptlv_sec80 = (struct spectral_phyerr_tlv_gen2 *)( 1018 data + 1019 sizeof(struct spectral_phyerr_tlv_gen2) + 1020 ptlv->length); 1021 1022 if (ptlv_sec80->signature != 1023 SPECTRAL_PHYERR_SIGNATURE_GEN2) { 1024 spectral->diag_stats.spectral_mismatch++; 1025 return -EPERM; 1026 } 1027 1028 if (ptlv_sec80->tag != TLV_TAG_SEARCH_FFT_REPORT_GEN2) { 1029 spectral->diag_stats.spectral_no_sec80_sfft++; 1030 return -EPERM; 1031 } 1032 1033 segid_sec80 = *((SPECTRAL_SEGID_INFO *)( 1034 (uint8_t *)ptlv_sec80 + 1035 sizeof(struct spectral_phyerr_tlv_gen2) + 1036 sizeof(struct spectral_phyerr_hdr_gen2))); 1037 1038 if (segid_sec80 != 1) { 1039 struct spectral_diag_stats *p_diag_stats = 1040 &spectral->diag_stats; 1041 p_diag_stats->spectral_vhtseg2id_mismatch++; 1042 return -EPERM; 1043 } 1044 1045 params.vhtop_ch_freq_seg1 = p_chaninfo->center_freq1; 1046 params.vhtop_ch_freq_seg2 = p_chaninfo->center_freq2; 1047 1048 target_if_process_sfft_report_gen2( 1049 ptlv_sec80, 1050 ptlv_sec80->length, 1051 &search_fft_info_sec80); 1052 1053 pfft_sec80 = (struct spectral_phyerr_fft_gen2 *)( 1054 ((uint8_t *)ptlv_sec80) + 1055 sizeof(struct spectral_phyerr_tlv_gen2) + 1056 sizeof(struct spectral_phyerr_hdr_gen2) + 1057 segid_skiplen); 1058 1059 /* XXX: Confirm. TBD at SoD. */ 1060 params.rssi_sec80 = p_rfqual->rssi_comb; 1061 if (spectral->is_sec80_rssi_war_required) 1062 params.rssi_sec80 = 1063 target_if_get_combrssi_sec80_seg_gen2 1064 (spectral, &search_fft_info_sec80); 1065 /* XXX: Determine dynamically. TBD at SoD. */ 1066 /* 1067 * For VHT80_80/VHT160, the noise floor for primary 1068 * 80MHz segment is populated with the 1069 * lowest enabled antenna chain and the noise floor for 1070 * secondary 80MHz segment is populated 1071 * with the highest enabled antenna chain 1072 */ 1073 params.noise_floor_sec80 = 1074 p_rfqual->noise_floor[chn_idx_highest_enabled]; 1075 params.noise_floor = 1076 p_rfqual->noise_floor[chn_idx_lowest_enabled]; 1077 1078 params.max_mag_sec80 = p_sfft_sec80->peak_mag; 1079 params.max_index_sec80 = p_sfft_sec80->peak_inx; 1080 /* XXX Does this definition of datalen *still hold? */ 1081 params.datalen_sec80 = ptlv_sec80->length; 1082 params.pwr_count_sec80 = 1083 ptlv_sec80->length - 1084 sizeof(struct spectral_phyerr_hdr_gen2) - 1085 segid_skiplen; 1086 params.bin_pwr_data_sec80 = (uint8_t *)pfft_sec80; 1087 } 1088 qdf_mem_copy(¶ms.classifier_params, 1089 &spectral->classifier_params, 1090 sizeof(struct spectral_classifier_params)); 1091 1092 target_if_spectral_log_SAMP_param(¶ms); 1093 target_if_spectral_create_samp_msg(spectral, ¶ms); 1094 } 1095 1096 return 0; 1097 } 1098 1099 int 1100 target_if_spectral_dump_hdr_gen2(struct spectral_phyerr_hdr_gen2 *phdr) 1101 { 1102 uint32_t a = 0; 1103 uint32_t b = 0; 1104 1105 qdf_mem_copy(&a, (uint8_t *)phdr, sizeof(int)); 1106 qdf_mem_copy(&b, 1107 (uint8_t *)((uint8_t *)phdr + sizeof(int)), 1108 sizeof(int)); 1109 1110 spectral_debug("SPECTRAL : HEADER A 0x%x (%d)", a, a); 1111 spectral_debug("SPECTRAL : HEADER B 0x%x (%d)", b, b); 1112 return 0; 1113 } 1114 1115 int8_t 1116 target_if_get_combrssi_sec80_seg_gen2( 1117 struct target_if_spectral *spectral, 1118 struct spectral_search_fft_info_gen2 *p_sfft_sec80) 1119 { 1120 uint32_t avgpwr_db = 0; 1121 uint32_t total_gain_db = 0; 1122 uint32_t offset = 0; 1123 int8_t comb_rssi = 0; 1124 1125 /* Obtain required parameters for algorithm from search FFT report */ 1126 avgpwr_db = p_sfft_sec80->avgpwr_db; 1127 total_gain_db = p_sfft_sec80->total_gain_info; 1128 1129 /* Calculate offset */ 1130 offset = target_if_get_offset_swar_sec80( 1131 spectral->ch_width[SPECTRAL_SCAN_MODE_NORMAL]); 1132 1133 /* Calculate RSSI */ 1134 comb_rssi = ((avgpwr_db - total_gain_db) + offset); 1135 1136 return comb_rssi; 1137 } 1138 1139 int 1140 target_if_spectral_dump_tlv_gen2( 1141 struct spectral_phyerr_tlv_gen2 *ptlv, bool is_160_format) 1142 { 1143 int ret = 0; 1144 1145 /* 1146 * TODO : Do not delete the following print 1147 * The scripts used to validate Spectral depend on this Print 1148 */ 1149 spectral_debug("SPECTRAL : TLV Length is 0x%x (%d)", 1150 ptlv->length, ptlv->length); 1151 1152 switch (ptlv->tag) { 1153 case TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN2: 1154 ret = 1155 target_if_dump_summary_report_gen2( 1156 ptlv, ptlv->length, is_160_format); 1157 break; 1158 1159 case TLV_TAG_SEARCH_FFT_REPORT_GEN2: 1160 ret = 1161 target_if_dump_sfft_report_gen2(ptlv, ptlv->length, 1162 is_160_format); 1163 break; 1164 1165 case TLV_TAG_ADC_REPORT_GEN2: 1166 ret = target_if_dump_adc_report_gen2(ptlv, ptlv->length); 1167 break; 1168 1169 default: 1170 spectral_warn("INVALID TLV"); 1171 ret = -1; 1172 break; 1173 } 1174 1175 return ret; 1176 } 1177 1178 int 1179 target_if_spectral_dump_phyerr_data_gen2(uint8_t *data, uint32_t datalen, 1180 bool is_160_format) 1181 { 1182 struct spectral_phyerr_tlv_gen2 *ptlv = NULL; 1183 uint32_t bytes_processed = 0; 1184 uint32_t bytes_remaining = datalen; 1185 uint32_t curr_tlv_complete_size = 0; 1186 1187 if (datalen < sizeof(struct spectral_phyerr_tlv_gen2)) { 1188 spectral_err("Total PHY error data length %u too short to contain any TLVs", 1189 datalen); 1190 return -EPERM; 1191 } 1192 1193 while (bytes_processed < datalen) { 1194 if (bytes_remaining < sizeof(struct spectral_phyerr_tlv_gen2)) { 1195 spectral_err("Remaining PHY error data length %u too short to contain a TLV", 1196 bytes_remaining); 1197 return -EPERM; 1198 } 1199 1200 ptlv = (struct spectral_phyerr_tlv_gen2 *)(data + 1201 bytes_processed); 1202 1203 if (ptlv->signature != SPECTRAL_PHYERR_SIGNATURE_GEN2) { 1204 spectral_err("Invalid signature 0x%x!", 1205 ptlv->signature); 1206 return -EPERM; 1207 } 1208 1209 curr_tlv_complete_size = 1210 sizeof(struct spectral_phyerr_tlv_gen2) + 1211 ptlv->length; 1212 1213 if (curr_tlv_complete_size > bytes_remaining) { 1214 spectral_err("TLV size %d greater than number of bytes remaining %d", 1215 curr_tlv_complete_size, bytes_remaining); 1216 return -EPERM; 1217 } 1218 1219 if (target_if_spectral_dump_tlv_gen2(ptlv, is_160_format) == -1) 1220 return -EPERM; 1221 1222 bytes_processed += curr_tlv_complete_size; 1223 bytes_remaining = datalen - bytes_processed; 1224 } 1225 1226 return 0; 1227 } 1228 1229 #ifdef DIRECT_BUF_RX_ENABLE 1230 /** 1231 * target_if_get_spectral_mode() - Get Spectral scan mode corresponding to a 1232 * detector id 1233 * @detector_id: detector id in the Spectral report 1234 * @rparams: pointer to report params object 1235 * 1236 * Helper API to get Spectral scan mode from the detector ID. This mapping is 1237 * target specific. 1238 * 1239 * Return: Spectral scan mode 1240 */ 1241 static enum spectral_scan_mode 1242 target_if_get_spectral_mode(enum spectral_detector_id detector_id, 1243 struct spectral_report_params *rparams) 1244 { 1245 if (detector_id >= SPECTRAL_DETECTOR_ID_MAX) { 1246 spectral_err_rl("Invalid detector id %d", detector_id); 1247 return SPECTRAL_SCAN_MODE_INVALID; 1248 } 1249 1250 return rparams->detid_mode_table[detector_id]; 1251 } 1252 1253 /** 1254 * target_if_spectral_get_bin_count_after_len_adj() - Get number of FFT bins in 1255 * Spectral FFT report 1256 * @fft_bin_len: FFT bin length reported by target 1257 * @rpt_mode: Spectral report mode 1258 * @swar: Spectral FFT bin length adjustments SWAR parameters 1259 * @fft_bin_size: Size of one FFT bin in bytes 1260 * 1261 * Get actual number of FFT bins in the FFT report after adjusting the length 1262 * by applying the SWARs for getting correct length. 1263 * 1264 * Return: FFT bin count 1265 */ 1266 static size_t 1267 target_if_spectral_get_bin_count_after_len_adj( 1268 size_t fft_bin_len, uint8_t rpt_mode, 1269 struct spectral_fft_bin_len_adj_swar *swar, 1270 size_t *fft_bin_size) 1271 { 1272 size_t fft_bin_count = fft_bin_len; 1273 1274 if (rpt_mode == 1 && swar->null_fftbin_adj) { 1275 /* 1276 * No FFT bins are expected. Explicitly set FFT bin 1277 * count to 0. 1278 */ 1279 fft_bin_count = 0; 1280 *fft_bin_size = 0; 1281 } else { 1282 /* 1283 * Divide fft bin length by appropriate factor depending 1284 * on the value of fftbin_size_war. 1285 */ 1286 switch (swar->fftbin_size_war) { 1287 case SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE: 1288 fft_bin_count >>= 2; 1289 *fft_bin_size = 4; 1290 break; 1291 case SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE: 1292 fft_bin_count >>= 1; 1293 *fft_bin_size = 2; 1294 /* Ideally we should be dividing fft bin length 1295 * by 2. Due to a HW bug, actual length is two 1296 * times the expected length. 1297 */ 1298 if (swar->packmode_fftbin_size_adj) 1299 fft_bin_count >>= 1; 1300 break; 1301 case SPECTRAL_FFTBIN_SIZE_NO_WAR: 1302 *fft_bin_size = 1; 1303 /* No length adjustment */ 1304 break; 1305 default: 1306 qdf_assert_always(0); 1307 } 1308 1309 if (rpt_mode == 2 && swar->inband_fftbin_size_adj) 1310 fft_bin_count >>= 1; 1311 } 1312 1313 return fft_bin_count; 1314 } 1315 1316 /** 1317 * target_if_process_sfft_report_gen3() - Process Search FFT Report for gen3 1318 * @p_fft_report: Pointer to fft report 1319 * @p_sfft: Pointer to search fft report 1320 * 1321 * Process Search FFT Report for gen3 1322 * 1323 * Return: Success/Failure 1324 */ 1325 static int 1326 target_if_process_sfft_report_gen3( 1327 struct spectral_phyerr_fft_report_gen3 *p_fft_report, 1328 struct spectral_search_fft_info_gen3 *p_sfft) 1329 { 1330 /* 1331 * For simplicity, everything is defined as uint32_t (except one). 1332 * Proper code will later use the right sizes. 1333 */ 1334 /* 1335 * For easy comparision between MDK team and OS team, the MDK script 1336 * variable names have been used 1337 */ 1338 int32_t peak_sidx; 1339 int32_t peak_mag; 1340 1341 /* Populate the Search FFT Info */ 1342 if (p_sfft) { 1343 p_sfft->timestamp = p_fft_report->fft_timestamp; 1344 1345 p_sfft->fft_detector_id = get_bitfield(p_fft_report->hdr_a, 1346 2, 0); 1347 p_sfft->fft_num = get_bitfield(p_fft_report->hdr_a, 3, 2); 1348 p_sfft->fft_radar_check = get_bitfield(p_fft_report->hdr_a, 1349 12, 5); 1350 1351 peak_sidx = get_bitfield(p_fft_report->hdr_a, 11, 17); 1352 p_sfft->fft_peak_sidx = unsigned_to_signed(peak_sidx, 11); 1353 p_sfft->fft_chn_idx = get_bitfield(p_fft_report->hdr_a, 3, 28); 1354 1355 p_sfft->fft_base_pwr_db = get_bitfield(p_fft_report->hdr_b, 1356 9, 0); 1357 p_sfft->fft_total_gain_db = get_bitfield(p_fft_report->hdr_b, 1358 8, 9); 1359 1360 p_sfft->fft_num_str_bins_ib = get_bitfield(p_fft_report->hdr_c, 1361 8, 0); 1362 peak_mag = get_bitfield(p_fft_report->hdr_c, 10, 8); 1363 p_sfft->fft_peak_mag = unsigned_to_signed(peak_mag, 10); 1364 p_sfft->fft_avgpwr_db = get_bitfield(p_fft_report->hdr_c, 1365 7, 18); 1366 p_sfft->fft_relpwr_db = get_bitfield(p_fft_report->hdr_c, 1367 7, 25); 1368 } 1369 1370 return 0; 1371 } 1372 1373 /** 1374 * target_if_dump_fft_report_gen3() - Dump FFT Report for gen3 1375 * @spectral: Pointer to Spectral object 1376 * @smode: Spectral scan mode 1377 * @p_fft_report: Pointer to fft report 1378 * @p_sfft: Pointer to search fft report 1379 * 1380 * Dump FFT Report for gen3 1381 * 1382 * Return: void 1383 */ 1384 static void 1385 target_if_dump_fft_report_gen3(struct target_if_spectral *spectral, 1386 enum spectral_scan_mode smode, 1387 struct spectral_phyerr_fft_report_gen3 *p_fft_report, 1388 struct spectral_search_fft_info_gen3 *p_sfft) 1389 { 1390 size_t fft_hdr_length = (p_fft_report->fft_hdr_length * 4); 1391 size_t report_len = (fft_hdr_length + 8); 1392 size_t fft_bin_len; 1393 size_t fft_bin_count; 1394 size_t fft_bin_size; 1395 size_t fft_bin_len_inband_tfer = 0; 1396 uint8_t *fft_bin_buf = NULL; 1397 size_t fft_bin_buf_size; 1398 1399 fft_bin_len = fft_hdr_length - spectral->rparams.fft_report_hdr_len; 1400 fft_bin_count = target_if_spectral_get_bin_count_after_len_adj( 1401 fft_bin_len, 1402 spectral->params[smode].ss_rpt_mode, 1403 &spectral->len_adj_swar, &fft_bin_size); 1404 1405 if ((spectral->params[smode].ss_rpt_mode == 2) && 1406 spectral->len_adj_swar.inband_fftbin_size_adj) 1407 fft_bin_len_inband_tfer = fft_bin_len >> 1; 1408 1409 spectral_debug("Spectral FFT Report"); 1410 spectral_debug("fft_timestamp = 0x%x", p_fft_report->fft_timestamp); 1411 spectral_debug("fft_hdr_length = %u(32 bit words)", 1412 p_fft_report->fft_hdr_length); 1413 spectral_debug("fft_hdr_tag = 0x%x", p_fft_report->fft_hdr_tag); 1414 spectral_debug("fft_hdr_sig = 0x%x", p_fft_report->fft_hdr_sig); 1415 1416 spectral_debug("Length field in search fft report is %zu(0x%zx) bytes", 1417 fft_hdr_length, fft_hdr_length); 1418 spectral_debug("Total length of search fft report is %zu(0x%zx) bytes", 1419 report_len, report_len); 1420 spectral_debug("Target reported fftbins in report is %zu(0x%zx)", 1421 fft_bin_len, fft_bin_len); 1422 1423 if ((spectral->params[smode].ss_rpt_mode == 1) && 1424 spectral->len_adj_swar.null_fftbin_adj) 1425 spectral_debug("WAR: Considering number of FFT bins as 0"); 1426 else if ((spectral->params[smode].ss_rpt_mode == 2) && 1427 spectral->len_adj_swar.inband_fftbin_size_adj) { 1428 spectral_debug("FW fftbins actually transferred (in-band report mode) %zu(0x%zx)", 1429 fft_bin_len_inband_tfer, 1430 fft_bin_len_inband_tfer); 1431 } 1432 1433 spectral_debug("Actual number of fftbins in report is %zu(0x%zx)", 1434 fft_bin_count, fft_bin_count); 1435 1436 spectral_debug("fft_detector_id = %u", p_sfft->fft_detector_id); 1437 spectral_debug("fft_num = %u", p_sfft->fft_num); 1438 spectral_debug("fft_radar_check = %u", p_sfft->fft_radar_check); 1439 spectral_debug("fft_peak_sidx = %d", p_sfft->fft_peak_sidx); 1440 spectral_debug("fft_chn_idx = %u", p_sfft->fft_chn_idx); 1441 spectral_debug("fft_base_pwr_db = %u", p_sfft->fft_base_pwr_db); 1442 spectral_debug("fft_total_gain_db = %u", p_sfft->fft_total_gain_db); 1443 spectral_debug("fft_num_str_bins_ib = %u", p_sfft->fft_num_str_bins_ib); 1444 spectral_debug("fft_peak_mag = %d", p_sfft->fft_peak_mag); 1445 spectral_debug("fft_avgpwr_db = %u", p_sfft->fft_avgpwr_db); 1446 spectral_debug("fft_relpwr_db = %u", p_sfft->fft_relpwr_db); 1447 1448 fft_bin_buf_size = fft_bin_count; 1449 1450 if (fft_bin_count > 0) { 1451 int idx; 1452 1453 spectral_debug("FFT bins:"); 1454 if (spectral->len_adj_swar.fftbin_size_war == 1455 SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE) { 1456 uint32_t *binptr_32 = (uint32_t *)&p_fft_report->buf; 1457 uint16_t *fft_bin_buf_16 = NULL; 1458 1459 /* Useful width of FFT bin is 10 bits, increasing it to 1460 * byte boundary makes it 2 bytes. Hence, buffer to be 1461 * allocated should be of size fft_bin_count 1462 * multiplied by 2. 1463 */ 1464 fft_bin_buf_size <<= 1; 1465 1466 fft_bin_buf_16 = (uint16_t *)qdf_mem_malloc( 1467 fft_bin_buf_size); 1468 if (!fft_bin_buf_16) { 1469 spectral_err("Failed to allocate memory"); 1470 return; 1471 } 1472 1473 for (idx = 0; idx < fft_bin_count; idx++) 1474 fft_bin_buf_16[idx] = 1475 *((uint16_t *)binptr_32++); 1476 1477 fft_bin_buf = (uint8_t *)fft_bin_buf_16; 1478 } else if (spectral->len_adj_swar.fftbin_size_war == 1479 SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE) { 1480 uint16_t *binptr_16 = (uint16_t *)&p_fft_report->buf; 1481 uint16_t *fft_bin_buf_16 = NULL; 1482 1483 /* Useful width of FFT bin is 10 bits, increasing it to 1484 * byte boundary makes it 2 bytes. Hence, buffer to be 1485 * allocated should be of size fft_bin_count 1486 * multiplied by 2. 1487 */ 1488 fft_bin_buf_size <<= 1; 1489 1490 fft_bin_buf_16 = (uint16_t *)qdf_mem_malloc( 1491 fft_bin_buf_size); 1492 if (!fft_bin_buf_16) { 1493 spectral_err("Failed to allocate memory"); 1494 return; 1495 } 1496 1497 for (idx = 0; idx < fft_bin_count; idx++) 1498 fft_bin_buf_16[idx] = *(binptr_16++); 1499 1500 fft_bin_buf = (uint8_t *)fft_bin_buf_16; 1501 } else { 1502 fft_bin_buf = (uint8_t *)&p_fft_report->buf; 1503 } 1504 1505 spectral_debug("FFT bin buffer size = %zu", fft_bin_buf_size); 1506 target_if_spectral_hexdump(fft_bin_buf, fft_bin_buf_size); 1507 if ((spectral->len_adj_swar.fftbin_size_war != 1508 SPECTRAL_FFTBIN_SIZE_NO_WAR) && fft_bin_buf) 1509 qdf_mem_free(fft_bin_buf); 1510 } 1511 } 1512 #endif 1513 1514 QDF_STATUS 1515 target_if_160mhz_delivery_state_change(struct target_if_spectral *spectral, 1516 enum spectral_scan_mode smode, 1517 uint8_t detector_id) { 1518 QDF_STATUS status = QDF_STATUS_SUCCESS; 1519 1520 if (smode >= SPECTRAL_SCAN_MODE_MAX) { 1521 spectral_err_rl("Invalid Spectral mode %d", smode); 1522 return QDF_STATUS_E_INVAL; 1523 } 1524 1525 if (!is_ch_width_160_or_80p80(spectral->ch_width[smode])) { 1526 spectral_err_rl("Scan BW %d is not 160/80p80 for mode %d", 1527 spectral->ch_width[smode], smode); 1528 return QDF_STATUS_E_FAILURE; 1529 } 1530 1531 switch (spectral->state_160mhz_delivery[smode]) { 1532 case SPECTRAL_REPORT_WAIT_PRIMARY80: 1533 if (detector_id == SPECTRAL_DETECTOR_ID_0) 1534 spectral->state_160mhz_delivery[smode] = 1535 SPECTRAL_REPORT_RX_PRIMARY80; 1536 else { 1537 status = QDF_STATUS_E_FAILURE; 1538 spectral->diag_stats.spectral_vhtseg1id_mismatch++; 1539 } 1540 break; 1541 1542 case SPECTRAL_REPORT_WAIT_SECONDARY80: 1543 if (detector_id == SPECTRAL_DETECTOR_ID_1) 1544 spectral->state_160mhz_delivery[smode] = 1545 SPECTRAL_REPORT_RX_SECONDARY80; 1546 else { 1547 spectral->state_160mhz_delivery[smode] = 1548 SPECTRAL_REPORT_WAIT_PRIMARY80; 1549 status = QDF_STATUS_E_FAILURE; 1550 spectral->diag_stats.spectral_vhtseg2id_mismatch++; 1551 } 1552 break; 1553 1554 case SPECTRAL_REPORT_RX_SECONDARY80: 1555 /* We don't care about detector id in this state. */ 1556 reset_160mhz_delivery_state_machine(spectral, smode); 1557 break; 1558 1559 case SPECTRAL_REPORT_RX_PRIMARY80: 1560 /* We don't care about detector id in this state */ 1561 spectral->state_160mhz_delivery[smode] = 1562 SPECTRAL_REPORT_WAIT_SECONDARY80; 1563 break; 1564 1565 default: 1566 break; 1567 } 1568 1569 return status; 1570 } 1571 1572 #ifdef DIRECT_BUF_RX_ENABLE 1573 /** 1574 * target_if_get_detector_id_sscan_summary_report_gen3() - Get Spectral detector 1575 * ID from Spectral summary report 1576 * @data: Pointer to Spectral summary report 1577 * 1578 * Return: Detector ID 1579 */ 1580 static uint8_t 1581 target_if_get_detector_id_sscan_summary_report_gen3(uint8_t *data) { 1582 struct spectral_sscan_summary_report_gen3 *psscan_summary_report; 1583 uint8_t detector_id; 1584 1585 qdf_assert_always(data); 1586 1587 psscan_summary_report = 1588 (struct spectral_sscan_summary_report_gen3 *)data; 1589 1590 detector_id = get_bitfield( 1591 psscan_summary_report->hdr_a, 1592 SSCAN_SUMMARY_REPORT_HDR_A_DETECTOR_ID_SIZE_GEN3, 1593 SSCAN_SUMMARY_REPORT_HDR_A_DETECTOR_ID_POS_GEN3); 1594 1595 return detector_id; 1596 } 1597 1598 /** 1599 * target_if_consume_sscan_summary_report_gen3() - Consume Spectral summary 1600 * report 1601 * @data: Pointer to Spectral summary report 1602 * @fields: Pointer to structure to be populated with extracted fields 1603 * @rparams: Pointer to structure with Spectral report params 1604 * 1605 * Consume Spectral summary report for gen3 1606 * 1607 * Return: void 1608 */ 1609 static void 1610 target_if_consume_sscan_summary_report_gen3( 1611 uint8_t *data, 1612 struct sscan_report_fields_gen3 *fields, 1613 struct spectral_report_params *rparams) { 1614 struct spectral_sscan_summary_report_gen3 *psscan_summary_report; 1615 1616 qdf_assert_always(data); 1617 qdf_assert_always(fields); 1618 qdf_assert_always(rparams); 1619 1620 psscan_summary_report = 1621 (struct spectral_sscan_summary_report_gen3 *)data; 1622 1623 fields->sscan_agc_total_gain = get_bitfield( 1624 psscan_summary_report->hdr_a, 1625 SSCAN_SUMMARY_REPORT_HDR_A_AGC_TOTAL_GAIN_SIZE_GEN3, 1626 SSCAN_SUMMARY_REPORT_HDR_A_AGC_TOTAL_GAIN_POS_GEN3); 1627 fields->inband_pwr_db = get_bitfield( 1628 psscan_summary_report->hdr_a, 1629 SSCAN_SUMMARY_REPORT_HDR_A_INBAND_PWR_DB_SIZE_GEN3, 1630 SSCAN_SUMMARY_REPORT_HDR_A_INBAND_PWR_DB_POS_GEN3); 1631 fields->sscan_pri80 = get_bitfield( 1632 psscan_summary_report->hdr_a, 1633 SSCAN_SUMMARY_REPORT_HDR_A_PRI80_SIZE_GEN3, 1634 SSCAN_SUMMARY_REPORT_HDR_A_PRI80_POS_GEN3); 1635 1636 switch (rparams->version) { 1637 case SPECTRAL_REPORT_FORMAT_VERSION_1: 1638 fields->sscan_gainchange = get_bitfield( 1639 psscan_summary_report->hdr_b, 1640 SSCAN_SUMMARY_REPORT_HDR_B_GAINCHANGE_SIZE_GEN3_V1, 1641 SSCAN_SUMMARY_REPORT_HDR_B_GAINCHANGE_POS_GEN3_V1); 1642 break; 1643 case SPECTRAL_REPORT_FORMAT_VERSION_2: 1644 fields->sscan_gainchange = get_bitfield( 1645 psscan_summary_report->hdr_c, 1646 SSCAN_SUMMARY_REPORT_HDR_C_GAINCHANGE_SIZE_GEN3_V2, 1647 SSCAN_SUMMARY_REPORT_HDR_C_GAINCHANGE_POS_GEN3_V2); 1648 break; 1649 default: 1650 qdf_assert_always(0); 1651 } 1652 } 1653 1654 /** 1655 * target_if_verify_sig_and_tag_gen3() - Verify tag and signature 1656 * of spectral report 1657 * @spectral: Pointer to spectral object 1658 * @data: Pointer to spectral summary report 1659 * @exp_tag: iexpected tag value 1660 * 1661 * Process fft report for gen3 1662 * 1663 * Return: SUCCESS/FAILURE 1664 */ 1665 static int 1666 target_if_verify_sig_and_tag_gen3(struct target_if_spectral *spectral, 1667 uint8_t *data, uint8_t exp_tag) 1668 { 1669 uint8_t tag = 0; 1670 uint8_t signature = 0; 1671 1672 /* Peek into the data to figure out whether 1673 * 1) Signature matches the expected value 1674 * 2) What is inside the package (TAG ID is used for finding this) 1675 */ 1676 tag = *(data + PHYERR_HDR_TAG_POS); 1677 signature = *(data + PHYERR_HDR_SIG_POS); 1678 1679 if (signature != SPECTRAL_PHYERR_SIGNATURE_GEN3) { 1680 spectral->diag_stats.spectral_mismatch++; 1681 return -EINVAL; 1682 } 1683 1684 if (tag != exp_tag) { 1685 spectral->diag_stats.spectral_mismatch++; 1686 return -EINVAL; 1687 } 1688 1689 return 0; 1690 } 1691 1692 static uint8_t 1693 target_if_spectral_get_lowest_chn_idx(uint8_t chainmask) 1694 { 1695 uint8_t idx; 1696 1697 for (idx = 0; idx < DBR_MAX_CHAINS; idx++) { 1698 if (chainmask & 0x1) 1699 break; 1700 chainmask >>= 1; 1701 } 1702 return idx; 1703 } 1704 1705 #ifdef DIRECT_BUF_RX_DEBUG 1706 static void target_if_spectral_check_buffer_poisoning( 1707 struct target_if_spectral *spectral, 1708 struct spectral_report *report, 1709 int num_fft_bins, enum spectral_scan_mode smode) 1710 { 1711 uint32_t *data; 1712 size_t len; 1713 size_t words_to_check = 1714 sizeof(struct spectral_sscan_summary_report_gen3) >> 2; 1715 bool poisoned_words_found = false; 1716 1717 if (!spectral) { 1718 spectral_err_rl("Spectral LMAC object is null"); 1719 return; 1720 } 1721 1722 if (!spectral->dbr_buff_debug) 1723 return; 1724 1725 if (!report) { 1726 spectral_err_rl("Spectral report is null"); 1727 return; 1728 } 1729 1730 /* Add search FFT report */ 1731 if (spectral->params[smode].ss_rpt_mode > 0) 1732 words_to_check += 1733 sizeof(struct spectral_phyerr_fft_report_gen3) >> 2; 1734 1735 /* Now add the number of FFT bins */ 1736 if (spectral->params[smode].ss_rpt_mode > 1) { 1737 /* Caller should take care to pass correct number of FFT bins */ 1738 if (spectral->len_adj_swar.fftbin_size_war == 1739 SPECTRAL_FFTBIN_SIZE_WAR_4BYTE_TO_1BYTE) 1740 words_to_check += num_fft_bins; 1741 else if (spectral->len_adj_swar.fftbin_size_war == 1742 SPECTRAL_FFTBIN_SIZE_WAR_2BYTE_TO_1BYTE) 1743 words_to_check += (num_fft_bins >> 1); 1744 } 1745 1746 data = (uint32_t *)report->data; 1747 for (len = 0; len < words_to_check; ++len) { 1748 if (*data == MEM_POISON_SIGNATURE) { 1749 spectral_err("Pattern(%x) found in Spectral search FFT report at position %zu in the buffer %pK", 1750 MEM_POISON_SIGNATURE, 1751 (len << 2), report->data); 1752 poisoned_words_found = true; 1753 break; 1754 } 1755 ++data; 1756 } 1757 1758 /* Crash the FW even if one word is poisoned */ 1759 if (poisoned_words_found) { 1760 spectral_err("Pattern(%x) found in Spectral report, Hex dump of the sfft follows", 1761 MEM_POISON_SIGNATURE); 1762 target_if_spectral_hexdump((unsigned char *)report->data, 1763 words_to_check << 2); 1764 spectral_err("Asserting the FW"); 1765 target_if_spectral_fw_hang(spectral); 1766 } 1767 } 1768 1769 static void target_if_spectral_verify_ts(struct target_if_spectral *spectral, 1770 uint8_t *buf, uint32_t current_ts) 1771 { 1772 if (!spectral) { 1773 spectral_err_rl("Spectral LMAC object is null"); 1774 return; 1775 } 1776 1777 if (!spectral->dbr_buff_debug) 1778 return; 1779 1780 if (spectral->prev_tstamp) { 1781 if (current_ts == spectral->prev_tstamp) { 1782 spectral_err("Spectral timestamp(%u) in the current buffer(%pK) is equal to the previous timestamp, same report DMAed twice? Asserting the FW", 1783 current_ts, buf); 1784 target_if_spectral_fw_hang(spectral); 1785 } 1786 } 1787 spectral->prev_tstamp = current_ts; 1788 } 1789 #else 1790 static void target_if_spectral_check_buffer_poisoning( 1791 struct target_if_spectral *spectral, 1792 struct spectral_report *report, 1793 int num_fft_bins, enum spectral_scan_mode smode) 1794 { 1795 } 1796 1797 static void target_if_spectral_verify_ts(struct target_if_spectral *spectral, 1798 uint8_t *buf, uint32_t current_ts) 1799 { 1800 } 1801 #endif 1802 1803 /** 1804 * target_if_spectral_get_adjusted_timestamp() - Adjust Spectral time 1805 * stamp to account for reset in time stamp due to target reset 1806 * @twar: Spectral time stamp WAR related information 1807 * @raw_timestamp: Spectral time stamp reported by target 1808 * @reset_delay: Reset delay at target 1809 * @smode: Spectral scan mode 1810 * 1811 * Correct time stamp to account for reset in time stamp due to target reset 1812 * 1813 * Return: Adjusted time stamp 1814 */ 1815 static uint32_t 1816 target_if_spectral_get_adjusted_timestamp(struct spectral_timestamp_war *twar, 1817 uint32_t raw_timestamp, 1818 uint32_t reset_delay, 1819 enum spectral_scan_mode smode) { 1820 qdf_assert_always(smode < SPECTRAL_SCAN_MODE_MAX); 1821 1822 if (reset_delay) { 1823 enum spectral_scan_mode m = 1824 SPECTRAL_SCAN_MODE_NORMAL; 1825 1826 /* Adjust the offset for all the Spectral modes. 1827 * Target will be sending the non zero reset delay for 1828 * the first Spectral report after reset. This delay is 1829 * common for all the Spectral modes. 1830 */ 1831 for (; m < SPECTRAL_SCAN_MODE_MAX; m++) 1832 twar->timestamp_war_offset[m] += (reset_delay + 1833 twar->last_fft_timestamp[m]); 1834 twar->target_reset_count++; 1835 } 1836 twar->last_fft_timestamp[smode] = raw_timestamp; 1837 1838 return raw_timestamp + twar->timestamp_war_offset[smode]; 1839 } 1840 1841 int 1842 target_if_consume_spectral_report_gen3( 1843 struct target_if_spectral *spectral, 1844 struct spectral_report *report) 1845 { 1846 /* 1847 * XXX : The classifier do not use all the members of the SAMP 1848 * message data format. 1849 * The classifier only depends upon the following parameters 1850 * 1851 * 1. Frequency (freq, msg->freq) 1852 * 2. Spectral RSSI (spectral_rssi, 1853 * msg->samp_data.spectral_rssi) 1854 * 3. Bin Power Count (bin_pwr_count, 1855 * msg->samp_data.bin_pwr_count) 1856 * 4. Bin Power values (bin_pwr, msg->samp_data.bin_pwr[0] 1857 * 5. Spectral Timestamp (spectral_tstamp, 1858 * msg->samp_data.spectral_tstamp) 1859 * 6. MAC Address (macaddr, msg->macaddr) 1860 * 1861 * This function prepares the params structure and populates it 1862 * with 1863 * relevant values, this is in turn passed to 1864 * spectral_create_samp_msg() 1865 * to prepare fully formatted Spectral SAMP message 1866 * 1867 * XXX : Need to verify 1868 * 1. Order of FFT bin values 1869 * 1870 */ 1871 struct target_if_samp_msg_params params = {0}; 1872 struct spectral_search_fft_info_gen3 search_fft_info; 1873 struct spectral_search_fft_info_gen3 *p_sfft = &search_fft_info; 1874 int8_t chn_idx_lowest_enabled = 0; 1875 int fft_hdr_length = 0; 1876 int report_len = 0; 1877 size_t fft_bin_count; 1878 size_t fft_bin_size; 1879 struct target_if_spectral_ops *p_sops = 1880 GET_TARGET_IF_SPECTRAL_OPS(spectral); 1881 struct spectral_phyerr_fft_report_gen3 *p_fft_report; 1882 int8_t rssi; 1883 uint8_t *data = report->data; 1884 struct wlan_objmgr_vdev *vdev; 1885 uint8_t vdev_rxchainmask; 1886 struct sscan_report_fields_gen3 sscan_report_fields = {0}; 1887 enum spectral_detector_id detector_id; 1888 QDF_STATUS ret; 1889 enum spectral_scan_mode spectral_mode = SPECTRAL_SCAN_MODE_INVALID; 1890 uint8_t *temp; 1891 bool finite_scan = false; 1892 1893 /* Process Spectral scan summary report */ 1894 if (target_if_verify_sig_and_tag_gen3( 1895 spectral, data, 1896 TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3) != 0) { 1897 spectral_err_rl("Wrong tag/sig in sscan summary"); 1898 goto fail; 1899 } 1900 1901 detector_id = target_if_get_detector_id_sscan_summary_report_gen3(data); 1902 if (detector_id >= spectral->rparams.num_spectral_detectors) { 1903 spectral->diag_stats.spectral_invalid_detector_id++; 1904 spectral_err("Invalid detector id %u, expected is 0/1/2", 1905 detector_id); 1906 goto fail; 1907 } 1908 1909 spectral_mode = target_if_get_spectral_mode(detector_id, 1910 &spectral->rparams); 1911 if (spectral_mode >= SPECTRAL_SCAN_MODE_MAX) { 1912 spectral_err_rl("No valid Spectral mode for detector id %u", 1913 detector_id); 1914 goto fail; 1915 } 1916 1917 /* Drop the sample if Spectral is not active for the current mode */ 1918 if (!p_sops->is_spectral_active(spectral, spectral_mode)) 1919 return -EINVAL; 1920 1921 ret = target_if_spectral_is_finite_scan(spectral, spectral_mode, 1922 &finite_scan); 1923 if (QDF_IS_STATUS_ERROR(ret)) { 1924 spectral_err_rl("Failed to check scan is finite"); 1925 goto fail; 1926 } 1927 1928 if (finite_scan) { 1929 ret = target_if_spectral_finite_scan_update(spectral, 1930 spectral_mode); 1931 if (QDF_IS_STATUS_ERROR(ret)) { 1932 spectral_err_rl("Failed to update scan count"); 1933 goto fail; 1934 } 1935 } 1936 1937 target_if_consume_sscan_summary_report_gen3(data, &sscan_report_fields, 1938 &spectral->rparams); 1939 /* Advance buf pointer to the search fft report */ 1940 data += sizeof(struct spectral_sscan_summary_report_gen3); 1941 data += spectral->rparams.ssumaary_padding_bytes; 1942 params.vhtop_ch_freq_seg1 = report->cfreq1; 1943 params.vhtop_ch_freq_seg2 = report->cfreq2; 1944 1945 if (is_primaryseg_expected(spectral, spectral_mode)) { 1946 /* RSSI is in 1/2 dBm steps, Covert it to dBm scale */ 1947 rssi = (sscan_report_fields.inband_pwr_db) >> 1; 1948 params.agc_total_gain = 1949 sscan_report_fields.sscan_agc_total_gain; 1950 params.gainchange = sscan_report_fields.sscan_gainchange; 1951 params.pri80ind = sscan_report_fields.sscan_pri80; 1952 1953 /* Process Spectral search FFT report */ 1954 if (target_if_verify_sig_and_tag_gen3( 1955 spectral, data, 1956 TLV_TAG_SEARCH_FFT_REPORT_GEN3) != 0) { 1957 spectral_err_rl("Unexpected tag/sig in sfft, detid= %u", 1958 detector_id); 1959 goto fail; 1960 } 1961 p_fft_report = (struct spectral_phyerr_fft_report_gen3 *)data; 1962 fft_hdr_length = p_fft_report->fft_hdr_length * 4; 1963 if (fft_hdr_length < 16) { 1964 spectral_err("Wrong TLV length %u, detector id = %d", 1965 fft_hdr_length, detector_id); 1966 goto fail; 1967 } 1968 1969 report_len = (fft_hdr_length + 8); 1970 1971 target_if_process_sfft_report_gen3(p_fft_report, p_sfft); 1972 /* It is expected to have same detector id for 1973 * summary and fft report 1974 */ 1975 if (detector_id != p_sfft->fft_detector_id) { 1976 spectral_err_rl 1977 ("Different detid in ssummary(%u) and sfft(%u)", 1978 detector_id, p_sfft->fft_detector_id); 1979 goto fail; 1980 } 1981 1982 if (detector_id > spectral->rparams.num_spectral_detectors) { 1983 spectral->diag_stats.spectral_invalid_detector_id++; 1984 spectral_err("Invalid detector id %u, expected is 0/2", 1985 detector_id); 1986 goto fail; 1987 } 1988 params.smode = spectral_mode; 1989 1990 fft_bin_count = target_if_spectral_get_bin_count_after_len_adj( 1991 fft_hdr_length - spectral->rparams.fft_report_hdr_len, 1992 spectral->params[spectral_mode].ss_rpt_mode, 1993 &spectral->len_adj_swar, &fft_bin_size); 1994 1995 params.last_raw_timestamp = spectral->timestamp_war. 1996 last_fft_timestamp[spectral_mode]; 1997 params.reset_delay = report->reset_delay; 1998 params.raw_timestamp = p_sfft->timestamp; 1999 params.tstamp = target_if_spectral_get_adjusted_timestamp( 2000 &spectral->timestamp_war, 2001 p_sfft->timestamp, report->reset_delay, 2002 spectral_mode); 2003 params.timestamp_war_offset = spectral->timestamp_war. 2004 timestamp_war_offset[spectral_mode]; 2005 params.target_reset_count = spectral->timestamp_war. 2006 target_reset_count; 2007 2008 /* Take care of state transitions for 160 MHz and 80p80 */ 2009 if (is_ch_width_160_or_80p80(spectral->ch_width 2010 [spectral_mode]) && spectral->rparams. 2011 fragmentation_160[spectral_mode]) { 2012 ret = target_if_160mhz_delivery_state_change( 2013 spectral, spectral_mode, 2014 detector_id); 2015 if (ret != QDF_STATUS_SUCCESS) 2016 goto fail; 2017 } 2018 2019 if (spectral_debug_level & (DEBUG_SPECTRAL2 | DEBUG_SPECTRAL4)) 2020 target_if_dump_fft_report_gen3(spectral, spectral_mode, 2021 p_fft_report, p_sfft); 2022 2023 params.rssi = rssi; 2024 2025 vdev = target_if_spectral_get_vdev(spectral, spectral_mode); 2026 if (!vdev) { 2027 spectral_info("First vdev is NULL"); 2028 reset_160mhz_delivery_state_machine( 2029 spectral, spectral_mode); 2030 return -EPERM; 2031 } 2032 vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev); 2033 QDF_ASSERT(vdev_rxchainmask != 0); 2034 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 2035 2036 chn_idx_lowest_enabled = 2037 target_if_spectral_get_lowest_chn_idx(vdev_rxchainmask); 2038 if (chn_idx_lowest_enabled >= DBR_MAX_CHAINS) { 2039 spectral_err("Invalid chain index, detector id = %u", 2040 detector_id); 2041 goto fail; 2042 } 2043 2044 params.max_mag = p_sfft->fft_peak_mag; 2045 2046 params.freq = p_sops->get_current_channel(spectral, 2047 spectral_mode); 2048 params.agile_freq1 = spectral->params[SPECTRAL_SCAN_MODE_AGILE]. 2049 ss_frequency.cfreq1; 2050 params.agile_freq2 = spectral->params[SPECTRAL_SCAN_MODE_AGILE]. 2051 ss_frequency.cfreq2; 2052 params.noise_floor = 2053 report->noisefloor[chn_idx_lowest_enabled]; 2054 temp = (uint8_t *)p_fft_report + SPECTRAL_FFT_BINS_POS; 2055 if (is_ch_width_160_or_80p80(spectral->ch_width 2056 [spectral_mode]) && !spectral->rparams. 2057 fragmentation_160[spectral_mode]) { 2058 struct wlan_objmgr_psoc *psoc; 2059 struct spectral_fft_bin_markers_160_165mhz *marker; 2060 2061 qdf_assert_always(spectral->pdev_obj); 2062 psoc = wlan_pdev_get_psoc(spectral->pdev_obj); 2063 qdf_assert_always(psoc); 2064 2065 params.agc_total_gain_sec80 = 2066 sscan_report_fields.sscan_agc_total_gain; 2067 params.gainchange_sec80 = 2068 sscan_report_fields.sscan_gainchange; 2069 params.raw_timestamp_sec80 = p_sfft->timestamp; 2070 params.rssi_sec80 = rssi; 2071 params.noise_floor_sec80 = 2072 report->noisefloor[chn_idx_lowest_enabled]; 2073 params.max_mag_sec80 = p_sfft->fft_peak_mag; 2074 params.datalen = fft_hdr_length * 2; 2075 params.datalen_sec80 = fft_hdr_length * 2; 2076 2077 marker = &spectral->rparams.marker[spectral_mode]; 2078 if (!marker->is_valid) { 2079 /* update stats */ 2080 goto fail_no_print; 2081 } 2082 params.bin_pwr_data = temp + 2083 marker->start_pri80 * fft_bin_size; 2084 params.pwr_count = marker->num_pri80; 2085 params.bin_pwr_data_sec80 = temp + 2086 marker->start_sec80 * fft_bin_size; 2087 params.pwr_count_sec80 = marker->num_sec80; 2088 if (spectral->ch_width[spectral_mode] == 2089 CH_WIDTH_80P80MHZ && wlan_psoc_nif_fw_ext_cap_get( 2090 psoc, WLAN_SOC_RESTRICTED_80P80_SUPPORT)) { 2091 params.bin_pwr_data_5mhz = temp + 2092 marker->start_5mhz * fft_bin_size; 2093 params.pwr_count_5mhz = marker->num_5mhz; 2094 } 2095 } else { 2096 params.bin_pwr_data = temp; 2097 params.pwr_count = fft_bin_count; 2098 params.datalen = (fft_hdr_length * 4); 2099 } 2100 2101 target_if_spectral_verify_ts(spectral, report->data, 2102 params.tstamp); 2103 } else if (is_secondaryseg_expected(spectral, spectral_mode)) { 2104 /* RSSI is in 1/2 dBm steps, Covert it to dBm scale */ 2105 rssi = (sscan_report_fields.inband_pwr_db) >> 1; 2106 params.agc_total_gain_sec80 = 2107 sscan_report_fields.sscan_agc_total_gain; 2108 params.gainchange_sec80 = sscan_report_fields.sscan_gainchange; 2109 params.pri80ind_sec80 = sscan_report_fields.sscan_pri80; 2110 2111 /* Process Spectral search FFT report */ 2112 if (target_if_verify_sig_and_tag_gen3( 2113 spectral, data, 2114 TLV_TAG_SEARCH_FFT_REPORT_GEN3) != 0) { 2115 spectral_err_rl("Unexpected tag/sig in sfft, detid= %u", 2116 detector_id); 2117 goto fail; 2118 } 2119 p_fft_report = (struct spectral_phyerr_fft_report_gen3 *)data; 2120 fft_hdr_length = p_fft_report->fft_hdr_length * 4; 2121 if (fft_hdr_length < 16) { 2122 spectral_err("Wrong TLV length %u, detector id = %u", 2123 fft_hdr_length, detector_id); 2124 goto fail; 2125 } 2126 2127 report_len = (fft_hdr_length + 8); 2128 2129 target_if_process_sfft_report_gen3(p_fft_report, p_sfft); 2130 /* It is expected to have same detector id for 2131 * summary and fft report 2132 */ 2133 if (detector_id != p_sfft->fft_detector_id) { 2134 spectral_err_rl 2135 ("Different detid in ssummary(%u) and sfft(%u)", 2136 detector_id, p_sfft->fft_detector_id); 2137 goto fail; 2138 } 2139 2140 if (detector_id > spectral->rparams.num_spectral_detectors) { 2141 spectral->diag_stats.spectral_invalid_detector_id++; 2142 spectral_err("Invalid detector id %u, expected is 1", 2143 detector_id); 2144 goto fail; 2145 } 2146 params.smode = spectral_mode; 2147 2148 fft_bin_count = target_if_spectral_get_bin_count_after_len_adj( 2149 fft_hdr_length - spectral->rparams.fft_report_hdr_len, 2150 spectral->params[spectral_mode].ss_rpt_mode, 2151 &spectral->len_adj_swar, &fft_bin_size); 2152 params.raw_timestamp_sec80 = p_sfft->timestamp; 2153 2154 /* Take care of state transitions for 160 MHz and 80p80 */ 2155 if (is_ch_width_160_or_80p80(spectral->ch_width 2156 [spectral_mode]) && spectral->rparams. 2157 fragmentation_160[spectral_mode]) { 2158 ret = target_if_160mhz_delivery_state_change( 2159 spectral, spectral_mode, 2160 detector_id); 2161 if (ret != QDF_STATUS_SUCCESS) 2162 goto fail; 2163 } 2164 2165 if (spectral_debug_level & (DEBUG_SPECTRAL2 | DEBUG_SPECTRAL4)) 2166 target_if_dump_fft_report_gen3(spectral, spectral_mode, 2167 p_fft_report, p_sfft); 2168 2169 params.rssi_sec80 = rssi; 2170 2171 vdev = target_if_spectral_get_vdev(spectral, spectral_mode); 2172 if (!vdev) { 2173 spectral_info("First vdev is NULL"); 2174 reset_160mhz_delivery_state_machine 2175 (spectral, spectral_mode); 2176 return -EPERM; 2177 } 2178 vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev); 2179 QDF_ASSERT(vdev_rxchainmask != 0); 2180 wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); 2181 2182 chn_idx_lowest_enabled = 2183 target_if_spectral_get_lowest_chn_idx(vdev_rxchainmask); 2184 if (chn_idx_lowest_enabled >= DBR_MAX_CHAINS) { 2185 spectral_err("Invalid chain index"); 2186 goto fail; 2187 } 2188 2189 /* Need to change this as per FW team's inputs */ 2190 params.noise_floor_sec80 = 2191 report->noisefloor[chn_idx_lowest_enabled]; 2192 2193 params.max_mag_sec80 = p_sfft->fft_peak_mag; 2194 /* params.max_index_sec80 = p_sfft->peak_inx; */ 2195 /* XXX Does this definition of datalen *still hold? */ 2196 params.datalen_sec80 = fft_hdr_length * 4; 2197 params.pwr_count_sec80 = fft_bin_count; 2198 params.bin_pwr_data_sec80 = 2199 (uint8_t *)((uint8_t *)p_fft_report + 2200 SPECTRAL_FFT_BINS_POS); 2201 } else { 2202 spectral_err("Spectral state machine in undefined state"); 2203 goto fail; 2204 } 2205 2206 target_if_spectral_check_buffer_poisoning(spectral, report, 2207 fft_bin_count, spectral_mode); 2208 qdf_mem_copy(¶ms.classifier_params, 2209 &spectral->classifier_params, 2210 sizeof(struct spectral_classifier_params)); 2211 2212 target_if_spectral_log_SAMP_param(¶ms); 2213 target_if_spectral_create_samp_msg(spectral, ¶ms); 2214 2215 return 0; 2216 fail: 2217 spectral_err_rl("Error while processing Spectral report"); 2218 fail_no_print: 2219 if (spectral_mode != SPECTRAL_SCAN_MODE_INVALID) 2220 reset_160mhz_delivery_state_machine(spectral, spectral_mode); 2221 return -EPERM; 2222 } 2223 2224 int target_if_spectral_process_report_gen3( 2225 struct wlan_objmgr_pdev *pdev, 2226 void *buf) 2227 { 2228 int ret = 0; 2229 struct direct_buf_rx_data *payload = buf; 2230 struct target_if_spectral *spectral; 2231 struct spectral_report report; 2232 2233 spectral = get_target_if_spectral_handle_from_pdev(pdev); 2234 if (!spectral) { 2235 spectral_err("Spectral target object is null"); 2236 return -EINVAL; 2237 } 2238 2239 report.data = payload->vaddr; 2240 if (payload->meta_data_valid) { 2241 qdf_mem_copy(report.noisefloor, payload->meta_data.noisefloor, 2242 qdf_min(sizeof(report.noisefloor), 2243 sizeof(payload->meta_data.noisefloor))); 2244 report.reset_delay = payload->meta_data.reset_delay; 2245 report.cfreq1 = payload->meta_data.cfreq1; 2246 report.cfreq2 = payload->meta_data.cfreq2; 2247 report.ch_width = payload->meta_data.ch_width; 2248 } 2249 2250 if (spectral_debug_level & (DEBUG_SPECTRAL2 | DEBUG_SPECTRAL4)) { 2251 spectral_debug("Printing the spectral phyerr buffer for debug"); 2252 spectral_debug("Datalength of buffer = 0x%zx(%zd) bufptr = 0x%pK", 2253 payload->dbr_len, 2254 payload->dbr_len, 2255 payload->vaddr); 2256 target_if_spectral_hexdump((unsigned char *)payload->vaddr, 2257 1024); 2258 } 2259 2260 ret = target_if_consume_spectral_report_gen3(spectral, &report); 2261 2262 if (spectral_debug_level & DEBUG_SPECTRAL4) 2263 spectral_debug_level = DEBUG_SPECTRAL; 2264 2265 return ret; 2266 } 2267 #else 2268 int target_if_spectral_process_report_gen3( 2269 struct wlan_objmgr_pdev *pdev, 2270 void *buf) 2271 { 2272 spectral_err("Direct dma support is not enabled"); 2273 return -EINVAL; 2274 } 2275 #endif 2276 qdf_export_symbol(target_if_spectral_process_report_gen3); 2277 /* END of spectral GEN III HW specific functions */ 2278 2279 #endif /* WLAN_CONV_SPECTRAL_ENABLE */ 2280