|
@@ -609,6 +609,107 @@ static int wma_unified_link_peer_stats_event_handler(void *handle,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * wma_unified_radio_tx_power_level_stats_event_handler() - tx power level stats
|
|
|
+ * @handle: WMI handle
|
|
|
+ * @cmd_param_info: command param info
|
|
|
+ * @len: Length of @cmd_param_info
|
|
|
+ *
|
|
|
+ * This is the WMI event handler function to receive radio stats tx
|
|
|
+ * power level stats.
|
|
|
+ *
|
|
|
+ * Return: 0 on success, error number otherwise.
|
|
|
+*/
|
|
|
+static int wma_unified_radio_tx_power_level_stats_event_handler(void *handle,
|
|
|
+ u_int8_t *cmd_param_info, u_int32_t len)
|
|
|
+{
|
|
|
+ tp_wma_handle wma_handle = (tp_wma_handle) handle;
|
|
|
+ WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *param_tlvs;
|
|
|
+ wmi_tx_power_level_stats_evt_fixed_param *fixed_param;
|
|
|
+ uint8_t *tx_power_level_values;
|
|
|
+ tSirLLStatsResults *link_stats_results;
|
|
|
+ tSirWifiRadioStat *rs_results;
|
|
|
+
|
|
|
+ tpAniSirGlobal mac = cds_get_context(QDF_MODULE_ID_PE);
|
|
|
+
|
|
|
+ if (!mac) {
|
|
|
+ WMA_LOGD("%s: NULL pMac ptr. Exiting", __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (!mac->sme.pLinkLayerStatsIndCallback) {
|
|
|
+ WMA_LOGD("%s: HDD callback is null", __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ param_tlvs = (WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID_param_tlvs *)cmd_param_info;
|
|
|
+ if (!param_tlvs) {
|
|
|
+ WMA_LOGA("%s: Invalid tx power level stats event", __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ fixed_param = param_tlvs->fixed_param;
|
|
|
+ if (!fixed_param) {
|
|
|
+ WMA_LOGA("%s: Invalid param_tlvs for Radio tx_power level Stats", __func__);
|
|
|
+ return -EINVAL;
|
|
|
+ }
|
|
|
+
|
|
|
+ link_stats_results = wma_handle->link_stats_results;
|
|
|
+ rs_results = (tSirWifiRadioStat *) &link_stats_results->results[0];
|
|
|
+ tx_power_level_values = (uint8_t *) param_tlvs->tx_time_per_power_level;
|
|
|
+
|
|
|
+ WMA_LOGD("%s: total_num_tx_power_levels: %u num_tx_power_levels: %u power_level_offset: %u",
|
|
|
+ __func__, fixed_param->total_num_tx_power_levels,
|
|
|
+ fixed_param->num_tx_power_levels,
|
|
|
+ fixed_param->power_level_offset);
|
|
|
+
|
|
|
+ rs_results->total_num_tx_power_levels =
|
|
|
+ fixed_param->total_num_tx_power_levels;
|
|
|
+ if (!rs_results->total_num_tx_power_levels)
|
|
|
+ goto post_stats;
|
|
|
+
|
|
|
+ if (!rs_results->tx_time_per_power_level) {
|
|
|
+ rs_results->tx_time_per_power_level = qdf_mem_malloc(
|
|
|
+ sizeof(uint32_t) *
|
|
|
+ rs_results->total_num_tx_power_levels);
|
|
|
+ if (!rs_results->tx_time_per_power_level) {
|
|
|
+ WMA_LOGA("%s: Mem alloc failed for tx power level stats", __func__);
|
|
|
+
|
|
|
+ * tx_power_level stats */
|
|
|
+ rs_results->total_num_tx_power_levels = 0;
|
|
|
+ goto post_stats;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ qdf_mem_copy(&rs_results->tx_time_per_power_level[fixed_param->power_level_offset],
|
|
|
+ tx_power_level_values,
|
|
|
+ sizeof(uint32_t) * fixed_param->num_tx_power_levels);
|
|
|
+ if (rs_results->total_num_tx_power_levels ==
|
|
|
+ (fixed_param->num_tx_power_levels + fixed_param->power_level_offset))
|
|
|
+ link_stats_results->moreResultToFollow = 0;
|
|
|
+
|
|
|
+ WMA_LOGD("%s: moreResultToFollow: %u",
|
|
|
+ __func__, link_stats_results->moreResultToFollow);
|
|
|
+
|
|
|
+
|
|
|
+ if (link_stats_results->moreResultToFollow)
|
|
|
+ return 0;
|
|
|
+
|
|
|
+post_stats:
|
|
|
+
|
|
|
+ * vdev_id/ifacId in link_stats_results will be
|
|
|
+ * used to retrieve the correct HDD context
|
|
|
+ */
|
|
|
+ mac->sme.pLinkLayerStatsIndCallback(mac->hHdd,
|
|
|
+ WMA_LINK_LAYER_STATS_RESULTS_RSP,
|
|
|
+ link_stats_results);
|
|
|
+ WMA_LOGD("%s: Radio Stats event posted to HDD", __func__);
|
|
|
+ qdf_mem_free(rs_results->tx_time_per_power_level);
|
|
|
+ qdf_mem_free(wma_handle->link_stats_results);
|
|
|
+ rs_results->tx_time_per_power_level = NULL;
|
|
|
+ wma_handle->link_stats_results = NULL;
|
|
|
+
|
|
|
+ return 0;
|
|
|
+}
|
|
|
|
|
|
|
|
|
* wma_unified_link_radio_stats_event_handler() - radio link stats event handler
|
|
@@ -622,15 +723,18 @@ static int wma_unified_link_radio_stats_event_handler(void *handle,
|
|
|
uint8_t *cmd_param_info,
|
|
|
uint32_t len)
|
|
|
{
|
|
|
+ tp_wma_handle wma_handle = (tp_wma_handle) handle;
|
|
|
WMI_RADIO_LINK_STATS_EVENTID_param_tlvs *param_tlvs;
|
|
|
wmi_radio_link_stats_event_fixed_param *fixed_param;
|
|
|
wmi_radio_link_stats *radio_stats;
|
|
|
wmi_channel_stats *channel_stats;
|
|
|
tSirLLStatsResults *link_stats_results;
|
|
|
uint8_t *results, *t_radio_stats, *t_channel_stats;
|
|
|
- uint32_t next_res_offset, next_chan_offset, count;
|
|
|
+ uint32_t next_chan_offset, count;
|
|
|
size_t radio_stats_size, chan_stats_size;
|
|
|
size_t link_stats_results_size;
|
|
|
+ tSirWifiRadioStat *rs_results;
|
|
|
+ tSirWifiChannelStats *chn_results;
|
|
|
|
|
|
tpAniSirGlobal pMac = cds_get_context(QDF_MODULE_ID_PE);
|
|
|
|
|
@@ -672,15 +776,14 @@ static int wma_unified_link_radio_stats_event_handler(void *handle,
|
|
|
link_stats_results_size = sizeof(*link_stats_results) +
|
|
|
radio_stats_size + (radio_stats->num_channels * chan_stats_size);
|
|
|
|
|
|
- link_stats_results = qdf_mem_malloc(link_stats_results_size);
|
|
|
- if (NULL == link_stats_results) {
|
|
|
+ wma_handle->link_stats_results = qdf_mem_malloc(link_stats_results_size);
|
|
|
+ if (NULL == wma_handle->link_stats_results) {
|
|
|
WMA_LOGD("%s: could not allocate mem for stats results-len %zu",
|
|
|
__func__, link_stats_results_size);
|
|
|
return -ENOMEM;
|
|
|
}
|
|
|
|
|
|
- WMA_LOGD("Radio stats from FW event buf");
|
|
|
- WMA_LOGD("Fixed Param:");
|
|
|
+ WMA_LOGD("Radio stats Fixed Param:");
|
|
|
WMA_LOGD("request_id %u num_radio %u more_radio_events %u",
|
|
|
fixed_param->request_id, fixed_param->num_radio,
|
|
|
fixed_param->more_radio_events);
|
|
@@ -696,6 +799,7 @@ static int wma_unified_link_radio_stats_event_handler(void *handle,
|
|
|
radio_stats->on_time_pno_scan,
|
|
|
radio_stats->on_time_hs20, radio_stats->num_channels);
|
|
|
|
|
|
+ link_stats_results = wma_handle->link_stats_results;
|
|
|
qdf_mem_zero(link_stats_results, link_stats_results_size);
|
|
|
|
|
|
link_stats_results->paramId = WMI_LINK_STATS_RADIO;
|
|
@@ -703,16 +807,37 @@ static int wma_unified_link_radio_stats_event_handler(void *handle,
|
|
|
link_stats_results->ifaceId = 0;
|
|
|
link_stats_results->num_radio = fixed_param->num_radio;
|
|
|
link_stats_results->peer_event_number = 0;
|
|
|
+
|
|
|
+
|
|
|
+ * Backward compatibility:
|
|
|
+ * There are firmware(s) which will send Radio stats only with
|
|
|
+ * more_radio_events set to 0 and firmware which sends Radio stats
|
|
|
+ * followed by tx_power level stats with more_radio_events set to 1.
|
|
|
+ * if more_radio_events is set to 1, buffer the radio stats and
|
|
|
+ * wait for tx_power_level stats.
|
|
|
+ */
|
|
|
link_stats_results->moreResultToFollow = fixed_param->more_radio_events;
|
|
|
|
|
|
results = (uint8_t *) link_stats_results->results;
|
|
|
t_radio_stats = (uint8_t *) radio_stats;
|
|
|
t_channel_stats = (uint8_t *) channel_stats;
|
|
|
|
|
|
- qdf_mem_copy(results, t_radio_stats + WMI_TLV_HDR_SIZE,
|
|
|
- radio_stats_size);
|
|
|
-
|
|
|
- next_res_offset = radio_stats_size;
|
|
|
+ rs_results = (tSirWifiRadioStat *) &results[0];
|
|
|
+ rs_results->radio = radio_stats->radio_id;
|
|
|
+ rs_results->onTime = radio_stats->on_time;
|
|
|
+ rs_results->txTime = radio_stats->tx_time;
|
|
|
+ rs_results->rxTime = radio_stats->rx_time;
|
|
|
+ rs_results->onTimeScan = radio_stats->on_time_scan;
|
|
|
+ rs_results->onTimeNbd = radio_stats->on_time_nbd;
|
|
|
+ rs_results->onTimeGscan = radio_stats->on_time_gscan;
|
|
|
+ rs_results->onTimeRoamScan = radio_stats->on_time_roam_scan;
|
|
|
+ rs_results->onTimePnoScan = radio_stats->on_time_pno_scan;
|
|
|
+ rs_results->onTimeHs20 = radio_stats->on_time_hs20;
|
|
|
+ rs_results->total_num_tx_power_levels = 0;
|
|
|
+ rs_results->tx_time_per_power_level = NULL;
|
|
|
+ rs_results->numChannels = radio_stats->num_channels;
|
|
|
+
|
|
|
+ chn_results = (tSirWifiChannelStats *) &rs_results->channels[0];
|
|
|
next_chan_offset = WMI_TLV_HDR_SIZE;
|
|
|
WMA_LOGD("Channel Stats Info");
|
|
|
for (count = 0; count < radio_stats->num_channels; count++) {
|
|
@@ -726,21 +851,23 @@ static int wma_unified_link_radio_stats_event_handler(void *handle,
|
|
|
channel_stats->cca_busy_time);
|
|
|
channel_stats++;
|
|
|
|
|
|
- qdf_mem_copy(results + next_res_offset,
|
|
|
+ qdf_mem_copy(chn_results,
|
|
|
t_channel_stats + next_chan_offset,
|
|
|
chan_stats_size);
|
|
|
- next_res_offset += chan_stats_size;
|
|
|
+ chn_results++;
|
|
|
next_chan_offset += sizeof(*channel_stats);
|
|
|
}
|
|
|
|
|
|
-
|
|
|
- * vdev_id/ifacId in link_stats_results will be
|
|
|
- * used to retrieve the correct HDD context
|
|
|
- */
|
|
|
+ if (link_stats_results->moreResultToFollow) {
|
|
|
+
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
pMac->sme.pLinkLayerStatsIndCallback(pMac->hHdd,
|
|
|
WMA_LINK_LAYER_STATS_RESULTS_RSP,
|
|
|
link_stats_results);
|
|
|
- qdf_mem_free(link_stats_results);
|
|
|
+ qdf_mem_free(wma_handle->link_stats_results);
|
|
|
+ wma_handle->link_stats_results = NULL;
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
@@ -771,6 +898,10 @@ void wma_register_ll_stats_event_handler(tp_wma_handle wma_handle)
|
|
|
WMI_RADIO_LINK_STATS_EVENTID,
|
|
|
wma_unified_link_radio_stats_event_handler,
|
|
|
WMA_RX_SERIALIZER_CTX);
|
|
|
+ wmi_unified_register_event_handler(wma_handle->wmi_handle,
|
|
|
+ WMI_RADIO_TX_POWER_LEVEL_STATS_EVENTID,
|
|
|
+ wma_unified_radio_tx_power_level_stats_event_handler,
|
|
|
+ WMA_RX_SERIALIZER_CTX);
|
|
|
|
|
|
return;
|
|
|
}
|