Commit 7285eb96 authored by Zong-Zhe Yang's avatar Zong-Zhe Yang Committed by Kalle Valo
Browse files

rtw88: support adaptivity for ETSI/JP DFS region



Add Energy Detected CCA (EDCCA) mechanism to detect energy on the channel.
And EDCCA support adaptivity mode now. From MIC Ordinance Regulating Radio
Equipment article 49.20, ETSI EN-300-328 and EN-301-893, the device should
be able to dynamically pause TX activity when energy detected on the air.
According to ETSI/JP DFS region, driver will set corresponding threshold
and stop TX activity if the detected energy exceeds the threshold. For now,
we support it on 8822b and 8822c first.

By default, EDCCA mechanism is turned on. For ETSI/JP DFS region, it will
turn to adaptivity mode. However, with adaptivity, if environment is too
noisy, TX may often be halted. So, a debugfs for EDCCA is added. It can
show what EDCCA mode is used currently. And EDCCA mechanism can be turned
on/off through the debugfs while debugging.

Signed-off-by: default avatarZong-Zhe Yang <kevin_yang@realtek.com>
Signed-off-by: default avatarPing-Ke Shih <pkshih@realtek.com>
Signed-off-by: default avatarKalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/20210830072014.12250-4-pkshih@realtek.com
parent 8d4fb399
Loading
Loading
Loading
Loading
+38 −0
Original line number Diff line number Diff line
@@ -829,6 +829,38 @@ static int rtw_debugfs_get_coex_enable(struct seq_file *m, void *v)
	return 0;
}

static ssize_t rtw_debugfs_set_edcca_enable(struct file *filp,
					    const char __user *buffer,
					    size_t count, loff_t *loff)
{
	struct seq_file *seqpriv = (struct seq_file *)filp->private_data;
	struct rtw_debugfs_priv *debugfs_priv = seqpriv->private;
	struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
	bool input;
	int err;

	err = kstrtobool_from_user(buffer, count, &input);
	if (err)
		return err;

	rtw_edcca_enabled = input;
	rtw_phy_adaptivity_set_mode(rtwdev);

	return count;
}

static int rtw_debugfs_get_edcca_enable(struct seq_file *m, void *v)
{
	struct rtw_debugfs_priv *debugfs_priv = m->private;
	struct rtw_dev *rtwdev = debugfs_priv->rtwdev;
	struct rtw_dm_info *dm_info = &rtwdev->dm_info;

	seq_printf(m, "EDCCA %s: EDCCA mode %d\n",
		   rtw_edcca_enabled ? "enabled" : "disabled",
		   dm_info->edcca_mode);
	return 0;
}

static ssize_t rtw_debugfs_set_fw_crash(struct file *filp,
					const char __user *buffer,
					size_t count, loff_t *loff)
@@ -1049,6 +1081,11 @@ static struct rtw_debugfs_priv rtw_debug_priv_coex_info = {
	.cb_read = rtw_debugfs_get_coex_info,
};

static struct rtw_debugfs_priv rtw_debug_priv_edcca_enable = {
	.cb_write = rtw_debugfs_set_edcca_enable,
	.cb_read = rtw_debugfs_get_edcca_enable,
};

static struct rtw_debugfs_priv rtw_debug_priv_fw_crash = {
	.cb_write = rtw_debugfs_set_fw_crash,
	.cb_read = rtw_debugfs_get_fw_crash,
@@ -1132,6 +1169,7 @@ void rtw_debugfs_init(struct rtw_dev *rtwdev)
	}
	rtw_debugfs_add_r(rf_dump);
	rtw_debugfs_add_r(tx_pwr_tbl);
	rtw_debugfs_add_rw(edcca_enable);
	rtw_debugfs_add_rw(fw_crash);
	rtw_debugfs_add_rw(dm_cap);
}
+8 −0
Original line number Diff line number Diff line
@@ -23,6 +23,14 @@ EXPORT_SYMBOL(rtw_disable_lps_deep_mode);
bool rtw_bf_support = true;
unsigned int rtw_debug_mask;
EXPORT_SYMBOL(rtw_debug_mask);
/* EDCCA is enabled during normal behavior. For debugging purpose in
 * a noisy environment, it can be disabled via edcca debugfs. Because
 * all rtw88 devices will probably be affected if environment is noisy,
 * rtw_edcca_enabled is just declared by driver instead of by device.
 * So, turning it off will take effect for all rtw88 devices before
 * there is a tough reason to maintain rtw_edcca_enabled by device.
 */
