From 77dd1efb64f4dd34bff01369e9a405a0c1908483 Mon Sep 17 00:00:00 2001 From: Sreelakshmi Konamki Date: Fri, 21 Jul 2017 17:37:30 +0530 Subject: [PATCH] qcacmn: Add support for PNO scan in connected state qcacld-2.0 to qcacmn propagation Add changes to support PNO scan in connected state to find better Ap's based on rssi threshold, band and rssi preference. Change-Id: I0744297cc5269f0fe37613247c911102e293d8e9 CRs-Fixed: 2000342 --- os_if/linux/scan/src/wlan_cfg80211_scan.c | 69 +++++++++---------- .../dispatcher/inc/wlan_scan_public_structs.h | 18 +++++ wmi/src/wmi_unified_tlv.c | 49 ++++++++++++- 3 files changed, 97 insertions(+), 39 deletions(-) diff --git a/os_if/linux/scan/src/wlan_cfg80211_scan.c b/os_if/linux/scan/src/wlan_cfg80211_scan.c index 298ca2c36d..24bf613c1d 100644 --- a/os_if/linux/scan/src/wlan_cfg80211_scan.c +++ b/os_if/linux/scan/src/wlan_cfg80211_scan.c @@ -234,37 +234,6 @@ static void wlan_cfg80211_pno_callback(struct wlan_objmgr_vdev *vdev, cfg80211_sched_scan_results(pdev_ospriv->wiphy); } -/** - * wlan_cfg80211_is_pno_allowed() - Check if PNO is allowed - * @vdev: vdev ptr - * - * The PNO Start request is coming from upper layers. - * It is to be allowed only for Infra STA device type - * and the link should be in a disconnected state. - * - * Return: Success if PNO is allowed, Failure otherwise. - */ -static QDF_STATUS wlan_cfg80211_is_pno_allowed(struct wlan_objmgr_vdev *vdev) -{ - enum wlan_vdev_state state; - enum tQDF_ADAPTER_MODE vdev_opmode; - uint8_t vdev_id; - - vdev_opmode = wlan_vdev_mlme_get_opmode(vdev); - state = wlan_vdev_mlme_get_state(vdev); - vdev_id = wlan_vdev_get_id(vdev); - - cfg80211_notice("dev_mode=%d, state=%d vdev id %d", - vdev_opmode, state, vdev_id); - - if ((vdev_opmode == QDF_STA_MODE) && - ((state == WLAN_VDEV_S_INIT) || - (state == WLAN_VDEV_S_STOP))) - return QDF_STATUS_SUCCESS; - else - return QDF_STATUS_E_FAILURE; -} - #ifdef WLAN_POLICY_MGR_ENABLE static bool wlan_cfg80211_is_ap_go_present(struct wlan_objmgr_psoc *psoc) { @@ -354,6 +323,36 @@ static void wlan_pno_scan_rand_attr(struct wlan_objmgr_vdev *vdev, } #endif +/** + * wlan_hdd_sched_scan_update_relative_rssi() - update CPNO params + * @pno_request: pointer to PNO scan request + * @request: Pointer to cfg80211 scheduled scan start request + * + * This function is used to update Connected PNO params sent by kernel + * + * Return: None + */ +#if defined(CFG80211_REPORT_BETTER_BSS_IN_SCHED_SCAN) +static inline void wlan_hdd_sched_scan_update_relative_rssi( + struct pno_scan_req_params *pno_request, + struct cfg80211_sched_scan_request *request) +{ + pno_request->relative_rssi_set = request->relative_rssi_set; + pno_request->relative_rssi = request->relative_rssi; + if (NL80211_BAND_2GHZ == request->rssi_adjust.band) + pno_request->band_rssi_pref.band = WLAN_BAND_2_4_GHZ; + else if (NL80211_BAND_5GHZ == request->rssi_adjust.band) + pno_request->band_rssi_pref.band = WLAN_BAND_5_GHZ; + pno_request->band_rssi_pref.rssi = request->rssi_adjust.delta; +} +#else +static inline void wlan_hdd_sched_scan_update_relative_rssi( + struct pno_scan_req_params *pno_request, + struct cfg80211_sched_scan_request *request) +{ +} +#endif + int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_pdev *pdev, struct net_device *dev, struct cfg80211_sched_scan_request *request, @@ -374,13 +373,6 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_pdev *pdev, return -EIO; } - status = wlan_cfg80211_is_pno_allowed(vdev); - if (QDF_IS_STATUS_ERROR(status)) { - cfg80211_err("pno is not allowed"); - wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID); - return -ENOTSUPP; - } - if (ucfg_scan_get_pno_in_progress(vdev)) { cfg80211_debug("pno is already in progress"); wlan_objmgr_vdev_release_ref(vdev, WLAN_OSIF_ID); @@ -544,6 +536,7 @@ int wlan_cfg80211_sched_scan_start(struct wlan_objmgr_pdev *pdev, cfg80211_notice("Base scan interval: %d sec, scan cycles: %d, slow scan interval %d", req->fast_scan_period, req->fast_scan_max_cycles, req->slow_scan_period); + wlan_hdd_sched_scan_update_relative_rssi(req, request); psoc = wlan_pdev_get_psoc(pdev); ucfg_scan_register_pno_cb(psoc, diff --git a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h index 4759db8de9..0afd9c23d5 100644 --- a/umac/scan/dispatcher/inc/wlan_scan_public_structs.h +++ b/umac/scan/dispatcher/inc/wlan_scan_public_structs.h @@ -916,6 +916,17 @@ struct pno_nw_type { int32_t rssi_thresh; }; +/** + * struct connected_pno_band_rssi_pref - BSS preference based on band + * and RSSI + * @band: band preference + * @rssi_pref: RSSI preference + */ +struct cpno_band_rssi_pref { + int8_t band; + int8_t rssi; +}; + /** * struct pno_scan_req_params - PNO Scan request structure * @networks_cnt: Number of networks @@ -937,6 +948,10 @@ struct pno_nw_type { * @networks_list: Preferred network list * @scan_random: scan randomization params * @ie_whitelist: probe req IE whitelist attrs + * @relative_rssi_set: Flag to check whether realtive_rssi is set or not + * @relative_rssi: Relative rssi threshold, used for connected pno + * @band_rssi_pref: Band and RSSI preference that can be given to one BSS + * over the other BSS * * E.g. * { fast_scan_period=120, fast_scan_max_cycles=2, @@ -961,6 +976,9 @@ struct pno_scan_req_params { struct pno_nw_type networks_list[SCAN_PNO_MAX_SUPP_NETWORKS]; struct scan_random_attr scan_random; struct probe_req_whitelist_attr ie_whitelist; + bool relative_rssi_set; + int8_t relative_rssi; + struct cpno_band_rssi_pref band_rssi_pref; }; /** diff --git a/wmi/src/wmi_unified_tlv.c b/wmi/src/wmi_unified_tlv.c index b315b4bd11..88db385647 100644 --- a/wmi/src/wmi_unified_tlv.c +++ b/wmi/src/wmi_unified_tlv.c @@ -7465,16 +7465,19 @@ static QDF_STATUS send_pno_start_cmd_tlv(wmi_unified_t wmi_handle, uint8_t i; int ret; struct probe_req_whitelist_attr *ie_whitelist = &pno->ie_whitelist; + connected_nlo_rssi_params *nlo_relative_rssi; + connected_nlo_bss_band_rssi_pref *nlo_band_rssi; /* * TLV place holder for array nlo_configured_parameters(nlo_list) * TLV place holder for array of uint32_t channel_list * TLV place holder for chnnl prediction cfg * TLV place holder for array of wmi_vendor_oui + * TLV place holder for array of connected_nlo_bss_band_rssi_pref */ len = sizeof(*cmd) + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE + - WMI_TLV_HDR_SIZE; + WMI_TLV_HDR_SIZE + WMI_TLV_HDR_SIZE; len += sizeof(uint32_t) * QDF_MIN(pno->networks_list[0].channel_cnt, WMI_NLO_MAX_CHAN); @@ -7483,6 +7486,8 @@ static QDF_STATUS send_pno_start_cmd_tlv(wmi_unified_t wmi_handle, len += sizeof(nlo_channel_prediction_cfg); len += sizeof(enlo_candidate_score_params); len += sizeof(wmi_vendor_oui) * ie_whitelist->num_vendor_oui; + len += sizeof(connected_nlo_rssi_params); + len += sizeof(connected_nlo_bss_band_rssi_pref); buf = wmi_buf_alloc(wmi_handle, len); if (!buf) { @@ -7621,6 +7626,48 @@ static QDF_STATUS send_pno_start_cmd_tlv(wmi_unified_t wmi_handle, buf_ptr += cmd->num_vendor_oui * sizeof(wmi_vendor_oui); } + if (pno->relative_rssi_set) + cmd->flags |= WMI_NLO_CONFIG_ENABLE_CNLO_RSSI_CONFIG; + + /* + * Firmware calculation using connected PNO params: + * New AP's RSSI >= (Connected AP's RSSI + relative_rssi +/- rssi_pref) + * deduction of rssi_pref for chosen band_pref and + * addition of rssi_pref for remaining bands (other than chosen band). + */ + nlo_relative_rssi = (connected_nlo_rssi_params *) buf_ptr; + WMITLV_SET_HDR(&nlo_relative_rssi->tlv_header, + WMITLV_TAG_STRUC_wmi_connected_nlo_rssi_params, + WMITLV_GET_STRUCT_TLVLEN(connected_nlo_rssi_params)); + nlo_relative_rssi->relative_rssi = pno->relative_rssi; + WMI_LOGD("relative_rssi %d", nlo_relative_rssi->relative_rssi); + buf_ptr += sizeof(*nlo_relative_rssi); + + /* + * As of now Kernel and Host supports one band and rssi preference. + * Firmware supports array of band and rssi preferences + */ + cmd->num_cnlo_band_pref = 1; + WMITLV_SET_HDR(buf_ptr, + WMITLV_TAG_ARRAY_STRUC, + cmd->num_cnlo_band_pref * + sizeof(connected_nlo_bss_band_rssi_pref)); + buf_ptr += WMI_TLV_HDR_SIZE; + + nlo_band_rssi = (connected_nlo_bss_band_rssi_pref *) buf_ptr; + for (i = 0; i < cmd->num_cnlo_band_pref; i++) { + WMITLV_SET_HDR(&nlo_band_rssi[i].tlv_header, + WMITLV_TAG_STRUC_wmi_connected_nlo_bss_band_rssi_pref, + WMITLV_GET_STRUCT_TLVLEN( + connected_nlo_bss_band_rssi_pref)); + nlo_band_rssi[i].band = pno->band_rssi_pref.band; + nlo_band_rssi[i].rssi_pref = pno->band_rssi_pref.rssi; + WMI_LOGI("band_pref %d, rssi_pref %d", + nlo_band_rssi[i].band, + nlo_band_rssi[i].rssi_pref); + } + buf_ptr += cmd->num_cnlo_band_pref * sizeof(*nlo_band_rssi); + ret = wmi_unified_cmd_send(wmi_handle, buf, len, WMI_NETWORK_LIST_OFFLOAD_CONFIG_CMDID); if (ret) {