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}