Commit a0ac8061 authored by Felix Fietkau's avatar Felix Fietkau
Browse files

mt76: mt76x02: reduce false positives in ED/CCA tx blocking



Full tx blocking (as opposed to CCA blocking) should only happen if there
is a continuous non-802.11 signal above the energy detect threshold.
Unfortunately the ED/CCA counter can't detect that, as it also counts 802.11
signals as busy.

Similar to the vendor code, implement a learning mode that waits until the AGC
gain has already been adjusted to the lowest value (due to false CCA events),
and the number of false CCA events still remains high, and the blocking
threshold is exceeded for more than 5 seconds.

Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 3fd0824a
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ struct mt76x02_calibration {
	u16 false_cca;
	s8 avg_rssi_all;
	s8 agc_gain_adjust;
	s8 agc_lowest_gain;
	s8 low_gain;

	s8 temp_vco;
@@ -114,8 +115,10 @@ struct mt76x02_dev {
	struct mt76x02_dfs_pattern_detector dfs_pd;

	/* edcca monitor */
	unsigned long ed_trigger_timeout;
	bool ed_tx_blocked;
	bool ed_monitor;
	u8 ed_monitor_learning;
	u8 ed_trigger;
	u8 ed_silent;
	ktime_t ed_time;
+21 −4
Original line number Diff line number Diff line
@@ -960,6 +960,7 @@ void mt76x02_edcca_init(struct mt76x02_dev *dev, bool enable)
		}
	}
	mt76x02_edcca_tx_enable(dev, true);
	dev->ed_monitor_learning = true;

	/* clear previous CCA timer value */
	mt76_rr(dev, MT_ED_CCA_TIMER);
@@ -969,6 +970,10 @@ EXPORT_SYMBOL_GPL(mt76x02_edcca_init);

#define MT_EDCCA_TH		92
#define MT_EDCCA_BLOCK_TH	2
#define MT_EDCCA_LEARN_TH	50
#define MT_EDCCA_LEARN_CCA	180
#define MT_EDCCA_LEARN_TIMEOUT	(20 * HZ)

static void mt76x02_edcca_check(struct mt76x02_dev *dev)
{
	ktime_t cur_time;
@@ -991,11 +996,23 @@ static void mt76x02_edcca_check(struct mt76x02_dev *dev)
		dev->ed_trigger = 0;
	}

	if (dev->ed_trigger > MT_EDCCA_BLOCK_TH &&
	    !dev->ed_tx_blocked)
	if (dev->cal.agc_lowest_gain &&
	    dev->cal.false_cca > MT_EDCCA_LEARN_CCA &&
	    dev->ed_trigger > MT_EDCCA_LEARN_TH) {
		dev->ed_monitor_learning = false;
		dev->ed_trigger_timeout = jiffies + 20 * HZ;
	} else if (!dev->ed_monitor_learning &&
		   time_is_after_jiffies(dev->ed_trigger_timeout)) {
		dev->ed_monitor_learning = true;
		mt76x02_edcca_tx_enable(dev, true);
	}

	if (dev->ed_monitor_learning)
		return;

	if (dev->ed_trigger > MT_EDCCA_BLOCK_TH && !dev->ed_tx_blocked)
		mt76x02_edcca_tx_enable(dev, false);
	else if (dev->ed_silent > MT_EDCCA_BLOCK_TH &&
		 dev->ed_tx_blocked)
	else if (dev->ed_silent > MT_EDCCA_BLOCK_TH && dev->ed_tx_blocked)
		mt76x02_edcca_tx_enable(dev, true);
}

+2 −0
Original line number Diff line number Diff line
@@ -194,6 +194,8 @@ bool mt76x02_phy_adjust_vga_gain(struct mt76x02_dev *dev)
		ret = true;
	}

	dev->cal.agc_lowest_gain = dev->cal.agc_gain_adjust >= limit;

	return ret;
}
EXPORT_SYMBOL_GPL(mt76x02_phy_adjust_vga_gain);