1 /* 2 * Copyright (c) 2013-2021, The Linux Foundation. All rights reserved. 3 * Copyright (c) 2021-2024 Qualcomm Innovation Center, Inc. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 /** 19 * DOC: Implement API's specific to roaming component. 20 */ 21 22 #include <wmi_unified_priv.h> 23 #include <wmi_unified_roam_api.h> 24 #include <wmi_unified_roam_param.h> 25 #include "wmi.h" 26 #include "wlan_roam_debug.h" 27 #include "ol_defines.h" 28 #include "wlan_cm_roam_api.h" 29 #include "wlan_mlme_api.h" 30 #include "wlan_crypto_global_api.h" 31 32 #define WMI_MAC_TO_PDEV_MAP(x) ((x) + (1)) 33 #define WMI_PDEV_TO_MAC_MAP(x) ((x) - (1)) 34 35 #ifdef FEATURE_LFR_SUBNET_DETECTION 36 /** 37 * send_set_gateway_params_cmd_tlv() - set gateway parameters 38 * @wmi_handle: wmi handle 39 * @req: gateway parameter update request structure 40 * 41 * This function reads the incoming @req and fill in the destination 42 * WMI structure and sends down the gateway configs down to the firmware 43 * 44 * Return: QDF_STATUS 45 */ 46 static QDF_STATUS send_set_gateway_params_cmd_tlv(wmi_unified_t wmi_handle, 47 struct gateway_update_req_param *req) 48 { 49 wmi_roam_subnet_change_config_fixed_param *cmd; 50 wmi_buf_t buf; 51 QDF_STATUS ret; 52 int len = sizeof(*cmd); 53 54 buf = wmi_buf_alloc(wmi_handle, len); 55 if (!buf) 56 return QDF_STATUS_E_NOMEM; 57 58 cmd = (wmi_roam_subnet_change_config_fixed_param *)wmi_buf_data(buf); 59 WMITLV_SET_HDR(&cmd->tlv_header, 60 WMITLV_TAG_STRUC_wmi_roam_subnet_change_config_fixed_param, 61 WMITLV_GET_STRUCT_TLVLEN( 62 wmi_roam_subnet_change_config_fixed_param)); 63 64 cmd->vdev_id = req->vdev_id; 65 qdf_mem_copy(&cmd->inet_gw_ip_v4_addr, req->ipv4_addr, 66 QDF_IPV4_ADDR_SIZE); 67 qdf_mem_copy(&cmd->inet_gw_ip_v6_addr, req->ipv6_addr, 68 QDF_IPV6_ADDR_SIZE); 69 WMI_CHAR_ARRAY_TO_MAC_ADDR(req->gw_mac_addr.bytes, 70 &cmd->inet_gw_mac_addr); 71 cmd->max_retries = req->max_retries; 72 cmd->timeout = req->timeout; 73 cmd->num_skip_subnet_change_detection_bssid_list = 0; 74 cmd->flag = 0; 75 if (req->ipv4_addr_type) 76 WMI_SET_ROAM_SUBNET_CHANGE_FLAG_IP4_ENABLED(cmd->flag); 77 78 if (req->ipv6_addr_type) 79 WMI_SET_ROAM_SUBNET_CHANGE_FLAG_IP6_ENABLED(cmd->flag); 80 81 wmi_mtrace(WMI_ROAM_SUBNET_CHANGE_CONFIG_CMDID, cmd->vdev_id, 0); 82 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 83 WMI_ROAM_SUBNET_CHANGE_CONFIG_CMDID); 84 if (QDF_IS_STATUS_ERROR(ret)) { 85 wmi_err("Failed to send gw config parameter to fw, ret: %d", 86 ret); 87 wmi_buf_free(buf); 88 } 89 90 return ret; 91 } 92 93 void wmi_lfr_subnet_detection_attach_tlv(struct wmi_unified *wmi_handle) 94 { 95 struct wmi_ops *ops = wmi_handle->ops; 96 97 ops->send_set_gateway_params_cmd = send_set_gateway_params_cmd_tlv; 98 } 99 #endif /* FEATURE_LFR_SUBNET_DETECTION */ 100 101 #ifdef FEATURE_RSSI_MONITOR 102 /** 103 * send_set_rssi_monitoring_cmd_tlv() - set rssi monitoring 104 * @wmi_handle: wmi handle 105 * @req: rssi monitoring request structure 106 * 107 * This function reads the incoming @req and fill in the destination 108 * WMI structure and send down the rssi monitoring configs down to the firmware 109 * 110 * Return: 0 on success; error number otherwise 111 */ 112 static QDF_STATUS send_set_rssi_monitoring_cmd_tlv(wmi_unified_t wmi_handle, 113 struct rssi_monitor_param *req) 114 { 115 wmi_rssi_breach_monitor_config_fixed_param *cmd; 116 wmi_buf_t buf; 117 QDF_STATUS ret; 118 uint32_t len = sizeof(*cmd); 119 120 buf = wmi_buf_alloc(wmi_handle, len); 121 if (!buf) 122 return QDF_STATUS_E_NOMEM; 123 124 cmd = (wmi_rssi_breach_monitor_config_fixed_param *)wmi_buf_data(buf); 125 WMITLV_SET_HDR(&cmd->tlv_header, 126 WMITLV_TAG_STRUC_wmi_rssi_breach_monitor_config_fixed_param, 127 WMITLV_GET_STRUCT_TLVLEN( 128 wmi_rssi_breach_monitor_config_fixed_param)); 129 130 cmd->vdev_id = req->vdev_id; 131 cmd->request_id = req->request_id; 132 cmd->lo_rssi_reenable_hysteresis = 0; 133 cmd->hi_rssi_reenable_histeresis = 0; 134 cmd->min_report_interval = 0; 135 cmd->max_num_report = 1; 136 if (req->control) { 137 /* enable one threshold for each min/max */ 138 cmd->enabled_bitmap = 0x09; 139 cmd->low_rssi_breach_threshold[0] = req->min_rssi; 140 cmd->hi_rssi_breach_threshold[0] = req->max_rssi; 141 } else { 142 cmd->enabled_bitmap = 0; 143 cmd->low_rssi_breach_threshold[0] = 0; 144 cmd->hi_rssi_breach_threshold[0] = 0; 145 } 146 147 wmi_mtrace(WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID, cmd->vdev_id, 0); 148 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 149 WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID); 150 if (QDF_IS_STATUS_ERROR(ret)) { 151 wmi_err("Failed to send WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID"); 152 wmi_buf_free(buf); 153 } 154 155 wmi_debug("Sent WMI_RSSI_BREACH_MONITOR_CONFIG_CMDID to FW"); 156 157 return ret; 158 } 159 160 void wmi_rssi_monitor_attach_tlv(struct wmi_unified *wmi_handle) 161 { 162 struct wmi_ops *ops = wmi_handle->ops; 163 164 ops->send_set_rssi_monitoring_cmd = send_set_rssi_monitoring_cmd_tlv; 165 } 166 #endif /* FEATURE_RSSI_MONITOR */ 167 168 /** 169 * send_roam_scan_offload_rssi_thresh_cmd_tlv() - set scan offload 170 * rssi threshold 171 * @wmi_handle: wmi handle 172 * @roam_req: Roaming request buffer 173 * 174 * Send WMI_ROAM_SCAN_RSSI_THRESHOLD TLV to firmware 175 * 176 * Return: QDF status 177 */ 178 static QDF_STATUS send_roam_scan_offload_rssi_thresh_cmd_tlv( 179 wmi_unified_t wmi_handle, 180 struct wlan_roam_offload_scan_rssi_params *roam_req) 181 { 182 wmi_buf_t buf = NULL; 183 QDF_STATUS status; 184 int len; 185 uint8_t *buf_ptr; 186 wmi_roam_scan_rssi_threshold_fixed_param *rssi_threshold_fp; 187 wmi_roam_scan_extended_threshold_param *ext_thresholds = NULL; 188 wmi_roam_earlystop_rssi_thres_param *early_stop_thresholds = NULL; 189 wmi_roam_dense_thres_param *dense_thresholds = NULL; 190 wmi_roam_bg_scan_roaming_param *bg_scan_params = NULL; 191 wmi_roam_data_rssi_roaming_param *data_rssi_param = NULL; 192 193 len = sizeof(wmi_roam_scan_rssi_threshold_fixed_param); 194 len += WMI_TLV_HDR_SIZE; /* TLV for ext_thresholds*/ 195 len += sizeof(wmi_roam_scan_extended_threshold_param); 196 len += WMI_TLV_HDR_SIZE; 197 len += sizeof(wmi_roam_earlystop_rssi_thres_param); 198 len += WMI_TLV_HDR_SIZE; /* TLV for dense thresholds*/ 199 len += sizeof(wmi_roam_dense_thres_param); 200 len += WMI_TLV_HDR_SIZE; /* TLV for BG Scan*/ 201 len += sizeof(wmi_roam_bg_scan_roaming_param); 202 len += WMI_TLV_HDR_SIZE; /* TLV for data RSSI*/ 203 len += sizeof(wmi_roam_data_rssi_roaming_param); 204 buf = wmi_buf_alloc(wmi_handle, len); 205 if (!buf) 206 return QDF_STATUS_E_NOMEM; 207 208 buf_ptr = (uint8_t *)wmi_buf_data(buf); 209 rssi_threshold_fp = 210 (wmi_roam_scan_rssi_threshold_fixed_param *)buf_ptr; 211 WMITLV_SET_HDR( 212 &rssi_threshold_fp->tlv_header, 213 WMITLV_TAG_STRUC_wmi_roam_scan_rssi_threshold_fixed_param, 214 WMITLV_GET_STRUCT_TLVLEN 215 (wmi_roam_scan_rssi_threshold_fixed_param)); 216 /* fill in threshold values */ 217 rssi_threshold_fp->vdev_id = roam_req->vdev_id; 218 rssi_threshold_fp->roam_scan_rssi_thresh = roam_req->rssi_thresh; 219 rssi_threshold_fp->roam_rssi_thresh_diff = roam_req->rssi_thresh_diff; 220 rssi_threshold_fp->hirssi_scan_max_count = 221 roam_req->hi_rssi_scan_max_count; 222 rssi_threshold_fp->hirssi_scan_delta = 223 roam_req->hi_rssi_scan_rssi_delta; 224 rssi_threshold_fp->hirssi_upper_bound = roam_req->hi_rssi_scan_rssi_ub; 225 rssi_threshold_fp->rssi_thresh_offset_5g = 226 roam_req->rssi_thresh_offset_5g; 227 rssi_threshold_fp->flags = roam_req->flags; 228 229 buf_ptr += sizeof(wmi_roam_scan_rssi_threshold_fixed_param); 230 WMITLV_SET_HDR(buf_ptr, 231 WMITLV_TAG_ARRAY_STRUC, 232 sizeof(wmi_roam_scan_extended_threshold_param)); 233 buf_ptr += WMI_TLV_HDR_SIZE; 234 ext_thresholds = (wmi_roam_scan_extended_threshold_param *)buf_ptr; 235 236 ext_thresholds->penalty_threshold_5g = roam_req->penalty_threshold_5g; 237 if (roam_req->raise_rssi_thresh_5g >= WMI_NOISE_FLOOR_DBM_DEFAULT) 238 ext_thresholds->boost_threshold_5g = 239 roam_req->boost_threshold_5g; 240 241 ext_thresholds->boost_algorithm_5g = 242 WMI_ROAM_5G_BOOST_PENALIZE_ALGO_LINEAR; 243 ext_thresholds->boost_factor_5g = roam_req->raise_factor_5g; 244 ext_thresholds->penalty_algorithm_5g = 245 WMI_ROAM_5G_BOOST_PENALIZE_ALGO_LINEAR; 246 ext_thresholds->penalty_factor_5g = roam_req->drop_factor_5g; 247 ext_thresholds->max_boost_5g = roam_req->max_raise_rssi_5g; 248 ext_thresholds->max_penalty_5g = roam_req->max_drop_rssi_5g; 249 ext_thresholds->good_rssi_threshold = roam_req->good_rssi_threshold; 250 251 WMITLV_SET_HDR(&ext_thresholds->tlv_header, 252 WMITLV_TAG_STRUC_wmi_roam_scan_extended_threshold_param, 253 WMITLV_GET_STRUCT_TLVLEN 254 (wmi_roam_scan_extended_threshold_param)); 255 buf_ptr += sizeof(wmi_roam_scan_extended_threshold_param); 256 WMITLV_SET_HDR(buf_ptr, 257 WMITLV_TAG_ARRAY_STRUC, 258 sizeof(wmi_roam_earlystop_rssi_thres_param)); 259 buf_ptr += WMI_TLV_HDR_SIZE; 260 early_stop_thresholds = (wmi_roam_earlystop_rssi_thres_param *)buf_ptr; 261 early_stop_thresholds->roam_earlystop_thres_min = 262 roam_req->roam_earlystop_thres_min; 263 early_stop_thresholds->roam_earlystop_thres_max = 264 roam_req->roam_earlystop_thres_max; 265 WMITLV_SET_HDR(&early_stop_thresholds->tlv_header, 266 WMITLV_TAG_STRUC_wmi_roam_earlystop_rssi_thres_param, 267 WMITLV_GET_STRUCT_TLVLEN 268 (wmi_roam_earlystop_rssi_thres_param)); 269 270 buf_ptr += sizeof(wmi_roam_earlystop_rssi_thres_param); 271 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 272 sizeof(wmi_roam_dense_thres_param)); 273 buf_ptr += WMI_TLV_HDR_SIZE; 274 dense_thresholds = (wmi_roam_dense_thres_param *)buf_ptr; 275 dense_thresholds->roam_dense_rssi_thres_offset = 276 roam_req->dense_rssi_thresh_offset; 277 dense_thresholds->roam_dense_min_aps = roam_req->dense_min_aps_cnt; 278 dense_thresholds->roam_dense_traffic_thres = 279 roam_req->traffic_threshold; 280 dense_thresholds->roam_dense_status = roam_req->initial_dense_status; 281 WMITLV_SET_HDR(&dense_thresholds->tlv_header, 282 WMITLV_TAG_STRUC_wmi_roam_dense_thres_param, 283 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_dense_thres_param)); 284 285 buf_ptr += sizeof(wmi_roam_dense_thres_param); 286 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 287 sizeof(wmi_roam_bg_scan_roaming_param)); 288 buf_ptr += WMI_TLV_HDR_SIZE; 289 bg_scan_params = (wmi_roam_bg_scan_roaming_param *)buf_ptr; 290 bg_scan_params->roam_bg_scan_bad_rssi_thresh = 291 roam_req->bg_scan_bad_rssi_thresh; 292 bg_scan_params->roam_bg_scan_client_bitmap = 293 roam_req->bg_scan_client_bitmap; 294 bg_scan_params->bad_rssi_thresh_offset_2g = 295 roam_req->roam_bad_rssi_thresh_offset_2g; 296 297 bg_scan_params->flags = 0; 298 if (roam_req->roam_bad_rssi_thresh_offset_2g) 299 bg_scan_params->flags |= WMI_ROAM_BG_SCAN_FLAGS_2G_TO_5G_ONLY; 300 WMITLV_SET_HDR(&bg_scan_params->tlv_header, 301 WMITLV_TAG_STRUC_wmi_roam_bg_scan_roaming_param, 302 WMITLV_GET_STRUCT_TLVLEN 303 (wmi_roam_bg_scan_roaming_param)); 304 305 buf_ptr += sizeof(wmi_roam_bg_scan_roaming_param); 306 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 307 sizeof(wmi_roam_data_rssi_roaming_param)); 308 buf_ptr += WMI_TLV_HDR_SIZE; 309 data_rssi_param = (wmi_roam_data_rssi_roaming_param *)buf_ptr; 310 data_rssi_param->flags = 311 roam_req->roam_data_rssi_threshold_triggers; 312 data_rssi_param->roam_data_rssi_thres = 313 roam_req->roam_data_rssi_threshold; 314 data_rssi_param->rx_inactivity_ms = 315 roam_req->rx_data_inactivity_time; 316 WMITLV_SET_HDR(&data_rssi_param->tlv_header, 317 WMITLV_TAG_STRUC_wmi_roam_data_rssi_roaming_param, 318 WMITLV_GET_STRUCT_TLVLEN 319 (wmi_roam_data_rssi_roaming_param)); 320 wmi_debug("vdev %d Data rssi threshold: %d, triggers: 0x%x, rx time: %d, rssi_thresh:%d", 321 rssi_threshold_fp->vdev_id, 322 data_rssi_param->roam_data_rssi_thres, 323 data_rssi_param->flags, 324 data_rssi_param->rx_inactivity_ms, 325 rssi_threshold_fp->roam_scan_rssi_thresh); 326 327 wmi_mtrace(WMI_ROAM_SCAN_RSSI_THRESHOLD, NO_SESSION, 0); 328 status = wmi_unified_cmd_send(wmi_handle, buf, 329 len, WMI_ROAM_SCAN_RSSI_THRESHOLD); 330 if (QDF_IS_STATUS_ERROR(status)) { 331 wmi_err("cmd WMI_ROAM_SCAN_RSSI_THRESHOLD returned Error %d", 332 status); 333 wmi_buf_free(buf); 334 } 335 336 return status; 337 } 338 339 /** 340 * send_roam_scan_offload_scan_period_cmd_tlv() - set roam offload scan period 341 * @wmi_handle: wmi handle 342 * @param: roam scan parameters to be sent to firmware 343 * 344 * Send WMI_ROAM_SCAN_PERIOD parameters to fw. 345 * 346 * Return: QDF status 347 */ 348 static QDF_STATUS 349 send_roam_scan_offload_scan_period_cmd_tlv( 350 wmi_unified_t wmi_handle, 351 struct wlan_roam_scan_period_params *param) 352 { 353 QDF_STATUS status; 354 wmi_buf_t buf = NULL; 355 int len; 356 uint8_t *buf_ptr; 357 wmi_roam_scan_period_fixed_param *scan_period_fp; 358 359 /* Send scan period values */ 360 len = sizeof(wmi_roam_scan_period_fixed_param); 361 buf = wmi_buf_alloc(wmi_handle, len); 362 if (!buf) 363 return QDF_STATUS_E_NOMEM; 364 365 buf_ptr = (uint8_t *)wmi_buf_data(buf); 366 scan_period_fp = (wmi_roam_scan_period_fixed_param *)buf_ptr; 367 WMITLV_SET_HDR(&scan_period_fp->tlv_header, 368 WMITLV_TAG_STRUC_wmi_roam_scan_period_fixed_param, 369 WMITLV_GET_STRUCT_TLVLEN 370 (wmi_roam_scan_period_fixed_param)); 371 /* fill in scan period values */ 372 scan_period_fp->vdev_id = param->vdev_id; 373 scan_period_fp->roam_scan_period = param->scan_period; 374 scan_period_fp->roam_scan_age = param->scan_age; 375 scan_period_fp->inactivity_time_period = 376 param->roam_scan_inactivity_time; 377 scan_period_fp->roam_inactive_count = 378 param->roam_inactive_data_packet_count; 379 /* Firmware expects the full scan period in msec whereas host 380 * provides the same in seconds. 381 * Convert it to msec and send to firmware 382 */ 383 scan_period_fp->roam_full_scan_period = param->full_scan_period * 1000; 384 385 wmi_debug("roam_scan_period=%d, roam_scan_age=%d, full_scan_period= %u", 386 scan_period_fp->roam_scan_period, 387 scan_period_fp->roam_scan_age, 388 scan_period_fp->roam_full_scan_period); 389 390 wmi_debug("inactiviy time:%d inactive cnt:%d", 391 scan_period_fp->inactivity_time_period, 392 scan_period_fp->roam_inactive_count); 393 394 wmi_mtrace(WMI_ROAM_SCAN_PERIOD, NO_SESSION, 0); 395 status = wmi_unified_cmd_send(wmi_handle, buf, len, 396 WMI_ROAM_SCAN_PERIOD); 397 if (QDF_IS_STATUS_ERROR(status)) { 398 wmi_buf_free(buf); 399 return status; 400 } 401 402 return QDF_STATUS_SUCCESS; 403 } 404 405 static QDF_STATUS send_roam_mawc_params_cmd_tlv( 406 wmi_unified_t wmi_handle, 407 struct wlan_roam_mawc_params *params) 408 { 409 wmi_buf_t buf = NULL; 410 QDF_STATUS status; 411 int len; 412 uint8_t *buf_ptr; 413 wmi_roam_configure_mawc_cmd_fixed_param *wmi_roam_mawc_params; 414 415 len = sizeof(*wmi_roam_mawc_params); 416 buf = wmi_buf_alloc(wmi_handle, len); 417 if (!buf) 418 return QDF_STATUS_E_NOMEM; 419 420 buf_ptr = (uint8_t *)wmi_buf_data(buf); 421 wmi_roam_mawc_params = 422 (wmi_roam_configure_mawc_cmd_fixed_param *)buf_ptr; 423 WMITLV_SET_HDR(&wmi_roam_mawc_params->tlv_header, 424 WMITLV_TAG_STRUC_wmi_roam_configure_mawc_cmd_fixed_param, 425 WMITLV_GET_STRUCT_TLVLEN 426 (wmi_roam_configure_mawc_cmd_fixed_param)); 427 wmi_roam_mawc_params->vdev_id = params->vdev_id; 428 if (params->enable) 429 wmi_roam_mawc_params->enable = 1; 430 else 431 wmi_roam_mawc_params->enable = 0; 432 wmi_roam_mawc_params->traffic_load_threshold = 433 params->traffic_load_threshold; 434 wmi_roam_mawc_params->best_ap_rssi_threshold = 435 params->best_ap_rssi_threshold; 436 wmi_roam_mawc_params->rssi_stationary_high_adjust = 437 params->rssi_stationary_high_adjust; 438 wmi_roam_mawc_params->rssi_stationary_low_adjust = 439 params->rssi_stationary_low_adjust; 440 wmi_debug("MAWC roam en=%d, vdev=%d, tr=%d, ap=%d, high=%d, low=%d", 441 wmi_roam_mawc_params->enable, wmi_roam_mawc_params->vdev_id, 442 wmi_roam_mawc_params->traffic_load_threshold, 443 wmi_roam_mawc_params->best_ap_rssi_threshold, 444 wmi_roam_mawc_params->rssi_stationary_high_adjust, 445 wmi_roam_mawc_params->rssi_stationary_low_adjust); 446 447 wmi_mtrace(WMI_ROAM_CONFIGURE_MAWC_CMDID, NO_SESSION, 0); 448 status = wmi_unified_cmd_send(wmi_handle, buf, 449 len, WMI_ROAM_CONFIGURE_MAWC_CMDID); 450 if (QDF_IS_STATUS_ERROR(status)) { 451 wmi_err("WMI_ROAM_CONFIGURE_MAWC_CMDID failed, Error %d", 452 status); 453 wmi_buf_free(buf); 454 return status; 455 } 456 457 return QDF_STATUS_SUCCESS; 458 } 459 460 /** 461 * send_roam_scan_filter_cmd_tlv() - Filter to be applied while roaming 462 * @wmi_handle: wmi handle 463 * @roam_req: Request which contains the filters 464 * 465 * There are filters such as allowlist, denylist and preferred 466 * list that need to be applied to the scan results to form the 467 * probable candidates for roaming. 468 * 469 * Return: Return success upon successfully passing the 470 * parameters to the firmware, otherwise failure. 471 */ 472 static QDF_STATUS send_roam_scan_filter_cmd_tlv(wmi_unified_t wmi_handle, 473 struct roam_scan_filter_params *roam_req) 474 { 475 wmi_buf_t buf = NULL; 476 QDF_STATUS status; 477 uint32_t i; 478 uint32_t len, blist_len = 0; 479 uint8_t *buf_ptr; 480 wmi_roam_filter_fixed_param *roam_filter; 481 uint8_t *bssid_src_ptr = NULL; 482 wmi_mac_addr *bssid_dst_ptr = NULL; 483 wmi_ssid *ssid_ptr = NULL; 484 uint32_t *bssid_preferred_factor_ptr = NULL; 485 wmi_roam_lca_disallow_config_tlv_param *blist_param; 486 wmi_roam_rssi_rejection_oce_config_param *rssi_rej; 487 488 len = sizeof(wmi_roam_filter_fixed_param); 489 490 len += WMI_TLV_HDR_SIZE; 491 if (roam_req->num_bssid_deny_list) 492 len += roam_req->num_bssid_deny_list * sizeof(wmi_mac_addr); 493 len += WMI_TLV_HDR_SIZE; 494 if (roam_req->num_ssid_allow_list) 495 len += roam_req->num_ssid_allow_list * sizeof(wmi_ssid); 496 len += 2 * WMI_TLV_HDR_SIZE; 497 if (roam_req->num_bssid_preferred_list) { 498 len += (roam_req->num_bssid_preferred_list * 499 sizeof(wmi_mac_addr)); 500 len += roam_req->num_bssid_preferred_list * sizeof(uint32_t); 501 } 502 len += WMI_TLV_HDR_SIZE; 503 if (roam_req->lca_disallow_config_present) { 504 len += sizeof(*blist_param); 505 blist_len = sizeof(*blist_param); 506 } 507 508 len += WMI_TLV_HDR_SIZE; 509 if (roam_req->num_rssi_rejection_ap) 510 len += roam_req->num_rssi_rejection_ap * sizeof(*rssi_rej); 511 512 buf = wmi_buf_alloc(wmi_handle, len); 513 if (!buf) 514 return QDF_STATUS_E_NOMEM; 515 516 buf_ptr = (u_int8_t *)wmi_buf_data(buf); 517 roam_filter = (wmi_roam_filter_fixed_param *)buf_ptr; 518 WMITLV_SET_HDR(&roam_filter->tlv_header, 519 WMITLV_TAG_STRUC_wmi_roam_filter_fixed_param, 520 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_filter_fixed_param)); 521 /* fill in fixed values */ 522 roam_filter->vdev_id = roam_req->vdev_id; 523 roam_filter->flags = 0; 524 roam_filter->op_bitmap = roam_req->op_bitmap; 525 roam_filter->num_bssid_black_list = roam_req->num_bssid_deny_list; 526 roam_filter->num_ssid_white_list = roam_req->num_ssid_allow_list; 527 roam_filter->num_bssid_preferred_list = 528 roam_req->num_bssid_preferred_list; 529 roam_filter->num_rssi_rejection_ap = 530 roam_req->num_rssi_rejection_ap; 531 roam_filter->delta_rssi = roam_req->delta_rssi; 532 buf_ptr += sizeof(wmi_roam_filter_fixed_param); 533 534 WMITLV_SET_HDR((buf_ptr), 535 WMITLV_TAG_ARRAY_FIXED_STRUC, 536 (roam_req->num_bssid_deny_list * sizeof(wmi_mac_addr))); 537 bssid_src_ptr = (uint8_t *)&roam_req->bssid_avoid_list; 538 bssid_dst_ptr = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE); 539 for (i = 0; i < roam_req->num_bssid_deny_list; i++) { 540 WMI_CHAR_ARRAY_TO_MAC_ADDR(bssid_src_ptr, bssid_dst_ptr); 541 bssid_src_ptr += ATH_MAC_LEN; 542 bssid_dst_ptr++; 543 } 544 buf_ptr += WMI_TLV_HDR_SIZE + 545 (roam_req->num_bssid_deny_list * sizeof(wmi_mac_addr)); 546 WMITLV_SET_HDR((buf_ptr), 547 WMITLV_TAG_ARRAY_FIXED_STRUC, 548 (roam_req->num_ssid_allow_list * sizeof(wmi_ssid))); 549 ssid_ptr = (wmi_ssid *)(buf_ptr + WMI_TLV_HDR_SIZE); 550 for (i = 0; i < roam_req->num_ssid_allow_list; i++) { 551 qdf_mem_copy(&ssid_ptr->ssid, 552 &roam_req->ssid_allowed_list[i].ssid, 553 roam_req->ssid_allowed_list[i].length); 554 ssid_ptr->ssid_len = roam_req->ssid_allowed_list[i].length; 555 ssid_ptr++; 556 } 557 buf_ptr += WMI_TLV_HDR_SIZE + (roam_req->num_ssid_allow_list * 558 sizeof(wmi_ssid)); 559 WMITLV_SET_HDR((buf_ptr), 560 WMITLV_TAG_ARRAY_FIXED_STRUC, 561 (roam_req->num_bssid_preferred_list * sizeof(wmi_mac_addr))); 562 bssid_src_ptr = (uint8_t *)&roam_req->bssid_favored; 563 bssid_dst_ptr = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE); 564 for (i = 0; i < roam_req->num_bssid_preferred_list; i++) { 565 WMI_CHAR_ARRAY_TO_MAC_ADDR(bssid_src_ptr, 566 (wmi_mac_addr *)bssid_dst_ptr); 567 bssid_src_ptr += ATH_MAC_LEN; 568 bssid_dst_ptr++; 569 } 570 buf_ptr += WMI_TLV_HDR_SIZE + 571 (roam_req->num_bssid_preferred_list * sizeof(wmi_mac_addr)); 572 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 573 (roam_req->num_bssid_preferred_list * sizeof(uint32_t))); 574 bssid_preferred_factor_ptr = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE); 575 for (i = 0; i < roam_req->num_bssid_preferred_list; i++) { 576 *bssid_preferred_factor_ptr = 577 roam_req->bssid_favored_factor[i]; 578 bssid_preferred_factor_ptr++; 579 } 580 buf_ptr += WMI_TLV_HDR_SIZE + 581 (roam_req->num_bssid_preferred_list * sizeof(uint32_t)); 582 583 WMITLV_SET_HDR(buf_ptr, 584 WMITLV_TAG_ARRAY_STRUC, blist_len); 585 buf_ptr += WMI_TLV_HDR_SIZE; 586 if (roam_req->lca_disallow_config_present) { 587 blist_param = 588 (wmi_roam_lca_disallow_config_tlv_param *)buf_ptr; 589 WMITLV_SET_HDR(&blist_param->tlv_header, 590 WMITLV_TAG_STRUC_wmi_roam_lca_disallow_config_tlv_param, 591 WMITLV_GET_STRUCT_TLVLEN( 592 wmi_roam_lca_disallow_config_tlv_param)); 593 594 blist_param->disallow_duration = roam_req->disallow_duration; 595 blist_param->rssi_channel_penalization = 596 roam_req->rssi_channel_penalization; 597 blist_param->num_disallowed_aps = roam_req->num_disallowed_aps; 598 blist_param->disallow_lca_enable_source_bitmap = 599 (WMI_ROAM_LCA_DISALLOW_SOURCE_PER | 600 WMI_ROAM_LCA_DISALLOW_SOURCE_BACKGROUND); 601 buf_ptr += (sizeof(wmi_roam_lca_disallow_config_tlv_param)); 602 } 603 604 WMITLV_SET_HDR(buf_ptr, 605 WMITLV_TAG_ARRAY_STRUC, 606 (roam_req->num_rssi_rejection_ap * sizeof(*rssi_rej))); 607 buf_ptr += WMI_TLV_HDR_SIZE; 608 for (i = 0; i < roam_req->num_rssi_rejection_ap; i++) { 609 rssi_rej = 610 (wmi_roam_rssi_rejection_oce_config_param *)buf_ptr; 611 612 WMITLV_SET_HDR(&rssi_rej->tlv_header, 613 WMITLV_TAG_STRUC_wmi_roam_rssi_rejection_oce_config_param, 614 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_rssi_rejection_oce_config_param)); 615 616 WMI_CHAR_ARRAY_TO_MAC_ADDR( 617 roam_req->rssi_rejection_ap[i].bssid.bytes, 618 &rssi_rej->bssid); 619 rssi_rej->remaining_disallow_duration = 620 roam_req->rssi_rejection_ap[i].reject_duration; 621 rssi_rej->requested_rssi = 622 (int32_t)roam_req->rssi_rejection_ap[i].expected_rssi; 623 buf_ptr += 624 (sizeof(wmi_roam_rssi_rejection_oce_config_param)); 625 } 626 627 wmi_mtrace(WMI_ROAM_FILTER_CMDID, NO_SESSION, 0); 628 status = wmi_unified_cmd_send(wmi_handle, buf, 629 len, WMI_ROAM_FILTER_CMDID); 630 if (QDF_IS_STATUS_ERROR(status)) { 631 wmi_err("cmd WMI_ROAM_FILTER_CMDID returned Error %d", 632 status); 633 wmi_buf_free(buf); 634 } 635 636 return status; 637 } 638 639 #ifdef FEATURE_WLAN_ESE 640 /** 641 * send_plm_stop_cmd_tlv() - plm stop request 642 * @wmi_handle: wmi handle 643 * @plm: plm request parameters 644 * 645 * This function request FW to stop PLM. 646 * 647 * Return: CDF status 648 */ 649 static QDF_STATUS send_plm_stop_cmd_tlv(wmi_unified_t wmi_handle, 650 const struct plm_req_params *plm) 651 { 652 wmi_vdev_plmreq_stop_cmd_fixed_param *cmd; 653 int32_t len; 654 wmi_buf_t buf; 655 uint8_t *buf_ptr; 656 int ret; 657 658 len = sizeof(*cmd); 659 buf = wmi_buf_alloc(wmi_handle, len); 660 if (!buf) 661 return QDF_STATUS_E_NOMEM; 662 663 cmd = (wmi_vdev_plmreq_stop_cmd_fixed_param *)wmi_buf_data(buf); 664 665 buf_ptr = (uint8_t *)cmd; 666 667 WMITLV_SET_HDR(&cmd->tlv_header, 668 WMITLV_TAG_STRUC_wmi_vdev_plmreq_stop_cmd_fixed_param, 669 WMITLV_GET_STRUCT_TLVLEN 670 (wmi_vdev_plmreq_stop_cmd_fixed_param)); 671 672 cmd->vdev_id = plm->vdev_id; 673 674 cmd->meas_token = plm->meas_token; 675 wmi_debug("vdev %d meas token %d", cmd->vdev_id, cmd->meas_token); 676 677 wmi_mtrace(WMI_VDEV_PLMREQ_STOP_CMDID, cmd->vdev_id, 0); 678 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 679 WMI_VDEV_PLMREQ_STOP_CMDID); 680 if (ret) { 681 wmi_err("Failed to send plm stop wmi cmd"); 682 wmi_buf_free(buf); 683 return QDF_STATUS_E_FAILURE; 684 } 685 686 return QDF_STATUS_SUCCESS; 687 } 688 689 /** 690 * send_plm_start_cmd_tlv() - plm start request 691 * @wmi_handle: wmi handle 692 * @plm: plm request parameters 693 * 694 * This function request FW to start PLM. 695 * 696 * Return: CDF status 697 */ 698 static QDF_STATUS send_plm_start_cmd_tlv(wmi_unified_t wmi_handle, 699 const struct plm_req_params *plm) 700 { 701 wmi_vdev_plmreq_start_cmd_fixed_param *cmd; 702 uint32_t *channel_list; 703 int32_t len; 704 wmi_buf_t buf; 705 uint8_t *buf_ptr; 706 uint8_t count; 707 int ret; 708 709 /* TLV place holder for channel_list */ 710 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE; 711 len += sizeof(uint32_t) * plm->plm_num_ch; 712 713 buf = wmi_buf_alloc(wmi_handle, len); 714 if (!buf) 715 return QDF_STATUS_E_NOMEM; 716 717 cmd = (wmi_vdev_plmreq_start_cmd_fixed_param *)wmi_buf_data(buf); 718 719 buf_ptr = (uint8_t *)cmd; 720 721 WMITLV_SET_HDR(&cmd->tlv_header, 722 WMITLV_TAG_STRUC_wmi_vdev_plmreq_start_cmd_fixed_param, 723 WMITLV_GET_STRUCT_TLVLEN 724 (wmi_vdev_plmreq_start_cmd_fixed_param)); 725 726 cmd->vdev_id = plm->vdev_id; 727 728 cmd->meas_token = plm->meas_token; 729 cmd->dialog_token = plm->diag_token; 730 cmd->number_bursts = plm->num_bursts; 731 cmd->burst_interval = WMI_SEC_TO_MSEC(plm->burst_int); 732 cmd->off_duration = plm->meas_duration; 733 cmd->burst_cycle = plm->burst_len; 734 cmd->tx_power = plm->desired_tx_pwr; 735 WMI_CHAR_ARRAY_TO_MAC_ADDR(plm->mac_addr.bytes, &cmd->dest_mac); 736 cmd->num_chans = plm->plm_num_ch; 737 738 buf_ptr += sizeof(wmi_vdev_plmreq_start_cmd_fixed_param); 739 740 wmi_debug("vdev: %d measu token: %d dialog_token: %d number_bursts: %d burst_interval: %d off_duration: %d burst_cycle: %d tx_power: %d Number of channels: %d", 741 cmd->vdev_id, cmd->meas_token, cmd->dialog_token, 742 cmd->number_bursts, cmd->burst_interval, cmd->off_duration, 743 cmd->burst_cycle, cmd->tx_power, cmd->num_chans); 744 745 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 746 (cmd->num_chans * sizeof(uint32_t))); 747 748 buf_ptr += WMI_TLV_HDR_SIZE; 749 if (cmd->num_chans) { 750 channel_list = (uint32_t *)buf_ptr; 751 for (count = 0; count < cmd->num_chans; count++) { 752 channel_list[count] = plm->plm_ch_freq_list[count]; 753 wmi_debug("Ch[%d]: %d MHz", count, channel_list[count]); 754 } 755 buf_ptr += cmd->num_chans * sizeof(uint32_t); 756 } 757 758 wmi_mtrace(WMI_VDEV_PLMREQ_START_CMDID, cmd->vdev_id, 0); 759 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 760 WMI_VDEV_PLMREQ_START_CMDID); 761 if (ret) { 762 wmi_err("Failed to send plm start wmi cmd"); 763 wmi_buf_free(buf); 764 return QDF_STATUS_E_FAILURE; 765 } 766 767 return QDF_STATUS_SUCCESS; 768 } 769 770 void wmi_ese_attach_tlv(wmi_unified_t wmi_handle) 771 { 772 struct wmi_ops *ops = wmi_handle->ops; 773 774 ops->send_plm_stop_cmd = send_plm_stop_cmd_tlv; 775 ops->send_plm_start_cmd = send_plm_start_cmd_tlv; 776 } 777 #endif /* FEATURE_WLAN_ESE */ 778 779 /** 780 * convert_roam_trigger_reason() - Function to convert unified Roam trigger 781 * enum to TLV specific WMI_ROAM_TRIGGER_REASON_ID 782 * @trigger_reason: Roam trigger reason 783 * 784 * Return: WMI roam trigger reason 785 */ 786 static uint32_t 787 convert_roam_trigger_reason(enum roam_trigger_reason trigger_reason) 788 { 789 switch (trigger_reason) { 790 case ROAM_TRIGGER_REASON_NONE: 791 return WMI_ROAM_TRIGGER_REASON_NONE; 792 case ROAM_TRIGGER_REASON_PER: 793 return WMI_ROAM_TRIGGER_REASON_PER; 794 case ROAM_TRIGGER_REASON_BMISS: 795 return WMI_ROAM_TRIGGER_REASON_BMISS; 796 case ROAM_TRIGGER_REASON_LOW_RSSI: 797 return WMI_ROAM_TRIGGER_REASON_LOW_RSSI; 798 case ROAM_TRIGGER_REASON_HIGH_RSSI: 799 return WMI_ROAM_TRIGGER_REASON_HIGH_RSSI; 800 case ROAM_TRIGGER_REASON_PERIODIC: 801 return WMI_ROAM_TRIGGER_REASON_PERIODIC; 802 case ROAM_TRIGGER_REASON_MAWC: 803 return WMI_ROAM_TRIGGER_REASON_MAWC; 804 case ROAM_TRIGGER_REASON_DENSE: 805 return WMI_ROAM_TRIGGER_REASON_DENSE; 806 case ROAM_TRIGGER_REASON_BACKGROUND: 807 return WMI_ROAM_TRIGGER_REASON_BACKGROUND; 808 case ROAM_TRIGGER_REASON_FORCED: 809 return WMI_ROAM_TRIGGER_REASON_FORCED; 810 case ROAM_TRIGGER_REASON_BTM: 811 return WMI_ROAM_TRIGGER_REASON_BTM; 812 case ROAM_TRIGGER_REASON_UNIT_TEST: 813 return WMI_ROAM_TRIGGER_REASON_UNIT_TEST; 814 case ROAM_TRIGGER_REASON_BSS_LOAD: 815 return WMI_ROAM_TRIGGER_REASON_BSS_LOAD; 816 case ROAM_TRIGGER_REASON_DEAUTH: 817 return WMI_ROAM_TRIGGER_REASON_DEAUTH; 818 case ROAM_TRIGGER_REASON_IDLE: 819 return WMI_ROAM_TRIGGER_REASON_IDLE; 820 case ROAM_TRIGGER_REASON_STA_KICKOUT: 821 return WMI_ROAM_TRIGGER_REASON_STA_KICKOUT; 822 case ROAM_TRIGGER_REASON_ESS_RSSI: 823 return WMI_ROAM_TRIGGER_REASON_ESS_RSSI; 824 case ROAM_TRIGGER_REASON_WTC_BTM: 825 return WMI_ROAM_TRIGGER_REASON_WTC_BTM; 826 case ROAM_TRIGGER_REASON_PMK_TIMEOUT: 827 return WMI_ROAM_TRIGGER_REASON_PMK_TIMEOUT; 828 case ROAM_TRIGGER_REASON_BTC: 829 return WMI_ROAM_TRIGGER_REASON_BTC; 830 case ROAM_TRIGGER_REASON_MAX: 831 return WMI_ROAM_TRIGGER_REASON_MAX; 832 default: 833 return WMI_ROAM_TRIGGER_REASON_NONE; 834 } 835 } 836 837 #if defined(WLAN_FEATURE_HOST_ROAM) || defined(WLAN_FEATURE_ROAM_OFFLOAD) 838 static char *wmi_get_roam_event_reason_string(uint32_t reason) 839 { 840 switch (reason) { 841 case WMI_ROAM_REASON_INVALID: 842 return "Default"; 843 case WMI_ROAM_REASON_BETTER_AP: 844 return "Better AP"; 845 case WMI_ROAM_REASON_BMISS: 846 return "BMISS"; 847 case WMI_ROAM_REASON_LOW_RSSI: 848 return "Low Rssi"; 849 case WMI_ROAM_REASON_SUITABLE_AP: 850 return "Suitable AP"; 851 case WMI_ROAM_REASON_HO_FAILED: 852 return "Hand-off Failed"; 853 case WMI_ROAM_REASON_INVOKE_ROAM_FAIL: 854 return "Roam Invoke failed"; 855 case WMI_ROAM_REASON_RSO_STATUS: 856 return "RSO status"; 857 case WMI_ROAM_REASON_BTM: 858 return "BTM"; 859 case WMI_ROAM_REASON_DEAUTH: 860 return "Deauth"; 861 default: 862 return "Invalid"; 863 } 864 865 return "Invalid"; 866 } 867 868 static enum roam_reason 869 wmi_convert_fw_reason_to_cm_reason(uint32_t reason) 870 { 871 switch (reason) { 872 case WMI_ROAM_REASON_INVALID: 873 return ROAM_REASON_INVALID; 874 case WMI_ROAM_REASON_BETTER_AP: 875 return ROAM_REASON_BETTER_AP; 876 case WMI_ROAM_REASON_BMISS: 877 return ROAM_REASON_BMISS; 878 case WMI_ROAM_REASON_LOW_RSSI: 879 return ROAM_REASON_LOW_RSSI; 880 case WMI_ROAM_REASON_SUITABLE_AP: 881 return ROAM_REASON_SUITABLE_AP; 882 case WMI_ROAM_REASON_HO_FAILED: 883 return ROAM_REASON_HO_FAILED; 884 case WMI_ROAM_REASON_INVOKE_ROAM_FAIL: 885 return ROAM_REASON_INVOKE_ROAM_FAIL; 886 case WMI_ROAM_REASON_RSO_STATUS: 887 return ROAM_REASON_RSO_STATUS; 888 case WMI_ROAM_REASON_BTM: 889 return ROAM_REASON_BTM; 890 case WMI_ROAM_REASON_DEAUTH: 891 return ROAM_REASON_DEAUTH; 892 default: 893 return ROAM_REASON_INVALID; 894 } 895 896 return ROAM_REASON_INVALID; 897 } 898 899 static enum cm_roam_notif 900 wmi_convert_fw_notif_to_cm_notif(uint32_t fw_notif) 901 { 902 switch (fw_notif) { 903 case WMI_ROAM_NOTIF_ROAM_START: 904 return CM_ROAM_NOTIF_ROAM_START; 905 case WMI_ROAM_NOTIF_ROAM_ABORT: 906 return CM_ROAM_NOTIF_ROAM_ABORT; 907 case WMI_ROAM_NOTIF_ROAM_REASSOC: 908 return CM_ROAM_NOTIF_ROAM_REASSOC; 909 case WMI_ROAM_NOTIF_SCAN_MODE_SUCCESS: 910 return CM_ROAM_NOTIF_SCAN_MODE_SUCCESS; 911 case WMI_ROAM_NOTIF_SCAN_MODE_FAIL: 912 return CM_ROAM_NOTIF_SCAN_MODE_FAIL; 913 case WMI_ROAM_NOTIF_DISCONNECT: 914 return CM_ROAM_NOTIF_DISCONNECT; 915 case WMI_ROAM_NOTIF_SUBNET_CHANGED: 916 return CM_ROAM_NOTIF_SUBNET_CHANGED; 917 case WMI_ROAM_NOTIF_SCAN_START: 918 return CM_ROAM_NOTIF_SCAN_START; 919 case WMI_ROAM_NOTIF_DEAUTH_RECV: 920 return CM_ROAM_NOTIF_DEAUTH_RECV; 921 case WMI_ROAM_NOTIF_DISASSOC_RECV: 922 return CM_ROAM_NOTIF_DISASSOC_RECV; 923 case WMI_ROAM_NOTIF_SCAN_MODE_SUCCESS_WITH_HO_FAIL: 924 return CM_ROAM_NOTIF_HO_FAIL; 925 case WMI_ROAM_NOTIF_SCAN_END: 926 return CM_ROAM_NOTIF_SCAN_END; 927 default: 928 return CM_ROAM_NOTIF_INVALID; 929 } 930 931 return CM_ROAM_NOTIF_INVALID; 932 } 933 934 static void 935 wmi_extract_pdev_hw_mode_trans_ind( 936 wmi_pdev_hw_mode_transition_event_fixed_param *fixed_param, 937 wmi_pdev_set_hw_mode_response_vdev_mac_entry *vdev_mac_entry, 938 struct cm_hw_mode_trans_ind *hw_mode_trans_ind) 939 { 940 uint32_t i; 941 942 if (fixed_param->num_vdev_mac_entries > MAX_VDEV_SUPPORTED) { 943 wmi_err("Number of Vdev mac entries %d exceeded max vdev supported %d", 944 fixed_param->num_vdev_mac_entries, 945 MAX_VDEV_SUPPORTED); 946 return; 947 } 948 hw_mode_trans_ind->old_hw_mode_index = fixed_param->old_hw_mode_index; 949 hw_mode_trans_ind->new_hw_mode_index = fixed_param->new_hw_mode_index; 950 hw_mode_trans_ind->num_vdev_mac_entries = 951 fixed_param->num_vdev_mac_entries; 952 wmi_debug("old_hw_mode_index:%d new_hw_mode_index:%d entries=%d", 953 fixed_param->old_hw_mode_index, 954 fixed_param->new_hw_mode_index, 955 fixed_param->num_vdev_mac_entries); 956 957 if (!vdev_mac_entry) { 958 wmi_err("Invalid vdev_mac_entry"); 959 return; 960 } 961 962 /* Store the vdev-mac map in WMA and send to policy manager */ 963 for (i = 0; i < fixed_param->num_vdev_mac_entries; i++) { 964 uint32_t vdev_id, mac_id, pdev_id; 965 966 vdev_id = vdev_mac_entry[i].vdev_id; 967 pdev_id = vdev_mac_entry[i].pdev_id; 968 969 if (pdev_id == OL_TXRX_PDEV_ID) { 970 wmi_err("soc level id received for mac id"); 971 return; 972 } 973 if (vdev_id >= WLAN_MAX_VDEVS) { 974 wmi_err("vdev_id: %d is invalid, max_bssid: %d", 975 vdev_id, WLAN_MAX_VDEVS); 976 return; 977 } 978 979 mac_id = WMI_PDEV_TO_MAC_MAP(vdev_mac_entry[i].pdev_id); 980 981 hw_mode_trans_ind->vdev_mac_map[i].vdev_id = vdev_id; 982 hw_mode_trans_ind->vdev_mac_map[i].mac_id = mac_id; 983 984 wmi_debug("vdev_id:%d mac_id:%d", vdev_id, mac_id); 985 } 986 } 987 988 /** 989 * extract_roam_event_tlv() - Extract the roam event 990 * @wmi_handle: wmi handle 991 * @evt_buf: Pointer to the event buffer 992 * @len: Data length 993 * @roam_event: Roam event data 994 */ 995 static QDF_STATUS 996 extract_roam_event_tlv(wmi_unified_t wmi_handle, void *evt_buf, uint32_t len, 997 struct roam_offload_roam_event *roam_event) 998 { 999 QDF_STATUS status = QDF_STATUS_SUCCESS; 1000 wmi_roam_event_fixed_param *wmi_event = NULL; 1001 WMI_ROAM_EVENTID_param_tlvs *param_buf = NULL; 1002 struct cm_hw_mode_trans_ind *hw_mode_trans_ind; 1003 wmi_pdev_hw_mode_transition_event_fixed_param *hw_mode_trans_param; 1004 1005 if (!evt_buf) { 1006 wmi_debug("Empty roam_sync_event param buf"); 1007 status = QDF_STATUS_E_FAILURE; 1008 goto end; 1009 } 1010 1011 param_buf = (WMI_ROAM_EVENTID_param_tlvs *)evt_buf; 1012 if (!param_buf) { 1013 wmi_debug("received null buf from target"); 1014 status = QDF_STATUS_E_FAILURE; 1015 goto end; 1016 } 1017 1018 wmi_event = param_buf->fixed_param; 1019 if (!wmi_event) { 1020 wmi_debug("received null event data from target"); 1021 status = QDF_STATUS_E_FAILURE; 1022 goto end; 1023 } 1024 roam_event->vdev_id = wmi_event->vdev_id; 1025 1026 if (roam_event->vdev_id >= WLAN_MAX_VDEVS) { 1027 wmi_err("Invalid vdev id from firmware: %u", 1028 roam_event->vdev_id); 1029 return -EINVAL; 1030 } 1031 hw_mode_trans_param = param_buf->hw_mode_transition_fixed_param; 1032 if (hw_mode_trans_param && 1033 hw_mode_trans_param->num_vdev_mac_entries > 1034 param_buf->num_wmi_pdev_set_hw_mode_response_vdev_mac_mapping) { 1035 wmi_debug("invalid vdev mac entries %d %d", 1036 hw_mode_trans_param->num_vdev_mac_entries, 1037 param_buf->num_wmi_pdev_set_hw_mode_response_vdev_mac_mapping); 1038 return QDF_STATUS_E_FAILURE; 1039 } 1040 1041 roam_event->reason = 1042 wmi_convert_fw_reason_to_cm_reason(wmi_event->reason); 1043 roam_event->rssi = wmi_event->rssi; 1044 roam_event->notif = wmi_convert_fw_notif_to_cm_notif(wmi_event->notif); 1045 roam_event->notif_params = wmi_event->notif_params; 1046 roam_event->notif_params1 = wmi_event->notif_params1; 1047 1048 wlan_roam_debug_log(roam_event->vdev_id, DEBUG_ROAM_EVENT, 1049 DEBUG_INVALID_PEER_ID, NULL, NULL, 1050 roam_event->reason, 1051 (roam_event->reason == WMI_ROAM_REASON_INVALID) ? 1052 roam_event->notif : roam_event->rssi); 1053 1054 DPTRACE(qdf_dp_trace_record_event(QDF_DP_TRACE_EVENT_RECORD, 1055 roam_event->vdev_id, 1056 QDF_TRACE_DEFAULT_PDEV_ID, 1057 QDF_PROTO_TYPE_EVENT, 1058 QDF_ROAM_EVENTID)); 1059 1060 wmi_debug("FW_ROAM_EVT: Reason:%s[%d], Notif %x for vdevid %x, rssi %d, params %d, params1 %d", 1061 wmi_get_roam_event_reason_string(roam_event->reason), 1062 roam_event->reason, 1063 roam_event->notif, roam_event->vdev_id, roam_event->rssi, 1064 roam_event->notif_params, roam_event->notif_params1); 1065 1066 if (param_buf->hw_mode_transition_fixed_param) { 1067 hw_mode_trans_ind = qdf_mem_malloc(sizeof(*hw_mode_trans_ind)); 1068 if (!hw_mode_trans_ind) { 1069 status = QDF_STATUS_E_NOMEM; 1070 goto end; 1071 } 1072 wmi_extract_pdev_hw_mode_trans_ind( 1073 param_buf->hw_mode_transition_fixed_param, 1074 param_buf->wmi_pdev_set_hw_mode_response_vdev_mac_mapping, 1075 hw_mode_trans_ind); 1076 roam_event->hw_mode_trans_ind = hw_mode_trans_ind; 1077 } 1078 1079 if (wmi_event->notif_params1) 1080 roam_event->deauth_disassoc_frame = 1081 param_buf->deauth_disassoc_frame; 1082 end: 1083 return status; 1084 } 1085 #endif /* WLAN_FEATURE_HOST_ROAM || WLAN_FEATURE_ROAM_OFFLOAD */ 1086 1087 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 1088 /* send_set_ric_req_cmd_tlv() - set ric request element 1089 * @wmi_handle: wmi handle 1090 * @msg: message 1091 * @is_add_ts: is addts required 1092 * 1093 * This function sets ric request element for 11r roaming. 1094 * 1095 * Return: CDF status 1096 */ 1097 static QDF_STATUS send_set_ric_req_cmd_tlv(wmi_unified_t wmi_handle, 1098 void *msg, uint8_t is_add_ts) 1099 { 1100 wmi_ric_request_fixed_param *cmd; 1101 wmi_ric_tspec *tspec_param; 1102 wmi_buf_t buf; 1103 uint8_t *buf_ptr; 1104 struct mac_tspec_ie *tspec_ie = NULL; 1105 int32_t len = sizeof(wmi_ric_request_fixed_param) + 1106 WMI_TLV_HDR_SIZE + sizeof(wmi_ric_tspec); 1107 1108 buf = wmi_buf_alloc(wmi_handle, len); 1109 if (!buf) 1110 return QDF_STATUS_E_NOMEM; 1111 1112 buf_ptr = (uint8_t *)wmi_buf_data(buf); 1113 1114 cmd = (wmi_ric_request_fixed_param *)buf_ptr; 1115 WMITLV_SET_HDR(&cmd->tlv_header, 1116 WMITLV_TAG_STRUC_wmi_ric_request_fixed_param, 1117 WMITLV_GET_STRUCT_TLVLEN(wmi_ric_request_fixed_param)); 1118 if (is_add_ts) 1119 cmd->vdev_id = ((struct add_ts_param *)msg)->vdev_id; 1120 else 1121 cmd->vdev_id = ((struct del_ts_params *)msg)->sessionId; 1122 cmd->num_ric_request = 1; 1123 cmd->is_add_ric = is_add_ts; 1124 1125 buf_ptr += sizeof(wmi_ric_request_fixed_param); 1126 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, sizeof(wmi_ric_tspec)); 1127 1128 buf_ptr += WMI_TLV_HDR_SIZE; 1129 tspec_param = (wmi_ric_tspec *)buf_ptr; 1130 WMITLV_SET_HDR(&tspec_param->tlv_header, 1131 WMITLV_TAG_STRUC_wmi_ric_tspec, 1132 WMITLV_GET_STRUCT_TLVLEN(wmi_ric_tspec)); 1133 1134 if (is_add_ts) 1135 tspec_ie = &(((struct add_ts_param *)msg)->tspec); 1136 else 1137 tspec_ie = &(((struct del_ts_params *)msg)->delTsInfo.tspec); 1138 if (tspec_ie) { 1139 /* Fill the tsinfo in the format expected by firmware */ 1140 #ifndef ANI_LITTLE_BIT_ENDIAN 1141 qdf_mem_copy(((uint8_t *)&tspec_param->ts_info) + 1, 1142 ((uint8_t *)&tspec_ie->tsinfo) + 1, 2); 1143 #else 1144 qdf_mem_copy(((uint8_t *)&tspec_param->ts_info), 1145 ((uint8_t *)&tspec_ie->tsinfo) + 1, 2); 1146 #endif /* ANI_LITTLE_BIT_ENDIAN */ 1147 1148 tspec_param->nominal_msdu_size = tspec_ie->nomMsduSz; 1149 tspec_param->maximum_msdu_size = tspec_ie->maxMsduSz; 1150 tspec_param->min_service_interval = tspec_ie->minSvcInterval; 1151 tspec_param->max_service_interval = tspec_ie->maxSvcInterval; 1152 tspec_param->inactivity_interval = tspec_ie->inactInterval; 1153 tspec_param->suspension_interval = tspec_ie->suspendInterval; 1154 tspec_param->svc_start_time = tspec_ie->svcStartTime; 1155 tspec_param->min_data_rate = tspec_ie->minDataRate; 1156 tspec_param->mean_data_rate = tspec_ie->meanDataRate; 1157 tspec_param->peak_data_rate = tspec_ie->peakDataRate; 1158 tspec_param->max_burst_size = tspec_ie->maxBurstSz; 1159 tspec_param->delay_bound = tspec_ie->delayBound; 1160 tspec_param->min_phy_rate = tspec_ie->minPhyRate; 1161 tspec_param->surplus_bw_allowance = tspec_ie->surplusBw; 1162 tspec_param->medium_time = 0; 1163 } 1164 wmi_debug("Set RIC Req is_add_ts: %d", is_add_ts); 1165 1166 wmi_mtrace(WMI_ROAM_SET_RIC_REQUEST_CMDID, cmd->vdev_id, 0); 1167 if (wmi_unified_cmd_send(wmi_handle, buf, len, 1168 WMI_ROAM_SET_RIC_REQUEST_CMDID)) { 1169 wmi_err("Failed to send vdev Set RIC Req command"); 1170 if (is_add_ts) 1171 ((struct add_ts_param *)msg)->status = 1172 QDF_STATUS_E_FAILURE; 1173 wmi_buf_free(buf); 1174 return QDF_STATUS_E_FAILURE; 1175 } 1176 1177 return QDF_STATUS_SUCCESS; 1178 } 1179 1180 /** 1181 * send_process_roam_synch_complete_cmd_tlv() - roam synch complete command to 1182 * fw. 1183 * @wmi_handle: wmi handle 1184 * @vdev_id: vdev id 1185 * 1186 * This function sends roam synch complete event to fw. 1187 * 1188 * Return: QDF STATUS 1189 */ 1190 static QDF_STATUS 1191 send_process_roam_synch_complete_cmd_tlv(wmi_unified_t wmi_handle, 1192 uint8_t vdev_id) 1193 { 1194 wmi_roam_synch_complete_fixed_param *cmd; 1195 wmi_buf_t wmi_buf; 1196 uint8_t *buf_ptr; 1197 uint16_t len; 1198 len = sizeof(wmi_roam_synch_complete_fixed_param); 1199 1200 wmi_buf = wmi_buf_alloc(wmi_handle, len); 1201 if (!wmi_buf) 1202 return QDF_STATUS_E_NOMEM; 1203 1204 cmd = (wmi_roam_synch_complete_fixed_param *)wmi_buf_data(wmi_buf); 1205 buf_ptr = (uint8_t *)cmd; 1206 WMITLV_SET_HDR(&cmd->tlv_header, 1207 WMITLV_TAG_STRUC_wmi_roam_synch_complete_fixed_param, 1208 WMITLV_GET_STRUCT_TLVLEN 1209 (wmi_roam_synch_complete_fixed_param)); 1210 cmd->vdev_id = vdev_id; 1211 wmi_mtrace(WMI_ROAM_SYNCH_COMPLETE, cmd->vdev_id, 0); 1212 if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len, 1213 WMI_ROAM_SYNCH_COMPLETE)) { 1214 wmi_err("Failed to send roam synch confirmation"); 1215 wmi_buf_free(wmi_buf); 1216 return QDF_STATUS_E_FAILURE; 1217 } 1218 1219 return QDF_STATUS_SUCCESS; 1220 } 1221 1222 /** 1223 * send_roam_invoke_cmd_tlv() - send roam invoke command to fw. 1224 * @wmi_handle: wma handle 1225 * @roaminvoke: roam invoke command 1226 * 1227 * Send roam invoke command to fw for fastreassoc. 1228 * 1229 * Return: CDF STATUS 1230 */ 1231 static QDF_STATUS send_roam_invoke_cmd_tlv(wmi_unified_t wmi_handle, 1232 struct roam_invoke_req *roaminvoke) 1233 { 1234 wmi_roam_invoke_cmd_fixed_param *cmd; 1235 wmi_buf_t wmi_buf; 1236 u_int8_t *buf_ptr; 1237 u_int16_t len, args_tlv_len; 1238 uint32_t *channel_list; 1239 wmi_mac_addr *bssid_list; 1240 wmi_tlv_buf_len_param *buf_len_tlv; 1241 1242 args_tlv_len = (4 * WMI_TLV_HDR_SIZE) + sizeof(uint32_t) + 1243 sizeof(wmi_mac_addr) + sizeof(wmi_tlv_buf_len_param) + 1244 roundup(roaminvoke->frame_len, sizeof(uint32_t)); 1245 len = sizeof(wmi_roam_invoke_cmd_fixed_param) + args_tlv_len; 1246 wmi_buf = wmi_buf_alloc(wmi_handle, len); 1247 if (!wmi_buf) 1248 return QDF_STATUS_E_NOMEM; 1249 1250 cmd = (wmi_roam_invoke_cmd_fixed_param *)wmi_buf_data(wmi_buf); 1251 buf_ptr = (u_int8_t *)cmd; 1252 WMITLV_SET_HDR(&cmd->tlv_header, 1253 WMITLV_TAG_STRUC_wmi_roam_invoke_cmd_fixed_param, 1254 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_invoke_cmd_fixed_param)); 1255 cmd->vdev_id = roaminvoke->vdev_id; 1256 cmd->flags |= (1 << WMI_ROAM_INVOKE_FLAG_REPORT_FAILURE); 1257 if (roaminvoke->is_same_bssid) 1258 cmd->flags |= (1 << WMI_ROAM_INVOKE_FLAG_NO_NULL_FRAME_TO_AP); 1259 1260 if (roaminvoke->frame_len) { 1261 cmd->roam_scan_mode = WMI_ROAM_INVOKE_SCAN_MODE_SKIP; 1262 /* packing 1 beacon/probe_rsp frame with WMI cmd */ 1263 cmd->num_buf = 1; 1264 } else { 1265 cmd->roam_scan_mode = WMI_ROAM_INVOKE_SCAN_MODE_FIXED_CH; 1266 cmd->num_buf = 0; 1267 } 1268 1269 cmd->roam_ap_sel_mode = 0; 1270 cmd->roam_delay = 0; 1271 cmd->num_chan = 1; 1272 cmd->num_bssid = 1; 1273 1274 if (roaminvoke->forced_roaming) { 1275 cmd->num_chan = 0; 1276 cmd->num_bssid = 0; 1277 cmd->roam_scan_mode = WMI_ROAM_INVOKE_SCAN_MODE_CACHE_MAP; 1278 cmd->flags |= 1279 (1 << WMI_ROAM_INVOKE_FLAG_FULL_SCAN_IF_NO_CANDIDATE); 1280 cmd->reason = ROAM_INVOKE_REASON_NUD_FAILURE; 1281 } else if (qdf_is_macaddr_broadcast(&roaminvoke->target_bssid)) { 1282 cmd->num_chan = 0; 1283 cmd->num_bssid = 0; 1284 cmd->roam_scan_mode = WMI_ROAM_INVOKE_SCAN_MODE_CACHE_MAP; 1285 cmd->flags |= 1286 (1 << WMI_ROAM_INVOKE_FLAG_FULL_SCAN_IF_NO_CANDIDATE) | 1287 (1 << WMI_ROAM_INVOKE_FLAG_SELECT_CANDIDATE_CONSIDER_SCORE); 1288 cmd->reason = ROAM_INVOKE_REASON_USER_SPACE; 1289 } else { 1290 cmd->reason = ROAM_INVOKE_REASON_USER_SPACE; 1291 } 1292 1293 buf_ptr += sizeof(wmi_roam_invoke_cmd_fixed_param); 1294 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 1295 (sizeof(u_int32_t))); 1296 channel_list = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE); 1297 *channel_list = roaminvoke->ch_freq; 1298 buf_ptr += sizeof(uint32_t) + WMI_TLV_HDR_SIZE; 1299 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC, 1300 (sizeof(wmi_mac_addr))); 1301 bssid_list = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE); 1302 WMI_CHAR_ARRAY_TO_MAC_ADDR(roaminvoke->target_bssid.bytes, bssid_list); 1303 1304 /* move to next tlv i.e. bcn_prb_buf_list */ 1305 buf_ptr += WMI_TLV_HDR_SIZE + sizeof(wmi_mac_addr); 1306 1307 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_FIXED_STRUC, 1308 sizeof(wmi_tlv_buf_len_param)); 1309 1310 buf_len_tlv = (wmi_tlv_buf_len_param *)(buf_ptr + WMI_TLV_HDR_SIZE); 1311 WMITLV_SET_HDR(&buf_len_tlv->tlv_header, 1312 WMITLV_TAG_STRUC_wmi_tlv_buf_len_param, 1313 WMITLV_GET_STRUCT_TLVLEN(wmi_tlv_buf_len_param)); 1314 buf_len_tlv->buf_len = roaminvoke->frame_len; 1315 1316 /* move to next tlv i.e. bcn_prb_frm */ 1317 buf_ptr += WMI_TLV_HDR_SIZE + sizeof(wmi_tlv_buf_len_param); 1318 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, 1319 roundup(roaminvoke->frame_len, sizeof(uint32_t))); 1320 1321 /* copy frame after the header */ 1322 qdf_mem_copy(buf_ptr + WMI_TLV_HDR_SIZE, 1323 roaminvoke->frame_buf, 1324 roaminvoke->frame_len); 1325 1326 wmi_debug("flag:%d, MODE:%d, ap:%d, dly:%d, n_ch:%d, n_bssid:%d, ch_freq:%d, is_same_bss:%d", 1327 cmd->flags, cmd->roam_scan_mode, 1328 cmd->roam_ap_sel_mode, cmd->roam_delay, 1329 cmd->num_chan, cmd->num_bssid, roaminvoke->ch_freq, 1330 roaminvoke->is_same_bssid); 1331 1332 wmi_mtrace(WMI_ROAM_INVOKE_CMDID, cmd->vdev_id, 0); 1333 if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len, 1334 WMI_ROAM_INVOKE_CMDID)) { 1335 wmi_err("Failed to send roam invoke command"); 1336 wmi_buf_free(wmi_buf); 1337 return QDF_STATUS_E_FAILURE; 1338 } 1339 1340 return QDF_STATUS_SUCCESS; 1341 } 1342 1343 /** 1344 * convert_control_roam_trigger_reason_bitmap() - Convert roam trigger bitmap 1345 * 1346 * @trigger_reason_bitmap: Roam trigger reason bitmap received from upper layers 1347 * 1348 * Converts the controlled roam trigger reason bitmap of 1349 * type @roam_control_trigger_reason to firmware trigger 1350 * reason bitmap as defined in 1351 * trigger_reason_bitmask @wmi_roam_enable_disable_trigger_reason_fixed_param 1352 * 1353 * Return: trigger_reason_bitmask as defined in 1354 * wmi_roam_enable_disable_trigger_reason_fixed_param 1355 */ 1356 static uint32_t 1357 convert_control_roam_trigger_reason_bitmap(uint32_t trigger_reason_bitmap) 1358 { 1359 uint32_t fw_trigger_bitmap = 0, all_bitmap; 1360 1361 /* Enable the complete trigger bitmap when all bits are set in 1362 * the control config bitmap 1363 */ 1364 all_bitmap = BIT(ROAM_TRIGGER_REASON_MAX) - 1; 1365 if (trigger_reason_bitmap == all_bitmap) 1366 return BIT(WMI_ROAM_TRIGGER_EXT_REASON_MAX) - 1; 1367 1368 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_NONE)) 1369 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_NONE); 1370 1371 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_PER)) 1372 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_PER); 1373 1374 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_BMISS)) 1375 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_BMISS); 1376 1377 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_LOW_RSSI)) 1378 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_LOW_RSSI); 1379 1380 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_HIGH_RSSI)) 1381 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_HIGH_RSSI); 1382 1383 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_PERIODIC)) 1384 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_PERIODIC); 1385 1386 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_MAWC)) 1387 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_MAWC); 1388 1389 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_DENSE)) 1390 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_DENSE); 1391 1392 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_BACKGROUND)) 1393 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_BACKGROUND); 1394 1395 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_FORCED)) 1396 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_FORCED); 1397 1398 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_BTM)) 1399 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_BTM); 1400 1401 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_UNIT_TEST)) 1402 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_UNIT_TEST); 1403 1404 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_BSS_LOAD)) 1405 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_BSS_LOAD); 1406 1407 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_DEAUTH)) 1408 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_DEAUTH); 1409 1410 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_IDLE)) 1411 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_IDLE); 1412 1413 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_STA_KICKOUT)) 1414 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_STA_KICKOUT); 1415 1416 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_ESS_RSSI)) 1417 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_ESS_RSSI); 1418 1419 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_WTC_BTM)) 1420 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_WTC_BTM); 1421 1422 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_PMK_TIMEOUT)) 1423 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_PMK_TIMEOUT); 1424 1425 if (trigger_reason_bitmap & BIT(ROAM_TRIGGER_REASON_BTC)) 1426 fw_trigger_bitmap |= BIT(WMI_ROAM_TRIGGER_REASON_BTC); 1427 1428 return fw_trigger_bitmap; 1429 } 1430 1431 /** 1432 * get_internal_mandatory_roam_triggers() - Internal triggers to be added 1433 * 1434 * Return: the bitmap of mandatory triggers to be sent to firmware but not given 1435 * by user. 1436 */ 1437 static uint32_t 1438 get_internal_mandatory_roam_triggers(void) 1439 { 1440 return BIT(WMI_ROAM_TRIGGER_REASON_FORCED); 1441 } 1442 1443 /** 1444 * convert_roam_trigger_scan_mode() - Function to convert unified Roam trigger 1445 * scan mode enum to TLV specific ROAM_TRIGGER_SCAN_MODE 1446 * @scan_freq_scheme: scan freq scheme coming from userspace 1447 * 1448 * Return: ROAM_TRIGGER_SCAN_MODE 1449 */ 1450 static WMI_ROAM_TRIGGER_SCAN_MODE 1451 convert_roam_trigger_scan_mode(enum roam_scan_freq_scheme scan_freq_scheme) 1452 { 1453 switch (scan_freq_scheme) { 1454 case ROAM_SCAN_FREQ_SCHEME_NO_SCAN: 1455 return ROAM_TRIGGER_SCAN_MODE_NO_SCAN_DISCONNECTION; 1456 case ROAM_SCAN_FREQ_SCHEME_PARTIAL_SCAN: 1457 return ROAM_TRIGGER_SCAN_MODE_PARTIAL; 1458 case ROAM_SCAN_FREQ_SCHEME_FULL_SCAN: 1459 return ROAM_TRIGGER_SCAN_MODE_FULL; 1460 default: 1461 return ROAM_TRIGGER_SCAN_MODE_NONE; 1462 } 1463 } 1464 1465 /** 1466 * wmi_fill_default_roam_trigger_parameters() - Fill the default parameters 1467 * for wmi_configure_roam_trigger_parameters tlv. 1468 * @roam_trigger_params: pointer to wmi_configure_roam_trigger_parameters tlv 1469 * to be filled. 1470 * @roam_trigger: Roam trigger reason 1471 * 1472 * Return: None 1473 */ 1474 static void wmi_fill_default_roam_trigger_parameters( 1475 wmi_configure_roam_trigger_parameters *roam_trigger_params, 1476 uint32_t roam_trigger) 1477 { 1478 WMITLV_SET_HDR(&roam_trigger_params->tlv_header, 1479 WMITLV_TAG_STRUC_wmi_configure_roam_trigger_parameters, 1480 WMITLV_GET_STRUCT_TLVLEN(wmi_configure_roam_trigger_parameters)); 1481 1482 roam_trigger_params->trigger_reason = roam_trigger; 1483 roam_trigger_params->enable = 1; 1484 roam_trigger_params->scan_mode = ROAM_TRIGGER_SCAN_MODE_NONE; 1485 roam_trigger_params->trigger_rssi_threshold = 1486 ROAM_MAX_CFG_VALUE; 1487 roam_trigger_params->cand_ap_min_rssi_threshold = 1488 ROAM_MAX_CFG_VALUE; 1489 roam_trigger_params->cand_ap_min_rssi_threshold_5g = 1490 ROAM_MAX_CFG_VALUE; 1491 roam_trigger_params->cand_ap_min_rssi_threshold_6g = 1492 ROAM_MAX_CFG_VALUE; 1493 roam_trigger_params->roam_score_delta_percentage = 1494 ROAM_MAX_CFG_VALUE; 1495 roam_trigger_params->reason_code = ROAM_MAX_CFG_VALUE; 1496 } 1497 1498 static void wmi_fill_score_delta_params( 1499 wmi_configure_roam_trigger_parameters *roam_trigger_params, 1500 struct wlan_roam_triggers *triggers, 1501 uint8_t trig_index) 1502 { 1503 enum roam_trigger_reason trig_reason; 1504 1505 if (trig_index >= NUM_OF_ROAM_TRIGGERS) 1506 return; 1507 1508 trig_reason = 1509 triggers->score_delta_param[trig_index].trigger_reason; 1510 wmi_fill_default_roam_trigger_parameters( 1511 roam_trigger_params, 1512 convert_roam_trigger_reason(trig_reason)); 1513 roam_trigger_params->roam_score_delta_percentage = 1514 triggers->score_delta_param[trig_index].roam_score_delta; 1515 1516 wmi_debug("RSO_CFG: Score delta per: %d converted trig_reason: %d", 1517 roam_trigger_params->roam_score_delta_percentage, 1518 convert_roam_trigger_reason(trig_reason)); 1519 1520 } 1521 1522 static void wmi_fill_min_rssi_params( 1523 wmi_configure_roam_trigger_parameters *roam_trigger_params, 1524 struct wlan_roam_triggers *triggers, 1525 uint8_t trig_index) 1526 { 1527 enum roam_trigger_reason trig_reason; 1528 1529 if (trig_index >= NUM_OF_ROAM_MIN_RSSI) 1530 return; 1531 1532 trig_reason = 1533 triggers->min_rssi_params[trig_index].trigger_reason; 1534 wmi_fill_default_roam_trigger_parameters( 1535 roam_trigger_params, 1536 convert_roam_trigger_reason(trig_reason)); 1537 roam_trigger_params->cand_ap_min_rssi_threshold = 1538 triggers->min_rssi_params[trig_index].min_rssi; 1539 roam_trigger_params->cand_ap_min_rssi_threshold_5g = 1540 triggers->min_rssi_params[trig_index].min_rssi; 1541 roam_trigger_params->cand_ap_min_rssi_threshold_6g = 1542 triggers->min_rssi_params[trig_index].min_rssi; 1543 1544 wmi_debug("RSO_CFG: Min rssi thresh: %d converted trig_reason: %d", 1545 roam_trigger_params->cand_ap_min_rssi_threshold, 1546 convert_roam_trigger_reason(trig_reason)); 1547 } 1548 1549 /** 1550 * send_set_roam_trigger_cmd_tlv() - send set roam triggers to fw 1551 * @wmi_handle: wmi handle 1552 * @triggers: roam trigger bitmap to be enabled 1553 * 1554 * Send WMI_ROAM_ENABLE_DISABLE_TRIGGER_REASON_CMDID to fw. 1555 * 1556 * Return: QDF_STATUS 1557 */ 1558 static QDF_STATUS send_set_roam_trigger_cmd_tlv(wmi_unified_t wmi_handle, 1559 struct wlan_roam_triggers *triggers) 1560 { 1561 wmi_buf_t buf; 1562 wmi_roam_enable_disable_trigger_reason_fixed_param *cmd; 1563 uint32_t len = sizeof(*cmd); 1564 int ret; 1565 uint8_t *buf_ptr; 1566 wmi_configure_roam_trigger_parameters 1567 *roam_trigger_parameters; 1568 uint32_t num_triggers_enabled = 0; 1569 uint32_t roam_scan_scheme_bitmap = triggers->roam_scan_scheme_bitmap; 1570 uint32_t total_tlv_len = 0; 1571 1572 if (BIT(ROAM_TRIGGER_REASON_PER) & roam_scan_scheme_bitmap) 1573 num_triggers_enabled++; 1574 1575 if (BIT(ROAM_TRIGGER_REASON_BTC) & roam_scan_scheme_bitmap) 1576 num_triggers_enabled++; 1577 1578 if (BIT(ROAM_TRIGGER_REASON_BMISS) & roam_scan_scheme_bitmap) 1579 num_triggers_enabled++; 1580 1581 if (BIT(ROAM_TRIGGER_REASON_LOW_RSSI) & roam_scan_scheme_bitmap) 1582 num_triggers_enabled++; 1583 1584 if (BIT(ROAM_TRIGGER_REASON_BTM) & roam_scan_scheme_bitmap) 1585 num_triggers_enabled++; 1586 1587 if (BIT(ROAM_TRIGGER_REASON_BSS_LOAD) & roam_scan_scheme_bitmap) 1588 num_triggers_enabled++; 1589 1590 if (wmi_service_enabled(wmi_handle, 1591 wmi_service_configure_roam_trigger_param_support)) 1592 total_tlv_len += (NUM_OF_ROAM_TRIGGERS + NUM_OF_ROAM_MIN_RSSI) * 1593 sizeof(wmi_configure_roam_trigger_parameters); 1594 1595 total_tlv_len += 2 * sizeof(wmi_configure_roam_trigger_parameters) + 1596 num_triggers_enabled * 1597 sizeof(wmi_configure_roam_trigger_parameters); 1598 len += WMI_TLV_HDR_SIZE + total_tlv_len; 1599 1600 buf = wmi_buf_alloc(wmi_handle, len); 1601 if (!buf) { 1602 wmi_err("Failed to allocate wmi buffer"); 1603 return QDF_STATUS_E_NOMEM; 1604 } 1605 1606 buf_ptr = (uint8_t *)wmi_buf_data(buf); 1607 1608 cmd = (wmi_roam_enable_disable_trigger_reason_fixed_param *) 1609 wmi_buf_data(buf); 1610 WMITLV_SET_HDR(&cmd->tlv_header, 1611 WMITLV_TAG_STRUC_wmi_roam_enable_disable_trigger_reason_fixed_param, 1612 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_enable_disable_trigger_reason_fixed_param)); 1613 1614 cmd->vdev_id = triggers->vdev_id; 1615 cmd->trigger_reason_bitmask = 1616 convert_control_roam_trigger_reason_bitmap(triggers->trigger_bitmap); 1617 wmi_debug("RSO_CFG: Received trigger bitmap: 0x%x converted trigger_bitmap: 0x%x", 1618 triggers->trigger_bitmap, cmd->trigger_reason_bitmask); 1619 cmd->trigger_reason_bitmask |= get_internal_mandatory_roam_triggers(); 1620 wmi_debug("RSO_CFG: vdev id: %d final trigger_bitmap: 0x%x roam_scan_scheme:0x%x num_triggers_enabled:%d", 1621 cmd->vdev_id, cmd->trigger_reason_bitmask, 1622 roam_scan_scheme_bitmap, num_triggers_enabled); 1623 1624 buf_ptr += sizeof(wmi_roam_enable_disable_trigger_reason_fixed_param); 1625 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, total_tlv_len); 1626 buf_ptr += WMI_TLV_HDR_SIZE; 1627 1628 roam_trigger_parameters = 1629 (wmi_configure_roam_trigger_parameters *)buf_ptr; 1630 1631 WMITLV_SET_HDR(&roam_trigger_parameters->tlv_header, 1632 WMITLV_TAG_STRUC_wmi_configure_roam_trigger_parameters, 1633 WMITLV_GET_STRUCT_TLVLEN( 1634 wmi_configure_roam_trigger_parameters)); 1635 roam_trigger_parameters->trigger_reason = 1636 WMI_ROAM_TRIGGER_REASON_WTC_BTM; 1637 if (triggers->vendor_btm_param.user_roam_reason == 0) 1638 roam_trigger_parameters->enable = 1; 1639 roam_trigger_parameters->scan_mode = convert_roam_trigger_scan_mode( 1640 triggers->vendor_btm_param.scan_freq_scheme); 1641 roam_trigger_parameters->trigger_rssi_threshold = 1642 triggers->vendor_btm_param.connected_rssi_threshold; 1643 roam_trigger_parameters->cand_ap_min_rssi_threshold = 1644 triggers->vendor_btm_param.candidate_rssi_threshold_2g; 1645 roam_trigger_parameters->cand_ap_min_rssi_threshold_5g = 1646 triggers->vendor_btm_param.candidate_rssi_threshold_5g; 1647 roam_trigger_parameters->cand_ap_min_rssi_threshold_6g = 1648 triggers->vendor_btm_param.candidate_rssi_threshold_6g; 1649 roam_trigger_parameters->roam_score_delta_percentage = 1650 triggers->roam_score_delta; 1651 roam_trigger_parameters->reason_code = 1652 triggers->vendor_btm_param.user_roam_reason; 1653 1654 roam_trigger_parameters++; 1655 1656 if (wmi_service_enabled(wmi_handle, 1657 wmi_service_configure_roam_trigger_param_support)) { 1658 wmi_fill_score_delta_params(roam_trigger_parameters, 1659 triggers, 1660 IDLE_ROAM_TRIGGER); 1661 if (cmd->trigger_reason_bitmask & 1662 BIT(WMI_ROAM_TRIGGER_REASON_IDLE)) 1663 roam_trigger_parameters->enable = 1; 1664 else 1665 roam_trigger_parameters->enable = 0; 1666 1667 roam_trigger_parameters++; 1668 1669 wmi_fill_score_delta_params(roam_trigger_parameters, 1670 triggers, 1671 BTM_ROAM_TRIGGER); 1672 roam_trigger_parameters++; 1673 1674 wmi_fill_min_rssi_params(roam_trigger_parameters, 1675 triggers, 1676 DEAUTH_MIN_RSSI); 1677 roam_trigger_parameters++; 1678 1679 wmi_fill_min_rssi_params(roam_trigger_parameters, 1680 triggers, 1681 BMISS_MIN_RSSI); 1682 roam_trigger_parameters++; 1683 1684 wmi_fill_min_rssi_params(roam_trigger_parameters, 1685 triggers, 1686 MIN_RSSI_2G_TO_5G_ROAM); 1687 roam_trigger_parameters++; 1688 } 1689 1690 wmi_fill_default_roam_trigger_parameters( 1691 roam_trigger_parameters, 1692 WMI_ROAM_TRIGGER_REASON_PMK_TIMEOUT); 1693 1694 if (cmd->trigger_reason_bitmask & 1695 BIT(WMI_ROAM_TRIGGER_REASON_PMK_TIMEOUT)) 1696 roam_trigger_parameters->enable = 1; 1697 else 1698 roam_trigger_parameters->enable = 0; 1699 1700 roam_trigger_parameters->roam_score_delta_percentage = 0; 1701 roam_trigger_parameters++; 1702 1703 if (num_triggers_enabled == 0) 1704 goto send; 1705 1706 if (BIT(ROAM_TRIGGER_REASON_PER) & roam_scan_scheme_bitmap) { 1707 wmi_fill_default_roam_trigger_parameters( 1708 roam_trigger_parameters, 1709 WMI_ROAM_TRIGGER_REASON_PER); 1710 roam_trigger_parameters->scan_mode = 1711 ROAM_TRIGGER_SCAN_MODE_PARTIAL; 1712 1713 roam_trigger_parameters++; 1714 } 1715 1716 if (BIT(ROAM_TRIGGER_REASON_BTC) & roam_scan_scheme_bitmap) { 1717 wmi_fill_default_roam_trigger_parameters( 1718 roam_trigger_parameters, 1719 WMI_ROAM_TRIGGER_REASON_BTC); 1720 roam_trigger_parameters->scan_mode = 1721 ROAM_TRIGGER_SCAN_MODE_PARTIAL; 1722 1723 roam_trigger_parameters++; 1724 } 1725 1726 if (BIT(ROAM_TRIGGER_REASON_BMISS) & roam_scan_scheme_bitmap) { 1727 wmi_fill_default_roam_trigger_parameters( 1728 roam_trigger_parameters, 1729 WMI_ROAM_TRIGGER_REASON_BMISS); 1730 roam_trigger_parameters->scan_mode = 1731 ROAM_TRIGGER_SCAN_MODE_PARTIAL; 1732 1733 roam_trigger_parameters++; 1734 } 1735 1736 if (BIT(ROAM_TRIGGER_REASON_LOW_RSSI) & roam_scan_scheme_bitmap) { 1737 wmi_fill_default_roam_trigger_parameters( 1738 roam_trigger_parameters, 1739 WMI_ROAM_TRIGGER_REASON_LOW_RSSI); 1740 roam_trigger_parameters->scan_mode = 1741 ROAM_TRIGGER_SCAN_MODE_PARTIAL; 1742 1743 roam_trigger_parameters++; 1744 } 1745 1746 if (BIT(ROAM_TRIGGER_REASON_BTM) & roam_scan_scheme_bitmap) { 1747 wmi_fill_default_roam_trigger_parameters( 1748 roam_trigger_parameters, 1749 WMI_ROAM_TRIGGER_REASON_BTM); 1750 roam_trigger_parameters->scan_mode = 1751 ROAM_TRIGGER_SCAN_MODE_PARTIAL; 1752 1753 roam_trigger_parameters++; 1754 } 1755 1756 if (BIT(ROAM_TRIGGER_REASON_BSS_LOAD) & roam_scan_scheme_bitmap) { 1757 wmi_fill_default_roam_trigger_parameters( 1758 roam_trigger_parameters, 1759 WMI_ROAM_TRIGGER_REASON_BSS_LOAD); 1760 roam_trigger_parameters->scan_mode = 1761 ROAM_TRIGGER_SCAN_MODE_PARTIAL; 1762 1763 roam_trigger_parameters++; 1764 } 1765 1766 send: 1767 wmi_mtrace(WMI_ROAM_ENABLE_DISABLE_TRIGGER_REASON_CMDID, 1768 triggers->vdev_id, 0); 1769 ret = wmi_unified_cmd_send(wmi_handle, buf, len, 1770 WMI_ROAM_ENABLE_DISABLE_TRIGGER_REASON_CMDID); 1771 if (QDF_IS_STATUS_ERROR(ret)) { 1772 wmi_err("Failed to send set roam triggers command ret = %d", 1773 ret); 1774 wmi_buf_free(buf); 1775 } 1776 return ret; 1777 } 1778 1779 /** 1780 * send_vdev_set_pcl_cmd_tlv() - Send WMI_VDEV_SET_PCL_CMDID to FW 1781 * @wmi_handle: wmi handle 1782 * @params: Set VDEV PCL params 1783 * 1784 * WMI_VDEV_SET_PCL_CMDID provides the Preferred Channel List (PCL) to WLAN 1785 * firmware. The roaming module is the consumer of this information 1786 * in the WLAN firmware. The channel list will be used when a VDEV needs 1787 * to migrate to a new channel without host driver involvement. An example of 1788 * this behavior is Legacy Fast Roaming (LFR 3.0). 1789 * 1790 * WMI_VDEV_SET_PCL_CMDID will carry only the weight list and not the actual 1791 * channel list. The weights corresponds to the channels sent in 1792 * WMI_SCAN_CHAN_LIST_CMDID. The channels from PCL would be having a higher 1793 * weightage compared to the non PCL channels. 1794 * 1795 * When roaming is enabled on STA 1, PDEV pcl will be sent. When STA2 is 1796 * up, VDEV pcl will be sent on STA 1 after calculating pcl again applying 1797 * the bandmask and VDEV pcl will be sent for STA2. When one of the STA 1798 * is disconnected, PDEV pcl will be sent on the other STA again. 1799 * 1800 * Return: Success if the cmd is sent successfully to the firmware 1801 */ 1802 static QDF_STATUS 1803 send_vdev_set_pcl_cmd_tlv(wmi_unified_t wmi_handle, 1804 struct set_pcl_cmd_params *params) 1805 { 1806 wmi_vdev_set_pcl_cmd_fixed_param *cmd; 1807 wmi_buf_t buf; 1808 uint8_t *buf_ptr; 1809 uint32_t *ch_weight, i; 1810 size_t len; 1811 uint32_t chan_len; 1812 1813 chan_len = params->weights->saved_num_chan; 1814 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + (chan_len * sizeof(uint32_t)); 1815 1816 buf = wmi_buf_alloc(wmi_handle, len); 1817 if (!buf) 1818 return QDF_STATUS_E_NOMEM; 1819 1820 cmd = (wmi_vdev_set_pcl_cmd_fixed_param *)wmi_buf_data(buf); 1821 buf_ptr = (uint8_t *)cmd; 1822 WMITLV_SET_HDR(&cmd->tlv_header, 1823 WMITLV_TAG_STRUC_wmi_vdev_set_pcl_cmd_fixed_param, 1824 WMITLV_GET_STRUCT_TLVLEN(wmi_vdev_set_pcl_cmd_fixed_param)); 1825 cmd->vdev_id = params->vdev_id; 1826 buf_ptr += sizeof(wmi_vdev_set_pcl_cmd_fixed_param); 1827 1828 /* Channel weights uint32 Array TLV */ 1829 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 1830 (chan_len * sizeof(uint32_t))); 1831 ch_weight = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE); 1832 for (i = 0; i < chan_len; i++) 1833 ch_weight[i] = params->weights->weighed_valid_list[i]; 1834 1835 wmi_mtrace(WMI_VDEV_SET_PCL_CMDID, params->vdev_id, 0); 1836 if (wmi_unified_cmd_send(wmi_handle, buf, len, 1837 WMI_VDEV_SET_PCL_CMDID)) { 1838 wmi_err("Failed to send WMI_VDEV_SET_PCL_CMDID"); 1839 wmi_buf_free(buf); 1840 return QDF_STATUS_E_FAILURE; 1841 } 1842 1843 return QDF_STATUS_SUCCESS; 1844 } 1845 1846 /** 1847 * extract_roam_btm_response_stats_tlv() - Extract the btm rsp stats 1848 * from the WMI_ROAM_STATS_EVENTID 1849 * @wmi_handle: wmi handle 1850 * @evt_buf: Pointer to the event buffer 1851 * @dst: Pointer to destination structure to fill data 1852 * @idx: TLV id 1853 */ 1854 static QDF_STATUS 1855 extract_roam_btm_response_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, 1856 struct roam_btm_response_data *dst, 1857 uint8_t idx) 1858 { 1859 WMI_ROAM_STATS_EVENTID_param_tlvs *param_buf; 1860 wmi_roam_btm_response_info *src_data = NULL; 1861 1862 param_buf = (WMI_ROAM_STATS_EVENTID_param_tlvs *)evt_buf; 1863 1864 if (!param_buf || !param_buf->roam_btm_response_info || 1865 !param_buf->num_roam_btm_response_info || 1866 idx >= param_buf->num_roam_btm_response_info) { 1867 wmi_debug("Empty btm response param buf"); 1868 return QDF_STATUS_SUCCESS; 1869 } 1870 1871 src_data = ¶m_buf->roam_btm_response_info[idx]; 1872 if (!src_data->timestamp) 1873 return QDF_STATUS_SUCCESS; 1874 1875 dst->present = true; 1876 dst->btm_status = src_data->btm_status; 1877 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_data->target_bssid, 1878 dst->target_bssid.bytes); 1879 dst->vsie_reason = src_data->vsie_reason; 1880 dst->timestamp = src_data->timestamp; 1881 dst->btm_resp_dialog_token = src_data->btm_resp_dialog_token; 1882 dst->btm_delay = src_data->btm_resp_bss_termination_delay; 1883 dst->band = WMI_ROAM_BTM_RESP_MLO_BAND_INFO_GET(src_data->info); 1884 if (dst->band != WMI_MLO_BAND_NO_MLO) 1885 dst->is_mlo = true; 1886 1887 return QDF_STATUS_SUCCESS; 1888 } 1889 1890 /** 1891 * extract_roam_initial_info_tlv() - Extract the roam initial info 1892 * from the WMI_ROAM_STATS_EVENTID 1893 * @wmi_handle: wmi handle 1894 * @evt_buf: Pointer to the event buffer 1895 * @dst: Pointer to destination structure to fill data 1896 * @idx: TLV id 1897 */ 1898 static QDF_STATUS 1899 extract_roam_initial_info_tlv(wmi_unified_t wmi_handle, void *evt_buf, 1900 struct roam_initial_data *dst, uint8_t idx) 1901 { 1902 WMI_ROAM_STATS_EVENTID_param_tlvs *param_buf; 1903 wmi_roam_initial_info *src_data = NULL; 1904 1905 param_buf = (WMI_ROAM_STATS_EVENTID_param_tlvs *)evt_buf; 1906 1907 if (!param_buf || !param_buf->roam_initial_info || 1908 !param_buf->num_roam_initial_info || 1909 idx >= param_buf->num_roam_initial_info) { 1910 wmi_debug("Empty roam_initial_info param buf"); 1911 return QDF_STATUS_SUCCESS; 1912 } 1913 1914 src_data = ¶m_buf->roam_initial_info[idx]; 1915 1916 dst->present = true; 1917 dst->roam_full_scan_count = src_data->roam_full_scan_count; 1918 dst->rssi_th = src_data->rssi_th; 1919 dst->cu_th = src_data->cu_th; 1920 dst->fw_cancel_timer_bitmap = src_data->timer_canceled; 1921 1922 return QDF_STATUS_SUCCESS; 1923 } 1924 1925 /** 1926 * extract_roam_msg_info_tlv() - Extract the roam message info 1927 * from the WMI_ROAM_STATS_EVENTID 1928 * @wmi_handle: wmi handle 1929 * @evt_buf: Pointer to the event buffer 1930 * @dst: Pointer to destination structure to fill data 1931 * @idx: TLV id 1932 */ 1933 static QDF_STATUS 1934 extract_roam_msg_info_tlv(wmi_unified_t wmi_handle, void *evt_buf, 1935 struct roam_msg_info *dst, uint8_t idx) 1936 { 1937 WMI_ROAM_STATS_EVENTID_param_tlvs *param_buf; 1938 wmi_roam_msg_info *src_data = NULL; 1939 1940 param_buf = (WMI_ROAM_STATS_EVENTID_param_tlvs *)evt_buf; 1941 1942 if (!param_buf || !param_buf->roam_msg_info || 1943 !param_buf->num_roam_msg_info || 1944 idx >= param_buf->num_roam_msg_info) 1945 return QDF_STATUS_SUCCESS; 1946 1947 src_data = ¶m_buf->roam_msg_info[idx]; 1948 1949 dst->present = true; 1950 dst->timestamp = src_data->timestamp; 1951 dst->msg_id = src_data->msg_id; 1952 dst->msg_param1 = src_data->msg_param1; 1953 dst->msg_param2 = src_data->msg_param2; 1954 1955 return QDF_STATUS_SUCCESS; 1956 } 1957 1958 static enum wlan_roam_frame_subtype 1959 wmi_get_converted_roam_eapol_subtype( 1960 WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_SUBTYPE eapol_subtype) 1961 { 1962 switch (eapol_subtype) { 1963 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_SUBTYPE_M1: 1964 return ROAM_FRAME_SUBTYPE_M1; 1965 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_SUBTYPE_M2: 1966 return ROAM_FRAME_SUBTYPE_M2; 1967 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_SUBTYPE_M3: 1968 return ROAM_FRAME_SUBTYPE_M3; 1969 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_SUBTYPE_M4: 1970 return ROAM_FRAME_SUBTYPE_M4; 1971 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_SUBTYPE_GTK_M1: 1972 return ROAM_FRAME_SUBTYPE_GTK_M1; 1973 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_SUBTYPE_GTK_M2: 1974 return ROAM_FRAME_SUBTYPE_GTK_M2; 1975 default: 1976 break; 1977 } 1978 1979 return 0; 1980 } 1981 1982 static enum qdf_dp_tx_rx_status 1983 wmi_get_converted_tx_status( 1984 WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_STATUS roam_tx_status) 1985 { 1986 switch (roam_tx_status) { 1987 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_STATUS_ACK: 1988 return QDF_TX_RX_STATUS_OK; 1989 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_STATUS_NO_ACK: 1990 return QDF_TX_RX_STATUS_NO_ACK; 1991 case WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT_STATUS_TX_FAIL: 1992 return QDF_TX_RX_STATUS_DROP; 1993 default: 1994 break; 1995 } 1996 1997 return QDF_TX_RX_STATUS_INVALID; 1998 } 1999 2000 #define WLAN_FC0_SUBTYPE_SHIFT 4 2001 #define WLAN_FRAME_INFO_TYPE_OFFSET 0 2002 #define WLAN_FRAME_INFO_SUBTYPE_OFFSET 2 2003 #define WLAN_FRAME_INFO_RESP_OFFSET 6 2004 #define WLAN_FRAME_INFO_AUTH_ALG_OFFSET 7 2005 #define WLAN_FRAME_INFO_SEQ_NUM_OFFSET 16 2006 2007 /** 2008 * extract_roam_frame_info_tlv() - Extract the frame exchanges during roaming 2009 * info from the WMI_ROAM_STATS_EVENTID 2010 * @wmi_handle: wmi handle 2011 * @evt_buf: Pointer to the event buffer 2012 * @dst: Pointer to destination structure to fill data 2013 * @frame_idx: TLV id 2014 * @num_frames: Number of Frame TLVs to be extracted 2015 */ 2016 static QDF_STATUS 2017 extract_roam_frame_info_tlv(wmi_unified_t wmi_handle, void *evt_buf, 2018 struct roam_frame_stats *dst, uint8_t frame_idx, 2019 uint8_t num_frames) 2020 { 2021 WMI_ROAM_STATS_EVENTID_param_tlvs *param_buf; 2022 wmi_roam_frame_info *src_data = NULL; 2023 struct roam_frame_info *dst_buf; 2024 uint8_t i, subtype; 2025 2026 param_buf = (WMI_ROAM_STATS_EVENTID_param_tlvs *)evt_buf; 2027 2028 if (!param_buf || !param_buf->roam_frame_info || 2029 !param_buf->num_roam_frame_info || 2030 (frame_idx + num_frames) > param_buf->num_roam_frame_info) { 2031 wmi_err("Empty roam_frame_info param buf frame_idx:%d num_frames:%d", 2032 frame_idx, num_frames); 2033 return QDF_STATUS_SUCCESS; 2034 } 2035 2036 src_data = ¶m_buf->roam_frame_info[frame_idx]; 2037 2038 if (num_frames > WLAN_ROAM_MAX_FRAME_INFO) 2039 num_frames = WLAN_ROAM_MAX_FRAME_INFO; 2040 2041 dst->num_frame = num_frames; 2042 dst_buf = dst->frame_info; 2043 for (i = 0; i < num_frames; i++) { 2044 dst_buf->timestamp = src_data->timestamp; 2045 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_data->bssid, 2046 dst_buf->bssid.bytes); 2047 dst_buf->type = WMI_GET_BITS(src_data->frame_info, 2048 WLAN_FRAME_INFO_TYPE_OFFSET, 2); 2049 2050 subtype = WMI_GET_BITS(src_data->frame_info, 2051 WLAN_FRAME_INFO_SUBTYPE_OFFSET, 4); 2052 if (dst_buf->type == WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT) { 2053 dst_buf->type = ROAM_FRAME_INFO_FRAME_TYPE_EXT; 2054 dst_buf->subtype = 2055 wmi_get_converted_roam_eapol_subtype(subtype); 2056 } else { 2057 dst_buf->subtype = subtype << WLAN_FC0_SUBTYPE_SHIFT; 2058 } 2059 2060 dst_buf->is_rsp = WMI_GET_BITS(src_data->frame_info, 2061 WLAN_FRAME_INFO_RESP_OFFSET, 1); 2062 dst_buf->seq_num = WMI_GET_BITS(src_data->frame_info, 2063 WLAN_FRAME_INFO_SEQ_NUM_OFFSET, 2064 16); 2065 dst_buf->status_code = src_data->status_code; 2066 if (dst_buf->type != WMI_ROAM_FRAME_INFO_FRAME_TYPE_EXT && 2067 dst_buf->subtype == MGMT_SUBTYPE_AUTH) 2068 dst_buf->auth_algo = 2069 WMI_GET_BITS(src_data->frame_info, 2070 WLAN_FRAME_INFO_AUTH_ALG_OFFSET, 2071 4); 2072 2073 if (!dst_buf->is_rsp) { 2074 dst_buf->tx_status = wmi_get_converted_tx_status( 2075 src_data->status_code); 2076 /* wmi_roam_frame_info->status_code sent from the fw 2077 * denotes the tx_status of the transmitted frames. 2078 * To Do: Need a separate field for status code or 2079 * use existing field of wmi_roam_frame_info tlv 2080 * to send the tx status of transmitted frame from the 2081 * FW. 2082 */ 2083 dst_buf->status_code = 0; 2084 } 2085 2086 dst_buf->retry_count = src_data->retry_count; 2087 dst_buf->rssi = (-1) * src_data->rssi_dbm_abs; 2088 dst_buf->assoc_id = 2089 WMI_GET_ASSOC_ID(src_data->frame_info_ext); 2090 2091 dst_buf->band = 2092 WMI_GET_MLO_BITMAP_BAND_INFO(src_data->frame_info_ext); 2093 2094 dst_buf++; 2095 src_data++; 2096 } 2097 2098 return QDF_STATUS_SUCCESS; 2099 } 2100 2101 /** 2102 * wmi_fill_data_synch_frame_event() - Fill the the roam sync data buffer using 2103 * synch frame event data 2104 * @rso_cfg: Source buffer 2105 * @roam_sync_ind: Buffer to be filled 2106 * 2107 * Firmware sends all the required information required for roam 2108 * synch propagation as TLV's and stored in param_buf. These 2109 * parameters are parsed and filled into the roam synch indication 2110 * buffer which will be used at different layers for propagation. 2111 * 2112 * Return: None 2113 */ 2114 static void 2115 wmi_fill_data_synch_frame_event(struct rso_config *rso_cfg, 2116 struct roam_offload_synch_ind *roam_sync_ind) 2117 { 2118 uint8_t *bcn_probersp_ptr, *link_bcn_probersp_ptr; 2119 uint8_t *reassoc_rsp_ptr; 2120 uint8_t *reassoc_req_ptr; 2121 2122 /* Beacon/Probe Rsp data */ 2123 roam_sync_ind->beacon_probe_resp_offset = 2124 sizeof(struct roam_offload_synch_ind); 2125 bcn_probersp_ptr = (uint8_t *)roam_sync_ind + 2126 roam_sync_ind->beacon_probe_resp_offset; 2127 roam_sync_ind->beacon_probe_resp_length = 2128 rso_cfg->roam_sync_frame_ind.bcn_probe_rsp_len; 2129 qdf_mem_copy(bcn_probersp_ptr, 2130 rso_cfg->roam_sync_frame_ind.bcn_probe_rsp, 2131 roam_sync_ind->beacon_probe_resp_length); 2132 qdf_mem_free(rso_cfg->roam_sync_frame_ind.bcn_probe_rsp); 2133 rso_cfg->roam_sync_frame_ind.bcn_probe_rsp = NULL; 2134 2135 /* Link beacon/probe rsp data */ 2136 if (rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp) { 2137 roam_sync_ind->link_beacon_probe_resp_offset = 2138 sizeof(struct roam_offload_synch_ind) + 2139 roam_sync_ind->beacon_probe_resp_length; 2140 roam_sync_ind->link_beacon_probe_resp_length = 2141 rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp_len; 2142 roam_sync_ind->is_link_beacon = 2143 rso_cfg->roam_sync_frame_ind.is_link_beacon; 2144 link_bcn_probersp_ptr = (uint8_t *)roam_sync_ind + 2145 roam_sync_ind->link_beacon_probe_resp_offset; 2146 qdf_mem_copy(link_bcn_probersp_ptr, 2147 rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp, 2148 roam_sync_ind->link_beacon_probe_resp_length); 2149 qdf_mem_free(rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp); 2150 rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp = NULL; 2151 } 2152 2153 /* ReAssoc Rsp data */ 2154 roam_sync_ind->reassoc_resp_offset = 2155 sizeof(struct roam_offload_synch_ind) + 2156 roam_sync_ind->beacon_probe_resp_length + 2157 roam_sync_ind->link_beacon_probe_resp_length; 2158 roam_sync_ind->reassoc_resp_length = 2159 rso_cfg->roam_sync_frame_ind.reassoc_rsp_len; 2160 reassoc_rsp_ptr = (uint8_t *)roam_sync_ind + 2161 roam_sync_ind->reassoc_resp_offset; 2162 qdf_mem_copy(reassoc_rsp_ptr, 2163 rso_cfg->roam_sync_frame_ind.reassoc_rsp, 2164 roam_sync_ind->reassoc_resp_length); 2165 qdf_mem_free(rso_cfg->roam_sync_frame_ind.reassoc_rsp); 2166 rso_cfg->roam_sync_frame_ind.reassoc_rsp = NULL; 2167 2168 /* ReAssoc Req data */ 2169 roam_sync_ind->reassoc_req_offset = 2170 sizeof(struct roam_offload_synch_ind) + 2171 roam_sync_ind->beacon_probe_resp_length + 2172 roam_sync_ind->link_beacon_probe_resp_length + 2173 roam_sync_ind->reassoc_resp_length; 2174 roam_sync_ind->reassoc_req_length = 2175 rso_cfg->roam_sync_frame_ind.reassoc_req_len; 2176 reassoc_req_ptr = (uint8_t *)roam_sync_ind + 2177 roam_sync_ind->reassoc_req_offset; 2178 qdf_mem_copy(reassoc_req_ptr, 2179 rso_cfg->roam_sync_frame_ind.reassoc_req, 2180 roam_sync_ind->reassoc_req_length); 2181 qdf_mem_free(rso_cfg->roam_sync_frame_ind.reassoc_req); 2182 rso_cfg->roam_sync_frame_ind.reassoc_req = NULL; 2183 } 2184 2185 /** 2186 * wmi_fill_data_synch_event() - Fill the the roam sync data buffer 2187 * using synch event data 2188 * @roam_sync_ind: Buffer to be filled 2189 * @param_buf: Source buffer 2190 * 2191 * Firmware sends all the required information required for roam 2192 * synch propagation as TLV's and stored in param_buf. These 2193 * parameters are parsed and filled into the roam synch indication 2194 * buffer which will be used at different layers for propagation. 2195 * 2196 * Return: None 2197 */ 2198 static void 2199 wmi_fill_data_synch_event(struct roam_offload_synch_ind *roam_sync_ind, 2200 WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf) 2201 { 2202 uint8_t *bcn_probersp_ptr; 2203 uint8_t *reassoc_rsp_ptr; 2204 uint8_t *reassoc_req_ptr; 2205 wmi_roam_synch_event_fixed_param *synch_event; 2206 2207 synch_event = param_buf->fixed_param; 2208 2209 /* Beacon/Probe Rsp data */ 2210 roam_sync_ind->beacon_probe_resp_offset = 2211 sizeof(struct roam_offload_synch_ind); 2212 bcn_probersp_ptr = (uint8_t *)roam_sync_ind + 2213 roam_sync_ind->beacon_probe_resp_offset; 2214 roam_sync_ind->beacon_probe_resp_length = 2215 synch_event->bcn_probe_rsp_len; 2216 qdf_mem_copy(bcn_probersp_ptr, param_buf->bcn_probe_rsp_frame, 2217 roam_sync_ind->beacon_probe_resp_length); 2218 /* 2219 * Firmware doesn't support link beacon/Probe Rsp data in roam sync 2220 * event. It's always sent in sync_frame event 2221 */ 2222 /* ReAssoc Rsp data */ 2223 roam_sync_ind->reassoc_resp_offset = 2224 sizeof(struct roam_offload_synch_ind) + 2225 roam_sync_ind->beacon_probe_resp_length; 2226 roam_sync_ind->reassoc_resp_length = synch_event->reassoc_rsp_len; 2227 reassoc_rsp_ptr = (uint8_t *)roam_sync_ind + 2228 roam_sync_ind->reassoc_resp_offset; 2229 qdf_mem_copy(reassoc_rsp_ptr, 2230 param_buf->reassoc_rsp_frame, 2231 roam_sync_ind->reassoc_resp_length); 2232 2233 /* ReAssoc Req data */ 2234 roam_sync_ind->reassoc_req_offset = 2235 sizeof(struct roam_offload_synch_ind) + 2236 roam_sync_ind->beacon_probe_resp_length + 2237 roam_sync_ind->reassoc_resp_length; 2238 roam_sync_ind->reassoc_req_length = synch_event->reassoc_req_len; 2239 reassoc_req_ptr = (uint8_t *)roam_sync_ind + 2240 roam_sync_ind->reassoc_req_offset; 2241 qdf_mem_copy(reassoc_req_ptr, param_buf->reassoc_req_frame, 2242 roam_sync_ind->reassoc_req_length); 2243 } 2244 2245 #ifdef WLAN_FEATURE_11BE_MLO 2246 #define STANDBY_VDEV_ID (0xFFFFFFFF) 2247 static QDF_STATUS 2248 wmi_fill_roam_mlo_info(wmi_unified_t wmi_handle, 2249 WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf, 2250 struct roam_offload_synch_ind *roam_sync_ind) 2251 { 2252 uint8_t i, mlo_max_allowed_links; 2253 wmi_roam_ml_setup_links_param *setup_links; 2254 wmi_roam_ml_key_material_param *ml_key_param; 2255 struct ml_setup_link_param *link; 2256 struct ml_key_material_param *key; 2257 2258 mlo_max_allowed_links = 2259 wlan_mlme_get_sta_mlo_conn_max_num(wmi_handle->soc->wmi_psoc); 2260 if (param_buf->num_setup_links_param) { 2261 if (param_buf->num_setup_links_param > mlo_max_allowed_links || 2262 param_buf->num_setup_links_param > WLAN_MAX_ML_BSS_LINKS) { 2263 wmi_err("Number of links %d exceeded max vdev supported %d", 2264 param_buf->num_setup_links_param, 2265 mlo_max_allowed_links); 2266 return QDF_STATUS_E_INVAL; 2267 } 2268 2269 roam_sync_ind->num_setup_links = 2270 param_buf->num_setup_links_param; 2271 setup_links = param_buf->setup_links_param; 2272 2273 for (i = 0; i < roam_sync_ind->num_setup_links; i++) { 2274 link = &roam_sync_ind->ml_link[i]; 2275 link->link_id = setup_links->link_id; 2276 2277 /* 2278 * setup_links->vdev_id == UINT32_MAX for standby link 2279 */ 2280 link->vdev_id = WLAN_INVALID_VDEV_ID; 2281 if (setup_links->vdev_id != STANDBY_VDEV_ID) 2282 link->vdev_id = setup_links->vdev_id; 2283 2284 link->channel = setup_links->channel; 2285 link->flags = setup_links->flags; 2286 2287 WMI_MAC_ADDR_TO_CHAR_ARRAY(&setup_links->link_addr, 2288 link->link_addr.bytes); 2289 WMI_MAC_ADDR_TO_CHAR_ARRAY(&setup_links->self_link_addr, 2290 link->self_link_addr.bytes); 2291 wmi_debug("link_id: %u vdev_id: %u flags: 0x%x addr: " QDF_MAC_ADDR_FMT " self_addr:" QDF_MAC_ADDR_FMT, 2292 link->link_id, link->vdev_id, 2293 link->flags, 2294 QDF_MAC_ADDR_REF(link->link_addr.bytes), 2295 QDF_MAC_ADDR_REF(link->self_link_addr.bytes)); 2296 wmi_debug("channel: %u mhz center_freq1: %u center_freq2: %u", 2297 link->channel.mhz, 2298 link->channel.band_center_freq1, 2299 link->channel.band_center_freq2); 2300 setup_links++; 2301 } 2302 } 2303 2304 if (!param_buf->num_ml_key_material) 2305 return QDF_STATUS_SUCCESS; 2306 2307 if (param_buf->num_ml_key_material > WLAN_MAX_ML_BSS_LINKS) 2308 param_buf->num_ml_key_material = WLAN_MAX_ML_BSS_LINKS; 2309 2310 roam_sync_ind->num_ml_key_material = param_buf->num_ml_key_material; 2311 ml_key_param = param_buf->ml_key_material; 2312 2313 for (i = 0; i < roam_sync_ind->num_ml_key_material; i++) { 2314 key = &roam_sync_ind->ml_key[i]; 2315 key->link_id = ml_key_param->link_id; 2316 key->key_idx = ml_key_param->key_ix; 2317 key->key_cipher = ml_key_param->key_cipher; 2318 qdf_mem_copy(key->pn, ml_key_param->pn, 2319 WMI_MAX_PN_LEN); 2320 qdf_mem_copy(key->key_buff, ml_key_param->key_buff, 2321 WMI_MAX_KEY_LEN); 2322 wmi_debug("link_id: %u key_idx: %u key_cipher: %u", 2323 key->link_id, key->key_idx, key->key_cipher); 2324 ml_key_param++; 2325 } 2326 2327 return QDF_STATUS_SUCCESS; 2328 } 2329 #else 2330 static QDF_STATUS 2331 wmi_fill_roam_mlo_info(wmi_unified_t wmi_handle, 2332 WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf, 2333 struct roam_offload_synch_ind *roam_sync_ind) 2334 { 2335 return QDF_STATUS_SUCCESS; 2336 } 2337 #endif 2338 2339 static QDF_STATUS 2340 wmi_fill_roam_sync_buffer(wmi_unified_t wmi_handle, 2341 struct wlan_objmgr_vdev *vdev, 2342 struct rso_config *rso_cfg, 2343 struct roam_offload_synch_ind *roam_sync_ind, 2344 WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf) 2345 { 2346 wmi_roam_synch_event_fixed_param *synch_event; 2347 void *soc = cds_get_context(QDF_MODULE_ID_SOC); 2348 wmi_channel *chan = NULL; 2349 wmi_key_material *key; 2350 wmi_key_material_ext *key_ext; 2351 wmi_roam_fils_synch_tlv_param *fils_info; 2352 wmi_roam_pmk_cache_synch_tlv_param *pmk_cache_info; 2353 QDF_STATUS status = QDF_STATUS_E_FAILURE; 2354 uint8_t kck_len; 2355 uint8_t kek_len; 2356 struct roam_scan_candidate_frame roam_candidate = {0}; 2357 2358 synch_event = param_buf->fixed_param; 2359 roam_sync_ind->roamed_vdev_id = synch_event->vdev_id; 2360 roam_sync_ind->auth_status = synch_event->auth_status; 2361 roam_sync_ind->roam_reason = synch_event->roam_reason; 2362 roam_sync_ind->rssi = -1 * synch_event->rssi; 2363 roam_sync_ind->is_beacon = synch_event->is_beacon; 2364 2365 WMI_MAC_ADDR_TO_CHAR_ARRAY(&synch_event->bssid, 2366 roam_sync_ind->bssid.bytes); 2367 wmi_debug("roamed_vdev_id %d auth_status %d roam_reason %d rssi %d is_beacon %d", 2368 roam_sync_ind->roamed_vdev_id, 2369 roam_sync_ind->auth_status, 2370 roam_sync_ind->roam_reason, 2371 roam_sync_ind->rssi, 2372 roam_sync_ind->is_beacon); 2373 2374 cdp_update_roaming_peer_in_vdev(soc, synch_event->vdev_id, 2375 roam_sync_ind->bssid.bytes, 2376 synch_event->auth_status); 2377 /* 2378 * If lengths of bcn_probe_rsp, reassoc_req and reassoc_rsp are zero in 2379 * synch_event driver would have received bcn_probe_rsp, reassoc_req 2380 * and reassoc_rsp via the event WMI_ROAM_SYNCH_FRAME_EVENTID 2381 */ 2382 if ((!synch_event->bcn_probe_rsp_len) && 2383 (!synch_event->reassoc_req_len) && 2384 (!synch_event->reassoc_rsp_len)) { 2385 if (!rso_cfg->roam_sync_frame_ind.bcn_probe_rsp) { 2386 wmi_err("LFR3: bcn_probe_rsp is NULL"); 2387 QDF_ASSERT(rso_cfg->roam_sync_frame_ind.bcn_probe_rsp); 2388 wlan_cm_free_roam_synch_frame_ind(rso_cfg); 2389 return status; 2390 } 2391 2392 if (!rso_cfg->roam_sync_frame_ind.reassoc_rsp) { 2393 wmi_err("LFR3: reassoc_rsp is NULL"); 2394 QDF_ASSERT(rso_cfg->roam_sync_frame_ind.reassoc_rsp); 2395 wlan_cm_free_roam_synch_frame_ind(rso_cfg); 2396 return status; 2397 } 2398 if (!rso_cfg->roam_sync_frame_ind.reassoc_req) { 2399 wmi_err("LFR3: reassoc_req is NULL"); 2400 QDF_ASSERT(rso_cfg->roam_sync_frame_ind.reassoc_req); 2401 wlan_cm_free_roam_synch_frame_ind(rso_cfg); 2402 return status; 2403 } 2404 wmi_fill_data_synch_frame_event(rso_cfg, roam_sync_ind); 2405 } else { 2406 wmi_fill_data_synch_event(roam_sync_ind, param_buf); 2407 2408 roam_candidate.vdev_id = roam_sync_ind->roamed_vdev_id; 2409 roam_candidate.frame_length = 2410 roam_sync_ind->beacon_probe_resp_length; 2411 roam_candidate.frame = (uint8_t *)roam_sync_ind + 2412 roam_sync_ind->beacon_probe_resp_offset; 2413 roam_candidate.rssi = roam_sync_ind->rssi; 2414 roam_candidate.roam_offload_candidate_frm = false; 2415 wlan_cm_add_all_link_probe_rsp_to_scan_db(wlan_vdev_get_psoc(vdev), 2416 &roam_candidate); 2417 } 2418 chan = param_buf->chan; 2419 if (chan) { 2420 roam_sync_ind->chan_freq = chan->mhz; 2421 roam_sync_ind->phy_mode = 2422 wlan_cm_fw_to_host_phymode(WMI_GET_CHANNEL_MODE(chan)); 2423 roam_sync_ind->chan = *chan; 2424 } else { 2425 roam_sync_ind->phy_mode = WLAN_PHYMODE_AUTO; 2426 } 2427 2428 key = param_buf->key; 2429 key_ext = param_buf->key_ext; 2430 if (key) { 2431 roam_sync_ind->kck_len = KCK_KEY_LEN; 2432 qdf_mem_copy(roam_sync_ind->kck, key->kck, 2433 KCK_KEY_LEN); 2434 roam_sync_ind->kek_len = KEK_KEY_LEN; 2435 qdf_mem_copy(roam_sync_ind->kek, key->kek, 2436 KEK_KEY_LEN); 2437 qdf_mem_copy(roam_sync_ind->replay_ctr, 2438 key->replay_counter, REPLAY_CTR_LEN); 2439 } else if (key_ext) { 2440 /* 2441 * key_ext carries key materials whose size 2442 * is greater than conventional 16bytes. 2443 */ 2444 kck_len = key_ext->kck_len ? 2445 key_ext->kck_len : KCK_192BIT_KEY_LEN; 2446 kek_len = key_ext->kek_len ? 2447 key_ext->kek_len : KEK_256BIT_KEY_LEN; 2448 2449 roam_sync_ind->kck_len = kck_len; 2450 qdf_mem_copy(roam_sync_ind->kck, 2451 key_ext->key_buffer, kck_len); 2452 2453 roam_sync_ind->kek_len = kek_len; 2454 qdf_mem_copy(roam_sync_ind->kek, 2455 (key_ext->key_buffer + kck_len), 2456 kek_len); 2457 2458 qdf_mem_copy(roam_sync_ind->replay_ctr, 2459 (key_ext->key_buffer + kek_len + kck_len), 2460 REPLAY_CTR_LEN); 2461 } 2462 2463 wmi_debug("ROAM_SYNC kek_len %d kck_len %d", 2464 roam_sync_ind->kek_len, 2465 roam_sync_ind->kck_len); 2466 2467 if (param_buf->hw_mode_transition_fixed_param) { 2468 wmi_extract_pdev_hw_mode_trans_ind( 2469 param_buf->hw_mode_transition_fixed_param, 2470 param_buf->wmi_pdev_set_hw_mode_response_vdev_mac_mapping, 2471 &roam_sync_ind->hw_mode_trans_ind); 2472 roam_sync_ind->hw_mode_trans_present = true; 2473 } else { 2474 wmi_debug("hw_mode transition fixed param is NULL"); 2475 } 2476 2477 fils_info = param_buf->roam_fils_synch_info; 2478 if (fils_info) { 2479 if ((fils_info->kek_len > MAX_KEK_LENGTH) || 2480 (fils_info->pmk_len > MAX_PMK_LEN)) { 2481 wmi_err("Invalid kek_len %d or pmk_len %d", 2482 fils_info->kek_len, 2483 fils_info->pmk_len); 2484 wlan_cm_free_roam_synch_frame_ind(rso_cfg); 2485 return status; 2486 } 2487 2488 roam_sync_ind->kek_len = fils_info->kek_len; 2489 qdf_mem_copy(roam_sync_ind->kek, fils_info->kek, 2490 fils_info->kek_len); 2491 2492 roam_sync_ind->pmk_len = fils_info->pmk_len; 2493 qdf_mem_copy(roam_sync_ind->pmk, fils_info->pmk, 2494 fils_info->pmk_len); 2495 2496 qdf_mem_copy(roam_sync_ind->pmkid, fils_info->pmkid, 2497 PMKID_LEN); 2498 2499 roam_sync_ind->update_erp_next_seq_num = 2500 fils_info->update_erp_next_seq_num; 2501 roam_sync_ind->next_erp_seq_num = 2502 fils_info->next_erp_seq_num; 2503 2504 wmi_debug("Update ERP Seq Num %d, Next ERP Seq Num %d KEK len %d", 2505 roam_sync_ind->update_erp_next_seq_num, 2506 roam_sync_ind->next_erp_seq_num, 2507 roam_sync_ind->kek_len); 2508 } 2509 2510 pmk_cache_info = param_buf->roam_pmk_cache_synch_info; 2511 if (pmk_cache_info && (pmk_cache_info->pmk_len)) { 2512 if (pmk_cache_info->pmk_len > MAX_PMK_LEN) { 2513 wmi_err("Invalid pmk_len %d", 2514 pmk_cache_info->pmk_len); 2515 wlan_cm_free_roam_synch_frame_ind(rso_cfg); 2516 return status; 2517 } 2518 2519 roam_sync_ind->pmk_len = pmk_cache_info->pmk_len; 2520 qdf_mem_copy(roam_sync_ind->pmk, 2521 pmk_cache_info->pmk, pmk_cache_info->pmk_len); 2522 qdf_mem_copy(roam_sync_ind->pmkid, 2523 pmk_cache_info->pmkid, PMKID_LEN); 2524 } 2525 2526 status = wmi_fill_roam_mlo_info(wmi_handle, param_buf, roam_sync_ind); 2527 if (QDF_IS_STATUS_ERROR(status)) { 2528 wmi_err("Failed to fill roam mlo info"); 2529 return status; 2530 } 2531 wlan_cm_free_roam_synch_frame_ind(rso_cfg); 2532 return QDF_STATUS_SUCCESS; 2533 } 2534 2535 /** 2536 * extract_roam_sync_event_tlv() - Extract the roam sync event 2537 * from the wmi_roam_synch_event_id 2538 * @wmi_handle: wmi handle 2539 * @evt_buf: Pointer to the event buffer 2540 * @len: Data length 2541 * @roam_sync_ind: Ptr to roam offload sync struct 2542 */ 2543 static QDF_STATUS 2544 extract_roam_sync_event_tlv(wmi_unified_t wmi_handle, void *evt_buf, 2545 uint32_t len, 2546 struct roam_offload_synch_ind **roam_sync_ind) 2547 { 2548 QDF_STATUS status = QDF_STATUS_SUCCESS; 2549 wmi_roam_synch_event_fixed_param *synch_event = NULL; 2550 WMI_ROAM_SYNCH_EVENTID_param_tlvs *param_buf = NULL; 2551 struct roam_offload_synch_ind *roam_sync = NULL; 2552 struct wlan_objmgr_vdev *vdev = NULL; 2553 struct wlan_objmgr_psoc *psoc = NULL; 2554 struct rso_config *rso_cfg; 2555 uint32_t roam_synch_data_len; 2556 uint32_t bcn_probe_rsp_len, link_bcn_probe_rsp_len; 2557 uint32_t reassoc_rsp_len; 2558 uint32_t reassoc_req_len; 2559 wmi_pdev_hw_mode_transition_event_fixed_param *hw_mode_trans_param; 2560 2561 if (!evt_buf) { 2562 wmi_debug("Empty roam_sync_event param buf"); 2563 return QDF_STATUS_E_FAILURE; 2564 } 2565 2566 param_buf = (WMI_ROAM_SYNCH_EVENTID_param_tlvs *)evt_buf; 2567 if (!param_buf) { 2568 wmi_debug("received null buf from target"); 2569 return QDF_STATUS_E_FAILURE; 2570 } 2571 2572 synch_event = param_buf->fixed_param; 2573 if (!synch_event) { 2574 wmi_debug("received null event data from target"); 2575 return QDF_STATUS_E_FAILURE; 2576 } 2577 hw_mode_trans_param = param_buf->hw_mode_transition_fixed_param; 2578 if (hw_mode_trans_param && 2579 hw_mode_trans_param->num_vdev_mac_entries > 2580 param_buf->num_wmi_pdev_set_hw_mode_response_vdev_mac_mapping) { 2581 wmi_debug("invalid vdev mac entries %d %d in roam sync", 2582 hw_mode_trans_param->num_vdev_mac_entries, 2583 param_buf->num_wmi_pdev_set_hw_mode_response_vdev_mac_mapping); 2584 return QDF_STATUS_E_FAILURE; 2585 } 2586 2587 if (synch_event->vdev_id >= WLAN_MAX_VDEVS) { 2588 wmi_err("received invalid vdev_id %d", 2589 synch_event->vdev_id); 2590 return QDF_STATUS_E_FAILURE; 2591 } 2592 2593 psoc = wmi_handle->soc->wmi_psoc; 2594 vdev = wlan_objmgr_get_vdev_by_id_from_psoc(psoc, synch_event->vdev_id, 2595 WLAN_MLME_SB_ID); 2596 if (!vdev) { 2597 wmi_err("For vdev:%d object is NULL", synch_event->vdev_id); 2598 return QDF_STATUS_E_FAILURE; 2599 } 2600 2601 if (synch_event->bcn_probe_rsp_len > 2602 param_buf->num_bcn_probe_rsp_frame || 2603 synch_event->reassoc_req_len > 2604 param_buf->num_reassoc_req_frame || 2605 synch_event->reassoc_rsp_len > 2606 param_buf->num_reassoc_rsp_frame) { 2607 wmi_debug("Invalid sync payload: LEN bcn:%d, req:%d, rsp:%d, vdev:%d", 2608 synch_event->bcn_probe_rsp_len, 2609 synch_event->reassoc_req_len, 2610 synch_event->reassoc_rsp_len, 2611 synch_event->vdev_id); 2612 status = QDF_STATUS_E_FAILURE; 2613 goto abort_roam; 2614 } 2615 2616 rso_cfg = wlan_cm_get_rso_config(vdev); 2617 if (!rso_cfg) { 2618 status = QDF_STATUS_E_FAILURE; 2619 goto abort_roam; 2620 } 2621 2622 /* 2623 * All below length fields are unsigned and hence positive numbers. 2624 * Maximum number during the addition would be (3 * MAX_LIMIT(UINT32) + 2625 * few fixed fields). 2626 */ 2627 wmi_debug("synch payload: LEN bcn:%d, req:%d, rsp:%d", 2628 synch_event->bcn_probe_rsp_len, 2629 synch_event->reassoc_req_len, 2630 synch_event->reassoc_rsp_len); 2631 2632 /* 2633 * If lengths of bcn_probe_rsp, reassoc_req and reassoc_rsp are zero in 2634 * synch_event driver would have received bcn_probe_rsp, reassoc_req 2635 * and reassoc_rsp via the event WMI_ROAM_SYNCH_FRAME_EVENTID 2636 */ 2637 if ((!synch_event->bcn_probe_rsp_len) && 2638 (!synch_event->reassoc_req_len) && 2639 (!synch_event->reassoc_rsp_len)) { 2640 bcn_probe_rsp_len = 2641 rso_cfg->roam_sync_frame_ind.bcn_probe_rsp_len; 2642 link_bcn_probe_rsp_len = 2643 rso_cfg->roam_sync_frame_ind.link_bcn_probe_rsp_len; 2644 reassoc_req_len = rso_cfg->roam_sync_frame_ind.reassoc_req_len; 2645 reassoc_rsp_len = rso_cfg->roam_sync_frame_ind.reassoc_rsp_len; 2646 2647 roam_synch_data_len = 2648 bcn_probe_rsp_len + link_bcn_probe_rsp_len + 2649 reassoc_rsp_len + reassoc_req_len + 2650 sizeof(struct roam_offload_synch_ind); 2651 2652 wmi_debug("Updated synch payload: LEN bcn:%d, link bcn: %d req:%d, rsp:%d", 2653 bcn_probe_rsp_len, 2654 link_bcn_probe_rsp_len, 2655 reassoc_req_len, 2656 reassoc_rsp_len); 2657 } else { 2658 bcn_probe_rsp_len = synch_event->bcn_probe_rsp_len; 2659 reassoc_req_len = synch_event->reassoc_req_len; 2660 reassoc_rsp_len = synch_event->reassoc_rsp_len; 2661 2662 roam_synch_data_len = bcn_probe_rsp_len + 2663 reassoc_rsp_len + reassoc_req_len; 2664 roam_synch_data_len += sizeof(struct roam_offload_synch_ind); 2665 } 2666 2667 roam_sync = qdf_mem_malloc(roam_synch_data_len); 2668 if (!roam_sync) { 2669 QDF_ASSERT(roam_sync); 2670 status = QDF_STATUS_E_NOMEM; 2671 goto abort_roam; 2672 } 2673 2674 *roam_sync_ind = roam_sync; 2675 status = wmi_fill_roam_sync_buffer(wmi_handle, vdev, rso_cfg, 2676 roam_sync, param_buf); 2677 2678 abort_roam: 2679 if (QDF_IS_STATUS_ERROR(status)) { 2680 wmi_err("%d Failed to extract roam sync ind", status); 2681 wlan_cm_roam_state_change(wlan_vdev_get_pdev(vdev), 2682 synch_event->vdev_id, 2683 WLAN_ROAM_RSO_STOPPED, 2684 REASON_ROAM_SYNCH_FAILED); 2685 } 2686 wlan_objmgr_vdev_release_ref(vdev, WLAN_MLME_SB_ID); 2687 return status; 2688 } 2689 2690 /** 2691 * extract_roam_sync_frame_event_tlv() - Extract the roam sync frame event 2692 * from the wmi_roam_synch_event_id 2693 * @wmi_handle: wmi handle 2694 * @event: Pointer to the event buffer 2695 * @len: event buffer length 2696 * @frame_ptr: wmi sync frame event ptr 2697 */ 2698 static QDF_STATUS 2699 extract_roam_sync_frame_event_tlv(wmi_unified_t wmi_handle, void *event, 2700 uint32_t len, 2701 struct roam_synch_frame_ind *frame_ptr) 2702 { 2703 WMI_ROAM_SYNCH_FRAME_EVENTID_param_tlvs *param_buf = NULL; 2704 struct roam_synch_frame_ind *frame_ind; 2705 wmi_roam_synch_frame_event_fixed_param *frame_evt; 2706 2707 if (!event) { 2708 wmi_err("Event param null"); 2709 return QDF_STATUS_E_NULL_VALUE; 2710 } 2711 2712 param_buf = (WMI_ROAM_SYNCH_FRAME_EVENTID_param_tlvs *)event; 2713 if (!param_buf) { 2714 wmi_err("received null buf from target"); 2715 return QDF_STATUS_E_NULL_VALUE; 2716 } 2717 2718 frame_evt = param_buf->fixed_param; 2719 if (!frame_evt) { 2720 wmi_err("received null event data from target"); 2721 return QDF_STATUS_E_NULL_VALUE; 2722 } 2723 2724 if (frame_evt->vdev_id >= WLAN_MAX_VDEVS) { 2725 wmi_err("received invalid vdev_id %d", frame_evt->vdev_id); 2726 return QDF_STATUS_E_FAILURE; 2727 } 2728 2729 /* 2730 * Firmware can send more than one roam synch frame event to host 2731 * driver. So Bcn_prb_rsp_len/reassoc_req_len/reassoc_rsp_len can be 0 2732 * in some of the events. 2733 */ 2734 if (frame_evt->bcn_probe_rsp_len > param_buf->num_bcn_probe_rsp_frame || 2735 frame_evt->reassoc_req_len > param_buf->num_reassoc_req_frame || 2736 frame_evt->reassoc_rsp_len > param_buf->num_reassoc_rsp_frame || 2737 (frame_evt->bcn_probe_rsp_len && 2738 frame_evt->bcn_probe_rsp_len < sizeof(struct wlan_frame_hdr)) || 2739 (frame_evt->reassoc_req_len && 2740 frame_evt->reassoc_req_len < sizeof(struct wlan_frame_hdr)) || 2741 (frame_evt->reassoc_rsp_len && 2742 frame_evt->reassoc_rsp_len < sizeof(struct wlan_frame_hdr))) { 2743 wmi_err("fixed/actual len err: bcn:%d/%d req:%d/%d rsp:%d/%d", 2744 frame_evt->bcn_probe_rsp_len, 2745 param_buf->num_bcn_probe_rsp_frame, 2746 frame_evt->reassoc_req_len, 2747 param_buf->num_reassoc_req_frame, 2748 frame_evt->reassoc_rsp_len, 2749 param_buf->num_reassoc_rsp_frame); 2750 return QDF_STATUS_E_FAILURE; 2751 } 2752 2753 frame_ind = frame_ptr; 2754 frame_ind->vdev_id = frame_evt->vdev_id; 2755 2756 wmi_debug("synch frame payload: LEN %s bcn:%d, req:%d, rsp:%d", 2757 frame_evt->reassoc_rsp_len ? "Assoc" : "Link", 2758 frame_evt->bcn_probe_rsp_len, 2759 frame_evt->reassoc_req_len, 2760 frame_evt->reassoc_rsp_len); 2761 2762 if (frame_evt->bcn_probe_rsp_len && 2763 frame_evt->reassoc_rsp_len) { 2764 frame_ind->bcn_probe_rsp_len = frame_evt->bcn_probe_rsp_len; 2765 2766 frame_ind->is_beacon = frame_evt->is_beacon; 2767 2768 frame_ind->bcn_probe_rsp = 2769 qdf_mem_malloc(frame_ind->bcn_probe_rsp_len); 2770 if (!frame_ind->bcn_probe_rsp) { 2771 QDF_ASSERT(frame_ind->bcn_probe_rsp); 2772 return QDF_STATUS_E_NOMEM; 2773 } 2774 qdf_mem_copy(frame_ind->bcn_probe_rsp, 2775 param_buf->bcn_probe_rsp_frame, 2776 frame_ind->bcn_probe_rsp_len); 2777 } else if (frame_evt->bcn_probe_rsp_len) { 2778 frame_ind->link_bcn_probe_rsp_len = 2779 frame_evt->bcn_probe_rsp_len; 2780 2781 frame_ind->is_link_beacon = frame_evt->is_beacon; 2782 2783 if (frame_ind->link_bcn_probe_rsp) 2784 qdf_mem_free(frame_ind->bcn_probe_rsp); 2785 2786 frame_ind->link_bcn_probe_rsp = 2787 qdf_mem_malloc(frame_ind->link_bcn_probe_rsp_len); 2788 if (!frame_ind->link_bcn_probe_rsp) { 2789 QDF_ASSERT(frame_ind->link_bcn_probe_rsp); 2790 return QDF_STATUS_E_NOMEM; 2791 } 2792 qdf_mem_copy(frame_ind->link_bcn_probe_rsp, 2793 param_buf->bcn_probe_rsp_frame, 2794 frame_ind->link_bcn_probe_rsp_len); 2795 } 2796 2797 if (frame_evt->reassoc_req_len) { 2798 frame_ind->reassoc_req_len = frame_evt->reassoc_req_len; 2799 2800 frame_ind->reassoc_req = 2801 qdf_mem_malloc(frame_ind->reassoc_req_len); 2802 if (!frame_ind->reassoc_req) { 2803 QDF_ASSERT(frame_ind->reassoc_req); 2804 return QDF_STATUS_E_NOMEM; 2805 } 2806 qdf_mem_copy(frame_ind->reassoc_req, 2807 param_buf->reassoc_req_frame, 2808 frame_ind->reassoc_req_len); 2809 } 2810 2811 if (frame_evt->reassoc_rsp_len) { 2812 frame_ind->reassoc_rsp_len = frame_evt->reassoc_rsp_len; 2813 2814 frame_ind->reassoc_rsp = 2815 qdf_mem_malloc(frame_ind->reassoc_rsp_len); 2816 if (!frame_ind->reassoc_rsp) { 2817 QDF_ASSERT(frame_ind->reassoc_rsp); 2818 return QDF_STATUS_E_NOMEM; 2819 } 2820 qdf_mem_copy(frame_ind->reassoc_rsp, 2821 param_buf->reassoc_rsp_frame, 2822 frame_ind->reassoc_rsp_len); 2823 } 2824 2825 return QDF_STATUS_SUCCESS; 2826 } 2827 2828 static enum dlm_reject_ap_reason wmi_get_reject_reason(uint32_t reason) 2829 { 2830 switch (reason) { 2831 case WMI_BL_REASON_NUD_FAILURE: 2832 return REASON_NUD_FAILURE; 2833 case WMI_BL_REASON_STA_KICKOUT: 2834 return REASON_STA_KICKOUT; 2835 case WMI_BL_REASON_ROAM_HO_FAILURE: 2836 return REASON_ROAM_HO_FAILURE; 2837 case WMI_BL_REASON_ASSOC_REJECT_POOR_RSSI: 2838 return REASON_ASSOC_REJECT_POOR_RSSI; 2839 case WMI_BL_REASON_ASSOC_REJECT_OCE: 2840 return REASON_ASSOC_REJECT_OCE; 2841 case WMI_BL_REASON_USERSPACE_BL: 2842 return REASON_USERSPACE_BL; 2843 case WMI_BL_REASON_USERSPACE_AVOID_LIST: 2844 return REASON_USERSPACE_AVOID_LIST; 2845 case WMI_BL_REASON_BTM_DIASSOC_IMMINENT: 2846 return REASON_BTM_DISASSOC_IMMINENT; 2847 case WMI_BL_REASON_BTM_BSS_TERMINATION: 2848 return REASON_BTM_BSS_TERMINATION; 2849 case WMI_BL_REASON_BTM_MBO_RETRY: 2850 return REASON_BTM_MBO_RETRY; 2851 case WMI_BL_REASON_REASSOC_RSSI_REJECT: 2852 return REASON_REASSOC_RSSI_REJECT; 2853 case WMI_BL_REASON_REASSOC_NO_MORE_STAS: 2854 return REASON_REASSOC_NO_MORE_STAS; 2855 default: 2856 return REASON_UNKNOWN; 2857 } 2858 } 2859 2860 static QDF_STATUS 2861 extract_btm_denylist_event(wmi_unified_t wmi_handle, 2862 uint8_t *event, uint32_t len, 2863 struct roam_denylist_event **list) 2864 { 2865 WMI_ROAM_BLACKLIST_EVENTID_param_tlvs *param_buf; 2866 wmi_roam_blacklist_event_fixed_param *resp_event; 2867 wmi_roam_blacklist_with_timeout_tlv_param *src_list; 2868 struct roam_denylist_timeout *roam_denylist; 2869 struct roam_denylist_event *dst_list; 2870 uint32_t num_entries, i; 2871 2872 param_buf = (WMI_ROAM_BLACKLIST_EVENTID_param_tlvs *)event; 2873 if (!param_buf) { 2874 wmi_err("Invalid event buffer"); 2875 return QDF_STATUS_E_INVAL; 2876 } 2877 2878 resp_event = param_buf->fixed_param; 2879 if (!resp_event) { 2880 wmi_err("received null event data from target"); 2881 return QDF_STATUS_E_INVAL; 2882 } 2883 2884 if (resp_event->vdev_id >= WLAN_MAX_VDEVS) { 2885 wmi_err("received invalid vdev_id %d", resp_event->vdev_id); 2886 return QDF_STATUS_E_INVAL; 2887 } 2888 2889 num_entries = param_buf->num_blacklist_with_timeout; 2890 if (num_entries == 0) 2891 return QDF_STATUS_SUCCESS; 2892 2893 if (num_entries > MAX_RSSI_AVOID_BSSID_LIST) { 2894 wmi_err("num blacklist entries:%d exceeds maximum value", 2895 num_entries); 2896 return QDF_STATUS_E_INVAL; 2897 } 2898 2899 src_list = param_buf->blacklist_with_timeout; 2900 if (len < (sizeof(*resp_event) + (num_entries * sizeof(*src_list)))) { 2901 wmi_err("Invalid length:%d", len); 2902 return QDF_STATUS_E_INVAL; 2903 } 2904 2905 dst_list = qdf_mem_malloc(sizeof(struct roam_denylist_event) + 2906 (sizeof(struct roam_denylist_timeout) * 2907 num_entries)); 2908 if (!dst_list) 2909 return QDF_STATUS_E_NOMEM; 2910 2911 dst_list->vdev_id = resp_event->vdev_id; 2912 roam_denylist = &dst_list->roam_denylist[0]; 2913 for (i = 0; i < num_entries; i++) { 2914 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_list->bssid, 2915 roam_denylist->bssid.bytes); 2916 roam_denylist->timeout = src_list->timeout; 2917 roam_denylist->received_time = src_list->timestamp; 2918 roam_denylist->original_timeout = src_list->original_timeout; 2919 roam_denylist->reject_reason = 2920 wmi_get_reject_reason(src_list->reason); 2921 roam_denylist->source = src_list->source; 2922 roam_denylist++; 2923 src_list++; 2924 } 2925 2926 dst_list->num_entries = num_entries; 2927 *list = dst_list; 2928 2929 return QDF_STATUS_SUCCESS; 2930 } 2931 2932 static QDF_STATUS 2933 extract_vdev_disconnect_event_tlv(wmi_unified_t wmi_handle, 2934 uint8_t *event, uint32_t data_len, 2935 struct vdev_disconnect_event_data *data) 2936 { 2937 WMI_VDEV_DISCONNECT_EVENTID_param_tlvs *param_buf; 2938 wmi_vdev_disconnect_event_fixed_param *roam_vdev_disc_ev; 2939 2940 param_buf = (WMI_VDEV_DISCONNECT_EVENTID_param_tlvs *)event; 2941 2942 roam_vdev_disc_ev = param_buf->fixed_param; 2943 if (!roam_vdev_disc_ev) { 2944 wmi_err("roam cap event is NULL"); 2945 return QDF_STATUS_E_INVAL; 2946 } 2947 2948 if (roam_vdev_disc_ev->vdev_id >= WLAN_MAX_VDEVS) { 2949 wmi_err("Invalid vdev id %d", roam_vdev_disc_ev->vdev_id); 2950 return QDF_STATUS_E_INVAL; 2951 } 2952 data->vdev_id = roam_vdev_disc_ev->vdev_id; 2953 data->reason = roam_vdev_disc_ev->reason; 2954 2955 wmi_debug("Received disconnect roam event on vdev_id : %d, reason:%d", 2956 data->vdev_id, data->reason); 2957 2958 return QDF_STATUS_SUCCESS; 2959 } 2960 2961 static QDF_STATUS 2962 extract_roam_scan_chan_list_tlv(wmi_unified_t wmi_handle, 2963 uint8_t *event, uint32_t data_len, 2964 struct cm_roam_scan_ch_resp **list) 2965 { 2966 WMI_ROAM_SCAN_CHANNEL_LIST_EVENTID_param_tlvs *param_buf; 2967 wmi_roam_scan_channel_list_event_fixed_param *fixed_param; 2968 struct cm_roam_scan_ch_resp *data; 2969 uint8_t i = 0, num_ch = 0; 2970 2971 param_buf = (WMI_ROAM_SCAN_CHANNEL_LIST_EVENTID_param_tlvs *)event; 2972 if (!param_buf) { 2973 wmi_err_rl("NULL event received from target"); 2974 return -EINVAL; 2975 } 2976 2977 fixed_param = param_buf->fixed_param; 2978 if (!fixed_param) { 2979 wmi_err_rl(" NULL fixed param"); 2980 return -EINVAL; 2981 } 2982 2983 if (fixed_param->vdev_id >= WLAN_MAX_VDEVS) { 2984 wmi_err_rl("Invalid vdev_id %d", fixed_param->vdev_id); 2985 return -EINVAL; 2986 } 2987 2988 num_ch = (param_buf->num_channel_list < CM_CFG_VALID_CHANNEL_LIST_LEN) ? 2989 param_buf->num_channel_list : CM_CFG_VALID_CHANNEL_LIST_LEN; 2990 2991 data = qdf_mem_malloc(sizeof(struct cm_roam_scan_ch_resp) + 2992 num_ch * sizeof(param_buf->channel_list[0])); 2993 if (!data) 2994 return -EINVAL; 2995 2996 data->chan_list = (uint32_t *)(data + 1); 2997 data->vdev_id = fixed_param->vdev_id; 2998 data->command_resp = fixed_param->command_response; 2999 data->num_channels = param_buf->num_channel_list; 3000 3001 for (i = 0; i < num_ch; i++) 3002 data->chan_list[i] = param_buf->channel_list[i]; 3003 3004 *list = data; 3005 return QDF_STATUS_SUCCESS; 3006 } 3007 3008 static QDF_STATUS 3009 extract_roam_stats_with_single_tlv(wmi_unified_t wmi_handle, uint8_t *evt_buf, 3010 struct roam_stats_event *stats_info) 3011 { 3012 QDF_STATUS status; 3013 uint8_t vdev_id = stats_info->vdev_id; 3014 3015 status = wmi_unified_extract_roam_scan_stats( 3016 wmi_handle, evt_buf, &stats_info->scan[0], 0, 0, 0); 3017 if (QDF_IS_STATUS_ERROR(status)) 3018 wmi_debug("Roam scan stats extract failed vdev %d", vdev_id); 3019 3020 status = wmi_unified_extract_roam_11kv_stats( 3021 wmi_handle, evt_buf, &stats_info->data_11kv[0], 0, 0); 3022 if (QDF_IS_STATUS_ERROR(status)) 3023 wmi_debug("Roam 11kv stats extract failed vdev %d", vdev_id); 3024 3025 status = wmi_unified_extract_roam_trigger_stats( 3026 wmi_handle, evt_buf, &stats_info->trigger[0], 0, 0); 3027 if (QDF_IS_STATUS_ERROR(status)) 3028 wmi_debug("Extract roamtrigger stats failed vdev %d", 3029 vdev_id); 3030 3031 status = wmi_unified_extract_roam_btm_response( 3032 wmi_handle, evt_buf, &stats_info->btm_rsp[0], 0); 3033 if (QDF_IS_STATUS_ERROR(status)) 3034 wmi_debug("Roam btm rsp stats extract fail vdev %d", 3035 vdev_id); 3036 3037 return QDF_STATUS_SUCCESS; 3038 } 3039 3040 /** 3041 * extract_roam_stats_event_tlv() - Extract the roam stats event 3042 * from the wmi_roam_stats_event_id 3043 * @wmi_handle: wmi handle 3044 * @evt_buf: Pointer to the event buffer 3045 * @len: Data length 3046 * @data: Double pointer to roam stats data 3047 */ 3048 static QDF_STATUS 3049 extract_roam_stats_event_tlv(wmi_unified_t wmi_handle, uint8_t *evt_buf, 3050 uint32_t len, 3051 struct roam_stats_event **data) 3052 { 3053 WMI_ROAM_STATS_EVENTID_param_tlvs *param_buf; 3054 wmi_roam_stats_event_fixed_param *fixed_param; 3055 struct roam_stats_event *stats_info; 3056 struct roam_msg_info *roam_msg_info = NULL; 3057 uint8_t vdev_id, i, num_btm = 0, num_frames = 0; 3058 uint8_t num_tlv = 0, num_chan = 0, num_ap = 0, num_rpt = 0; 3059 uint8_t num_trigger_reason = 0; 3060 uint32_t rem_len; 3061 QDF_STATUS status; 3062 3063 param_buf = (WMI_ROAM_STATS_EVENTID_param_tlvs *)evt_buf; 3064 if (!param_buf) { 3065 wmi_err_rl("NULL event received from target"); 3066 return QDF_STATUS_E_INVAL; 3067 } 3068 3069 fixed_param = param_buf->fixed_param; 3070 if (!fixed_param) { 3071 wmi_err_rl(" NULL fixed param"); 3072 return QDF_STATUS_E_INVAL; 3073 } 3074 3075 vdev_id = fixed_param->vdev_id; 3076 3077 if (vdev_id >= WLAN_MAX_VDEVS) { 3078 wmi_err_rl("Invalid vdev_id %d", vdev_id); 3079 return QDF_STATUS_E_INVAL; 3080 } 3081 3082 num_tlv = fixed_param->roam_scan_trigger_count; 3083 if (num_tlv > MAX_ROAM_SCAN_STATS_TLV) { 3084 wmi_err_rl("Limiting roam triggers to 5"); 3085 num_tlv = MAX_ROAM_SCAN_STATS_TLV; 3086 } 3087 3088 if (param_buf->roam_trigger_reason) 3089 num_trigger_reason = num_tlv; 3090 else 3091 num_trigger_reason = 0; 3092 3093 rem_len = len - sizeof(*fixed_param); 3094 if (rem_len < num_trigger_reason * sizeof(wmi_roam_trigger_reason)) { 3095 wmi_err_rl("Invalid roam trigger data"); 3096 return QDF_STATUS_E_INVAL; 3097 } 3098 3099 rem_len -= num_trigger_reason * sizeof(wmi_roam_trigger_reason); 3100 if (rem_len < num_tlv * sizeof(wmi_roam_scan_info)) { 3101 wmi_err_rl("Invalid roam scan data"); 3102 return QDF_STATUS_E_INVAL; 3103 } 3104 3105 rem_len -= num_tlv * sizeof(wmi_roam_scan_info); 3106 if (rem_len < num_tlv * sizeof(wmi_roam_result)) { 3107 wmi_err_rl("Invalid roam result data"); 3108 return QDF_STATUS_E_INVAL; 3109 } 3110 3111 rem_len -= num_tlv * sizeof(wmi_roam_result); 3112 if (rem_len < (num_tlv * sizeof(wmi_roam_neighbor_report_info))) { 3113 wmi_err_rl("Invalid roam neighbor report data"); 3114 return QDF_STATUS_E_INVAL; 3115 } 3116 3117 rem_len -= num_tlv * sizeof(wmi_roam_neighbor_report_info); 3118 if (rem_len < (param_buf->num_roam_scan_chan_info * 3119 sizeof(wmi_roam_scan_channel_info))) { 3120 wmi_err_rl("Invalid roam chan data num_tlv:%d", 3121 param_buf->num_roam_scan_chan_info); 3122 return QDF_STATUS_E_INVAL; 3123 } 3124 3125 rem_len -= param_buf->num_roam_scan_chan_info * 3126 sizeof(wmi_roam_scan_channel_info); 3127 3128 if (rem_len < (param_buf->num_roam_ap_info * 3129 sizeof(wmi_roam_ap_info))) { 3130 wmi_err_rl("Invalid roam ap data num_tlv:%d", 3131 param_buf->num_roam_ap_info); 3132 return QDF_STATUS_E_INVAL; 3133 } 3134 3135 rem_len -= param_buf->num_roam_ap_info * sizeof(wmi_roam_ap_info); 3136 if (rem_len < (param_buf->num_roam_neighbor_report_chan_info * 3137 sizeof(wmi_roam_neighbor_report_channel_info))) { 3138 wmi_err_rl("Invalid roam neigb rpt chan data num_tlv:%d", 3139 param_buf->num_roam_neighbor_report_chan_info); 3140 return QDF_STATUS_E_INVAL; 3141 } 3142 3143 rem_len -= param_buf->num_roam_neighbor_report_chan_info * 3144 sizeof(wmi_roam_neighbor_report_channel_info); 3145 if (rem_len < param_buf->num_roam_btm_response_info * 3146 sizeof(wmi_roam_btm_response_info)) { 3147 wmi_err_rl("Invalid btm rsp data"); 3148 return QDF_STATUS_E_INVAL; 3149 } 3150 3151 rem_len -= param_buf->num_roam_btm_response_info * 3152 sizeof(wmi_roam_btm_response_info); 3153 if (rem_len < param_buf->num_roam_initial_info * 3154 sizeof(wmi_roam_initial_info)) { 3155 wmi_err_rl("Invalid Initial roam info"); 3156 return QDF_STATUS_E_INVAL; 3157 } 3158 3159 rem_len -= param_buf->num_roam_initial_info * 3160 sizeof(wmi_roam_initial_info); 3161 if (rem_len < param_buf->num_roam_msg_info * 3162 sizeof(wmi_roam_msg_info)) { 3163 wmi_err_rl("Invalid roam msg info"); 3164 return QDF_STATUS_E_INVAL; 3165 } 3166 3167 rem_len -= param_buf->num_roam_msg_info * sizeof(wmi_roam_msg_info); 3168 if (rem_len < 3169 param_buf->num_roam_frame_info * sizeof(wmi_roam_frame_info)) { 3170 wmi_err_rl("Invalid roam frame info"); 3171 return QDF_STATUS_E_INVAL; 3172 } 3173 3174 stats_info = qdf_mem_malloc(sizeof(struct roam_stats_event)); 3175 if (!stats_info) { 3176 status = QDF_STATUS_E_NOMEM; 3177 goto err; 3178 } 3179 *data = stats_info; 3180 qdf_mem_set(stats_info, sizeof(struct roam_stats_event), 0); 3181 stats_info->vdev_id = vdev_id; 3182 stats_info->num_roam_msg_info = param_buf->num_roam_msg_info; 3183 stats_info->num_tlv = num_tlv; 3184 3185 if (!num_tlv) 3186 extract_roam_stats_with_single_tlv(wmi_handle, evt_buf, 3187 stats_info); 3188 3189 for (i = 0; i < num_tlv; i++) { 3190 /* 3191 * Roam Trigger id and that specific roam trigger related 3192 * details. 3193 */ 3194 status = wmi_unified_extract_roam_trigger_stats(wmi_handle, 3195 evt_buf, 3196 &stats_info->trigger[i], i, 3197 num_btm); 3198 if (QDF_IS_STATUS_ERROR(status)) { 3199 wmi_debug_rl("Extract roam trigger stats failed vdev %d at %d iteration", 3200 vdev_id, i); 3201 status = QDF_STATUS_E_INVAL; 3202 goto err; 3203 } 3204 3205 if (stats_info->trigger[i].trigger_reason == 3206 WMI_ROAM_TRIGGER_REASON_BTM) 3207 num_btm += stats_info->trigger[i].btm_trig_data.candidate_list_count; 3208 3209 /* Roam scan related details - Scan channel, scan type .. */ 3210 status = wmi_unified_extract_roam_scan_stats(wmi_handle, 3211 evt_buf, 3212 &stats_info->scan[i], i, 3213 num_chan, num_ap); 3214 if (QDF_IS_STATUS_ERROR(status)) { 3215 wmi_debug_rl("Roam scan stats extract failed vdev %d at %d iteration", 3216 vdev_id, i); 3217 status = QDF_STATUS_E_INVAL; 3218 goto err; 3219 } 3220 num_chan += stats_info->scan[i].num_chan; 3221 num_ap += stats_info->scan[i].num_ap; 3222 num_frames = stats_info->scan[i].frame_info_count; 3223 3224 /* Roam result - Success/Failure status, failure reason */ 3225 status = wmi_unified_extract_roam_result_stats(wmi_handle, 3226 evt_buf, 3227 &stats_info->result[i], i); 3228 if (QDF_IS_STATUS_ERROR(status)) { 3229 wmi_debug_rl("Roam result stats extract failed vdev %d at %d iteration", 3230 vdev_id, i); 3231 status = QDF_STATUS_E_INVAL; 3232 goto err; 3233 } 3234 3235 if (num_frames) { 3236 status = wmi_unified_extract_roam_extract_frame_info( 3237 wmi_handle, evt_buf, 3238 &stats_info->frame_stats[i], i, 3239 num_frames); 3240 if (QDF_IS_STATUS_ERROR(status)) { 3241 wmi_debug_rl("Roam frame stats extract failed vdev %d at %d iteration", 3242 vdev_id, i); 3243 status = QDF_STATUS_E_INVAL; 3244 goto err; 3245 } 3246 } 3247 3248 /* BTM req/resp or Neighbor report/response info */ 3249 status = wmi_unified_extract_roam_11kv_stats( 3250 wmi_handle, 3251 evt_buf, 3252 &stats_info->data_11kv[i], 3253 i, num_rpt); 3254 if (QDF_IS_STATUS_ERROR(status)) 3255 wmi_debug_rl("Roam 11kv stats extract fail vdev %d iter %d", 3256 vdev_id, i); 3257 3258 if (stats_info->data_11kv[i].present) 3259 num_rpt += stats_info->data_11kv[i].num_freq; 3260 3261 /* BTM resp info */ 3262 status = wmi_unified_extract_roam_btm_response(wmi_handle, 3263 evt_buf, 3264 &stats_info->btm_rsp[i], 3265 i); 3266 if (QDF_IS_STATUS_ERROR(status)) { 3267 wmi_debug_rl("Roam btm rsp stats extract fail vdev %d at %d iteration", 3268 vdev_id, i); 3269 status = QDF_STATUS_E_INVAL; 3270 goto err; 3271 } 3272 3273 /* Initial Roam info */ 3274 status = wmi_unified_extract_roam_initial_info(wmi_handle, 3275 evt_buf, 3276 &stats_info->roam_init_info[i], i); 3277 if (QDF_IS_STATUS_ERROR(status)) { 3278 wmi_debug_rl("Initial roam stats extract fail vdev %d at %d iteration", 3279 vdev_id, i); 3280 status = QDF_STATUS_E_INVAL; 3281 goto err; 3282 } 3283 } 3284 3285 if (param_buf->roam_msg_info && param_buf->num_roam_msg_info) { 3286 roam_msg_info = qdf_mem_malloc(param_buf->num_roam_msg_info * 3287 sizeof(*roam_msg_info)); 3288 if (!roam_msg_info) { 3289 status = QDF_STATUS_E_NOMEM; 3290 goto err; 3291 } 3292 stats_info->roam_msg_info = roam_msg_info; 3293 for (i = 0; i < param_buf->num_roam_msg_info; i++) { 3294 status = wmi_unified_extract_roam_msg_info(wmi_handle, 3295 evt_buf, 3296 &roam_msg_info[i], i); 3297 if (QDF_IS_STATUS_ERROR(status)) { 3298 wmi_err("roam msg stats extract fail vdev %d", 3299 vdev_id); 3300 status = QDF_STATUS_E_INVAL; 3301 goto err; 3302 } 3303 } 3304 } 3305 return QDF_STATUS_SUCCESS; 3306 err: 3307 if (stats_info) { 3308 if (roam_msg_info) 3309 qdf_mem_free(roam_msg_info); 3310 qdf_mem_free(stats_info); 3311 } 3312 return status; 3313 } 3314 3315 static QDF_STATUS 3316 extract_auth_offload_event_tlv(wmi_unified_t wmi_handle, 3317 uint8_t *event, uint32_t len, 3318 struct auth_offload_event *auth_event) 3319 { 3320 wmi_roam_preauth_start_event_fixed_param *rso_auth_start_ev; 3321 WMI_ROAM_PREAUTH_START_EVENTID_param_tlvs *param_buf; 3322 3323 param_buf = (WMI_ROAM_PREAUTH_START_EVENTID_param_tlvs *) event; 3324 3325 rso_auth_start_ev = param_buf->fixed_param; 3326 if (!rso_auth_start_ev) { 3327 wmi_debug("received null event data from target"); 3328 return QDF_STATUS_E_INVAL; 3329 } 3330 3331 if (rso_auth_start_ev->vdev_id > WLAN_MAX_VDEVS) { 3332 wmi_debug("received invalid vdev_id %d", 3333 rso_auth_start_ev->vdev_id); 3334 return QDF_STATUS_E_INVAL; 3335 } 3336 3337 auth_event->vdev_id = rso_auth_start_ev->vdev_id; 3338 auth_event->akm = rso_auth_start_ev->akm_suite_type; 3339 3340 WMI_MAC_ADDR_TO_CHAR_ARRAY(&rso_auth_start_ev->candidate_ap_bssid, 3341 auth_event->ap_bssid.bytes); 3342 WMI_MAC_ADDR_TO_CHAR_ARRAY(&rso_auth_start_ev->transmit_addr, 3343 auth_event->ta.bytes); 3344 if (qdf_is_macaddr_zero(&auth_event->ap_bssid) || 3345 qdf_is_macaddr_broadcast(&auth_event->ap_bssid) || 3346 qdf_is_macaddr_group(&auth_event->ap_bssid)) { 3347 wmi_debug("Invalid bssid"); 3348 return -EINVAL; 3349 } 3350 3351 wmi_debug("Received Roam auth offload event for bss:" 3352 QDF_MAC_ADDR_FMT " ta:" QDF_MAC_ADDR_FMT " vdev_id: %d akm: %d", 3353 QDF_MAC_ADDR_REF(auth_event->ap_bssid.bytes), 3354 QDF_MAC_ADDR_REF(auth_event->ta.bytes), 3355 auth_event->vdev_id, auth_event->akm); 3356 3357 return QDF_STATUS_SUCCESS; 3358 } 3359 3360 /** 3361 * extract_roam_pmkid_request_tlv() - Extract the roam pmkid request event 3362 * @wmi_handle: wmi handle 3363 * @evt_buf: Pointer to the event buffer 3364 * @len: Data length 3365 * @list: Extract the data and fill in list 3366 */ 3367 static QDF_STATUS 3368 extract_roam_pmkid_request_tlv(wmi_unified_t wmi_handle, uint8_t *evt_buf, 3369 uint32_t len, 3370 struct roam_pmkid_req_event **list) 3371 { 3372 WMI_ROAM_PMKID_REQUEST_EVENTID_param_tlvs *param_buf; 3373 wmi_roam_pmkid_request_event_fixed_param *roam_pmkid_req_ev; 3374 wmi_roam_pmkid_request_tlv_param *src_list; 3375 struct qdf_mac_addr *roam_bsslist; 3376 uint32_t num_entries, i; 3377 struct roam_pmkid_req_event *dst_list; 3378 3379 if (!evt_buf || !len) { 3380 wmi_err("received null event from target"); 3381 return QDF_STATUS_E_INVAL; 3382 } 3383 3384 param_buf = (WMI_ROAM_PMKID_REQUEST_EVENTID_param_tlvs *)evt_buf; 3385 if (!param_buf) { 3386 wmi_err("received null buf from target"); 3387 return QDF_STATUS_E_INVAL; 3388 } 3389 3390 roam_pmkid_req_ev = param_buf->fixed_param; 3391 if (!roam_pmkid_req_ev) { 3392 wmi_err("received null event data from target"); 3393 return QDF_STATUS_E_INVAL; 3394 } 3395 3396 if (roam_pmkid_req_ev->vdev_id >= WLAN_MAX_VDEVS) { 3397 wmi_err_rl("Invalid vdev_id %d", roam_pmkid_req_ev->vdev_id); 3398 return QDF_STATUS_E_INVAL; 3399 } 3400 3401 num_entries = param_buf->num_pmkid_request; 3402 if (num_entries > MAX_RSSI_AVOID_BSSID_LIST) { 3403 wmi_err("num bssid entries:%d exceeds maximum value", 3404 num_entries); 3405 return QDF_STATUS_E_INVAL; 3406 } 3407 3408 src_list = param_buf->pmkid_request; 3409 if (len < (sizeof(*roam_pmkid_req_ev) + 3410 (num_entries * sizeof(*src_list)))) { 3411 wmi_err("Invalid length: %d", len); 3412 return QDF_STATUS_E_INVAL; 3413 } 3414 3415 dst_list = qdf_mem_malloc(sizeof(struct roam_pmkid_req_event) + 3416 (sizeof(struct qdf_mac_addr) * num_entries)); 3417 if (!dst_list) 3418 return QDF_STATUS_E_NOMEM; 3419 3420 dst_list->vdev_id = roam_pmkid_req_ev->vdev_id; 3421 3422 for (i = 0; i < num_entries; i++) { 3423 roam_bsslist = &dst_list->ap_bssid[i]; 3424 WMI_MAC_ADDR_TO_CHAR_ARRAY(&src_list->bssid, 3425 roam_bsslist->bytes); 3426 if (qdf_is_macaddr_zero(roam_bsslist) || 3427 qdf_is_macaddr_broadcast(roam_bsslist) || 3428 qdf_is_macaddr_group(roam_bsslist)) { 3429 wmi_err("Invalid bssid"); 3430 qdf_mem_free(dst_list); 3431 return QDF_STATUS_E_INVAL; 3432 } 3433 wmi_debug("Received pmkid fallback for bssid: " QDF_MAC_ADDR_FMT" vdev_id:%d", 3434 QDF_MAC_ADDR_REF(roam_bsslist->bytes), 3435 roam_pmkid_req_ev->vdev_id); 3436 src_list++; 3437 } 3438 dst_list->num_entries = num_entries; 3439 *list = dst_list; 3440 3441 return QDF_STATUS_SUCCESS; 3442 } 3443 3444 static QDF_STATUS 3445 extract_roam_candidate_frame_tlv(wmi_unified_t wmi_handle, uint8_t *event, 3446 uint32_t len, 3447 struct roam_scan_candidate_frame *data) 3448 { 3449 WMI_ROAM_FRAME_EVENTID_param_tlvs *param_buf = NULL; 3450 wmi_roam_frame_event_fixed_param *frame_params = NULL; 3451 3452 if (!event || !len) { 3453 wmi_debug("Empty roam candidate frame event"); 3454 return QDF_STATUS_E_FAILURE; 3455 } 3456 3457 param_buf = (WMI_ROAM_FRAME_EVENTID_param_tlvs *)event; 3458 if (!param_buf) { 3459 wmi_err("received null buf from target"); 3460 return -EINVAL; 3461 } 3462 3463 frame_params = 3464 (wmi_roam_frame_event_fixed_param *)param_buf->fixed_param; 3465 3466 if (frame_params->vdev_id >= WLAN_MAX_VDEVS) { 3467 wmi_debug("Invalid VDEV id %d", frame_params->vdev_id); 3468 return QDF_STATUS_E_FAILURE; 3469 } 3470 3471 if (frame_params->frame_length > param_buf->num_frame) { 3472 wmi_debug("Invalid frame length %d expected : %d", 3473 frame_params->frame_length, 3474 param_buf->num_frame); 3475 return QDF_STATUS_E_FAILURE; 3476 } 3477 3478 if (!param_buf->frame) { 3479 wmi_debug("Frame pointer is Null"); 3480 return QDF_STATUS_E_FAILURE; 3481 } 3482 3483 data->vdev_id = frame_params->vdev_id; 3484 data->frame_length = frame_params->frame_length; 3485 data->frame = (uint8_t *)param_buf->frame; 3486 data->roam_offload_candidate_frm = true; 3487 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 3488 data->frame, data->frame_length); 3489 3490 return QDF_STATUS_SUCCESS; 3491 } 3492 3493 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 3494 static QDF_STATUS 3495 extract_peer_oper_mode_event_tlv(wmi_unified_t wmi_handle, uint8_t *event, 3496 uint32_t len, 3497 struct peer_oper_mode_event *data) 3498 { 3499 WMI_PEER_OPER_MODE_CHANGE_EVENTID_param_tlvs *param_buf = NULL; 3500 wmi_peer_oper_mode_change_event_fixed_param *params = NULL; 3501 3502 if (!event || !len) { 3503 wmi_debug("Empty operating mode change event"); 3504 return QDF_STATUS_E_FAILURE; 3505 } 3506 3507 param_buf = (WMI_PEER_OPER_MODE_CHANGE_EVENTID_param_tlvs *)event; 3508 if (!param_buf) { 3509 wmi_err("Received null buf from target"); 3510 return -EINVAL; 3511 } 3512 3513 params = 3514 (wmi_peer_oper_mode_change_event_fixed_param *)param_buf->fixed_param; 3515 3516 WMI_MAC_ADDR_TO_CHAR_ARRAY(¶ms->peer_mac_address, 3517 data->peer_mac_address.bytes); 3518 data->ind_type = params->ind_type; 3519 data->new_rxnss = params->new_rxnss; 3520 data->new_bw = params->new_bw; 3521 data->new_txnss = params->new_txnss; 3522 data->new_disablemu = params->new_disablemu; 3523 3524 wmi_debug("peer_mac_addr: " QDF_MAC_ADDR_FMT " ind_type: %d new_rxnss: %d new_bw: %d new_txnss: %d new_disablemu: %d", 3525 QDF_MAC_ADDR_REF(data->peer_mac_address.bytes), 3526 data->ind_type, 3527 data->new_rxnss, 3528 data->new_bw, 3529 data->new_txnss, 3530 data->new_disablemu); 3531 3532 return QDF_STATUS_SUCCESS; 3533 } 3534 #endif 3535 #ifdef WLAN_VENDOR_HANDOFF_CONTROL 3536 /** 3537 * convert_roam_vendor_control_param() - Function to convert 3538 * vendor_control_roam_param enum to TLV specific 3539 * WMI_ROAM_GET_VENDOR_CONTROL_PARAM_ID 3540 * @param_id: Roam vendor control param id 3541 * 3542 * Return: wmi roam vendor control param id 3543 */ 3544 static WMI_ROAM_GET_VENDOR_CONTROL_PARAM_ID 3545 convert_roam_vendor_control_param(enum vendor_control_roam_param param_id) 3546 { 3547 switch (param_id) { 3548 case VENDOR_CONTROL_PARAM_ROAM_TRIGGER: 3549 return ROAM_VENDOR_CONTROL_PARAM_TRIGGER; 3550 case VENDOR_CONTROL_PARAM_ROAM_DELTA: 3551 return ROAM_VENDOR_CONTROL_PARAM_DELTA; 3552 case VENDOR_CONTROL_PARAM_ROAM_FULL_SCANPERIOD: 3553 return ROAM_VENDOR_CONTROL_PARAM_FULL_SCANPERIOD; 3554 case VENDOR_CONTROL_PARAM_ROAM_PARTIAL_SCANPERIOD: 3555 return ROAM_VENDOR_CONTROL_PARAM_PARTIAL_SCANPERIOD; 3556 case VENDOR_CONTROL_PARAM_ROAM_ACTIVE_CH_DWELLTIME: 3557 return ROAM_VENDOR_CONTROL_PARAM_ACTIVE_CH_DWELLTIME; 3558 case VENDOR_CONTROL_PARAM_ROAM_PASSIVE_CH_DWELLTIME: 3559 return ROAM_VENDOR_CONTROL_PARAM_PASSIVE_CH_DWELLTIME; 3560 case VENDOR_CONTROL_PARAM_ROAM_HOME_CH_TIME: 3561 return ROAM_VENDOR_CONTROL_PARAM_HOME_CH_TIME; 3562 case VENDOR_CONTROL_PARAM_ROAM_AWAY_TIME: 3563 return ROAM_VENDOR_CONTROL_PARAM_AWAY_TIME; 3564 case VENDOR_CONTROL_PARAM_ROAM_ALL: 3565 return ROAM_VENDOR_CONTROL_PARAM_ALL; 3566 default: 3567 wmi_debug("Invalid param id"); 3568 return 0; 3569 } 3570 } 3571 3572 /** 3573 * convert_wmi_roam_vendor_control_param() - Function to convert TLV specific 3574 * WMI_ROAM_GET_VENDOR_CONTROL_PARAM_ID to vendor_control_roam_param 3575 * @param_id: wmi vendor control param id 3576 * 3577 * Return: roam vendor control param id 3578 */ 3579 static enum vendor_control_roam_param convert_wmi_roam_vendor_control_param( 3580 WMI_ROAM_GET_VENDOR_CONTROL_PARAM_ID param_id) 3581 { 3582 switch (param_id) { 3583 case ROAM_VENDOR_CONTROL_PARAM_TRIGGER: 3584 return VENDOR_CONTROL_PARAM_ROAM_TRIGGER; 3585 case ROAM_VENDOR_CONTROL_PARAM_DELTA: 3586 return VENDOR_CONTROL_PARAM_ROAM_DELTA; 3587 case ROAM_VENDOR_CONTROL_PARAM_FULL_SCANPERIOD: 3588 return VENDOR_CONTROL_PARAM_ROAM_FULL_SCANPERIOD; 3589 case ROAM_VENDOR_CONTROL_PARAM_PARTIAL_SCANPERIOD: 3590 return VENDOR_CONTROL_PARAM_ROAM_PARTIAL_SCANPERIOD; 3591 case ROAM_VENDOR_CONTROL_PARAM_ACTIVE_CH_DWELLTIME: 3592 return VENDOR_CONTROL_PARAM_ROAM_ACTIVE_CH_DWELLTIME; 3593 case ROAM_VENDOR_CONTROL_PARAM_PASSIVE_CH_DWELLTIME: 3594 return VENDOR_CONTROL_PARAM_ROAM_PASSIVE_CH_DWELLTIME; 3595 case ROAM_VENDOR_CONTROL_PARAM_HOME_CH_TIME: 3596 return VENDOR_CONTROL_PARAM_ROAM_HOME_CH_TIME; 3597 case ROAM_VENDOR_CONTROL_PARAM_AWAY_TIME: 3598 return VENDOR_CONTROL_PARAM_ROAM_AWAY_TIME; 3599 case ROAM_VENDOR_CONTROL_PARAM_ALL: 3600 return VENDOR_CONTROL_PARAM_ROAM_ALL; 3601 default: 3602 wmi_debug("Invalid param id"); 3603 return 0; 3604 } 3605 } 3606 3607 static QDF_STATUS 3608 extract_roam_vendor_control_param_event_tlv(wmi_unified_t wmi_handle, 3609 uint8_t *event, uint32_t len, 3610 struct roam_vendor_handoff_params **list) 3611 { 3612 WMI_ROAM_GET_VENDOR_CONTROL_PARAM_EVENTID_param_tlvs *param_buf = NULL; 3613 wmi_roam_get_vendor_control_param_event_fixed_param *fixed_param = NULL; 3614 uint32_t num_entries, i; 3615 wmi_vendor_control_param *src_list; 3616 struct roam_vendor_handoff_params *dst_list; 3617 struct roam_param_info *param_info; 3618 3619 if (!event || !len) { 3620 wmi_debug("Empty roam vendor control param event"); 3621 return QDF_STATUS_E_FAILURE; 3622 } 3623 3624 param_buf = 3625 (WMI_ROAM_GET_VENDOR_CONTROL_PARAM_EVENTID_param_tlvs *)event; 3626 if (!param_buf) { 3627 wmi_err("received null buf from target"); 3628 return QDF_STATUS_E_INVAL; 3629 } 3630 3631 fixed_param = (wmi_roam_get_vendor_control_param_event_fixed_param *) 3632 param_buf->fixed_param; 3633 if (!fixed_param) { 3634 wmi_err("received null event data from target"); 3635 return QDF_STATUS_E_INVAL; 3636 } 3637 3638 if (fixed_param->vdev_id >= WLAN_MAX_VDEVS) { 3639 wmi_debug("Invalid VDEV id %d", fixed_param->vdev_id); 3640 return QDF_STATUS_E_FAILURE; 3641 } 3642 3643 num_entries = param_buf->num_vendor_control_param; 3644 src_list = param_buf->vendor_control_param; 3645 3646 if (len < (sizeof(*fixed_param) + (num_entries * sizeof(*src_list)))) { 3647 wmi_err("Invalid length: %d", len); 3648 return QDF_STATUS_E_FAILURE; 3649 } 3650 3651 dst_list = qdf_mem_malloc(sizeof(struct roam_vendor_handoff_params)); 3652 if (!dst_list) 3653 return QDF_STATUS_E_FAILURE; 3654 3655 dst_list->vdev_id = fixed_param->vdev_id; 3656 wmi_debug("vdev_id:%d, num_tlv:%d", dst_list->vdev_id, num_entries); 3657 3658 param_info = &dst_list->param_info[0]; 3659 for (i = 0; i < num_entries; i++) { 3660 param_info->param_id = 3661 convert_wmi_roam_vendor_control_param(src_list->param_id); 3662 param_info->param_value = src_list->param_value; 3663 wmi_debug("param_info->param_id:%d, param_info->param_value:%d", 3664 param_info->param_id, param_info->param_value); 3665 param_info++; 3666 src_list++; 3667 } 3668 3669 dst_list->num_entries = num_entries; 3670 *list = dst_list; 3671 3672 return QDF_STATUS_SUCCESS; 3673 } 3674 3675 /** 3676 * send_process_roam_vendor_handoff_req_cmd_tlv() - Send vendor handoff command 3677 * to fw. 3678 * @wmi_handle: wmi handle 3679 * @vdev_id: vdev id 3680 * @param_id: parameter ID to set 3681 * 3682 * Return: QDF STATUS 3683 */ 3684 static QDF_STATUS 3685 send_process_roam_vendor_handoff_req_cmd_tlv(wmi_unified_t wmi_handle, 3686 uint8_t vdev_id, 3687 uint32_t param_id) 3688 { 3689 wmi_roam_get_vendor_control_param_cmd_fixed_param *cmd; 3690 wmi_buf_t wmi_buf; 3691 uint8_t *buf_ptr; 3692 uint16_t len; 3693 3694 len = sizeof(wmi_roam_get_vendor_control_param_cmd_fixed_param); 3695 3696 wmi_buf = wmi_buf_alloc(wmi_handle, len); 3697 if (!wmi_buf) 3698 return QDF_STATUS_E_NOMEM; 3699 3700 cmd = (wmi_roam_get_vendor_control_param_cmd_fixed_param *)wmi_buf_data( 3701 wmi_buf); 3702 buf_ptr = (uint8_t *)cmd; 3703 WMITLV_SET_HDR(&cmd->tlv_header, 3704 WMITLV_TAG_STRUC_wmi_roam_get_vendor_control_param_cmd_fixed_param, 3705 WMITLV_GET_STRUCT_TLVLEN 3706 (wmi_roam_get_vendor_control_param_cmd_fixed_param)); 3707 cmd->vdev_id = vdev_id; 3708 cmd->param_id = convert_roam_vendor_control_param(param_id); 3709 wmi_debug("Send GET_VENDOR_CONTROL_PARAM cmd vdev_id:%d, param_id:0x%x", 3710 cmd->vdev_id, cmd->param_id); 3711 wmi_mtrace(WMI_ROAM_GET_VENDOR_CONTROL_PARAM_CMDID, cmd->vdev_id, 0); 3712 if (wmi_unified_cmd_send(wmi_handle, wmi_buf, len, 3713 WMI_ROAM_GET_VENDOR_CONTROL_PARAM_CMDID)) { 3714 wmi_err("Failed to send get vendor control param command"); 3715 wmi_buf_free(wmi_buf); 3716 return QDF_STATUS_E_FAILURE; 3717 } 3718 3719 return QDF_STATUS_SUCCESS; 3720 } 3721 3722 /** 3723 * wmi_roam_offload_attach_vendor_handoff_tlv() - register wmi ops for vendor 3724 * handoff related command and event 3725 * @ops: wmi ops 3726 * 3727 * Return: none 3728 */ 3729 static inline void 3730 wmi_roam_offload_attach_vendor_handoff_tlv(struct wmi_ops *ops) 3731 { 3732 ops->extract_roam_vendor_control_param_event = 3733 extract_roam_vendor_control_param_event_tlv; 3734 ops->send_process_roam_vendor_handoff_req_cmd = 3735 send_process_roam_vendor_handoff_req_cmd_tlv; 3736 } 3737 #else 3738 static inline void 3739 wmi_roam_offload_attach_vendor_handoff_tlv(struct wmi_ops *ops) 3740 { 3741 } 3742 #endif 3743 3744 #if defined(WLAN_FEATURE_ROAM_OFFLOAD) && defined(WLAN_FEATURE_11BE_MLO) 3745 static inline 3746 enum wlan_crypto_cipher_type wlan_wmi_cipher_to_crypto(uint8_t cipher) 3747 { 3748 switch (cipher) { 3749 case WMI_CIPHER_NONE: 3750 return WLAN_CRYPTO_CIPHER_NONE; 3751 case WMI_CIPHER_WEP: 3752 return WLAN_CRYPTO_CIPHER_WEP; 3753 case WMI_CIPHER_TKIP: 3754 return WLAN_CRYPTO_CIPHER_TKIP; 3755 case WMI_CIPHER_AES_OCB: 3756 return WLAN_CRYPTO_CIPHER_AES_OCB; 3757 case WMI_CIPHER_AES_CCM: 3758 return WLAN_CRYPTO_CIPHER_AES_CCM; 3759 case WMI_CIPHER_WAPI: 3760 return WLAN_CRYPTO_CIPHER_WAPI_SMS4; 3761 case WMI_CIPHER_CKIP: 3762 return WLAN_CRYPTO_CIPHER_CKIP; 3763 case WMI_CIPHER_AES_CMAC: 3764 return WLAN_CRYPTO_CIPHER_AES_CMAC; 3765 case WMI_CIPHER_AES_GCM: 3766 return WLAN_CRYPTO_CIPHER_AES_GCM; 3767 case WMI_CIPHER_AES_GMAC: 3768 return WLAN_CRYPTO_CIPHER_AES_GMAC; 3769 case WMI_CIPHER_WAPI_GCM_SM4: 3770 return WLAN_CRYPTO_CIPHER_WAPI_GCM4; 3771 case WMI_CIPHER_BIP_CMAC_128: 3772 return WLAN_CRYPTO_CIPHER_AES_CMAC; 3773 case WMI_CIPHER_BIP_CMAC_256: 3774 return WLAN_CRYPTO_CIPHER_AES_CMAC_256; 3775 case WMI_CIPHER_BIP_GMAC_128: 3776 return WLAN_CRYPTO_CIPHER_AES_GMAC; 3777 case WMI_CIPHER_BIP_GMAC_256: 3778 return WLAN_CRYPTO_CIPHER_AES_GMAC_256; 3779 3780 default: 3781 return 0; 3782 } 3783 } 3784 #define MLO_PAIRWISE_LINKID 0xF 3785 /** 3786 * wmi_fill_keys_from_tlv - Fill the destination key buffer from the WMI TLV 3787 * @ml_keys: ML Keys TLV pointer 3788 * @dst_key: Destination keys 3789 * @dst_key_len: Destination keys length 3790 * @count: TLV count 3791 * @max_num_tlv: Total number of TLVs 3792 * 3793 * Return: None 3794 */ 3795 static void 3796 wmi_fill_keys_from_tlv(wmi_roam_ml_key_material_param **ml_keys, 3797 uint8_t *dst_key, uint8_t *dst_key_len, uint8_t *count, 3798 uint8_t max_num_tlv) 3799 { 3800 uint8_t rem_key_len, bytes_filled, key_len, total_key_len; 3801 uint8_t max_key_len = WLAN_CRYPTO_KEYBUF_SIZE + WLAN_CRYPTO_MICBUF_SIZE; 3802 3803 *dst_key_len = (*ml_keys)->key_len; 3804 if (*dst_key_len > max_key_len) 3805 *dst_key_len = max_key_len; 3806 3807 total_key_len = *dst_key_len; 3808 rem_key_len = *dst_key_len; 3809 3810 while (rem_key_len) { 3811 if (!(*ml_keys)) { 3812 wmi_err_rl("ml_keys is NULL. rem_key_len:%d", 3813 rem_key_len); 3814 return; 3815 } 3816 3817 if (*count >= max_num_tlv) { 3818 wmi_debug("Read all TLVs count:%d", *count); 3819 return; 3820 } 3821 3822 if (rem_key_len < WMI_MAX_KEY_LEN) 3823 key_len = rem_key_len; 3824 else 3825 key_len = WMI_MAX_KEY_LEN; 3826 3827 bytes_filled = total_key_len - rem_key_len; 3828 qdf_mem_copy(dst_key + bytes_filled, (*ml_keys)->key_buff, 3829 key_len); 3830 (*ml_keys)++; 3831 (*count)++; 3832 3833 rem_key_len -= key_len; 3834 } 3835 } 3836 3837 #define WMI_NUM_KEYS_ALLOCATED (WLAN_MAX_ML_BSS_LINKS * 4) 3838 static QDF_STATUS 3839 extract_roam_synch_key_event_tlv(wmi_unified_t wmi_handle, 3840 uint8_t *event, uint32_t data_len, 3841 struct wlan_crypto_key_entry **entries, 3842 uint8_t *num_entries, 3843 struct qdf_mac_addr *mld_addr) 3844 { 3845 WMI_ROAM_SYNCH_KEY_EVENTID_param_tlvs *param_buf = NULL; 3846 wmi_roam_ml_key_material_param *ml_keys = NULL; 3847 struct wlan_crypto_key_entry *key_entry; 3848 struct wlan_crypto_keys *all_keys; 3849 struct wlan_crypto_key *dst_key, *pairwise; 3850 struct wlan_crypto_key *key_alloc_buf[WMI_NUM_KEYS_ALLOCATED]; 3851 bool flush_keybuf; 3852 uint8_t total_num_tlv, j = 0, k = 0; 3853 uint8_t count = 0, total_links = 0, dst_key_count = 0; 3854 uint8_t igtk_idx = 0, bigtk_idx = 0; 3855 bool slot_found; 3856 QDF_STATUS status = QDF_STATUS_SUCCESS; 3857 3858 param_buf = (WMI_ROAM_SYNCH_KEY_EVENTID_param_tlvs *)event; 3859 if (!param_buf) { 3860 wmi_err_rl("received null buf from target"); 3861 return QDF_STATUS_E_INVAL; 3862 } 3863 3864 total_num_tlv = param_buf->num_ml_key_material; 3865 ml_keys = (wmi_roam_ml_key_material_param *)param_buf->ml_key_material; 3866 if (!ml_keys) { 3867 wmi_err_rl("received ml keys param is null"); 3868 return QDF_STATUS_E_INVAL; 3869 } 3870 3871 *entries = qdf_mem_malloc(WLAN_MAX_ML_BSS_LINKS * sizeof(*key_entry)); 3872 if (!*entries) 3873 return QDF_STATUS_E_NOMEM; 3874 3875 /* 3876 * Allocate memory for each PTK, GTK, IGTK, BIGTK keys. 3877 * So total WLAN_MAX_ML_BSS_LINKS * 4 keys are needed 3878 */ 3879 for (k = 0; k < WMI_NUM_KEYS_ALLOCATED; k++) { 3880 key_alloc_buf[k] = qdf_mem_malloc(sizeof(*dst_key)); 3881 if (!key_alloc_buf[k]) { 3882 flush_keybuf = true; 3883 status = QDF_STATUS_E_NOMEM; 3884 goto free_entries; 3885 } 3886 } 3887 3888 /* 3889 * key_entry is the master structure that is given directly to the 3890 * crypto module and stored for each link. 3891 * key_entry -> keys ->key filled from dst_key has the PTK & GTK indexed 3892 * with corresponding key index 3893 * 3894 * key_entry -> keys -> iGTK holds the iGTK key 3895 * key_entry -> keys -> BIGTK holds the BIGTK key 3896 */ 3897 key_entry = *entries; 3898 3899 /* 3900 * Initialize all the Key Entry structures with invalid Link 3901 * ID to identify empty links allocated and will be freed 3902 * at the end. 3903 */ 3904 for (j = 0; j < WLAN_MAX_ML_BSS_LINKS; j++) 3905 key_entry[j].link_id = MLO_INVALID_LINK_IDX; 3906 3907 /* 3908 * TLV Format to parse: 3909 * 1. wmi_roam_ml_key_material_param -> For PTK with Link ID = 0xF 3910 * Copy this PTK to all the key entry of all the links. 3911 * 3912 * 2. wmi_roam_ml_key_material_param -> GTK for a valid Link. 3913 * Get available entry, and fill the GTK to that entry 3914 * 3915 * 3. wmi_roam_ml_key_material_param -> IGTK for a valid link 3916 * 3917 * 4. wmi_roam_ml_key_material_param -> BIGTK for a valid link 3918 * 3919 * 5. wmi_roam_ml_key_material_param -> For LTF Keyseed with Link ID = 3920 * 0xF and flags has LTF_USAGE set. 3921 * 3922 * If any of the key length is > WMI_MAX_KEY_LEN, then multiple 3923 * wmi_roam_ml_key_material_param TLVs follow to get the entire key 3924 */ 3925 while (ml_keys && count < total_num_tlv && 3926 dst_key_count < WMI_NUM_KEYS_ALLOCATED) { 3927 /* 3928 * Track individual keys with key_alloc_buf[dst_key_count] array 3929 * pointer to avoid mem leaks if parsing/validating any of the 3930 * keys fail. 3931 * Freeing the allocated keys it done at the end of this 3932 * function 3933 */ 3934 dst_key = key_alloc_buf[dst_key_count]; 3935 wmi_debug("link_id:%d key_ix:%d key_cipher:%d key_len:%d key_flags:%d", 3936 ml_keys->link_id, ml_keys->key_ix, 3937 ml_keys->key_cipher, 3938 ml_keys->key_len, ml_keys->key_flags); 3939 3940 if (!is_valid_keyix(ml_keys->key_ix)) { 3941 wmi_err_rl("invalid key index:%d", ml_keys->key_ix); 3942 status = QDF_STATUS_E_INVAL; 3943 flush_keybuf = true; 3944 goto free_entries; 3945 } 3946 3947 /* Copy pairwise keys to all the entries */ 3948 if (ml_keys->link_id == MLO_PAIRWISE_LINKID) { 3949 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ml_keys->mac_addr, 3950 mld_addr->bytes); 3951 if (!ml_keys->key_len) { 3952 wmi_err_rl("Received key_len as 0 for tlv:%d", 3953 count); 3954 status = QDF_STATUS_E_INVAL; 3955 flush_keybuf = true; 3956 goto free_entries; 3957 } 3958 3959 if (ml_keys->key_flags & LTF_USAGE) { 3960 struct wlan_crypto_ltf_keyseed_data key_seed; 3961 uint8_t key_seed_len; 3962 3963 if (ml_keys->key_len > 3964 WLAN_MAX_SECURE_LTF_KEYSEED_LEN) 3965 ml_keys->key_len = 3966 WLAN_MAX_SECURE_LTF_KEYSEED_LEN; 3967 3968 /* 3969 * Filling the keys from multiple TLVs is 3970 * handled by below API and ml_keys ptr gets 3971 * incremented accordingly inside 3972 */ 3973 wmi_fill_keys_from_tlv(&ml_keys, 3974 key_seed.key_seed, 3975 &key_seed_len, &count, 3976 total_num_tlv); 3977 key_seed.key_seed_len = key_seed_len; 3978 wmi_debug("ML_KEY: Got LTF keyseed key for MLD: " 3979 QDF_MAC_ADDR_FMT " key_seed_len:%d", 3980 QDF_MAC_ADDR_REF(mld_addr->bytes), 3981 key_seed.key_seed_len); 3982 3983 for (j = 0; j < WLAN_MAX_ML_BSS_LINKS; j++) 3984 key_entry[j].keys.ltf_key_seed = 3985 key_seed; 3986 3987 continue; 3988 } 3989 3990 dst_key->valid = true; 3991 dst_key->keylen = ml_keys->key_len; 3992 dst_key->flags = ml_keys->key_flags; 3993 dst_key->keyix = ml_keys->key_ix; 3994 dst_key->key_type = 3995 WLAN_CRYPTO_KEY_TYPE_UNICAST; 3996 dst_key->cipher_type = 3997 wlan_wmi_cipher_to_crypto(ml_keys->key_cipher); 3998 dst_key->keylen = ml_keys->key_len; 3999 4000 wmi_fill_keys_from_tlv(&ml_keys, dst_key->keyval, 4001 &dst_key->keylen, &count, 4002 total_num_tlv); 4003 wmi_err_rl("ML_KEY: Got Pairwise key for MLD: " 4004 QDF_MAC_ADDR_FMT " rem_len:%d", 4005 QDF_MAC_ADDR_REF(mld_addr->bytes), 4006 dst_key->keylen); 4007 4008 pairwise = dst_key; 4009 /* 4010 * Pairwise keys will be sent only once. Copy that for 4011 * all the link entries 4012 */ 4013 for (j = 0; j < WLAN_MAX_ML_BSS_LINKS; j++) { 4014 dst_key = key_alloc_buf[dst_key_count]; 4015 *dst_key = *pairwise; 4016 key_entry[j].keys.key[dst_key->keyix] = dst_key; 4017 dst_key_count++; 4018 } 4019 4020 continue; 4021 } 4022 4023 slot_found = false; 4024 for (j = 0; j < WLAN_MAX_ML_BSS_LINKS; j++) { 4025 if (ml_keys->link_id == MLO_INVALID_LINK_IDX) 4026 break; 4027 4028 if (key_entry[j].link_id == MLO_INVALID_LINK_IDX || 4029 key_entry[j].link_id == ml_keys->link_id) { 4030 slot_found = true; 4031 break; 4032 } 4033 } 4034 4035 if (!slot_found) { 4036 wmi_err_rl("Not able to find a entry for link:%d j=%d", 4037 ml_keys->link_id, j); 4038 break; 4039 } 4040 4041 WMI_MAC_ADDR_TO_CHAR_ARRAY(&ml_keys->mac_addr, 4042 dst_key->macaddr); 4043 key_entry[j].link_id = ml_keys->link_id; 4044 qdf_copy_macaddr((struct qdf_mac_addr *)key_entry[j].mac_addr.raw, 4045 (struct qdf_mac_addr *)dst_key->macaddr); 4046 all_keys = &key_entry[j].keys; 4047 4048 dst_key->valid = true; 4049 dst_key->keyix = ml_keys->key_ix; 4050 dst_key->cipher_type = 4051 wlan_wmi_cipher_to_crypto(ml_keys->key_cipher); 4052 4053 qdf_mem_copy(dst_key->keyrsc, ml_keys->pn, WMI_MAX_PN_LEN); 4054 4055 /* 4056 * For LTF keyseed or FILS SHA 384, FILS SHA 512 cases, the key 4057 * size will go beyond WMI_MAX_KEY_LEN(32). So extract first 32 4058 * bytes from 1st TLV and extract the rest of the bytes from 4059 * the following TLVs 4060 */ 4061 dst_key->keylen = ml_keys->key_len; 4062 wmi_fill_keys_from_tlv(&ml_keys, dst_key->keyval, 4063 &dst_key->keylen, &count, total_num_tlv); 4064 4065 if (is_igtk(dst_key->keyix)) { 4066 dst_key->key_type = WLAN_CRYPTO_KEY_TYPE_GROUP; 4067 4068 igtk_idx = dst_key->keyix - WLAN_CRYPTO_MAXKEYIDX; 4069 bigtk_idx = igtk_idx - WLAN_CRYPTO_MAXIGTKKEYIDX; 4070 4071 wmi_debug("ML_KEY: Slot:%d link_id:%d addr: " QDF_MAC_ADDR_FMT "Key is IGTK key_ix:%d igtk_idx:%d bigtk:%d", 4072 j, key_entry[j].link_id, 4073 QDF_MAC_ADDR_REF(dst_key->macaddr), 4074 dst_key->keyix, igtk_idx, bigtk_idx); 4075 all_keys->igtk_key[igtk_idx] = dst_key; 4076 all_keys->def_igtk_tx_keyid = igtk_idx; 4077 4078 bigtk_idx = 0; 4079 igtk_idx = 0; 4080 } else if (is_bigtk(dst_key->keyix)) { 4081 dst_key->key_type = WLAN_CRYPTO_KEY_TYPE_GROUP; 4082 4083 igtk_idx = dst_key->keyix - WLAN_CRYPTO_MAXKEYIDX; 4084 bigtk_idx = igtk_idx - WLAN_CRYPTO_MAXIGTKKEYIDX; 4085 4086 wmi_debug("ML_KEY: Slot:%d link_id:%d addr: " QDF_MAC_ADDR_FMT "Key is BIGTK key_ix:%d igtk_idx:%d bigtk:%d", 4087 j, key_entry[j].link_id, 4088 QDF_MAC_ADDR_REF(dst_key->macaddr), 4089 dst_key->keyix, igtk_idx, bigtk_idx); 4090 all_keys->bigtk_key[bigtk_idx] = dst_key; 4091 all_keys->def_bigtk_tx_keyid = bigtk_idx; 4092 4093 bigtk_idx = 0; 4094 igtk_idx = 0; 4095 } else if (is_gtk(dst_key->keyix)) { 4096 wmi_debug("ML_KEY: Slot:%d link_id:%d addr: " QDF_MAC_ADDR_FMT " Key is GTK key_ix:%d", 4097 j, key_entry[j].link_id, 4098 QDF_MAC_ADDR_REF(dst_key->macaddr), 4099 dst_key->keyix); 4100 dst_key->key_type = WLAN_CRYPTO_KEY_TYPE_GROUP; 4101 all_keys->key[dst_key->keyix] = dst_key; 4102 } else { 4103 wmi_debug("Key is Pairwise. Shouldn't reach here"); 4104 /* Pairwise key */ 4105 dst_key->key_type = WLAN_CRYPTO_KEY_TYPE_UNICAST; 4106 all_keys->key[dst_key->keyix] = dst_key; 4107 } 4108 4109 dst_key_count++; 4110 } 4111 4112 for (j = 0; j < WLAN_MAX_ML_BSS_LINKS; j++) { 4113 /* 4114 * Pairwise keys maybe copied for all the WLAN_MAX_ML_BSS_LINKS 4115 * but firmware might have roamed to AP with number of links 4116 * less than WLAN_MAX_ML_BSS_LINKS. So free the memory for those 4117 * links 4118 */ 4119 if (key_entry[j].link_id != MLO_INVALID_LINK_IDX) { 4120 total_links++; 4121 } else { 4122 wmi_err_rl("Free keys for invalid entry at index:%d", 4123 j); 4124 wlan_crypto_free_key(&key_entry[j].keys); 4125 } 4126 } 4127 4128 *num_entries = total_links; 4129 /* Free the invalid dst_keys allocated */ 4130 if (!*num_entries) 4131 goto free_entries; 4132 4133 /* 4134 * This is to free the unfilled key_alloc_buf that 4135 * was allocated initially 4136 */ 4137 flush_keybuf = false; 4138 4139 wmi_err_rl("ML_KEYS: total_entries filled:%d total_num_tlv:%d dst_key_count:%d", 4140 *num_entries, total_num_tlv, dst_key_count); 4141 goto free_keys; 4142 4143 free_entries: 4144 qdf_mem_zero(*entries, 4145 WLAN_MAX_ML_BSS_LINKS * sizeof(**entries)); 4146 qdf_mem_free(*entries); 4147 4148 free_keys: 4149 for (k = 0; k < WMI_NUM_KEYS_ALLOCATED; k++) { 4150 if (!key_alloc_buf[k]) 4151 continue; 4152 4153 wmi_err_rl("flush keybuf :%d, key is valid", flush_keybuf, 4154 key_alloc_buf[k]->valid); 4155 if (!flush_keybuf && key_alloc_buf[k]->valid) 4156 continue; 4157 4158 wmi_err("Free key allocated at idx:%d", k); 4159 qdf_mem_zero(key_alloc_buf[k], sizeof(*key_alloc_buf[k])); 4160 qdf_mem_free(key_alloc_buf[k]); 4161 } 4162 4163 return status; 4164 } 4165 4166 static void 4167 wmi_roam_offload_attach_mlo_tlv(struct wmi_ops *ops) 4168 { 4169 ops->extract_roam_synch_key_event = extract_roam_synch_key_event_tlv; 4170 } 4171 #else 4172 static inline void 4173 wmi_roam_offload_attach_mlo_tlv(struct wmi_ops *ops) 4174 {} 4175 #endif 4176 4177 void wmi_roam_offload_attach_tlv(wmi_unified_t wmi_handle) 4178 { 4179 struct wmi_ops *ops = wmi_handle->ops; 4180 4181 ops->extract_roam_btm_response_stats = 4182 extract_roam_btm_response_stats_tlv; 4183 ops->extract_roam_initial_info = extract_roam_initial_info_tlv; 4184 ops->extract_roam_msg_info = extract_roam_msg_info_tlv; 4185 ops->extract_roam_frame_info = extract_roam_frame_info_tlv; 4186 ops->extract_roam_sync_event = extract_roam_sync_event_tlv; 4187 ops->extract_roam_sync_frame_event = extract_roam_sync_frame_event_tlv; 4188 ops->extract_roam_event = extract_roam_event_tlv; 4189 ops->extract_btm_dl_event = extract_btm_denylist_event; 4190 ops->extract_vdev_disconnect_event = extract_vdev_disconnect_event_tlv; 4191 ops->extract_roam_scan_chan_list = extract_roam_scan_chan_list_tlv; 4192 ops->extract_roam_stats_event = extract_roam_stats_event_tlv; 4193 ops->extract_auth_offload_event = extract_auth_offload_event_tlv; 4194 ops->extract_roam_pmkid_request = extract_roam_pmkid_request_tlv; 4195 ops->send_set_ric_req_cmd = send_set_ric_req_cmd_tlv; 4196 ops->send_process_roam_synch_complete_cmd = 4197 send_process_roam_synch_complete_cmd_tlv; 4198 ops->send_roam_invoke_cmd = send_roam_invoke_cmd_tlv; 4199 ops->send_vdev_set_pcl_cmd = send_vdev_set_pcl_cmd_tlv; 4200 ops->send_set_roam_trigger_cmd = send_set_roam_trigger_cmd_tlv; 4201 ops->extract_roam_candidate_frame = extract_roam_candidate_frame_tlv; 4202 ops->extract_peer_oper_mode_event = extract_peer_oper_mode_event_tlv; 4203 wmi_roam_offload_attach_vendor_handoff_tlv(ops); 4204 wmi_roam_offload_attach_mlo_tlv(ops); 4205 } 4206 #else 4207 static inline QDF_STATUS 4208 extract_roam_btm_response_stats_tlv(wmi_unified_t wmi_handle, void *evt_buf, 4209 struct roam_btm_response_data *dst, 4210 uint8_t idx) 4211 { 4212 return QDF_STATUS_E_NOSUPPORT; 4213 } 4214 4215 static inline QDF_STATUS 4216 extract_roam_initial_info_tlv(wmi_unified_t wmi_handle, void *evt_buf, 4217 struct roam_initial_data *dst, uint8_t idx) 4218 { 4219 return QDF_STATUS_E_NOSUPPORT; 4220 } 4221 4222 static inline QDF_STATUS 4223 extract_roam_msg_info_tlv(wmi_unified_t wmi_handle, void *evt_buf, 4224 struct roam_msg_info *dst, uint8_t idx) 4225 { 4226 return QDF_STATUS_E_NOSUPPORT; 4227 } 4228 4229 static inline QDF_STATUS 4230 extract_roam_sync_event(wmi_unified_t wmi_handle, void *evt_buf, 4231 uint32_t len, 4232 struct roam_offload_synch_ind **roam_sync_ind) 4233 { 4234 return QDF_STATUS_E_NOSUPPORT; 4235 } 4236 4237 static inline QDF_STATUS 4238 extract_roam_sync_frame_event(wmi_unified_t wmi_handle, void *evt_buf, 4239 struct roam_msg_info *dst, uint8_t idx) 4240 { 4241 return QDF_STATUS_E_NOSUPPORT; 4242 } 4243 4244 static inline QDF_STATUS 4245 extract_roam_event(wmi_unified_t wmi_handle, void *evt_buf, uint32_t len, 4246 struct roam_offload_roam_event *roam_event) 4247 { 4248 return QDF_STATUS_E_NOSUPPORT; 4249 } 4250 #endif /* WLAN_FEATURE_ROAM_OFFLOAD */ 4251 4252 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 4253 /** 4254 * wmi_fill_roam_offload_11r_params() - Fill roam scan params to send it to fw 4255 * @akm: Authentication key management type 4256 * @roam_offload_11r: TLV to be filled with 11r params 4257 * @roam_req: roam request param 4258 */ 4259 static void wmi_fill_roam_offload_11r_params( 4260 uint32_t akm, 4261 wmi_roam_11r_offload_tlv_param *roam_offload_11r, 4262 struct wlan_roam_scan_offload_params *roam_req) 4263 { 4264 struct wlan_rso_11r_params *src_11r_params; 4265 uint8_t *psk_msk, len; 4266 4267 src_11r_params = &roam_req->rso_11r_info; 4268 4269 if ((akm == WMI_AUTH_FT_RSNA_FILS_SHA256 || 4270 akm == WMI_AUTH_FT_RSNA_FILS_SHA384) && 4271 roam_req->fils_roam_config.fils_ft_len) { 4272 wmi_debug("Update the FILS FT key to Firmware"); 4273 psk_msk = roam_req->fils_roam_config.fils_ft; 4274 len = roam_req->fils_roam_config.fils_ft_len; 4275 } else { 4276 psk_msk = src_11r_params->psk_pmk; 4277 len = src_11r_params->pmk_len; 4278 } 4279 4280 /* 4281 * For SHA384 based akm, the pmk length is 48 bytes. So fill 4282 * first 32 bytes in roam_offload_11r->psk_msk and the remaining 4283 * bytes in roam_offload_11r->psk_msk_ext buffer 4284 */ 4285 roam_offload_11r->psk_msk_len = len > ROAM_OFFLOAD_PSK_MSK_BYTES ? 4286 ROAM_OFFLOAD_PSK_MSK_BYTES : len; 4287 qdf_mem_copy(roam_offload_11r->psk_msk, psk_msk, 4288 roam_offload_11r->psk_msk_len); 4289 roam_offload_11r->psk_msk_ext_len = 0; 4290 4291 if (len > ROAM_OFFLOAD_PSK_MSK_BYTES) { 4292 roam_offload_11r->psk_msk_ext_len = 4293 len - roam_offload_11r->psk_msk_len; 4294 qdf_mem_copy(roam_offload_11r->psk_msk_ext, 4295 &psk_msk[roam_offload_11r->psk_msk_len], 4296 roam_offload_11r->psk_msk_ext_len); 4297 } 4298 } 4299 4300 /** 4301 * wmi_is_ft_akm() - Check if the akm is FT akm. Based on the AKM 11r params 4302 * will be sent for lfr-3.0 roaming offload 4303 * @akm: AKM negotiated for the connection 4304 * @roam_req: roam request sent to firmware 4305 * 4306 * Return: true if the akm is 11r based 4307 */ 4308 static bool wmi_is_ft_akm(int akm, 4309 struct wlan_roam_scan_offload_params *roam_req) 4310 { 4311 switch (akm) { 4312 case WMI_AUTH_FT_RSNA: 4313 case WMI_AUTH_FT_RSNA_PSK: 4314 case WMI_AUTH_FT_RSNA_SAE: 4315 case WMI_AUTH_FT_RSNA_SUITE_B_8021X_SHA384: 4316 case WMI_AUTH_FT_RSNA_FILS_SHA256: 4317 case WMI_AUTH_FT_RSNA_FILS_SHA384: 4318 case WMI_AUTH_FT_RSNA_SAE_SHA384: 4319 return true; 4320 case WMI_AUTH_OPEN: 4321 if (roam_req->rso_11r_info.mdid.mdie_present && 4322 roam_req->rso_11r_info.is_11r_assoc) 4323 return true; 4324 4325 break; 4326 default: 4327 return false; 4328 } 4329 4330 return false; 4331 } 4332 4333 /** 4334 * wmi_get_rso_buf_len() - calculate the length needed to allocate buffer 4335 * for RSO mode command 4336 * @roam_req: roam request parameters 4337 */ 4338 static uint32_t 4339 wmi_get_rso_buf_len(struct wlan_roam_scan_offload_params *roam_req) 4340 { 4341 wmi_tlv_buf_len_param *assoc_ies; 4342 uint32_t buf_len; 4343 uint32_t fils_tlv_len = 0; 4344 int akm = roam_req->akm; 4345 4346 /* 4347 * Allocate room for wmi_roam_offload_tlv_param and 4348 * 11i or 11r or ese roam offload tlv param 4349 * Todo: Test if below headroom of 2 TLV header is needed 4350 */ 4351 buf_len = (2 * WMI_TLV_HDR_SIZE); 4352 4353 if (roam_req->is_rso_stop || 4354 !roam_req->roam_offload_enabled) { 4355 buf_len += (4 * WMI_TLV_HDR_SIZE); 4356 4357 if (!roam_req->is_rso_stop) 4358 wmi_debug("vdev[%d]: %s roam offload: %d", 4359 roam_req->vdev_id, 4360 roam_req->is_rso_stop ? "RSO stop cmd." : "", 4361 roam_req->roam_offload_enabled); 4362 4363 return buf_len; 4364 } 4365 4366 wmi_debug("wmi akm = %d", akm); 4367 4368 buf_len += sizeof(wmi_roam_offload_tlv_param); 4369 buf_len += 2 * WMI_TLV_HDR_SIZE; 4370 4371 if ((akm != WMI_AUTH_OPEN || roam_req->rso_ese_info.is_ese_assoc || 4372 wmi_is_ft_akm(akm, roam_req)) && akm != WMI_AUTH_NONE) { 4373 if (roam_req->rso_ese_info.is_ese_assoc) 4374 buf_len += sizeof(wmi_roam_ese_offload_tlv_param); 4375 else if (wmi_is_ft_akm(akm, roam_req)) 4376 buf_len += sizeof(wmi_roam_11r_offload_tlv_param); 4377 else 4378 buf_len += sizeof(wmi_roam_11i_offload_tlv_param); 4379 } 4380 4381 buf_len += (sizeof(*assoc_ies) + (2 * WMI_TLV_HDR_SIZE) + 4382 roundup(roam_req->assoc_ie_length, sizeof(uint32_t))); 4383 4384 /* Fils TLV */ 4385 buf_len += WMI_TLV_HDR_SIZE; 4386 if (roam_req->add_fils_tlv) { 4387 fils_tlv_len = sizeof(wmi_roam_fils_offload_tlv_param); 4388 buf_len += fils_tlv_len; 4389 } 4390 4391 if (roam_req->rso_11i_info.is_sae_same_pmk) 4392 buf_len += WMI_TLV_HDR_SIZE + 4393 sizeof(wmi_roam_sae_offload_tlv_param); 4394 4395 roam_req->rso_mode_info.roam_scan_mode |= 4396 WMI_ROAM_SCAN_MODE_ROAMOFFLOAD; 4397 4398 return buf_len; 4399 } 4400 4401 #if defined(WLAN_FEATURE_FILS_SK) 4402 /** 4403 * wmi_add_fils_tlv() - Add FILS TLV to roam scan offload command 4404 * @wmi_handle: wmi handle 4405 * @roam_req: Roam scan offload params 4406 * @buf_ptr: command buffer to send 4407 * @fils_tlv_len: fils tlv length 4408 * 4409 * Return: Updated buffer pointer 4410 */ 4411 static uint8_t *wmi_add_fils_tlv(wmi_unified_t wmi_handle, 4412 struct wlan_roam_scan_offload_params *roam_req, 4413 uint8_t *buf_ptr, uint32_t fils_tlv_len) 4414 { 4415 wmi_roam_fils_offload_tlv_param *fils_tlv; 4416 wmi_erp_info *erp_info; 4417 struct wlan_roam_fils_params *roam_fils_params; 4418 4419 if (!roam_req->add_fils_tlv) { 4420 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 0); 4421 buf_ptr += WMI_TLV_HDR_SIZE; 4422 return buf_ptr; 4423 } 4424 4425 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 4426 sizeof(*fils_tlv)); 4427 buf_ptr += WMI_TLV_HDR_SIZE; 4428 4429 fils_tlv = (wmi_roam_fils_offload_tlv_param *)buf_ptr; 4430 WMITLV_SET_HDR(&fils_tlv->tlv_header, 4431 WMITLV_TAG_STRUC_wmi_roam_fils_offload_tlv_param, 4432 WMITLV_GET_STRUCT_TLVLEN 4433 (wmi_roam_fils_offload_tlv_param)); 4434 4435 roam_fils_params = &roam_req->fils_roam_config; 4436 erp_info = (wmi_erp_info *)(&fils_tlv->vdev_erp_info); 4437 4438 erp_info->username_length = roam_fils_params->username_length; 4439 qdf_mem_copy(erp_info->username, roam_fils_params->username, 4440 erp_info->username_length); 4441 4442 erp_info->next_erp_seq_num = roam_fils_params->next_erp_seq_num; 4443 4444 erp_info->rRk_length = roam_fils_params->rrk_length; 4445 qdf_mem_copy(erp_info->rRk, roam_fils_params->rrk, 4446 erp_info->rRk_length); 4447 4448 erp_info->rIk_length = roam_fils_params->rik_length; 4449 qdf_mem_copy(erp_info->rIk, roam_fils_params->rik, 4450 erp_info->rIk_length); 4451 4452 erp_info->realm_len = roam_fils_params->realm_len; 4453 qdf_mem_copy(erp_info->realm, roam_fils_params->realm, 4454 erp_info->realm_len); 4455 4456 buf_ptr += sizeof(*fils_tlv); 4457 wmi_debug("RSO_CFG: ERP: usrname_len:%d next_erp_seq_num:%d rRk_len:%d rIk_len:%d realm_len:%d", 4458 erp_info->username_length, erp_info->next_erp_seq_num, 4459 erp_info->rRk_length, erp_info->rIk_length, 4460 erp_info->realm_len); 4461 return buf_ptr; 4462 } 4463 #else 4464 static inline 4465 uint8_t *wmi_add_fils_tlv(wmi_unified_t wmi_handle, 4466 struct wlan_roam_scan_offload_params *roam_req, 4467 uint8_t *buf_ptr, uint32_t fils_tlv_len) 4468 { 4469 return buf_ptr; 4470 } 4471 #endif 4472 4473 #ifdef WLAN_SAE_SINGLE_PMK 4474 static inline void 4475 wmi_fill_sae_single_pmk_param(struct wlan_rso_11i_params *src_11i, 4476 wmi_roam_11i_offload_tlv_param *roam_offload_11i) 4477 { 4478 if (src_11i->is_sae_same_pmk) 4479 roam_offload_11i->flags |= 4480 1 << WMI_ROAM_OFFLOAD_FLAG_SAE_SAME_PMKID; 4481 } 4482 4483 static uint8_t *wmi_fill_sae_single_pmk_tlv( 4484 struct wlan_roam_scan_offload_params *roam_req, uint8_t *buf_ptr) 4485 { 4486 wmi_roam_sae_offload_tlv_param *sae_offload_param; 4487 4488 if (!roam_req->rso_11i_info.is_sae_same_pmk) 4489 return buf_ptr; 4490 4491 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 4492 sizeof(wmi_roam_sae_offload_tlv_param)); 4493 buf_ptr += WMI_TLV_HDR_SIZE; 4494 4495 sae_offload_param = (wmi_roam_sae_offload_tlv_param *)buf_ptr; 4496 WMITLV_SET_HDR(&sae_offload_param->tlv_header, 4497 WMITLV_TAG_STRUC_wmi_roam_sae_offload_tlv_param, 4498 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_sae_offload_tlv_param)); 4499 4500 sae_offload_param->spmk_timeout = 4501 roam_req->sae_offload_params.spmk_timeout; 4502 wmi_debug("spmk_timeout:%d seconds", sae_offload_param->spmk_timeout); 4503 4504 buf_ptr += sizeof(*sae_offload_param); 4505 4506 return buf_ptr; 4507 } 4508 #else 4509 static inline void 4510 wmi_fill_sae_single_pmk_param(struct wlan_rso_11i_params *src_11i, 4511 wmi_roam_11i_offload_tlv_param *roam_offload_11i) 4512 {} 4513 4514 static inline uint8_t *wmi_fill_sae_single_pmk_tlv( 4515 struct wlan_roam_scan_offload_params *roam_req, 4516 uint8_t *buf_ptr) 4517 { 4518 return buf_ptr; 4519 } 4520 4521 #endif 4522 4523 static QDF_STATUS 4524 wmi_fill_rso_tlvs(wmi_unified_t wmi_handle, uint8_t *buf, 4525 struct wlan_roam_scan_offload_params *roam_req) 4526 { 4527 wmi_roam_offload_tlv_param *roam_offload_params; 4528 wmi_roam_11i_offload_tlv_param *roam_offload_11i; 4529 wmi_roam_11r_offload_tlv_param *roam_offload_11r; 4530 wmi_roam_ese_offload_tlv_param *roam_offload_ese; 4531 wmi_tlv_buf_len_param *assoc_ies; 4532 uint32_t fils_tlv_len = 0; 4533 int akm = roam_req->akm; 4534 struct wlan_rso_lfr3_params *src_lfr3_params = 4535 &roam_req->rso_lfr3_params; 4536 struct wlan_rso_lfr3_caps *src_lfr3_caps = 4537 &roam_req->rso_lfr3_caps; 4538 struct wlan_rso_11i_params *src_11i_info = 4539 &roam_req->rso_11i_info; 4540 struct wlan_rso_ese_params *src_ese_info = 4541 &roam_req->rso_ese_info; 4542 struct wlan_rso_11r_params *src_11r_info = 4543 &roam_req->rso_11r_info; 4544 4545 /* For RSO stop command, dont fill 11i, 11r or ese tlv */ 4546 if (roam_req->is_rso_stop || !roam_req->roam_offload_enabled) { 4547 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 4548 WMITLV_GET_STRUCT_TLVLEN(0)); 4549 buf += WMI_TLV_HDR_SIZE; 4550 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 4551 WMITLV_GET_STRUCT_TLVLEN(0)); 4552 buf += WMI_TLV_HDR_SIZE; 4553 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 4554 WMITLV_GET_STRUCT_TLVLEN(0)); 4555 buf += WMI_TLV_HDR_SIZE; 4556 4557 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 4558 WMITLV_GET_STRUCT_TLVLEN(0)); 4559 buf += WMI_TLV_HDR_SIZE; 4560 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 4561 WMITLV_GET_STRUCT_TLVLEN(0)); 4562 buf += WMI_TLV_HDR_SIZE; 4563 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_BYTE, 4564 WMITLV_GET_STRUCT_TLVLEN(0)); 4565 4566 return QDF_STATUS_SUCCESS; 4567 } 4568 4569 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 4570 sizeof(wmi_roam_offload_tlv_param)); 4571 4572 buf += WMI_TLV_HDR_SIZE; 4573 roam_offload_params = (wmi_roam_offload_tlv_param *)buf; 4574 WMITLV_SET_HDR(buf, 4575 WMITLV_TAG_STRUC_wmi_roam_offload_tlv_param, 4576 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_offload_tlv_param)); 4577 4578 roam_offload_params->prefer_5g = src_lfr3_params->prefer_5ghz; 4579 roam_offload_params->rssi_cat_gap = src_lfr3_params->roam_rssi_cat_gap; 4580 roam_offload_params->select_5g_margin = 4581 src_lfr3_params->select_5ghz_margin; 4582 roam_offload_params->handoff_delay_for_rx = 4583 src_lfr3_params->ho_delay_for_rx; 4584 roam_offload_params->max_mlme_sw_retries = 4585 src_lfr3_params->roam_retry_count; 4586 roam_offload_params->no_ack_timeout = 4587 src_lfr3_params->roam_preauth_no_ack_timeout; 4588 roam_offload_params->reassoc_failure_timeout = 4589 src_lfr3_params->reassoc_failure_timeout; 4590 roam_offload_params->roam_candidate_validity_time = 4591 src_lfr3_params->rct_validity_timer; 4592 roam_offload_params->roam_to_current_bss_disable = 4593 src_lfr3_params->disable_self_roam; 4594 wmi_debug("RSO_CFG: prefer_5g:%d rssi_cat_gap:%d select_5g_margin:%d ho_delay:%d max_sw_retry:%d no_ack_timeout:%d", 4595 roam_offload_params->prefer_5g, 4596 roam_offload_params->rssi_cat_gap, 4597 roam_offload_params->select_5g_margin, 4598 roam_offload_params->handoff_delay_for_rx, 4599 roam_offload_params->max_mlme_sw_retries, 4600 roam_offload_params->no_ack_timeout); 4601 wmi_debug("RSO_CFG: reassoc_fail_timeout:%d rct_validity_time:%d disable_self_roam:%d", 4602 roam_offload_params->reassoc_failure_timeout, 4603 roam_offload_params->roam_candidate_validity_time, 4604 roam_offload_params->roam_to_current_bss_disable); 4605 4606 /* Fill the capabilities */ 4607 roam_offload_params->capability = src_lfr3_caps->capability; 4608 roam_offload_params->ht_caps_info = src_lfr3_caps->ht_caps_info; 4609 roam_offload_params->ampdu_param = src_lfr3_caps->ampdu_param; 4610 roam_offload_params->ht_ext_cap = src_lfr3_caps->ht_ext_cap; 4611 roam_offload_params->ht_txbf = src_lfr3_caps->ht_txbf; 4612 roam_offload_params->asel_cap = src_lfr3_caps->asel_cap; 4613 roam_offload_params->qos_caps = src_lfr3_caps->qos_caps; 4614 roam_offload_params->qos_enabled = src_lfr3_caps->qos_enabled; 4615 roam_offload_params->wmm_caps = src_lfr3_caps->wmm_caps; 4616 qdf_mem_copy((uint8_t *)roam_offload_params->mcsset, 4617 (uint8_t *)src_lfr3_caps->mcsset, 4618 ROAM_OFFLOAD_NUM_MCS_SET); 4619 wmi_debug("RSO_CFG: capability:0x%x ht_caps:0x%x ampdu_param:0%x ht_ext_cap:0x%x ht_txbf:0x%x asel_cap:0x%x qos_caps:0x%x qos_en:%d wmm_caps:0x%x", 4620 roam_offload_params->capability, 4621 roam_offload_params->ht_caps_info, 4622 roam_offload_params->ampdu_param, 4623 roam_offload_params->ht_ext_cap, 4624 roam_offload_params->ht_txbf, roam_offload_params->asel_cap, 4625 roam_offload_params->qos_caps, 4626 roam_offload_params->qos_enabled, 4627 roam_offload_params->wmm_caps); 4628 4629 buf += sizeof(wmi_roam_offload_tlv_param); 4630 /* 4631 * The TLV's are in the order of 11i, 11R, ESE. Hence, 4632 * they are filled in the same order.Depending on the 4633 * authentication type, the other mode TLV's are nullified 4634 * and only headers are filled. 4635 */ 4636 if ((akm != WMI_AUTH_OPEN || roam_req->rso_ese_info.is_ese_assoc || 4637 wmi_is_ft_akm(akm, roam_req)) && akm != WMI_AUTH_NONE) { 4638 if (roam_req->rso_ese_info.is_ese_assoc) { 4639 /* Fill the length of 11i, 11r TLV as 0 */ 4640 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0); 4641 buf += WMI_TLV_HDR_SIZE; 4642 4643 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0); 4644 buf += WMI_TLV_HDR_SIZE; 4645 4646 /* Start filling the ESE TLV */ 4647 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 4648 sizeof(wmi_roam_ese_offload_tlv_param)); 4649 buf += WMI_TLV_HDR_SIZE; 4650 roam_offload_ese = 4651 (wmi_roam_ese_offload_tlv_param *)buf; 4652 qdf_mem_copy(roam_offload_ese->krk, src_ese_info->krk, 4653 sizeof(src_ese_info->krk)); 4654 qdf_mem_copy(roam_offload_ese->btk, src_ese_info->btk, 4655 sizeof(src_ese_info->btk)); 4656 4657 WMITLV_SET_HDR(&roam_offload_ese->tlv_header, 4658 WMITLV_TAG_STRUC_wmi_roam_ese_offload_tlv_param, 4659 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_ese_offload_tlv_param)); 4660 4661 buf += sizeof(wmi_roam_ese_offload_tlv_param); 4662 } else if (wmi_is_ft_akm(akm, roam_req)) { 4663 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0); 4664 buf += WMI_TLV_HDR_SIZE; 4665 4666 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 4667 sizeof(wmi_roam_11r_offload_tlv_param)); 4668 buf += WMI_TLV_HDR_SIZE; 4669 4670 roam_offload_11r = 4671 (wmi_roam_11r_offload_tlv_param *)buf; 4672 4673 roam_offload_11r->r0kh_id_len = 4674 src_11r_info->r0kh_id_length; 4675 qdf_mem_copy(roam_offload_11r->r0kh_id, 4676 src_11r_info->r0kh_id, 4677 src_11r_info->r0kh_id_length); 4678 4679 wmi_fill_roam_offload_11r_params(akm, roam_offload_11r, 4680 roam_req); 4681 4682 roam_offload_11r->mdie_present = 4683 src_11r_info->mdid.mdie_present; 4684 roam_offload_11r->mdid = 4685 src_11r_info->mdid.mobility_domain; 4686 roam_offload_11r->adaptive_11r = 4687 src_11r_info->is_adaptive_11r; 4688 roam_offload_11r->ft_im_for_deauth = 4689 src_11r_info->enable_ft_im_roaming; 4690 roam_offload_11r->ft_over_ds_enable = 4691 src_11r_info->enable_ft_over_ds; 4692 4693 if (akm == WMI_AUTH_OPEN) { 4694 /* 4695 * If FT-Open ensure pmk length 4696 * and r0khid len are zero 4697 */ 4698 roam_offload_11r->r0kh_id_len = 0; 4699 roam_offload_11r->psk_msk_len = 0; 4700 } 4701 4702 WMITLV_SET_HDR(&roam_offload_11r->tlv_header, 4703 WMITLV_TAG_STRUC_wmi_roam_11r_offload_tlv_param, 4704 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_11r_offload_tlv_param)); 4705 4706 buf += sizeof(wmi_roam_11r_offload_tlv_param); 4707 /* Set ESE TLV len to 0*/ 4708 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0); 4709 buf += WMI_TLV_HDR_SIZE; 4710 4711 wmi_debug("RSO_CFG: vdev[%d] 11r TLV psk_msk_len = %d psk_msk_ext:%d md:0x%x", 4712 roam_req->vdev_id, 4713 roam_offload_11r->psk_msk_len, 4714 roam_offload_11r->psk_msk_ext_len, 4715 roam_offload_11r->mdid); 4716 if (roam_offload_11r->psk_msk_len) 4717 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, 4718 QDF_TRACE_LEVEL_DEBUG, 4719 roam_offload_11r->psk_msk, 4720 WLAN_MAX_PMK_DUMP_BYTES); 4721 } else { 4722 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 4723 sizeof(wmi_roam_11i_offload_tlv_param)); 4724 buf += WMI_TLV_HDR_SIZE; 4725 4726 roam_offload_11i = 4727 (wmi_roam_11i_offload_tlv_param *)buf; 4728 4729 if (src_11i_info->roam_key_mgmt_offload_enabled && 4730 src_11i_info->fw_okc) 4731 WMI_SET_ROAM_OFFLOAD_OKC_ENABLED( 4732 roam_offload_11i->flags); 4733 else 4734 WMI_SET_ROAM_OFFLOAD_OKC_DISABLED( 4735 roam_offload_11i->flags); 4736 4737 if (src_11i_info->roam_key_mgmt_offload_enabled && 4738 src_11i_info->fw_pmksa_cache) 4739 WMI_SET_ROAM_OFFLOAD_PMK_CACHE_ENABLED( 4740 roam_offload_11i->flags); 4741 else 4742 WMI_SET_ROAM_OFFLOAD_PMK_CACHE_DISABLED( 4743 roam_offload_11i->flags); 4744 4745 wmi_fill_sae_single_pmk_param(src_11i_info, 4746 roam_offload_11i); 4747 4748 roam_offload_11i->pmk_len = 4749 src_11i_info->pmk_len > ROAM_OFFLOAD_PMK_BYTES ? 4750 ROAM_OFFLOAD_PMK_BYTES : src_11i_info->pmk_len; 4751 qdf_mem_copy(roam_offload_11i->pmk, 4752 src_11i_info->psk_pmk, 4753 roam_offload_11i->pmk_len); 4754 4755 roam_offload_11i->pmk_ext_len = 0; 4756 if (src_11i_info->pmk_len > ROAM_OFFLOAD_PMK_BYTES) { 4757 roam_offload_11i->pmk_ext_len = 4758 QDF_MIN(src_11i_info->pmk_len - 4759 ROAM_OFFLOAD_PMK_BYTES, 4760 ROAM_OFFLOAD_PMK_BYTES); 4761 } 4762 qdf_mem_copy( 4763 roam_offload_11i->pmk_ext, 4764 &src_11i_info->psk_pmk[ROAM_OFFLOAD_PMK_BYTES], 4765 roam_offload_11i->pmk_ext_len); 4766 4767 WMITLV_SET_HDR(&roam_offload_11i->tlv_header, 4768 WMITLV_TAG_STRUC_wmi_roam_11i_offload_tlv_param, 4769 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_11i_offload_tlv_param)); 4770 4771 buf += sizeof(wmi_roam_11i_offload_tlv_param); 4772 4773 /* 4774 * Set 11r TLV len to 0, since security profile is not 4775 * FT 4776 */ 4777 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0); 4778 buf += WMI_TLV_HDR_SIZE; 4779 4780 /* 4781 * Set ESE TLV len to 0 since security profile is not 4782 * ESE 4783 */ 4784 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0); 4785 buf += WMI_TLV_HDR_SIZE; 4786 4787 wmi_info("RSO_CFG: vdev:%d pmk_len = %d pmksa caching:%d OKC:%d sae_same_pmk:%d key_mgmt_offload:%d", 4788 roam_req->vdev_id, roam_offload_11i->pmk_len, 4789 src_11i_info->fw_pmksa_cache, 4790 src_11i_info->fw_okc, 4791 src_11i_info->is_sae_same_pmk, 4792 src_11i_info->roam_key_mgmt_offload_enabled); 4793 if (roam_offload_11i->pmk_len) 4794 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, 4795 QDF_TRACE_LEVEL_DEBUG, 4796 roam_offload_11i->pmk, 4797 WLAN_MAX_PMK_DUMP_BYTES); 4798 if (roam_offload_11i->pmk_ext_len) 4799 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, 4800 QDF_TRACE_LEVEL_DEBUG, 4801 roam_offload_11i->pmk_ext, 4802 WLAN_MAX_PMK_DUMP_BYTES); 4803 } 4804 } else { 4805 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0); 4806 buf += WMI_TLV_HDR_SIZE; 4807 4808 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0); 4809 buf += WMI_TLV_HDR_SIZE; 4810 4811 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, 0); 4812 buf += WMI_TLV_HDR_SIZE; 4813 } 4814 4815 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_STRUC, sizeof(*assoc_ies)); 4816 buf += WMI_TLV_HDR_SIZE; 4817 4818 assoc_ies = (wmi_tlv_buf_len_param *)buf; 4819 WMITLV_SET_HDR(&assoc_ies->tlv_header, 4820 WMITLV_TAG_STRUC_wmi_tlv_buf_len_param, 4821 WMITLV_GET_STRUCT_TLVLEN(wmi_tlv_buf_len_param)); 4822 assoc_ies->buf_len = roam_req->assoc_ie_length; 4823 4824 buf += sizeof(*assoc_ies); 4825 4826 WMITLV_SET_HDR(buf, WMITLV_TAG_ARRAY_BYTE, 4827 roundup(assoc_ies->buf_len, sizeof(uint32_t))); 4828 buf += WMI_TLV_HDR_SIZE; 4829 4830 wmi_debug("RSO_CFG: akm:%d assoc_ies len:%d", akm, assoc_ies->buf_len); 4831 if (assoc_ies->buf_len) 4832 qdf_mem_copy(buf, roam_req->assoc_ie, assoc_ies->buf_len); 4833 4834 buf += qdf_roundup(assoc_ies->buf_len, sizeof(uint32_t)); 4835 buf = wmi_add_fils_tlv(wmi_handle, roam_req, buf, fils_tlv_len); 4836 4837 buf = wmi_fill_sae_single_pmk_tlv(roam_req, buf); 4838 4839 return QDF_STATUS_SUCCESS; 4840 } 4841 #else 4842 static inline 4843 uint32_t wmi_get_rso_buf_len(struct wlan_roam_scan_offload_params *roam_req) 4844 { 4845 return 0; 4846 } 4847 4848 static inline QDF_STATUS 4849 wmi_fill_rso_tlvs(wmi_unified_t wmi_handle, uint8_t *buf_ptr, 4850 struct wlan_roam_scan_offload_params *roam_req) 4851 { 4852 return QDF_STATUS_SUCCESS; 4853 } 4854 #endif 4855 4856 static QDF_STATUS 4857 wmi_fill_rso_start_scan_tlv(struct wlan_roam_scan_offload_params *rso_req, 4858 wmi_start_scan_cmd_fixed_param *scan_tlv) 4859 { 4860 struct wlan_roam_scan_params *src_scan_params; 4861 4862 src_scan_params = &rso_req->rso_scan_params; 4863 scan_tlv->scan_ctrl_flags = WMI_SCAN_ADD_CCK_RATES | 4864 WMI_SCAN_ADD_OFDM_RATES | 4865 WMI_SCAN_ADD_DS_IE_IN_PROBE_REQ | 4866 WMI_SCAN_FILTER_PROBE_REQ; 4867 if (rso_req->is_rso_stop) { 4868 scan_tlv->dwell_time_active = 4869 ROAM_SCAN_DWELL_TIME_ACTIVE_DEFAULT; 4870 scan_tlv->dwell_time_passive = 4871 ROAM_SCAN_DWELL_TIME_PASSIVE_DEFAULT; 4872 scan_tlv->min_rest_time = ROAM_SCAN_MIN_REST_TIME_DEFAULT; 4873 scan_tlv->max_rest_time = ROAM_SCAN_MAX_REST_TIME_DEFAULT; 4874 scan_tlv->repeat_probe_time = 0; 4875 scan_tlv->probe_spacing_time = 0; 4876 scan_tlv->probe_delay = 0; 4877 scan_tlv->max_scan_time = ROAM_SCAN_HW_DEF_SCAN_MAX_DURATION; 4878 scan_tlv->idle_time = src_scan_params->min_rest_time; 4879 scan_tlv->burst_duration = 0; 4880 4881 return QDF_STATUS_SUCCESS; 4882 } 4883 4884 scan_tlv->dwell_time_active = src_scan_params->dwell_time_active; 4885 scan_tlv->dwell_time_passive = src_scan_params->dwell_time_passive; 4886 scan_tlv->min_dwell_time_6ghz = src_scan_params->min_dwell_time_6ghz; 4887 scan_tlv->burst_duration = src_scan_params->burst_duration; 4888 scan_tlv->min_rest_time = src_scan_params->min_rest_time; 4889 scan_tlv->max_rest_time = src_scan_params->max_rest_time; 4890 scan_tlv->repeat_probe_time = src_scan_params->repeat_probe_time; 4891 scan_tlv->probe_spacing_time = src_scan_params->probe_spacing_time; 4892 scan_tlv->probe_delay = src_scan_params->probe_delay; 4893 scan_tlv->max_scan_time = ROAM_SCAN_HW_DEF_SCAN_MAX_DURATION; 4894 scan_tlv->idle_time = src_scan_params->idle_time; 4895 scan_tlv->n_probes = src_scan_params->n_probes; 4896 scan_tlv->scan_ctrl_flags |= src_scan_params->scan_ctrl_flags; 4897 scan_tlv->dwell_time_active_6ghz = 4898 src_scan_params->dwell_time_active_6ghz; 4899 scan_tlv->dwell_time_passive_6ghz = 4900 src_scan_params->dwell_time_passive_6ghz; 4901 4902 WMI_SCAN_SET_DWELL_MODE(scan_tlv->scan_ctrl_flags, 4903 src_scan_params->rso_adaptive_dwell_mode); 4904 4905 /* Configure roaming scan behavior (DBS/Non-DBS scan) */ 4906 if (rso_req->roaming_scan_policy) 4907 scan_tlv->scan_ctrl_flags_ext |= 4908 WMI_SCAN_DBS_POLICY_FORCE_NONDBS; 4909 else 4910 scan_tlv->scan_ctrl_flags_ext |= 4911 WMI_SCAN_DBS_POLICY_DEFAULT; 4912 4913 wmi_debug("RSO_CFG: dwell time: active %d passive %d, burst_duration:%d, active 6g %d passive 6g %d, min_rest_time %d max rest %d repeat probe time %d probe_spacing:%d", 4914 scan_tlv->dwell_time_active, scan_tlv->dwell_time_passive, 4915 scan_tlv->burst_duration, 4916 scan_tlv->dwell_time_active_6ghz, 4917 scan_tlv->dwell_time_passive_6ghz, 4918 scan_tlv->min_rest_time, scan_tlv->max_rest_time, 4919 scan_tlv->repeat_probe_time, scan_tlv->probe_spacing_time); 4920 wmi_debug("RSO_CFG: ctrl_flags:0x%x probe_delay:%d max_scan_time:%d idle_time:%d n_probes:%d", 4921 scan_tlv->scan_ctrl_flags_ext, scan_tlv->probe_delay, 4922 scan_tlv->max_scan_time, scan_tlv->idle_time, 4923 scan_tlv->n_probes); 4924 4925 return QDF_STATUS_SUCCESS; 4926 } 4927 4928 #ifdef WLAN_FEATURE_11BE_MLO 4929 static void 4930 wmi_set_rso_stop_report_status(wmi_roam_scan_mode_fixed_param *rso_fp) 4931 { 4932 /** 4933 * Set the REPORT status flag always, so that firmware sends RSO stop 4934 * status always 4935 */ 4936 rso_fp->flags |= WMI_ROAM_SCAN_MODE_FLAG_REPORT_STATUS; 4937 } 4938 #else 4939 static void 4940 wmi_set_rso_stop_report_status(wmi_roam_scan_mode_fixed_param *rso_fp) 4941 { 4942 } 4943 #endif 4944 4945 /** 4946 * send_roam_scan_offload_mode_cmd_tlv() - send roam scan mode request to fw 4947 * @wmi_handle: wmi handle 4948 * @rso_req: roam request param 4949 * 4950 * send WMI_ROAM_SCAN_MODE TLV to firmware. It has a piggyback 4951 * of WMI_ROAM_SCAN_MODE. 4952 * 4953 * Return: QDF status 4954 */ 4955 static QDF_STATUS 4956 send_roam_scan_offload_mode_cmd_tlv( 4957 wmi_unified_t wmi_handle, 4958 struct wlan_roam_scan_offload_params *rso_req) 4959 { 4960 wmi_buf_t buf = NULL; 4961 QDF_STATUS status; 4962 size_t len; 4963 uint8_t *buf_ptr; 4964 wmi_roam_scan_mode_fixed_param *roam_scan_mode_fp; 4965 wmi_start_scan_cmd_fixed_param *scan_cmd_fp; 4966 struct wlan_roam_scan_mode_params *src_rso_mode_info = NULL; 4967 4968 /* 4969 * Need to create a buf with roam_scan command at 4970 * front and piggyback with scan command 4971 */ 4972 len = sizeof(wmi_roam_scan_mode_fixed_param) + 4973 sizeof(wmi_start_scan_cmd_fixed_param); 4974 len += wmi_get_rso_buf_len(rso_req); 4975 4976 if (rso_req->rso_mode_info.roam_scan_mode == 4977 (WMI_ROAM_SCAN_MODE_NONE | WMI_ROAM_SCAN_MODE_ROAMOFFLOAD)) 4978 len = sizeof(wmi_roam_scan_mode_fixed_param); 4979 4980 buf = wmi_buf_alloc(wmi_handle, len); 4981 if (!buf) 4982 return QDF_STATUS_E_NOMEM; 4983 4984 buf_ptr = (uint8_t *)wmi_buf_data(buf); 4985 4986 src_rso_mode_info = &rso_req->rso_mode_info; 4987 roam_scan_mode_fp = (wmi_roam_scan_mode_fixed_param *)buf_ptr; 4988 WMITLV_SET_HDR( 4989 &roam_scan_mode_fp->tlv_header, 4990 WMITLV_TAG_STRUC_wmi_roam_scan_mode_fixed_param, 4991 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_scan_mode_fixed_param)); 4992 4993 roam_scan_mode_fp->min_delay_roam_trigger_reason_bitmask = 4994 src_rso_mode_info->min_delay_roam_trigger_bitmask; 4995 roam_scan_mode_fp->min_delay_btw_scans = 4996 WMI_SEC_TO_MSEC(src_rso_mode_info->min_delay_btw_scans); 4997 roam_scan_mode_fp->roam_scan_mode = src_rso_mode_info->roam_scan_mode; 4998 roam_scan_mode_fp->vdev_id = rso_req->vdev_id; 4999 wmi_debug("RSO_CFG: vdev_id:%d roam scan mode:0x%x min_delay_bitmap:0x%x min_delay_btw_scans:%d", 5000 rso_req->vdev_id, 5001 roam_scan_mode_fp->roam_scan_mode, 5002 roam_scan_mode_fp->min_delay_roam_trigger_reason_bitmask, 5003 roam_scan_mode_fp->min_delay_btw_scans); 5004 /* 5005 * For supplicant disabled roaming, all other roam triggers are disabled 5006 * so send only roam scan mode Fixed param in the command 5007 */ 5008 if (src_rso_mode_info->roam_scan_mode == 5009 (WMI_ROAM_SCAN_MODE_NONE | WMI_ROAM_SCAN_MODE_ROAMOFFLOAD)) { 5010 roam_scan_mode_fp->flags |= 5011 WMI_ROAM_SCAN_MODE_FLAG_REPORT_STATUS; 5012 goto send_roam_scan_mode_cmd; 5013 } else { 5014 wmi_set_rso_stop_report_status(roam_scan_mode_fp); 5015 } 5016 5017 /* Fill in scan parameters suitable for roaming scan */ 5018 buf_ptr += sizeof(wmi_roam_scan_mode_fixed_param); 5019 WMITLV_SET_HDR( 5020 buf_ptr, 5021 WMITLV_TAG_STRUC_wmi_start_scan_cmd_fixed_param, 5022 WMITLV_GET_STRUCT_TLVLEN(wmi_start_scan_cmd_fixed_param)); 5023 scan_cmd_fp = (wmi_start_scan_cmd_fixed_param *)buf_ptr; 5024 wmi_fill_rso_start_scan_tlv(rso_req, scan_cmd_fp); 5025 5026 /* Ensure there is no additional IEs */ 5027 scan_cmd_fp->ie_len = 0; 5028 buf_ptr += sizeof(wmi_start_scan_cmd_fixed_param); 5029 5030 status = wmi_fill_rso_tlvs(wmi_handle, buf_ptr, rso_req); 5031 if (QDF_IS_STATUS_ERROR(status)) { 5032 wmi_buf_free(buf); 5033 return status; 5034 } 5035 5036 send_roam_scan_mode_cmd: 5037 wmi_mtrace(WMI_ROAM_SCAN_MODE, rso_req->vdev_id, 0); 5038 status = wmi_unified_cmd_send(wmi_handle, buf, 5039 len, WMI_ROAM_SCAN_MODE); 5040 if (QDF_IS_STATUS_ERROR(status)) 5041 wmi_buf_free(buf); 5042 5043 return status; 5044 } 5045 5046 #ifdef WLAN_FEATURE_11BE_MLO 5047 static void 5048 send_update_mlo_roam_params(wmi_roam_cnd_scoring_param *score_param, 5049 struct ap_profile_params *ap_profile) 5050 { 5051 score_param->eht_weightage_pcnt = 5052 ap_profile->param.eht_caps_weightage; 5053 score_param->mlo_weightage_pcnt = 5054 ap_profile->param.mlo_weightage; 5055 wmi_debug("11be score params weightage: EHT %d MLO %d", 5056 score_param->eht_weightage_pcnt, 5057 score_param->mlo_weightage_pcnt); 5058 } 5059 5060 static uint32_t convert_support_link_band_to_wmi(uint32_t bands) 5061 { 5062 uint32_t target_bands = 0; 5063 5064 if (bands & BIT(REG_BAND_2G)) 5065 target_bands |= BIT(0); 5066 if (bands & BIT(REG_BAND_5G)) 5067 target_bands |= BIT(1); 5068 if (bands & BIT(REG_BAND_6G)) 5069 target_bands |= BIT(2); 5070 5071 return target_bands; 5072 } 5073 5074 /** 5075 * send_roam_mlo_config_tlv() - send roam mlo config parameters 5076 * @wmi_handle: wmi handle 5077 * @req: pointer to wlan roam mlo config parameters 5078 * 5079 * This function sends the roam mlo config parameters to fw. 5080 * 5081 * Return: QDF status 5082 */ 5083 static QDF_STATUS 5084 send_roam_mlo_config_tlv(wmi_unified_t wmi_handle, 5085 struct wlan_roam_mlo_config *req) 5086 { 5087 wmi_roam_mlo_config_cmd_fixed_param *cmd; 5088 wmi_buf_t buf; 5089 uint32_t len; 5090 5091 len = sizeof(*cmd); 5092 buf = wmi_buf_alloc(wmi_handle, len); 5093 if (!buf) 5094 return QDF_STATUS_E_NOMEM; 5095 5096 cmd = (wmi_roam_mlo_config_cmd_fixed_param *)wmi_buf_data(buf); 5097 WMITLV_SET_HDR( 5098 &cmd->tlv_header, 5099 WMITLV_TAG_STRUC_wmi_roam_mlo_config_cmd_fixed_param, 5100 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_mlo_config_cmd_fixed_param)); 5101 5102 cmd->vdev_id = req->vdev_id; 5103 cmd->support_link_num = req->support_link_num; 5104 cmd->support_link_band = convert_support_link_band_to_wmi( 5105 req->support_link_band); 5106 if (!req->mlo_5gl_5gh_mlsr) 5107 cmd->disallow_connect_modes |= WMI_ROAM_MLO_CONNECTION_MODE_5GL_5GH_MLSR; 5108 5109 WMI_CHAR_ARRAY_TO_MAC_ADDR(req->partner_link_addr.bytes, 5110 &cmd->partner_link_addr); 5111 5112 wmi_debug("RSO_CFG MLO: vdev_id:%d support_link_num:%d support_link_band:0x%0x disallow_connect_mode %d link addr:"QDF_MAC_ADDR_FMT, 5113 cmd->vdev_id, cmd->support_link_num, 5114 cmd->support_link_band, 5115 cmd->disallow_connect_modes, 5116 QDF_MAC_ADDR_REF(req->partner_link_addr.bytes)); 5117 5118 wmi_mtrace(WMI_ROAM_MLO_CONFIG_CMDID, cmd->vdev_id, 0); 5119 if (wmi_unified_cmd_send(wmi_handle, buf, len, 5120 WMI_ROAM_MLO_CONFIG_CMDID)) { 5121 wmi_err("Failed to send WMI_ROAM_MLO_CONFIG_CMDID"); 5122 wmi_buf_free(buf); 5123 return QDF_STATUS_E_FAILURE; 5124 } 5125 5126 return QDF_STATUS_SUCCESS; 5127 } 5128 5129 static void wmi_roam_mlo_attach_tlv(struct wmi_unified *wmi_handle) 5130 { 5131 struct wmi_ops *ops = wmi_handle->ops; 5132 5133 ops->send_roam_mlo_config = send_roam_mlo_config_tlv; 5134 } 5135 5136 #else 5137 static void 5138 send_update_mlo_roam_params(wmi_roam_cnd_scoring_param *score_param, 5139 struct ap_profile_params *ap_profile) 5140 { 5141 } 5142 5143 static void wmi_roam_mlo_attach_tlv(struct wmi_unified *wmi_handle) 5144 { 5145 } 5146 #endif 5147 5148 #ifdef WLAN_FEATURE_11BE_MLO 5149 /** 5150 * update_mlo_prefer_percentage() - Update mlo preference with configured value 5151 * @psoc: psoc object 5152 * @mlo_prefer_percentage: pointer to hold mlo preference percentage 5153 * 5154 * Return: None 5155 */ 5156 static void update_mlo_prefer_percentage(struct wlan_objmgr_psoc *psoc, 5157 int8_t *mlo_prefer_percentage) 5158 { 5159 wlan_mlme_get_mlo_prefer_percentage(psoc, mlo_prefer_percentage); 5160 /* host will deliver actual weighted number based on 100. 5161 * For example: 5162 * If percentage value in INI is 20, then host will give 120 (100 + 20) 5163 * i.e (100 * 1.2) as mlo_etp_weightage_pcnt. 5164 * If percentage value in INI is -20, then host will give 80 (100 - 20) 5165 * i.e (100 * 0.8) as mlo_etp_weightage_pcnt. 5166 */ 5167 *mlo_prefer_percentage += 100; 5168 } 5169 #else 5170 static inline 5171 void update_mlo_prefer_percentage(struct wlan_objmgr_psoc *psoc, 5172 int8_t *mlo_preference_pctn) 5173 {} 5174 #endif 5175 5176 /** 5177 * send_roam_scan_offload_ap_profile_cmd_tlv() - set roam ap profile in fw 5178 * @wmi_handle: wmi handle 5179 * @ap_profile: ap profile 5180 * 5181 * Send WMI_ROAM_AP_PROFILE to firmware 5182 * 5183 * Return: CDF status 5184 */ 5185 static QDF_STATUS 5186 send_roam_scan_offload_ap_profile_cmd_tlv(wmi_unified_t wmi_handle, 5187 struct ap_profile_params *ap_profile) 5188 { 5189 wmi_buf_t buf = NULL; 5190 QDF_STATUS status; 5191 size_t len; 5192 uint8_t *buf_ptr; 5193 wmi_roam_ap_profile_fixed_param *roam_ap_profile_fp; 5194 wmi_roam_cnd_scoring_param *score_param; 5195 wmi_ap_profile *profile; 5196 wmi_roam_score_delta_param *score_delta_param; 5197 wmi_roam_cnd_min_rssi_param *min_rssi_param; 5198 wmi_owe_ap_profile *owe_ap_profile; 5199 enum roam_trigger_reason trig_reason; 5200 uint32_t *authmode_list; 5201 int8_t mlo_prefer_percentage = 0; 5202 wmi_ssid *ssid; 5203 int i; 5204 5205 len = sizeof(wmi_roam_ap_profile_fixed_param) + sizeof(wmi_ap_profile); 5206 len += sizeof(*score_param) + WMI_TLV_HDR_SIZE; 5207 5208 if (!wmi_service_enabled(wmi_handle, 5209 wmi_service_configure_roam_trigger_param_support)) { 5210 len += WMI_TLV_HDR_SIZE; 5211 len += NUM_OF_ROAM_TRIGGERS * sizeof(*score_delta_param); 5212 len += WMI_TLV_HDR_SIZE; 5213 len += NUM_OF_ROAM_MIN_RSSI * sizeof(*min_rssi_param); 5214 } else { 5215 len += 2 * WMI_TLV_HDR_SIZE; 5216 } 5217 5218 if (ap_profile->owe_ap_profile.is_owe_transition_conn) { 5219 len += WMI_TLV_HDR_SIZE; 5220 len += sizeof(*owe_ap_profile); 5221 } else { 5222 len += WMI_TLV_HDR_SIZE; 5223 } 5224 5225 if (ap_profile->profile.num_allowed_authmode) { 5226 len += WMI_TLV_HDR_SIZE; 5227 len += ap_profile->profile.num_allowed_authmode * 5228 sizeof(uint32_t); 5229 } else { 5230 len += WMI_TLV_HDR_SIZE; 5231 } 5232 5233 buf = wmi_buf_alloc(wmi_handle, len); 5234 if (!buf) 5235 return QDF_STATUS_E_NOMEM; 5236 5237 buf_ptr = (uint8_t *)wmi_buf_data(buf); 5238 roam_ap_profile_fp = (wmi_roam_ap_profile_fixed_param *)buf_ptr; 5239 WMITLV_SET_HDR(&roam_ap_profile_fp->tlv_header, 5240 WMITLV_TAG_STRUC_wmi_roam_ap_profile_fixed_param, 5241 WMITLV_GET_STRUCT_TLVLEN 5242 (wmi_roam_ap_profile_fixed_param)); 5243 /* fill in threshold values */ 5244 roam_ap_profile_fp->vdev_id = ap_profile->vdev_id; 5245 roam_ap_profile_fp->id = 0; 5246 buf_ptr += sizeof(wmi_roam_ap_profile_fixed_param); 5247 5248 profile = (wmi_ap_profile *)buf_ptr; 5249 WMITLV_SET_HDR(&profile->tlv_header, 5250 WMITLV_TAG_STRUC_wmi_ap_profile, 5251 WMITLV_GET_STRUCT_TLVLEN(wmi_ap_profile)); 5252 profile->flags = ap_profile->profile.flags; 5253 profile->rssi_threshold = ap_profile->profile.rssi_threshold; 5254 profile->bg_rssi_threshold = ap_profile->profile.bg_rssi_threshold; 5255 profile->ssid.ssid_len = ap_profile->profile.ssid.length; 5256 qdf_mem_copy(profile->ssid.ssid, ap_profile->profile.ssid.ssid, 5257 profile->ssid.ssid_len); 5258 profile->rsn_authmode = ap_profile->profile.rsn_authmode; 5259 profile->rsn_ucastcipherset = ap_profile->profile.rsn_ucastcipherset; 5260 profile->rsn_mcastcipherset = ap_profile->profile.rsn_mcastcipherset; 5261 profile->rsn_mcastmgmtcipherset = 5262 ap_profile->profile.rsn_mcastmgmtcipherset; 5263 profile->rssi_abs_thresh = ap_profile->profile.rssi_abs_thresh; 5264 5265 wmi_debug("vdev %d AP PROFILE: flags:%x rssi_thres:%d bg_rssi_thres:%d ssid:" QDF_SSID_FMT " authmode:%d uc cipher:%d mc cipher:%d mc mgmt cipher:%d rssi abs thresh:%d", 5266 roam_ap_profile_fp->vdev_id, 5267 profile->flags, profile->rssi_threshold, 5268 profile->bg_rssi_threshold, 5269 QDF_SSID_REF(profile->ssid.ssid_len, 5270 ap_profile->profile.ssid.ssid), 5271 profile->rsn_authmode, profile->rsn_ucastcipherset, 5272 profile->rsn_mcastcipherset, profile->rsn_mcastmgmtcipherset, 5273 profile->rssi_abs_thresh); 5274 5275 buf_ptr += sizeof(wmi_ap_profile); 5276 5277 score_param = (wmi_roam_cnd_scoring_param *)buf_ptr; 5278 WMITLV_SET_HDR(&score_param->tlv_header, 5279 WMITLV_TAG_STRUC_wmi_roam_cnd_scoring_param, 5280 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_cnd_scoring_param)); 5281 score_param->disable_bitmap = ap_profile->param.disable_bitmap; 5282 score_param->rssi_weightage_pcnt = 5283 ap_profile->param.rssi_weightage; 5284 score_param->ht_weightage_pcnt = ap_profile->param.ht_weightage; 5285 score_param->vht_weightage_pcnt = ap_profile->param.vht_weightage; 5286 score_param->he_weightage_pcnt = ap_profile->param.he_weightage; 5287 score_param->bw_weightage_pcnt = ap_profile->param.bw_weightage; 5288 score_param->band_weightage_pcnt = ap_profile->param.band_weightage; 5289 score_param->nss_weightage_pcnt = ap_profile->param.nss_weightage; 5290 score_param->security_weightage_pcnt = 5291 ap_profile->param.security_weightage; 5292 score_param->esp_qbss_weightage_pcnt = 5293 ap_profile->param.esp_qbss_weightage; 5294 score_param->beamforming_weightage_pcnt = 5295 ap_profile->param.beamforming_weightage; 5296 score_param->pcl_weightage_pcnt = ap_profile->param.pcl_weightage; 5297 score_param->oce_wan_weightage_pcnt = 5298 ap_profile->param.oce_wan_weightage; 5299 score_param->oce_ap_tx_pwr_weightage_pcnt = 5300 ap_profile->param.oce_ap_tx_pwr_weightage; 5301 score_param->oce_ap_subnet_id_weightage_pcnt = 5302 ap_profile->param.oce_subnet_id_weightage; 5303 score_param->vendor_roam_score_algorithm_id = 5304 ap_profile->param.vendor_roam_score_algorithm; 5305 score_param->sae_pk_ap_weightage_pcnt = 5306 ap_profile->param.sae_pk_ap_weightage; 5307 update_mlo_prefer_percentage(wmi_handle->soc->wmi_psoc, 5308 &mlo_prefer_percentage); 5309 score_param->mlo_etp_weightage_pcnt = mlo_prefer_percentage; 5310 send_update_mlo_roam_params(score_param, ap_profile); 5311 wmi_debug("Score params weightage: disable_bitmap %x rssi %d ht %d vht %d he %d BW %d band %d NSS %d ESP %d BF %d PCL %d OCE WAN %d APTX %d roam score algo %d subnet id %d sae-pk %d security %d mlo_etp_weight_pct %d", 5312 score_param->disable_bitmap, score_param->rssi_weightage_pcnt, 5313 score_param->ht_weightage_pcnt, 5314 score_param->vht_weightage_pcnt, 5315 score_param->he_weightage_pcnt, 5316 score_param->bw_weightage_pcnt, 5317 score_param->band_weightage_pcnt, 5318 score_param->nss_weightage_pcnt, 5319 score_param->esp_qbss_weightage_pcnt, 5320 score_param->beamforming_weightage_pcnt, 5321 score_param->pcl_weightage_pcnt, 5322 score_param->oce_wan_weightage_pcnt, 5323 score_param->oce_ap_tx_pwr_weightage_pcnt, 5324 score_param->vendor_roam_score_algorithm_id, 5325 score_param->oce_ap_subnet_id_weightage_pcnt, 5326 score_param->sae_pk_ap_weightage_pcnt, 5327 score_param->security_weightage_pcnt, 5328 score_param->mlo_etp_weightage_pcnt); 5329 5330 score_param->bw_scoring.score_pcnt = ap_profile->param.bw_index_score; 5331 score_param->band_scoring.score_pcnt = 5332 ap_profile->param.band_index_score; 5333 score_param->nss_scoring.score_pcnt = 5334 ap_profile->param.nss_index_score; 5335 score_param->security_scoring.score_pcnt = 5336 ap_profile->param.security_index_score; 5337 5338 wmi_debug("bw_index_score %x band_index_score %x nss_index_score %x security_index_score %x", 5339 score_param->bw_scoring.score_pcnt, 5340 score_param->band_scoring.score_pcnt, 5341 score_param->nss_scoring.score_pcnt, 5342 score_param->security_scoring.score_pcnt); 5343 5344 score_param->rssi_scoring.best_rssi_threshold = 5345 (-1) * ap_profile->param.rssi_scoring.best_rssi_threshold; 5346 score_param->rssi_scoring.good_rssi_threshold = 5347 (-1) * ap_profile->param.rssi_scoring.good_rssi_threshold; 5348 score_param->rssi_scoring.bad_rssi_threshold = 5349 (-1) * ap_profile->param.rssi_scoring.bad_rssi_threshold; 5350 score_param->rssi_scoring.good_rssi_pcnt = 5351 ap_profile->param.rssi_scoring.good_rssi_pcnt; 5352 score_param->rssi_scoring.bad_rssi_pcnt = 5353 ap_profile->param.rssi_scoring.bad_rssi_pcnt; 5354 score_param->rssi_scoring.good_bucket_size = 5355 ap_profile->param.rssi_scoring.good_rssi_bucket_size; 5356 score_param->rssi_scoring.bad_bucket_size = 5357 ap_profile->param.rssi_scoring.bad_rssi_bucket_size; 5358 score_param->rssi_scoring.rssi_pref_5g_rssi_thresh = 5359 (-1) * ap_profile->param.rssi_scoring.rssi_pref_5g_rssi_thresh; 5360 5361 wmi_debug("Rssi scoring threshold: best RSSI %d good RSSI %d bad RSSI %d prefer 5g threshold %d", 5362 score_param->rssi_scoring.best_rssi_threshold, 5363 score_param->rssi_scoring.good_rssi_threshold, 5364 score_param->rssi_scoring.bad_rssi_threshold, 5365 score_param->rssi_scoring.rssi_pref_5g_rssi_thresh); 5366 wmi_debug("Good RSSI score for each slot %d bad RSSI score for each slot %d good bucket %d bad bucket %d", 5367 score_param->rssi_scoring.good_rssi_pcnt, 5368 score_param->rssi_scoring.bad_rssi_pcnt, 5369 score_param->rssi_scoring.good_bucket_size, 5370 score_param->rssi_scoring.bad_bucket_size); 5371 5372 score_param->esp_qbss_scoring.num_slot = 5373 ap_profile->param.esp_qbss_scoring.num_slot; 5374 score_param->esp_qbss_scoring.score_pcnt3_to_0 = 5375 ap_profile->param.esp_qbss_scoring.score_pcnt3_to_0; 5376 score_param->esp_qbss_scoring.score_pcnt7_to_4 = 5377 ap_profile->param.esp_qbss_scoring.score_pcnt7_to_4; 5378 score_param->esp_qbss_scoring.score_pcnt11_to_8 = 5379 ap_profile->param.esp_qbss_scoring.score_pcnt11_to_8; 5380 score_param->esp_qbss_scoring.score_pcnt15_to_12 = 5381 ap_profile->param.esp_qbss_scoring.score_pcnt15_to_12; 5382 5383 wmi_debug("ESP QBSS index weight: slots %d weight 0to3 %x weight 4to7 %x weight 8to11 %x weight 12to15 %x", 5384 score_param->esp_qbss_scoring.num_slot, 5385 score_param->esp_qbss_scoring.score_pcnt3_to_0, 5386 score_param->esp_qbss_scoring.score_pcnt7_to_4, 5387 score_param->esp_qbss_scoring.score_pcnt11_to_8, 5388 score_param->esp_qbss_scoring.score_pcnt15_to_12); 5389 5390 score_param->oce_wan_scoring.num_slot = 5391 ap_profile->param.oce_wan_scoring.num_slot; 5392 score_param->oce_wan_scoring.score_pcnt3_to_0 = 5393 ap_profile->param.oce_wan_scoring.score_pcnt3_to_0; 5394 score_param->oce_wan_scoring.score_pcnt7_to_4 = 5395 ap_profile->param.oce_wan_scoring.score_pcnt7_to_4; 5396 score_param->oce_wan_scoring.score_pcnt11_to_8 = 5397 ap_profile->param.oce_wan_scoring.score_pcnt11_to_8; 5398 score_param->oce_wan_scoring.score_pcnt15_to_12 = 5399 ap_profile->param.oce_wan_scoring.score_pcnt15_to_12; 5400 5401 wmi_debug("OCE WAN index weight: slots %d weight 0to3 %x weight 4to7 %x weight 8to11 %x weight 12to15 %x", 5402 score_param->oce_wan_scoring.num_slot, 5403 score_param->oce_wan_scoring.score_pcnt3_to_0, 5404 score_param->oce_wan_scoring.score_pcnt7_to_4, 5405 score_param->oce_wan_scoring.score_pcnt11_to_8, 5406 score_param->oce_wan_scoring.score_pcnt15_to_12); 5407 5408 score_param->roam_score_delta_pcnt = ap_profile->param.roam_score_delta; 5409 score_param->roam_score_delta_mask = 5410 ap_profile->param.roam_trigger_bitmap; 5411 score_param->candidate_min_roam_score_delta = 5412 ap_profile->param.cand_min_roam_score_delta; 5413 wmi_debug("Roam score delta:%d Roam_trigger_bitmap:%x cand min score delta = %d", 5414 score_param->roam_score_delta_pcnt, 5415 score_param->roam_score_delta_mask, 5416 score_param->candidate_min_roam_score_delta); 5417 5418 buf_ptr += sizeof(*score_param); 5419 5420 if (!wmi_service_enabled(wmi_handle, 5421 wmi_service_configure_roam_trigger_param_support)) { 5422 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 5423 (NUM_OF_ROAM_TRIGGERS * sizeof(*score_delta_param))); 5424 buf_ptr += WMI_TLV_HDR_SIZE; 5425 5426 score_delta_param = (wmi_roam_score_delta_param *)buf_ptr; 5427 WMITLV_SET_HDR(&score_delta_param->tlv_header, 5428 WMITLV_TAG_STRUC_wmi_roam_score_delta_param, 5429 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_score_delta_param)); 5430 trig_reason = 5431 ap_profile->score_delta_param[IDLE_ROAM_TRIGGER].trigger_reason; 5432 score_delta_param->roam_trigger_reason = 5433 convert_roam_trigger_reason(trig_reason); 5434 score_delta_param->roam_score_delta = 5435 ap_profile->score_delta_param[IDLE_ROAM_TRIGGER].roam_score_delta; 5436 5437 buf_ptr += sizeof(*score_delta_param); 5438 score_delta_param = (wmi_roam_score_delta_param *)buf_ptr; 5439 WMITLV_SET_HDR(&score_delta_param->tlv_header, 5440 WMITLV_TAG_STRUC_wmi_roam_score_delta_param, 5441 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_score_delta_param)); 5442 trig_reason = 5443 ap_profile->score_delta_param[BTM_ROAM_TRIGGER].trigger_reason; 5444 score_delta_param->roam_trigger_reason = 5445 convert_roam_trigger_reason(trig_reason); 5446 score_delta_param->roam_score_delta = 5447 ap_profile->score_delta_param[BTM_ROAM_TRIGGER].roam_score_delta; 5448 5449 buf_ptr += sizeof(*score_delta_param); 5450 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 5451 (NUM_OF_ROAM_MIN_RSSI * sizeof(*min_rssi_param))); 5452 buf_ptr += WMI_TLV_HDR_SIZE; 5453 5454 min_rssi_param = (wmi_roam_cnd_min_rssi_param *)buf_ptr; 5455 WMITLV_SET_HDR(&min_rssi_param->tlv_header, 5456 WMITLV_TAG_STRUC_wmi_roam_cnd_min_rssi_param, 5457 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_cnd_min_rssi_param)); 5458 trig_reason = 5459 ap_profile->min_rssi_params[DEAUTH_MIN_RSSI].trigger_reason; 5460 min_rssi_param->roam_trigger_reason = 5461 convert_roam_trigger_reason(trig_reason); 5462 min_rssi_param->candidate_min_rssi = 5463 ap_profile->min_rssi_params[DEAUTH_MIN_RSSI].min_rssi; 5464 5465 buf_ptr += sizeof(*min_rssi_param); 5466 min_rssi_param = (wmi_roam_cnd_min_rssi_param *)buf_ptr; 5467 WMITLV_SET_HDR(&min_rssi_param->tlv_header, 5468 WMITLV_TAG_STRUC_wmi_roam_cnd_min_rssi_param, 5469 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_cnd_min_rssi_param)); 5470 trig_reason = 5471 ap_profile->min_rssi_params[BMISS_MIN_RSSI].trigger_reason; 5472 min_rssi_param->roam_trigger_reason = 5473 convert_roam_trigger_reason(trig_reason); 5474 min_rssi_param->candidate_min_rssi = 5475 ap_profile->min_rssi_params[BMISS_MIN_RSSI].min_rssi; 5476 5477 buf_ptr += sizeof(*min_rssi_param); 5478 min_rssi_param = (wmi_roam_cnd_min_rssi_param *)buf_ptr; 5479 WMITLV_SET_HDR(&min_rssi_param->tlv_header, 5480 WMITLV_TAG_STRUC_wmi_roam_cnd_min_rssi_param, 5481 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_cnd_min_rssi_param)); 5482 trig_reason = 5483 ap_profile->min_rssi_params[MIN_RSSI_2G_TO_5G_ROAM].trigger_reason; 5484 min_rssi_param->roam_trigger_reason = 5485 convert_roam_trigger_reason(trig_reason); 5486 min_rssi_param->candidate_min_rssi = 5487 ap_profile->min_rssi_params[MIN_RSSI_2G_TO_5G_ROAM].min_rssi; 5488 5489 buf_ptr += sizeof(*min_rssi_param); 5490 } else { 5491 /* set zero TLV's for roam_score_delta_param_list */ 5492 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 5493 WMITLV_GET_STRUCT_TLVLEN(0)); 5494 buf_ptr += WMI_TLV_HDR_SIZE; 5495 5496 /* set zero TLV's for roam_cnd_min_rssi_param_list */ 5497 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 5498 WMITLV_GET_STRUCT_TLVLEN(0)); 5499 buf_ptr += WMI_TLV_HDR_SIZE; 5500 } 5501 5502 /* set zero TLV's for roam_cnd_vendor_scoring_param */ 5503 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 5504 WMITLV_GET_STRUCT_TLVLEN(0)); 5505 buf_ptr += WMI_TLV_HDR_SIZE; 5506 5507 if (ap_profile->owe_ap_profile.is_owe_transition_conn) { 5508 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 5509 sizeof(*owe_ap_profile)); 5510 buf_ptr += WMI_TLV_HDR_SIZE; 5511 5512 owe_ap_profile = (wmi_owe_ap_profile *)buf_ptr; 5513 ssid = &owe_ap_profile->open_ssid_for_owe_transition; 5514 WMITLV_SET_HDR(&owe_ap_profile->tlv_header, 5515 WMITLV_TAG_STRUC_wmi_owe_ap_profile, 5516 WMITLV_GET_STRUCT_TLVLEN(wmi_owe_ap_profile)); 5517 5518 ssid->ssid_len = ap_profile->owe_ap_profile.ssid.length; 5519 qdf_mem_copy(ssid->ssid, 5520 ap_profile->owe_ap_profile.ssid.ssid, 5521 ap_profile->owe_ap_profile.ssid.length); 5522 wmi_debug("[OWE_TRANSITION]: open ssid:" QDF_SSID_FMT, 5523 QDF_SSID_REF(ssid->ssid_len, (char *)ssid->ssid)); 5524 5525 buf_ptr += sizeof(*owe_ap_profile); 5526 } else { 5527 /* set zero TLV's for owe_ap_profile */ 5528 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 5529 WMITLV_GET_STRUCT_TLVLEN(0)); 5530 buf_ptr += WMI_TLV_HDR_SIZE; 5531 } 5532 5533 /* List of Allowed authmode other than the connected akm */ 5534 if (ap_profile->profile.num_allowed_authmode) { 5535 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 5536 (ap_profile->profile.num_allowed_authmode * 5537 sizeof(uint32_t))); 5538 5539 buf_ptr += WMI_TLV_HDR_SIZE; 5540 5541 authmode_list = (uint32_t *)buf_ptr; 5542 for (i = 0; i < ap_profile->profile.num_allowed_authmode; i++) 5543 authmode_list[i] = 5544 ap_profile->profile.allowed_authmode[i]; 5545 5546 wmi_debug("[Allowed Authmode]: num_allowed_authmode: %d", 5547 ap_profile->profile.num_allowed_authmode); 5548 QDF_TRACE_HEX_DUMP(QDF_MODULE_ID_WMI, QDF_TRACE_LEVEL_DEBUG, 5549 authmode_list, 5550 ap_profile->profile.num_allowed_authmode * 5551 sizeof(uint32_t)); 5552 } else { 5553 /* set zero TLV's for allowed_authmode */ 5554 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 5555 WMITLV_GET_STRUCT_TLVLEN(0)); 5556 buf_ptr += WMI_TLV_HDR_SIZE; 5557 } 5558 5559 wmi_mtrace(WMI_ROAM_AP_PROFILE, NO_SESSION, 0); 5560 status = wmi_unified_cmd_send(wmi_handle, buf, 5561 len, WMI_ROAM_AP_PROFILE); 5562 if (QDF_IS_STATUS_ERROR(status)) 5563 wmi_buf_free(buf); 5564 5565 return status; 5566 } 5567 5568 /** 5569 * send_roam_scan_offload_cmd_tlv() - set roam offload command 5570 * @wmi_handle: wmi handle 5571 * @command: command 5572 * @vdev_id: vdev id 5573 * 5574 * This function set roam offload command to fw. 5575 * 5576 * Return: QDF status 5577 */ 5578 static QDF_STATUS 5579 send_roam_scan_offload_cmd_tlv(wmi_unified_t wmi_handle, 5580 uint32_t command, uint32_t vdev_id) 5581 { 5582 QDF_STATUS status; 5583 wmi_roam_scan_cmd_fixed_param *cmd_fp; 5584 wmi_buf_t buf = NULL; 5585 int len; 5586 uint8_t *buf_ptr; 5587 5588 len = sizeof(wmi_roam_scan_cmd_fixed_param); 5589 buf = wmi_buf_alloc(wmi_handle, len); 5590 if (!buf) 5591 return QDF_STATUS_E_NOMEM; 5592 5593 buf_ptr = (uint8_t *)wmi_buf_data(buf); 5594 5595 cmd_fp = (wmi_roam_scan_cmd_fixed_param *)buf_ptr; 5596 WMITLV_SET_HDR(&cmd_fp->tlv_header, 5597 WMITLV_TAG_STRUC_wmi_roam_scan_cmd_fixed_param, 5598 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_scan_cmd_fixed_param)); 5599 cmd_fp->vdev_id = vdev_id; 5600 cmd_fp->command_arg = command; 5601 5602 wmi_mtrace(WMI_ROAM_SCAN_CMD, NO_SESSION, 0); 5603 status = wmi_unified_cmd_send(wmi_handle, buf, 5604 len, WMI_ROAM_SCAN_CMD); 5605 if (QDF_IS_STATUS_ERROR(status)) 5606 goto error; 5607 5608 wmi_info("WMI --> WMI_ROAM_SCAN_CMD"); 5609 return QDF_STATUS_SUCCESS; 5610 5611 error: 5612 wmi_buf_free(buf); 5613 5614 return status; 5615 } 5616 5617 /** 5618 * send_roam_scan_offload_chan_list_cmd_tlv() - set roam offload channel list 5619 * @wmi_handle: wmi handle 5620 * @rso_ch_info: Roam offload channel information 5621 * 5622 * Set roam offload channel list. 5623 * 5624 * Return: QDF status 5625 */ 5626 static QDF_STATUS send_roam_scan_offload_chan_list_cmd_tlv( 5627 wmi_unified_t wmi_handle, 5628 struct wlan_roam_scan_channel_list *rso_ch_info) 5629 { 5630 wmi_buf_t buf = NULL; 5631 QDF_STATUS status; 5632 int len, list_tlv_len; 5633 int i; 5634 uint8_t *buf_ptr; 5635 wmi_roam_chan_list_fixed_param *chan_list_fp; 5636 uint32_t *roam_chan_list_array; 5637 uint8_t chan_count = rso_ch_info->chan_count; 5638 uint32_t *chan_list = rso_ch_info->chan_freq_list; 5639 5640 /* Channel list is a table of 2 TLV's */ 5641 list_tlv_len = WMI_TLV_HDR_SIZE + chan_count * sizeof(uint32_t); 5642 len = sizeof(wmi_roam_chan_list_fixed_param) + list_tlv_len; 5643 buf = wmi_buf_alloc(wmi_handle, len); 5644 if (!buf) 5645 return QDF_STATUS_E_NOMEM; 5646 5647 buf_ptr = (uint8_t *)wmi_buf_data(buf); 5648 chan_list_fp = (wmi_roam_chan_list_fixed_param *)buf_ptr; 5649 WMITLV_SET_HDR(&chan_list_fp->tlv_header, 5650 WMITLV_TAG_STRUC_wmi_roam_chan_list_fixed_param, 5651 WMITLV_GET_STRUCT_TLVLEN 5652 (wmi_roam_chan_list_fixed_param)); 5653 chan_list_fp->vdev_id = rso_ch_info->vdev_id; 5654 chan_list_fp->num_chan = chan_count; 5655 if (rso_ch_info->chan_cache_type == WMI_CHANNEL_LIST_STATIC) 5656 /* external app is controlling channel list */ 5657 chan_list_fp->chan_list_type = 5658 WMI_ROAM_SCAN_CHAN_LIST_TYPE_STATIC; 5659 else 5660 /* umac supplied occupied channel list in LFR */ 5661 chan_list_fp->chan_list_type = 5662 WMI_ROAM_SCAN_CHAN_LIST_TYPE_DYNAMIC; 5663 5664 buf_ptr += sizeof(wmi_roam_chan_list_fixed_param); 5665 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, 5666 (chan_list_fp->num_chan * sizeof(uint32_t))); 5667 roam_chan_list_array = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE); 5668 for (i = 0; ((i < chan_list_fp->num_chan) && 5669 (i < WMI_ROAM_MAX_CHANNELS)); i++) 5670 roam_chan_list_array[i] = chan_list[i]; 5671 5672 wmi_debug("RSO_CFG: vdev:%d num_chan:%d cache_type:%d", 5673 chan_list_fp->vdev_id, chan_list_fp->num_chan, 5674 rso_ch_info->chan_cache_type); 5675 wmi_mtrace(WMI_ROAM_CHAN_LIST, NO_SESSION, 0); 5676 status = wmi_unified_cmd_send(wmi_handle, buf, 5677 len, WMI_ROAM_CHAN_LIST); 5678 if (QDF_IS_STATUS_ERROR(status)) 5679 goto error; 5680 5681 return QDF_STATUS_SUCCESS; 5682 error: 5683 wmi_buf_free(buf); 5684 5685 return status; 5686 } 5687 5688 /** 5689 * send_roam_scan_offload_rssi_change_cmd_tlv() - set roam offload RSSI th 5690 * @wmi_handle: wmi handle 5691 * @params: RSSI change parameters 5692 * 5693 * Send WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD parameters to fw. 5694 * 5695 * Return: CDF status 5696 */ 5697 static QDF_STATUS send_roam_scan_offload_rssi_change_cmd_tlv( 5698 wmi_unified_t wmi_handle, 5699 struct wlan_roam_rssi_change_params *params) 5700 { 5701 wmi_buf_t buf = NULL; 5702 QDF_STATUS status; 5703 int len; 5704 uint8_t *buf_ptr; 5705 wmi_roam_scan_rssi_change_threshold_fixed_param *rssi_change_fp; 5706 5707 /* Send rssi change parameters */ 5708 len = sizeof(wmi_roam_scan_rssi_change_threshold_fixed_param); 5709 buf = wmi_buf_alloc(wmi_handle, len); 5710 if (!buf) 5711 return QDF_STATUS_E_NOMEM; 5712 5713 buf_ptr = (uint8_t *)wmi_buf_data(buf); 5714 rssi_change_fp = 5715 (wmi_roam_scan_rssi_change_threshold_fixed_param *)buf_ptr; 5716 WMITLV_SET_HDR(&rssi_change_fp->tlv_header, 5717 WMITLV_TAG_STRUC_wmi_roam_scan_rssi_change_threshold_fixed_param, 5718 WMITLV_GET_STRUCT_TLVLEN 5719 (wmi_roam_scan_rssi_change_threshold_fixed_param)); 5720 /* fill in rssi change threshold (hysteresis) values */ 5721 rssi_change_fp->vdev_id = params->vdev_id; 5722 rssi_change_fp->roam_scan_rssi_change_thresh = 5723 params->rssi_change_thresh; 5724 rssi_change_fp->bcn_rssi_weight = params->bcn_rssi_weight; 5725 rssi_change_fp->hirssi_delay_btw_scans = params->hirssi_delay_btw_scans; 5726 5727 wmi_nofl_debug("RSO_CFG: vdev %d rssi_change_thresh:%d bcn_rssi_weight:%d hirssi_delay_btw_scans:%d", 5728 rssi_change_fp->vdev_id, 5729 rssi_change_fp->roam_scan_rssi_change_thresh, 5730 rssi_change_fp->bcn_rssi_weight, 5731 rssi_change_fp->hirssi_delay_btw_scans); 5732 5733 wmi_mtrace(WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD, 5734 rssi_change_fp->vdev_id, 0); 5735 status = wmi_unified_cmd_send(wmi_handle, buf, len, 5736 WMI_ROAM_SCAN_RSSI_CHANGE_THRESHOLD); 5737 if (QDF_IS_STATUS_ERROR(status)) 5738 goto error; 5739 5740 return QDF_STATUS_SUCCESS; 5741 error: 5742 wmi_buf_free(buf); 5743 5744 return status; 5745 } 5746 5747 /** 5748 * send_per_roam_config_cmd_tlv() - set per roaming config to FW 5749 * @wmi_handle: wmi handle 5750 * @req_buf: per roam config buffer 5751 * 5752 * Return: QDF status 5753 */ 5754 static QDF_STATUS 5755 send_per_roam_config_cmd_tlv(wmi_unified_t wmi_handle, 5756 struct wlan_per_roam_config_req *req_buf) 5757 { 5758 wmi_buf_t buf = NULL; 5759 QDF_STATUS status; 5760 int len; 5761 uint8_t *buf_ptr; 5762 wmi_roam_per_config_fixed_param *wmi_per_config; 5763 5764 len = sizeof(wmi_roam_per_config_fixed_param); 5765 buf = wmi_buf_alloc(wmi_handle, len); 5766 if (!buf) 5767 return QDF_STATUS_E_NOMEM; 5768 5769 buf_ptr = (uint8_t *)wmi_buf_data(buf); 5770 wmi_per_config = 5771 (wmi_roam_per_config_fixed_param *)buf_ptr; 5772 WMITLV_SET_HDR(&wmi_per_config->tlv_header, 5773 WMITLV_TAG_STRUC_wmi_roam_per_config_fixed_param, 5774 WMITLV_GET_STRUCT_TLVLEN 5775 (wmi_roam_per_config_fixed_param)); 5776 5777 /* fill in per roam config values */ 5778 wmi_per_config->vdev_id = req_buf->vdev_id; 5779 5780 wmi_per_config->enable = req_buf->per_config.enable; 5781 wmi_per_config->high_rate_thresh = 5782 (req_buf->per_config.tx_high_rate_thresh << 16) | 5783 (req_buf->per_config.rx_high_rate_thresh & 0x0000ffff); 5784 wmi_per_config->low_rate_thresh = 5785 (req_buf->per_config.tx_low_rate_thresh << 16) | 5786 (req_buf->per_config.rx_low_rate_thresh & 0x0000ffff); 5787 wmi_per_config->pkt_err_rate_thresh_pct = 5788 (req_buf->per_config.tx_rate_thresh_percnt << 16) | 5789 (req_buf->per_config.rx_rate_thresh_percnt & 0x0000ffff); 5790 wmi_per_config->per_rest_time = req_buf->per_config.per_rest_time; 5791 wmi_per_config->pkt_err_rate_mon_time = 5792 (req_buf->per_config.tx_per_mon_time << 16) | 5793 (req_buf->per_config.rx_per_mon_time & 0x0000ffff); 5794 wmi_per_config->min_candidate_rssi = 5795 req_buf->per_config.min_candidate_rssi; 5796 5797 /* Send per roam config parameters */ 5798 wmi_mtrace(WMI_ROAM_PER_CONFIG_CMDID, NO_SESSION, 0); 5799 status = wmi_unified_cmd_send(wmi_handle, buf, 5800 len, WMI_ROAM_PER_CONFIG_CMDID); 5801 if (QDF_IS_STATUS_ERROR(status)) { 5802 wmi_err("WMI_ROAM_PER_CONFIG_CMDID failed, Error %d", status); 5803 wmi_buf_free(buf); 5804 return status; 5805 } 5806 wmi_debug("per roam enable=%d, vdev=%d", 5807 req_buf->per_config.enable, req_buf->vdev_id); 5808 5809 return QDF_STATUS_SUCCESS; 5810 } 5811 5812 /** 5813 * send_limit_off_chan_cmd_tlv() - send wmi cmd of limit off chan 5814 * configuration params 5815 * @wmi_handle: wmi handler 5816 * @limit_off_chan_param: pointer to wmi_off_chan_param 5817 * 5818 * Return: 0 for success and non zero for failure 5819 */ 5820 static QDF_STATUS send_limit_off_chan_cmd_tlv( 5821 wmi_unified_t wmi_handle, 5822 struct wmi_limit_off_chan_param *limit_off_chan_param) 5823 { 5824 wmi_vdev_limit_offchan_cmd_fixed_param *cmd; 5825 wmi_buf_t buf; 5826 uint32_t len = sizeof(*cmd); 5827 int err; 5828 5829 buf = wmi_buf_alloc(wmi_handle, len); 5830 if (!buf) 5831 return QDF_STATUS_E_NOMEM; 5832 5833 cmd = (wmi_vdev_limit_offchan_cmd_fixed_param *)wmi_buf_data(buf); 5834 5835 WMITLV_SET_HDR(&cmd->tlv_header, 5836 WMITLV_TAG_STRUC_wmi_vdev_limit_offchan_cmd_fixed_param, 5837 WMITLV_GET_STRUCT_TLVLEN( 5838 wmi_vdev_limit_offchan_cmd_fixed_param)); 5839 5840 cmd->vdev_id = limit_off_chan_param->vdev_id; 5841 5842 cmd->flags &= 0; 5843 if (limit_off_chan_param->status) 5844 cmd->flags |= WMI_VDEV_LIMIT_OFFCHAN_ENABLE; 5845 if (limit_off_chan_param->skip_dfs_chans) 5846 cmd->flags |= WMI_VDEV_LIMIT_OFFCHAN_SKIP_DFS; 5847 5848 cmd->max_offchan_time = limit_off_chan_param->max_offchan_time; 5849 cmd->rest_time = limit_off_chan_param->rest_time; 5850 5851 wmi_debug("vdev_id=%d, flags =%x, max_offchan_time=%d, rest_time=%d", 5852 cmd->vdev_id, cmd->flags, cmd->max_offchan_time, 5853 cmd->rest_time); 5854 5855 wmi_mtrace(WMI_VDEV_LIMIT_OFFCHAN_CMDID, cmd->vdev_id, 0); 5856 err = wmi_unified_cmd_send(wmi_handle, buf, 5857 len, WMI_VDEV_LIMIT_OFFCHAN_CMDID); 5858 if (QDF_IS_STATUS_ERROR(err)) { 5859 wmi_err("Failed to send limit off chan cmd err=%d", err); 5860 wmi_buf_free(buf); 5861 return QDF_STATUS_E_FAILURE; 5862 } 5863 5864 return QDF_STATUS_SUCCESS; 5865 } 5866 5867 #ifdef WLAN_FEATURE_FILS_SK 5868 static QDF_STATUS send_roam_scan_send_hlp_cmd_tlv(wmi_unified_t wmi_handle, 5869 struct hlp_params *params) 5870 { 5871 uint32_t len; 5872 uint8_t *buf_ptr; 5873 wmi_buf_t buf = NULL; 5874 wmi_pdev_update_fils_hlp_pkt_cmd_fixed_param *hlp_params; 5875 5876 len = sizeof(wmi_pdev_update_fils_hlp_pkt_cmd_fixed_param); 5877 len += WMI_TLV_HDR_SIZE; 5878 len += qdf_roundup(params->hlp_ie_len, sizeof(uint32_t)); 5879 5880 buf = wmi_buf_alloc(wmi_handle, len); 5881 if (!buf) 5882 return QDF_STATUS_E_NOMEM; 5883 5884 buf_ptr = (uint8_t *)wmi_buf_data(buf); 5885 hlp_params = (wmi_pdev_update_fils_hlp_pkt_cmd_fixed_param *)buf_ptr; 5886 WMITLV_SET_HDR(&hlp_params->tlv_header, 5887 WMITLV_TAG_STRUC_wmi_pdev_update_fils_hlp_pkt_cmd_fixed_param, 5888 WMITLV_GET_STRUCT_TLVLEN( 5889 wmi_pdev_update_fils_hlp_pkt_cmd_fixed_param)); 5890 5891 hlp_params->vdev_id = params->vdev_id; 5892 hlp_params->size = params->hlp_ie_len; 5893 hlp_params->pkt_type = WMI_FILS_HLP_PKT_TYPE_DHCP_DISCOVER; 5894 5895 buf_ptr += sizeof(*hlp_params); 5896 5897 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, 5898 round_up(params->hlp_ie_len, sizeof(uint32_t))); 5899 5900 buf_ptr += WMI_TLV_HDR_SIZE; 5901 qdf_mem_copy(buf_ptr, params->hlp_ie, params->hlp_ie_len); 5902 5903 wmi_debug("send FILS HLP pkt vdev %d len %d", 5904 hlp_params->vdev_id, hlp_params->size); 5905 wmi_mtrace(WMI_PDEV_UPDATE_FILS_HLP_PKT_CMDID, NO_SESSION, 0); 5906 if (wmi_unified_cmd_send(wmi_handle, buf, len, 5907 WMI_PDEV_UPDATE_FILS_HLP_PKT_CMDID)) { 5908 wmi_err("Failed to send FILS HLP pkt cmd"); 5909 wmi_buf_free(buf); 5910 return QDF_STATUS_E_FAILURE; 5911 } 5912 5913 return QDF_STATUS_SUCCESS; 5914 } 5915 5916 void wmi_fils_sk_attach_tlv(wmi_unified_t wmi_handle) 5917 { 5918 struct wmi_ops *ops = wmi_handle->ops; 5919 5920 ops->send_roam_scan_hlp_cmd = send_roam_scan_send_hlp_cmd_tlv; 5921 } 5922 #endif /* WLAN_FEATURE_FILS_SK */ 5923 5924 /* 5925 * send_btm_config_cmd_tlv() - Send wmi cmd for BTM config 5926 * @wmi_handle: wmi handle 5927 * @params: pointer to wlan_roam_btm_config 5928 * 5929 * Return: QDF_STATUS 5930 */ 5931 static QDF_STATUS send_btm_config_cmd_tlv(wmi_unified_t wmi_handle, 5932 struct wlan_roam_btm_config *params) 5933 { 5934 wmi_btm_config_fixed_param *cmd; 5935 wmi_buf_t buf; 5936 uint32_t len; 5937 5938 len = sizeof(*cmd); 5939 buf = wmi_buf_alloc(wmi_handle, len); 5940 if (!buf) 5941 return QDF_STATUS_E_NOMEM; 5942 5943 cmd = (wmi_btm_config_fixed_param *)wmi_buf_data(buf); 5944 WMITLV_SET_HDR(&cmd->tlv_header, 5945 WMITLV_TAG_STRUC_wmi_btm_config_fixed_param, 5946 WMITLV_GET_STRUCT_TLVLEN(wmi_btm_config_fixed_param)); 5947 cmd->vdev_id = params->vdev_id; 5948 cmd->flags = params->btm_offload_config; 5949 cmd->max_attempt_cnt = params->btm_max_attempt_cnt; 5950 cmd->solicited_timeout_ms = params->btm_solicited_timeout; 5951 cmd->stick_time_seconds = params->btm_sticky_time; 5952 cmd->disassoc_timer_threshold = params->disassoc_timer_threshold; 5953 cmd->btm_bitmap = params->btm_query_bitmask; 5954 cmd->btm_candidate_min_score = params->btm_candidate_min_score; 5955 5956 wmi_debug("RSO_CFG: vdev_id:%u btm_offload:%u btm_query_bitmask:%u btm_candidate_min_score:%u", 5957 cmd->vdev_id, cmd->flags, cmd->btm_bitmap, 5958 cmd->btm_candidate_min_score); 5959 wmi_debug("RSO_CFG: btm_solicited_timeout:%u btm_max_attempt_cnt:%u btm_sticky_time:%u disassoc_timer_threshold:%u", 5960 cmd->solicited_timeout_ms, cmd->max_attempt_cnt, 5961 cmd->stick_time_seconds, cmd->disassoc_timer_threshold); 5962 5963 wmi_mtrace(WMI_ROAM_BTM_CONFIG_CMDID, cmd->vdev_id, 0); 5964 if (wmi_unified_cmd_send(wmi_handle, buf, len, 5965 WMI_ROAM_BTM_CONFIG_CMDID)) { 5966 wmi_err("Failed to send WMI_ROAM_BTM_CONFIG_CMDID"); 5967 wmi_buf_free(buf); 5968 return QDF_STATUS_E_FAILURE; 5969 } 5970 5971 return QDF_STATUS_SUCCESS; 5972 } 5973 5974 /** 5975 * send_roam_bss_load_config_tlv() - send roam load bss trigger configuration 5976 * @wmi_handle: wmi handle 5977 * @params: pointer to wlan_roam_bss_load_config 5978 * 5979 * This function sends the roam load bss trigger configuration to fw. 5980 * the bss_load_threshold parameter is used to configure the maximum 5981 * bss load percentage, above which the firmware should trigger roaming 5982 * 5983 * Return: QDF status 5984 */ 5985 static QDF_STATUS 5986 send_roam_bss_load_config_tlv(wmi_unified_t wmi_handle, 5987 struct wlan_roam_bss_load_config *params) 5988 { 5989 wmi_roam_bss_load_config_cmd_fixed_param *cmd; 5990 wmi_buf_t buf; 5991 uint32_t len; 5992 5993 len = sizeof(*cmd); 5994 buf = wmi_buf_alloc(wmi_handle, len); 5995 if (!buf) 5996 return QDF_STATUS_E_NOMEM; 5997 5998 cmd = (wmi_roam_bss_load_config_cmd_fixed_param *)wmi_buf_data(buf); 5999 WMITLV_SET_HDR( 6000 &cmd->tlv_header, 6001 WMITLV_TAG_STRUC_wmi_roam_bss_load_config_cmd_fixed_param, 6002 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_bss_load_config_cmd_fixed_param)); 6003 6004 cmd->vdev_id = params->vdev_id; 6005 cmd->bss_load_threshold = params->bss_load_threshold; 6006 cmd->monitor_time_window = params->bss_load_sample_time; 6007 cmd->rssi_2g_threshold = params->rssi_threshold_24ghz; 6008 cmd->rssi_5g_threshold = params->rssi_threshold_5ghz; 6009 cmd->rssi_6g_threshold = params->rssi_threshold_6ghz; 6010 6011 wmi_debug("RSO_CFG: vdev:%d bss_load_thres:%d monitor_time:%d rssi_2g:%d rssi_5g:%d, rssi_6g:%d", 6012 cmd->vdev_id, cmd->bss_load_threshold, 6013 cmd->monitor_time_window, cmd->rssi_2g_threshold, 6014 cmd->rssi_5g_threshold, cmd->rssi_6g_threshold); 6015 6016 wmi_mtrace(WMI_ROAM_BSS_LOAD_CONFIG_CMDID, cmd->vdev_id, 0); 6017 if (wmi_unified_cmd_send(wmi_handle, buf, len, 6018 WMI_ROAM_BSS_LOAD_CONFIG_CMDID)) { 6019 wmi_err("Failed to send WMI_ROAM_BSS_LOAD_CONFIG_CMDID"); 6020 wmi_buf_free(buf); 6021 return QDF_STATUS_E_FAILURE; 6022 } 6023 6024 return QDF_STATUS_SUCCESS; 6025 } 6026 6027 #ifdef WLAN_FEATURE_ROAM_OFFLOAD 6028 /** 6029 * send_disconnect_roam_params_tlv() - send disconnect roam trigger parameters 6030 * @wmi_handle: wmi handle 6031 * @req: pointer to wlan_roam_disconnect_params which carries the 6032 * disconnect_roam_trigger parameters 6033 * 6034 * This function sends the disconnect roam trigger parameters to fw. 6035 * 6036 * Return: QDF status 6037 */ 6038 static QDF_STATUS 6039 send_disconnect_roam_params_tlv(wmi_unified_t wmi_handle, 6040 struct wlan_roam_disconnect_params *req) 6041 { 6042 wmi_roam_deauth_config_cmd_fixed_param *cmd; 6043 wmi_buf_t buf; 6044 uint32_t len; 6045 6046 len = sizeof(*cmd); 6047 buf = wmi_buf_alloc(wmi_handle, len); 6048 if (!buf) 6049 return QDF_STATUS_E_NOMEM; 6050 6051 cmd = (wmi_roam_deauth_config_cmd_fixed_param *)wmi_buf_data(buf); 6052 WMITLV_SET_HDR( 6053 &cmd->tlv_header, 6054 WMITLV_TAG_STRUC_wmi_roam_deauth_config_cmd_fixed_param, 6055 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_deauth_config_cmd_fixed_param)); 6056 6057 cmd->vdev_id = req->vdev_id; 6058 cmd->enable = req->enable; 6059 wmi_debug("RSO_CFG: vdev_id:%d enable:%d", cmd->vdev_id, cmd->enable); 6060 6061 wmi_mtrace(WMI_ROAM_DEAUTH_CONFIG_CMDID, cmd->vdev_id, 0); 6062 if (wmi_unified_cmd_send(wmi_handle, buf, len, 6063 WMI_ROAM_DEAUTH_CONFIG_CMDID)) { 6064 wmi_err("Failed to send WMI_ROAM_DEAUTH_CONFIG_CMDID"); 6065 wmi_buf_free(buf); 6066 return QDF_STATUS_E_FAILURE; 6067 } 6068 6069 return QDF_STATUS_SUCCESS; 6070 } 6071 6072 #define WLAN_TIME_IN_MS 1000 6073 /** 6074 * send_idle_roam_params_tlv() - send idle roam trigger parameters 6075 * @wmi_handle: wmi handle 6076 * @idle_roam_params: pointer to wlan_roam_idle_params which carries the 6077 * idle roam parameters from CSR 6078 * 6079 * This function sends the idle roam trigger parameters to fw. 6080 * 6081 * Return: QDF status 6082 */ 6083 static QDF_STATUS 6084 send_idle_roam_params_tlv(wmi_unified_t wmi_handle, 6085 struct wlan_roam_idle_params *idle_roam_params) 6086 { 6087 wmi_roam_idle_config_cmd_fixed_param *cmd; 6088 wmi_buf_t buf; 6089 uint32_t len; 6090 6091 len = sizeof(*cmd); 6092 buf = wmi_buf_alloc(wmi_handle, len); 6093 if (!buf) 6094 return QDF_STATUS_E_NOMEM; 6095 6096 cmd = (wmi_roam_idle_config_cmd_fixed_param *)wmi_buf_data(buf); 6097 WMITLV_SET_HDR( 6098 &cmd->tlv_header, 6099 WMITLV_TAG_STRUC_wmi_roam_idle_config_cmd_fixed_param, 6100 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_idle_config_cmd_fixed_param)); 6101 6102 cmd->vdev_id = idle_roam_params->vdev_id; 6103 cmd->enable = idle_roam_params->enable; 6104 cmd->band = idle_roam_params->band; 6105 cmd->rssi_delta = idle_roam_params->conn_ap_rssi_delta; 6106 cmd->min_rssi = idle_roam_params->conn_ap_min_rssi; 6107 cmd->idle_time = idle_roam_params->inactive_time / WLAN_TIME_IN_MS; 6108 cmd->data_packet_count = idle_roam_params->data_pkt_count; 6109 wmi_debug("RSO_CFG: vdev_id:%d enable:%d band:%d rssi_delta:%d min_rssi:%d idle_time:%d data_pkt:%d", 6110 cmd->vdev_id, cmd->enable, 6111 cmd->band, cmd->rssi_delta, cmd->min_rssi, 6112 cmd->idle_time, cmd->data_packet_count); 6113 6114 wmi_mtrace(WMI_ROAM_IDLE_CONFIG_CMDID, cmd->vdev_id, 0); 6115 if (wmi_unified_cmd_send(wmi_handle, buf, len, 6116 WMI_ROAM_IDLE_CONFIG_CMDID)) { 6117 wmi_err("Failed to send WMI_ROAM_IDLE_CONFIG_CMDID"); 6118 wmi_buf_free(buf); 6119 return QDF_STATUS_E_FAILURE; 6120 } 6121 6122 return QDF_STATUS_SUCCESS; 6123 } 6124 6125 /** 6126 * send_roam_preauth_status_tlv() - send roam pre-authentication status 6127 * @wmi_handle: wmi handle 6128 * @params: pre-auth status params 6129 * 6130 * This function sends the roam pre-authentication status for WPA3 SAE 6131 * pre-auth to target. 6132 * 6133 * Return: QDF status 6134 */ 6135 static QDF_STATUS 6136 send_roam_preauth_status_tlv(wmi_unified_t wmi_handle, 6137 struct wmi_roam_auth_status_params *params) 6138 { 6139 wmi_roam_preauth_status_cmd_fixed_param *cmd; 6140 wmi_buf_t buf; 6141 uint32_t len; 6142 uint8_t *buf_ptr; 6143 6144 len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + PMKID_LEN; 6145 buf = wmi_buf_alloc(wmi_handle, len); 6146 if (!buf) 6147 return QDF_STATUS_E_NOMEM; 6148 6149 buf_ptr = (uint8_t *)wmi_buf_data(buf); 6150 cmd = (wmi_roam_preauth_status_cmd_fixed_param *)buf_ptr; 6151 WMITLV_SET_HDR( 6152 &cmd->tlv_header, 6153 WMITLV_TAG_STRUC_wmi_roam_preauth_status_cmd_fixed_param, 6154 WMITLV_GET_STRUCT_TLVLEN(wmi_roam_preauth_status_cmd_fixed_param)); 6155 6156 cmd->vdev_id = params->vdev_id; 6157 cmd->preauth_status = params->preauth_status; 6158 WMI_CHAR_ARRAY_TO_MAC_ADDR(params->bssid.bytes, 6159 &cmd->candidate_ap_bssid); 6160 6161 buf_ptr += sizeof(wmi_roam_preauth_status_cmd_fixed_param); 6162 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_BYTE, PMKID_LEN); 6163 buf_ptr += WMI_TLV_HDR_SIZE; 6164 6165 qdf_mem_copy(buf_ptr, params->pmkid, PMKID_LEN); 6166 wmi_debug("vdev_id:%d status:%d bssid:"QDF_MAC_ADDR_FMT, 6167 cmd->vdev_id, cmd->preauth_status, 6168 QDF_MAC_ADDR_REF(params->bssid.bytes)); 6169 6170 wmi_mtrace(WMI_ROAM_PREAUTH_STATUS_CMDID, cmd->vdev_id, 0); 6171 if (wmi_unified_cmd_send(wmi_handle, buf, len, 6172 WMI_ROAM_PREAUTH_STATUS_CMDID)) { 6173 wmi_buf_free(buf); 6174 return QDF_STATUS_E_FAILURE; 6175 } 6176 6177 return QDF_STATUS_SUCCESS; 6178 } 6179 #else 6180 static inline QDF_STATUS 6181 send_disconnect_roam_params_tlv(wmi_unified_t wmi_handle, 6182 struct wlan_roam_disconnect_params *req) 6183 { 6184 return QDF_STATUS_E_FAILURE; 6185 } 6186 6187 static inline QDF_STATUS 6188 send_idle_roam_params_tlv(wmi_unified_t wmi_handle, 6189 struct wlan_roam_idle_params *idle_roam_params) 6190 { 6191 return QDF_STATUS_E_FAILURE; 6192 } 6193 6194 static inline QDF_STATUS 6195 send_roam_preauth_status_tlv(wmi_unified_t wmi_handle, 6196 struct wmi_roam_auth_status_params *params) 6197 { 6198 return QDF_STATUS_E_FAILURE; 6199 } 6200 #endif 6201 6202 /** 6203 * send_offload_11k_cmd_tlv() - send wmi cmd with 11k offload params 6204 * @wmi_handle: wmi handler 6205 * @params: pointer to 11k offload params 6206 * 6207 * Return: 0 for success and non zero for failure 6208 */ 6209 static QDF_STATUS 6210 send_offload_11k_cmd_tlv(wmi_unified_t wmi_handle, 6211 struct wlan_roam_11k_offload_params *params) 6212 { 6213 wmi_11k_offload_report_fixed_param *cmd; 6214 wmi_buf_t buf; 6215 QDF_STATUS status; 6216 uint8_t *buf_ptr; 6217 wmi_neighbor_report_11k_offload_tlv_param 6218 *neighbor_report_offload_params; 6219 wmi_neighbor_report_offload *neighbor_report_offload; 6220 uint32_t len = sizeof(*cmd); 6221 6222 if (params->offload_11k_bitmask & 6223 WMI_11K_OFFLOAD_BITMAP_NEIGHBOR_REPORT_REQ) 6224 len += WMI_TLV_HDR_SIZE + 6225 sizeof(wmi_neighbor_report_11k_offload_tlv_param); 6226 6227 buf = wmi_buf_alloc(wmi_handle, len); 6228 if (!buf) 6229 return QDF_STATUS_E_NOMEM; 6230 6231 buf_ptr = (uint8_t *)wmi_buf_data(buf); 6232 cmd = (wmi_11k_offload_report_fixed_param *)buf_ptr; 6233 6234 WMITLV_SET_HDR(&cmd->tlv_header, 6235 WMITLV_TAG_STRUC_wmi_offload_11k_report_fixed_param, 6236 WMITLV_GET_STRUCT_TLVLEN( 6237 wmi_11k_offload_report_fixed_param)); 6238 6239 cmd->vdev_id = params->vdev_id; 6240 cmd->offload_11k = params->offload_11k_bitmask; 6241 6242 if (params->offload_11k_bitmask & 6243 WMI_11K_OFFLOAD_BITMAP_NEIGHBOR_REPORT_REQ) { 6244 buf_ptr += sizeof(wmi_11k_offload_report_fixed_param); 6245 6246 WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, 6247 sizeof(wmi_neighbor_report_11k_offload_tlv_param)); 6248 buf_ptr += WMI_TLV_HDR_SIZE; 6249 6250 neighbor_report_offload_params = 6251 (wmi_neighbor_report_11k_offload_tlv_param *)buf_ptr; 6252 WMITLV_SET_HDR(&neighbor_report_offload_params->tlv_header, 6253 WMITLV_TAG_STRUC_wmi_neighbor_report_offload_tlv_param, 6254 WMITLV_GET_STRUCT_TLVLEN( 6255 wmi_neighbor_report_11k_offload_tlv_param)); 6256 6257 neighbor_report_offload = &neighbor_report_offload_params-> 6258 neighbor_rep_ofld_params; 6259 6260 neighbor_report_offload->time_offset = 6261 params->neighbor_report_params.time_offset; 6262 neighbor_report_offload->low_rssi_offset = 6263 params->neighbor_report_params.low_rssi_offset; 6264 neighbor_report_offload->bmiss_count_trigger = 6265 params->neighbor_report_params.bmiss_count_trigger; 6266 neighbor_report_offload->per_threshold_offset = 6267 params->neighbor_report_params.per_threshold_offset; 6268 neighbor_report_offload->neighbor_report_cache_timeout = 6269 params->neighbor_report_params. 6270 neighbor_report_cache_timeout; 6271 neighbor_report_offload->max_neighbor_report_req_cap = 6272 params->neighbor_report_params. 6273 max_neighbor_report_req_cap; 6274 neighbor_report_offload->ssid.ssid_len = 6275 params->neighbor_report_params.ssid.length; 6276 qdf_mem_copy(neighbor_report_offload->ssid.ssid, 6277 ¶ms->neighbor_report_params.ssid.ssid, 6278 neighbor_report_offload->ssid.ssid_len); 6279 } 6280 6281 wmi_debug("RSO_CFG: vdev %d 11k_bitmask:%u time_offset:%u low_rssi_offset:%u bmiss_count_trigger:%u per_threshold_offset%u", 6282 cmd->vdev_id, params->offload_11k_bitmask, 6283 params->neighbor_report_params.time_offset, 6284 params->neighbor_report_params.low_rssi_offset, 6285 params->neighbor_report_params.bmiss_count_trigger, 6286 params->neighbor_report_params.per_threshold_offset); 6287 wmi_debug("RSO_CFG: neighbor_report_cache_timeout:%u max_neighbor_report_req_cap:%u SSID:" QDF_SSID_FMT, 6288 params->neighbor_report_params.neighbor_report_cache_timeout, 6289 params->neighbor_report_params.max_neighbor_report_req_cap, 6290 QDF_SSID_REF(params->neighbor_report_params.ssid.length, 6291 params->neighbor_report_params.ssid.ssid)); 6292 6293 wmi_mtrace(WMI_11K_OFFLOAD_REPORT_CMDID, cmd->vdev_id, 0); 6294 status = wmi_unified_cmd_send(wmi_handle, buf, len, 6295 WMI_11K_OFFLOAD_REPORT_CMDID); 6296 if (status != QDF_STATUS_SUCCESS) { 6297 wmi_err("Failed to send 11k offload command %d", status); 6298 wmi_buf_free(buf); 6299 } 6300 6301 return status; 6302 } 6303 6304 /** 6305 * send_invoke_neighbor_report_cmd_tlv() - send invoke 11k neighbor report 6306 * command 6307 * @wmi_handle: wmi handler 6308 * @params: pointer to neighbor report invoke params 6309 * 6310 * Return: 0 for success and non zero for failure 6311 */ 6312 static QDF_STATUS send_invoke_neighbor_report_cmd_tlv( 6313 wmi_unified_t wmi_handle, 6314 struct wmi_invoke_neighbor_report_params *params) 6315 { 6316 wmi_11k_offload_invoke_neighbor_report_fixed_param *cmd; 6317 wmi_buf_t buf; 6318 QDF_STATUS status; 6319 uint8_t *buf_ptr; 6320 uint32_t len = sizeof(*cmd); 6321 6322 buf = wmi_buf_alloc(wmi_handle, len); 6323 if (!buf) 6324 return QDF_STATUS_E_NOMEM; 6325 6326 buf_ptr = (uint8_t *)wmi_buf_data(buf); 6327 cmd = (wmi_11k_offload_invoke_neighbor_report_fixed_param *)buf_ptr; 6328 6329 WMITLV_SET_HDR(&cmd->tlv_header, 6330 WMITLV_TAG_STRUC_wmi_invoke_neighbor_report_fixed_param, 6331 WMITLV_GET_STRUCT_TLVLEN( 6332 wmi_11k_offload_invoke_neighbor_report_fixed_param)); 6333 6334 cmd->vdev_id = params->vdev_id; 6335 cmd->flags = params->send_resp_to_host; 6336 6337 cmd->ssid.ssid_len = params->ssid.length; 6338 qdf_mem_copy(cmd->ssid.ssid, ¶ms->ssid.ssid, cmd->ssid.ssid_len); 6339 6340 wmi_mtrace(WMI_11K_INVOKE_NEIGHBOR_REPORT_CMDID, cmd->vdev_id, 0); 6341 status = wmi_unified_cmd_send(wmi_handle, buf, len, 6342 WMI_11K_INVOKE_NEIGHBOR_REPORT_CMDID); 6343 if (status != QDF_STATUS_SUCCESS) { 6344 wmi_err("Failed to send invoke neighbor report command %d", 6345 status); 6346 wmi_buf_free(buf); 6347 } 6348 6349 return status; 6350 } 6351 6352 void wmi_roam_attach_tlv(wmi_unified_t wmi_handle) 6353 { 6354 struct wmi_ops *ops = wmi_handle->ops; 6355 6356 ops->send_roam_scan_offload_rssi_thresh_cmd = 6357 send_roam_scan_offload_rssi_thresh_cmd_tlv; 6358 ops->send_roam_mawc_params_cmd = send_roam_mawc_params_cmd_tlv; 6359 ops->send_roam_scan_filter_cmd = 6360 send_roam_scan_filter_cmd_tlv; 6361 ops->send_roam_scan_offload_mode_cmd = 6362 send_roam_scan_offload_mode_cmd_tlv; 6363 ops->send_roam_scan_offload_ap_profile_cmd = 6364 send_roam_scan_offload_ap_profile_cmd_tlv; 6365 ops->send_roam_scan_offload_cmd = send_roam_scan_offload_cmd_tlv; 6366 ops->send_roam_scan_offload_scan_period_cmd = 6367 send_roam_scan_offload_scan_period_cmd_tlv; 6368 ops->send_roam_scan_offload_chan_list_cmd = 6369 send_roam_scan_offload_chan_list_cmd_tlv; 6370 ops->send_roam_scan_offload_rssi_change_cmd = 6371 send_roam_scan_offload_rssi_change_cmd_tlv; 6372 ops->send_per_roam_config_cmd = send_per_roam_config_cmd_tlv; 6373 ops->send_limit_off_chan_cmd = send_limit_off_chan_cmd_tlv; 6374 ops->send_btm_config = send_btm_config_cmd_tlv; 6375 ops->send_offload_11k_cmd = send_offload_11k_cmd_tlv; 6376 ops->send_invoke_neighbor_report_cmd = 6377 send_invoke_neighbor_report_cmd_tlv; 6378 ops->send_roam_bss_load_config = send_roam_bss_load_config_tlv; 6379 ops->send_idle_roam_params = send_idle_roam_params_tlv; 6380 ops->send_disconnect_roam_params = send_disconnect_roam_params_tlv; 6381 ops->send_roam_preauth_status = send_roam_preauth_status_tlv; 6382 ops->extract_roam_event = extract_roam_event_tlv; 6383 6384 wmi_roam_mlo_attach_tlv(wmi_handle); 6385 wmi_lfr_subnet_detection_attach_tlv(wmi_handle); 6386 wmi_rssi_monitor_attach_tlv(wmi_handle); 6387 wmi_ese_attach_tlv(wmi_handle); 6388 wmi_roam_offload_attach_tlv(wmi_handle); 6389 wmi_fils_sk_attach_tlv(wmi_handle); 6390 } 6391