diff --git a/core/hdd/inc/wlan_hdd_cfg.h b/core/hdd/inc/wlan_hdd_cfg.h index 6dde98b0af33..5e34ee250f81 100644 --- a/core/hdd/inc/wlan_hdd_cfg.h +++ b/core/hdd/inc/wlan_hdd_cfg.h @@ -3482,6 +3482,11 @@ enum dot11p_mode { #define CFG_SIFS_BURST_DURATION_MAX (12) #define CFG_SIFS_BURST_DURATION_DEFAULT (8) +/* Optimize channel avoidance indication comming from firmware */ +#define CFG_OPTIMIZE_CA_EVENT_NAME "goptimize_chan_avoid_event" +#define CFG_OPTIMIZE_CA_EVENT_DISABLE (0) +#define CFG_OPTIMIZE_CA_EVENT_ENABLE (1) +#define CFG_OPTIMIZE_CA_EVENT_DEFAULT (0) /*--------------------------------------------------------------------------- Type declarations @@ -4140,6 +4145,7 @@ struct hdd_config { bool multicast_replay_filter; /* parameter for indicating sifs burst duration to fw */ uint8_t sifs_burst_duration; + bool goptimize_chan_avoid_event; }; #define VAR_OFFSET(_Struct, _Var) (offsetof(_Struct, _Var)) diff --git a/core/hdd/inc/wlan_hdd_main.h b/core/hdd/inc/wlan_hdd_main.h index 76be402b99a8..d649737380ff 100644 --- a/core/hdd/inc/wlan_hdd_main.h +++ b/core/hdd/inc/wlan_hdd_main.h @@ -1866,4 +1866,6 @@ enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode); void hdd_ch_avoid_cb(void *hdd_context, void *indi_param); void hdd_unsafe_channel_restart_sap(hdd_context_t *hdd_ctx); +int hdd_enable_disable_ca_event(hdd_context_t *hddctx, + uint8_t set_value); #endif /* end #if !defined(WLAN_HDD_MAIN_H) */ diff --git a/core/hdd/src/wlan_hdd_cfg.c b/core/hdd/src/wlan_hdd_cfg.c index 5bb4ad0cae1e..e28f70dfaa3e 100644 --- a/core/hdd/src/wlan_hdd_cfg.c +++ b/core/hdd/src/wlan_hdd_cfg.c @@ -3970,6 +3970,13 @@ REG_TABLE_ENTRY g_registry_table[] = { CFG_SIFS_BURST_DURATION_DEFAULT, CFG_SIFS_BURST_DURATION_MIN, CFG_SIFS_BURST_DURATION_MAX), + REG_VARIABLE(CFG_OPTIMIZE_CA_EVENT_NAME, WLAN_PARAM_Integer, + struct hdd_config, goptimize_chan_avoid_event, + VAR_FLAGS_OPTIONAL | + VAR_FLAGS_RANGE_CHECK_ASSUME_DEFAULT, + CFG_OPTIMIZE_CA_EVENT_DEFAULT, + CFG_OPTIMIZE_CA_EVENT_DISABLE, + CFG_OPTIMIZE_CA_EVENT_ENABLE), }; /** diff --git a/core/hdd/src/wlan_hdd_cfg80211.c b/core/hdd/src/wlan_hdd_cfg80211.c index 42add2736949..e17753c2ec29 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.c +++ b/core/hdd/src/wlan_hdd_cfg80211.c @@ -3868,6 +3868,7 @@ wlan_hdd_wifi_config_policy[QCA_WLAN_VENDOR_ATTR_CONFIG_MAX + 1] = { [QCA_WLAN_VENDOR_ATTR_CONFIG_MODULATED_DTIM] = {.type = NLA_U32 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR] = {.type = NLA_U16 }, [QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME] = {.type = NLA_U32 }, + [QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND] = {.type = NLA_U8 }, }; @@ -3898,6 +3899,7 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, u32 modulated_dtim; u16 stats_avg_factor; u32 guard_time; + uint8_t set_value; u32 ftm_capab; QDF_STATUS status; int attr_len; @@ -4023,6 +4025,13 @@ __wlan_hdd_cfg80211_wifi_configuration_set(struct wiphy *wiphy, } } + if (tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]) { + set_value = nla_get_u8( + tb[QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND]); + hdd_info("set_value: %d", set_value); + ret_val = hdd_enable_disable_ca_event(hdd_ctx, set_value); + } + return ret_val; } diff --git a/core/hdd/src/wlan_hdd_cfg80211.h b/core/hdd/src/wlan_hdd_cfg80211.h index 2a930e3c912b..c7ec0ce1a771 100644 --- a/core/hdd/src/wlan_hdd_cfg80211.h +++ b/core/hdd/src/wlan_hdd_cfg80211.h @@ -2341,6 +2341,8 @@ enum qca_wlan_vendor_config { QCA_WLAN_VENDOR_ATTR_CONFIG_STATS_AVG_FACTOR, QCA_WLAN_VENDOR_ATTR_CONFIG_GUARD_TIME, QCA_WLAN_VENDOR_ATTR_CONFIG_FINE_TIME_MEASUREMENT, + QCA_WLAN_VENDOR_ATTR_CONFIG_PENALIZE_AFTER_NCONS_BEACON_MISS, + QCA_WLAN_VENDOR_ATTR_CONFIG_CHANNEL_AVOIDANCE_IND, /* Attribute used to set scan default IEs to the driver. * * These IEs can be used by scan operations that will be initiated by diff --git a/core/hdd/src/wlan_hdd_main.c b/core/hdd/src/wlan_hdd_main.c index d91259794eb6..c058df7c2544 100644 --- a/core/hdd/src/wlan_hdd_main.c +++ b/core/hdd/src/wlan_hdd_main.c @@ -7765,6 +7765,13 @@ int hdd_wlan_startup(struct device *dev) qdf_mc_timer_start(&hdd_ctx->iface_change_timer, hdd_ctx->config->iface_change_wait_time * 5000); + + if (hdd_ctx->config->goptimize_chan_avoid_event) { + status = sme_enable_disable_chanavoidind_event( + hdd_ctx->hHal, 0); + if (!QDF_IS_STATUS_SUCCESS(status)) + hdd_err("Failed to disable Chan Avoidance Indication"); + } goto success; err_debugfs_exit: @@ -9291,6 +9298,38 @@ enum sap_acs_dfs_mode wlan_hdd_get_dfs_mode(enum dfs_mode mode) } } +/** + * hdd_enable_disable_ca_event() - enable/disable channel avoidance event + * @hddctx: pointer to hdd context + * @set_value: enable/disable + * + * When Host sends vendor command enable, FW will send *ONE* CA ind to + * Host(even though it is duplicate). When Host send vendor command + * disable,FW doesn't perform any action. Whenever any change in + * CA *and* WLAN is in SAP/P2P-GO mode, FW sends CA ind to host. + * + * return - 0 on success, appropriate error values on failure. + */ +int hdd_enable_disable_ca_event(hdd_context_t *hddctx, uint8_t set_value) +{ + QDF_STATUS status; + + if (0 != wlan_hdd_validate_context(hddctx)) { + return -EAGAIN; + } + + if (!hddctx->config->goptimize_chan_avoid_event) { + hdd_warn("goptimize_chan_avoid_event ini param disabled"); + return -EINVAL; + } + + status = sme_enable_disable_chanavoidind_event(hddctx->hHal, set_value); + if (!QDF_IS_STATUS_SUCCESS(status)) { + hdd_err("Failed to send chan avoid command to SME"); + return -EINVAL; + } + return 0; +} /* Register the module init/exit functions */ module_init(hdd_module_init); diff --git a/core/mac/src/include/sir_params.h b/core/mac/src/include/sir_params.h index ad58fab5470b..903f3a6e9500 100644 --- a/core/mac/src/include/sir_params.h +++ b/core/mac/src/include/sir_params.h @@ -630,6 +630,7 @@ typedef struct sSirMbMsgP2p { #define SIR_HAL_NDP_END_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 357) #define SIR_HAL_UPDATE_WEP_DEFAULT_KEY (SIR_HAL_ITC_MSG_TYPES_BEGIN + 358) +#define SIR_HAL_SEND_FREQ_RANGE_CONTROL_IND (SIR_HAL_ITC_MSG_TYPES_BEGIN + 360) #define SIR_HAL_POWER_DBG_CMD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 362) #define SIR_HAL_SET_DTIM_PERIOD (SIR_HAL_ITC_MSG_TYPES_BEGIN + 363) diff --git a/core/sme/inc/sme_api.h b/core/sme/inc/sme_api.h index c82450b98fd9..9e0e659691a5 100644 --- a/core/sme/inc/sme_api.h +++ b/core/sme/inc/sme_api.h @@ -1259,4 +1259,6 @@ QDF_STATUS sme_update_sta_roam_policy(tHalHandle hal, enum sta_roam_policy_dfs_mode dfs_mode, bool skip_unsafe_channels, uint8_t session_id); +QDF_STATUS sme_enable_disable_chanavoidind_event(tHalHandle hal, + uint8_t set_value); #endif /* #if !defined( __SME_API_H ) */ diff --git a/core/sme/src/common/sme_api.c b/core/sme/src/common/sme_api.c index 0af0db1425ac..44c132c10e89 100644 --- a/core/sme/src/common/sme_api.c +++ b/core/sme/src/common/sme_api.c @@ -16541,6 +16541,35 @@ QDF_STATUS sme_update_sta_roam_policy(tHalHandle hal_handle, csr_roam_offload_scan(mac_ctx, session_id, ROAM_SCAN_OFFLOAD_UPDATE_CFG, REASON_ROAM_SCAN_STA_ROAM_POLICY_CHANGED); + return status; +} + +/** + * sme_enable_disable_chanavoidind_event - configure ca event ind + * @hal: handler to hal + * @set_value: enable/disable + * + * function to enable/disable chan avoidance indication + * + * Return: QDF_STATUS + */ +QDF_STATUS sme_enable_disable_chanavoidind_event(tHalHandle hal, + uint8_t set_value) +{ + QDF_STATUS status; + tpAniSirGlobal mac_ctx = PMAC_STRUCT(hal); + cds_msg_t msg; + + sms_log(mac_ctx, LOG1, FL("set_value: %d"), set_value); + status = sme_acquire_global_lock(&mac_ctx->sme); + if (QDF_STATUS_SUCCESS == status) { + qdf_mem_zero(&msg, sizeof(cds_msg_t)); + msg.type = WMA_SEND_FREQ_RANGE_CONTROL_IND; + msg.bodyval = set_value; + status = cds_mq_post_message(QDF_MODULE_ID_WMA, &msg); + sme_release_global_lock(&mac_ctx->sme); + return status; + } return status; } diff --git a/core/wma/inc/wma.h b/core/wma/inc/wma.h index b82ba1f1738d..08792473b103 100644 --- a/core/wma/inc/wma.h +++ b/core/wma/inc/wma.h @@ -2213,3 +2213,6 @@ WLAN_PHY_MODE wma_chan_phy_mode(u8 chan, enum phy_ch_width chan_width, QDF_STATUS wma_start_oem_data_req(tp_wma_handle wma_handle, struct oem_data_req *oem_req); #endif + +QDF_STATUS wma_enable_disable_caevent_ind(tp_wma_handle wma_handle, + uint8_t val); diff --git a/core/wma/inc/wma_types.h b/core/wma/inc/wma_types.h index 247744e10fb2..e0fe6e4eb35a 100644 --- a/core/wma/inc/wma_types.h +++ b/core/wma/inc/wma_types.h @@ -473,6 +473,8 @@ #define WMA_SET_PDEV_IE_REQ SIR_HAL_SET_PDEV_IE_REQ #define WMA_UPDATE_WEP_DEFAULT_KEY SIR_HAL_UPDATE_WEP_DEFAULT_KEY +#define WMA_SEND_FREQ_RANGE_CONTROL_IND SIR_HAL_SEND_FREQ_RANGE_CONTROL_IND + /* Bit 6 will be used to control BD rate for Management frames */ #define HAL_USE_BD_RATE2_FOR_MANAGEMENT_FRAME 0x40 diff --git a/core/wma/src/wma_features.c b/core/wma/src/wma_features.c index 53b7762ddef0..b40be6ec7825 100644 --- a/core/wma/src/wma_features.c +++ b/core/wma/src/wma_features.c @@ -8175,3 +8175,46 @@ void wma_process_fw_test_cmd(WMA_HANDLE handle, return; } } + +/** + * wma_enable_disable_caevent_ind() - Issue WMI command to enable or + * disable ca event indication + * @wma: wma handler + * @val: boolean value true or false + * + * Return: QDF_STATUS + */ +QDF_STATUS wma_enable_disable_caevent_ind(tp_wma_handle wma, uint8_t val) +{ + WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param *cmd; + wmi_buf_t wmi_buf; + uint8_t *buf_ptr; + uint32_t len; + + if (!wma || !wma->wmi_handle) { + WMA_LOGE(FL("WMA is closed, can not issue set/clear CA")); + return QDF_STATUS_E_INVAL; + } + + len = sizeof(*cmd); + wmi_buf = wmi_buf_alloc(wma->wmi_handle, len); + if (!wmi_buf) { + WMA_LOGE(FL("wmi_buf_alloc failed")); + return QDF_STATUS_E_NOMEM; + } + buf_ptr = (uint8_t *) wmi_buf_data(wmi_buf); + cmd = (WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param *) buf_ptr; + WMITLV_SET_HDR(&cmd->tlv_header, + WMITLV_TAG_STRUC_WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param, + WMITLV_GET_STRUCT_TLVLEN( + WMI_CHAN_AVOID_RPT_ALLOW_CMD_fixed_param)); + cmd->rpt_allow = val; + if (wmi_unified_cmd_send(wma->wmi_handle, wmi_buf, len, + WMI_CHAN_AVOID_RPT_ALLOW_CMDID)) { + WMA_LOGE(FL("Failed to send enable/disable CA event command")); + wmi_buf_free(wmi_buf); + return QDF_STATUS_E_FAILURE; + } + + return QDF_STATUS_SUCCESS; +} diff --git a/core/wma/src/wma_main.c b/core/wma/src/wma_main.c index 7a46b314380f..b4559cf27472 100644 --- a/core/wma/src/wma_main.c +++ b/core/wma/src/wma_main.c @@ -6294,6 +6294,9 @@ QDF_STATUS wma_mc_process_msg(void *cds_context, cds_msg_t *msg) (struct wep_update_default_key_idx *)msg->bodyptr); qdf_mem_free(msg->bodyptr); break; + case WMA_SEND_FREQ_RANGE_CONTROL_IND: + wma_enable_disable_caevent_ind(wma_handle, msg->bodyval); + break; default: WMA_LOGD("unknow msg type %x", msg->type); /* Do Nothing? MSG Body should be freed at here */