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

1 // SPDX-License-Identifier: ISC
3 * Copyright (c) 2015-2017 Qualcomm Atheros, Inc.
15 #include "wmi-ops.h"
27 struct ath10k *ar = arvif->ar; in ath10k_wow_vif_cleanup()
31 ret = ath10k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 0); in ath10k_wow_vif_cleanup()
33 ath10k_warn(ar, "failed to issue wow wakeup for event %s on vdev %i: %d\n", in ath10k_wow_vif_cleanup()
34 wow_wakeup_event(i), arvif->vdev_id, ret); in ath10k_wow_vif_cleanup()
39 for (i = 0; i < ar->wow.max_num_patterns; i++) { in ath10k_wow_vif_cleanup()
40 ret = ath10k_wmi_wow_del_pattern(ar, arvif->vdev_id, i); in ath10k_wow_vif_cleanup()
43 i, arvif->vdev_id, ret); in ath10k_wow_vif_cleanup()
56 lockdep_assert_held(&ar->conf_mutex); in ath10k_wow_cleanup()
58 list_for_each_entry(arvif, &ar->arvifs, list) { in ath10k_wow_cleanup()
62 arvif->vdev_id, ret); in ath10k_wow_cleanup()
72 * +------------+-----------+--------+----------------+
74 * +------------+-----------+--------+----------------+
77 * +--+------------+----+-----------+---------------+-----------+
79 * +--+------------+----+-----------+---------------+-----------+
89 int total_len = old->pkt_offset + old->pattern_len; in ath10k_wow_convert_8023_to_80211()
106 memcpy(hdr_8023_pattern + old->pkt_offset, in ath10k_wow_convert_8023_to_80211()
107 old->pattern, ETH_HLEN - old->pkt_offset); in ath10k_wow_convert_8023_to_80211()
108 memcpy(hdr_8023_bit_mask + old->pkt_offset, in ath10k_wow_convert_8023_to_80211()
109 old->mask, ETH_HLEN - old->pkt_offset); in ath10k_wow_convert_8023_to_80211()
112 memcpy(new_hdr_pattern->addr1, old_hdr_pattern->h_dest, ETH_ALEN); in ath10k_wow_convert_8023_to_80211()
113 memcpy(new_hdr_mask->addr1, old_hdr_mask->h_dest, ETH_ALEN); in ath10k_wow_convert_8023_to_80211()
116 memcpy(new_hdr_pattern->addr3, old_hdr_pattern->h_source, ETH_ALEN); in ath10k_wow_convert_8023_to_80211()
117 memcpy(new_hdr_mask->addr3, old_hdr_mask->h_source, ETH_ALEN); in ath10k_wow_convert_8023_to_80211()
120 memcpy(&new_rfc_pattern->snap_type, in ath10k_wow_convert_8023_to_80211()
121 &old_hdr_pattern->h_proto, in ath10k_wow_convert_8023_to_80211()
122 sizeof(old_hdr_pattern->h_proto)); in ath10k_wow_convert_8023_to_80211()
123 memcpy(&new_rfc_mask->snap_type, in ath10k_wow_convert_8023_to_80211()
124 &old_hdr_mask->h_proto, in ath10k_wow_convert_8023_to_80211()
125 sizeof(old_hdr_mask->h_proto)); in ath10k_wow_convert_8023_to_80211()
128 if (old->pkt_offset < ETH_ALEN) in ath10k_wow_convert_8023_to_80211()
129 new->pkt_offset = old->pkt_offset + in ath10k_wow_convert_8023_to_80211()
131 else if (old->pkt_offset < offsetof(struct ethhdr, h_proto)) in ath10k_wow_convert_8023_to_80211()
132 new->pkt_offset = old->pkt_offset + in ath10k_wow_convert_8023_to_80211()
133 offsetof(struct ieee80211_hdr_3addr, addr3) - in ath10k_wow_convert_8023_to_80211()
136 new->pkt_offset = old->pkt_offset + hdr_len + rfc_len - ETH_HLEN; in ath10k_wow_convert_8023_to_80211()
142 hdr_80211_end_offset = hdr_len + rfc_len + total_len - ETH_HLEN; in ath10k_wow_convert_8023_to_80211()
144 hdr_80211_end_offset = total_len - ETH_ALEN + in ath10k_wow_convert_8023_to_80211()
150 new->pattern_len = hdr_80211_end_offset - new->pkt_offset; in ath10k_wow_convert_8023_to_80211()
152 memcpy((u8 *)new->pattern, in ath10k_wow_convert_8023_to_80211()
153 hdr_80211_pattern + new->pkt_offset, in ath10k_wow_convert_8023_to_80211()
154 new->pattern_len); in ath10k_wow_convert_8023_to_80211()
155 memcpy((u8 *)new->mask, in ath10k_wow_convert_8023_to_80211()
156 hdr_80211_bit_mask + new->pkt_offset, in ath10k_wow_convert_8023_to_80211()
157 new->pattern_len); in ath10k_wow_convert_8023_to_80211()
161 memcpy((u8 *)new->pattern + new->pattern_len, in ath10k_wow_convert_8023_to_80211()
162 (void *)old->pattern + ETH_HLEN - old->pkt_offset, in ath10k_wow_convert_8023_to_80211()
163 total_len - ETH_HLEN); in ath10k_wow_convert_8023_to_80211()
164 memcpy((u8 *)new->mask + new->pattern_len, in ath10k_wow_convert_8023_to_80211()
165 (void *)old->mask + ETH_HLEN - old->pkt_offset, in ath10k_wow_convert_8023_to_80211()
166 total_len - ETH_HLEN); in ath10k_wow_convert_8023_to_80211()
168 new->pattern_len += total_len - ETH_HLEN; in ath10k_wow_convert_8023_to_80211()
179 pno->enable = 1; in ath10k_wmi_pno_check()
180 pno->vdev_id = vdev_id; in ath10k_wmi_pno_check()
181 pno->uc_networks_count = nd_config->n_match_sets; in ath10k_wmi_pno_check()
183 if (!pno->uc_networks_count || in ath10k_wmi_pno_check()
184 pno->uc_networks_count > WMI_PNO_MAX_SUPP_NETWORKS) in ath10k_wmi_pno_check()
185 return -EINVAL; in ath10k_wmi_pno_check()
187 if (nd_config->n_channels > WMI_PNO_MAX_NETW_CHANNELS_EX) in ath10k_wmi_pno_check()
188 return -EINVAL; in ath10k_wmi_pno_check()
191 for (i = 0; i < pno->uc_networks_count; i++) { in ath10k_wmi_pno_check()
192 ssid_len = nd_config->match_sets[i].ssid.ssid_len; in ath10k_wmi_pno_check()
195 return -EINVAL; in ath10k_wmi_pno_check()
197 pno->a_networks[i].ssid.ssid_len = __cpu_to_le32(ssid_len); in ath10k_wmi_pno_check()
199 memcpy(pno->a_networks[i].ssid.ssid, in ath10k_wmi_pno_check()
200 nd_config->match_sets[i].ssid.ssid, in ath10k_wmi_pno_check()
201 nd_config->match_sets[i].ssid.ssid_len); in ath10k_wmi_pno_check()
202 pno->a_networks[i].authentication = 0; in ath10k_wmi_pno_check()
203 pno->a_networks[i].encryption = 0; in ath10k_wmi_pno_check()
204 pno->a_networks[i].bcast_nw_type = 0; in ath10k_wmi_pno_check()
206 /*Copying list of valid channel into request */ in ath10k_wmi_pno_check()
207 pno->a_networks[i].channel_count = nd_config->n_channels; in ath10k_wmi_pno_check()
208 pno->a_networks[i].rssi_threshold = nd_config->match_sets[i].rssi_thold; in ath10k_wmi_pno_check()
210 for (j = 0; j < nd_config->n_channels; j++) { in ath10k_wmi_pno_check()
211 pno->a_networks[i].channels[j] = in ath10k_wmi_pno_check()
212 nd_config->channels[j]->center_freq; in ath10k_wmi_pno_check()
217 if (nd_config->n_ssids == 0) in ath10k_wmi_pno_check()
218 pno->do_passive_scan = true; in ath10k_wmi_pno_check()
220 pno->do_passive_scan = false; in ath10k_wmi_pno_check()
222 for (i = 0; i < nd_config->n_ssids; i++) { in ath10k_wmi_pno_check()
224 while (j < pno->uc_networks_count) { in ath10k_wmi_pno_check()
225 if (__le32_to_cpu(pno->a_networks[j].ssid.ssid_len) == in ath10k_wmi_pno_check()
226 nd_config->ssids[i].ssid_len && in ath10k_wmi_pno_check()
227 (memcmp(pno->a_networks[j].ssid.ssid, in ath10k_wmi_pno_check()
228 nd_config->ssids[i].ssid, in ath10k_wmi_pno_check()
229 __le32_to_cpu(pno->a_networks[j].ssid.ssid_len)) == 0)) { in ath10k_wmi_pno_check()
230 pno->a_networks[j].bcast_nw_type = BCAST_HIDDEN; in ath10k_wmi_pno_check()
237 if (nd_config->n_scan_plans == 2) { in ath10k_wmi_pno_check()
238 pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC; in ath10k_wmi_pno_check()
239 pno->fast_scan_max_cycles = nd_config->scan_plans[0].iterations; in ath10k_wmi_pno_check()
240 pno->slow_scan_period = in ath10k_wmi_pno_check()
241 nd_config->scan_plans[1].interval * MSEC_PER_SEC; in ath10k_wmi_pno_check()
242 } else if (nd_config->n_scan_plans == 1) { in ath10k_wmi_pno_check()
243 pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC; in ath10k_wmi_pno_check()
244 pno->fast_scan_max_cycles = 1; in ath10k_wmi_pno_check()
245 pno->slow_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC; in ath10k_wmi_pno_check()
248 nd_config->n_scan_plans); in ath10k_wmi_pno_check()
251 if (nd_config->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { in ath10k_wmi_pno_check()
253 pno->enable_pno_scan_randomization = 1; in ath10k_wmi_pno_check()
254 memcpy(pno->mac_addr, nd_config->mac_addr, ETH_ALEN); in ath10k_wmi_pno_check()
255 memcpy(pno->mac_addr_mask, nd_config->mac_addr_mask, ETH_ALEN); in ath10k_wmi_pno_check()
258 pno->delay_start_time = nd_config->delay; in ath10k_wmi_pno_check()
260 /* Current FW does not support min-max range for dwell time */ in ath10k_wmi_pno_check()
261 pno->active_max_time = WMI_ACTIVE_MAX_CHANNEL_TIME; in ath10k_wmi_pno_check()
262 pno->passive_max_time = WMI_PASSIVE_MAX_CHANNEL_TIME; in ath10k_wmi_pno_check()
271 struct ath10k *ar = arvif->ar; in ath10k_vif_wow_set_wakeups()
272 const struct cfg80211_pkt_pattern *patterns = wowlan->patterns; in ath10k_vif_wow_set_wakeups()
276 switch (arvif->vdev_type) { in ath10k_vif_wow_set_wakeups()
290 if (wowlan->disconnect) { in ath10k_vif_wow_set_wakeups()
297 if (wowlan->magic_pkt) in ath10k_vif_wow_set_wakeups()
300 if (wowlan->nd_config) { in ath10k_vif_wow_set_wakeups()
306 return -ENOMEM; in ath10k_vif_wow_set_wakeups()
308 ar->nlo_enabled = true; in ath10k_vif_wow_set_wakeups()
310 ret = ath10k_wmi_pno_check(ar, arvif->vdev_id, in ath10k_vif_wow_set_wakeups()
311 wowlan->nd_config, pno); in ath10k_vif_wow_set_wakeups()
313 ath10k_wmi_wow_config_pno(ar, arvif->vdev_id, pno); in ath10k_vif_wow_set_wakeups()
324 for (i = 0; i < wowlan->n_patterns; i++) { in ath10k_vif_wow_set_wakeups()
333 new_pattern.mask = ath_bitmask; in ath10k_vif_wow_set_wakeups()
338 if (patterns[i].mask[j / 8] & BIT(j % 8)) in ath10k_vif_wow_set_wakeups()
340 old_pattern.mask = bitmask; in ath10k_vif_wow_set_wakeups()
342 if (ar->wmi.rx_decap_mode == ATH10K_HW_TXRX_NATIVE_WIFI) { in ath10k_vif_wow_set_wakeups()
348 new_pattern.pkt_offset += WOW_HDR_LEN - ETH_HLEN; in ath10k_vif_wow_set_wakeups()
353 return -EINVAL; in ath10k_vif_wow_set_wakeups()
355 ret = ath10k_wmi_wow_add_pattern(ar, arvif->vdev_id, in ath10k_vif_wow_set_wakeups()
358 new_pattern.mask, in ath10k_vif_wow_set_wakeups()
364 arvif->vdev_id, ret); in ath10k_vif_wow_set_wakeups()
375 ret = ath10k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 1); in ath10k_vif_wow_set_wakeups()
377 ath10k_warn(ar, "failed to enable wakeup event %s on vdev %i: %d\n", in ath10k_vif_wow_set_wakeups()
378 wow_wakeup_event(i), arvif->vdev_id, ret); in ath10k_vif_wow_set_wakeups()
392 lockdep_assert_held(&ar->conf_mutex); in ath10k_wow_set_wakeups()
394 list_for_each_entry(arvif, &ar->arvifs, list) { in ath10k_wow_set_wakeups()
398 arvif->vdev_id, ret); in ath10k_wow_set_wakeups()
409 struct ath10k *ar = arvif->ar; in ath10k_vif_wow_clean_nlo()
411 switch (arvif->vdev_type) { in ath10k_vif_wow_clean_nlo()
413 if (ar->nlo_enabled) { in ath10k_vif_wow_clean_nlo()
418 return -ENOMEM; in ath10k_vif_wow_clean_nlo()
420 pno->enable = 0; in ath10k_vif_wow_clean_nlo()
421 ar->nlo_enabled = false; in ath10k_vif_wow_clean_nlo()
422 ret = ath10k_wmi_wow_config_pno(ar, arvif->vdev_id, pno); in ath10k_vif_wow_clean_nlo()
437 lockdep_assert_held(&ar->conf_mutex); in ath10k_wow_nlo_cleanup()
439 list_for_each_entry(arvif, &ar->arvifs, list) { in ath10k_wow_nlo_cleanup()
443 arvif->vdev_id, ret); in ath10k_wow_nlo_cleanup()
455 lockdep_assert_held(&ar->conf_mutex); in ath10k_wow_enable()
457 reinit_completion(&ar->target_suspend); in ath10k_wow_enable()
465 ret = wait_for_completion_timeout(&ar->target_suspend, 3 * HZ); in ath10k_wow_enable()
468 return -ETIMEDOUT; in ath10k_wow_enable()
478 lockdep_assert_held(&ar->conf_mutex); in ath10k_wow_wakeup()
480 reinit_completion(&ar->wow.wakeup_completed); in ath10k_wow_wakeup()
484 ath10k_warn(ar, "failed to send wow wakeup indication: %d\n", in ath10k_wow_wakeup()
489 ret = wait_for_completion_timeout(&ar->wow.wakeup_completed, 3 * HZ); in ath10k_wow_wakeup()
491 ath10k_warn(ar, "timed out while waiting for wow wakeup completion\n"); in ath10k_wow_wakeup()
492 return -ETIMEDOUT; in ath10k_wow_wakeup()
501 struct ath10k *ar = hw->priv; in ath10k_wow_op_suspend()
504 mutex_lock(&ar->conf_mutex); in ath10k_wow_op_suspend()
507 ar->running_fw->fw_file.fw_features))) { in ath10k_wow_op_suspend()
514 ath10k_warn(ar, "failed to clear wow wakeup events: %d\n", in ath10k_wow_op_suspend()
521 ath10k_warn(ar, "failed to set wow wakeup events: %d\n", in ath10k_wow_op_suspend()
537 goto wakeup; in ath10k_wow_op_suspend()
542 wakeup: in ath10k_wow_op_suspend()
549 mutex_unlock(&ar->conf_mutex); in ath10k_wow_op_suspend()
555 struct ath10k *ar = hw->priv; in ath10k_wow_op_set_wakeup()
557 mutex_lock(&ar->conf_mutex); in ath10k_wow_op_set_wakeup()
559 ar->running_fw->fw_file.fw_features)) { in ath10k_wow_op_set_wakeup()
560 device_set_wakeup_enable(ar->dev, enabled); in ath10k_wow_op_set_wakeup()
562 mutex_unlock(&ar->conf_mutex); in ath10k_wow_op_set_wakeup()
567 struct ath10k *ar = hw->priv; in ath10k_wow_op_resume()
570 mutex_lock(&ar->conf_mutex); in ath10k_wow_op_resume()
573 ar->running_fw->fw_file.fw_features))) { in ath10k_wow_op_resume()
586 ath10k_warn(ar, "failed to wakeup from wow: %d\n", ret); in ath10k_wow_op_resume()
594 switch (ar->state) { in ath10k_wow_op_resume()
596 ar->state = ATH10K_STATE_RESTARTING; in ath10k_wow_op_resume()
605 ar->state); in ath10k_wow_op_resume()
606 ret = -EIO; in ath10k_wow_op_resume()
611 mutex_unlock(&ar->conf_mutex); in ath10k_wow_op_resume()
618 ar->running_fw->fw_file.fw_features)) in ath10k_wow_init()
621 if (WARN_ON(!test_bit(WMI_SERVICE_WOW, ar->wmi.svc_map))) in ath10k_wow_init()
622 return -EINVAL; in ath10k_wow_init()
624 ar->wow.wowlan_support = ath10k_wowlan_support; in ath10k_wow_init()
626 if (ar->wmi.rx_decap_mode == ATH10K_HW_TXRX_NATIVE_WIFI) { in ath10k_wow_init()
627 ar->wow.wowlan_support.pattern_max_len -= WOW_MAX_REDUCE; in ath10k_wow_init()
628 ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE; in ath10k_wow_init()
631 if (test_bit(WMI_SERVICE_NLO, ar->wmi.svc_map)) { in ath10k_wow_init()
632 ar->wow.wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT; in ath10k_wow_init()
633 ar->wow.wowlan_support.max_nd_match_sets = WMI_PNO_MAX_SUPP_NETWORKS; in ath10k_wow_init()
636 ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns; in ath10k_wow_init()
637 ar->hw->wiphy->wowlan = &ar->wow.wowlan_support; in ath10k_wow_init()
639 device_set_wakeup_capable(ar->dev, true); in ath10k_wow_init()