Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: BSD-3-Clause-Clear
0002 /*
0003  * Copyright (c) 2020 The Linux Foundation. All rights reserved.
0004  */
0005 
0006 #include <linux/delay.h>
0007 
0008 #include "mac.h"
0009 
0010 #include <net/mac80211.h>
0011 #include "core.h"
0012 #include "hif.h"
0013 #include "debug.h"
0014 #include "wmi.h"
0015 #include "wow.h"
0016 #include "dp_rx.h"
0017 
0018 static const struct wiphy_wowlan_support ath11k_wowlan_support = {
0019     .flags = WIPHY_WOWLAN_DISCONNECT |
0020          WIPHY_WOWLAN_MAGIC_PKT |
0021          WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
0022          WIPHY_WOWLAN_GTK_REKEY_FAILURE,
0023     .pattern_min_len = WOW_MIN_PATTERN_SIZE,
0024     .pattern_max_len = WOW_MAX_PATTERN_SIZE,
0025     .max_pkt_offset = WOW_MAX_PKT_OFFSET,
0026 };
0027 
0028 int ath11k_wow_enable(struct ath11k_base *ab)
0029 {
0030     struct ath11k *ar = ath11k_ab_to_ar(ab, 0);
0031     int i, ret;
0032 
0033     clear_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags);
0034 
0035     for (i = 0; i < ATH11K_WOW_RETRY_NUM; i++) {
0036         reinit_completion(&ab->htc_suspend);
0037 
0038         ret = ath11k_wmi_wow_enable(ar);
0039         if (ret) {
0040             ath11k_warn(ab, "failed to issue wow enable: %d\n", ret);
0041             return ret;
0042         }
0043 
0044         ret = wait_for_completion_timeout(&ab->htc_suspend, 3 * HZ);
0045         if (ret == 0) {
0046             ath11k_warn(ab,
0047                     "timed out while waiting for htc suspend completion\n");
0048             return -ETIMEDOUT;
0049         }
0050 
0051         if (test_bit(ATH11K_FLAG_HTC_SUSPEND_COMPLETE, &ab->dev_flags))
0052             /* success, suspend complete received */
0053             return 0;
0054 
0055         ath11k_warn(ab, "htc suspend not complete, retrying (try %d)\n",
0056                 i);
0057         msleep(ATH11K_WOW_RETRY_WAIT_MS);
0058     }
0059 
0060     ath11k_warn(ab, "htc suspend not complete, failing after %d tries\n", i);
0061 
0062     return -ETIMEDOUT;
0063 }
0064 
0065 int ath11k_wow_wakeup(struct ath11k_base *ab)
0066 {
0067     struct ath11k *ar = ath11k_ab_to_ar(ab, 0);
0068     int ret;
0069 
0070     reinit_completion(&ab->wow.wakeup_completed);
0071 
0072     ret = ath11k_wmi_wow_host_wakeup_ind(ar);
0073     if (ret) {
0074         ath11k_warn(ab, "failed to send wow wakeup indication: %d\n",
0075                 ret);
0076         return ret;
0077     }
0078 
0079     ret = wait_for_completion_timeout(&ab->wow.wakeup_completed, 3 * HZ);
0080     if (ret == 0) {
0081         ath11k_warn(ab, "timed out while waiting for wow wakeup completion\n");
0082         return -ETIMEDOUT;
0083     }
0084 
0085     return 0;
0086 }
0087 
0088 static int ath11k_wow_vif_cleanup(struct ath11k_vif *arvif)
0089 {
0090     struct ath11k *ar = arvif->ar;
0091     int i, ret;
0092 
0093     for (i = 0; i < WOW_EVENT_MAX; i++) {
0094         ret = ath11k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 0);
0095         if (ret) {
0096             ath11k_warn(ar->ab, "failed to issue wow wakeup for event %s on vdev %i: %d\n",
0097                     wow_wakeup_event(i), arvif->vdev_id, ret);
0098             return ret;
0099         }
0100     }
0101 
0102     for (i = 0; i < ar->wow.max_num_patterns; i++) {
0103         ret = ath11k_wmi_wow_del_pattern(ar, arvif->vdev_id, i);
0104         if (ret) {
0105             ath11k_warn(ar->ab, "failed to delete wow pattern %d for vdev %i: %d\n",
0106                     i, arvif->vdev_id, ret);
0107             return ret;
0108         }
0109     }
0110 
0111     return 0;
0112 }
0113 
0114 static int ath11k_wow_cleanup(struct ath11k *ar)
0115 {
0116     struct ath11k_vif *arvif;
0117     int ret;
0118 
0119     lockdep_assert_held(&ar->conf_mutex);
0120 
0121     list_for_each_entry(arvif, &ar->arvifs, list) {
0122         ret = ath11k_wow_vif_cleanup(arvif);
0123         if (ret) {
0124             ath11k_warn(ar->ab, "failed to clean wow wakeups on vdev %i: %d\n",
0125                     arvif->vdev_id, ret);
0126             return ret;
0127         }
0128     }
0129 
0130     return 0;
0131 }
0132 
0133 /* Convert a 802.3 format to a 802.11 format.
0134  *         +------------+-----------+--------+----------------+
0135  * 802.3:  |dest mac(6B)|src mac(6B)|type(2B)|     body...    |
0136  *         +------------+-----------+--------+----------------+
0137  *                |__         |_______    |____________  |________
0138  *                   |                |                |          |
0139  *         +--+------------+----+-----------+---------------+-----------+
0140  * 802.11: |4B|dest mac(6B)| 6B |src mac(6B)|  8B  |type(2B)|  body...  |
0141  *         +--+------------+----+-----------+---------------+-----------+
0142  */
0143 static void ath11k_wow_convert_8023_to_80211(struct cfg80211_pkt_pattern *new,
0144                          const struct cfg80211_pkt_pattern *old)
0145 {
0146     u8 hdr_8023_pattern[ETH_HLEN] = {};
0147     u8 hdr_8023_bit_mask[ETH_HLEN] = {};
0148     u8 hdr_80211_pattern[WOW_HDR_LEN] = {};
0149     u8 hdr_80211_bit_mask[WOW_HDR_LEN] = {};
0150 
0151     int total_len = old->pkt_offset + old->pattern_len;
0152     int hdr_80211_end_offset;
0153 
0154     struct ieee80211_hdr_3addr *new_hdr_pattern =
0155         (struct ieee80211_hdr_3addr *)hdr_80211_pattern;
0156     struct ieee80211_hdr_3addr *new_hdr_mask =
0157         (struct ieee80211_hdr_3addr *)hdr_80211_bit_mask;
0158     struct ethhdr *old_hdr_pattern = (struct ethhdr *)hdr_8023_pattern;
0159     struct ethhdr *old_hdr_mask = (struct ethhdr *)hdr_8023_bit_mask;
0160     int hdr_len = sizeof(*new_hdr_pattern);
0161 
0162     struct rfc1042_hdr *new_rfc_pattern =
0163         (struct rfc1042_hdr *)(hdr_80211_pattern + hdr_len);
0164     struct rfc1042_hdr *new_rfc_mask =
0165         (struct rfc1042_hdr *)(hdr_80211_bit_mask + hdr_len);
0166     int rfc_len = sizeof(*new_rfc_pattern);
0167 
0168     memcpy(hdr_8023_pattern + old->pkt_offset,
0169            old->pattern, ETH_HLEN - old->pkt_offset);
0170     memcpy(hdr_8023_bit_mask + old->pkt_offset,
0171            old->mask, ETH_HLEN - old->pkt_offset);
0172 
0173     /* Copy destination address */
0174     memcpy(new_hdr_pattern->addr1, old_hdr_pattern->h_dest, ETH_ALEN);
0175     memcpy(new_hdr_mask->addr1, old_hdr_mask->h_dest, ETH_ALEN);
0176 
0177     /* Copy source address */
0178     memcpy(new_hdr_pattern->addr3, old_hdr_pattern->h_source, ETH_ALEN);
0179     memcpy(new_hdr_mask->addr3, old_hdr_mask->h_source, ETH_ALEN);
0180 
0181     /* Copy logic link type */
0182     memcpy(&new_rfc_pattern->snap_type,
0183            &old_hdr_pattern->h_proto,
0184            sizeof(old_hdr_pattern->h_proto));
0185     memcpy(&new_rfc_mask->snap_type,
0186            &old_hdr_mask->h_proto,
0187            sizeof(old_hdr_mask->h_proto));
0188 
0189     /* Compute new pkt_offset */
0190     if (old->pkt_offset < ETH_ALEN)
0191         new->pkt_offset = old->pkt_offset +
0192             offsetof(struct ieee80211_hdr_3addr, addr1);
0193     else if (old->pkt_offset < offsetof(struct ethhdr, h_proto))
0194         new->pkt_offset = old->pkt_offset +
0195             offsetof(struct ieee80211_hdr_3addr, addr3) -
0196             offsetof(struct ethhdr, h_source);
0197     else
0198         new->pkt_offset = old->pkt_offset + hdr_len + rfc_len - ETH_HLEN;
0199 
0200     /* Compute new hdr end offset */
0201     if (total_len > ETH_HLEN)
0202         hdr_80211_end_offset = hdr_len + rfc_len;
0203     else if (total_len > offsetof(struct ethhdr, h_proto))
0204         hdr_80211_end_offset = hdr_len + rfc_len + total_len - ETH_HLEN;
0205     else if (total_len > ETH_ALEN)
0206         hdr_80211_end_offset = total_len - ETH_ALEN +
0207             offsetof(struct ieee80211_hdr_3addr, addr3);
0208     else
0209         hdr_80211_end_offset = total_len +
0210             offsetof(struct ieee80211_hdr_3addr, addr1);
0211 
0212     new->pattern_len = hdr_80211_end_offset - new->pkt_offset;
0213 
0214     memcpy((u8 *)new->pattern,
0215            hdr_80211_pattern + new->pkt_offset,
0216            new->pattern_len);
0217     memcpy((u8 *)new->mask,
0218            hdr_80211_bit_mask + new->pkt_offset,
0219            new->pattern_len);
0220 
0221     if (total_len > ETH_HLEN) {
0222         /* Copy frame body */
0223         memcpy((u8 *)new->pattern + new->pattern_len,
0224                (void *)old->pattern + ETH_HLEN - old->pkt_offset,
0225                total_len - ETH_HLEN);
0226         memcpy((u8 *)new->mask + new->pattern_len,
0227                (void *)old->mask + ETH_HLEN - old->pkt_offset,
0228                total_len - ETH_HLEN);
0229 
0230         new->pattern_len += total_len - ETH_HLEN;
0231     }
0232 }
0233 
0234 static int ath11k_wmi_pno_check_and_convert(struct ath11k *ar, u32 vdev_id,
0235                         struct cfg80211_sched_scan_request *nd_config,
0236                         struct wmi_pno_scan_req *pno)
0237 {
0238     int i, j;
0239     u8 ssid_len;
0240 
0241     pno->enable = 1;
0242     pno->vdev_id = vdev_id;
0243     pno->uc_networks_count = nd_config->n_match_sets;
0244 
0245     if (!pno->uc_networks_count ||
0246         pno->uc_networks_count > WMI_PNO_MAX_SUPP_NETWORKS)
0247         return -EINVAL;
0248 
0249     if (nd_config->n_channels > WMI_PNO_MAX_NETW_CHANNELS_EX)
0250         return -EINVAL;
0251 
0252     /* Filling per profile params */
0253     for (i = 0; i < pno->uc_networks_count; i++) {
0254         ssid_len = nd_config->match_sets[i].ssid.ssid_len;
0255 
0256         if (ssid_len == 0 || ssid_len > 32)
0257             return -EINVAL;
0258 
0259         pno->a_networks[i].ssid.ssid_len = ssid_len;
0260 
0261         memcpy(pno->a_networks[i].ssid.ssid,
0262                nd_config->match_sets[i].ssid.ssid,
0263                nd_config->match_sets[i].ssid.ssid_len);
0264         pno->a_networks[i].authentication = 0;
0265         pno->a_networks[i].encryption     = 0;
0266         pno->a_networks[i].bcast_nw_type  = 0;
0267 
0268         /* Copying list of valid channel into request */
0269         pno->a_networks[i].channel_count = nd_config->n_channels;
0270         pno->a_networks[i].rssi_threshold = nd_config->match_sets[i].rssi_thold;
0271 
0272         for (j = 0; j < nd_config->n_channels; j++) {
0273             pno->a_networks[i].channels[j] =
0274                     nd_config->channels[j]->center_freq;
0275         }
0276     }
0277 
0278     /* set scan to passive if no SSIDs are specified in the request */
0279     if (nd_config->n_ssids == 0)
0280         pno->do_passive_scan = true;
0281     else
0282         pno->do_passive_scan = false;
0283 
0284     for (i = 0; i < nd_config->n_ssids; i++) {
0285         j = 0;
0286         while (j < pno->uc_networks_count) {
0287             if (pno->a_networks[j].ssid.ssid_len ==
0288                 nd_config->ssids[i].ssid_len &&
0289             (memcmp(pno->a_networks[j].ssid.ssid,
0290                 nd_config->ssids[i].ssid,
0291                 pno->a_networks[j].ssid.ssid_len) == 0)) {
0292                 pno->a_networks[j].bcast_nw_type = BCAST_HIDDEN;
0293                 break;
0294             }
0295             j++;
0296         }
0297     }
0298 
0299     if (nd_config->n_scan_plans == 2) {
0300         pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC;
0301         pno->fast_scan_max_cycles = nd_config->scan_plans[0].iterations;
0302         pno->slow_scan_period =
0303             nd_config->scan_plans[1].interval * MSEC_PER_SEC;
0304     } else if (nd_config->n_scan_plans == 1) {
0305         pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC;
0306         pno->fast_scan_max_cycles = 1;
0307         pno->slow_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC;
0308     } else {
0309         ath11k_warn(ar->ab, "Invalid number of scan plans %d !!",
0310                 nd_config->n_scan_plans);
0311     }
0312 
0313     if (nd_config->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) {
0314         /* enable mac randomization */
0315         pno->enable_pno_scan_randomization = 1;
0316         memcpy(pno->mac_addr, nd_config->mac_addr, ETH_ALEN);
0317         memcpy(pno->mac_addr_mask, nd_config->mac_addr_mask, ETH_ALEN);
0318     }
0319 
0320     pno->delay_start_time = nd_config->delay;
0321 
0322     /* Current FW does not support min-max range for dwell time */
0323     pno->active_max_time = WMI_ACTIVE_MAX_CHANNEL_TIME;
0324     pno->passive_max_time = WMI_PASSIVE_MAX_CHANNEL_TIME;
0325 
0326     return 0;
0327 }
0328 
0329 static int ath11k_vif_wow_set_wakeups(struct ath11k_vif *arvif,
0330                       struct cfg80211_wowlan *wowlan)
0331 {
0332     int ret, i;
0333     unsigned long wow_mask = 0;
0334     struct ath11k *ar = arvif->ar;
0335     const struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
0336     int pattern_id = 0;
0337 
0338     /* Setup requested WOW features */
0339     switch (arvif->vdev_type) {
0340     case WMI_VDEV_TYPE_IBSS:
0341         __set_bit(WOW_BEACON_EVENT, &wow_mask);
0342         fallthrough;
0343     case WMI_VDEV_TYPE_AP:
0344         __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask);
0345         __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask);
0346         __set_bit(WOW_PROBE_REQ_WPS_IE_EVENT, &wow_mask);
0347         __set_bit(WOW_AUTH_REQ_EVENT, &wow_mask);
0348         __set_bit(WOW_ASSOC_REQ_EVENT, &wow_mask);
0349         __set_bit(WOW_HTT_EVENT, &wow_mask);
0350         __set_bit(WOW_RA_MATCH_EVENT, &wow_mask);
0351         break;
0352     case WMI_VDEV_TYPE_STA:
0353         if (wowlan->disconnect) {
0354             __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask);
0355             __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask);
0356             __set_bit(WOW_BMISS_EVENT, &wow_mask);
0357             __set_bit(WOW_CSA_IE_EVENT, &wow_mask);
0358         }
0359 
0360         if (wowlan->magic_pkt)
0361             __set_bit(WOW_MAGIC_PKT_RECVD_EVENT, &wow_mask);
0362 
0363         if (wowlan->nd_config) {
0364             struct wmi_pno_scan_req *pno;
0365             int ret;
0366 
0367             pno = kzalloc(sizeof(*pno), GFP_KERNEL);
0368             if (!pno)
0369                 return -ENOMEM;
0370 
0371             ar->nlo_enabled = true;
0372 
0373             ret = ath11k_wmi_pno_check_and_convert(ar, arvif->vdev_id,
0374                                    wowlan->nd_config, pno);
0375             if (!ret) {
0376                 ath11k_wmi_wow_config_pno(ar, arvif->vdev_id, pno);
0377                 __set_bit(WOW_NLO_DETECTED_EVENT, &wow_mask);
0378             }
0379 
0380             kfree(pno);
0381         }
0382         break;
0383     default:
0384         break;
0385     }
0386 
0387     for (i = 0; i < wowlan->n_patterns; i++) {
0388         u8 bitmask[WOW_MAX_PATTERN_SIZE] = {};
0389         u8 ath_pattern[WOW_MAX_PATTERN_SIZE] = {};
0390         u8 ath_bitmask[WOW_MAX_PATTERN_SIZE] = {};
0391         struct cfg80211_pkt_pattern new_pattern = {};
0392         struct cfg80211_pkt_pattern old_pattern = patterns[i];
0393         int j;
0394 
0395         new_pattern.pattern = ath_pattern;
0396         new_pattern.mask = ath_bitmask;
0397         if (patterns[i].pattern_len > WOW_MAX_PATTERN_SIZE)
0398             continue;
0399         /* convert bytemask to bitmask */
0400         for (j = 0; j < patterns[i].pattern_len; j++)
0401             if (patterns[i].mask[j / 8] & BIT(j % 8))
0402                 bitmask[j] = 0xff;
0403         old_pattern.mask = bitmask;
0404 
0405         if (ar->wmi->wmi_ab->wlan_resource_config.rx_decap_mode ==
0406             ATH11K_HW_TXRX_NATIVE_WIFI) {
0407             if (patterns[i].pkt_offset < ETH_HLEN) {
0408                 u8 pattern_ext[WOW_MAX_PATTERN_SIZE] = {};
0409 
0410                 memcpy(pattern_ext, old_pattern.pattern,
0411                        old_pattern.pattern_len);
0412                 old_pattern.pattern = pattern_ext;
0413                 ath11k_wow_convert_8023_to_80211(&new_pattern,
0414                                  &old_pattern);
0415             } else {
0416                 new_pattern = old_pattern;
0417                 new_pattern.pkt_offset += WOW_HDR_LEN - ETH_HLEN;
0418             }
0419         }
0420 
0421         if (WARN_ON(new_pattern.pattern_len > WOW_MAX_PATTERN_SIZE))
0422             return -EINVAL;
0423 
0424         ret = ath11k_wmi_wow_add_pattern(ar, arvif->vdev_id,
0425                          pattern_id,
0426                          new_pattern.pattern,
0427                          new_pattern.mask,
0428                          new_pattern.pattern_len,
0429                          new_pattern.pkt_offset);
0430         if (ret) {
0431             ath11k_warn(ar->ab, "failed to add pattern %i to vdev %i: %d\n",
0432                     pattern_id,
0433                     arvif->vdev_id, ret);
0434             return ret;
0435         }
0436 
0437         pattern_id++;
0438         __set_bit(WOW_PATTERN_MATCH_EVENT, &wow_mask);
0439     }
0440 
0441     for (i = 0; i < WOW_EVENT_MAX; i++) {
0442         if (!test_bit(i, &wow_mask))
0443             continue;
0444         ret = ath11k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 1);
0445         if (ret) {
0446             ath11k_warn(ar->ab, "failed to enable wakeup event %s on vdev %i: %d\n",
0447                     wow_wakeup_event(i), arvif->vdev_id, ret);
0448             return ret;
0449         }
0450     }
0451 
0452     return 0;
0453 }
0454 
0455 static int ath11k_wow_set_wakeups(struct ath11k *ar,
0456                   struct cfg80211_wowlan *wowlan)
0457 {
0458     struct ath11k_vif *arvif;
0459     int ret;
0460 
0461     lockdep_assert_held(&ar->conf_mutex);
0462 
0463     list_for_each_entry(arvif, &ar->arvifs, list) {
0464         ret = ath11k_vif_wow_set_wakeups(arvif, wowlan);
0465         if (ret) {
0466             ath11k_warn(ar->ab, "failed to set wow wakeups on vdev %i: %d\n",
0467                     arvif->vdev_id, ret);
0468             return ret;
0469         }
0470     }
0471 
0472     return 0;
0473 }
0474 
0475 static int ath11k_vif_wow_clean_nlo(struct ath11k_vif *arvif)
0476 {
0477     int ret = 0;
0478     struct ath11k *ar = arvif->ar;
0479 
0480     switch (arvif->vdev_type) {
0481     case WMI_VDEV_TYPE_STA:
0482         if (ar->nlo_enabled) {
0483             struct wmi_pno_scan_req *pno;
0484 
0485             pno = kzalloc(sizeof(*pno), GFP_KERNEL);
0486             if (!pno)
0487                 return -ENOMEM;
0488 
0489             pno->enable = 0;
0490             ar->nlo_enabled = false;
0491             ret = ath11k_wmi_wow_config_pno(ar, arvif->vdev_id, pno);
0492             kfree(pno);
0493         }
0494         break;
0495     default:
0496         break;
0497     }
0498     return ret;
0499 }
0500 
0501 static int ath11k_wow_nlo_cleanup(struct ath11k *ar)
0502 {
0503     struct ath11k_vif *arvif;
0504     int ret;
0505 
0506     lockdep_assert_held(&ar->conf_mutex);
0507 
0508     list_for_each_entry(arvif, &ar->arvifs, list) {
0509         ret = ath11k_vif_wow_clean_nlo(arvif);
0510         if (ret) {
0511             ath11k_warn(ar->ab, "failed to clean nlo settings on vdev %i: %d\n",
0512                     arvif->vdev_id, ret);
0513             return ret;
0514         }
0515     }
0516 
0517     return 0;
0518 }
0519 
0520 static int ath11k_wow_set_hw_filter(struct ath11k *ar)
0521 {
0522     struct ath11k_vif *arvif;
0523     u32 bitmap;
0524     int ret;
0525 
0526     lockdep_assert_held(&ar->conf_mutex);
0527 
0528     list_for_each_entry(arvif, &ar->arvifs, list) {
0529         bitmap = WMI_HW_DATA_FILTER_DROP_NON_ICMPV6_MC |
0530             WMI_HW_DATA_FILTER_DROP_NON_ARP_BC;
0531         ret = ath11k_wmi_hw_data_filter_cmd(ar, arvif->vdev_id,
0532                             bitmap,
0533                             true);
0534         if (ret) {
0535             ath11k_warn(ar->ab, "failed to set hw data filter on vdev %i: %d\n",
0536                     arvif->vdev_id, ret);
0537             return ret;
0538         }
0539     }
0540 
0541     return 0;
0542 }
0543 
0544 static int ath11k_wow_clear_hw_filter(struct ath11k *ar)
0545 {
0546     struct ath11k_vif *arvif;
0547     int ret;
0548 
0549     lockdep_assert_held(&ar->conf_mutex);
0550 
0551     list_for_each_entry(arvif, &ar->arvifs, list) {
0552         ret = ath11k_wmi_hw_data_filter_cmd(ar, arvif->vdev_id, 0, false);
0553 
0554         if (ret) {
0555             ath11k_warn(ar->ab, "failed to clear hw data filter on vdev %i: %d\n",
0556                     arvif->vdev_id, ret);
0557             return ret;
0558         }
0559     }
0560 
0561     return 0;
0562 }
0563 
0564 static int ath11k_wow_arp_ns_offload(struct ath11k *ar, bool enable)
0565 {
0566     struct ath11k_vif *arvif;
0567     int ret;
0568 
0569     lockdep_assert_held(&ar->conf_mutex);
0570 
0571     list_for_each_entry(arvif, &ar->arvifs, list) {
0572         if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
0573             continue;
0574 
0575         ret = ath11k_wmi_arp_ns_offload(ar, arvif, enable);
0576 
0577         if (ret) {
0578             ath11k_warn(ar->ab, "failed to set arp ns offload vdev %i: enable %d, ret %d\n",
0579                     arvif->vdev_id, enable, ret);
0580             return ret;
0581         }
0582     }
0583 
0584     return 0;
0585 }
0586 
0587 static int ath11k_gtk_rekey_offload(struct ath11k *ar, bool enable)
0588 {
0589     struct ath11k_vif *arvif;
0590     int ret;
0591 
0592     lockdep_assert_held(&ar->conf_mutex);
0593 
0594     list_for_each_entry(arvif, &ar->arvifs, list) {
0595         if (arvif->vdev_type != WMI_VDEV_TYPE_STA ||
0596             !arvif->is_up ||
0597             !arvif->rekey_data.enable_offload)
0598             continue;
0599 
0600         /* get rekey info before disable rekey offload */
0601         if (!enable) {
0602             ret = ath11k_wmi_gtk_rekey_getinfo(ar, arvif);
0603             if (ret) {
0604                 ath11k_warn(ar->ab, "failed to request rekey info vdev %i, ret %d\n",
0605                         arvif->vdev_id, ret);
0606                 return ret;
0607             }
0608         }
0609 
0610         ret = ath11k_wmi_gtk_rekey_offload(ar, arvif, enable);
0611 
0612         if (ret) {
0613             ath11k_warn(ar->ab, "failed to offload gtk reky vdev %i: enable %d, ret %d\n",
0614                     arvif->vdev_id, enable, ret);
0615             return ret;
0616         }
0617     }
0618 
0619     return 0;
0620 }
0621 
0622 static int ath11k_wow_protocol_offload(struct ath11k *ar, bool enable)
0623 {
0624     int ret;
0625 
0626     ret = ath11k_wow_arp_ns_offload(ar, enable);
0627     if (ret) {
0628         ath11k_warn(ar->ab, "failed to offload ARP and NS %d %d\n",
0629                 enable, ret);
0630         return ret;
0631     }
0632 
0633     ret = ath11k_gtk_rekey_offload(ar, enable);
0634     if (ret) {
0635         ath11k_warn(ar->ab, "failed to offload gtk rekey %d %d\n",
0636                 enable, ret);
0637         return ret;
0638     }
0639 
0640     return 0;
0641 }
0642 
0643 static int ath11k_wow_set_keepalive(struct ath11k *ar,
0644                     enum wmi_sta_keepalive_method method,
0645                     u32 interval)
0646 {
0647     struct ath11k_vif *arvif;
0648     int ret;
0649 
0650     lockdep_assert_held(&ar->conf_mutex);
0651 
0652     list_for_each_entry(arvif, &ar->arvifs, list) {
0653         ret = ath11k_mac_vif_set_keepalive(arvif, method, interval);
0654         if (ret)
0655             return ret;
0656     }
0657 
0658     return 0;
0659 }
0660 
0661 int ath11k_wow_op_suspend(struct ieee80211_hw *hw,
0662               struct cfg80211_wowlan *wowlan)
0663 {
0664     struct ath11k *ar = hw->priv;
0665     int ret;
0666 
0667     mutex_lock(&ar->conf_mutex);
0668 
0669     ret = ath11k_dp_rx_pktlog_stop(ar->ab, true);
0670     if (ret) {
0671         ath11k_warn(ar->ab,
0672                 "failed to stop dp rx (and timer) pktlog during wow suspend: %d\n",
0673                 ret);
0674         goto exit;
0675     }
0676 
0677     ret =  ath11k_wow_cleanup(ar);
0678     if (ret) {
0679         ath11k_warn(ar->ab, "failed to clear wow wakeup events: %d\n",
0680                 ret);
0681         goto exit;
0682     }
0683 
0684     ret = ath11k_wow_set_wakeups(ar, wowlan);
0685     if (ret) {
0686         ath11k_warn(ar->ab, "failed to set wow wakeup events: %d\n",
0687                 ret);
0688         goto cleanup;
0689     }
0690 
0691     ret = ath11k_wow_protocol_offload(ar, true);
0692     if (ret) {
0693         ath11k_warn(ar->ab, "failed to set wow protocol offload events: %d\n",
0694                 ret);
0695         goto cleanup;
0696     }
0697 
0698     ath11k_mac_drain_tx(ar);
0699     ret = ath11k_mac_wait_tx_complete(ar);
0700     if (ret) {
0701         ath11k_warn(ar->ab, "failed to wait tx complete: %d\n", ret);
0702         goto cleanup;
0703     }
0704 
0705     ret = ath11k_wow_set_hw_filter(ar);
0706     if (ret) {
0707         ath11k_warn(ar->ab, "failed to set hw filter: %d\n",
0708                 ret);
0709         goto cleanup;
0710     }
0711 
0712     ret = ath11k_wow_set_keepalive(ar,
0713                        WMI_STA_KEEPALIVE_METHOD_NULL_FRAME,
0714                        WMI_STA_KEEPALIVE_INTERVAL_DEFAULT);
0715     if (ret) {
0716         ath11k_warn(ar->ab, "failed to enable wow keepalive: %d\n", ret);
0717         goto cleanup;
0718     }
0719 
0720     ret = ath11k_wow_enable(ar->ab);
0721     if (ret) {
0722         ath11k_warn(ar->ab, "failed to start wow: %d\n", ret);
0723         goto cleanup;
0724     }
0725 
0726     ret = ath11k_dp_rx_pktlog_stop(ar->ab, false);
0727     if (ret) {
0728         ath11k_warn(ar->ab,
0729                 "failed to stop dp rx pktlog during wow suspend: %d\n",
0730                 ret);
0731         goto cleanup;
0732     }
0733 
0734     ath11k_ce_stop_shadow_timers(ar->ab);
0735     ath11k_dp_stop_shadow_timers(ar->ab);
0736 
0737     ath11k_hif_irq_disable(ar->ab);
0738     ath11k_hif_ce_irq_disable(ar->ab);
0739 
0740     ret = ath11k_hif_suspend(ar->ab);
0741     if (ret) {
0742         ath11k_warn(ar->ab, "failed to suspend hif: %d\n", ret);
0743         goto wakeup;
0744     }
0745 
0746     goto exit;
0747 
0748 wakeup:
0749     ath11k_wow_wakeup(ar->ab);
0750 
0751 cleanup:
0752     ath11k_wow_cleanup(ar);
0753 
0754 exit:
0755     mutex_unlock(&ar->conf_mutex);
0756     return ret ? 1 : 0;
0757 }
0758 
0759 void ath11k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled)
0760 {
0761     struct ath11k *ar = hw->priv;
0762 
0763     mutex_lock(&ar->conf_mutex);
0764     device_set_wakeup_enable(ar->ab->dev, enabled);
0765     mutex_unlock(&ar->conf_mutex);
0766 }
0767 
0768 int ath11k_wow_op_resume(struct ieee80211_hw *hw)
0769 {
0770     struct ath11k *ar = hw->priv;
0771     int ret;
0772 
0773     mutex_lock(&ar->conf_mutex);
0774 
0775     ret = ath11k_hif_resume(ar->ab);
0776     if (ret) {
0777         ath11k_warn(ar->ab, "failed to resume hif: %d\n", ret);
0778         goto exit;
0779     }
0780 
0781     ath11k_hif_ce_irq_enable(ar->ab);
0782     ath11k_hif_irq_enable(ar->ab);
0783 
0784     ret = ath11k_dp_rx_pktlog_start(ar->ab);
0785     if (ret) {
0786         ath11k_warn(ar->ab, "failed to start rx pktlog from wow: %d\n", ret);
0787         goto exit;
0788     }
0789 
0790     ret = ath11k_wow_wakeup(ar->ab);
0791     if (ret) {
0792         ath11k_warn(ar->ab, "failed to wakeup from wow: %d\n", ret);
0793         goto exit;
0794     }
0795 
0796     ret = ath11k_wow_nlo_cleanup(ar);
0797     if (ret) {
0798         ath11k_warn(ar->ab, "failed to cleanup nlo: %d\n", ret);
0799         goto exit;
0800     }
0801 
0802     ret = ath11k_wow_clear_hw_filter(ar);
0803     if (ret) {
0804         ath11k_warn(ar->ab, "failed to clear hw filter: %d\n", ret);
0805         goto exit;
0806     }
0807 
0808     ret = ath11k_wow_protocol_offload(ar, false);
0809     if (ret) {
0810         ath11k_warn(ar->ab, "failed to clear wow protocol offload events: %d\n",
0811                 ret);
0812         goto exit;
0813     }
0814 
0815     ret = ath11k_wow_set_keepalive(ar,
0816                        WMI_STA_KEEPALIVE_METHOD_NULL_FRAME,
0817                        WMI_STA_KEEPALIVE_INTERVAL_DISABLE);
0818     if (ret) {
0819         ath11k_warn(ar->ab, "failed to disable wow keepalive: %d\n", ret);
0820         goto exit;
0821     }
0822 
0823 exit:
0824     if (ret) {
0825         switch (ar->state) {
0826         case ATH11K_STATE_ON:
0827             ar->state = ATH11K_STATE_RESTARTING;
0828             ret = 1;
0829             break;
0830         case ATH11K_STATE_OFF:
0831         case ATH11K_STATE_RESTARTING:
0832         case ATH11K_STATE_RESTARTED:
0833         case ATH11K_STATE_WEDGED:
0834             ath11k_warn(ar->ab, "encountered unexpected device state %d on resume, cannot recover\n",
0835                     ar->state);
0836             ret = -EIO;
0837             break;
0838         }
0839     }
0840 
0841     mutex_unlock(&ar->conf_mutex);
0842     return ret;
0843 }
0844 
0845 int ath11k_wow_init(struct ath11k *ar)
0846 {
0847     if (!test_bit(WMI_TLV_SERVICE_WOW, ar->wmi->wmi_ab->svc_map))
0848         return 0;
0849 
0850     ar->wow.wowlan_support = ath11k_wowlan_support;
0851 
0852     if (ar->wmi->wmi_ab->wlan_resource_config.rx_decap_mode ==
0853         ATH11K_HW_TXRX_NATIVE_WIFI) {
0854         ar->wow.wowlan_support.pattern_max_len -= WOW_MAX_REDUCE;
0855         ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE;
0856     }
0857 
0858     if (test_bit(WMI_TLV_SERVICE_NLO, ar->wmi->wmi_ab->svc_map)) {
0859         ar->wow.wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT;
0860         ar->wow.wowlan_support.max_nd_match_sets = WMI_PNO_MAX_SUPP_NETWORKS;
0861     }
0862 
0863     ar->wow.max_num_patterns = ATH11K_WOW_PATTERNS;
0864     ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns;
0865     ar->hw->wiphy->wowlan = &ar->wow.wowlan_support;
0866 
0867     device_set_wakeup_capable(ar->ab->dev, true);
0868 
0869     return 0;
0870 }