diff options
author | Carl Huang <quic_cjhuang@quicinc.com> | 2022-03-14 07:18:16 +0200 |
---|---|---|
committer | Kalle Valo <quic_kvalo@quicinc.com> | 2022-03-18 17:36:02 +0200 |
commit | c3c36bfe998b3ad14aa87a57037a05d861889ac8 (patch) | |
tree | 64db38bd05fda5ff5785c989c135b4c43820e8d1 /drivers/net/wireless/ath/ath11k/wow.c | |
parent | 90bf5c8d0f7ecddf96fc1cd9434af4e157b51970 (diff) | |
download | linux-c3c36bfe998b3ad14aa87a57037a05d861889ac8.tar.gz linux-c3c36bfe998b3ad14aa87a57037a05d861889ac8.tar.bz2 linux-c3c36bfe998b3ad14aa87a57037a05d861889ac8.zip |
ath11k: support ARP and NS offload
Support ARP and NS offload in WoW state.
Tested this way: put machine A with QCA6390 to WoW state,
ping/ping6 machine A from another machine B, check sniffer to see
any ARP response and Neighbour advertisement from machine A.
Tested-on: QCA6390 hw2.0 PCI WLAN.HST.1.0.1-01740-QCAHSTSWPLZ_V2_TO_X86-1
Signed-off-by: Carl Huang <quic_cjhuang@quicinc.com>
Signed-off-by: Baochen Qiang <quic_bqiang@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://lore.kernel.org/r/1644308006-22784-6-git-send-email-quic_cjhuang@quicinc.com
Diffstat (limited to 'drivers/net/wireless/ath/ath11k/wow.c')
-rw-r--r-- | drivers/net/wireless/ath/ath11k/wow.c | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath11k/wow.c b/drivers/net/wireless/ath/ath11k/wow.c index 602b8f4c5985..bc6a4d3d6d7c 100644 --- a/drivers/net/wireless/ath/ath11k/wow.c +++ b/drivers/net/wireless/ath/ath11k/wow.c @@ -559,6 +559,43 @@ static int ath11k_wow_clear_hw_filter(struct ath11k *ar) return 0; } +static int ath11k_wow_arp_ns_offload(struct ath11k *ar, bool enable) +{ + struct ath11k_vif *arvif; + int ret; + + lockdep_assert_held(&ar->conf_mutex); + + list_for_each_entry(arvif, &ar->arvifs, list) { + if (arvif->vdev_type != WMI_VDEV_TYPE_STA) + continue; + + ret = ath11k_wmi_arp_ns_offload(ar, arvif, enable); + + if (ret) { + ath11k_warn(ar->ab, "failed to set arp ns offload vdev %i: enable %d, ret %d\n", + arvif->vdev_id, enable, ret); + return ret; + } + } + + return 0; +} + +static int ath11k_wow_protocol_offload(struct ath11k *ar, bool enable) +{ + int ret; + + ret = ath11k_wow_arp_ns_offload(ar, enable); + if (ret) { + ath11k_warn(ar->ab, "failed to offload ARP and NS %d %d\n", + enable, ret); + return ret; + } + + return 0; +} + int ath11k_wow_op_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan) { @@ -589,6 +626,14 @@ int ath11k_wow_op_suspend(struct ieee80211_hw *hw, goto cleanup; } + ret = ath11k_wow_protocol_offload(ar, true); + if (ret) { + ath11k_warn(ar->ab, "failed to set wow protocol offload events: %d\n", + ret); + goto cleanup; + } + + ath11k_mac_drain_tx(ar); ret = ath11k_mac_wait_tx_complete(ar); if (ret) { ath11k_warn(ar->ab, "failed to wait tx complete: %d\n", ret); @@ -690,6 +735,13 @@ int ath11k_wow_op_resume(struct ieee80211_hw *hw) goto exit; } + ret = ath11k_wow_protocol_offload(ar, false); + if (ret) { + ath11k_warn(ar->ab, "failed to clear wow protocol offload events: %d\n", + ret); + goto exit; + } + exit: if (ret) { switch (ar->state) { |