mt7603: implement code for adjusting energy detect CCA thresholds

Ported from the reference driver.
Should fix compliance with ETSI rules on preventing transmission while
energy detect values are above the threshold.
Relax rules for non-ETSI regdomains

Signed-off-by: Felix Fietkau <[email protected]>
This commit is contained in:
Felix Fietkau
2018-12-03 18:03:52 +01:00
parent 5a5b396e6e
commit 80843237fa
5 changed files with 151 additions and 3 deletions
+12
View File
@@ -454,6 +454,16 @@ static u32 mt7603_rmw(struct mt76_dev *mdev, u32 offset, u32 mask, u32 val)
return dev->bus_ops->rmw(mdev, addr, mask, val);
}
static void
mt7603_regd_notifier(struct wiphy *wiphy,
struct regulatory_request *request)
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct mt7603_dev *dev = hw->priv;
dev->ed_monitor = request->dfs_region == NL80211_DFS_ETSI;
}
int mt7603_register_device(struct mt7603_dev *dev)
{
struct mt76_bus_ops *bus_ops;
@@ -512,6 +522,8 @@ int mt7603_register_device(struct mt7603_dev *dev)
#endif
BIT(NL80211_IFTYPE_ADHOC);
wiphy->reg_notifier = mt7603_regd_notifier;
ret = mt76_register_device(&dev->mt76, true, mt7603_rates,
ARRAY_SIZE(mt7603_rates));
if (ret)
+86
View File
@@ -1478,6 +1478,91 @@ void mt7603_update_channel(struct mt76_dev *mdev)
spin_unlock_bh(&dev->mt76.cc_lock);
}
void
mt7603_edcca_set_strict(struct mt7603_dev *dev, bool val)
{
u32 rxtd_6 = 0xd7c80000;
if (val == dev->ed_strict_mode)
return;
dev->ed_strict_mode = val;
/* Ensure that ED/CCA does not trigger if disabled */
if (!dev->ed_monitor)
rxtd_6 |= FIELD_PREP(MT_RXTD_6_CCAED_TH, 0x34);
else
rxtd_6 |= FIELD_PREP(MT_RXTD_6_CCAED_TH, 0x7d);
if (dev->ed_monitor && !dev->ed_strict_mode)
rxtd_6 |= FIELD_PREP(MT_RXTD_6_ACI_TH, 0x0f);
else
rxtd_6 |= FIELD_PREP(MT_RXTD_6_ACI_TH, 0x10);
mt76_wr(dev, MT_RXTD(6), rxtd_6);
mt76_rmw_field(dev, MT_RXTD(13), MT_RXTD_13_ACI_TH_EN,
dev->ed_monitor && !dev->ed_strict_mode);
}
static void
mt7603_edcca_check(struct mt7603_dev *dev)
{
u32 val = mt76_rr(dev, MT_AGC(41));
ktime_t cur_time;
int rssi0, rssi1;
u32 active;
u32 ed_busy;
if (!dev->ed_monitor)
return;
rssi0 = FIELD_GET(MT_AGC_41_RSSI_0, val);
if (rssi0 > 128)
rssi0 -= 256;
rssi1 = FIELD_GET(MT_AGC_41_RSSI_1, val);
if (rssi1 > 128)
rssi1 -= 256;
if (max(rssi0, rssi1) >= -40 &&
dev->ed_strong_signal < MT7603_EDCCA_BLOCK_TH)
dev->ed_strong_signal++;
else if (dev->ed_strong_signal > 0)
dev->ed_strong_signal--;
cur_time = ktime_get_boottime();
ed_busy = mt76_rr(dev, MT_MIB_STAT_ED) & MT_MIB_STAT_ED_MASK;
active = ktime_to_us(ktime_sub(cur_time, dev->ed_time));
dev->ed_time = cur_time;
if (!active)
return;
if (100 * ed_busy / active > 90) {
if (dev->ed_trigger < 0)
dev->ed_trigger = 0;
dev->ed_trigger++;
} else {
if (dev->ed_trigger > 0)
dev->ed_trigger = 0;
dev->ed_trigger--;
}
if (dev->ed_trigger > MT7603_EDCCA_BLOCK_TH ||
dev->ed_strong_signal < MT7603_EDCCA_BLOCK_TH / 2) {
mt7603_edcca_set_strict(dev, true);
} else if (dev->ed_trigger < -MT7603_EDCCA_BLOCK_TH) {
mt7603_edcca_set_strict(dev, false);
}
if (dev->ed_trigger > MT7603_EDCCA_BLOCK_TH)
dev->ed_trigger = MT7603_EDCCA_BLOCK_TH;
else if (dev->ed_trigger < -MT7603_EDCCA_BLOCK_TH)
dev->ed_trigger = -MT7603_EDCCA_BLOCK_TH;
}
void mt7603_mac_work(struct work_struct *work)
{
struct mt7603_dev *dev = container_of(work, struct mt7603_dev,
@@ -1489,6 +1574,7 @@ void mt7603_mac_work(struct work_struct *work)
mutex_lock(&dev->mt76.mutex);
mt7603_update_channel(&dev->mt76);
mt7603_edcca_check(dev);
if (mt7603_watchdog_check(dev, &dev->rx_pse_check,
RESET_CAUSE_RX_PSE_BUSY,
+23
View File
@@ -122,6 +122,27 @@ mt7603_remove_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
mutex_unlock(&dev->mt76.mutex);
}
static void
mt7603_init_edcca(struct mt7603_dev *dev)
{
/* Set lower signal level to -65dBm */
mt76_rmw_field(dev, MT_RXTD(8), MT_RXTD_8_LOWER_SIGNAL, 0x23);
/* clear previous energy detect monitor results */
mt76_rr(dev, MT_MIB_STAT_ED);
if (dev->ed_monitor)
mt76_set(dev, MT_MIB_CTL, MT_MIB_CTL_ED_TIME);
else
mt76_clear(dev, MT_MIB_CTL, MT_MIB_CTL_ED_TIME);
dev->ed_strict_mode = 0xff;
dev->ed_strong_signal = 0;
dev->ed_time = ktime_get_boottime();
mt7603_edcca_set_strict(dev, false);
}
static int
mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)
{
@@ -180,6 +201,8 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def)
dev->survey_time = ktime_get_boottime();
mt7603_init_edcca(dev);
out:
mutex_unlock(&dev->mt76.mutex);
+10
View File
@@ -46,6 +46,8 @@
#define MT7603_WATCHDOG_TIME 100 /* ms */
#define MT7603_WATCHDOG_TIMEOUT 10 /* number of checks */
#define MT7603_EDCCA_BLOCK_TH 10
struct mt7603_vif;
struct mt7603_sta;
@@ -115,6 +117,7 @@ struct mt7603_dev {
s16 coverage_class;
ktime_t survey_time;
ktime_t ed_time;
int beacon_int;
struct mt76_queue q_rx;
@@ -122,6 +125,11 @@ struct mt7603_dev {
spinlock_t ps_lock;
u8 mcu_running;
u8 ed_monitor;
s8 ed_trigger;
u8 ed_strict_mode;
u8 ed_strong_signal;
u8 beacon_mask;
@@ -241,4 +249,6 @@ void mt7603_pre_tbtt_tasklet(unsigned long arg);
void mt7603_update_channel(struct mt76_dev *mdev);
void mt7603_edcca_set_strict(struct mt7603_dev *dev, bool val);
#endif
+20 -3
View File
@@ -147,8 +147,21 @@
#define MT_WF_PHY_OFFSET 0x1000
#define MT_WF_PHY(ofs) (MT_WF_PHY_BASE + (ofs))
#define MT_WF_PHY_CR_RXTD_BASE MT_WF_PHY(0x600)
#define MT_WF_PHY_CR_RXTD(n) (MT_WF_PHY_CR_RXTD_BASE + ((n) * 4))
#define MT_AGC_BASE MT_WF_PHY(0x500)
#define MT_AGC(n) (MT_AGC_BASE + ((n) * 4))
#define MT_AGC_41_RSSI_0 GENMASK(23, 16)
#define MT_AGC_41_RSSI_1 GENMASK(7, 0)
#define MT_RXTD_BASE MT_WF_PHY(0x600)
#define MT_RXTD(n) (MT_RXTD_BASE + ((n) * 4))
#define MT_RXTD_6_ACI_TH GENMASK(4, 0)
#define MT_RXTD_6_CCAED_TH GENMASK(14, 8)
#define MT_RXTD_8_LOWER_SIGNAL GENMASK(5, 0)
#define MT_RXTD_13_ACI_TH_EN BIT(0)
#define MT_WF_PHY_CR_TSSI_BASE MT_WF_PHY(0xd00)
#define MT_WF_PHY_CR_TSSI(phy, n) (MT_WF_PHY_CR_TSSI_BASE + \
@@ -515,8 +528,9 @@ enum {
#define MT_MIB(_n) (MT_MIB_BASE + (_n))
#define MT_MIB_CTL MT_MIB(0x00)
#define MT_MIB_CTL_CCA_NAV_TX GENMASK(16, 14)
#define MT_MIB_CTL_PSCCA_TIME GENMASK(13, 11)
#define MT_MIB_CTL_CCA_NAV_TX GENMASK(16, 14)
#define MT_MIB_CTL_ED_TIME GENMASK(30, 28)
#define MT_MIB_CTL_READ_CLR_DIS BIT(31)
#define MT_MIB_STAT(_n) MT_MIB(0x08 + (_n) * 4)
@@ -527,6 +541,9 @@ enum {
#define MT_MIB_STAT_PSCCA MT_MIB_STAT(16)
#define MT_MIB_STAT_PSCCA_MASK GENMASK(23, 0)
#define MT_MIB_STAT_ED MT_MIB_STAT(18)
#define MT_MIB_STAT_ED_MASK GENMASK(23, 0)
#define MT_PCIE_REMAP_BASE_1 0x40000
#define MT_PCIE_REMAP_BASE_2 0x80000