2 * Copyright (c) 2015 Qualcomm Atheros, Inc.
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 #include <net/mac80211.h>
26 static const struct wiphy_wowlan_support ath10k_wowlan_support = {
27 .flags = WIPHY_WOWLAN_DISCONNECT |
28 WIPHY_WOWLAN_MAGIC_PKT |
29 WIPHY_WOWLAN_SUPPORTS_GTK_REKEY |
30 WIPHY_WOWLAN_GTK_REKEY_FAILURE,
31 .pattern_min_len = WOW_MIN_PATTERN_SIZE,
32 .pattern_max_len = WOW_MAX_PATTERN_SIZE,
33 .max_pkt_offset = WOW_MAX_PKT_OFFSET,
36 static int ath10k_wow_vif_cleanup(struct ath10k_vif *arvif)
38 struct ath10k *ar = arvif->ar;
41 for (i = 0; i < WOW_EVENT_MAX; i++) {
42 ret = ath10k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 0);
44 ath10k_warn(ar, "failed to issue wow wakeup for event %s on vdev %i: %d\n",
45 wow_wakeup_event(i), arvif->vdev_id, ret);
50 for (i = 0; i < ar->wow.max_num_patterns; i++) {
51 ret = ath10k_wmi_wow_del_pattern(ar, arvif->vdev_id, i);
53 ath10k_warn(ar, "failed to delete wow pattern %d for vdev %i: %d\n",
54 i, arvif->vdev_id, ret);
62 static int ath10k_wow_cleanup(struct ath10k *ar)
64 struct ath10k_vif *arvif;
67 lockdep_assert_held(&ar->conf_mutex);
69 list_for_each_entry(arvif, &ar->arvifs, list) {
70 ret = ath10k_wow_vif_cleanup(arvif);
72 ath10k_warn(ar, "failed to clean wow wakeups on vdev %i: %d\n",
81 static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif,
82 struct cfg80211_wowlan *wowlan)
85 unsigned long wow_mask = 0;
86 struct ath10k *ar = arvif->ar;
87 struct ieee80211_bss_conf *bss = &arvif->vif->bss_conf;
88 const struct cfg80211_pkt_pattern *patterns = wowlan->patterns;
91 /* Setup requested WOW features */
92 switch (arvif->vdev_type) {
93 case WMI_VDEV_TYPE_IBSS:
94 __set_bit(WOW_BEACON_EVENT, &wow_mask);
96 case WMI_VDEV_TYPE_AP:
97 __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask);
98 __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask);
99 __set_bit(WOW_PROBE_REQ_WPS_IE_EVENT, &wow_mask);
100 __set_bit(WOW_AUTH_REQ_EVENT, &wow_mask);
101 __set_bit(WOW_ASSOC_REQ_EVENT, &wow_mask);
102 __set_bit(WOW_HTT_EVENT, &wow_mask);
103 __set_bit(WOW_RA_MATCH_EVENT, &wow_mask);
105 case WMI_VDEV_TYPE_STA:
106 if (arvif->is_up && bss->assoc) {
107 if (wowlan->disconnect) {
108 __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask);
109 __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask);
110 __set_bit(WOW_BMISS_EVENT, &wow_mask);
111 __set_bit(WOW_CSA_IE_EVENT, &wow_mask);
114 if (wowlan->magic_pkt)
115 __set_bit(WOW_MAGIC_PKT_RECVD_EVENT, &wow_mask);
116 if (wowlan->gtk_rekey_failure)
117 __set_bit(WOW_GTK_ERR_EVENT, &wow_mask);
124 for (i = 0; i < wowlan->n_patterns; i++) {
125 u8 bitmask[WOW_MAX_PATTERN_SIZE] = {};
128 if (patterns[i].pattern_len > WOW_MAX_PATTERN_SIZE)
131 /* convert bytemask to bitmask */
132 for (j = 0; j < patterns[i].pattern_len; j++)
133 if (patterns[i].mask[j / 8] & BIT(j % 8))
136 ret = ath10k_wmi_wow_add_pattern(ar, arvif->vdev_id,
140 patterns[i].pattern_len,
141 patterns[i].pkt_offset);
143 ath10k_warn(ar, "failed to add pattern %i to vdev %i: %d\n",
145 arvif->vdev_id, ret);
150 __set_bit(WOW_PATTERN_MATCH_EVENT, &wow_mask);
153 for (i = 0; i < WOW_EVENT_MAX; i++) {
154 if (!test_bit(i, &wow_mask))
156 ret = ath10k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 1);
158 ath10k_warn(ar, "failed to enable wakeup event %s on vdev %i: %d\n",
159 wow_wakeup_event(i), arvif->vdev_id, ret);
167 static int ath10k_wow_set_wakeups(struct ath10k *ar,
168 struct cfg80211_wowlan *wowlan)
170 struct ath10k_vif *arvif;
173 lockdep_assert_held(&ar->conf_mutex);
175 list_for_each_entry(arvif, &ar->arvifs, list) {
176 ret = ath10k_vif_wow_set_wakeups(arvif, wowlan);
178 ath10k_warn(ar, "failed to set wow wakeups on vdev %i: %d\n",
179 arvif->vdev_id, ret);
187 static int ath10k_wow_enable(struct ath10k *ar)
191 lockdep_assert_held(&ar->conf_mutex);
193 reinit_completion(&ar->target_suspend);
195 ret = ath10k_wmi_wow_enable(ar);
197 ath10k_warn(ar, "failed to issue wow enable: %d\n", ret);
201 ret = wait_for_completion_timeout(&ar->target_suspend, 3 * HZ);
203 ath10k_warn(ar, "timed out while waiting for suspend completion\n");
210 static int ath10k_wow_wakeup(struct ath10k *ar)
214 lockdep_assert_held(&ar->conf_mutex);
216 reinit_completion(&ar->wow.wakeup_completed);
218 ret = ath10k_wmi_wow_host_wakeup_ind(ar);
220 ath10k_warn(ar, "failed to send wow wakeup indication: %d\n",
225 ret = wait_for_completion_timeout(&ar->wow.wakeup_completed, 3 * HZ);
227 ath10k_warn(ar, "timed out while waiting for wow wakeup completion\n");
235 ath10k_wow_fill_vdev_arp_offload_struct(struct ath10k_vif *arvif,
238 struct in_device *in_dev;
239 struct in_ifaddr *ifa;
240 bool offload_params_found = false;
241 struct wireless_dev *wdev = ieee80211_vif_to_wdev(arvif->vif);
242 struct wmi_ns_arp_offload_req *arp = &arvif->arp_offload;
244 if (!enable_offload) {
245 arp->offload_type = __cpu_to_le16(WMI_IPV4_ARP_REPLY_OFFLOAD);
246 arp->enable_offload = __cpu_to_le16(WMI_ARP_NS_OFFLOAD_DISABLE);
254 in_dev = __in_dev_get_rtnl(wdev->netdev);
258 arp->offload_type = __cpu_to_le16(WMI_IPV4_ARP_REPLY_OFFLOAD);
259 arp->enable_offload = __cpu_to_le16(WMI_ARP_NS_OFFLOAD_ENABLE);
260 for (ifa = in_dev->ifa_list; ifa; ifa = ifa->ifa_next) {
261 if (!memcmp(ifa->ifa_label, wdev->netdev->name, IFNAMSIZ)) {
262 offload_params_found = true;
267 if (!offload_params_found)
269 memcpy(&arp->params.ipv4_addr, &ifa->ifa_local,
270 sizeof(arp->params.ipv4_addr));
275 static int ath10k_wow_enable_ns_arp_offload(struct ath10k *ar, bool offload)
277 struct ath10k_vif *arvif;
280 list_for_each_entry(arvif, &ar->arvifs, list) {
281 if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
287 ret = ath10k_wow_fill_vdev_arp_offload_struct(arvif, offload);
289 ath10k_err(ar, "ARP-offload config failed, vdev: %d\n",
294 ret = ath10k_wmi_set_arp_ns_offload(ar, arvif);
296 ath10k_err(ar, "failed to send offload cmd, vdev: %d\n",
305 static int ath10k_config_wow_listen_interval(struct ath10k *ar)
308 u32 param = ar->wmi.vdev_param->listen_interval;
309 u8 listen_interval = ar->hw_values->default_listen_interval;
310 struct ath10k_vif *arvif;
312 if (!listen_interval)
315 list_for_each_entry(arvif, &ar->arvifs, list) {
316 if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
318 ret = ath10k_wmi_vdev_set_param(ar, arvif->vdev_id,
319 param, listen_interval);
321 ath10k_err(ar, "failed to config LI for vdev_id: %d\n",
330 void ath10k_wow_op_set_rekey_data(struct ieee80211_hw *hw,
331 struct ieee80211_vif *vif,
332 struct cfg80211_gtk_rekey_data *data)
334 struct ath10k *ar = hw->priv;
335 struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif);
337 mutex_lock(&ar->conf_mutex);
338 memcpy(&arvif->gtk_rekey_data.kek, data->kek, NL80211_KEK_LEN);
339 memcpy(&arvif->gtk_rekey_data.kck, data->kck, NL80211_KCK_LEN);
340 arvif->gtk_rekey_data.replay_ctr =
341 cpu_to_le64(be64_to_cpup((__be64 *)data->replay_ctr));
342 arvif->gtk_rekey_data.valid = true;
343 mutex_unlock(&ar->conf_mutex);
346 static int ath10k_wow_config_gtk_offload(struct ath10k *ar, bool gtk_offload)
348 struct ath10k_vif *arvif;
349 struct ieee80211_bss_conf *bss;
350 struct wmi_gtk_rekey_data *rekey_data;
353 list_for_each_entry(arvif, &ar->arvifs, list) {
354 if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
357 bss = &arvif->vif->bss_conf;
358 if (!arvif->is_up || !bss->assoc)
361 rekey_data = &arvif->gtk_rekey_data;
362 if (!rekey_data->valid)
366 rekey_data->enable_offload = WMI_GTK_OFFLOAD_ENABLE;
368 rekey_data->enable_offload = WMI_GTK_OFFLOAD_DISABLE;
369 ret = ath10k_wmi_gtk_offload(ar, arvif);
371 ath10k_err(ar, "GTK offload failed for vdev_id: %d\n",
380 int ath10k_wow_op_suspend(struct ieee80211_hw *hw,
381 struct cfg80211_wowlan *wowlan)
383 struct ath10k *ar = hw->priv;
386 mutex_lock(&ar->conf_mutex);
388 if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
389 ar->running_fw->fw_file.fw_features))) {
394 ret = ath10k_wow_config_gtk_offload(ar, true);
396 ath10k_warn(ar, "failed to enable GTK offload: %d\n", ret);
400 ret = ath10k_wow_enable_ns_arp_offload(ar, true);
402 ath10k_warn(ar, "failed to enable ARP-NS offload: %d\n", ret);
403 goto disable_gtk_offload;
406 ret = ath10k_wow_cleanup(ar);
408 ath10k_warn(ar, "failed to clear wow wakeup events: %d\n",
410 goto disable_ns_arp_offload;
413 ret = ath10k_wow_set_wakeups(ar, wowlan);
415 ath10k_warn(ar, "failed to set wow wakeup events: %d\n",
420 ret = ath10k_config_wow_listen_interval(ar);
422 ath10k_warn(ar, "failed to config wow listen interval: %d\n",
427 ret = ath10k_wow_enable(ar);
429 ath10k_warn(ar, "failed to start wow: %d\n", ret);
433 ret = ath10k_hif_suspend(ar);
435 ath10k_warn(ar, "failed to suspend hif: %d\n", ret);
442 ath10k_wow_wakeup(ar);
445 ath10k_wow_cleanup(ar);
447 disable_ns_arp_offload:
448 ath10k_wow_enable_ns_arp_offload(ar, false);
451 ath10k_wow_config_gtk_offload(ar, false);
453 mutex_unlock(&ar->conf_mutex);
457 void ath10k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled)
459 struct ath10k *ar = hw->priv;
461 mutex_lock(&ar->conf_mutex);
462 if (test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
463 ar->running_fw->fw_file.fw_features)) {
464 device_set_wakeup_enable(ar->dev, enabled);
466 mutex_unlock(&ar->conf_mutex);
469 static void ath10k_wow_op_report_wakeup_reason(struct ath10k *ar)
471 struct cfg80211_wowlan_wakeup *wakeup = &ar->wow.wakeup;
472 struct ath10k_vif *arvif;
474 memset(wakeup, 0, sizeof(struct cfg80211_wowlan_wakeup));
475 switch (ar->wow.wakeup_reason) {
476 case WOW_REASON_UNSPECIFIED:
479 case WOW_REASON_RECV_MAGIC_PATTERN:
480 wakeup->magic_pkt = true;
482 case WOW_REASON_DEAUTH_RECVD:
483 case WOW_REASON_DISASSOC_RECVD:
484 case WOW_REASON_AP_ASSOC_LOST:
485 case WOW_REASON_CSA_EVENT:
486 wakeup->disconnect = true;
488 case WOW_REASON_GTK_HS_ERR:
489 wakeup->gtk_rekey_failure = true;
492 ar->wow.wakeup_reason = WOW_REASON_UNSPECIFIED;
495 wakeup->pattern_idx = -1;
496 list_for_each_entry(arvif, &ar->arvifs, list) {
497 ieee80211_report_wowlan_wakeup(arvif->vif,
499 if (wakeup->disconnect)
500 ieee80211_resume_disconnect(arvif->vif);
503 list_for_each_entry(arvif, &ar->arvifs, list)
504 ieee80211_report_wowlan_wakeup(arvif->vif,
509 int ath10k_wow_op_resume(struct ieee80211_hw *hw)
511 struct ath10k *ar = hw->priv;
514 mutex_lock(&ar->conf_mutex);
516 if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
517 ar->running_fw->fw_file.fw_features))) {
522 ret = ath10k_hif_resume(ar);
524 ath10k_warn(ar, "failed to resume hif: %d\n", ret);
528 ret = ath10k_wow_wakeup(ar);
530 ath10k_warn(ar, "failed to wakeup from wow: %d\n", ret);
534 ret = ath10k_wow_enable_ns_arp_offload(ar, false);
536 ath10k_warn(ar, "failed to disable ARP-NS offload: %d\n", ret);
540 ret = ath10k_wow_config_gtk_offload(ar, false);
542 ath10k_warn(ar, "failed to disable GTK offload: %d\n", ret);
547 case ATH10K_STATE_ON:
548 ar->state = ATH10K_STATE_RESTARTING;
551 case ATH10K_STATE_OFF:
552 case ATH10K_STATE_RESTARTING:
553 case ATH10K_STATE_RESTARTED:
554 case ATH10K_STATE_UTF:
555 case ATH10K_STATE_WEDGED:
556 ath10k_warn(ar, "encountered unexpected device state %d on resume, cannot recover\n",
563 ath10k_wow_op_report_wakeup_reason(ar);
564 mutex_unlock(&ar->conf_mutex);
568 int ath10k_wow_init(struct ath10k *ar)
570 if (!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT,
571 ar->running_fw->fw_file.fw_features))
574 if (WARN_ON(!test_bit(WMI_SERVICE_WOW, ar->wmi.svc_map)))
577 ar->wow.wowlan_support = ath10k_wowlan_support;
578 ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns;
579 ar->hw->wiphy->wowlan = &ar->wow.wowlan_support;
581 device_set_wakeup_capable(ar->dev, true);