wifi: mt76: mt7925: cqm rssi low/high event notify

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: Jack Kao <jack.kao@mediatek.com>
Signed-off-by: Ming Yen Hsieh <mingyen.hsieh@mediatek.com>
Link: https://patch.msgid.link/20251001012506.2168037-1-mingyen.hsieh@mediatek.com
Signed-off-by: Felix Fietkau <nbd@nbd.name>
This commit is contained in:
Jack Kao 2025-10-01 09:25:06 +08:00 committed by Felix Fietkau
parent ee518f914c
commit 2a035ae206
5 changed files with 105 additions and 0 deletions

View File

@ -1062,6 +1062,7 @@ enum {
MCU_UNI_EVENT_ROC = 0x27,
MCU_UNI_EVENT_TX_DONE = 0x2d,
MCU_UNI_EVENT_THERMAL = 0x35,
MCU_UNI_EVENT_RSSI_MONITOR = 0x41,
MCU_UNI_EVENT_NIC_CAPAB = 0x43,
MCU_UNI_EVENT_WED_RRO = 0x57,
MCU_UNI_EVENT_PER_STA_INFO = 0x6d,
@ -1300,6 +1301,7 @@ enum {
MCU_UNI_CMD_THERMAL = 0x35,
MCU_UNI_CMD_VOW = 0x37,
MCU_UNI_CMD_FIXED_RATE_TABLE = 0x40,
MCU_UNI_CMD_RSSI_MONITOR = 0x41,
MCU_UNI_CMD_TESTMODE_CTRL = 0x46,
MCU_UNI_CMD_RRO = 0x57,
MCU_UNI_CMD_OFFCH_SCAN_CTRL = 0x58,

View File

@ -431,6 +431,9 @@ mt7925_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
goto out;
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);
@ -1936,6 +1939,9 @@ static void mt7925_link_info_changed(struct ieee80211_hw *hw,
mt7925_mcu_set_eht_pp(mvif->phy->mt76, &mconf->mt76,
link_conf, NULL);
if (changed & BSS_CHANGED_CQM)
mt7925_mcu_set_rssimonitor(dev, vif);
mt792x_mutex_release(dev);
}

View File

@ -447,6 +447,56 @@ mt7925_mcu_tx_done_event(struct mt792x_dev *dev, struct sk_buff *skb)
}
}
static void
mt7925_mcu_rssi_monitor_iter(void *priv, u8 *mac,
struct ieee80211_vif *vif)
{
struct mt7925_uni_rssi_monitor_event *event = priv;
enum nl80211_cqm_rssi_threshold_event nl_event;
s32 rssi = le32_to_cpu(event->rssi);
if (vif->type != NL80211_IFTYPE_STATION)
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
mt7925_mcu_rssi_monitor_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
struct tlv *tlv;
u32 tlv_len;
struct mt7925_uni_rssi_monitor_event *event;
skb_pull(skb, sizeof(struct mt7925_mcu_rxd) + 4);
tlv = (struct tlv *)skb->data;
tlv_len = skb->len;
while (tlv_len > 0 && le16_to_cpu(tlv->len) <= tlv_len) {
switch (le16_to_cpu(tlv->tag)) {
case UNI_EVENT_RSSI_MONITOR_INFO:
event = (struct mt7925_uni_rssi_monitor_event *)skb->data;
ieee80211_iterate_active_interfaces_atomic(dev->mt76.hw,
IEEE80211_IFACE_ITER_RESUME_ALL,
mt7925_mcu_rssi_monitor_iter,
event);
break;
default:
break;
}
tlv_len -= le16_to_cpu(tlv->len);
tlv = (struct tlv *)((char *)(tlv) + le16_to_cpu(tlv->len));
}
}
static void
mt7925_mcu_uni_debug_msg_event(struct mt792x_dev *dev, struct sk_buff *skb)
{
@ -543,6 +593,9 @@ mt7925_mcu_uni_rx_unsolicited_event(struct mt792x_dev *dev,
case MCU_UNI_EVENT_BSS_BEACON_LOSS:
mt7925_mcu_connection_loss_event(dev, skb);
break;
case MCU_UNI_EVENT_RSSI_MONITOR:
mt7925_mcu_rssi_monitor_event(dev, skb);
break;
case MCU_UNI_EVENT_COREDUMP:
dev->fw_assert = true;
mt76_connac_mcu_coredump_event(&dev->mt76, skb, &dev->coredump);
@ -3819,3 +3872,32 @@ int mt7925_mcu_set_rxfilter(struct mt792x_dev *dev, u32 fif,
return mt76_mcu_send_msg(&phy->dev->mt76, MCU_UNI_CMD(BAND_CONFIG),
&req, sizeof(req), true);
}
int mt7925_mcu_set_rssimonitor(struct mt792x_dev *dev, struct ieee80211_vif *vif)
{
struct mt792x_bss_conf *mconf = mt792x_link_conf_to_mconf(&vif->bss_conf);
struct {
struct {
u8 bss_idx;
u8 pad[3];
} __packed hdr;
__le16 tag;
__le16 len;
u8 enable;
s8 cqm_rssi_high;
s8 cqm_rssi_low;
u8 rsv;
} req = {
.hdr = {
.bss_idx = mconf->mt76.idx,
},
.tag = cpu_to_le16(UNI_CMD_RSSI_MONITOR_SET),
.len = cpu_to_le16(sizeof(req) - 4),
.enable = vif->cfg.assoc,
.cqm_rssi_high = (s8)(vif->bss_conf.cqm_rssi_thold + vif->bss_conf.cqm_rssi_hyst),
.cqm_rssi_low = (s8)(vif->bss_conf.cqm_rssi_thold - vif->bss_conf.cqm_rssi_hyst),
};
return mt76_mcu_send_msg(&dev->mt76, MCU_UNI_CMD(RSSI_MONITOR), &req,
sizeof(req), false);
}

View File

@ -152,6 +152,14 @@ enum {
UNI_EVENT_SCAN_DONE_NLO = 3,
};
enum {
UNI_CMD_RSSI_MONITOR_SET = 0,
};
enum {
UNI_EVENT_RSSI_MONITOR_INFO = 0,
};
enum connac3_mcu_cipher_type {
CONNAC3_CIPHER_NONE = 0,
CONNAC3_CIPHER_WEP40 = 1,

View File

@ -103,6 +103,12 @@ struct mt7925_uni_beacon_loss_event {
struct mt7925_beacon_loss_tlv beacon_loss;
} __packed;
struct mt7925_uni_rssi_monitor_event {
__le16 tag;
__le16 len;
__le32 rssi;
} __packed;
#define to_rssi(field, rxv) ((FIELD_GET(field, rxv) - 220) / 2)
#define to_rcpi(rssi) (2 * (rssi) + 220)
@ -370,4 +376,5 @@ int mt7925_testmode_cmd(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
int mt7925_testmode_dump(struct ieee80211_hw *hw, struct sk_buff *msg,
struct netlink_callback *cb, void *data, int len);
int mt7925_mcu_set_rssimonitor(struct mt792x_dev *dev, struct ieee80211_vif *vif);
#endif