[PATCH AUTOSEL 5.4 05/14] nl80211: reset regdom when reloading regdb

From: Sasha Levin
Date: Mon Dec 20 2021 - 21:01:28 EST


From: Finn Behrens <me@xxxxxxxxxx>

[ Upstream commit 1eda919126b420fee6b8d546f7f728fbbd4b8f11 ]

Reload the regdom when the regulatory db is reloaded.
Otherwise, the user had to change the regulatoy domain
to a different one and then reset it to the correct
one to have a new regulatory db take effect after a
reload.

Signed-off-by: Finn Behrens <fin@xxxxxxxxxxx>
Link: https://lore.kernel.org/r/YaIIZfxHgqc/UTA7@xxxxxxxxxxxxxxxx
[edit commit message]
Signed-off-by: Johannes Berg <johannes.berg@xxxxxxxxx>
Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>
---
include/net/regulatory.h | 1 +
net/wireless/reg.c | 27 +++++++++++++++++++++++++--
2 files changed, 26 insertions(+), 2 deletions(-)

diff --git a/include/net/regulatory.h b/include/net/regulatory.h
index 3469750df0f44..16d61a0980e35 100644
--- a/include/net/regulatory.h
+++ b/include/net/regulatory.h
@@ -83,6 +83,7 @@ struct regulatory_request {
enum nl80211_dfs_regions dfs_region;
bool intersect;
bool processed;
+ bool reload;
enum environment_cap country_ie_env;
struct list_head list;
};
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 0f3b57a73670b..38037a13e935e 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -133,6 +133,7 @@ static u32 reg_is_indoor_portid;

static void restore_regulatory_settings(bool reset_user, bool cached);
static void print_regdomain(const struct ieee80211_regdomain *rd);
+static void reg_process_hint(struct regulatory_request *reg_request);

static const struct ieee80211_regdomain *get_cfg80211_regdom(void)
{
@@ -1079,6 +1080,8 @@ int reg_reload_regdb(void)
const struct firmware *fw;
void *db;
int err;
+ const struct ieee80211_regdomain *current_regdomain;
+ struct regulatory_request *request;

err = request_firmware(&fw, "regulatory.db", &reg_pdev->dev);
if (err)
@@ -1099,8 +1102,27 @@ int reg_reload_regdb(void)
if (!IS_ERR_OR_NULL(regdb))
kfree(regdb);
regdb = db;
- rtnl_unlock();

+ /* reset regulatory domain */
+ current_regdomain = get_cfg80211_regdom();
+
+ request = kzalloc(sizeof(*request), GFP_KERNEL);
+ if (!request) {
+ err = -ENOMEM;
+ goto out_unlock;
+ }
+
+ request->wiphy_idx = WIPHY_IDX_INVALID;
+ request->alpha2[0] = current_regdomain->alpha2[0];
+ request->alpha2[1] = current_regdomain->alpha2[1];
+ request->initiator = NL80211_USER_REG_HINT_USER;
+ request->user_reg_hint_type = NL80211_USER_REG_HINT_USER;
+ request->reload = true;
+
+ reg_process_hint(request);
+
+out_unlock:
+ rtnl_unlock();
out:
release_firmware(fw);
return err;
@@ -2449,7 +2471,8 @@ reg_process_hint_user(struct regulatory_request *user_request)

treatment = __reg_process_hint_user(user_request);
if (treatment == REG_REQ_IGNORE ||
- treatment == REG_REQ_ALREADY_SET)
+ (treatment == REG_REQ_ALREADY_SET &&
+ !user_request->reload))
return REG_REQ_IGNORE;

user_request->intersect = treatment == REG_REQ_INTERSECT;
--
2.34.1