drivers: nrfwifi: Fix regulatory domain regression

Recent WPA supplicant changes have broken nRF regulatory support,
implement the new set/get country WPA supplicant ops.

WPA supplicant: Regulatory SET through WPA supplicant, GET is direct to
the driver

Scan only: SET and GET direct calls to the driver

Fixes #79916.

Signed-off-by: Chaitanya Tata <Chaitanya.Tata@nordicsemi.no>
This commit is contained in:
Chaitanya Tata 2024-10-16 23:39:40 +05:30 committed by David Leach
parent fac21acc6b
commit 2ea25ea238
3 changed files with 107 additions and 47 deletions

View file

@ -123,6 +123,8 @@ int nrf_wifi_supp_get_conn_info(void *if_priv, struct wpa_conn_info *info);
void nrf_wifi_supp_event_proc_get_conn_info(void *os_vif_ctx,
struct nrf_wifi_umac_event_conn_info *info,
unsigned int event_len);
int nrf_wifi_supp_set_country(void *if_priv, const char *alpha2);
int nrf_wifi_supp_get_country(void *if_priv, char *alpha2);
#endif /* CONFIG_NRF70_STA_MODE */
#ifdef CONFIG_NRF70_AP_MODE

View file

@ -343,28 +343,8 @@ int nrf_wifi_reg_domain(const struct device *dev, struct wifi_reg_domain *reg_do
goto err;
}
#ifdef CONFIG_NRF70_SCAN_ONLY
if (reg_domain->oper == WIFI_MGMT_SET) {
#ifndef CONFIG_NRF70_RADIO_TEST
#ifdef CONFIG_NRF70_STA_MODE
/* Need to check if WPA supplicant is initialized or not.
* Must be checked when CONFIG_WIFI_NM_WPA_SUPPLICANT is enabled.
* Not applicable for RADIO_TEST or when
* CONFIG_WIFI_NM_WPA_SUPPLICANT is not enabled.
*/
/* It is possbile that during supplicant initialization driver may
* get the command. lock will try to ensure that supplicant
* initialization is complete.
*/
k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
if ((!vif_ctx_zep->supp_drv_if_ctx) ||
(!wifi_nm_get_instance_iface(vif_ctx_zep->zep_net_if_ctx))) {
LOG_ERR("%s: WPA supplicant initialization not complete yet", __func__);
k_mutex_unlock(&vif_ctx_zep->vif_lock);
goto err;
}
k_mutex_unlock(&vif_ctx_zep->vif_lock);
#endif /* CONFIG_NRF70_STA_MODE */
#endif /* !CONFIG_NRF70_RADIO_TEST */
memcpy(reg_domain_info.alpha2, reg_domain->country_code, WIFI_COUNTRY_CODE_LEN);
reg_domain_info.force = reg_domain->force;
@ -374,36 +354,39 @@ int nrf_wifi_reg_domain(const struct device *dev, struct wifi_reg_domain *reg_do
LOG_ERR("%s: Failed to set regulatory domain", __func__);
goto err;
}
} else if (reg_domain->oper == WIFI_MGMT_GET) {
if (!reg_domain->chan_info) {
LOG_ERR("%s: Invalid regulatory info (NULL)\n", __func__);
goto err;
}
status = nrf_wifi_fmac_get_reg(fmac_dev_ctx, &reg_domain_info);
if (status != NRF_WIFI_STATUS_SUCCESS) {
LOG_ERR("%s: Failed to get regulatory domain", __func__);
goto err;
}
memcpy(reg_domain->country_code, reg_domain_info.alpha2, WIFI_COUNTRY_CODE_LEN);
reg_domain->num_channels = reg_domain_info.reg_chan_count;
for (chan_idx = 0; chan_idx < reg_domain_info.reg_chan_count; chan_idx++) {
chan_info = &(reg_domain->chan_info[chan_idx]);
reg_domain_chan_info = &(reg_domain_info.reg_chan_info[chan_idx]);
chan_info->center_frequency = reg_domain_chan_info->center_frequency;
chan_info->dfs = !!reg_domain_chan_info->dfs;
chan_info->max_power = reg_domain_chan_info->max_power;
chan_info->passive_only = !!reg_domain_chan_info->passive_channel;
chan_info->supported = !!reg_domain_chan_info->supported;
}
} else {
goto err;
}
#endif
if (reg_domain->oper != WIFI_MGMT_GET) {
LOG_ERR("%s: Invalid operation: %d", __func__, reg_domain->oper);
goto err;
}
if (!reg_domain->chan_info) {
LOG_ERR("%s: Invalid regulatory info (NULL)\n", __func__);
goto err;
}
status = nrf_wifi_fmac_get_reg(fmac_dev_ctx, &reg_domain_info);
if (status != NRF_WIFI_STATUS_SUCCESS) {
LOG_ERR("%s: Failed to get regulatory domain", __func__);
goto err;
}
memcpy(reg_domain->country_code, reg_domain_info.alpha2, WIFI_COUNTRY_CODE_LEN);
reg_domain->num_channels = reg_domain_info.reg_chan_count;
for (chan_idx = 0; chan_idx < reg_domain_info.reg_chan_count; chan_idx++) {
chan_info = &(reg_domain->chan_info[chan_idx]);
reg_domain_chan_info = &(reg_domain_info.reg_chan_info[chan_idx]);
chan_info->center_frequency = reg_domain_chan_info->center_frequency;
chan_info->dfs = !!reg_domain_chan_info->dfs;
chan_info->max_power = reg_domain_chan_info->max_power;
chan_info->passive_only = !!reg_domain_chan_info->passive_channel;
chan_info->supported = !!reg_domain_chan_info->supported;
}
ret = 0;
err:
k_mutex_unlock(&reg_lock);
@ -850,7 +833,7 @@ static struct wifi_mgmt_ops nrf_wifi_mgmt_ops = {
.get_power_save_config = nrf_wifi_get_power_save_config,
.set_rts_threshold = nrf_wifi_set_rts_threshold,
.get_rts_threshold = nrf_wifi_get_rts_threshold,
#endif /* CONFIG_NRF70_STA_MODE */
#endif
#ifdef CONFIG_NRF70_SYSTEM_WITH_RAW_MODES
.mode = nrf_wifi_mode,
#endif
@ -883,6 +866,8 @@ static struct zep_wpa_supp_dev_ops wpa_supp_ops = {
.register_frame = nrf_wifi_supp_register_frame,
.get_capa = nrf_wifi_supp_get_capa,
.get_conn_info = nrf_wifi_supp_get_conn_info,
.set_country = nrf_wifi_supp_set_country,
.get_country = nrf_wifi_supp_get_country,
#ifdef CONFIG_NRF70_AP_MODE
.init_ap = nrf_wifi_wpa_supp_init_ap,
.start_ap = nrf_wifi_wpa_supp_start_ap,

View file

@ -1861,6 +1861,79 @@ out:
return ret;
}
int nrf_wifi_supp_set_country(void *if_priv, const char *alpha2)
{
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
struct nrf_wifi_fmac_reg_info reg_domain_info = {0};
if (!if_priv || !alpha2) {
LOG_ERR("%s: Invalid params", __func__);
return -1;
}
vif_ctx_zep = if_priv;
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
if (!rpu_ctx_zep) {
LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
return -1;
}
k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
if (!rpu_ctx_zep->rpu_ctx) {
LOG_DBG("%s: RPU context not initialized", __func__);
goto out;
}
memcpy(reg_domain_info.alpha2, alpha2, NRF_WIFI_COUNTRY_CODE_LEN);
status = nrf_wifi_fmac_set_reg(rpu_ctx_zep->rpu_ctx, &reg_domain_info);
if (status != NRF_WIFI_STATUS_SUCCESS) {
LOG_ERR("%s: nrf_wifi_fmac_set_reg failed", __func__);
goto out;
}
out:
k_mutex_unlock(&vif_ctx_zep->vif_lock);
return status;
}
int nrf_wifi_supp_get_country(void *if_priv, char *alpha2)
{
struct nrf_wifi_vif_ctx_zep *vif_ctx_zep = NULL;
struct nrf_wifi_ctx_zep *rpu_ctx_zep = NULL;
enum nrf_wifi_status status = NRF_WIFI_STATUS_FAIL;
struct nrf_wifi_fmac_reg_info reg_domain_info = {0};
if (!if_priv || !alpha2) {
LOG_ERR("%s: Invalid params", __func__);
return -1;
}
vif_ctx_zep = if_priv;
rpu_ctx_zep = vif_ctx_zep->rpu_ctx_zep;
if (!rpu_ctx_zep) {
LOG_ERR("%s: rpu_ctx_zep is NULL", __func__);
return -1;
}
k_mutex_lock(&vif_ctx_zep->vif_lock, K_FOREVER);
if (!rpu_ctx_zep->rpu_ctx) {
LOG_DBG("%s: RPU context not initialized", __func__);
goto out;
}
status = nrf_wifi_fmac_get_reg(rpu_ctx_zep->rpu_ctx, &reg_domain_info);
if (status != NRF_WIFI_STATUS_SUCCESS) {
LOG_ERR("%s: nrf_wifi_fmac_get_reg failed", __func__);
goto out;
}
memcpy(alpha2, reg_domain_info.alpha2, NRF_WIFI_COUNTRY_CODE_LEN);
out:
k_mutex_unlock(&vif_ctx_zep->vif_lock);
return status;
}
void nrf_wifi_supp_event_proc_get_conn_info(void *if_priv,
struct nrf_wifi_umac_event_conn_info *info,