diff --git a/os_if/linux/spectral/src/os_if_spectral_netlink.c b/os_if/linux/spectral/src/os_if_spectral_netlink.c index 91584dcaeaa5..0a7c39627e6e 100644 --- a/os_if/linux/spectral/src/os_if_spectral_netlink.c +++ b/os_if/linux/spectral/src/os_if_spectral_netlink.c @@ -403,6 +403,7 @@ os_if_spectral_nl_unicast_msg(struct wlan_objmgr_pdev *pdev) } #endif + /** * os_if_spectral_nl_bcast_msg() - Sends broadcast Spectral message to user * space @@ -453,6 +454,44 @@ os_if_spectral_nl_bcast_msg(struct wlan_objmgr_pdev *pdev) return status; } +/** + * os_if_spectral_free_skb() - Free spectral SAMP message skb + * + * @pdev : Pointer to pdev + * + * Return: void + */ +static void +os_if_spectral_free_skb(struct wlan_objmgr_pdev *pdev) +{ + struct pdev_spectral *ps = NULL; + + if (!pdev) { + spectral_err("PDEV is NULL!"); + return; + } + ps = wlan_objmgr_pdev_get_comp_private_obj(pdev, + WLAN_UMAC_COMP_SPECTRAL); + + if (!ps) { + spectral_err("PDEV SPECTRAL object is NULL!"); + return; + } + + if (!ps->skb) { + spectral_err("Socket buffer is null"); + return; + } + + /* Free buffer */ + qdf_nbuf_free(ps->skb); + + /* clear the local copy */ + ps->skb = NULL; +} + +qdf_export_symbol(os_if_spectral_free_skb); + void os_if_spectral_netlink_init(struct wlan_objmgr_pdev *pdev) { @@ -477,6 +516,7 @@ os_if_spectral_netlink_init(struct wlan_objmgr_pdev *pdev) nl_cb.get_nbuff = os_if_spectral_prep_skb; nl_cb.send_nl_bcast = os_if_spectral_nl_bcast_msg; nl_cb.send_nl_unicast = os_if_spectral_nl_unicast_msg; + nl_cb.free_nbuff = os_if_spectral_free_skb; if (sptrl_ctx->sptrlc_register_netlink_cb) sptrl_ctx->sptrlc_register_netlink_cb(pdev, &nl_cb); diff --git a/spectral/dispatcher/inc/wlan_spectral_public_structs.h b/spectral/dispatcher/inc/wlan_spectral_public_structs.h index 4d3f96fbff61..452ae90f53b4 100644 --- a/spectral/dispatcher/inc/wlan_spectral_public_structs.h +++ b/spectral/dispatcher/inc/wlan_spectral_public_structs.h @@ -233,6 +233,7 @@ struct spectral_chan_stats { * mismatches in Search FFT report * @spectral_vhtseg2id_mismatch: VHT Operation Segment 2 ID * mismatches in Search FFT report + * @spectral_invalid_detector_id: Invalid detector id */ struct spectral_diag_stats { uint64_t spectral_mismatch; @@ -240,6 +241,7 @@ struct spectral_diag_stats { uint64_t spectral_no_sec80_sfft; uint64_t spectral_vhtseg1id_mismatch; uint64_t spectral_vhtseg2id_mismatch; + uint64_t spectral_invalid_detector_id; }; /** @@ -525,6 +527,7 @@ struct spectral_nl_cb { void *(*get_nbuff)(struct wlan_objmgr_pdev *pdev); int (*send_nl_bcast)(struct wlan_objmgr_pdev *pdev); int (*send_nl_unicast)(struct wlan_objmgr_pdev *pdev); + void (*free_nbuff)(struct wlan_objmgr_pdev *pdev); }; #ifndef __KERNEL__ diff --git a/target_if/spectral/target_if_spectral.c b/target_if/spectral/target_if_spectral.c index b0d872b29f46..9d74da5e0299 100644 --- a/target_if/spectral/target_if_spectral.c +++ b/target_if/spectral/target_if_spectral.c @@ -1885,6 +1885,8 @@ target_if_spectral_detach(struct target_if_spectral *spectral) spectral_info("spectral detach"); if (spectral) { + if (spectral->spectral_gen == SPECTRAL_GEN3) + deinit_160mhz_delivery_state_machine(spectral); qdf_spinlock_destroy(&spectral->param_info.osps_lock); target_if_spectral_detach_simulation(spectral); @@ -2076,6 +2078,8 @@ target_if_pdev_spectral_init(struct wlan_objmgr_pdev *pdev) #else spectral->use_nl_bcast = false; #endif + if (spectral->spectral_gen == SPECTRAL_GEN3) + init_160mhz_delivery_state_machine(spectral); } return spectral; diff --git a/target_if/spectral/target_if_spectral.h b/target_if/spectral/target_if_spectral.h index 0cee77675687..9daf8cd992c3 100644 --- a/target_if/spectral/target_if_spectral.h +++ b/target_if/spectral/target_if_spectral.h @@ -104,6 +104,46 @@ #define TLV_TAG_ADC_REPORT_GEN2 0xFA #define TLV_TAG_SEARCH_FFT_REPORT_GEN2 0xFB +/** + * enum spectral_160mhz_report_delivery_state - 160 MHz state machine states + * @SPECTRAL_REPORT_WAIT_PRIMARY80: Wait for primary80 report + * @SPECTRAL_REPORT_RX_PRIMARY80: Receive primary 80 report + * @SPECTRAL_REPORT_WAIT_SECONDARY80: Wait for secondory 80 report + * @SPECTRAL_REPORT_RX_SECONDARY80: Receive secondary 80 report + */ +enum spectral_160mhz_report_delivery_state { + SPECTRAL_REPORT_WAIT_PRIMARY80, + SPECTRAL_REPORT_RX_PRIMARY80, + SPECTRAL_REPORT_WAIT_SECONDARY80, + SPECTRAL_REPORT_RX_SECONDARY80, +}; + +/** + * enum spectral_detector_id - Spectral detector id + * @SPECTRAL_DETECTOR_PRIMARY: Primary detector + * @SPECTRAL_DETECTOR_SECONDARY: Secondary detector + * @SPECTRAL_DETECTOR_AGILE: Agile detector + * @SPECTRAL_DETECTOR_INVALID: Invalid detector + */ +enum spectral_detector_id { + SPECTRAL_DETECTOR_PRIMARY, + SPECTRAL_DETECTOR_SECONDARY, + SPECTRAL_DETECTOR_AGILE, + SPECTRAL_DETECTOR_INVALID, +}; + +/** + * enum spectral_160mhz_report_delivery_event - 160 MHz state machine event + * @SPECTRAL_REPORT_EVENT_DETECTORID0: Received detector id 0 + * @SPECTRAL_REPORT_EVENT_DETECTORID1: Received detector id 1 + * @SPECTRAL_REPORT_EVENT_DETECTORID_INVALID: Received invalid detector id + */ +enum spectral_160mhz_report_delivery_event { + SPECTRAL_REPORT_EVENT_DETECTORID0, + SPECTRAL_REPORT_EVENT_DETECTORID1, + SPECTRAL_REPORT_EVENT_DETECTORID_INVALID, +}; + /** * struct spectral_search_fft_info_gen2 - spectral search fft report for gen2 * @relpwr_db: Total bin power in db @@ -198,6 +238,8 @@ struct spectral_phyerr_fft_gen2 { (((value) >= (1 << ((width) - 1))) ? \ (value - (1 << (width))) : (value)) +#define SSCAN_REPORT_DETECTOR_ID_POS_GEN3 (29) +#define SSCAN_REPORT_DETECTOR_ID_SIZE_GEN3 (2) #define SPECTRAL_PHYERR_SIGNATURE_GEN3 (0xFA) #define TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3 (0x02) #define TLV_TAG_SEARCH_FFT_REPORT_GEN3 (0x03) @@ -827,6 +869,8 @@ struct target_if_spectral { int (*send_phy_data)(struct wlan_objmgr_pdev *pdev); u_int8_t fftbin_size_war; u_int8_t inband_fftbin_size_adj; + enum spectral_160mhz_report_delivery_state state_160mhz_delivery; + void *spectral_report_cache; }; /** @@ -1271,6 +1315,201 @@ void target_if_spectral_process_phyerr( tsf64, acs_stats); } +/** + * save_spectral_report_skb() - Save Spectral report skb + * @spectral: Pointer to Spectral + * @skb: Pointer to skb + * + * Save spectral report skb + * + * Return: void + */ +static inline void +save_spectral_report_skb(struct target_if_spectral *spectral, void *skb) { + if (spectral->ch_width == CH_WIDTH_160MHZ) + spectral->spectral_report_cache = skb; +} + +/** + * restore_spectral_report_skb() - Restore Spectral report skb + * @spectral: Pointer to Spectral + * @skb: Pointer to restore location + * + * Restore spectral report skb + * + * Return: void + */ +static inline void +restore_spectral_report_skb(struct target_if_spectral *spectral, void **dest) { + if (spectral->ch_width == CH_WIDTH_160MHZ) { + QDF_ASSERT(spectral->spectral_report_cache); + *dest = spectral->spectral_report_cache; + } +} + +/** + * clear_spectral_report_skb() - Clear Spectral report skb + * @spectral: Pointer to Spectral + * + * Clear spectral report skb + * + * Return: void + */ +static inline void +clear_spectral_report_skb(struct target_if_spectral *spectral) { + if (spectral->ch_width == CH_WIDTH_160MHZ) + spectral->spectral_report_cache = NULL; +} + +/** + * free_and_clear_spectral_report_skb() - Free and clear Spectral report skb + * @spectral: Pointer to Spectral + * + * Free and clear spectral report skb + * + * Return: void + */ +static inline void +free_and_clear_spectral_report_skb(struct target_if_spectral *spectral) { + if (spectral->spectral_report_cache) + spectral->nl_cb.free_nbuff(spectral->pdev_obj); + spectral->spectral_report_cache = NULL; +} + +/** + * init_160mhz_delivery_state_machine() - Initialize 160MHz Spectral + * state machine + * @spectral: Pointer to Spectral + * + * Initialize 160MHz Spectral state machine + * + * Return: void + */ +static inline void +init_160mhz_delivery_state_machine(struct target_if_spectral *spectral) { + spectral->state_160mhz_delivery = + SPECTRAL_REPORT_WAIT_PRIMARY80; + spectral->spectral_report_cache = NULL; +} + +/** + * deinit_160mhz_delivery_state_machine() - Deinitialize 160MHz Spectral + * state machine + * @spectral: Pointer to Spectral + * + * Deinitialize 160MHz Spectral state machine + * + * Return: void + */ +static inline void +deinit_160mhz_delivery_state_machine(struct target_if_spectral *spectral) { + if (spectral->spectral_report_cache) + spectral->nl_cb.free_nbuff(spectral->pdev_obj); + spectral->spectral_report_cache = NULL; +} + +/** + * reset_160mhz_delivery_state_machine() - Reset 160MHz Spectral state machine + * @spectral: Pointer to Spectral + * + * Reset 160MHz Spectral state machine + * + * Return: void + */ +static inline void +reset_160mhz_delivery_state_machine(struct target_if_spectral *spectral) { + if (spectral->ch_width == CH_WIDTH_160MHZ) { + spectral->state_160mhz_delivery = + SPECTRAL_REPORT_WAIT_PRIMARY80; + free_and_clear_spectral_report_skb(spectral); + } +} + +/** + * is_secondaryseg_expected() - Is waiting for secondary 80 report + * @spectral: Pointer to Spectral + * + * Return true if secondary 80 report expected and mode is 160 MHz + * + * Return: true or false + */ +static inline +bool is_secondaryseg_expected(struct target_if_spectral *spectral) +{ + return + ((spectral->ch_width == CH_WIDTH_160MHZ) && + (spectral->state_160mhz_delivery == SPECTRAL_REPORT_WAIT_SECONDARY80)); +} + +/** + * is_primaryseg_expected() - Is waiting for primary 80 report + * @spectral: Pointer to Spectral + * + * Return true if mode is 160 Mhz and primary 80 report expected or + * mode is not 160 Mhz + * + * Return: true or false + */ +static inline +bool is_primaryseg_expected(struct target_if_spectral *spectral) +{ + return + ((spectral->ch_width != CH_WIDTH_160MHZ) || + ((spectral->ch_width == CH_WIDTH_160MHZ) && + (spectral->state_160mhz_delivery == SPECTRAL_REPORT_WAIT_PRIMARY80))); +} + +/** + * is_primaryseg_rx_inprog() - Is primary 80 report processing is in progress + * @spectral: Pointer to Spectral + * + * Is primary 80 report processing is in progress + * + * Return: true or false + */ +static inline +bool is_primaryseg_rx_inprog(struct target_if_spectral *spectral) +{ + return + ((spectral->ch_width != CH_WIDTH_160MHZ) || + ((spectral->ch_width == CH_WIDTH_160MHZ) && + ((spectral->spectral_gen == SPECTRAL_GEN2) || + ((spectral->spectral_gen == SPECTRAL_GEN3) && + (spectral->state_160mhz_delivery == SPECTRAL_REPORT_RX_PRIMARY80))))); +} + +/** + * is_secondaryseg_rx_inprog() - Is secondary80 report processing is in progress + * @spectral: Pointer to Spectral + * + * Is secondary 80 report processing is in progress + * + * Return: true or false + */ +static inline +bool is_secondaryseg_rx_inprog(struct target_if_spectral *spectral) +{ + return + ((spectral->ch_width == CH_WIDTH_160MHZ) && + ((spectral->spectral_gen == SPECTRAL_GEN2) || + ((spectral->spectral_gen == SPECTRAL_GEN3) && + (spectral->state_160mhz_delivery == SPECTRAL_REPORT_RX_SECONDARY80)))); +} + +/** + * target_if_160mhz_delivery_state_change() - State transition for 160Mhz + * Spectral + * @spectral: Pointer to spectral object + * @detector_id: Detector id + * + * Move the states of state machine for 160MHz spectral scan report receive + * + * Return: QDF_STATUS + */ +QDF_STATUS +target_if_160mhz_delivery_state_change(struct target_if_spectral *spectral, + uint8_t detector_id); + /** * target_if_sops_is_spectral_enabled() - Get whether Spectral is enabled * @arg: Pointer to handle for Spectral target_if internal private data @@ -1588,6 +1827,9 @@ void target_if_register_wmi_spectral_cmd_ops( struct wlan_objmgr_pdev *pdev, struct wmi_spectral_cmd_ops *cmd_ops); +QDF_STATUS +target_if_160mhz_delivery_state_change(struct target_if_spectral *spectral, + uint8_t detector_id); #ifdef DIRECT_BUF_RX_ENABLE /** * target_if_consume_sfft_report_gen3() - Process fft report for gen3 diff --git a/target_if/spectral/target_if_spectral_netlink.c b/target_if/spectral/target_if_spectral_netlink.c index 2aae510357cd..947155897e3b 100644 --- a/target_if/spectral/target_if_spectral_netlink.c +++ b/target_if/spectral/target_if_spectral_netlink.c @@ -27,89 +27,6 @@ #include #include -static void -target_if_spectral_process_noise_pwr_report( - struct target_if_spectral *spectral, - const struct spectral_samp_msg *spec_samp_msg) -{ - int i, done; - - qdf_spin_lock(&spectral->noise_pwr_reports_lock); - - if (!spectral->noise_pwr_reports_reqd) { - qdf_spin_unlock(&spectral->noise_pwr_reports_lock); - return; - } - - if (spectral->noise_pwr_reports_recv < - spectral->noise_pwr_reports_reqd) { - spectral->noise_pwr_reports_recv++; - - for (i = 0; i < HOST_MAX_ANTENNA; i++) { - uint32_t index; - - if (spectral->noise_pwr_chain_ctl[i]) { - index = - spectral->noise_pwr_chain_ctl[i]-> - rptcount++; - spectral->noise_pwr_chain_ctl[i]->pwr[index] = - spec_samp_msg->samp_data. - spectral_chain_ctl_rssi[i]; - } - if (spectral->noise_pwr_chain_ext[i]) { - index = - spectral->noise_pwr_chain_ext[i]-> - rptcount++; - spectral->noise_pwr_chain_ext[i]->pwr[index] = - spec_samp_msg->samp_data. - spectral_chain_ext_rssi[i]; - } - } - } - - done = (spectral->noise_pwr_reports_recv >= - spectral->noise_pwr_reports_reqd); - - qdf_spin_unlock(&spectral->noise_pwr_reports_lock); - - if (done) { - qdf_spin_lock(&spectral->spectral_lock); - target_if_stop_spectral_scan(spectral->pdev_obj); - spectral->sc_spectral_scan = 0; - qdf_spin_unlock(&spectral->spectral_lock); - } -} - -/* - * Function : spectral_create_samp_msg - * Description : create SAMP message and send it host - * Input : - * Output : - * - */ - -#ifdef SPECTRAL_CLASSIFIER_IN_KERNEL -static void -target_if_spectral_init_interf_list( - struct spectral_samp_data *data, - struct target_if_samp_msg_params *params) -{ - if (params->interf_list.count) - OS_MEMCPY(&data->interf_list, - ¶ms->interf_list, sizeof(struct interf_src_rsp)); - else - data->interf_list.count = 0; -} -#else -static void -target_if_spectral_init_interf_list( - struct spectral_samp_data *data, - struct target_if_samp_msg_params *params) -{ - data->interf_list.count = 0; -} -#endif - void target_if_spectral_create_samp_msg(struct target_if_spectral *spectral, struct target_if_samp_msg_params *params) @@ -121,146 +38,155 @@ target_if_spectral_create_samp_msg(struct target_if_spectral *spectral, int temp_samp_msg_len = 0; - struct spectral_samp_msg *spec_samp_msg; + struct spectral_samp_msg *spec_samp_msg = NULL; - struct spectral_samp_data *data = NULL; uint8_t *bin_pwr_data = NULL; struct spectral_classifier_params *cp = NULL; struct spectral_classifier_params *pcp = NULL; struct target_if_spectral_ops *p_sops = NULL; uint32_t *binptr = NULL; int idx = 0; - + struct spectral_samp_data *samp_data; static int samp_msg_index; - spec_samp_msg = (struct spectral_samp_msg *)spectral->nl_cb.get_nbuff( - spectral->pdev_obj); - if (!spec_samp_msg) - return; + if (is_primaryseg_rx_inprog(spectral)) { + spec_samp_msg = (struct spectral_samp_msg *) + spectral->nl_cb.get_nbuff(spectral->pdev_obj); - p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); - temp_samp_msg_len = sizeof(struct spectral_samp_msg) - - (MAX_NUM_BINS * sizeof(uint8_t)); - temp_samp_msg_len += (params->pwr_count * sizeof(uint8_t)); - if (spectral->ch_width == CH_WIDTH_160MHZ) - temp_samp_msg_len += - (params->pwr_count_sec80 * sizeof(uint8_t)); - bin_pwr_data = params->bin_pwr_data; + if (!spec_samp_msg) + return; - data = &spec_samp_msg->samp_data; + samp_data = &spec_samp_msg->samp_data; + if (spectral->spectral_gen == SPECTRAL_GEN3) + save_spectral_report_skb(spectral, spec_samp_msg); + p_sops = GET_TARGET_IF_SPECTRAL_OPS(spectral); + temp_samp_msg_len = sizeof(struct spectral_samp_msg) - + (MAX_NUM_BINS * sizeof(uint8_t)); + temp_samp_msg_len += (params->pwr_count * sizeof(uint8_t)); + if (spectral->ch_width == CH_WIDTH_160MHZ) + temp_samp_msg_len += + (params->pwr_count_sec80 * sizeof(uint8_t)); + bin_pwr_data = params->bin_pwr_data; - spec_samp_msg->signature = SPECTRAL_SIGNATURE; - spec_samp_msg->freq = params->freq; - spec_samp_msg->freq_loading = params->freq_loading; - spec_samp_msg->samp_data.spectral_data_len = params->datalen; - spec_samp_msg->samp_data.spectral_rssi = params->rssi; - spec_samp_msg->samp_data.spectral_agc_total_gain = - params->agc_total_gain; - spec_samp_msg->samp_data.spectral_gainchange = params->gainchange; - spec_samp_msg->samp_data.ch_width = spectral->ch_width; + spec_samp_msg->signature = SPECTRAL_SIGNATURE; + spec_samp_msg->freq = params->freq; + spec_samp_msg->freq_loading = params->freq_loading; + samp_data->spectral_data_len = params->datalen; + samp_data->spectral_rssi = params->rssi; + samp_data->ch_width = spectral->ch_width; + samp_data->spectral_agc_total_gain = params->agc_total_gain; + samp_data->spectral_gainchange = params->gainchange; - spec_samp_msg->samp_data.spectral_combined_rssi = - (uint8_t)params->rssi; - spec_samp_msg->samp_data.spectral_upper_rssi = params->upper_rssi; - spec_samp_msg->samp_data.spectral_lower_rssi = params->lower_rssi; + samp_data->spectral_combined_rssi = + (uint8_t)params->rssi; + samp_data->spectral_upper_rssi = params->upper_rssi; + samp_data->spectral_lower_rssi = params->lower_rssi; - OS_MEMCPY(spec_samp_msg->samp_data.spectral_chain_ctl_rssi, - params->chain_ctl_rssi, sizeof(params->chain_ctl_rssi)); - OS_MEMCPY(spec_samp_msg->samp_data.spectral_chain_ext_rssi, - params->chain_ext_rssi, sizeof(params->chain_ext_rssi)); + qdf_mem_copy(samp_data->spectral_chain_ctl_rssi, + params->chain_ctl_rssi, + sizeof(params->chain_ctl_rssi)); + qdf_mem_copy(samp_data->spectral_chain_ext_rssi, + params->chain_ext_rssi, + sizeof(params->chain_ext_rssi)); - spec_samp_msg->samp_data.spectral_bwinfo = params->bwinfo; - spec_samp_msg->samp_data.spectral_tstamp = params->tstamp; - spec_samp_msg->samp_data.spectral_max_index = params->max_index; + samp_data->spectral_bwinfo = params->bwinfo; + samp_data->spectral_tstamp = params->tstamp; + samp_data->spectral_max_index = params->max_index; - /* Classifier in user space needs access to these */ - spec_samp_msg->samp_data.spectral_lower_max_index = - params->max_lower_index; - spec_samp_msg->samp_data.spectral_upper_max_index = - params->max_upper_index; - spec_samp_msg->samp_data.spectral_nb_lower = params->nb_lower; - spec_samp_msg->samp_data.spectral_nb_upper = params->nb_upper; - spec_samp_msg->samp_data.spectral_last_tstamp = params->last_tstamp; - spec_samp_msg->samp_data.spectral_max_mag = params->max_mag; - spec_samp_msg->samp_data.bin_pwr_count = params->pwr_count; - spec_samp_msg->samp_data.lb_edge_extrabins = - spectral->lb_edge_extrabins; - spec_samp_msg->samp_data.rb_edge_extrabins = - spectral->rb_edge_extrabins; - spec_samp_msg->samp_data.spectral_combined_rssi = params->rssi; - spec_samp_msg->samp_data.spectral_max_scale = params->max_exp; + /* Classifier in user space needs access to these */ + samp_data->spectral_lower_max_index = + params->max_lower_index; + samp_data->spectral_upper_max_index = + params->max_upper_index; + samp_data->spectral_nb_lower = params->nb_lower; + samp_data->spectral_nb_upper = params->nb_upper; + samp_data->spectral_last_tstamp = params->last_tstamp; + samp_data->spectral_max_mag = params->max_mag; + samp_data->bin_pwr_count = params->pwr_count; + samp_data->lb_edge_extrabins = + spectral->lb_edge_extrabins; + samp_data->rb_edge_extrabins = + spectral->rb_edge_extrabins; + samp_data->spectral_combined_rssi = params->rssi; + samp_data->spectral_max_scale = params->max_exp; - /* - * This is a dirty hack to get the Windows build pass. - * Currently Windows and Linux builds source spectral_data.h - * form two different place. The windows version do not - * have noise_floor member in it. - * - * As a temp workaround this variable is set under the - * SPECTRAL_USE_NETLINK_SOCKETS as this is called only - * under the linux build and this saves the day - * - * The plan to sync of header files in under the way - * - */ + samp_data->noise_floor = params->noise_floor; - spec_samp_msg->samp_data.noise_floor = params->noise_floor; + /* Classifier in user space needs access to these */ + cp = &samp_data->classifier_params; + pcp = ¶ms->classifier_params; - /* Classifier in user space needs access to these */ - cp = &spec_samp_msg->samp_data.classifier_params; - pcp = ¶ms->classifier_params; + qdf_mem_copy(cp, pcp, + sizeof(struct spectral_classifier_params)); - OS_MEMCPY(cp, pcp, sizeof(struct spectral_classifier_params)); + if (spectral->fftbin_size_war) { + binptr = (uint32_t *)bin_pwr_data; + for (idx = 0; idx < params->pwr_count; idx++) + samp_data->bin_pwr[idx] = *(binptr++); + } else { + SPECTRAL_MESSAGE_COPY_CHAR_ARRAY( + &samp_data->bin_pwr[0], bin_pwr_data, + params->pwr_count); + } - if (spectral->fftbin_size_war) { - binptr = (uint32_t *)bin_pwr_data; - for (idx = 0; idx < params->pwr_count; idx++) - data->bin_pwr[idx] = *(binptr++); - } else { - SPECTRAL_MESSAGE_COPY_CHAR_ARRAY(&data->bin_pwr[0], - bin_pwr_data, params->pwr_count); + p_sops->get_mac_address(spectral, spec_samp_msg->macaddr); } - spec_samp_msg->vhtop_ch_freq_seg1 = params->vhtop_ch_freq_seg1; - spec_samp_msg->vhtop_ch_freq_seg2 = params->vhtop_ch_freq_seg2; + if (is_secondaryseg_rx_inprog(spectral)) { + if (spectral->spectral_gen == SPECTRAL_GEN3) + restore_spectral_report_skb(spectral, + (void **)&spec_samp_msg); + if (!spec_samp_msg) { + spectral_err("Spectral SAMP message is NULL"); + return; + } - if (spectral->ch_width == CH_WIDTH_160MHZ) { - spec_samp_msg->samp_data.spectral_rssi_sec80 = + samp_data = &spec_samp_msg->samp_data; + spec_samp_msg->vhtop_ch_freq_seg1 = params->vhtop_ch_freq_seg1; + spec_samp_msg->vhtop_ch_freq_seg2 = params->vhtop_ch_freq_seg2; + samp_data->spectral_rssi_sec80 = params->rssi_sec80; - spec_samp_msg->samp_data.noise_floor_sec80 = + samp_data->noise_floor_sec80 = params->noise_floor_sec80; spec_samp_msg->samp_data.spectral_agc_total_gain_sec80 = params->agc_total_gain_sec80; spec_samp_msg->samp_data.spectral_gainchange_sec80 = params->gainchange_sec80; - spec_samp_msg->samp_data.spectral_data_len_sec80 = + samp_data->spectral_data_len_sec80 = params->datalen_sec80; - spec_samp_msg->samp_data.spectral_max_index_sec80 = + samp_data->spectral_max_index_sec80 = params->max_index_sec80; - spec_samp_msg->samp_data.spectral_max_mag_sec80 = + samp_data->spectral_max_mag_sec80 = params->max_mag_sec80; - spec_samp_msg->samp_data.bin_pwr_count_sec80 = + samp_data->bin_pwr_count_sec80 = params->pwr_count_sec80; - SPECTRAL_MESSAGE_COPY_CHAR_ARRAY(&data->bin_pwr_sec80[0], - (params->bin_pwr_data_sec80), - params->pwr_count_sec80); - /* - * Note: REVERSE_ORDER is not a known use case for - * secondary 80 data at this point. - */ + bin_pwr_data = params->bin_pwr_data_sec80; + if (spectral->fftbin_size_war) { + binptr = (uint32_t *)bin_pwr_data; + for (idx = 0; idx < params->pwr_count_sec80; idx++) + samp_data->bin_pwr_sec80[idx] = *(binptr++); + } else { + SPECTRAL_MESSAGE_COPY_CHAR_ARRAY( + &samp_data->bin_pwr_sec80[0], + params->bin_pwr_data_sec80, + params->pwr_count_sec80); + } } - target_if_spectral_init_interf_list(data, params); - p_sops->get_mac_address(spectral, spec_samp_msg->macaddr); + if ((spectral->ch_width != CH_WIDTH_160MHZ) || + is_secondaryseg_rx_inprog(spectral)) { + if (spectral->send_phy_data(spectral->pdev_obj) == 0) + spectral->spectral_sent_msg++; + samp_msg_index++; + if (spectral->spectral_gen == SPECTRAL_GEN3) + clear_spectral_report_skb(spectral); + } - if (spectral->sc_spectral_noise_pwr_cal) - target_if_spectral_process_noise_pwr_report( - spectral, spec_samp_msg); - - if (spectral->send_phy_data(spectral->pdev_obj) == 0) - spectral->spectral_sent_msg++; - - samp_msg_index++; + /* Take care of state transitions for 160MHz/ 80p80 */ + if (spectral->spectral_gen == SPECTRAL_GEN3) + target_if_160mhz_delivery_state_change( + spectral, + SPECTRAL_REPORT_EVENT_DETECTORID_INVALID); } diff --git a/target_if/spectral/target_if_spectral_phyerr.c b/target_if/spectral/target_if_spectral_phyerr.c index 40ad99f69b01..5308127c3d40 100644 --- a/target_if/spectral/target_if_spectral_phyerr.c +++ b/target_if/spectral/target_if_spectral_phyerr.c @@ -1245,7 +1245,79 @@ target_if_dump_fft_report_gen3(struct target_if_spectral *spectral, return 0; } +QDF_STATUS +target_if_160mhz_delivery_state_change(struct target_if_spectral *spectral, + uint8_t detector_id) { + QDF_STATUS status = QDF_STATUS_SUCCESS; + + if (spectral->ch_width != CH_WIDTH_160MHZ) + return QDF_STATUS_E_FAILURE; + + switch (spectral->state_160mhz_delivery) { + case SPECTRAL_REPORT_WAIT_PRIMARY80: + if (detector_id == SPECTRAL_DETECTOR_PRIMARY) + spectral->state_160mhz_delivery = + SPECTRAL_REPORT_RX_PRIMARY80; + else { + status = QDF_STATUS_E_FAILURE; + spectral->diag_stats.spectral_vhtseg1id_mismatch++; + } + break; + + case SPECTRAL_REPORT_WAIT_SECONDARY80: + if (detector_id == SPECTRAL_DETECTOR_SECONDARY) + spectral->state_160mhz_delivery = + SPECTRAL_REPORT_RX_SECONDARY80; + else { + spectral->state_160mhz_delivery = + SPECTRAL_REPORT_WAIT_PRIMARY80; + status = QDF_STATUS_E_FAILURE; + spectral->diag_stats.spectral_vhtseg2id_mismatch++; + } + break; + + case SPECTRAL_REPORT_RX_SECONDARY80: + /* We don't care about detector id in this state */ + reset_160mhz_delivery_state_machine(spectral); + break; + + case SPECTRAL_REPORT_RX_PRIMARY80: + /* We don't care about detector id in this state */ + spectral->state_160mhz_delivery = + SPECTRAL_REPORT_WAIT_SECONDARY80; + break; + + default: + break; + } + + return status; +} + #ifdef DIRECT_BUF_RX_ENABLE +/** + * target_if_get_detector_id_sscan_report_gen3() - Get Spectral detector id + * @data: Pointer to Spectral summary report / Spectral + * search FFT report + * + * Get Spectral detector id from Spectral summary report / Spectral + * search FFT report + * + * Return: detector id + */ +static uint8_t +target_if_get_detector_id_sscan_report_gen3(uint8_t *data) { + struct spectral_sscan_report_gen3 *psscan_report; + uint8_t detector_id; + + psscan_report = (struct spectral_sscan_report_gen3 *)data; + detector_id = get_bitfield(psscan_report->hdr_a, + SSCAN_REPORT_DETECTOR_ID_SIZE_GEN3, + SSCAN_REPORT_DETECTOR_ID_POS_GEN3); + + return detector_id; +} + /** * target_if_consume_sscan_report_gen3() - Consume spectral summary report * @spectral: Pointer to spectral object @@ -1358,14 +1430,10 @@ target_if_consume_spectral_report_gen3( * */ uint64_t tsf64 = 0; - struct target_if_samp_msg_params params; + struct target_if_samp_msg_params params = {0}; struct spectral_search_fft_info_gen3 search_fft_info; struct spectral_search_fft_info_gen3 *p_sfft = &search_fft_info; - int8_t rssi_up = 0; - int8_t rssi_low = 0; int8_t chn_idx_lowest_enabled = 0; - uint8_t control_rssi = 0; - uint8_t extension_rssi = 0; int fft_hdr_length = 0; int report_len = 0; int fft_bin_len = 0; @@ -1377,143 +1445,140 @@ target_if_consume_spectral_report_gen3( struct wlan_objmgr_vdev *vdev; uint8_t vdev_rxchainmask; struct sscan_report_fields_gen3 sscan_report_fields; + uint8_t detector_id; + QDF_STATUS ret; - OS_MEMZERO(¶ms, sizeof(params)); - - if (target_if_verify_sig_and_tag_gen3( - spectral, data, - TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3) != 0) - goto fail; - target_if_consume_sscan_report_gen3(spectral, data, - &sscan_report_fields); - /* RSSI is in 1/2 dBm steps, Covert it to dBm scale */ - rssi = (sscan_report_fields.inband_pwr_db) >> 1; - params.agc_total_gain = sscan_report_fields.sscan_agc_total_gain; - params.gainchange = sscan_report_fields.sscan_gainchange; - /* Advance buf pointer to the search fft report */ - data += sizeof(struct spectral_sscan_report_gen3); - - if (target_if_verify_sig_and_tag_gen3( - spectral, data, - TLV_TAG_SEARCH_FFT_REPORT_GEN3) != 0) - goto fail; - p_fft_report = (struct spectral_phyerr_fft_report_gen3 *)data; - fft_hdr_length = p_fft_report->fft_hdr_length * 4; - if (fft_hdr_length < 16) { - spectral_err("Unexpected TLV length %u for FFT Report! Hexdump follows", - fft_hdr_length); - goto fail; - } - - report_len = (fft_hdr_length + 8); - - fft_bin_len = (fft_hdr_length - 16); - /* Divide fft bin length by 4 if fftbin_size_war is enabled */ - if (spectral->fftbin_size_war) { - fft_bin_len >>= 2; - } - if ((spectral->params.ss_rpt_mode == 2) && - spectral->inband_fftbin_size_adj) { - fft_bin_len >>= 1; - } - - tsf64 = p_fft_report->fft_timestamp; - - target_if_process_sfft_report_gen3(p_fft_report, p_sfft); - - if (p_sfft->fft_detector_id != 0) { - spectral_err("Expected segid is 0 but we got %d", - p_sfft->fft_detector_id); - spectral->diag_stats.spectral_vhtseg1id_mismatch++; - goto fail; - } - - if (spectral_debug_level & (DEBUG_SPECTRAL2 | DEBUG_SPECTRAL4)) - target_if_dump_fft_report_gen3(spectral, p_fft_report, p_sfft); - - if (spectral->upper_is_control) - rssi_up = control_rssi; - else - rssi_up = extension_rssi; - - if (spectral->lower_is_control) - rssi_low = control_rssi; - else - rssi_low = extension_rssi; - - params.rssi = rssi; - params.lower_rssi = rssi_low; - params.upper_rssi = rssi_up; - - if (spectral->sc_spectral_noise_pwr_cal) { - /* Fill 0's till FW provides them */ - params.chain_ctl_rssi[0] = 0; - params.chain_ctl_rssi[1] = 0; - params.chain_ctl_rssi[2] = 0; - params.chain_ext_rssi[0] = 0; - params.chain_ext_rssi[1] = 0; - params.chain_ext_rssi[2] = 0; - } - - vdev = target_if_spectral_get_vdev(spectral); - if (!vdev) - return -ENOENT; - - vdev_rxchainmask = - wlan_vdev_mlme_get_rxchainmask(vdev); - QDF_ASSERT(vdev_rxchainmask != 0); - wlan_objmgr_vdev_release_ref(vdev, - WLAN_SPECTRAL_ID); - - chn_idx_lowest_enabled = - target_if_spectral_get_lowest_chn_idx(vdev_rxchainmask); - if (chn_idx_lowest_enabled >= DBR_MAX_CHAINS) - return -EINVAL; - - control_rssi = 0; - extension_rssi = 0; - - params.bwinfo = 0; - params.tstamp = 0; - params.max_mag = p_sfft->fft_peak_mag; - - /* params.max_index = p_sfft->peak_inx; */ - params.max_exp = 0; - params.peak = 0; - params.bin_pwr_data = (uint8_t *)((uint8_t *)p_fft_report + - SPECTRAL_FFT_BINS_POS); - params.freq = p_sops->get_current_channel(spectral); - params.freq_loading = 0; - - params.interf_list.count = 0; - params.max_lower_index = 0; - params.max_upper_index = 0; - params.nb_lower = 0; - params.nb_upper = 0; - /* - * For modes upto VHT80, the noise floor is populated with the one - * corresponding - * to the highest enabled antenna chain - */ - /* TODO: Fill proper values once FW provides them*/ - params.noise_floor = report->noisefloor[chn_idx_lowest_enabled]; - params.datalen = (fft_hdr_length * 4); - params.pwr_count = fft_bin_len; - params.tstamp = (tsf64 & SPECTRAL_TSMASK); - - if (spectral->ch_width == CH_WIDTH_160MHZ) { - /* We expect to see one more Search FFT report, and it should be - * equal in size to the current one. - */ - /* Advance to the secondary 80 Mhz spectral report */ - data += report_len; - + if (is_primaryseg_expected(spectral)) { + /* Process Spectral scan summary report */ if (target_if_verify_sig_and_tag_gen3( spectral, data, - TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3) != 0) + TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3) != 0) { + spectral_err("Wrong tag/signature in sscan summary(0)"); goto fail; - target_if_consume_sscan_report_gen3(spectral, data, - &sscan_report_fields); + } + + detector_id = target_if_get_detector_id_sscan_report_gen3(data); + /* Agile detector is not supported */ + if (detector_id >= SPECTRAL_DETECTOR_AGILE) { + spectral->diag_stats.spectral_invalid_detector_id++; + spectral_err("Invalid detector id %u, expected is 0", + detector_id); + goto fail; + } + target_if_consume_sscan_report_gen3(spectral, data, + &sscan_report_fields); + /* RSSI is in 1/2 dBm steps, Covert it to dBm scale */ + rssi = (sscan_report_fields.inband_pwr_db) >> 1; + params.agc_total_gain = + sscan_report_fields.sscan_agc_total_gain; + params.gainchange = sscan_report_fields.sscan_gainchange; + /* Advance buf pointer to the search fft report */ + data += sizeof(struct spectral_sscan_report_gen3); + + /* Process Spectral search FFT report */ + if (target_if_verify_sig_and_tag_gen3( + spectral, data, + TLV_TAG_SEARCH_FFT_REPORT_GEN3) != 0) { + spectral_err("Unexpected tag/signature in sfft(0)"); + goto fail; + } + p_fft_report = (struct spectral_phyerr_fft_report_gen3 *)data; + fft_hdr_length = p_fft_report->fft_hdr_length * 4; + if (fft_hdr_length < 16) { + spectral_err("Wrong TLV length %u, detector id = %d", + fft_hdr_length, detector_id); + goto fail; + } + + report_len = (fft_hdr_length + 8); + fft_bin_len = (fft_hdr_length - 16); + /* Divide fft bin length by 4 if fftbin_size_war is enabled */ + if (spectral->fftbin_size_war) + fft_bin_len >>= 2; + if ((spectral->params.ss_rpt_mode == 2) && + spectral->inband_fftbin_size_adj) { + fft_bin_len >>= 1; + } + + tsf64 = p_fft_report->fft_timestamp; + target_if_process_sfft_report_gen3(p_fft_report, p_sfft); + detector_id = p_sfft->fft_detector_id; + /* Agile detector is not supported */ + if (detector_id >= SPECTRAL_DETECTOR_AGILE) { + spectral->diag_stats.spectral_invalid_detector_id++; + spectral_err("Invalid detector id %u, expected is 0", + detector_id); + goto fail; + } + + /* Take care of state transitions for 160 MHz and 80p80 */ + if (spectral->ch_width == CH_WIDTH_160MHZ) { + ret = target_if_160mhz_delivery_state_change( + spectral, + detector_id); + if (ret != QDF_STATUS_SUCCESS) + goto fail; + } + + if (spectral_debug_level & (DEBUG_SPECTRAL2 | DEBUG_SPECTRAL4)) + target_if_dump_fft_report_gen3(spectral, + p_fft_report, p_sfft); + + params.rssi = rssi; + + vdev = target_if_spectral_get_vdev(spectral); + if (!vdev) { + spectral_err("First vdev is NULL"); + goto fail; + } + vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev); + QDF_ASSERT(vdev_rxchainmask != 0); + wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); + + chn_idx_lowest_enabled = + target_if_spectral_get_lowest_chn_idx(vdev_rxchainmask); + if (chn_idx_lowest_enabled >= DBR_MAX_CHAINS) { + spectral_err("Invalid chain index, detector id = %u", + detector_id); + goto fail; + } + + params.max_mag = p_sfft->fft_peak_mag; + + params.bin_pwr_data = (uint8_t *)((uint8_t *)p_fft_report + + SPECTRAL_FFT_BINS_POS); + params.freq = p_sops->get_current_channel(spectral); + + /* + * For modes upto VHT80, the noise floor is populated with + * the one corresponding + * to the highest enabled antenna chain + */ + /* TODO: Fill proper values once FW provides them*/ + params.noise_floor = + report->noisefloor[chn_idx_lowest_enabled]; + params.datalen = (fft_hdr_length * 4); + params.pwr_count = fft_bin_len; + params.tstamp = (tsf64 & SPECTRAL_TSMASK); + } else if (is_secondaryseg_expected(spectral)) { + /* Process Spectral scan summary report */ + if (target_if_verify_sig_and_tag_gen3( + spectral, data, + TLV_TAG_SPECTRAL_SUMMARY_REPORT_GEN3) != 0) { + spectral_err("Wrong tag/signature in sscan summary(1)"); + goto fail; + } + + detector_id = target_if_get_detector_id_sscan_report_gen3(data); + /* Agile detector is not supported */ + if (detector_id >= SPECTRAL_DETECTOR_AGILE) { + spectral->diag_stats.spectral_invalid_detector_id++; + spectral_err("Invalid detector id %u, expected is 1", + detector_id); + goto fail; + } + target_if_consume_sscan_report_gen3(spectral, data, + &sscan_report_fields); /* RSSI is in 1/2 dBm steps, Covert it to dBm scale */ rssi = (sscan_report_fields.inband_pwr_db) >> 1; params.agc_total_gain_sec80 = @@ -1522,14 +1587,22 @@ target_if_consume_spectral_report_gen3( /* Advance buf pointer to the search fft report */ data += sizeof(struct spectral_sscan_report_gen3); + /* Process Spectral search FFT report */ if (target_if_verify_sig_and_tag_gen3( spectral, data, - TLV_TAG_SEARCH_FFT_REPORT_GEN3) != 0) + TLV_TAG_SEARCH_FFT_REPORT_GEN3) != 0) { + spectral_err("Unexpected tag/signature in sfft(1)"); goto fail; - p_fft_report = (struct spectral_phyerr_fft_report_gen3 *)(data); + } + p_fft_report = (struct spectral_phyerr_fft_report_gen3 *)data; fft_hdr_length = p_fft_report->fft_hdr_length * 4; - report_len = (fft_hdr_length + 8); + if (fft_hdr_length < 16) { + spectral_err("Wrong TLV length %u, detector id = %u", + fft_hdr_length, detector_id); + goto fail; + } + report_len = (fft_hdr_length + 8); fft_bin_len = (fft_hdr_length - 16); /* Divide fft bin length by 4 if fftbin_size_war is enabled */ if (spectral->fftbin_size_war) { @@ -1541,14 +1614,24 @@ target_if_consume_spectral_report_gen3( } target_if_process_sfft_report_gen3(p_fft_report, p_sfft); - - if (p_sfft->fft_detector_id != 1) { - spectral_err("Expected segid is 1 but we got %d", - p_sfft->fft_detector_id); - spectral->diag_stats.spectral_vhtseg2id_mismatch++; + detector_id = p_sfft->fft_detector_id; + /* Agile detector is not supported */ + if (detector_id >= SPECTRAL_DETECTOR_AGILE) { + spectral->diag_stats.spectral_invalid_detector_id++; + spectral_err("Invalid detector id %u, expected is 1", + detector_id); goto fail; } + /* Take care of state transitions for 160 MHz and 80p80 */ + if (spectral->ch_width == CH_WIDTH_160MHZ) { + ret = target_if_160mhz_delivery_state_change( + spectral, + detector_id); + if (ret != QDF_STATUS_SUCCESS) + goto fail; + } + if (spectral_debug_level & (DEBUG_SPECTRAL2 | DEBUG_SPECTRAL4)) target_if_dump_fft_report_gen3(spectral, p_fft_report, p_sfft); @@ -1556,29 +1639,39 @@ target_if_consume_spectral_report_gen3( params.vhtop_ch_freq_seg1 = 0; params.vhtop_ch_freq_seg2 = 0; - /* XXX: Confirm. TBD at SoD. */ params.rssi_sec80 = rssi; - /* XXX: Determine dynamically. TBD at SoD. */ + vdev = target_if_spectral_get_vdev(spectral); + if (!vdev) { + spectral_err("First vdev is NULL"); + goto fail; + } + vdev_rxchainmask = wlan_vdev_mlme_get_rxchainmask(vdev); + QDF_ASSERT(vdev_rxchainmask != 0); + wlan_objmgr_vdev_release_ref(vdev, WLAN_SPECTRAL_ID); - /* - * For VHT80_80/VHT160,the noise floor for primary 80MHz segment - * populated with the - * lowest enabled antenna chain and the nf for secondary 80MHz - * segment is populated - * with the highest enabled antenna chain - */ - /* TODO: Fill proper values once FW provides them*/ - params.noise_floor_sec80 = DUMMY_NF_VALUE; - params.noise_floor = DUMMY_NF_VALUE; + chn_idx_lowest_enabled = + target_if_spectral_get_lowest_chn_idx(vdev_rxchainmask); + if (chn_idx_lowest_enabled >= DBR_MAX_CHAINS) { + spectral_err("Invalid chain index"); + goto fail; + } + + /* Need to change this as per FW team's inputs */ + params.noise_floor_sec80 = + report->noisefloor[chn_idx_lowest_enabled]; params.max_mag_sec80 = p_sfft->fft_peak_mag; /* params.max_index_sec80 = p_sfft->peak_inx; */ /* XXX Does this definition of datalen *still hold? */ - params.datalen_sec80 = fft_hdr_length; + params.datalen_sec80 = fft_hdr_length * 4; params.pwr_count_sec80 = fft_bin_len; - params.bin_pwr_data_sec80 = (u_int8_t *)( - (uint8_t *)p_fft_report + SPECTRAL_FFT_BINS_POS); + params.bin_pwr_data_sec80 = + (uint8_t *)((uint8_t *)p_fft_report + + SPECTRAL_FFT_BINS_POS); + } else { + spectral_err("Spectral state machine in undefined state"); + goto fail; } qdf_mem_copy(¶ms.classifier_params, @@ -1591,7 +1684,8 @@ target_if_consume_spectral_report_gen3( return 0; fail: - spectral_err("Error in function while processing search fft report"); + spectral_err("Error while processing Spectral report"); + reset_160mhz_delivery_state_machine(spectral); return -EPERM; }