During bootup, WMI_REG_CHAN_LIST_CC_EXT_EVENTID event sent from firmware
at an early stage and it expects the 6 GHz power type for 6 GHz reg rules.
As power mode is not defined at this point host selects IEEE80211_REG_UNSET_AP
as default mode.
When interface is created, it updates regd rules accordingly.
Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1
Signed-off-by: Aishwarya R <[email protected]>
---
drivers/net/wireless/ath/ath12k/mac.c | 11 ++++
drivers/net/wireless/ath/ath12k/mac.h | 1 +
drivers/net/wireless/ath/ath12k/wmi.c | 75 ++++++++++++++++-----------
drivers/net/wireless/ath/ath12k/wmi.h | 1 +
4 files changed, 58 insertions(+), 30 deletions(-)
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index ee792822b411..5b9af264d305 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -563,6 +563,17 @@ struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id)
return NULL;
}
+enum wmi_vdev_type ath12k_mac_get_ar_vdev_type(struct ath12k *ar)
+{
+ struct ath12k_vif *arvif;
+
+ list_for_each_entry(arvif, &ar->arvifs, list) {
+ return arvif->vdev_type;
+ }
+
+ return WMI_VDEV_TYPE_UNSPEC;
+}
+
struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id)
{
int i;
diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h
index 57f4295420bb..82f590004d05 100644
--- a/drivers/net/wireless/ath/ath12k/mac.h
+++ b/drivers/net/wireless/ath/ath12k/mac.h
@@ -66,6 +66,7 @@ struct ath12k_vif *ath12k_mac_get_arvif_by_vdev_id(struct ath12k_base *ab,
u32 vdev_id);
struct ath12k *ath12k_mac_get_ar_by_vdev_id(struct ath12k_base *ab, u32 vdev_id);
struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id);
+enum wmi_vdev_type ath12k_mac_get_ar_vdev_type(struct ath12k *ar);
void ath12k_mac_drain_tx(struct ath12k *ar);
void ath12k_mac_peer_cleanup_all(struct ath12k *ar);
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 1b9ce9a2ae96..211bdb915173 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -5299,26 +5299,15 @@ static bool ath12k_reg_is_world_alpha(char *alpha)
return alpha[0] == '0' && alpha[1] == '0';
}
-static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *skb)
+static int ath12k_reg_handle_chan_list(struct ath12k_base *ab,
+ struct ath12k_reg_info *reg_info,
+ enum ieee80211_ap_reg_power power_type)
{
- struct ath12k_reg_info *reg_info = NULL;
- struct ieee80211_regdomain *regd = NULL;
+ struct ieee80211_regdomain *regd;
bool intersect = false;
- int ret = 0, pdev_idx, i, j;
+ int pdev_idx;
struct ath12k *ar;
-
- reg_info = kzalloc(sizeof(*reg_info), GFP_ATOMIC);
- if (!reg_info) {
- ret = -ENOMEM;
- goto fallback;
- }
-
- ret = ath12k_pull_reg_chan_list_ext_update_ev(ab, skb, reg_info);
-
- if (ret) {
- ath12k_warn(ab, "failed to extract regulatory info from received event\n");
- goto fallback;
- }
+ enum wmi_vdev_type vdev_type;
if (reg_info->status_code != REG_SET_CC_STATUS_PASS) {
/* In case of failure to set the requested ctry,
@@ -5326,7 +5315,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
* and return from here.
*/
ath12k_warn(ab, "Failed to set the requested Country regulatory setting\n");
- goto mem_free;
+ return -EINVAL;
}
pdev_idx = reg_info->phy_id;
@@ -5338,9 +5327,8 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
*/
if (ab->hw_params->single_pdev_only &&
pdev_idx < ab->hw_params->num_rxmda_per_pdev)
- goto mem_free;
- else
- goto fallback;
+ return -EINVAL;
+ goto fallback;
}
/* Avoid multiple overwrites to default regd, during core
@@ -5349,7 +5337,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
if (ab->default_regd[pdev_idx] && !ab->new_regd[pdev_idx] &&
!memcmp(ab->default_regd[pdev_idx]->alpha2,
reg_info->alpha2, 2))
- goto mem_free;
+ return -EINVAL;
/* Intersect new rules with default regd if a new country setting was
* requested, i.e a default regd was already set during initialization
@@ -5361,8 +5349,13 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
!ath12k_reg_is_world_alpha((char *)reg_info->alpha2))
intersect = true;
- regd = ath12k_reg_build_regd(ab, reg_info, intersect,
- WMI_VDEV_TYPE_AP, IEEE80211_REG_UNSET_AP);
+ ar = ab->pdevs[pdev_idx].ar;
+ vdev_type = ath12k_mac_get_ar_vdev_type(ar);
+ ath12k_dbg(ab, ATH12K_DBG_WMI,
+ "wmi handle chan list power type %d vdev type %d intersect %d\n",
+ power_type, vdev_type, intersect);
+
+ regd = ath12k_reg_build_regd(ab, reg_info, intersect, vdev_type, power_type);
if (!regd) {
ath12k_warn(ab, "failed to build regd from reg_info\n");
goto fallback;
@@ -5394,7 +5387,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
ab->dfs_region = reg_info->dfs_region;
spin_unlock(&ab->base_lock);
- goto mem_free;
+ return 0;
fallback:
/* Fallback to older reg (by sending previous country setting
@@ -5406,17 +5399,39 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
*/
/* TODO: This is rare, but still should also be handled */
WARN_ON(1);
+ return -EINVAL;
+}
+
+static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *skb)
+{
+ struct ath12k_reg_info *reg_info;
+ int ret, i, j;
+
+ reg_info = kzalloc(sizeof(*reg_info), GFP_ATOMIC);
+ if (!reg_info)
+ return -ENOMEM;
+
+ ret = ath12k_pull_reg_chan_list_ext_update_ev(ab, skb, reg_info);
+
+ if (ret) {
+ ath12k_warn(ab, "failed to extract regulatory info from received event\n");
+ goto mem_free;
+ }
+
+ ret = ath12k_reg_handle_chan_list(ab, reg_info, IEEE80211_REG_UNSET_AP);
+ if (ret)
+ ath12k_warn(ab, "failed to process regulatory info from received event\n");
+
mem_free:
if (reg_info) {
kfree(reg_info->reg_rules_2g_ptr);
kfree(reg_info->reg_rules_5g_ptr);
if (reg_info->is_ext_reg_event) {
- for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++)
+ for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) {
kfree(reg_info->reg_rules_6g_ap_ptr[i]);
-
- for (j = 0; j < WMI_REG_CURRENT_MAX_AP_TYPE; j++)
- for (i = 0; i < WMI_REG_MAX_CLIENT_TYPE; i++)
- kfree(reg_info->reg_rules_6g_client_ptr[j][i]);
+ for (j = 0; j < WMI_REG_MAX_CLIENT_TYPE; j++)
+ kfree(reg_info->reg_rules_6g_client_ptr[i][j]);
+ }
}
kfree(reg_info);
}
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index 966e6ba4e162..c3b110af1272 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -4161,6 +4161,7 @@ struct ath12k_wmi_target_cap_arg {
};
enum wmi_vdev_type {
+ WMI_VDEV_TYPE_UNSPEC = 0,
WMI_VDEV_TYPE_AP = 1,
WMI_VDEV_TYPE_STA = 2,
WMI_VDEV_TYPE_IBSS = 3,
--
2.17.1
On 9/19/2023 12:17 AM, Aishwarya R wrote:
> During bootup, WMI_REG_CHAN_LIST_CC_EXT_EVENTID event sent from firmware
> at an early stage and it expects the 6 GHz power type for 6 GHz reg rules.
what is "it"?
> As power mode is not defined at this point host selects IEEE80211_REG_UNSET_AP
> as default mode.
>
> When interface is created, it updates regd rules accordingly.
Again what is "it"?
I'm having trouble discerning what is existing behavior and what is new
behavior.
That distinction should be clear. In the past the following template
has been suggested:
" Current code does (A), this has a problem when (B).
We can improve this doing (C), because (D)."
<http://www.spinics.net/lists/kernel/msg1633438.html>
Obviously that exact format isn't required, but you should at least
describe, if it isn't obvious:
1) what does the current code do
2) what is wrong with that code
3) what should be done to the code to fix the issue
I don't actually have an code patch comments