Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9ce311b8 authored by Dedy Lansky's avatar Dedy Lansky Committed by Lior David
Browse files

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: default avatarDedy Lansky <dlansky@codeaurora.org>
Signed-off-by: default avatarMaya Erez <merez@codeaurora.org>
[liord@codeaurora.org: fix merge conflicts]
Signed-off-by: default avatarLior David <liord@coreaurora.org>
parent 6b7ef10f
Loading
Loading
Loading
Loading
+66 −0
Original line number Diff line number Diff line
@@ -14,6 +14,7 @@
#include "fw.h"

#define WIL_MAX_ROC_DURATION_MS 5000
#define CTRY_CHINA "CN"

bool disable_ap_sme;
module_param(disable_ap_sme, bool, 0444);
@@ -25,6 +26,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)");
@@ -2102,6 +2107,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 const struct cfg80211_ops wil_cfg80211_ops = {
	.add_virtual_intf = wil_cfg80211_add_iface,
	.del_virtual_intf = wil_cfg80211_del_iface,
@@ -2173,6 +2237,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;
+22 −6
Original line number Diff line number Diff line
@@ -1159,6 +1159,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;

@@ -1174,7 +1176,21 @@ void wil_get_board_file(struct wil6210_priv *wil, char *buf, size_t len)
			board_file = WIL_BOARD_FILE_NAME;
	}

	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)
@@ -1556,16 +1572,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);

+4 −0
Original line number Diff line number Diff line
@@ -891,6 +891,7 @@ struct wil6210_priv {
	const char *hw_name;
	const char *wil_fw_name;
	char *board_file;
	char board_file_country[3]; /* alpha2 */
	u32 brd_file_addr;
	u32 brd_file_max_size;
	DECLARE_BITMAP(hw_capa, hw_capa_last);
@@ -997,6 +998,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;