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

Commit 84841ba2 authored by Kalle Valo's avatar Kalle Valo
Browse files

ath6kl: add support for changing contry code



To make it possible to change the country code from user space via nl80211
add handler for reg_notifier. The feature is only enabled when built
time option CONFIG_ATH6KL_REGDOMAIN is enabled, which again depends on
CFG80211_CERTIFICATION_ONUS for certication purposes.

Signed-off-by: default avatarKalle Valo <kvalo@qca.qualcomm.com>
parent 11f0bfcf
Loading
Loading
Loading
Loading
+9 −0
Original line number Diff line number Diff line
@@ -30,3 +30,12 @@ config ATH6KL_DEBUG
	depends on ATH6KL
	---help---
	  Enables debug support

config ATH6KL_REGDOMAIN
	bool "Atheros ath6kl regdomain support"
	depends on ATH6KL
	depends on CFG80211_CERTIFICATION_ONUS
	---help---
	  Enabling this makes it possible to change the regdomain in
	  the firmware. This can be only enabled if regulatory requirements
	  are taken into account.
+47 −0
Original line number Diff line number Diff line
@@ -3458,6 +3458,49 @@ void ath6kl_cfg80211_stop_all(struct ath6kl *ar)
		ath6kl_cfg80211_stop(vif);
}

static int ath6kl_cfg80211_reg_notify(struct wiphy *wiphy,
				      struct regulatory_request *request)
{
	struct ath6kl *ar = wiphy_priv(wiphy);
	u32 rates[IEEE80211_NUM_BANDS];
	int ret, i;

	ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
		   "cfg reg_notify %c%c%s%s initiator %d\n",
		   request->alpha2[0], request->alpha2[1],
		   request->intersect ? " intersect" : "",
		   request->processed ? " processed" : "",
		   request->initiator);

	ret = ath6kl_wmi_set_regdomain_cmd(ar->wmi, request->alpha2);
	if (ret) {
		ath6kl_err("failed to set regdomain: %d\n", ret);
		return ret;
	}

	/*
	 * Firmware will apply the regdomain change only after a scan is
	 * issued and it will send a WMI_REGDOMAIN_EVENTID when it has been
	 * changed.
	 */

	for (i = 0; i < IEEE80211_NUM_BANDS; i++)
		if (wiphy->bands[i])
			rates[i] = (1 << wiphy->bands[i]->n_bitrates) - 1;


	ret = ath6kl_wmi_beginscan_cmd(ar->wmi, 0, WMI_LONG_SCAN, false,
				       false, 0, ATH6KL_FG_SCAN_INTERVAL,
				       0, NULL, false, rates);
	if (ret) {
		ath6kl_err("failed to start scan for a regdomain change: %d\n",
			   ret);
		return ret;
	}

	return 0;
}

static int ath6kl_cfg80211_vif_init(struct ath6kl_vif *vif)
{
	vif->aggr_cntxt = aggr_init(vif);
@@ -3590,6 +3633,10 @@ int ath6kl_cfg80211_init(struct ath6kl *ar)
					  BIT(NL80211_IFTYPE_P2P_CLIENT);
	}

	if (config_enabled(CONFIG_ATH6KL_REGDOMAIN) &&
	    test_bit(ATH6KL_FW_CAPABILITY_REGDOMAIN, ar->fw_capabilities))
		wiphy->reg_notifier = ath6kl_cfg80211_reg_notify;

	/* max num of ssids that can be probed during scanning */
	wiphy->max_scan_ssids = MAX_PROBED_SSIDS;

+3 −0
Original line number Diff line number Diff line
@@ -124,6 +124,9 @@ enum ath6kl_fw_capability {
	/* Firmware supports TX error rate notification */
	ATH6KL_FW_CAPABILITY_TX_ERR_NOTIFY,

	/* supports WMI_SET_REGDOMAIN_CMDID command */
	ATH6KL_FW_CAPABILITY_REGDOMAIN,

	/* this needs to be last */
	ATH6KL_FW_CAPABILITY_MAX,
};
+17 −0
Original line number Diff line number Diff line
@@ -3216,6 +3216,23 @@ int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enhance)
	return ret;
}

int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2)
{
	struct sk_buff *skb;
	struct wmi_set_regdomain_cmd *cmd;

	skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
	if (!skb)
		return -ENOMEM;

	cmd = (struct wmi_set_regdomain_cmd *) skb->data;
	memcpy(cmd->iso_name, alpha2, 2);

	return ath6kl_wmi_cmd_send(wmi, 0, skb,
				   WMI_SET_REGDOMAIN_CMDID,
				   NO_SYNC_WMIFLAG);
}

s32 ath6kl_wmi_get_rate(s8 rate_index)
{
	if (rate_index == RATE_AUTO)
+6 −0
Original line number Diff line number Diff line
@@ -1042,6 +1042,11 @@ struct wmi_sta_bmiss_enhance_cmd {
	u8 enable;
} __packed;

struct wmi_set_regdomain_cmd {
	u8 length;
	u8 iso_name[2];
} __packed;

/* WMI_SET_POWER_MODE_CMDID */
enum wmi_power_mode {
	REC_POWER = 0x01,
@@ -2640,6 +2645,7 @@ int ath6kl_wmi_add_del_mcast_filter_cmd(struct wmi *wmi, u8 if_idx,
int ath6kl_wmi_sta_bmiss_enhance_cmd(struct wmi *wmi, u8 if_idx, bool enable);
int ath6kl_wmi_set_txe_notify(struct wmi *wmi, u8 idx,
			      u32 rate, u32 pkts, u32 intvl);
int ath6kl_wmi_set_regdomain_cmd(struct wmi *wmi, const char *alpha2);

/* AP mode uAPSD */
int ath6kl_wmi_ap_set_apsd(struct wmi *wmi, u8 if_idx, u8 enable);