wifi: mt76: mt7921: cqm rssi low/high event notify
authorRong Yan <rong.yan@mediatek.com>
Wed, 3 Apr 2024 09:52:14 +0000 (17:52 +0800)
committerFelix Fietkau <nbd@nbd.name>
Thu, 2 May 2024 10:47:04 +0000 (12:47 +0200)
The implementation amounts to setting the driver flag
IEEE80211_VIF_SUPPORTS_CQM_RSSI, and then providing
mechanisms for continuously updating enough information
to be able to provide notifications to userspace when
RSSI drops below a certain threshold

Signed-off-by: Rong Yan <rong.yan@mediatek.com>
Signed-off-by: Ming Yen Hsieh <mingyen.hsieh@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
drivers/net/wireless/mediatek/mt76/mt7921/main.c
drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
drivers/net/wireless/mediatek/mt76/mt792x.h

index 836cc4d5b1d2ccf6359fa510647adb750c385139..01a65d41b86ed8ad536480145ff1970307a9e3ca 100644 (file)
@@ -1011,6 +1011,7 @@ enum {
        MCU_EVENT_CH_PRIVILEGE = 0x18,
        MCU_EVENT_SCHED_SCAN_DONE = 0x23,
        MCU_EVENT_DBG_MSG = 0x27,
+       MCU_EVENT_RSSI_NOTIFY = 0x96,
        MCU_EVENT_TXPWR = 0xd0,
        MCU_EVENT_EXT = 0xed,
        MCU_EVENT_RESTART_DL = 0xef,
@@ -1311,6 +1312,7 @@ enum {
        MCU_CE_CMD_SCHED_SCAN_ENABLE = 0x61,
        MCU_CE_CMD_SCHED_SCAN_REQ = 0x62,
        MCU_CE_CMD_GET_NIC_CAPAB = 0x8a,
+       MCU_CE_CMD_RSSI_MONITOR = 0xa1,
        MCU_CE_CMD_SET_MU_EDCA_PARMS = 0xb0,
        MCU_CE_CMD_REG_WRITE = 0xc0,
        MCU_CE_CMD_REG_READ = 0xc0,
@@ -1456,6 +1458,10 @@ struct mt76_connac_beacon_loss_event {
        u8 pad[2];
 } __packed;
 
+struct mt76_connac_rssi_notify_event {
+       __le32 rssi[4];
+} __packed;
+
 struct mt76_connac_mcu_bss_event {
        u8 bss_idx;
        u8 is_absent;
index ca36de34171b6a607f5f55a1a910d3b0b26f2d3f..afcda7c481e08244e315754c09faa04fd62c034a 100644 (file)
@@ -310,6 +310,8 @@ mt7921_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
        }
 
        vif->driver_flags |= IEEE80211_VIF_BEACON_FILTER;
+       if (phy->chip_cap & MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN)
+               vif->driver_flags |= IEEE80211_VIF_SUPPORTS_CQM_RSSI;
 out:
        mt792x_mutex_release(dev);
 
@@ -679,6 +681,9 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw,
        if (changed & BSS_CHANGED_PS)
                mt7921_mcu_uni_bss_ps(dev, vif);
 
+       if (changed & BSS_CHANGED_CQM)
+               mt7921_mcu_set_rssimonitor(dev, vif);
+
        if (changed & BSS_CHANGED_ASSOC) {
                mt7921_mcu_sta_update(dev, NULL, vif, true,
                                      MT76_STA_INFO_STATE_ASSOC);
index 6a3a448db75a25001ab8cfefac93956c2ff9b547..f0b89b03083abd03747684b67f61e84fbef81794 100644 (file)
@@ -253,6 +253,42 @@ mt7921_mcu_tx_done_event(struct mt792x_dev *dev, struct sk_buff *skb)
        mt7921_mac_add_txs(dev, event->txs);
 }
 
+static void
+mt7921_mcu_rssi_monitor_iter(void *priv, u8 *mac,
+                            struct ieee80211_vif *vif)
+{
+       struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
+       struct mt76_connac_rssi_notify_event *event = priv;
+       enum nl80211_cqm_rssi_threshold_event nl_event;
+       s32 rssi = le32_to_cpu(event->rssi[mvif->mt76.idx]);
+
+       if (!rssi)
+               return;
+
+       if (!(vif->driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI))
+               return;
+
+       if (rssi > vif->bss_conf.cqm_rssi_thold)
+               nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH;
+       else
+               nl_event = NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW;
+
+       ieee80211_cqm_rssi_notify(vif, nl_event, rssi, GFP_KERNEL);
+}
+
+static void
+mt7921_mcu_rssi_monitor_event(struct mt792x_dev *dev, struct sk_buff *skb)
+{
+       struct mt76_connac_rssi_notify_event *event;
+
+       skb_pull(skb, sizeof(struct mt76_connac2_mcu_rxd));
+       event = (struct mt76_connac_rssi_notify_event *)skb->data;
+
+       ieee80211_iterate_active_interfaces_atomic(mt76_hw(dev),
+                                                  IEEE80211_IFACE_ITER_RESUME_ALL,
+                                                  mt7921_mcu_rssi_monitor_iter, event);
+}
+
 static void
 mt7921_mcu_rx_unsolicited_event(struct mt792x_dev *dev, struct sk_buff *skb)
 {
@@ -281,6 +317,9 @@ mt7921_mcu_rx_unsolicited_event(struct mt792x_dev *dev, struct sk_buff *skb)
        case MCU_EVENT_TX_DONE:
                mt7921_mcu_tx_done_event(dev, skb);
                break;
+       case MCU_EVENT_RSSI_NOTIFY:
+               mt7921_mcu_rssi_monitor_event(dev, skb);
+               break;
        default:
                break;
        }
@@ -327,6 +366,7 @@ void mt7921_mcu_rx_event(struct mt792x_dev *dev, struct sk_buff *skb)
        if (rxd->ext_eid == MCU_EXT_EVENT_RATE_REPORT ||
            rxd->eid == MCU_EVENT_BSS_BEACON_LOSS ||
            rxd->eid == MCU_EVENT_SCHED_SCAN_DONE ||
+           rxd->eid == MCU_EVENT_RSSI_NOTIFY ||
            rxd->eid == MCU_EVENT_SCAN_DONE ||
            rxd->eid == MCU_EVENT_TX_DONE ||
            rxd->eid == MCU_EVENT_DBG_MSG ||
@@ -1391,3 +1431,24 @@ int mt7921_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,
        return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(SET_RX_FILTER),
                                 &data, sizeof(data), false);
 }
+
+int mt7921_mcu_set_rssimonitor(struct mt792x_dev *dev, struct ieee80211_vif *vif)
+{
+       struct mt792x_vif *mvif = (struct mt792x_vif *)vif->drv_priv;
+       struct {
+               u8 enable;
+               s8 cqm_rssi_high;
+               s8 cqm_rssi_low;
+               u8 bss_idx;
+               u16 duration;
+               u8 rsv2[2];
+       } __packed data = {
+               .enable = vif->cfg.assoc,
+               .cqm_rssi_high = vif->bss_conf.cqm_rssi_thold + vif->bss_conf.cqm_rssi_hyst,
+               .cqm_rssi_low = vif->bss_conf.cqm_rssi_thold - vif->bss_conf.cqm_rssi_hyst,
+               .bss_idx = mvif->mt76.idx,
+       };
+
+       return mt76_mcu_send_msg(&dev->mt76, MCU_CE_CMD(RSSI_MONITOR),
+                                &data, sizeof(data), false);
+}
index 3016636d18c6fb25da215bbdf509c2dd3c5a5306..62617589a84fa8e12cacfdcc1a19327115af3935 100644 (file)
@@ -323,4 +323,5 @@ int mt7921_mcu_set_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,
 int mt7921_mcu_abort_roc(struct mt792x_phy *phy, struct mt792x_vif *vif,
                         u8 token_id);
 void mt7921_roc_abort_sync(struct mt792x_dev *dev);
+int mt7921_mcu_set_rssimonitor(struct mt792x_dev *dev, struct ieee80211_vif *vif);
 #endif
index 8c9fb5e98c6eeae1dfc8a87832d44d0463bf4cf5..20578497a405c2cc3453bb2873704e5e6f42297c 100644 (file)
@@ -26,6 +26,7 @@
 #define MT792x_FW_CAP_CNM      BIT(7)
 
 #define MT792x_CHIP_CAP_CLC_EVT_EN BIT(0)
+#define MT792x_CHIP_CAP_RSSI_NOTIFY_EVT_EN BIT(1)
 
 /* NOTE: used to map mt76_rates. idx may change if firmware expands table */
 #define MT792x_BASIC_RATES_TBL 11