bool rtw_edcca_enabled = true;

module_param_named(disable_lps_deep, rtw_disable_lps_deep_mode, bool, 0644);
module_param_named(support_bf, rtw_bf_support, bool, 0644);
+29 −0
Original line number Diff line number Diff line
@@ -41,6 +41,7 @@
extern bool rtw_bf_support;
extern bool rtw_disable_lps_deep_mode;
extern unsigned int rtw_debug_mask;
extern bool rtw_edcca_enabled;
extern const struct ieee80211_ops rtw_ops;

#define RTW_MAX_CHANNEL_NUM_2G 14
@@ -545,6 +546,11 @@ struct rtw_rf_sipi_addr {
	u32 lssi_read_pi;
};

struct rtw_hw_reg_offset {
	struct rtw_hw_reg hw_reg;
	u8 offset;
};

struct rtw_backup_info {
	u8 len;
	u32 reg;
@@ -815,6 +821,7 @@ enum rtw_regd_state {
struct rtw_regd {
	enum rtw_regd_state state;
	const struct rtw_regulatory *regulatory;
	enum nl80211_dfs_regions dfs_region;
};

struct rtw_chip_ops {
@@ -852,6 +859,8 @@ struct rtw_chip_ops {
			      struct ieee80211_bss_conf *conf);
	void (*cfg_csi_rate)(struct rtw_dev *rtwdev, u8 rssi, u8 cur_rate,
			     u8 fixrate_en, u8 *new_rate);
	void (*adaptivity_init)(struct rtw_dev *rtwdev);
	void (*adaptivity)(struct rtw_dev *rtwdev);
	void (*cfo_init)(struct rtw_dev *rtwdev);
	void (*cfo_track)(struct rtw_dev *rtwdev);
	void (*config_tx_path)(struct rtw_dev *rtwdev, u8 tx_path,
@@ -1207,6 +1216,10 @@ struct rtw_chip_info {
	u8 bfer_su_max_num;
	u8 bfer_mu_max_num;

	struct rtw_hw_reg_offset *edcca_th;
	s8 l2h_th_ini_cs;
	s8 l2h_th_ini_ad;

	const char *wow_fw_name;
	const struct wiphy_wowlan_support *wowlan_stub;
	const u8 max_sched_scan_ssids;
@@ -1555,6 +1568,20 @@ struct rtw_gapk_info {
	u8 channel;
};

#define EDCCA_TH_L2H_IDX 0
#define EDCCA_TH_H2L_IDX 1
#define EDCCA_TH_L2H_LB 48
#define EDCCA_ADC_BACKOFF 12
#define EDCCA_IGI_BASE 50
#define EDCCA_IGI_L2H_DIFF 8
#define EDCCA_L2H_H2L_DIFF 7
#define EDCCA_L2H_H2L_DIFF_NORMAL 8

enum rtw_edcca_mode {
	RTW_EDCCA_NORMAL	= 0,
	RTW_EDCCA_ADAPTIVITY	= 1,
};

struct rtw_cfo_track {
	bool is_adjust;
	u8 crystal_cap;
@@ -1646,6 +1673,8 @@ struct rtw_dm_info {
	struct rtw_gapk_info gapk;
	bool is_bt_iqk_timeout;

	s8 l2h_th_ini;
	enum rtw_edcca_mode edcca_mode;
	u8 scan_density;
};

+59 −0
Original line number Diff line number Diff line
@@ -120,6 +120,63 @@ static void rtw_phy_cck_pd_init(struct rtw_dev *rtwdev)
	dm_info->cck_fa_avg = CCK_FA_AVG_RESET;
}

void rtw_phy_set_edcca_th(struct rtw_dev *rtwdev, u8 l2h, u8 h2l)
{
	struct rtw_hw_reg_offset *edcca_th = rtwdev->chip->edcca_th;

	rtw_write32_mask(rtwdev,
			 edcca_th[EDCCA_TH_L2H_IDX].hw_reg.addr,
			 edcca_th[EDCCA_TH_L2H_IDX].hw_reg.mask,
			 l2h + edcca_th[EDCCA_TH_L2H_IDX].offset);
	rtw_write32_mask(rtwdev,
			 edcca_th[EDCCA_TH_H2L_IDX].hw_reg.addr,
			 edcca_th[EDCCA_TH_H2L_IDX].hw_reg.mask,
			 h2l + edcca_th[EDCCA_TH_H2L_IDX].offset);
}
EXPORT_SYMBOL(rtw_phy_set_edcca_th);

void rtw_phy_adaptivity_set_mode(struct rtw_dev *rtwdev)
{
	struct rtw_chip_info *chip = rtwdev->chip;
	struct rtw_dm_info *dm_info = &rtwdev->dm_info;

	/* turn off in debugfs for debug usage */
	if (!rtw_edcca_enabled) {
		dm_info->edcca_mode = RTW_EDCCA_NORMAL;
		rtw_dbg(rtwdev, RTW_DBG_PHY, "EDCCA disabled, cannot be set\n");
		return;
	}

	switch (rtwdev->regd.dfs_region) {
	case NL80211_DFS_ETSI:
		dm_info->edcca_mode = RTW_EDCCA_ADAPTIVITY;
		dm_info->l2h_th_ini = chip->l2h_th_ini_ad;
		break;
	case NL80211_DFS_JP:
		dm_info->edcca_mode = RTW_EDCCA_ADAPTIVITY;
		dm_info->l2h_th_ini = chip->l2h_th_ini_cs;
		break;
	default:
		dm_info->edcca_mode = RTW_EDCCA_NORMAL;
		break;
	}
}

static void rtw_phy_adaptivity_init(struct rtw_dev *rtwdev)
{
	struct rtw_chip_info *chip = rtwdev->chip;

	rtw_phy_adaptivity_set_mode(rtwdev);
	if (chip->ops->adaptivity_init)
		chip->ops->adaptivity_init(rtwdev);
}

static void rtw_phy_adaptivity(struct rtw_dev *rtwdev)
{
	if (rtwdev->chip->ops->adaptivity)
		rtwdev->chip->ops->adaptivity(rtwdev);
}

static void rtw_phy_cfo_init(struct rtw_dev *rtwdev)
{
	struct rtw_chip_info *chip = rtwdev->chip;
@@ -160,6 +217,7 @@ void rtw_phy_init(struct rtw_dev *rtwdev)
	rtw_phy_cck_pd_init(rtwdev);

	dm_info->iqk.done = false;
	rtw_phy_adaptivity_init(rtwdev);
	rtw_phy_cfo_init(rtwdev);
	rtw_phy_tx_path_div_init(rtwdev);
}
@@ -712,6 +770,7 @@ void rtw_phy_dynamic_mechanism(struct rtw_dev *rtwdev)
	rtw_phy_cfo_track(rtwdev);
	rtw_phy_dpk_track(rtwdev);
	rtw_phy_pwr_track(rtwdev);
	rtw_phy_adaptivity(rtwdev);
}

#define FRAC_BITS 3
+2 −0
Original line number Diff line number Diff line
@@ -59,6 +59,8 @@ bool rtw_phy_pwrtrack_need_lck(struct rtw_dev *rtwdev);
bool rtw_phy_pwrtrack_need_iqk(struct rtw_dev *rtwdev);
void rtw_phy_config_swing_table(struct rtw_dev *rtwdev,
				struct rtw_swing_table *swing_table);
void rtw_phy_set_edcca_th(struct rtw_dev *rtwdev, u8 l2h, u8 h2l);
void rtw_phy_adaptivity_set_mode(struct rtw_dev *rtwdev);
void rtw_phy_parsing_cfo(struct rtw_dev *rtwdev,
			 struct rtw_rx_pkt_stat *pkt_stat);
void rtw_phy_tx_path_diversity(struct rtw_dev *rtwdev);
Loading