Lines Matching +full:valid +full:- +full:wakeup +full:- +full:mask

1 // SPDX-License-Identifier: ISC
3 * Copyright (c) 2015-2017 Qualcomm Atheros, Inc.
14 #include "wmi-ops.h"
26 struct ath10k *ar = arvif->ar; in ath10k_wow_vif_cleanup()
30 ret = ath10k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 0); in ath10k_wow_vif_cleanup()
32 ath10k_warn(ar, "failed to issue wow wakeup for event %s on vdev %i: %d\n", in ath10k_wow_vif_cleanup()
33 wow_wakeup_event(i), arvif->vdev_id, ret); in ath10k_wow_vif_cleanup()
38 for (i = 0; i < ar->wow.max_num_patterns; i++) { in ath10k_wow_vif_cleanup()
39 ret = ath10k_wmi_wow_del_pattern(ar, arvif->vdev_id, i); in ath10k_wow_vif_cleanup()
42 i, arvif->vdev_id, ret); in ath10k_wow_vif_cleanup()
55 lockdep_assert_held(&ar->conf_mutex); in ath10k_wow_cleanup()
57 list_for_each_entry(arvif, &ar->arvifs, list) { in ath10k_wow_cleanup()
61 arvif->vdev_id, ret); in ath10k_wow_cleanup()
71 * +------------+-----------+--------+----------------+
73 * +------------+-----------+--------+----------------+
76 * +--+------------+----+-----------+---------------+-----------+
78 * +--+------------+----+-----------+---------------+-----------+
88 int total_len = old->pkt_offset + old->pattern_len; in ath10k_wow_convert_8023_to_80211()
105 memcpy(hdr_8023_pattern + old->pkt_offset, in ath10k_wow_convert_8023_to_80211()
106 old->pattern, ETH_HLEN - old->pkt_offset); in ath10k_wow_convert_8023_to_80211()
107 memcpy(hdr_8023_bit_mask + old->pkt_offset, in ath10k_wow_convert_8023_to_80211()
108 old->mask, ETH_HLEN - old->pkt_offset); in ath10k_wow_convert_8023_to_80211()
111 memcpy(new_hdr_pattern->addr1, old_hdr_pattern->h_dest, ETH_ALEN); in ath10k_wow_convert_8023_to_80211()
112 memcpy(new_hdr_mask->addr1, old_hdr_mask->h_dest, ETH_ALEN); in ath10k_wow_convert_8023_to_80211()
115 memcpy(new_hdr_pattern->addr3, old_hdr_pattern->h_source, ETH_ALEN); in ath10k_wow_convert_8023_to_80211()
116 memcpy(new_hdr_mask->addr3, old_hdr_mask->h_source, ETH_ALEN); in ath10k_wow_convert_8023_to_80211()
119 memcpy(&new_rfc_pattern->snap_type, in ath10k_wow_convert_8023_to_80211()
120 &old_hdr_pattern->h_proto, in ath10k_wow_convert_8023_to_80211()
121 sizeof(old_hdr_pattern->h_proto)); in ath10k_wow_convert_8023_to_80211()
122 memcpy(&new_rfc_mask->snap_type, in ath10k_wow_convert_8023_to_80211()
123 &old_hdr_mask->h_proto, in ath10k_wow_convert_8023_to_80211()
124 sizeof(old_hdr_mask->h_proto)); in ath10k_wow_convert_8023_to_80211()
127 if (old->pkt_offset < ETH_ALEN) in ath10k_wow_convert_8023_to_80211()
128 new->pkt_offset = old->pkt_offset + in ath10k_wow_convert_8023_to_80211()
130 else if (old->pkt_offset < offsetof(struct ethhdr, h_proto)) in ath10k_wow_convert_8023_to_80211()
131 new->pkt_offset = old->pkt_offset + in ath10k_wow_convert_8023_to_80211()
132 offsetof(struct ieee80211_hdr_3addr, addr3) - in ath10k_wow_convert_8023_to_80211()
135 new->pkt_offset = old->pkt_offset + hdr_len + rfc_len - ETH_HLEN; in ath10k_wow_convert_8023_to_80211()
141 hdr_80211_end_offset = hdr_len + rfc_len + total_len - ETH_HLEN; in ath10k_wow_convert_8023_to_80211()
143 hdr_80211_end_offset = total_len - ETH_ALEN + in ath10k_wow_convert_8023_to_80211()
149 new->pattern_len = hdr_80211_end_offset - new->pkt_offset; in ath10k_wow_convert_8023_to_80211()
151 memcpy((u8 *)new->pattern, in ath10k_wow_convert_8023_to_80211()
152 hdr_80211_pattern + new->pkt_offset, in ath10k_wow_convert_8023_to_80211()
153 new->pattern_len); in ath10k_wow_convert_8023_to_80211()
154 memcpy((u8 *)new->mask, in ath10k_wow_convert_8023_to_80211()
155 hdr_80211_bit_mask + new->pkt_offset, in ath10k_wow_convert_8023_to_80211()
156 new->pattern_len); in ath10k_wow_convert_8023_to_80211()
160 memcpy((u8 *)new->pattern + new->pattern_len, in ath10k_wow_convert_8023_to_80211()
161 (void *)old->pattern + ETH_HLEN - old->pkt_offset, in ath10k_wow_convert_8023_to_80211()
162 total_len - ETH_HLEN); in ath10k_wow_convert_8023_to_80211()
163 memcpy((u8 *)new->mask + new->pattern_len, in ath10k_wow_convert_8023_to_80211()
164 (void *)old->mask + ETH_HLEN - old->pkt_offset, in ath10k_wow_convert_8023_to_80211()
165 total_len - ETH_HLEN); in ath10k_wow_convert_8023_to_80211()
167 new->pattern_len += total_len - ETH_HLEN; in ath10k_wow_convert_8023_to_80211()
178 pno->enable = 1; in ath10k_wmi_pno_check()
179 pno->vdev_id = vdev_id; in ath10k_wmi_pno_check()
180 pno->uc_networks_count = nd_config->n_match_sets; in ath10k_wmi_pno_check()
182 if (!pno->uc_networks_count || in ath10k_wmi_pno_check()
183 pno->uc_networks_count > WMI_PNO_MAX_SUPP_NETWORKS) in ath10k_wmi_pno_check()
184 return -EINVAL; in ath10k_wmi_pno_check()
186 if (nd_config->n_channels > WMI_PNO_MAX_NETW_CHANNELS_EX) in ath10k_wmi_pno_check()
187 return -EINVAL; in ath10k_wmi_pno_check()
190 for (i = 0; i < pno->uc_networks_count; i++) { in ath10k_wmi_pno_check()
191 ssid_len = nd_config->match_sets[i].ssid.ssid_len; in ath10k_wmi_pno_check()
194 return -EINVAL; in ath10k_wmi_pno_check()
196 pno->a_networks[i].ssid.ssid_len = __cpu_to_le32(ssid_len); in ath10k_wmi_pno_check()
198 memcpy(pno->a_networks[i].ssid.ssid, in ath10k_wmi_pno_check()
199 nd_config->match_sets[i].ssid.ssid, in ath10k_wmi_pno_check()
200 nd_config->match_sets[i].ssid.ssid_len); in ath10k_wmi_pno_check()
201 pno->a_networks[i].authentication = 0; in ath10k_wmi_pno_check()
202 pno->a_networks[i].encryption = 0; in ath10k_wmi_pno_check()
203 pno->a_networks[i].bcast_nw_type = 0; in ath10k_wmi_pno_check()
205 /*Copying list of valid channel into request */ in ath10k_wmi_pno_check()
206 pno->a_networks[i].channel_count = nd_config->n_channels; in ath10k_wmi_pno_check()
207 pno->a_networks[i].rssi_threshold = nd_config->match_sets[i].rssi_thold; in ath10k_wmi_pno_check()
209 for (j = 0; j < nd_config->n_channels; j++) { in ath10k_wmi_pno_check()
210 pno->a_networks[i].channels[j] = in ath10k_wmi_pno_check()
211 nd_config->channels[j]->center_freq; in ath10k_wmi_pno_check()
216 if (nd_config->n_ssids == 0) in ath10k_wmi_pno_check()
217 pno->do_passive_scan = true; in ath10k_wmi_pno_check()
219 pno->do_passive_scan = false; in ath10k_wmi_pno_check()
221 for (i = 0; i < nd_config->n_ssids; i++) { in ath10k_wmi_pno_check()
223 while (j < pno->uc_networks_count) { in ath10k_wmi_pno_check()
224 if (__le32_to_cpu(pno->a_networks[j].ssid.ssid_len) == in ath10k_wmi_pno_check()
225 nd_config->ssids[i].ssid_len && in ath10k_wmi_pno_check()
226 (memcmp(pno->a_networks[j].ssid.ssid, in ath10k_wmi_pno_check()
227 nd_config->ssids[i].ssid, in ath10k_wmi_pno_check()
228 __le32_to_cpu(pno->a_networks[j].ssid.ssid_len)) == 0)) { in ath10k_wmi_pno_check()
229 pno->a_networks[j].bcast_nw_type = BCAST_HIDDEN; in ath10k_wmi_pno_check()
236 if (nd_config->n_scan_plans == 2) { in ath10k_wmi_pno_check()
237 pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC; in ath10k_wmi_pno_check()
238 pno->fast_scan_max_cycles = nd_config->scan_plans[0].iterations; in ath10k_wmi_pno_check()
239 pno->slow_scan_period = in ath10k_wmi_pno_check()
240 nd_config->scan_plans[1].interval * MSEC_PER_SEC; in ath10k_wmi_pno_check()
241 } else if (nd_config->n_scan_plans == 1) { in ath10k_wmi_pno_check()
242 pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC; in ath10k_wmi_pno_check()
243 pno->fast_scan_max_cycles = 1; in ath10k_wmi_pno_check()
244 pno->slow_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC; in ath10k_wmi_pno_check()
247 nd_config->n_scan_plans); in ath10k_wmi_pno_check()
250 if (nd_config->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { in ath10k_wmi_pno_check()
252 pno->enable_pno_scan_randomization = 1; in ath10k_wmi_pno_check()
253 memcpy(pno->mac_addr, nd_config->mac_addr, ETH_ALEN); in ath10k_wmi_pno_check()
254 memcpy(pno->mac_addr_mask, nd_config->mac_addr_mask, ETH_ALEN); in ath10k_wmi_pno_check()
257 pno->delay_start_time = nd_config->delay; in ath10k_wmi_pno_check()
259 /* Current FW does not support min-max range for dwell time */ in ath10k_wmi_pno_check()
260 pno->active_max_time = WMI_ACTIVE_MAX_CHANNEL_TIME; in ath10k_wmi_pno_check()
261 pno->passive_max_time = WMI_PASSIVE_MAX_CHANNEL_TIME; in ath10k_wmi_pno_check()
270 struct ath10k *ar = arvif->ar; in ath10k_vif_wow_set_wakeups()
271 const struct cfg80211_pkt_pattern *patterns = wowlan->patterns; in ath10k_vif_wow_set_wakeups()
275 switch (arvif->vdev_type) { in ath10k_vif_wow_set_wakeups()
289 if (wowlan->disconnect) { in ath10k_vif_wow_set_wakeups()
296 if (wowlan->magic_pkt) in ath10k_vif_wow_set_wakeups()
299 if (wowlan->nd_config) { in ath10k_vif_wow_set_wakeups()
305 return -ENOMEM; in ath10k_vif_wow_set_wakeups()
307 ar->nlo_enabled = true; in ath10k_vif_wow_set_wakeups()
309 ret = ath10k_wmi_pno_check(ar, arvif->vdev_id, in ath10k_vif_wow_set_wakeups()
310 wowlan->nd_config, pno); in ath10k_vif_wow_set_wakeups()
312 ath10k_wmi_wow_config_pno(ar, arvif->vdev_id, pno); in ath10k_vif_wow_set_wakeups()
323 for (i = 0; i < wowlan->n_patterns; i++) { in ath10k_vif_wow_set_wakeups()
332 new_pattern.mask = ath_bitmask; in ath10k_vif_wow_set_wakeups()
337 if (patterns[i].mask[j / 8] & BIT(j % 8)) in ath10k_vif_wow_set_wakeups()
339 old_pattern.mask = bitmask; in ath10k_vif_wow_set_wakeups()
341 if (ar->wmi.rx_decap_mode == ATH10K_HW_TXRX_NATIVE_WIFI) { in ath10k_vif_wow_set_wakeups()
347 new_pattern.pkt_offset += WOW_HDR_LEN - ETH_HLEN; in ath10k_vif_wow_set_wakeups()
352 return -EINVAL; in ath10k_vif_wow_set_wakeups()
354 ret = ath10k_wmi_wow_add_pattern(ar, arvif->vdev_id, in ath10k_vif_wow_set_wakeups()
357 new_pattern.mask, in ath10k_vif_wow_set_wakeups()
363 arvif->vdev_id, ret); in ath10k_vif_wow_set_wakeups()
374 ret = ath10k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 1); in ath10k_vif_wow_set_wakeups()
376 ath10k_warn(ar, "failed to enable wakeup event %s on vdev %i: %d\n", in ath10k_vif_wow_set_wakeups()
377 wow_wakeup_event(i), arvif->vdev_id, ret); in ath10k_vif_wow_set_wakeups()
391 lockdep_assert_held(&ar->conf_mutex); in ath10k_wow_set_wakeups()
393 list_for_each_entry(arvif, &ar->arvifs, list) { in ath10k_wow_set_wakeups()
397 arvif->vdev_id, ret); in ath10k_wow_set_wakeups()
408 struct ath10k *ar = arvif->ar; in ath10k_vif_wow_clean_nlo()
410 switch (arvif->vdev_type) { in ath10k_vif_wow_clean_nlo()
412 if (ar->nlo_enabled) { in ath10k_vif_wow_clean_nlo()
417 return -ENOMEM; in ath10k_vif_wow_clean_nlo()
419 pno->enable = 0; in ath10k_vif_wow_clean_nlo()
420 ar->nlo_enabled = false; in ath10k_vif_wow_clean_nlo()
421 ret = ath10k_wmi_wow_config_pno(ar, arvif->vdev_id, pno); in ath10k_vif_wow_clean_nlo()
436 lockdep_assert_held(&ar->conf_mutex); in ath10k_wow_nlo_cleanup()
438 list_for_each_entry(arvif, &ar->arvifs, list) { in ath10k_wow_nlo_cleanup()
442 arvif->vdev_id, ret); in ath10k_wow_nlo_cleanup()
454 lockdep_assert_held(&ar->conf_mutex); in ath10k_wow_enable()
456 reinit_completion(&ar->target_suspend); in ath10k_wow_enable()
464 ret = wait_for_completion_timeout(&ar->target_suspend, 3 * HZ); in ath10k_wow_enable()
467 return -ETIMEDOUT; in ath10k_wow_enable()
477 lockdep_assert_held(&ar->conf_mutex); in ath10k_wow_wakeup()
479 reinit_completion(&ar->wow.wakeup_completed); in ath10k_wow_wakeup()
483 ath10k_warn(ar, "failed to send wow wakeup indication: %d\n", in ath10k_wow_wakeup()
488 ret = wait_for_completion_timeout(&ar->wow.wakeup_completed, 3 * HZ); in ath10k_wow_wakeup()
490 ath10k_warn(ar, "timed out while waiting for wow wakeup completion\n"); in ath10k_wow_wakeup()
491 return -ETIMEDOUT; in ath10k_wow_wakeup()
500 struct ath10k *ar = hw->priv; in ath10k_wow_op_suspend()
503 mutex_lock(&ar->conf_mutex); in ath10k_wow_op_suspend()
506 ar->running_fw->fw_file.fw_features))) { in ath10k_wow_op_suspend()
513 ath10k_warn(ar, "failed to clear wow wakeup events: %d\n", in ath10k_wow_op_suspend()
520 ath10k_warn(ar, "failed to set wow wakeup events: %d\n", in ath10k_wow_op_suspend()
536 goto wakeup; in ath10k_wow_op_suspend()
541 wakeup: in ath10k_wow_op_suspend()
548 mutex_unlock(&ar->conf_mutex); in ath10k_wow_op_suspend()
554 struct ath10k *ar = hw->priv; in ath10k_wow_op_set_wakeup()
556 mutex_lock(&ar->conf_mutex); in ath10k_wow_op_set_wakeup()
558 ar->running_fw->fw_file.fw_features)) { in ath10k_wow_op_set_wakeup()
559 device_set_wakeup_enable(ar->dev, enabled); in ath10k_wow_op_set_wakeup()
561 mutex_unlock(&ar->conf_mutex); in ath10k_wow_op_set_wakeup()
566 struct ath10k *ar = hw->priv; in ath10k_wow_op_resume()
569 mutex_lock(&ar->conf_mutex); in ath10k_wow_op_resume()
572 ar->running_fw->fw_file.fw_features))) { in ath10k_wow_op_resume()
585 ath10k_warn(ar, "failed to wakeup from wow: %d\n", ret); in ath10k_wow_op_resume()
593 switch (ar->state) { in ath10k_wow_op_resume()
595 ar->state = ATH10K_STATE_RESTARTING; in ath10k_wow_op_resume()
604 ar->state); in ath10k_wow_op_resume()
605 ret = -EIO; in ath10k_wow_op_resume()
610 mutex_unlock(&ar->conf_mutex); in ath10k_wow_op_resume()
617 ar->running_fw->fw_file.fw_features)) in ath10k_wow_init()
620 if (WARN_ON(!test_bit(WMI_SERVICE_WOW, ar->wmi.svc_map))) in ath10k_wow_init()
621 return -EINVAL; in ath10k_wow_init()
623 ar->wow.wowlan_support = ath10k_wowlan_support; in ath10k_wow_init()
625 if (ar->wmi.rx_decap_mode == ATH10K_HW_TXRX_NATIVE_WIFI) { in ath10k_wow_init()
626 ar->wow.wowlan_support.pattern_max_len -= WOW_MAX_REDUCE; in ath10k_wow_init()
627 ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE; in ath10k_wow_init()
630 if (test_bit(WMI_SERVICE_NLO, ar->wmi.svc_map)) { in ath10k_wow_init()
631 ar->wow.wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT; in ath10k_wow_init()
632 ar->wow.wowlan_support.max_nd_match_sets = WMI_PNO_MAX_SUPP_NETWORKS; in ath10k_wow_init()
635 ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns; in ath10k_wow_init()
636 ar->hw->wiphy->wowlan = &ar->wow.wowlan_support; in ath10k_wow_init()
638 device_set_wakeup_capable(ar->dev, true); in ath10k_wow_init()