wow.c (ba9177fcef21fa98406e73c472b5ac2eb4ec5f31) | wow.c (fec4b898f369a9b9d516f7bfc459eb4a8c5ceb2c) |
---|---|
1// SPDX-License-Identifier: BSD-3-Clause-Clear 2/* 3 * Copyright (c) 2020 The Linux Foundation. All rights reserved. 4 */ 5 6#include <linux/delay.h> 7 8#include "mac.h" --- 214 unchanged lines hidden (view full) --- 223 memcpy((u8 *)new->mask + new->pattern_len, 224 (void *)old->mask + ETH_HLEN - old->pkt_offset, 225 total_len - ETH_HLEN); 226 227 new->pattern_len += total_len - ETH_HLEN; 228 } 229} 230 | 1// SPDX-License-Identifier: BSD-3-Clause-Clear 2/* 3 * Copyright (c) 2020 The Linux Foundation. All rights reserved. 4 */ 5 6#include <linux/delay.h> 7 8#include "mac.h" --- 214 unchanged lines hidden (view full) --- 223 memcpy((u8 *)new->mask + new->pattern_len, 224 (void *)old->mask + ETH_HLEN - old->pkt_offset, 225 total_len - ETH_HLEN); 226 227 new->pattern_len += total_len - ETH_HLEN; 228 } 229} 230 |
231static int ath11k_wmi_pno_check_and_convert(struct ath11k *ar, u32 vdev_id, 232 struct cfg80211_sched_scan_request *nd_config, 233 struct wmi_pno_scan_req *pno) 234{ 235 int i, j; 236 u8 ssid_len; 237 238 pno->enable = 1; 239 pno->vdev_id = vdev_id; 240 pno->uc_networks_count = nd_config->n_match_sets; 241 242 if (!pno->uc_networks_count || 243 pno->uc_networks_count > WMI_PNO_MAX_SUPP_NETWORKS) 244 return -EINVAL; 245 246 if (nd_config->n_channels > WMI_PNO_MAX_NETW_CHANNELS_EX) 247 return -EINVAL; 248 249 /* Filling per profile params */ 250 for (i = 0; i < pno->uc_networks_count; i++) { 251 ssid_len = nd_config->match_sets[i].ssid.ssid_len; 252 253 if (ssid_len == 0 || ssid_len > 32) 254 return -EINVAL; 255 256 pno->a_networks[i].ssid.ssid_len = ssid_len; 257 258 memcpy(pno->a_networks[i].ssid.ssid, 259 nd_config->match_sets[i].ssid.ssid, 260 nd_config->match_sets[i].ssid.ssid_len); 261 pno->a_networks[i].authentication = 0; 262 pno->a_networks[i].encryption = 0; 263 pno->a_networks[i].bcast_nw_type = 0; 264 265 /* Copying list of valid channel into request */ 266 pno->a_networks[i].channel_count = nd_config->n_channels; 267 pno->a_networks[i].rssi_threshold = nd_config->match_sets[i].rssi_thold; 268 269 for (j = 0; j < nd_config->n_channels; j++) { 270 pno->a_networks[i].channels[j] = 271 nd_config->channels[j]->center_freq; 272 } 273 } 274 275 /* set scan to passive if no SSIDs are specified in the request */ 276 if (nd_config->n_ssids == 0) 277 pno->do_passive_scan = true; 278 else 279 pno->do_passive_scan = false; 280 281 for (i = 0; i < nd_config->n_ssids; i++) { 282 j = 0; 283 while (j < pno->uc_networks_count) { 284 if (pno->a_networks[j].ssid.ssid_len == 285 nd_config->ssids[i].ssid_len && 286 (memcmp(pno->a_networks[j].ssid.ssid, 287 nd_config->ssids[i].ssid, 288 pno->a_networks[j].ssid.ssid_len) == 0)) { 289 pno->a_networks[j].bcast_nw_type = BCAST_HIDDEN; 290 break; 291 } 292 j++; 293 } 294 } 295 296 if (nd_config->n_scan_plans == 2) { 297 pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC; 298 pno->fast_scan_max_cycles = nd_config->scan_plans[0].iterations; 299 pno->slow_scan_period = 300 nd_config->scan_plans[1].interval * MSEC_PER_SEC; 301 } else if (nd_config->n_scan_plans == 1) { 302 pno->fast_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC; 303 pno->fast_scan_max_cycles = 1; 304 pno->slow_scan_period = nd_config->scan_plans[0].interval * MSEC_PER_SEC; 305 } else { 306 ath11k_warn(ar->ab, "Invalid number of scan plans %d !!", 307 nd_config->n_scan_plans); 308 } 309 310 if (nd_config->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) { 311 /* enable mac randomization */ 312 pno->enable_pno_scan_randomization = 1; 313 memcpy(pno->mac_addr, nd_config->mac_addr, ETH_ALEN); 314 memcpy(pno->mac_addr_mask, nd_config->mac_addr_mask, ETH_ALEN); 315 } 316 317 pno->delay_start_time = nd_config->delay; 318 319 /* Current FW does not support min-max range for dwell time */ 320 pno->active_max_time = WMI_ACTIVE_MAX_CHANNEL_TIME; 321 pno->passive_max_time = WMI_PASSIVE_MAX_CHANNEL_TIME; 322 323 return 0; 324} 325 |
|
231static int ath11k_vif_wow_set_wakeups(struct ath11k_vif *arvif, 232 struct cfg80211_wowlan *wowlan) 233{ 234 int ret, i; 235 unsigned long wow_mask = 0; 236 struct ath11k *ar = arvif->ar; 237 const struct cfg80211_pkt_pattern *patterns = wowlan->patterns; 238 int pattern_id = 0; --- 17 unchanged lines hidden (view full) --- 256 __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask); 257 __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask); 258 __set_bit(WOW_BMISS_EVENT, &wow_mask); 259 __set_bit(WOW_CSA_IE_EVENT, &wow_mask); 260 } 261 262 if (wowlan->magic_pkt) 263 __set_bit(WOW_MAGIC_PKT_RECVD_EVENT, &wow_mask); | 326static int ath11k_vif_wow_set_wakeups(struct ath11k_vif *arvif, 327 struct cfg80211_wowlan *wowlan) 328{ 329 int ret, i; 330 unsigned long wow_mask = 0; 331 struct ath11k *ar = arvif->ar; 332 const struct cfg80211_pkt_pattern *patterns = wowlan->patterns; 333 int pattern_id = 0; --- 17 unchanged lines hidden (view full) --- 351 __set_bit(WOW_DEAUTH_RECVD_EVENT, &wow_mask); 352 __set_bit(WOW_DISASSOC_RECVD_EVENT, &wow_mask); 353 __set_bit(WOW_BMISS_EVENT, &wow_mask); 354 __set_bit(WOW_CSA_IE_EVENT, &wow_mask); 355 } 356 357 if (wowlan->magic_pkt) 358 __set_bit(WOW_MAGIC_PKT_RECVD_EVENT, &wow_mask); |
359 360 if (wowlan->nd_config) { 361 struct wmi_pno_scan_req *pno; 362 int ret; 363 364 pno = kzalloc(sizeof(*pno), GFP_KERNEL); 365 if (!pno) 366 return -ENOMEM; 367 368 ar->nlo_enabled = true; 369 370 ret = ath11k_wmi_pno_check_and_convert(ar, arvif->vdev_id, 371 wowlan->nd_config, pno); 372 if (!ret) { 373 ath11k_wmi_wow_config_pno(ar, arvif->vdev_id, pno); 374 __set_bit(WOW_NLO_DETECTED_EVENT, &wow_mask); 375 } 376 377 kfree(pno); 378 } |
|
264 break; 265 default: 266 break; 267 } 268 269 for (i = 0; i < wowlan->n_patterns; i++) { 270 u8 bitmask[WOW_MAX_PATTERN_SIZE] = {}; 271 u8 ath_pattern[WOW_MAX_PATTERN_SIZE] = {}; --- 77 unchanged lines hidden (view full) --- 349 arvif->vdev_id, ret); 350 return ret; 351 } 352 } 353 354 return 0; 355} 356 | 379 break; 380 default: 381 break; 382 } 383 384 for (i = 0; i < wowlan->n_patterns; i++) { 385 u8 bitmask[WOW_MAX_PATTERN_SIZE] = {}; 386 u8 ath_pattern[WOW_MAX_PATTERN_SIZE] = {}; --- 77 unchanged lines hidden (view full) --- 464 arvif->vdev_id, ret); 465 return ret; 466 } 467 } 468 469 return 0; 470} 471 |
472static int ath11k_vif_wow_clean_nlo(struct ath11k_vif *arvif) 473{ 474 int ret = 0; 475 struct ath11k *ar = arvif->ar; 476 477 switch (arvif->vdev_type) { 478 case WMI_VDEV_TYPE_STA: 479 if (ar->nlo_enabled) { 480 struct wmi_pno_scan_req *pno; 481 482 pno = kzalloc(sizeof(*pno), GFP_KERNEL); 483 if (!pno) 484 return -ENOMEM; 485 486 pno->enable = 0; 487 ar->nlo_enabled = false; 488 ret = ath11k_wmi_wow_config_pno(ar, arvif->vdev_id, pno); 489 kfree(pno); 490 } 491 break; 492 default: 493 break; 494 } 495 return ret; 496} 497 498static int ath11k_wow_nlo_cleanup(struct ath11k *ar) 499{ 500 struct ath11k_vif *arvif; 501 int ret; 502 503 lockdep_assert_held(&ar->conf_mutex); 504 505 list_for_each_entry(arvif, &ar->arvifs, list) { 506 ret = ath11k_vif_wow_clean_nlo(arvif); 507 if (ret) { 508 ath11k_warn(ar->ab, "failed to clean nlo settings on vdev %i: %d\n", 509 arvif->vdev_id, ret); 510 return ret; 511 } 512 } 513 514 return 0; 515} 516 |
|
357int ath11k_wow_op_suspend(struct ieee80211_hw *hw, 358 struct cfg80211_wowlan *wowlan) 359{ 360 struct ath11k *ar = hw->priv; 361 int ret; 362 363 mutex_lock(&ar->conf_mutex); 364 --- 69 unchanged lines hidden (view full) --- 434 ath11k_warn(ar->ab, "failed to resume hif: %d\n", ret); 435 goto exit; 436 } 437 438 ath11k_hif_ce_irq_enable(ar->ab); 439 ath11k_hif_irq_enable(ar->ab); 440 441 ret = ath11k_wow_wakeup(ar->ab); | 517int ath11k_wow_op_suspend(struct ieee80211_hw *hw, 518 struct cfg80211_wowlan *wowlan) 519{ 520 struct ath11k *ar = hw->priv; 521 int ret; 522 523 mutex_lock(&ar->conf_mutex); 524 --- 69 unchanged lines hidden (view full) --- 594 ath11k_warn(ar->ab, "failed to resume hif: %d\n", ret); 595 goto exit; 596 } 597 598 ath11k_hif_ce_irq_enable(ar->ab); 599 ath11k_hif_irq_enable(ar->ab); 600 601 ret = ath11k_wow_wakeup(ar->ab); |
442 if (ret) | 602 if (ret) { |
443 ath11k_warn(ar->ab, "failed to wakeup from wow: %d\n", ret); | 603 ath11k_warn(ar->ab, "failed to wakeup from wow: %d\n", ret); |
604 goto exit; 605 } |
|
444 | 606 |
607 ret = ath11k_wow_nlo_cleanup(ar); 608 if (ret) { 609 ath11k_warn(ar->ab, "failed to cleanup nlo: %d\n", ret); 610 goto exit; 611 } 612 |
|
445exit: 446 if (ret) { 447 switch (ar->state) { 448 case ATH11K_STATE_ON: 449 ar->state = ATH11K_STATE_RESTARTING; 450 ret = 1; 451 break; 452 case ATH11K_STATE_OFF: --- 19 unchanged lines hidden (view full) --- 472 ar->wow.wowlan_support = ath11k_wowlan_support; 473 474 if (ar->wmi->wmi_ab->wlan_resource_config.rx_decap_mode == 475 ATH11K_HW_TXRX_NATIVE_WIFI) { 476 ar->wow.wowlan_support.pattern_max_len -= WOW_MAX_REDUCE; 477 ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE; 478 } 479 | 613exit: 614 if (ret) { 615 switch (ar->state) { 616 case ATH11K_STATE_ON: 617 ar->state = ATH11K_STATE_RESTARTING; 618 ret = 1; 619 break; 620 case ATH11K_STATE_OFF: --- 19 unchanged lines hidden (view full) --- 640 ar->wow.wowlan_support = ath11k_wowlan_support; 641 642 if (ar->wmi->wmi_ab->wlan_resource_config.rx_decap_mode == 643 ATH11K_HW_TXRX_NATIVE_WIFI) { 644 ar->wow.wowlan_support.pattern_max_len -= WOW_MAX_REDUCE; 645 ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE; 646 } 647 |
648 if (test_bit(WMI_TLV_SERVICE_NLO, ar->wmi->wmi_ab->svc_map)) { 649 ar->wow.wowlan_support.flags |= WIPHY_WOWLAN_NET_DETECT; 650 ar->wow.wowlan_support.max_nd_match_sets = WMI_PNO_MAX_SUPP_NETWORKS; 651 } 652 |
|
480 ar->wow.max_num_patterns = ATH11K_WOW_PATTERNS; 481 ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns; 482 ar->hw->wiphy->wowlan = &ar->wow.wowlan_support; 483 484 device_set_wakeup_capable(ar->ab->dev, true); 485 486 return 0; 487} | 653 ar->wow.max_num_patterns = ATH11K_WOW_PATTERNS; 654 ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns; 655 ar->hw->wiphy->wowlan = &ar->wow.wowlan_support; 656 657 device_set_wakeup_capable(ar->ab->dev, true); 658 659 return 0; 660} |