summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath11k/wow.c
diff options
context:
space:
mode:
authorCarl Huang <quic_cjhuang@quicinc.com>2022-03-14 07:18:16 +0200
committerKalle Valo <quic_kvalo@quicinc.com>2022-03-18 17:36:02 +0200
commitc3c36bfe998b3ad14aa87a57037a05d861889ac8 (patch)
tree64db38bd05fda5ff5785c989c135b4c43820e8d1 /drivers/net/wireless/ath/ath11k/wow.c
parent90bf5c8d0f7ecddf96fc1cd9434af4e157b51970 (diff)
downloadlinux-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.c52
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) {