From cf0badbc049748dd3cf2441d8e533194bc7376aa Mon Sep 17 00:00:00 2001 From: Sean Wang Date: Tue, 6 Apr 2021 11:34:34 +0800 Subject: [PATCH] mt76: mt7921: fix inappropriate WoW setup with the missing ARP informaiton Fix the Wake-on-WoWLAN failure should rely on ARP Information is being updated in time to the firmware. Fixes: ffa1bf97425b ("mt76: mt7921: introduce PM support") Signed-off-by: Sean Wang Signed-off-by: Felix Fietkau --- mt7921/main.c | 3 +++ mt7921/mcu.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ mt7921/mt7921.h | 3 +++ 3 files changed, 50 insertions(+) diff --git a/mt7921/main.c b/mt7921/main.c index d1a314c21..e0270d1c6 100644 --- a/mt7921/main.c +++ b/mt7921/main.c @@ -626,6 +626,9 @@ static void mt7921_bss_info_changed(struct ieee80211_hw *hw, if (changed & BSS_CHANGED_ASSOC) mt7921_bss_bcnft_apply(dev, vif, info->assoc); + if (changed & BSS_CHANGED_ARP_FILTER) + mt7921_mcu_update_arp_filter(hw, vif, info); + mt7921_mutex_release(dev); } diff --git a/mt7921/mcu.c b/mt7921/mcu.c index 4737827df..95af87059 100644 --- a/mt7921/mcu.c +++ b/mt7921/mcu.c @@ -1326,3 +1326,47 @@ mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif) mt76_clear(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON); } } + +int mt7921_mcu_update_arp_filter(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info) +{ + struct mt7921_vif *mvif = (struct mt7921_vif *)vif->drv_priv; + struct mt7921_dev *dev = mt7921_hw_dev(hw); + struct sk_buff *skb; + int i, len = min_t(int, info->arp_addr_cnt, + IEEE80211_BSS_ARP_ADDR_LIST_LEN); + struct { + struct { + u8 bss_idx; + u8 pad[3]; + } __packed hdr; + struct mt76_connac_arpns_tlv arp; + } req_hdr = { + .hdr = { + .bss_idx = mvif->mt76.idx, + }, + .arp = { + .tag = cpu_to_le16(UNI_OFFLOAD_OFFLOAD_ARP), + .len = cpu_to_le16(sizeof(struct mt76_connac_arpns_tlv)), + .ips_num = len, + .mode = 2, /* update */ + .option = 1, + }, + }; + + skb = mt76_mcu_msg_alloc(&dev->mt76, NULL, + sizeof(req_hdr) + len * sizeof(__be32)); + if (!skb) + return -ENOMEM; + + skb_put_data(skb, &req_hdr, sizeof(req_hdr)); + for (i = 0; i < len; i++) { + u8 *addr = (u8 *)skb_put(skb, sizeof(__be32)); + + memcpy(addr, &info->arp_addr_list[i], sizeof(__be32)); + } + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_UNI_CMD_OFFLOAD, + true); +} diff --git a/mt7921/mt7921.h b/mt7921/mt7921.h index 5cedefc41..ebe51017d 100644 --- a/mt7921/mt7921.h +++ b/mt7921/mt7921.h @@ -348,4 +348,7 @@ int mt7921_mac_set_beacon_filter(struct mt7921_phy *phy, bool enable); void mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif); void mt7921_coredump_work(struct work_struct *work); +int mt7921_mcu_update_arp_filter(struct ieee80211_hw *hw, + struct ieee80211_vif *vif, + struct ieee80211_bss_conf *info); #endif