diff --git a/mt7603/debugfs.c b/mt7603/debugfs.c index 14a92a5bf..ca7b109c7 100644 --- a/mt7603/debugfs.c +++ b/mt7603/debugfs.c @@ -43,6 +43,18 @@ mt7603_reset_read(struct seq_file *s, void *data) return 0; } +static int +mt7603_radio_read(struct seq_file *s, void *data) +{ + struct mt7603_dev *dev = dev_get_drvdata(s->private); + + seq_printf(s, "Sensitivity: %d\n", dev->sensitivity); + seq_printf(s, "False CCA: ofdm=%d cck=%d\n", + dev->false_cca_ofdm, dev->false_cca_cck); + + return 0; +} + void mt7603_init_debugfs(struct mt7603_dev *dev) { struct dentry *dir; @@ -54,4 +66,6 @@ void mt7603_init_debugfs(struct mt7603_dev *dev) debugfs_create_u32("reset_test", 0600, dir, &dev->reset_test); debugfs_create_devm_seqfile(dev->mt76.dev, "reset", dir, mt7603_reset_read); + debugfs_create_devm_seqfile(dev->mt76.dev, "radio", dir, + mt7603_radio_read); } diff --git a/mt7603/init.c b/mt7603/init.c index 3a711d4ae..aa1a572ac 100644 --- a/mt7603/init.c +++ b/mt7603/init.c @@ -151,6 +151,9 @@ mt7603_phy_init(struct mt7603_dev *dev) mt76_rmw_field(dev, MT_TMAC_TCR, MT_TMAC_TCR_TX_STREAMS, tx_chains); + + dev->agc0 = mt76_rr(dev, MT_AGC(0)); + dev->agc3 = mt76_rr(dev, MT_AGC(3)); } static void diff --git a/mt7603/mac.c b/mt7603/mac.c index cd4cda45d..e7e27c95a 100644 --- a/mt7603/mac.c +++ b/mt7603/mac.c @@ -1570,6 +1570,115 @@ mt7603_edcca_check(struct mt7603_dev *dev) dev->ed_trigger = -MT7603_EDCCA_BLOCK_TH; } +void mt7603_cca_stats_reset(struct mt7603_dev *dev) +{ + mt76_set(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_RESET); + mt76_clear(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_RESET); + mt76_set(dev, MT_PHYCTRL(2), MT_PHYCTRL_2_STATUS_EN); +} + +static void +mt7603_adjust_sensitivity(struct mt7603_dev *dev) +{ + u32 agc0 = dev->agc0, agc3 = dev->agc3; + u32 adj; + + if (!dev->sensitivity || dev->sensitivity < -100) { + dev->sensitivity = 0; + } else if (dev->sensitivity <= -84) { + adj = 7 + (dev->sensitivity + 92) / 2; + + agc0 = 0x56f0076f; + agc0 |= adj << 12; + agc0 |= adj << 16; + agc3 = 0x81d0d5e3; + } else if (dev->sensitivity <= -72) { + adj = 7 + (dev->sensitivity + 80) / 2; + + agc0 = 0x6af0006f; + agc0 |= adj << 8; + agc0 |= adj << 12; + agc0 |= adj << 16; + + agc3 = 0x8181d5e3; + } else { + if (dev->sensitivity > -54) + dev->sensitivity = -54; + + adj = 7 + (dev->sensitivity + 80) / 2; + + agc0 = 0x7ff0000f; + agc0 |= adj << 4; + agc0 |= adj << 8; + agc0 |= adj << 12; + agc0 |= adj << 16; + + agc3 = 0x818181e3; + } + + mt76_wr(dev, MT_AGC(0), agc0); + mt76_wr(dev, MT_AGC1(0), agc0); + + mt76_wr(dev, MT_AGC(3), agc3); + mt76_wr(dev, MT_AGC1(3), agc3); +} + +static void +mt7603_false_cca_check(struct mt7603_dev *dev) +{ + int pd_cck, pd_ofdm, mdrdy_cck, mdrdy_ofdm; + int false_cca; + int min_signal; + u32 val; + + val = mt76_rr(dev, MT_PHYCTRL_STAT_PD); + pd_cck = FIELD_GET(MT_PHYCTRL_STAT_PD_CCK, val); + pd_ofdm = FIELD_GET(MT_PHYCTRL_STAT_PD_OFDM, val); + + val = mt76_rr(dev, MT_PHYCTRL_STAT_MDRDY); + mdrdy_cck = FIELD_GET(MT_PHYCTRL_STAT_MDRDY_CCK, val); + mdrdy_ofdm = FIELD_GET(MT_PHYCTRL_STAT_MDRDY_OFDM, val); + + dev->false_cca_ofdm = pd_ofdm - mdrdy_ofdm; + dev->false_cca_cck = pd_cck - mdrdy_cck; + + mt7603_cca_stats_reset(dev); + + min_signal = mt76_get_min_avg_rssi(&dev->mt76); + if (!min_signal) { + dev->sensitivity = 0; + dev->last_cca_adj = jiffies; + goto out; + } + + min_signal -= 15; + + false_cca = dev->false_cca_ofdm + dev->false_cca_cck; + if (false_cca > 600) { + if (!dev->sensitivity) + dev->sensitivity = -92; + else + dev->sensitivity += 2; + dev->last_cca_adj = jiffies; + } else if (false_cca < 100 || + time_after(jiffies, dev->last_cca_adj + 10 * HZ)) { + + dev->last_cca_adj = jiffies; + if (!dev->sensitivity) + goto out; + + dev->sensitivity -= 2; + } + + if (dev->sensitivity && dev->sensitivity > min_signal) { + dev->sensitivity = min_signal; + dev->last_cca_adj = jiffies; + } + +out: + mt7603_adjust_sensitivity(dev); +} + void mt7603_mac_work(struct work_struct *work) { struct mt7603_dev *dev = container_of(work, struct mt7603_dev, @@ -1580,9 +1689,13 @@ void mt7603_mac_work(struct work_struct *work) mutex_lock(&dev->mt76.mutex); + dev->mac_work_count++; mt7603_update_channel(&dev->mt76); mt7603_edcca_check(dev); + if (dev->mac_work_count == 10) + mt7603_false_cca_check(dev); + if (mt7603_watchdog_check(dev, &dev->rx_pse_check, RESET_CAUSE_RX_PSE_BUSY, mt7603_rx_pse_busy) || @@ -1611,8 +1724,12 @@ void mt7603_mac_work(struct work_struct *work) dev->rx_dma_idx = ~0; memset(dev->tx_dma_idx, 0xff, sizeof(dev->tx_dma_idx)); reset = true; + dev->mac_work_count = 0; } + if (dev->mac_work_count >= 10) + dev->mac_work_count = 0; + mutex_unlock(&dev->mt76.mutex); if (reset) diff --git a/mt7603/main.c b/mt7603/main.c index ec8b1dd1b..14112ce79 100644 --- a/mt7603/main.c +++ b/mt7603/main.c @@ -198,6 +198,7 @@ mt7603_set_channel(struct mt7603_dev *dev, struct cfg80211_chan_def *def) mt76_set(dev, MT_MIB_CTL, MT_MIB_CTL_CCA_NAV_TX | MT_MIB_CTL_PSCCA_TIME); mt76_rr(dev, MT_MIB_STAT_PSCCA); + mt7603_cca_stats_reset(dev); dev->survey_time = ktime_get_boottime(); diff --git a/mt7603/mt7603.h b/mt7603/mt7603.h index 63bd4891e..6dfc7bff2 100644 --- a/mt7603/mt7603.h +++ b/mt7603/mt7603.h @@ -111,6 +111,10 @@ struct mt7603_dev { struct mt7603_sta global_sta; + u32 agc0, agc3; + u32 false_cca_ofdm, false_cca_cck; + unsigned long last_cca_adj; + u8 rssi_offset[3]; u8 slottime; @@ -124,6 +128,8 @@ struct mt7603_dev { spinlock_t ps_lock; + u8 mac_work_count; + u8 mcu_running; u8 ed_monitor; @@ -131,6 +137,8 @@ struct mt7603_dev { u8 ed_strict_mode; u8 ed_strong_signal; + s8 sensitivity; + u8 beacon_mask; u8 beacon_check; @@ -250,5 +258,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); +void mt7603_cca_stats_reset(struct mt7603_dev *dev); #endif diff --git a/mt7603/regs.h b/mt7603/regs.h index ec199ce06..3145c9970 100644 --- a/mt7603/regs.h +++ b/mt7603/regs.h @@ -150,6 +150,9 @@ #define MT_AGC_BASE MT_WF_PHY(0x500) #define MT_AGC(n) (MT_AGC_BASE + ((n) * 4)) +#define MT_AGC1_BASE MT_WF_PHY(0x1500) +#define MT_AGC1(n) (MT_AGC1_BASE + ((n) * 4)) + #define MT_AGC_41_RSSI_0 GENMASK(23, 16) #define MT_AGC_41_RSSI_1 GENMASK(7, 0) @@ -168,6 +171,20 @@ ((phy) * MT_WF_PHY_OFFSET) + \ ((n) * 4)) +#define MT_PHYCTRL_BASE MT_WF_PHY(0x4100) +#define MT_PHYCTRL(n) (MT_PHYCTRL_BASE + ((n) * 4)) + +#define MT_PHYCTRL_2_STATUS_RESET BIT(6) +#define MT_PHYCTRL_2_STATUS_EN BIT(7) + +#define MT_PHYCTRL_STAT_PD MT_PHYCTRL(3) +#define MT_PHYCTRL_STAT_PD_OFDM GENMASK(31, 16) +#define MT_PHYCTRL_STAT_PD_CCK GENMASK(15, 0) + +#define MT_PHYCTRL_STAT_MDRDY MT_PHYCTRL(8) +#define MT_PHYCTRL_STAT_MDRDY_OFDM GENMASK(31, 16) +#define MT_PHYCTRL_STAT_MDRDY_CCK GENMASK(15, 0) + #define MT_WF_AGG_BASE 0x21200 #define MT_WF_AGG(ofs) (MT_WF_AGG_BASE + (ofs))