diff --git a/wmi_unified_api.c b/wmi_unified_api.c index 28e5ac0eb6..26b89f337e 100644 --- a/wmi_unified_api.c +++ b/wmi_unified_api.c @@ -7492,3 +7492,29 @@ QDF_STATUS wmi_extract_smartlog_ev(void *wmi_hdl, return QDF_STATUS_E_FAILURE; } #endif /* OL_ATH_SMART_LOGGING */ + +QDF_STATUS +wmi_unified_send_roam_scan_stats_cmd(void *wmi_hdl, + struct wmi_roam_scan_stats_req *params) +{ + wmi_unified_t wmi_handle = (wmi_unified_t)wmi_hdl; + + if (wmi_handle->ops->send_roam_scan_stats_cmd) + return wmi_handle->ops->send_roam_scan_stats_cmd(wmi_handle, + params); + + return QDF_STATUS_E_FAILURE; +} + +QDF_STATUS +wmi_extract_roam_scan_stats_res_evt(wmi_unified_t wmi, void *evt_buf, + uint32_t *vdev_id, + struct wmi_roam_scan_stats_res **res_param) +{ + if (wmi->ops->extract_roam_scan_stats_res_evt) + return wmi->ops->extract_roam_scan_stats_res_evt(wmi, + evt_buf, + vdev_id, res_param); + + return QDF_STATUS_E_FAILURE; +} diff --git a/wmi_unified_tlv.c b/wmi_unified_tlv.c index ae4e1db8f4..2bedad4587 100644 --- a/wmi_unified_tlv.c +++ b/wmi_unified_tlv.c @@ -21424,6 +21424,237 @@ static QDF_STATUS extract_obss_detection_info_tlv(uint8_t *evt_buf, return QDF_STATUS_SUCCESS; } +/** + * send_roam_scan_stats_cmd_tlv() - Send roam scan stats req command to fw + * @wmi_handle: wmi handle + * @params: pointer to request structure + * + * Return: QDF_STATUS + */ +static QDF_STATUS +send_roam_scan_stats_cmd_tlv(wmi_unified_t wmi_handle, + struct wmi_roam_scan_stats_req *params) +{ + wmi_buf_t buf; + wmi_request_roam_scan_stats_cmd_fixed_param *cmd; + WMITLV_TAG_ID tag; + uint32_t size; + uint32_t len = sizeof(*cmd); + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMI_LOGE(FL("Failed to allocate wmi buffer")); + return QDF_STATUS_E_FAILURE; + } + + cmd = (wmi_request_roam_scan_stats_cmd_fixed_param *)wmi_buf_data(buf); + + tag = WMITLV_TAG_STRUC_wmi_request_roam_scan_stats_cmd_fixed_param; + size = WMITLV_GET_STRUCT_TLVLEN( + wmi_request_roam_scan_stats_cmd_fixed_param); + WMITLV_SET_HDR(&cmd->tlv_header, tag, size); + + cmd->vdev_id = params->vdev_id; + + WMI_LOGD(FL("Roam Scan Stats Req vdev_id: %u"), cmd->vdev_id); + if (wmi_unified_cmd_send(wmi_handle, buf, len, + WMI_REQUEST_ROAM_SCAN_STATS_CMDID)) { + WMI_LOGE("%s: Failed to send WMI_REQUEST_ROAM_SCAN_STATS_CMDID", + __func__); + wmi_buf_free(buf); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * extract_roam_scan_stats_res_evt_tlv() - Extract roam scan stats event + * @wmi_handle: wmi handle + * @evt_buf: pointer to event buffer + * @vdev_id: output pointer to hold vdev id + * @res_param: output pointer to hold the allocated response + * + * Return: QDF_STATUS + */ +static QDF_STATUS +extract_roam_scan_stats_res_evt_tlv(wmi_unified_t wmi_handle, void *evt_buf, + uint32_t *vdev_id, + struct wmi_roam_scan_stats_res **res_param) +{ + WMI_ROAM_SCAN_STATS_EVENTID_param_tlvs *param_buf; + wmi_roam_scan_stats_event_fixed_param *fixed_param; + uint32_t *client_id = NULL; + wmi_roaming_timestamp *timestamp = NULL; + uint32_t *num_channels = NULL; + uint32_t *chan_info = NULL; + wmi_mac_addr *old_bssid = NULL; + uint32_t *is_roaming_success = NULL; + wmi_mac_addr *new_bssid = NULL; + uint32_t *num_roam_candidates = NULL; + wmi_roam_scan_trigger_reason *roam_reason = NULL; + wmi_mac_addr *bssid = NULL; + uint32_t *score = NULL; + uint32_t *channel = NULL; + uint32_t *rssi = NULL; + int chan_idx = 0, cand_idx = 0; + uint32_t total_len; + struct wmi_roam_scan_stats_res *res; + uint32_t i, j; + uint32_t num_scans; + + *res_param = NULL; + *vdev_id = 0xFF; /* Initialize to invalid vdev id */ + param_buf = (WMI_ROAM_SCAN_STATS_EVENTID_param_tlvs *)evt_buf; + if (!param_buf) { + WMI_LOGE(FL("Invalid roam scan stats event")); + return QDF_STATUS_E_INVAL; + } + + fixed_param = param_buf->fixed_param; + total_len = sizeof(*res) + fixed_param->num_roam_scans * + sizeof(struct wmi_roam_scan_stats_params); + + *vdev_id = fixed_param->vdev_id; + num_scans = fixed_param->num_roam_scans; + + res = qdf_mem_malloc(total_len); + if (!res) { + WMI_LOGE("Failed to allocate roam scan stats response memory"); + return QDF_STATUS_E_NOMEM; + } + + if (!num_scans) { + *res_param = res; + return QDF_STATUS_SUCCESS; + } + + if (param_buf->client_id && + param_buf->num_client_id == num_scans) + client_id = param_buf->client_id; + + if (param_buf->timestamp && + param_buf->num_timestamp == num_scans) + timestamp = param_buf->timestamp; + + if (param_buf->old_bssid && + param_buf->num_old_bssid == num_scans) + old_bssid = param_buf->old_bssid; + + if (param_buf->new_bssid && + param_buf->num_new_bssid == num_scans) + new_bssid = param_buf->new_bssid; + + if (param_buf->is_roaming_success && + param_buf->num_is_roaming_success == num_scans) + is_roaming_success = param_buf->is_roaming_success; + + if (param_buf->roam_reason && + param_buf->num_roam_reason == num_scans) + roam_reason = param_buf->roam_reason; + + if (param_buf->num_channels && + param_buf->num_num_channels == num_scans) { + uint32_t count, chan_info_sum = 0; + + num_channels = param_buf->num_channels; + for (count = 0; count < param_buf->num_num_channels; count++) + chan_info_sum += param_buf->num_channels[count]; + + if (param_buf->chan_info && + param_buf->num_chan_info == chan_info_sum) + chan_info = param_buf->chan_info; + } + + if (param_buf->num_roam_candidates && + param_buf->num_num_roam_candidates == num_scans) { + uint32_t count, roam_cand_sum = 0; + + num_roam_candidates = param_buf->num_roam_candidates; + for (count = 0; count < param_buf->num_num_roam_candidates; + count++) + roam_cand_sum += param_buf->num_roam_candidates[count]; + + if (param_buf->bssid && + param_buf->num_bssid == roam_cand_sum) + bssid = param_buf->bssid; + + if (param_buf->score && + param_buf->num_score == roam_cand_sum) + score = param_buf->score; + + if (param_buf->channel && + param_buf->num_channel == roam_cand_sum) + channel = param_buf->channel; + + if (param_buf->rssi && + param_buf->num_rssi == roam_cand_sum) + rssi = param_buf->rssi; + } + + res->num_roam_scans = num_scans; + for (i = 0; i < num_scans; i++) { + struct wmi_roam_scan_stats_params *roam = &res->roam_scan[i]; + + if (timestamp) + roam->time_stamp = timestamp[i].lower32bit | + (timestamp[i].upper32bit << 31); + + if (client_id) + roam->client_id = client_id[i]; + + if (num_channels) { + roam->num_scan_chans = num_channels[i]; + if (chan_info) { + for (j = 0; j < num_channels[i]; j++) + roam->scan_freqs[j] = + chan_info[chan_idx++]; + } + } + + if (is_roaming_success) + roam->is_roam_successful = is_roaming_success[i]; + + if (roam_reason) { + roam->trigger_id = roam_reason[i].trigger_id; + roam->trigger_value = roam_reason[i].trigger_value; + } + + if (num_roam_candidates) { + roam->num_roam_candidates = num_roam_candidates[i]; + + for (j = 0; j < num_roam_candidates[i]; j++) { + if (score) + roam->cand[j].score = score[cand_idx]; + if (rssi) + roam->cand[j].rssi = rssi[cand_idx]; + if (channel) + roam->cand[j].freq = + channel[cand_idx]; + + if (bssid) + WMI_MAC_ADDR_TO_CHAR_ARRAY( + &bssid[cand_idx], + roam->cand[j].bssid); + + cand_idx++; + } + } + + if (old_bssid) + WMI_MAC_ADDR_TO_CHAR_ARRAY(&old_bssid[i], + roam->old_bssid); + + if (new_bssid) + WMI_MAC_ADDR_TO_CHAR_ARRAY(&new_bssid[i], + roam->new_bssid); + } + + *res_param = res; + + return QDF_STATUS_SUCCESS; +} + /** * send_offload_11k_cmd_tlv() - send wmi cmd with 11k offload params * @wmi_handle: wmi handler @@ -22415,6 +22646,8 @@ struct wmi_ops tlv_ops = { #endif .extract_esp_estimation_ev_param = extract_esp_estimation_ev_param_tlv, + .send_roam_scan_stats_cmd = send_roam_scan_stats_cmd_tlv, + .extract_roam_scan_stats_res_evt = extract_roam_scan_stats_res_evt_tlv, }; /** @@ -22710,6 +22943,7 @@ static void populate_tlv_events_id(uint32_t *event_ids) WMI_BPF_GET_VDEV_WORK_MEMORY_RESP_EVENTID; event_ids[wmi_wlan_sar2_result_event_id] = WMI_SAR2_RESULT_EVENTID; event_ids[wmi_esp_estimate_event_id] = WMI_ESP_ESTIMATE_EVENTID; + event_ids[wmi_roam_scan_stats_event_id] = WMI_ROAM_SCAN_STATS_EVENTID; } /**