wil6210: use country specific board file upon reg domain change

wil6210 device needs to use country specific board file while in China
regulatory domain. Register cfg80211 reg_notifier and switch board
file if needed according to new regulatory domain.
This feature is disabled by default and can be enabled with a new
country_specific_board_file module parameter.

Change-Id: I2f4555d2cf6a565c2c17a70a7a6307cc5ebbc27b
Signed-off-by: Dedy Lansky <dlansky@codeaurora.org>
Signed-off-by: Maya Erez <merez@codeaurora.org>
[liord@codeaurora.org: fix merge conflicts]
Signed-off-by: Lior David <liord@coreaurora.org>
Signed-off-by: Alexei Avshalom Lazar <ailizaro@codeaurora.org>
This commit is contained in:
Dedy Lansky 2019-12-02 16:02:05 +02:00 • committed by Alexei Avshalom Lazar
commit 5899ce5022
3 changed files with 92 additions and 6 deletions

View file

@ -14,6 +14,7 @@
#include "fw.h"
#define WIL_MAX_ROC_DURATION_MS 5000
#define CTRY_CHINA "CN"
#define WIL_EDMG_CHANNEL_9_SUBCHANNELS (BIT(0) | BIT(1))
#define WIL_EDMG_CHANNEL_10_SUBCHANNELS (BIT(1) | BIT(2))
@ -41,6 +42,10 @@ static struct wiphy_wowlan_support wil_wowlan_support = {
};
#endif
static bool country_specific_board_file;
module_param(country_specific_board_file, bool, 0444);
MODULE_PARM_DESC(country_specific_board_file, " switch board file upon regulatory domain change (Default: false)");
static bool ignore_reg_hints = true;
module_param(ignore_reg_hints, bool, 0444);
MODULE_PARM_DESC(ignore_reg_hints, " Ignore OTA regulatory hints (Default: true)");
@ -2604,6 +2609,65 @@ wil_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev,
return 0;
}
static int wil_switch_board_file(struct wil6210_priv *wil,
const u8 *new_regdomain)
{
int rc = 0;
if (!country_specific_board_file)
return 0;
if (memcmp(wil->regdomain, CTRY_CHINA, 2) == 0) {
wil_info(wil, "moving out of China reg domain, use default board file\n");
wil->board_file_country[0] = '\0';
} else if (memcmp(new_regdomain, CTRY_CHINA, 2) == 0) {
wil_info(wil, "moving into China reg domain, use country specific board file\n");
strlcpy(wil->board_file_country, CTRY_CHINA,
sizeof(wil->board_file_country));
} else {
return 0;
}
/* need to switch board file - reset the device */
mutex_lock(&wil->mutex);
if (!wil_has_active_ifaces(wil, true, false) ||
wil_is_recovery_blocked(wil))
/* new board file will be used in next FW load */
goto out;
__wil_down(wil);
rc = __wil_up(wil);
out:
mutex_unlock(&wil->mutex);
return rc;
}
static void wil_cfg80211_reg_notify(struct wiphy *wiphy,
struct regulatory_request *request)
{
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
int rc;
wil_info(wil, "cfg reg_notify %c%c%s%s initiator %d hint_type %d\n",
request->alpha2[0], request->alpha2[1],
request->intersect ? " intersect" : "",
request->processed ? " processed" : "",
request->initiator, request->user_reg_hint_type);
if (memcmp(wil->regdomain, request->alpha2, 2) == 0)
/* reg domain did not change */
return;
rc = wil_switch_board_file(wil, request->alpha2);
if (rc)
wil_err(wil, "switch board file failed %d\n", rc);
memcpy(wil->regdomain, request->alpha2, 2);
}
static int
wil_cfg80211_update_ft_ies(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_update_ft_ies_params *ftie)
@ -2724,6 +2788,8 @@ static void wil_wiphy_init(struct wiphy *wiphy)
wiphy->mgmt_stypes = wil_mgmt_stypes;
wiphy->features |= NL80211_FEATURE_SK_TX_STATUS;
wiphy->reg_notifier = wil_cfg80211_reg_notify;
wiphy->n_vendor_commands = ARRAY_SIZE(wil_nl80211_vendor_commands);
wiphy->vendor_commands = wil_nl80211_vendor_commands;
wiphy->vendor_events = wil_nl80211_vendor_events;

View file

@ -1291,6 +1291,8 @@ void wil_mbox_ring_le2cpus(struct wil6210_mbox_ring *r)
void wil_get_board_file(struct wil6210_priv *wil, char *buf, size_t len)
{
const char *board_file;
const char *ext;
int prefix_len;
const char *wil_talyn_fw_name = ftm_mode ? WIL_FW_NAME_FTM_TALYN :
WIL_FW_NAME_TALYN;
@ -1306,7 +1308,21 @@ void wil_get_board_file(struct wil6210_priv *wil, char *buf, size_t len)
board_file = WIL_BOARD_FILE_NAME;
}
strlcpy(buf, board_file, len);
if (wil->board_file_country[0] == '\0') {
strlcpy(buf, board_file, len);
return;
}
/* use country specific board file */
if (len < strlen(board_file) + 4 /* for _XX and terminating null */)
return;
ext = strrchr(board_file, '.');
prefix_len = (ext ? ext - board_file : strlen(board_file));
snprintf(buf, len, "%.*s_%.2s",
prefix_len, board_file, wil->board_file_country);
if (ext)
strlcat(buf, ext, len);
}
static int wil_get_bl_info(struct wil6210_priv *wil)
@ -1707,16 +1723,16 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw)
if (load_fw) {
char board_file[WIL_BOARD_FILE_MAX_NAMELEN];
if (wil->secured_boot) {
wil_err(wil, "secured boot is not supported\n");
return -ENOTSUPP;
}
board_file[0] = '\0';
wil_get_board_file(wil, board_file, sizeof(board_file));
wil_info(wil, "Use firmware <%s> + board <%s>\n",
wil->wil_fw_name, board_file);
if (wil->secured_boot) {
wil_err(wil, "secured boot is not supported\n");
return -ENOTSUPP;
}
if (!no_flash)
wil_bl_prepare_halt(wil);

View file

@ -934,6 +934,7 @@ struct wil6210_priv {
const char *hw_name;
const char *wil_fw_name;
char *board_file;
char board_file_country[3]; /* alpha2 */
u32 num_of_brd_entries;
struct wil_brd_info *brd_info;
DECLARE_BITMAP(hw_capa, hw_capa_last);
@ -1045,6 +1046,9 @@ struct wil6210_priv {
short direct;
} snr_thresh;
/* current reg domain configured in kernel */
char regdomain[3]; /* alpha2 */
struct notifier_block pm_notify;
bool suspend_resp_rcvd;