1 /* 2 * Copyright (c) 2015-2017 Qualcomm Atheros, Inc. 3 * Copyright (c) 2018, The Linux Foundation. All rights reserved. 4 * 5 * Permission to use, copy, modify, and/or distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include "mac.h" 19 20 #include <net/mac80211.h> 21 #include "hif.h" 22 #include "core.h" 23 #include "debug.h" 24 #include "wmi.h" 25 #include "wmi-ops.h" 26 27 static const struct wiphy_wowlan_support ath10k_wowlan_support = { 28 .flags = WIPHY_WOWLAN_DISCONNECT | 29 WIPHY_WOWLAN_MAGIC_PKT, 30 .pattern_min_len = WOW_MIN_PATTERN_SIZE, 31 .pattern_max_len = WOW_MAX_PATTERN_SIZE, 32 .max_pkt_offset = WOW_MAX_PKT_OFFSET, 33 }; 34 35 static int ath10k_wow_vif_cleanup(struct ath10k_vif *arvif) 36 { 37 struct ath10k *ar = arvif->ar; 38 int i, ret; 39 40 for (i = 0; i < WOW_EVENT_MAX; i++) { 41 ret = ath10k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 0); 42 if (ret) { 43 ath10k_warn(ar, "failed to issue wow wakeup for event %s on vdev %i: %d\n", 44 wow_wakeup_event(i), arvif->vdev_id, ret); 45 return ret; 46 } 47 } 48 49 for (i = 0; i < ar->wow.max_num_patterns; i++) { 50 ret = ath10k_wmi_wow_del_pattern(ar, arvif->vdev_id, i); 51 if (ret) { 52 ath10k_warn(ar, "failed to delete wow pattern %d for vdev %i: %d\n", 53 i, arvif->vdev_id, ret); 54 return ret; 55 } 56 } 57 58 return 0; 59 } 60 61 static int ath10k_wow_cleanup(struct ath10k *ar) 62 { 63 struct ath10k_vif *arvif; 64 int ret; 65 66 lockdep_assert_held(&ar->conf_mutex); 67 68 list_for_each_entry(arvif, &ar->arvifs, list) { 69 ret = ath10k_wow_vif_cleanup(arvif); 70 if (ret) { 71 ath10k_warn(ar, "failed to clean wow wakeups on vdev %i: %d\n", 72 arvif->vdev_id, ret); 73 return ret; 74 } 75 } 76 77 return 0; 78 } 79 80 /** 81 * Convert a 802.3 format to a 802.11 format. 82 * +------------+-----------+--------+----------------+ 83 * 802.3: |dest mac(6B)|src mac(6B)|type(2B)| body... | 84 * +------------+-----------+--------+----------------+ 85 * |__ |_______ |____________ |________ 86 * | | | | 87 * +--+------------+----+-----------+---------------+-----------+ 88 * 802.11: |4B|dest mac(6B)| 6B |src mac(6B)| 8B |type(2B)| body... | 89 * +--+------------+----+-----------+---------------+-----------+ 90 */ 91 static void ath10k_wow_convert_8023_to_80211 92 (struct cfg80211_pkt_pattern *new, 93 const struct cfg80211_pkt_pattern *old) 94 { 95 u8 hdr_8023_pattern[ETH_HLEN] = {}; 96 u8 hdr_8023_bit_mask[ETH_HLEN] = {}; 97 u8 hdr_80211_pattern[WOW_HDR_LEN] = {}; 98 u8 hdr_80211_bit_mask[WOW_HDR_LEN] = {}; 99 100 int total_len = old->pkt_offset + old->pattern_len; 101 int hdr_80211_end_offset; 102 103 struct ieee80211_hdr_3addr *new_hdr_pattern = 104 (struct ieee80211_hdr_3addr *)hdr_80211_pattern; 105 struct ieee80211_hdr_3addr *new_hdr_mask = 106 (struct ieee80211_hdr_3addr *)hdr_80211_bit_mask; 107 struct ethhdr *old_hdr_pattern = (struct ethhdr *)hdr_8023_pattern; 108 struct ethhdr *old_hdr_mask = (struct ethhdr *)hdr_8023_bit_mask; 109 int hdr_len = sizeof(*new_hdr_pattern); 110 111 struct rfc1042_hdr *new_rfc_pattern = 112 (struct rfc1042_hdr *)(hdr_80211_pattern + hdr_len); 113 struct rfc1042_hdr *new_rfc_mask = 114 (struct rfc1042_hdr *)(hdr_80211_bit_mask + hdr_len); 115 int rfc_len = sizeof(*new_rfc_pattern); 116 117 memcpy(hdr_8023_pattern + old->pkt_offset, 118 old->pattern, ETH_HLEN - old->pkt_offset); 119 memcpy(hdr_8023_bit_mask + old->pkt_offset, 120 old->mask, ETH_HLEN - old->pkt_offset); 121 122 /* Copy destination address */ 123 memcpy(new_hdr_pattern->addr1, old_hdr_pattern->h_dest, ETH_ALEN); 124 memcpy(new_hdr_mask->addr1, old_hdr_mask->h_dest, ETH_ALEN); 125 126 /* Copy source address */ 127 memcpy(new_hdr_pattern->addr3, old_hdr_pattern->h_source, ETH_ALEN); 128 memcpy(new_hdr_mask->addr3, old_hdr_mask->h_source, ETH_ALEN); 129 130 /* Copy logic link type */ 131 memcpy(&new_rfc_pattern->snap_type, 132 &old_hdr_pattern->h_proto, 133 sizeof(old_hdr_pattern->h_proto)); 134 memcpy(&new_rfc_mask->snap_type, 135 &old_hdr_mask->h_proto, 136 sizeof(old_hdr_mask->h_proto)); 137 138 /* Calculate new pkt_offset */ 139 if (old->pkt_offset < ETH_ALEN) 140 new->pkt_offset = old->pkt_offset + 141 offsetof(struct ieee80211_hdr_3addr, addr1); 142 else if (old->pkt_offset < offsetof(struct ethhdr, h_proto)) 143 new->pkt_offset = old->pkt_offset + 144 offsetof(struct ieee80211_hdr_3addr, addr3) - 145 offsetof(struct ethhdr, h_source); 146 else 147 new->pkt_offset = old->pkt_offset + hdr_len + rfc_len - ETH_HLEN; 148 149 /* Calculate new hdr end offset */ 150 if (total_len > ETH_HLEN) 151 hdr_80211_end_offset = hdr_len + rfc_len; 152 else if (total_len > offsetof(struct ethhdr, h_proto)) 153 hdr_80211_end_offset = hdr_len + rfc_len + total_len - ETH_HLEN; 154 else if (total_len > ETH_ALEN) 155 hdr_80211_end_offset = total_len - ETH_ALEN + 156 offsetof(struct ieee80211_hdr_3addr, addr3); 157 else 158 hdr_80211_end_offset = total_len + 159 offsetof(struct ieee80211_hdr_3addr, addr1); 160 161 new->pattern_len = hdr_80211_end_offset - new->pkt_offset; 162 163 memcpy((u8 *)new->pattern, 164 hdr_80211_pattern + new->pkt_offset, 165 new->pattern_len); 166 memcpy((u8 *)new->mask, 167 hdr_80211_bit_mask + new->pkt_offset, 168 new->pattern_len); 169 170 if (total_len > ETH_HLEN) { 171 /* Copy frame body */ 172 memcpy((u8 *)new->pattern + new->pattern_len, 173 (void *)old->pattern + ETH_HLEN - old->pkt_offset, 174 total_len - ETH_HLEN); 175 memcpy((u8 *)new->mask + new->pattern_len, 176 (void *)old->mask + ETH_HLEN - old->pkt_offset, 177 total_len - ETH_HLEN); 178 179 new->pattern_len += total_len - ETH_HLEN; 180 } 181 } 182 183 static int ath10k_wmi_pno_check(struct ath10k *ar, u32 vdev_id, 184 struct cfg80211_sched_scan_request *nd_config, 185 struct wmi_pno_scan_req *pno) 186 { 187 int i, j, ret = 0; 188 u8 ssid_len; 189 190 pno->enable = 1; 191 pno->vdev_id = vdev_id; 192 pno->uc_networks_count = nd_config->n_match_sets; 193 194 if (!pno->uc_networks_count || 195 pno->uc_networks_count > WMI_PNO_MAX_SUPP_NETWORKS) 196 return -EINVAL; 197 198 if (nd_config->n_channels > WMI_PNO_MAX_NETW_CHANNELS_EX) 199 return -EINVAL; 200 201 /* Filling per profile params */ 202 for (i = 0; i < pno->uc_networks_count; i++) { 203 ssid_len = nd_config->match_sets[i].ssid.ssid_len; 204 205 if (ssid_len == 0 || ssid_len > 32) 206 return -EINVAL; 207 208 pno->a_networks[i].ssid.ssid_len = __cpu_to_le32(ssid_len); 209 210 memcpy(pno->a_networks[i].ssid.ssid, 211 nd_config->match_sets[i].ssid.ssid, 212 nd_config->match_sets[i].ssid.ssid_len); 213 pno->a_networks[i].authentication = 0; 214 pno->a_networks[i].encryption = 0; 215 pno->a_networks[i].bcast_nw_type = 0; 216 217 /*Copying list of valid channel into request */ 218 pno->a_networks[i].channel_count = nd_config->n_channels; 219 pno->a_networks[i].rssi_threshold = nd_config->match_sets[i].rssi_thold; 220 221 for (j = 0; j < nd_config->n_channels; j++) { 222 pno->a_networks[i].channels[j] = 223 nd_config->channels[j]->center_freq; 224 } 225 } 226 227 /* set scan to passive if no SSIDs are specified in the request */ 228 if (nd_config->n_ssids == 0) 229 pno->do_passive_scan = true; 230 else 231 pno->do_passive_scan = false; 232 233 for (i = 0; i < nd_config->n_ssids; i++) { 234 j = 0; 235 while (j < pno->uc_networks_count) { 236 if (__le32_to_cpu(pno->a_networks[j].ssid.ssid_len) == 237 nd_config->ssids[i].ssid_len && 238 (memcmp(pno->a_networks[j].ssid.ssid, 239 nd_config->ssids[i].ssid, 240 __le32_to_cpu(pno->a_networks[j].ssid.ssid_len)) == 0)) { 241 pno->a_networks[j].bcast_nw_type = BCAST_HIDDEN; 242 break; 243 } 244 j++; 245 } 246 } 247 248 if (nd_config->n_scan_plans == 2) { 249 pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC; 250 pno->fast_scan_max_cycles = nd_config->scan_plans[0].iterations; 251 pno->slow_scan_period = 252 nd_config->scan_plans[1].interval * MSEC_PER_SEC; 253 } else if (nd_config->n_scan_plans == 1) { 254 pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC; 255 pno->fast_scan_max_cycles = 1; 256 pno->slow_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC; 257 } else { 258 ath10k_warn(ar, "Invalid number of scan plans %d !!", 259 nd_config->n_scan_plans); 260 } 261 262 if (nd_config->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { 263 /* enable mac randomization */ 264 pno->enable_pno_scan_randomization = 1; 265 memcpy(pno->mac_addr, nd_config->mac_addr, ETH_ALEN); 266 memcpy(pno->mac_addr_mask, nd_config->mac_addr_mask, ETH_ALEN); 267 } 268 269 pno->delay_start_time = nd_config->delay; 270 271 /* Current FW does not support min-max range for dwell time */ 272 pno->active_max_time = WMI_ACTIVE_MAX_CHANNEL_TIME; 273 pno->passive_max_time = WMI_PASSIVE_MAX_CHANNEL_TIME; 274 return ret; 275 } 276 277 static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif, 278 struct cfg80211_wowlan *wowlan) 279 { 280 int ret, i; 281 unsigned long wow_mask = 0; 282 struct ath10k *ar = arvif->ar; 283 const struct cfg80211_pkt_pattern *patterns = wowlan->patterns; 284 int pattern_id = 0; 285 286 /* Setup requested WOW features */ 287 switch (arvif->vdev_type) { 288 case WMI_VDEV_TYPE_IBSS: 289 __set_bit(WOW_BEACON_EVENT, &wow_mask); 290 /* fall through */ 291 case WMI_VDEV_TYPE_AP: 292 __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask); 293 __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask); 294 __set_bit(WOW_PROBE_REQ_WPS_IE_EVENT, &wow_mask); 295 __set_bit(WOW_AUTH_REQ_EVENT, &wow_mask); 296 __set_bit(WOW_ASSOC_REQ_EVENT, &wow_mask); 297 __set_bit(WOW_HTT_EVENT, &wow_mask); 298 __set_bit(WOW_RA_MATCH_EVENT, &wow_mask); 299 break; 300 case WMI_VDEV_TYPE_STA: 301 if (wowlan->disconnect) { 302 __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask); 303 __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask); 304 __set_bit(WOW_BMISS_EVENT, &wow_mask); 305 __set_bit(WOW_CSA_IE_EVENT, &wow_mask); 306 } 307 308 if (wowlan->magic_pkt) 309 __set_bit(WOW_MAGIC_PKT_RECVD_EVENT, &wow_mask); 310 311 if (wowlan->nd_config) { 312 struct wmi_pno_scan_req *pno; 313 int ret; 314 315 pno = kzalloc(sizeof(*pno), GFP_KERNEL); 316 if (!pno) 317 return -ENOMEM; 318 319 ar->nlo_enabled = true; 320 321 ret = ath10k_wmi_pno_check(ar, arvif->vdev_id, 322 wowlan->nd_config, pno); 323 if (!ret) { 324 ath10k_wmi_wow_config_pno(ar, arvif->vdev_id, pno); 325 __set_bit(WOW_NLO_DETECTED_EVENT, &wow_mask); 326 } 327 328 kfree(pno); 329 } 330 break; 331 default: 332 break; 333 } 334 335 for (i = 0; i < wowlan->n_patterns; i++) { 336 u8 bitmask[WOW_MAX_PATTERN_SIZE] = {}; 337 u8 ath_pattern[WOW_MAX_PATTERN_SIZE] = {}; 338 u8 ath_bitmask[WOW_MAX_PATTERN_SIZE] = {}; 339 struct cfg80211_pkt_pattern new_pattern = {}; 340 struct cfg80211_pkt_pattern old_pattern = patterns[i]; 341 int j; 342 343 new_pattern.pattern = ath_pattern; 344 new_pattern.mask = ath_bitmask; 345 if (patterns[i].pattern_len > WOW_MAX_PATTERN_SIZE) 346 continue; 347 /* convert bytemask to bitmask */ 348 for (j = 0; j < patterns[i].pattern_len; j++) 349 if (patterns[i].mask[j / 8] & BIT(j % 8)) 350 bitmask[j] = 0xff; 351 old_pattern.mask = bitmask; 352 new_pattern = old_pattern; 353 354 if (ar->wmi.rx_decap_mode == ATH10K_HW_TXRX_NATIVE_WIFI) { 355 if (patterns[i].pkt_offset < ETH_HLEN) 356 ath10k_wow_convert_8023_to_80211(&new_pattern, 357 &old_pattern); 358 else 359 new_pattern.pkt_offset += WOW_HDR_LEN - ETH_HLEN; 360 } 361 362 if (WARN_ON(new_pattern.pattern_len > WOW_MAX_PATTERN_SIZE)) 363 return -EINVAL; 364 365 ret = ath10k_wmi_wow_add_pattern(ar, arvif->vdev_id, 366 pattern_id, 367 new_pattern.pattern, 368 new_pattern.mask, 369 new_pattern.pattern_len, 370 new_pattern.pkt_offset); 371 if (ret) { 372 ath10k_warn(ar, "failed to add pattern %i to vdev %i: %d\n", 373 pattern_id, 374 arvif->vdev_id, ret); 375 return ret; 376 } 377 378 pattern_id++; 379 __set_bit(WOW_PATTERN_MATCH_EVENT, &wow_mask); 380 } 381 382 for (i = 0; i < WOW_EVENT_MAX; i++) { 383 if (!test_bit(i, &wow_mask)) 384 continue; 385 ret = ath10k_wmi_wow_add_wakeup_event(ar, arvif->vdev_id, i, 1); 386 if (ret) { 387 ath10k_warn(ar, "failed to enable wakeup event %s on vdev %i: %d\n", 388 wow_wakeup_event(i), arvif->vdev_id, ret); 389 return ret; 390 } 391 } 392 393 return 0; 394 } 395 396 static int ath10k_wow_set_wakeups(struct ath10k *ar, 397 struct cfg80211_wowlan *wowlan) 398 { 399 struct ath10k_vif *arvif; 400 int ret; 401 402 lockdep_assert_held(&ar->conf_mutex); 403 404 list_for_each_entry(arvif, &ar->arvifs, list) { 405 ret = ath10k_vif_wow_set_wakeups(arvif, wowlan); 406 if (ret) { 407 ath10k_warn(ar, "failed to set wow wakeups on vdev %i: %d\n", 408 arvif->vdev_id, ret); 409 return ret; 410 } 411 } 412 413 return 0; 414 } 415 416 static int ath10k_vif_wow_clean_nlo(struct ath10k_vif *arvif) 417 { 418 int ret = 0; 419 struct ath10k *ar = arvif->ar; 420 421 switch (arvif->vdev_type) { 422 case WMI_VDEV_TYPE_STA: 423 if (ar->nlo_enabled) { 424 struct wmi_pno_scan_req *pno; 425 426 pno = kzalloc(sizeof(*pno), GFP_KERNEL); 427 if (!pno) 428 return -ENOMEM; 429 430 pno->enable = 0; 431 ar->nlo_enabled = false; 432 ret = ath10k_wmi_wow_config_pno(ar, arvif->vdev_id, pno); 433 kfree(pno); 434 } 435 break; 436 default: 437 break; 438 } 439 return ret; 440 } 441 442 static int ath10k_wow_nlo_cleanup(struct ath10k *ar) 443 { 444 struct ath10k_vif *arvif; 445 int ret = 0; 446 447 lockdep_assert_held(&ar->conf_mutex); 448 449 list_for_each_entry(arvif, &ar->arvifs, list) { 450 ret = ath10k_vif_wow_clean_nlo(arvif); 451 if (ret) { 452 ath10k_warn(ar, "failed to clean nlo settings on vdev %i: %d\n", 453 arvif->vdev_id, ret); 454 return ret; 455 } 456 } 457 458 return 0; 459 } 460 461 static int ath10k_wow_enable(struct ath10k *ar) 462 { 463 int ret; 464 465 lockdep_assert_held(&ar->conf_mutex); 466 467 reinit_completion(&ar->target_suspend); 468 469 ret = ath10k_wmi_wow_enable(ar); 470 if (ret) { 471 ath10k_warn(ar, "failed to issue wow enable: %d\n", ret); 472 return ret; 473 } 474 475 ret = wait_for_completion_timeout(&ar->target_suspend, 3 * HZ); 476 if (ret == 0) { 477 ath10k_warn(ar, "timed out while waiting for suspend completion\n"); 478 return -ETIMEDOUT; 479 } 480 481 return 0; 482 } 483 484 static int ath10k_wow_wakeup(struct ath10k *ar) 485 { 486 int ret; 487 488 lockdep_assert_held(&ar->conf_mutex); 489 490 reinit_completion(&ar->wow.wakeup_completed); 491 492 ret = ath10k_wmi_wow_host_wakeup_ind(ar); 493 if (ret) { 494 ath10k_warn(ar, "failed to send wow wakeup indication: %d\n", 495 ret); 496 return ret; 497 } 498 499 ret = wait_for_completion_timeout(&ar->wow.wakeup_completed, 3 * HZ); 500 if (ret == 0) { 501 ath10k_warn(ar, "timed out while waiting for wow wakeup completion\n"); 502 return -ETIMEDOUT; 503 } 504 505 return 0; 506 } 507 508 int ath10k_wow_op_suspend(struct ieee80211_hw *hw, 509 struct cfg80211_wowlan *wowlan) 510 { 511 struct ath10k *ar = hw->priv; 512 int ret; 513 514 mutex_lock(&ar->conf_mutex); 515 516 if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, 517 ar->running_fw->fw_file.fw_features))) { 518 ret = 1; 519 goto exit; 520 } 521 522 ret = ath10k_wow_cleanup(ar); 523 if (ret) { 524 ath10k_warn(ar, "failed to clear wow wakeup events: %d\n", 525 ret); 526 goto exit; 527 } 528 529 ret = ath10k_wow_set_wakeups(ar, wowlan); 530 if (ret) { 531 ath10k_warn(ar, "failed to set wow wakeup events: %d\n", 532 ret); 533 goto cleanup; 534 } 535 536 ath10k_mac_wait_tx_complete(ar); 537 538 ret = ath10k_wow_enable(ar); 539 if (ret) { 540 ath10k_warn(ar, "failed to start wow: %d\n", ret); 541 goto cleanup; 542 } 543 544 ret = ath10k_hif_suspend(ar); 545 if (ret) { 546 ath10k_warn(ar, "failed to suspend hif: %d\n", ret); 547 goto wakeup; 548 } 549 550 goto exit; 551 552 wakeup: 553 ath10k_wow_wakeup(ar); 554 555 cleanup: 556 ath10k_wow_cleanup(ar); 557 558 exit: 559 mutex_unlock(&ar->conf_mutex); 560 return ret ? 1 : 0; 561 } 562 563 void ath10k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled) 564 { 565 struct ath10k *ar = hw->priv; 566 567 mutex_lock(&ar->conf_mutex); 568 if (test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, 569 ar->running_fw->fw_file.fw_features)) { 570 device_set_wakeup_enable(ar->dev, enabled); 571 } 572 mutex_unlock(&ar->conf_mutex); 573 } 574 575 int ath10k_wow_op_resume(struct ieee80211_hw *hw) 576 { 577 struct ath10k *ar = hw->priv; 578 int ret; 579 580 mutex_lock(&ar->conf_mutex); 581 582 if (WARN_ON(!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, 583 ar->running_fw->fw_file.fw_features))) { 584 ret = 1; 585 goto exit; 586 } 587 588 ret = ath10k_hif_resume(ar); 589 if (ret) { 590 ath10k_warn(ar, "failed to resume hif: %d\n", ret); 591 goto exit; 592 } 593 594 ret = ath10k_wow_wakeup(ar); 595 if (ret) 596 ath10k_warn(ar, "failed to wakeup from wow: %d\n", ret); 597 598 ret = ath10k_wow_nlo_cleanup(ar); 599 if (ret) 600 ath10k_warn(ar, "failed to cleanup nlo: %d\n", ret); 601 602 exit: 603 if (ret) { 604 switch (ar->state) { 605 case ATH10K_STATE_ON: 606 ar->state = ATH10K_STATE_RESTARTING; 607 ret = 1; 608 break; 609 case ATH10K_STATE_OFF: 610 case ATH10K_STATE_RESTARTING: 611 case ATH10K_STATE_RESTARTED: 612 case ATH10K_STATE_UTF: 613 case ATH10K_STATE_WEDGED: 614 ath10k_warn(ar, "encountered unexpected device state %d on resume, cannot recover\n", 615 ar->state); 616 ret = -EIO; 617 break; 618 } 619 } 620 621 mutex_unlock(&ar->conf_mutex); 622 return ret; 623 } 624 625 int ath10k_wow_init(struct ath10k *ar) 626 { 627 if (!test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, 628 ar->running_fw->fw_file.fw_features)) 629 return 0; 630 631 if (WARN_ON(!test_bit(WMI_SERVICE_WOW, ar->wmi.svc_map))) 632 return -EINVAL; 633 634 ar->wow.wowlan_support = ath10k_wowlan_support; 635 636 if (ar->wmi.rx_decap_mode == ATH10K_HW_TXRX_NATIVE_WIFI) { 637 ar->wow.wowlan_support.pattern_max_len -= WOW_MAX_REDUCE; 638 ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE; 639 } 640 641 if (test_bit(WMI_SERVICE_NLO, ar->wmi.svc_map)) { 642 ar->wow.wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT; 643 ar->wow.wowlan_support.max_nd_match_sets = WMI_PNO_MAX_SUPP_NETWORKS; 644 } 645 646 ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns; 647 ar->hw->wiphy->wowlan = &ar->wow.wowlan_support; 648 649 device_set_wakeup_capable(ar->dev, true); 650 651 return 0; 652 } 653