Skip to content

Commit

Permalink
mt7603: implement code for adjusting energy detect CCA thresholds
Browse files Browse the repository at this point in the history
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 <nbd@nbd.name>
  • Loading branch information
nbd168 committed Dec 3, 2018
1 parent 5a5b396 commit 8084323
Show file tree
Hide file tree
Showing 5 changed files with 151 additions and 3 deletions.
12 changes: 12 additions & 0 deletions mt7603/init.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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)
Expand Down
86 changes: 86 additions & 0 deletions mt7603/mac.c
Expand Up @@ -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,
Expand All @@ -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,
Expand Down
23 changes: 23 additions & 0 deletions mt7603/main.c
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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);

Expand Down
10 changes: 10 additions & 0 deletions mt7603/mt7603.h
Expand Up @@ -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;

Expand Down Expand Up @@ -115,13 +117,19 @@ struct mt7603_dev {
s16 coverage_class;

ktime_t survey_time;
ktime_t ed_time;
int beacon_int;

struct mt76_queue q_rx;

spinlock_t ps_lock;

u8 mcu_running;
u8 ed_monitor;

s8 ed_trigger;
u8 ed_strict_mode;
u8 ed_strong_signal;

u8 beacon_mask;

Expand Down Expand Up @@ -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
23 changes: 20 additions & 3 deletions mt7603/regs.h
Expand Up @@ -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 + \
Expand Down Expand Up @@ -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)
Expand All @@ -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

Expand Down

0 comments on commit 8084323

Please sign in to comment.