From e2082f28fd3ca79c7818696ea15a534cd01e0867 Mon Sep 17 00:00:00 2001 From: Himanshu Agarwal Date: Wed, 9 Mar 2016 15:25:44 +0530 Subject: [PATCH] qcacmn: Add tlv formation of wmi roam scan commands in common wmi layer Move tlv formation of roam scan related commands from umac to common wmi layer Change-Id: Ib582f09ccc90e29eeace1af1bfcd43e0ff1e5203 CRs-Fixed: 987362 --- wmi/inc/wmi_unified_api.h | 10 + wmi/inc/wmi_unified_param.h | 145 +++++++++++ wmi/inc/wmi_unified_priv.h | 10 + wmi/inc/wmi_unified_tlv.h | 10 + wmi/src/wmi_unified_api.c | 71 +++++ wmi/src/wmi_unified_tlv.c | 505 ++++++++++++++++++++++++++++++++++++ 6 files changed, 751 insertions(+) diff --git a/wmi/inc/wmi_unified_api.h b/wmi/inc/wmi_unified_api.h index 65d154b457..8302ecb69f 100644 --- a/wmi/inc/wmi_unified_api.h +++ b/wmi/inc/wmi_unified_api.h @@ -446,6 +446,16 @@ QDF_STATUS wmi_unified_reset_passpoint_network_list_cmd(void *wmi_hdl, QDF_STATUS wmi_unified_set_passpoint_network_list_cmd(void *wmi_hdl, struct wifi_passpoint_req_param *req); +QDF_STATUS wmi_unified_roam_scan_offload_mode_cmd(void *wmi_hdl, + wmi_start_scan_cmd_fixed_param *scan_cmd_fp, + struct roam_offload_scan_params *roam_req); + +QDF_STATUS wmi_unified_roam_scan_offload_rssi_thresh_cmd(void *wmi_hdl, + struct roam_offload_scan_rssi_params *roam_req); + +QDF_STATUS wmi_unified_roam_scan_filter_cmd(void *wmi_hdl, + struct roam_scan_filter_params *roam_req); + QDF_STATUS wmi_unified_set_epno_network_list_cmd(void *wmi_hdl, struct wifi_enhanched_pno_params *req); diff --git a/wmi/inc/wmi_unified_param.h b/wmi/inc/wmi_unified_param.h index 9d051d5492..009ef34168 100644 --- a/wmi/inc/wmi_unified_param.h +++ b/wmi/inc/wmi_unified_param.h @@ -61,6 +61,13 @@ #define WMI_IPV4_ADDR_LEN 4 #define WMI_KEEP_ALIVE_NULL_PKT 1 #define WMI_KEEP_ALIVE_UNSOLICIT_ARP_RSP 2 +#define WMI_KRK_KEY_LEN 16 +#ifdef WLAN_FEATURE_ROAM_OFFLOAD +#define WMI_BTK_KEY_LEN 32 +#define WMI_ROAM_R0KH_ID_MAX_LEN 48 +#define WMI_ROAM_SCAN_PSK_SIZE 32 +#endif +#define WMI_NOISE_FLOOR_DBM_DEFAULT (-96) #ifdef WLAN_NS_OFFLOAD /* support only one IPv6 offload */ #define WMI_MAC_NS_OFFLOAD_SIZE 1 @@ -911,6 +918,104 @@ struct wifi_passpoint_req_param { struct wifi_passpoint_network_param networks[]; }; +/* struct mobility_domain_info - structure containing + * mobility domain info + * @mdie_present: mobility domain present or not + * @mobility_domain: mobility domain + */ +struct mobility_domain_info { + uint8_t mdie_present; + uint16_t mobility_domain; +}; + +/* struct roam_offload_scan_params - structure + * containing roaming offload scan parameters + * @is_roam_req_valid: flag to tell whether roam req + * is valid or NULL + * @mode: stores flags for scan + * @vdev_id: vdev id + * @roam_offload_enabled: flag for offload enable + * @psk_pmk: pre shared key/pairwise master key + * @pmk_len: length of PMK + * @prefer_5ghz: prefer select 5G candidate + * @roam_rssi_cat_gap: gap for every category bucket + * @select_5ghz_margin: select 5 Ghz margin + * @krk: KRK + * @btk: BTK + * @reassoc_failure_timeout: reassoc failure timeout + * @rokh_id_length: r0kh id length + * @rokh_id: r0kh id + * @roam_key_mgmt_offload_enabled: roam offload flag + * @auth_mode: authentication mode + * @is_ese_assoc: flag to determine ese assoc + * @mdid: mobility domain info + * @roam_offload_params: roam offload tlv params + */ +struct roam_offload_scan_params { + uint8_t is_roam_req_valid; + uint32_t mode; + uint32_t vdev_id; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + uint8_t roam_offload_enabled; + uint8_t psk_pmk[WMI_ROAM_SCAN_PSK_SIZE]; + uint32_t pmk_len; + uint8_t prefer_5ghz; + uint8_t roam_rssi_cat_gap; + uint8_t select_5ghz_margin; + uint8_t krk[WMI_KRK_KEY_LEN]; + uint8_t btk[WMI_BTK_KEY_LEN]; + uint32_t reassoc_failure_timeout; + uint32_t rokh_id_length; + uint8_t rokh_id[WMI_ROAM_R0KH_ID_MAX_LEN]; + uint8_t roam_key_mgmt_offload_enabled; + int auth_mode; +#endif + bool is_ese_assoc; + struct mobility_domain_info mdid; + wmi_roam_offload_tlv_param roam_offload_params; +}; + +/* struct roam_offload_scan_rssi_params - structure containing + * parameters for roam offload scan based on RSSI + * @rssi_thresh: rssi threshold + * @rssi_thresh_diff: difference in rssi threshold + * @hi_rssi_scan_max_count: 5G scan max count + * @hi_rssi_scan_rssi_delta: 5G scan rssi change threshold value + * @hi_rssi_scan_rssi_ub: 5G scan upper bound + * @raise_rssi_thresh_5g: flag to determine penalty and boost thresholds + * @session_id: vdev id + * @penalty_threshold_5g: RSSI threshold below which 5GHz RSSI is penalized + * @boost_threshold_5g: RSSI threshold above which 5GHz RSSI is favored + * @raise_factor_5g: factor by which 5GHz RSSI is boosted + * @drop_factor_5g: factor by which 5GHz RSSI is penalized + * @max_raise_rssi_5g: maximum boost that can be applied to a 5GHz RSSI + * @max_drop_rssi_5g: maximum penalty that can be applied to a 5GHz RSSI + * @good_rssi_threshold: RSSI below which roam is kicked in by background + * scan although rssi is still good + * @roam_earlystop_thres_min: Minimum RSSI threshold value for early stop, + * unit is dB above NF + * @roam_earlystop_thres_max: Maximum RSSI threshold value for early stop, + * unit is dB above NF + */ +struct roam_offload_scan_rssi_params { + int8_t rssi_thresh; + uint8_t rssi_thresh_diff; + uint32_t hi_rssi_scan_max_count; + uint32_t hi_rssi_scan_rssi_delta; + int32_t hi_rssi_scan_rssi_ub; + int raise_rssi_thresh_5g; + uint8_t session_id; + uint32_t penalty_threshold_5g; + uint32_t boost_threshold_5g; + uint8_t raise_factor_5g; + uint8_t drop_factor_5g; + int max_raise_rssi_5g; + int max_drop_rssi_5g; + uint32_t good_rssi_threshold; + uint32_t roam_earlystop_thres_min; + uint32_t roam_earlystop_thres_max; +}; + /** * struct wifi_epno_network - enhanced pno network block * @ssid: ssid @@ -1314,6 +1419,9 @@ struct plm_req_params { bool enable; }; #endif +#define MAX_SSID_ALLOWED_LIST 4 +#define MAX_BSSID_AVOID_LIST 16 +#define MAX_BSSID_FAVORED 16 /** @@ -2208,6 +2316,43 @@ struct ssid_hotlist_param { int32_t rssi_high; }; +/** + * struct roam_scan_filter_params - Structure holding roaming scan + * parameters + * @len: length + * @op_bitmap: bitmap to determine reason of roaming + * @session_id: vdev id + * @num_bssid_black_list: The number of BSSID's that we should + * avoid connecting to. It is like a + * blacklist of BSSID's. + * @num_ssid_white_list: The number of SSID profiles that are + * in the Whitelist. When roaming, we + * consider the BSSID's with this SSID + * also for roaming apart from the connected one's + * @num_bssid_preferred_list: Number of BSSID's which have a preference over + * others + * @bssid_avoid_list: Blacklist SSID's + * @ssid_allowed_list: Whitelist SSID's + * @bssid_favored: Favorable BSSID's + * @bssid_favored_factor: RSSI to be added to this BSSID to prefer it + * + * This structure holds all the key parameters related to + * initial connection and roaming connections. + */ + +struct roam_scan_filter_params { + uint32_t len; + uint32_t op_bitmap; + uint8_t session_id; + uint32_t num_bssid_black_list; + uint32_t num_ssid_white_list; + uint32_t num_bssid_preferred_list; + struct qdf_mac_addr bssid_avoid_list[MAX_BSSID_AVOID_LIST]; + struct mac_ssid ssid_allowed_list[MAX_SSID_ALLOWED_LIST]; + struct qdf_mac_addr bssid_favored[MAX_BSSID_FAVORED]; + uint8_t bssid_favored_factor[MAX_BSSID_FAVORED]; +}; + /** * struct ssid_hotlist_request_params - set SSID hotlist request struct * @request_id: ID of the request diff --git a/wmi/inc/wmi_unified_priv.h b/wmi/inc/wmi_unified_priv.h index 0e6a6603dd..a1df724969 100644 --- a/wmi/inc/wmi_unified_priv.h +++ b/wmi/inc/wmi_unified_priv.h @@ -272,6 +272,16 @@ QDF_STATUS (*send_scan_probe_setoui_cmd)(wmi_unified_t wmi_handle, QDF_STATUS (*send_reset_passpoint_network_list_cmd)(wmi_unified_t wmi_handle, struct wifi_passpoint_req_param *req); +QDF_STATUS (*send_roam_scan_offload_mode_cmd)(wmi_unified_t wmi_handle, + wmi_start_scan_cmd_fixed_param *scan_cmd_fp, + struct roam_offload_scan_params *roam_req); + +QDF_STATUS (*send_roam_scan_offload_rssi_thresh_cmd)(wmi_unified_t wmi_handle, + struct roam_offload_scan_rssi_params *roam_req); + +QDF_STATUS (*send_roam_scan_filter_cmd)(wmi_unified_t wmi_handle, + struct roam_scan_filter_params *roam_req); + QDF_STATUS (*send_set_passpoint_network_list_cmd)(wmi_unified_t wmi_handle, struct wifi_passpoint_req_param *req); diff --git a/wmi/inc/wmi_unified_tlv.h b/wmi/inc/wmi_unified_tlv.h index c8418d197b..7387ba4624 100644 --- a/wmi/inc/wmi_unified_tlv.h +++ b/wmi/inc/wmi_unified_tlv.h @@ -240,6 +240,16 @@ QDF_STATUS send_reset_passpoint_network_list_cmd_tlv(wmi_unified_t wmi_handle, QDF_STATUS send_set_passpoint_network_list_cmd_tlv(wmi_unified_t wmi_handle, struct wifi_passpoint_req_param *req); +QDF_STATUS send_roam_scan_offload_mode_cmd_tlv(wmi_unified_t wmi_handle, + wmi_start_scan_cmd_fixed_param *scan_cmd_fp, + struct roam_offload_scan_params *roam_req); + +QDF_STATUS send_roam_scan_offload_rssi_thresh_cmd_tlv(wmi_unified_t wmi_handle, + struct roam_offload_scan_rssi_params *roam_req); + +QDF_STATUS send_roam_scan_filter_cmd_tlv(wmi_unified_t wmi_handle, + struct roam_scan_filter_params *roam_req); + QDF_STATUS send_set_ric_req_cmd_tlv(wmi_unified_t wmi_handle, void *msg, uint8_t is_add_ts); diff --git a/wmi/src/wmi_unified_api.c b/wmi/src/wmi_unified_api.c index 464b9a9615..f08c27ffda 100644 --- a/wmi/src/wmi_unified_api.c +++ b/wmi/src/wmi_unified_api.c @@ -1322,6 +1322,77 @@ QDF_STATUS wmi_unified_set_epno_network_list_cmd(void *wmi_hdl, return QDF_STATUS_E_FAILURE; } +/** + * wmi_unified_roam_scan_offload_mode_cmd() - set roam scan parameters + * @wmi_hdl: wmi handle + * @scan_cmd_fp: scan related parameters + * @roam_req: roam related parameters + * + * This function reads the incoming @roam_req and fill in the destination + * WMI structure and send down the roam scan configs down to the firmware + * + * Return: QDF_STATUS enumeration + */ +QDF_STATUS wmi_unified_roam_scan_offload_mode_cmd(void *wmi_hdl, + wmi_start_scan_cmd_fixed_param *scan_cmd_fp, + struct roam_offload_scan_params *roam_req) +{ + wmi_unified_t wmi_handle = (wmi_unified_t) wmi_hdl; + + if (wmi_handle->ops->send_roam_scan_offload_mode_cmd) + return wmi_handle->ops->send_roam_scan_offload_mode_cmd( + wmi_handle, scan_cmd_fp, roam_req); + + return QDF_STATUS_E_FAILURE; +} + +/** + * wmi_unified_roam_scan_offload_rssi_thresh_cmd() - set roam scan rssi + * parameters + * @wmi_hdl: wmi handle + * @roam_req: roam rssi related parameters + * + * This function reads the incoming @roam_req and fill in the destination + * WMI structure and send down the roam scan rssi configs down to the firmware + * + * Return: QDF_STATUS enumeration + */ +QDF_STATUS wmi_unified_roam_scan_offload_rssi_thresh_cmd(void *wmi_hdl, + struct roam_offload_scan_rssi_params + *roam_req) +{ + wmi_unified_t wmi_handle = (wmi_unified_t) wmi_hdl; + + if (wmi_handle->ops->send_roam_scan_offload_rssi_thresh_cmd) + return wmi_handle->ops->send_roam_scan_offload_rssi_thresh_cmd( + wmi_handle, roam_req); + + return QDF_STATUS_E_FAILURE; +} + +/** + * wmi_unified_roam_scan_filter_cmd() - send roam scan whitelist, + * blacklist and preferred list + * @wmi_hdl: wmi handle + * @roam_req: roam scan lists related parameters + * + * This function reads the incoming @roam_req and fill in the destination + * WMI structure and send down the different roam scan lists down to the fw + * + * Return: QDF_STATUS enumeration + */ +QDF_STATUS wmi_unified_roam_scan_filter_cmd(void *wmi_hdl, + struct roam_scan_filter_params *roam_req) +{ + wmi_unified_t wmi_handle = (wmi_unified_t) wmi_hdl; + + if (wmi_handle->ops->send_roam_scan_filter_cmd) + return wmi_handle->ops->send_roam_scan_filter_cmd( + wmi_handle, roam_req); + + return QDF_STATUS_E_FAILURE; +} + /** wmi_unified_ipa_offload_control_cmd() - ipa offload control parameter * @wmi_hdl: wmi handle * @ipa_offload: ipa offload control parameter diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index 3955d2e876..118bd50949 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -3536,6 +3536,505 @@ QDF_STATUS send_set_passpoint_network_list_cmd_tlv(wmi_unified_t wmi_handle, return QDF_STATUS_SUCCESS; } +/** + * send_roam_scan_offload_mode_cmd_tlv() - send roam scan mode request to fw + * @wmi_handle: wmi handle + * @scan_cmd_fp: start scan command ptr + * @roam_req: roam request param + * + * send WMI_ROAM_SCAN_MODE TLV to firmware. It has a piggyback + * of WMI_ROAM_SCAN_MODE. + * + * Return: QDF status + */ +QDF_STATUS send_roam_scan_offload_mode_cmd_tlv(wmi_unified_t wmi_handle, + wmi_start_scan_cmd_fixed_param * + scan_cmd_fp, + struct roam_offload_scan_params *roam_req) +{ + wmi_buf_t buf = NULL; + int status = 0; + int len; + uint8_t *buf_ptr; + wmi_roam_scan_mode_fixed_param *roam_scan_mode_fp; +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + int auth_mode = roam_req->auth_mode; + wmi_roam_offload_tlv_param *roam_offload_params; + wmi_roam_11i_offload_tlv_param *roam_offload_11i; + wmi_roam_11r_offload_tlv_param *roam_offload_11r; + wmi_roam_ese_offload_tlv_param *roam_offload_ese; +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + /* Need to create a buf with roam_scan command at + * front and piggyback with scan command */ + len = sizeof(wmi_roam_scan_mode_fixed_param) + +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + (2 * WMI_TLV_HDR_SIZE) + +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + sizeof(wmi_start_scan_cmd_fixed_param); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + if (roam_req->is_roam_req_valid && + roam_req->roam_offload_enabled) { + len += sizeof(wmi_roam_offload_tlv_param); + len += WMI_TLV_HDR_SIZE; + if ((auth_mode != WMI_AUTH_NONE) && + ((auth_mode != WMI_AUTH_OPEN) || + (auth_mode == WMI_AUTH_OPEN && + roam_req->mdid.mdie_present) || + roam_req->is_ese_assoc)) { + len += WMI_TLV_HDR_SIZE; + if (roam_req->is_ese_assoc) + len += + sizeof(wmi_roam_ese_offload_tlv_param); + else if (auth_mode == WMI_AUTH_FT_RSNA || + auth_mode == WMI_AUTH_FT_RSNA_PSK || + (auth_mode == WMI_AUTH_OPEN && + roam_req->mdid.mdie_present)) + len += + sizeof(wmi_roam_11r_offload_tlv_param); + else + len += + sizeof(wmi_roam_11i_offload_tlv_param); + } else { + len += WMI_TLV_HDR_SIZE; + } + } else { + if (roam_req->is_roam_req_valid) + WMA_LOGD("%s : roam offload = %d", + __func__, roam_req->roam_offload_enabled); + else + WMA_LOGD("%s : roam_req is NULL", __func__); + len += (2 * WMI_TLV_HDR_SIZE); + } + if (roam_req->is_roam_req_valid && + roam_req->roam_offload_enabled) { + roam_req->mode = roam_req->mode | + WMI_ROAM_SCAN_MODE_ROAMOFFLOAD; + } +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return QDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_t *) wmi_buf_data(buf); + roam_scan_mode_fp = (wmi_roam_scan_mode_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&roam_scan_mode_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_scan_mode_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_roam_scan_mode_fixed_param)); + + roam_scan_mode_fp->roam_scan_mode = roam_req->mode; + roam_scan_mode_fp->vdev_id = roam_req->vdev_id; + /* Fill in scan parameters suitable for roaming scan */ + buf_ptr += sizeof(wmi_roam_scan_mode_fixed_param); + qdf_mem_copy(buf_ptr, scan_cmd_fp, + sizeof(wmi_start_scan_cmd_fixed_param)); + /* Ensure there is no additional IEs */ + scan_cmd_fp->ie_len = 0; + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_STRUC_wmi_start_scan_cmd_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_start_scan_cmd_fixed_param)); +#ifdef WLAN_FEATURE_ROAM_OFFLOAD + buf_ptr += sizeof(wmi_start_scan_cmd_fixed_param); + if (roam_req->is_roam_req_valid && roam_req->roam_offload_enabled) { + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_roam_offload_tlv_param)); + buf_ptr += WMI_TLV_HDR_SIZE; + roam_offload_params = (wmi_roam_offload_tlv_param *) buf_ptr; + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_STRUC_wmi_roam_offload_tlv_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_roam_offload_tlv_param)); + roam_offload_params->prefer_5g = roam_req->prefer_5ghz; + roam_offload_params->rssi_cat_gap = roam_req->roam_rssi_cat_gap; + roam_offload_params->select_5g_margin = + roam_req->select_5ghz_margin; + roam_offload_params->reassoc_failure_timeout = + roam_req->reassoc_failure_timeout; + + /* Fill the capabilities */ + roam_offload_params->capability = + roam_req->roam_offload_params.capability; + roam_offload_params->ht_caps_info = + roam_req->roam_offload_params.ht_caps_info; + roam_offload_params->ampdu_param = + roam_req->roam_offload_params.ampdu_param; + roam_offload_params->ht_ext_cap = + roam_req->roam_offload_params.ht_ext_cap; + roam_offload_params->ht_txbf = + roam_req->roam_offload_params.ht_txbf; + roam_offload_params->asel_cap = + roam_req->roam_offload_params.asel_cap; + roam_offload_params->qos_caps = + roam_req->roam_offload_params.qos_caps; + roam_offload_params->wmm_caps = + roam_req->roam_offload_params.wmm_caps; + qdf_mem_copy((uint8_t *)roam_offload_params->mcsset, + (uint8_t *)roam_req->roam_offload_params.mcsset, + ROAM_OFFLOAD_NUM_MCS_SET); + + buf_ptr += sizeof(wmi_roam_offload_tlv_param); + /* The TLV's are in the order of 11i, 11R, ESE. Hence, + * they are filled in the same order.Depending on the + * authentication type, the other mode TLV's are nullified + * and only headers are filled.*/ + if ((auth_mode != WMI_AUTH_NONE) && + ((auth_mode != WMI_AUTH_OPEN) || + (auth_mode == WMI_AUTH_OPEN + && roam_req->mdid.mdie_present) || + roam_req->is_ese_assoc)) { + if (roam_req->is_ese_assoc) { + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_roam_ese_offload_tlv_param)); + buf_ptr += WMI_TLV_HDR_SIZE; + roam_offload_ese = + (wmi_roam_ese_offload_tlv_param *) buf_ptr; + qdf_mem_copy(roam_offload_ese->krk, + roam_req->krk, + sizeof(roam_req->krk)); + qdf_mem_copy(roam_offload_ese->btk, + roam_req->btk, + sizeof(roam_req->btk)); + WMITLV_SET_HDR(&roam_offload_ese->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_ese_offload_tlv_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_roam_ese_offload_tlv_param)); + buf_ptr += + sizeof(wmi_roam_ese_offload_tlv_param); + } else if (auth_mode == WMI_AUTH_FT_RSNA + || auth_mode == WMI_AUTH_FT_RSNA_PSK + || (auth_mode == WMI_AUTH_OPEN + && roam_req->mdid.mdie_present)) { + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + 0); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_roam_11r_offload_tlv_param)); + buf_ptr += WMI_TLV_HDR_SIZE; + roam_offload_11r = + (wmi_roam_11r_offload_tlv_param *) buf_ptr; + roam_offload_11r->r0kh_id_len = + roam_req->rokh_id_length; + qdf_mem_copy(roam_offload_11r->r0kh_id, + roam_req->rokh_id, + roam_offload_11r->r0kh_id_len); + qdf_mem_copy(roam_offload_11r->psk_msk, + roam_req->psk_pmk, + sizeof(roam_req->psk_pmk)); + roam_offload_11r->psk_msk_len = + roam_req->pmk_len; + roam_offload_11r->mdie_present = + roam_req->mdid.mdie_present; + roam_offload_11r->mdid = + roam_req->mdid.mobility_domain; + if (auth_mode == WMI_AUTH_OPEN) { + /* If FT-Open ensure pmk length + and r0khid len are zero */ + roam_offload_11r->r0kh_id_len = 0; + roam_offload_11r->psk_msk_len = 0; + } + WMITLV_SET_HDR(&roam_offload_11r->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_11r_offload_tlv_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_roam_11r_offload_tlv_param)); + buf_ptr += + sizeof(wmi_roam_11r_offload_tlv_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + } else { + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_roam_11i_offload_tlv_param)); + buf_ptr += WMI_TLV_HDR_SIZE; + roam_offload_11i = + (wmi_roam_11i_offload_tlv_param *) buf_ptr; + if (roam_req->roam_key_mgmt_offload_enabled) { + WMI_SET_ROAM_OFFLOAD_OKC_ENABLED + (roam_offload_11i->flags); + WMA_LOGE("LFR3:OKC Enabled"); + } else { + WMI_SET_ROAM_OFFLOAD_OKC_DISABLED + (roam_offload_11i->flags); + WMA_LOGE("LFR3:OKC Disabled"); + } + + qdf_mem_copy(roam_offload_11i->pmk, + roam_req->psk_pmk, + sizeof(roam_req->psk_pmk)); + roam_offload_11i->pmk_len = roam_req->pmk_len; + WMITLV_SET_HDR(&roam_offload_11i->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_11i_offload_tlv_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_roam_11i_offload_tlv_param)); + buf_ptr += + sizeof(wmi_roam_11i_offload_tlv_param); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + 0); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + 0); + buf_ptr += WMI_TLV_HDR_SIZE; + } + } else { + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + } + } else { + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + buf_ptr += WMI_TLV_HDR_SIZE; + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_STRUC, + WMITLV_GET_STRUCT_TLVLEN(0)); + } +#endif /* WLAN_FEATURE_ROAM_OFFLOAD */ + status = wmi_unified_cmd_send(wmi_handle, buf, + len, WMI_ROAM_SCAN_MODE); + if (status != EOK) { + WMA_LOGE( + "wmi_unified_cmd_send WMI_ROAM_SCAN_MODE returned Error %d", + status); + wmi_buf_free(buf); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + + +/** + * send_roam_scan_offload_rssi_thresh_cmd_tlv() - set scan offload + * rssi threashold + * @wmi_handle: wmi handle + * @roam_req: Roaming request buffer + * + * Send WMI_ROAM_SCAN_RSSI_THRESHOLD TLV to firmware + * + * Return: QDF status + */ +QDF_STATUS send_roam_scan_offload_rssi_thresh_cmd_tlv(wmi_unified_t wmi_handle, + struct roam_offload_scan_rssi_params *roam_req) +{ + wmi_buf_t buf = NULL; + int status = 0; + int len; + uint8_t *buf_ptr; + wmi_roam_scan_rssi_threshold_fixed_param *rssi_threshold_fp; + wmi_roam_scan_extended_threshold_param *ext_thresholds = NULL; + wmi_roam_earlystop_rssi_thres_param *early_stop_thresholds = NULL; + + + len = sizeof(wmi_roam_scan_rssi_threshold_fixed_param); + len += WMI_TLV_HDR_SIZE; /* TLV for ext_thresholds*/ + len += sizeof(wmi_roam_scan_extended_threshold_param); + len += WMI_TLV_HDR_SIZE; + len += sizeof(wmi_roam_earlystop_rssi_thres_param); + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return QDF_STATUS_E_NOMEM; + } + + buf_ptr = (uint8_t *) wmi_buf_data(buf); + rssi_threshold_fp = + (wmi_roam_scan_rssi_threshold_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&rssi_threshold_fp->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_scan_rssi_threshold_fixed_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_roam_scan_rssi_threshold_fixed_param)); + /* fill in threshold values */ + rssi_threshold_fp->vdev_id = roam_req->session_id; + rssi_threshold_fp->roam_scan_rssi_thresh = roam_req->rssi_thresh; + rssi_threshold_fp->roam_rssi_thresh_diff = roam_req->rssi_thresh_diff; + rssi_threshold_fp->hirssi_scan_max_count = + roam_req->hi_rssi_scan_max_count; + rssi_threshold_fp->hirssi_scan_delta = + roam_req->hi_rssi_scan_rssi_delta; + rssi_threshold_fp->hirssi_upper_bound = roam_req->hi_rssi_scan_rssi_ub; + + buf_ptr += sizeof(wmi_roam_scan_rssi_threshold_fixed_param); + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_roam_scan_extended_threshold_param)); + buf_ptr += WMI_TLV_HDR_SIZE; + ext_thresholds = (wmi_roam_scan_extended_threshold_param *) buf_ptr; + + ext_thresholds->penalty_threshold_5g = roam_req->penalty_threshold_5g; + if (roam_req->raise_rssi_thresh_5g >= WMI_NOISE_FLOOR_DBM_DEFAULT) + ext_thresholds->boost_threshold_5g = + roam_req->boost_threshold_5g; + + ext_thresholds->boost_algorithm_5g = + WMI_ROAM_5G_BOOST_PENALIZE_ALGO_LINEAR; + ext_thresholds->boost_factor_5g = roam_req->raise_factor_5g; + ext_thresholds->penalty_algorithm_5g = + WMI_ROAM_5G_BOOST_PENALIZE_ALGO_LINEAR; + ext_thresholds->penalty_factor_5g = roam_req->drop_factor_5g; + ext_thresholds->max_boost_5g = roam_req->max_raise_rssi_5g; + ext_thresholds->max_penalty_5g = roam_req->max_drop_rssi_5g; + ext_thresholds->good_rssi_threshold = roam_req->good_rssi_threshold; + + WMITLV_SET_HDR(&ext_thresholds->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_scan_extended_threshold_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_roam_scan_extended_threshold_param)); + buf_ptr += sizeof(wmi_roam_scan_extended_threshold_param); + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_STRUC, + sizeof(wmi_roam_earlystop_rssi_thres_param)); + buf_ptr += WMI_TLV_HDR_SIZE; + early_stop_thresholds = (wmi_roam_earlystop_rssi_thres_param *) buf_ptr; + early_stop_thresholds->roam_earlystop_thres_min = + roam_req->roam_earlystop_thres_min; + early_stop_thresholds->roam_earlystop_thres_max = + roam_req->roam_earlystop_thres_max; + WMITLV_SET_HDR(&early_stop_thresholds->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_earlystop_rssi_thres_param, + WMITLV_GET_STRUCT_TLVLEN + (wmi_roam_earlystop_rssi_thres_param)); + + status = wmi_unified_cmd_send(wmi_handle, buf, + len, WMI_ROAM_SCAN_RSSI_THRESHOLD); + if (status != EOK) { + WMA_LOGE("cmd WMI_ROAM_SCAN_RSSI_THRESHOLD returned Error %d", + status); + wmi_buf_free(buf); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} + +/** + * send_roam_scan_filter_cmd_tlv() - Filter to be applied while roaming + * @wmi_handle: wmi handle + * @roam_req: Request which contains the filters + * + * There are filters such as whitelist, blacklist and preferred + * list that need to be applied to the scan results to form the + * probable candidates for roaming. + * + * Return: Return success upon succesfully passing the + * parameters to the firmware, otherwise failure. + */ +QDF_STATUS send_roam_scan_filter_cmd_tlv(wmi_unified_t wmi_handle, + struct roam_scan_filter_params *roam_req) +{ + wmi_buf_t buf = NULL; + int status = 0, i; + uint32_t len; + uint8_t *buf_ptr; + wmi_roam_filter_fixed_param *roam_filter; + uint8_t *bssid_src_ptr = NULL; + wmi_mac_addr *bssid_dst_ptr = NULL; + wmi_ssid *ssid_ptr = NULL; + uint32_t *bssid_preferred_factor_ptr = NULL; + + len = sizeof(wmi_roam_filter_fixed_param); + len += WMI_TLV_HDR_SIZE; + len += roam_req->len; + + buf = wmi_buf_alloc(wmi_handle, len); + if (!buf) { + WMA_LOGE("%s : wmi_buf_alloc failed", __func__); + return QDF_STATUS_E_NOMEM; + } + + buf_ptr = (u_int8_t *) wmi_buf_data(buf); + roam_filter = (wmi_roam_filter_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&roam_filter->tlv_header, + WMITLV_TAG_STRUC_wmi_roam_filter_fixed_param, + WMITLV_GET_STRUCT_TLVLEN(wmi_roam_filter_fixed_param)); + /* fill in fixed values */ + roam_filter->vdev_id = roam_req->session_id; + roam_filter->flags = 0; + roam_filter->op_bitmap = roam_req->op_bitmap; + roam_filter->num_bssid_black_list = roam_req->num_bssid_black_list; + roam_filter->num_ssid_white_list = roam_req->num_ssid_white_list; + roam_filter->num_bssid_preferred_list = + roam_req->num_bssid_preferred_list; + buf_ptr += sizeof(wmi_roam_filter_fixed_param); + + WMITLV_SET_HDR((buf_ptr), + WMITLV_TAG_ARRAY_FIXED_STRUC, + (roam_req->num_bssid_black_list * sizeof(wmi_mac_addr))); + bssid_src_ptr = (uint8_t *)&roam_req->bssid_avoid_list; + bssid_dst_ptr = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE); + for (i = 0; i < roam_req->num_bssid_black_list; i++) { + WMI_CHAR_ARRAY_TO_MAC_ADDR(bssid_src_ptr, bssid_dst_ptr); + bssid_src_ptr += ATH_MAC_LEN; + bssid_dst_ptr++; + } + buf_ptr += WMI_TLV_HDR_SIZE + + (roam_req->num_bssid_black_list * sizeof(wmi_mac_addr)); + WMITLV_SET_HDR((buf_ptr), + WMITLV_TAG_ARRAY_FIXED_STRUC, + (roam_req->num_ssid_white_list * sizeof(wmi_ssid))); + ssid_ptr = (wmi_ssid *)(buf_ptr + WMI_TLV_HDR_SIZE); + for (i = 0; i < roam_req->num_ssid_white_list; i++) { + qdf_mem_copy(&ssid_ptr->ssid, + &roam_req->ssid_allowed_list[i].mac_ssid, + roam_req->ssid_allowed_list[i].length); + ssid_ptr->ssid_len = roam_req->ssid_allowed_list[i].length; + ssid_ptr++; + } + buf_ptr += WMI_TLV_HDR_SIZE + (roam_req->num_ssid_white_list * + sizeof(wmi_ssid)); + WMITLV_SET_HDR((buf_ptr), + WMITLV_TAG_ARRAY_FIXED_STRUC, + (roam_req->num_bssid_preferred_list * sizeof(wmi_mac_addr))); + bssid_src_ptr = (uint8_t *)&roam_req->bssid_favored; + bssid_dst_ptr = (wmi_mac_addr *)(buf_ptr + WMI_TLV_HDR_SIZE); + for (i = 0; i < roam_req->num_bssid_preferred_list; i++) { + WMI_CHAR_ARRAY_TO_MAC_ADDR(bssid_src_ptr, + (wmi_mac_addr *)bssid_dst_ptr); + bssid_src_ptr += ATH_MAC_LEN; + bssid_dst_ptr++; + } + buf_ptr += WMI_TLV_HDR_SIZE + + (roam_req->num_bssid_preferred_list * sizeof(wmi_mac_addr)); + WMITLV_SET_HDR(buf_ptr, WMITLV_TAG_ARRAY_UINT32, + (roam_req->num_bssid_preferred_list * sizeof(uint32_t))); + bssid_preferred_factor_ptr = (uint32_t *)(buf_ptr + WMI_TLV_HDR_SIZE); + for (i = 0; i < roam_req->num_bssid_preferred_list; i++) { + *bssid_preferred_factor_ptr = + roam_req->bssid_favored_factor[i]; + bssid_preferred_factor_ptr++; + } + buf_ptr += WMI_TLV_HDR_SIZE + + (roam_req->num_bssid_preferred_list * sizeof(uint32_t)); + + status = wmi_unified_cmd_send(wmi_handle, buf, + len, WMI_ROAM_FILTER_CMDID); + if (status != EOK) { + WMA_LOGE("cmd WMI_ROAM_FILTER_CMDID returned Error %d", + status); + wmi_buf_free(buf); + return QDF_STATUS_E_FAILURE; + } + return QDF_STATUS_SUCCESS; +} + /** send_set_epno_network_list_cmd_tlv() - set epno network list * @wmi_handle: wmi handle * @req: epno config params request structure @@ -9579,6 +10078,12 @@ struct wmi_ops tlv_ops = { send_reset_passpoint_network_list_cmd_tlv, .send_set_passpoint_network_list_cmd = send_set_passpoint_network_list_cmd_tlv, + .send_roam_scan_offload_mode_cmd = + send_roam_scan_offload_mode_cmd_tlv, + .send_roam_scan_offload_rssi_thresh_cmd = + send_roam_scan_offload_rssi_thresh_cmd_tlv, + .send_roam_scan_filter_cmd = + send_roam_scan_filter_cmd_tlv, .send_set_epno_network_list_cmd = send_set_epno_network_list_cmd_tlv, .send_ipa_offload_control_cmd =