aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorWen Gong <wgong@codeaurora.org>2018-10-04 01:45:31 -0400
committerKalle Valo <kvalo@codeaurora.org>2018-10-13 13:18:02 -0400
commitce834e280f2f8753ab0432fb5b1912547abc5330 (patch)
tree9d531f49563a6c04f651c1309330d94a34bf73f2 /drivers/net/wireless/ath
parentf1157695c527d4ee949ac83f743f80107751a70c (diff)
ath10k: support NET_DETECT WoWLAN feature
For WoWLAN support it is expected to support wake up based on discovery of one or more known SSIDs. This is the WIPHY_WOWLAN_NET_DETECT feature, which shows up as an NL80211 feature flag. This shows up in 'iw phy' as: WoWLAN support: * wake up on network detection, up to 16 match sets And it can be enabled with command: iw phy0 wowlan enable net-detect interval 5000 delay 30 freqs 2412 matches ssid foo Firmware will do scan by the configured parameters after suspend and wakeup if it found matched SSIDs. Tested with QCA6174 hw3.0 with firmware WLAN.RM.4.4.1-00110-QCARMSWPZ-1. Signed-off-by: Wen Gong <wgong@codeaurora.org> [kvalo@codeaurora.org: fix lots of endian bugs, whitespace, commit log and style cleanup] Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h1
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c12
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-ops.h21
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.c187
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi-tlv.h254
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h57
-rw-r--r--drivers/net/wireless/ath/ath10k/wow.c168
7 files changed, 700 insertions, 0 deletions
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index c76af343db3d..c0d205daa55f 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -951,6 +951,7 @@ struct ath10k {
951 /* protected by conf_mutex */ 951 /* protected by conf_mutex */
952 u8 ps_state_enable; 952 u8 ps_state_enable;
953 953
954 bool nlo_enabled;
954 bool p2p; 955 bool p2p;
955 956
956 struct { 957 struct {
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index e1462cda4c20..a32bfcf23178 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -8501,6 +8501,18 @@ int ath10k_mac_register(struct ath10k *ar)
8501 ar->hw->wiphy->max_scan_ssids = WLAN_SCAN_PARAMS_MAX_SSID; 8501 ar->hw->wiphy->max_scan_ssids = WLAN_SCAN_PARAMS_MAX_SSID;
8502 ar->hw->wiphy->max_scan_ie_len = WLAN_SCAN_PARAMS_MAX_IE_LEN; 8502 ar->hw->wiphy->max_scan_ie_len = WLAN_SCAN_PARAMS_MAX_IE_LEN;
8503 8503
8504 if (test_bit(WMI_SERVICE_NLO, ar->wmi.svc_map)) {
8505 ar->hw->wiphy->max_sched_scan_reqs = 1;
8506 ar->hw->wiphy->max_sched_scan_ssids = WMI_PNO_MAX_SUPP_NETWORKS;
8507 ar->hw->wiphy->max_match_sets = WMI_PNO_MAX_SUPP_NETWORKS;
8508 ar->hw->wiphy->max_sched_scan_ie_len = WMI_PNO_MAX_IE_LENGTH;
8509 ar->hw->wiphy->max_sched_scan_plans = WMI_PNO_MAX_SCHED_SCAN_PLANS;
8510 ar->hw->wiphy->max_sched_scan_plan_interval =
8511 WMI_PNO_MAX_SCHED_SCAN_PLAN_INT;
8512 ar->hw->wiphy->max_sched_scan_plan_iterations =
8513 WMI_PNO_MAX_SCHED_SCAN_PLAN_ITRNS;
8514 }
8515
8504 ar->hw->vif_data_size = sizeof(struct ath10k_vif); 8516 ar->hw->vif_data_size = sizeof(struct ath10k_vif);
8505 ar->hw->sta_data_size = sizeof(struct ath10k_sta); 8517 ar->hw->sta_data_size = sizeof(struct ath10k_sta);
8506 ar->hw->txq_data_size = sizeof(struct ath10k_txq); 8518 ar->hw->txq_data_size = sizeof(struct ath10k_txq);
diff --git a/drivers/net/wireless/ath/ath10k/wmi-ops.h b/drivers/net/wireless/ath/ath10k/wmi-ops.h
index 7fd63bbf8e24..7978a7783f90 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-ops.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-ops.h
@@ -210,6 +210,9 @@ struct wmi_ops {
210 u32 fw_feature_bitmap); 210 u32 fw_feature_bitmap);
211 int (*get_vdev_subtype)(struct ath10k *ar, 211 int (*get_vdev_subtype)(struct ath10k *ar,
212 enum wmi_vdev_subtype subtype); 212 enum wmi_vdev_subtype subtype);
213 struct sk_buff *(*gen_wow_config_pno)(struct ath10k *ar,
214 u32 vdev_id,
215 struct wmi_pno_scan_req *pno_scan);
213 struct sk_buff *(*gen_pdev_bss_chan_info_req) 216 struct sk_buff *(*gen_pdev_bss_chan_info_req)
214 (struct ath10k *ar, 217 (struct ath10k *ar,
215 enum wmi_bss_survey_req_type type); 218 enum wmi_bss_survey_req_type type);
@@ -1361,6 +1364,24 @@ ath10k_wmi_wow_del_pattern(struct ath10k *ar, u32 vdev_id, u32 pattern_id)
1361} 1364}
1362 1365
1363static inline int 1366static inline int
1367ath10k_wmi_wow_config_pno(struct ath10k *ar, u32 vdev_id,
1368 struct wmi_pno_scan_req *pno_scan)
1369{
1370 struct sk_buff *skb;
1371 u32 cmd_id;
1372
1373 if (!ar->wmi.ops->gen_wow_config_pno)
1374 return -EOPNOTSUPP;
1375
1376 skb = ar->wmi.ops->gen_wow_config_pno(ar, vdev_id, pno_scan);
1377 if (IS_ERR(skb))
1378 return PTR_ERR(skb);
1379
1380 cmd_id = ar->wmi.cmd->network_list_offload_config_cmdid;
1381 return ath10k_wmi_cmd_send(ar, skb, cmd_id);
1382}
1383
1384static inline int
1364ath10k_wmi_update_fw_tdls_state(struct ath10k *ar, u32 vdev_id, 1385ath10k_wmi_update_fw_tdls_state(struct ath10k *ar, u32 vdev_id,
1365 enum wmi_tdls_state state) 1386 enum wmi_tdls_state state)
1366{ 1387{
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
index 731ceaed4d5a..bab8b2527fb8 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c
@@ -3441,6 +3441,192 @@ ath10k_wmi_tlv_op_gen_wow_del_pattern(struct ath10k *ar, u32 vdev_id,
3441 return skb; 3441 return skb;
3442} 3442}
3443 3443
3444/* Request FW to start PNO operation */
3445static struct sk_buff *
3446ath10k_wmi_tlv_op_gen_config_pno_start(struct ath10k *ar,
3447 u32 vdev_id,
3448 struct wmi_pno_scan_req *pno)
3449{
3450 struct nlo_configured_parameters *nlo_list;
3451 struct wmi_tlv_wow_nlo_config_cmd *cmd;
3452 struct wmi_tlv *tlv;
3453 struct sk_buff *skb;
3454 __le32 *channel_list;
3455 u16 tlv_len;
3456 size_t len;
3457 void *ptr;
3458 u32 i;
3459
3460 len = sizeof(*tlv) + sizeof(*cmd) +
3461 sizeof(*tlv) +
3462 /* TLV place holder for array of structures
3463 * nlo_configured_parameters(nlo_list)
3464 */
3465 sizeof(*tlv);
3466 /* TLV place holder for array of uint32 channel_list */
3467
3468 len += sizeof(u32) * min_t(u8, pno->a_networks[0].channel_count,
3469 WMI_NLO_MAX_CHAN);
3470 len += sizeof(struct nlo_configured_parameters) *
3471 min_t(u8, pno->uc_networks_count, WMI_NLO_MAX_SSIDS);
3472
3473 skb = ath10k_wmi_alloc_skb(ar, len);
3474 if (!skb)
3475 return ERR_PTR(-ENOMEM);
3476
3477 ptr = (void *)skb->data;
3478 tlv = ptr;
3479 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_NLO_CONFIG_CMD);
3480 tlv->len = __cpu_to_le16(sizeof(*cmd));
3481 cmd = (void *)tlv->value;
3482
3483 /* wmi_tlv_wow_nlo_config_cmd parameters*/
3484 cmd->vdev_id = __cpu_to_le32(pno->vdev_id);
3485 cmd->flags = __cpu_to_le32(WMI_NLO_CONFIG_START | WMI_NLO_CONFIG_SSID_HIDE_EN);
3486
3487 /* current FW does not support min-max range for dwell time */
3488 cmd->active_dwell_time = __cpu_to_le32(pno->active_max_time);
3489 cmd->passive_dwell_time = __cpu_to_le32(pno->passive_max_time);
3490
3491 if (pno->do_passive_scan)
3492 cmd->flags |= __cpu_to_le32(WMI_NLO_CONFIG_SCAN_PASSIVE);
3493
3494 /* copy scan interval */
3495 cmd->fast_scan_period = __cpu_to_le32(pno->fast_scan_period);
3496 cmd->slow_scan_period = __cpu_to_le32(pno->slow_scan_period);
3497 cmd->fast_scan_max_cycles = __cpu_to_le32(pno->fast_scan_max_cycles);
3498 cmd->delay_start_time = __cpu_to_le32(pno->delay_start_time);
3499
3500 if (pno->enable_pno_scan_randomization) {
3501 cmd->flags |= __cpu_to_le32(WMI_NLO_CONFIG_SPOOFED_MAC_IN_PROBE_REQ |
3502 WMI_NLO_CONFIG_RANDOM_SEQ_NO_IN_PROBE_REQ);
3503 ether_addr_copy(cmd->mac_addr.addr, pno->mac_addr);
3504 ether_addr_copy(cmd->mac_mask.addr, pno->mac_addr_mask);
3505 }
3506
3507 ptr += sizeof(*tlv);
3508 ptr += sizeof(*cmd);
3509
3510 /* nlo_configured_parameters(nlo_list) */
3511 cmd->no_of_ssids = __cpu_to_le32(min_t(u8, pno->uc_networks_count,
3512 WMI_NLO_MAX_SSIDS));
3513 tlv_len = __le32_to_cpu(cmd->no_of_ssids) *
3514 sizeof(struct nlo_configured_parameters);
3515
3516 tlv = ptr;
3517 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3518 tlv->len = __cpu_to_le16(len);
3519
3520 ptr += sizeof(*tlv);
3521 nlo_list = ptr;
3522 for (i = 0; i < __le32_to_cpu(cmd->no_of_ssids); i++) {
3523 tlv = (struct wmi_tlv *)(&nlo_list[i].tlv_header);
3524 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_BYTE);
3525 tlv->len = __cpu_to_le16(sizeof(struct nlo_configured_parameters) -
3526 sizeof(*tlv));
3527
3528 /* copy ssid and it's length */
3529 nlo_list[i].ssid.valid = __cpu_to_le32(true);
3530 nlo_list[i].ssid.ssid.ssid_len = pno->a_networks[i].ssid.ssid_len;
3531 memcpy(nlo_list[i].ssid.ssid.ssid,
3532 pno->a_networks[i].ssid.ssid,
3533 __le32_to_cpu(nlo_list[i].ssid.ssid.ssid_len));
3534
3535 /* copy rssi threshold */
3536 if (pno->a_networks[i].rssi_threshold &&
3537 pno->a_networks[i].rssi_threshold > -300) {
3538 nlo_list[i].rssi_cond.valid = __cpu_to_le32(true);
3539 nlo_list[i].rssi_cond.rssi =
3540 __cpu_to_le32(pno->a_networks[i].rssi_threshold);
3541 }
3542
3543 nlo_list[i].bcast_nw_type.valid = __cpu_to_le32(true);
3544 nlo_list[i].bcast_nw_type.bcast_nw_type =
3545 __cpu_to_le32(pno->a_networks[i].bcast_nw_type);
3546 }
3547
3548 ptr += __le32_to_cpu(cmd->no_of_ssids) * sizeof(struct nlo_configured_parameters);
3549
3550 /* copy channel info */
3551 cmd->num_of_channels = __cpu_to_le32(min_t(u8,
3552 pno->a_networks[0].channel_count,
3553 WMI_NLO_MAX_CHAN));
3554
3555 tlv = ptr;
3556 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
3557 tlv->len = __cpu_to_le16(__le32_to_cpu(cmd->num_of_channels) *
3558 sizeof(u_int32_t));
3559 ptr += sizeof(*tlv);
3560
3561 channel_list = (__le32 *)ptr;
3562 for (i = 0; i < __le32_to_cpu(cmd->num_of_channels); i++)
3563 channel_list[i] = __cpu_to_le32(pno->a_networks[0].channels[i]);
3564
3565 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv start pno config vdev_id %d\n",
3566 vdev_id);
3567
3568 return skb;
3569}
3570
3571/* Request FW to stop ongoing PNO operation */
3572static struct sk_buff *ath10k_wmi_tlv_op_gen_config_pno_stop(struct ath10k *ar,
3573 u32 vdev_id)
3574{
3575 struct wmi_tlv_wow_nlo_config_cmd *cmd;
3576 struct wmi_tlv *tlv;
3577 struct sk_buff *skb;
3578 void *ptr;
3579 size_t len;
3580
3581 len = sizeof(*tlv) + sizeof(*cmd) +
3582 sizeof(*tlv) +
3583 /* TLV place holder for array of structures
3584 * nlo_configured_parameters(nlo_list)
3585 */
3586 sizeof(*tlv);
3587 /* TLV place holder for array of uint32 channel_list */
3588 skb = ath10k_wmi_alloc_skb(ar, len);
3589 if (!skb)
3590 return ERR_PTR(-ENOMEM);
3591
3592 ptr = (void *)skb->data;
3593 tlv = ptr;
3594 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_STRUCT_NLO_CONFIG_CMD);
3595 tlv->len = __cpu_to_le16(sizeof(*cmd));
3596 cmd = (void *)tlv->value;
3597
3598 cmd->vdev_id = __cpu_to_le32(vdev_id);
3599 cmd->flags = __cpu_to_le32(WMI_NLO_CONFIG_STOP);
3600
3601 ptr += sizeof(*tlv);
3602 ptr += sizeof(*cmd);
3603
3604 /* nlo_configured_parameters(nlo_list) */
3605 tlv = ptr;
3606 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_STRUCT);
3607 tlv->len = __cpu_to_le16(0);
3608
3609 ptr += sizeof(*tlv);
3610
3611 /* channel list */
3612 tlv = ptr;
3613 tlv->tag = __cpu_to_le16(WMI_TLV_TAG_ARRAY_UINT32);
3614 tlv->len = __cpu_to_le16(0);
3615
3616 ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi tlv stop pno config vdev_id %d\n", vdev_id);
3617 return skb;
3618}
3619
3620static struct sk_buff *
3621ath10k_wmi_tlv_op_gen_config_pno(struct ath10k *ar, u32 vdev_id,
3622 struct wmi_pno_scan_req *pno_scan)
3623{
3624 if (pno_scan->enable)
3625 return ath10k_wmi_tlv_op_gen_config_pno_start(ar, vdev_id, pno_scan);
3626 else
3627 return ath10k_wmi_tlv_op_gen_config_pno_stop(ar, vdev_id);
3628}
3629
3444static struct sk_buff * 3630static struct sk_buff *
3445ath10k_wmi_tlv_op_gen_adaptive_qcs(struct ath10k *ar, bool enable) 3631ath10k_wmi_tlv_op_gen_adaptive_qcs(struct ath10k *ar, bool enable)
3446{ 3632{
@@ -3973,6 +4159,7 @@ static const struct wmi_ops wmi_tlv_ops = {
3973 .gen_wow_host_wakeup_ind = ath10k_wmi_tlv_gen_wow_host_wakeup_ind, 4159 .gen_wow_host_wakeup_ind = ath10k_wmi_tlv_gen_wow_host_wakeup_ind,
3974 .gen_wow_add_pattern = ath10k_wmi_tlv_op_gen_wow_add_pattern, 4160 .gen_wow_add_pattern = ath10k_wmi_tlv_op_gen_wow_add_pattern,
3975 .gen_wow_del_pattern = ath10k_wmi_tlv_op_gen_wow_del_pattern, 4161 .gen_wow_del_pattern = ath10k_wmi_tlv_op_gen_wow_del_pattern,
4162 .gen_wow_config_pno = ath10k_wmi_tlv_op_gen_config_pno,
3976 .gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state, 4163 .gen_update_fw_tdls_state = ath10k_wmi_tlv_op_gen_update_fw_tdls_state,
3977 .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update, 4164 .gen_tdls_peer_update = ath10k_wmi_tlv_op_gen_tdls_peer_update,
3978 .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs, 4165 .gen_adaptive_qcs = ath10k_wmi_tlv_op_gen_adaptive_qcs,
diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.h b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
index 4f0c20c90642..92c25f51bf86 100644
--- a/drivers/net/wireless/ath/ath10k/wmi-tlv.h
+++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.h
@@ -2146,6 +2146,260 @@ struct wmi_tlv_tdls_peer_event {
2146 2146
2147void ath10k_wmi_tlv_attach(struct ath10k *ar); 2147void ath10k_wmi_tlv_attach(struct ath10k *ar);
2148 2148
2149enum wmi_nlo_auth_algorithm {
2150 WMI_NLO_AUTH_ALGO_80211_OPEN = 1,
2151 WMI_NLO_AUTH_ALGO_80211_SHARED_KEY = 2,
2152 WMI_NLO_AUTH_ALGO_WPA = 3,
2153 WMI_NLO_AUTH_ALGO_WPA_PSK = 4,
2154 WMI_NLO_AUTH_ALGO_WPA_NONE = 5,
2155 WMI_NLO_AUTH_ALGO_RSNA = 6,
2156 WMI_NLO_AUTH_ALGO_RSNA_PSK = 7,
2157};
2158
2159enum wmi_nlo_cipher_algorithm {
2160 WMI_NLO_CIPHER_ALGO_NONE = 0x00,
2161 WMI_NLO_CIPHER_ALGO_WEP40 = 0x01,
2162 WMI_NLO_CIPHER_ALGO_TKIP = 0x02,
2163 WMI_NLO_CIPHER_ALGO_CCMP = 0x04,
2164 WMI_NLO_CIPHER_ALGO_WEP104 = 0x05,
2165 WMI_NLO_CIPHER_ALGO_BIP = 0x06,
2166 WMI_NLO_CIPHER_ALGO_RSN_USE_GROUP = 0x100,
2167 WMI_NLO_CIPHER_ALGO_WEP = 0x101,
2168};
2169
2170/* SSID broadcast type passed in NLO params */
2171enum wmi_nlo_ssid_bcastnwtype {
2172 WMI_NLO_BCAST_UNKNOWN = 0,
2173 WMI_NLO_BCAST_NORMAL = 1,
2174 WMI_NLO_BCAST_HIDDEN = 2,
2175};
2176
2177#define WMI_NLO_MAX_SSIDS 16
2178#define WMI_NLO_MAX_CHAN 48
2179
2180#define WMI_NLO_CONFIG_STOP (0x1 << 0)
2181#define WMI_NLO_CONFIG_START (0x1 << 1)
2182#define WMI_NLO_CONFIG_RESET (0x1 << 2)
2183#define WMI_NLO_CONFIG_SLOW_SCAN (0x1 << 4)
2184#define WMI_NLO_CONFIG_FAST_SCAN (0x1 << 5)
2185#define WMI_NLO_CONFIG_SSID_HIDE_EN (0x1 << 6)
2186
2187/* This bit is used to indicate if EPNO or supplicant PNO is enabled.
2188 * Only one of them can be enabled at a given time
2189 */
2190#define WMI_NLO_CONFIG_ENLO (0x1 << 7)
2191#define WMI_NLO_CONFIG_SCAN_PASSIVE (0x1 << 8)
2192#define WMI_NLO_CONFIG_ENLO_RESET (0x1 << 9)
2193#define WMI_NLO_CONFIG_SPOOFED_MAC_IN_PROBE_REQ (0x1 << 10)
2194#define WMI_NLO_CONFIG_RANDOM_SEQ_NO_IN_PROBE_REQ (0x1 << 11)
2195#define WMI_NLO_CONFIG_ENABLE_IE_WHITELIST_IN_PROBE_REQ (0x1 << 12)
2196#define WMI_NLO_CONFIG_ENABLE_CNLO_RSSI_CONFIG (0x1 << 13)
2197
2198/* Whether directed scan needs to be performed (for hidden SSIDs) */
2199#define WMI_ENLO_FLAG_DIRECTED_SCAN 1
2200
2201/* Whether PNO event shall be triggered if the network is found on A band */
2202#define WMI_ENLO_FLAG_A_BAND 2
2203
2204/* Whether PNO event shall be triggered if the network is found on G band */
2205#define WMI_ENLO_FLAG_G_BAND 4
2206
2207/* Whether strict matching is required (i.e. firmware shall not
2208 * match on the entire SSID)
2209 */
2210#define WMI_ENLO_FLAG_STRICT_MATCH 8
2211
2212/* Code for matching the beacon AUTH IE - additional codes TBD */
2213/* open */
2214#define WMI_ENLO_AUTH_CODE_OPEN 1
2215
2216/* WPA_PSK or WPA2PSK */
2217#define WMI_ENLO_AUTH_CODE_PSK 2
2218
2219/* any EAPOL */
2220#define WMI_ENLO_AUTH_CODE_EAPOL 4
2221
2222struct wmi_nlo_ssid_param {
2223 __le32 valid;
2224 struct wmi_ssid ssid;
2225} __packed;
2226
2227struct wmi_nlo_enc_param {
2228 __le32 valid;
2229 __le32 enc_type;
2230} __packed;
2231
2232struct wmi_nlo_auth_param {
2233 __le32 valid;
2234 __le32 auth_type;
2235} __packed;
2236
2237struct wmi_nlo_bcast_nw_param {
2238 __le32 valid;
2239
2240 /* If WMI_NLO_CONFIG_EPNO is not set. Supplicant PNO is enabled.
2241 * The value should be true/false. Otherwise EPNO is enabled.
2242 * bcast_nw_type would be used as a bit flag contains WMI_ENLO_FLAG_XXX
2243 */
2244 __le32 bcast_nw_type;
2245} __packed;
2246
2247struct wmi_nlo_rssi_param {
2248 __le32 valid;
2249 __le32 rssi;
2250} __packed;
2251
2252struct nlo_configured_parameters {
2253 /* TLV tag and len;*/
2254 __le32 tlv_header;
2255 struct wmi_nlo_ssid_param ssid;
2256 struct wmi_nlo_enc_param enc_type;
2257 struct wmi_nlo_auth_param auth_type;
2258 struct wmi_nlo_rssi_param rssi_cond;
2259
2260 /* indicates if the SSID is hidden or not */
2261 struct wmi_nlo_bcast_nw_param bcast_nw_type;
2262} __packed;
2263
2264/* Support channel prediction for PNO scan after scanning top_k_num channels
2265 * if stationary_threshold is met.
2266 */
2267struct nlo_channel_prediction_cfg {
2268 __le32 tlv_header;
2269
2270 /* Enable or disable this feature. */
2271 __le32 enable;
2272
2273 /* Top K channels will be scanned before deciding whether to further scan
2274 * or stop. Minimum value is 3 and maximum is 5.
2275 */
2276 __le32 top_k_num;
2277
2278 /* Preconfigured stationary threshold.
2279 * Lesser value means more conservative. Bigger value means more aggressive.
2280 * Maximum is 100 and mininum is 0.
2281 */
2282 __le32 stationary_threshold;
2283
2284 /* Periodic full channel scan in milliseconds unit.
2285 * After full_scan_period_ms since last full scan, channel prediction
2286 * scan is suppressed and will do full scan.
2287 * This is to help detecting sudden AP power-on or -off. Value 0 means no
2288 * full scan at all (not recommended).
2289 */
2290 __le32 full_scan_period_ms;
2291} __packed;
2292
2293struct enlo_candidate_score_params_t {
2294 __le32 tlv_header; /* TLV tag and len; */
2295
2296 /* minimum 5GHz RSSI for a BSSID to be considered (units = dBm) */
2297 __le32 min_5ghz_rssi;
2298
2299 /* minimum 2.4GHz RSSI for a BSSID to be considered (units = dBm) */
2300 __le32 min_24ghz_rssi;
2301
2302 /* the maximum score that a network can have before bonuses */
2303 __le32 initial_score_max;
2304
2305 /* current_connection_bonus:
2306 * only report when there is a network's score this much higher
2307 * than the current connection
2308 */
2309 __le32 current_connection_bonus;
2310
2311 /* score bonus for all networks with the same network flag */
2312 __le32 same_network_bonus;
2313
2314 /* score bonus for networks that are not open */
2315 __le32 secure_bonus;
2316
2317 /* 5GHz RSSI score bonus (applied to all 5GHz networks) */
2318 __le32 band_5ghz_bonus;
2319} __packed;
2320
2321struct connected_nlo_bss_band_rssi_pref_t {
2322 __le32 tlv_header; /* TLV tag and len;*/
2323
2324 /* band which needs to get preference over other band
2325 * - see wmi_set_vdev_ie_band enum
2326 */
2327 __le32 band;
2328
2329 /* Amount of RSSI preference (in dB) that can be given to a band */
2330 __le32 rssi_pref;
2331} __packed;
2332
2333struct connected_nlo_rssi_params_t {
2334 __le32 tlv_header; /* TLV tag and len;*/
2335
2336 /* Relative rssi threshold (in dB) by which new BSS should have
2337 * better rssi than the current connected BSS.
2338 */
2339 __le32 relative_rssi;
2340
2341 /* The amount of rssi preference (in dB) that can be given
2342 * to a 5G BSS over 2.4G BSS.
2343 */
2344 __le32 relative_rssi_5g_pref;
2345} __packed;
2346
2347struct wmi_tlv_wow_nlo_config_cmd {
2348 __le32 flags;
2349 __le32 vdev_id;
2350 __le32 fast_scan_max_cycles;
2351 __le32 active_dwell_time;
2352 __le32 passive_dwell_time; /* PDT in msecs */
2353 __le32 probe_bundle_size;
2354
2355 /* ART = IRT */
2356 __le32 rest_time;
2357
2358 /* Max value that can be reached after SBM */
2359 __le32 max_rest_time;
2360
2361 /* SBM */
2362 __le32 scan_backoff_multiplier;
2363
2364 /* SCBM */
2365 __le32 fast_scan_period;
2366
2367 /* specific to windows */
2368 __le32 slow_scan_period;
2369
2370 __le32 no_of_ssids;
2371
2372 __le32 num_of_channels;
2373
2374 /* NLO scan start delay time in milliseconds */
2375 __le32 delay_start_time;
2376
2377 /** MAC Address to use in Probe Req as SA **/
2378 struct wmi_mac_addr mac_addr;
2379
2380 /** Mask on which MAC has to be randomized **/
2381 struct wmi_mac_addr mac_mask;
2382
2383 /** IE bitmap to use in Probe Req **/
2384 __le32 ie_bitmap[8];
2385
2386 /** Number of vendor OUIs. In the TLV vendor_oui[] **/
2387 __le32 num_vendor_oui;
2388
2389 /** Number of connected NLO band preferences **/
2390 __le32 num_cnlo_band_pref;
2391
2392 /* The TLVs will follow.
2393 * nlo_configured_parameters nlo_list[];
2394 * A_UINT32 channel_list[num_of_channels];
2395 * nlo_channel_prediction_cfg ch_prediction_cfg;
2396 * enlo_candidate_score_params candidate_score_params;
2397 * wmi_vendor_oui vendor_oui[num_vendor_oui];
2398 * connected_nlo_rssi_params cnlo_rssi_params;
2399 * connected_nlo_bss_band_rssi_pref cnlo_bss_band_rssi_pref[num_cnlo_band_pref];
2400 */
2401} __packed;
2402
2149struct wmi_tlv_mgmt_tx_cmd { 2403struct wmi_tlv_mgmt_tx_cmd {
2150 __le32 vdev_id; 2404 __le32 vdev_id;
2151 __le32 desc_id; 2405 __le32 desc_id;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index f67c52757ea6..f7badd079051 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -7068,6 +7068,63 @@ struct wmi_pdev_set_adaptive_cca_params {
7068 __le32 cca_detect_margin; 7068 __le32 cca_detect_margin;
7069} __packed; 7069} __packed;
7070 7070
7071#define WMI_PNO_MAX_SCHED_SCAN_PLANS 2
7072#define WMI_PNO_MAX_SCHED_SCAN_PLAN_INT 7200
7073#define WMI_PNO_MAX_SCHED_SCAN_PLAN_ITRNS 100
7074#define WMI_PNO_MAX_NETW_CHANNELS 26
7075#define WMI_PNO_MAX_NETW_CHANNELS_EX 60
7076#define WMI_PNO_MAX_SUPP_NETWORKS WLAN_SCAN_PARAMS_MAX_SSID
7077#define WMI_PNO_MAX_IE_LENGTH WLAN_SCAN_PARAMS_MAX_IE_LEN
7078
7079/*size based of dot11 declaration without extra IEs as we will not carry those for PNO*/
7080#define WMI_PNO_MAX_PB_REQ_SIZE 450
7081
7082#define WMI_PNO_24G_DEFAULT_CH 1
7083#define WMI_PNO_5G_DEFAULT_CH 36
7084
7085#define WMI_ACTIVE_MAX_CHANNEL_TIME 40
7086#define WMI_PASSIVE_MAX_CHANNEL_TIME 110
7087
7088/* SSID broadcast type */
7089enum wmi_SSID_bcast_type {
7090 BCAST_UNKNOWN = 0,
7091 BCAST_NORMAL = 1,
7092 BCAST_HIDDEN = 2,
7093};
7094
7095struct wmi_network_type {
7096 struct wmi_ssid ssid;
7097 u32 authentication;
7098 u32 encryption;
7099 u32 bcast_nw_type;
7100 u8 channel_count;
7101 u16 channels[WMI_PNO_MAX_NETW_CHANNELS_EX];
7102 s32 rssi_threshold;
7103} __packed;
7104
7105struct wmi_pno_scan_req {
7106 u8 enable;
7107 u8 vdev_id;
7108 u8 uc_networks_count;
7109 struct wmi_network_type a_networks[WMI_PNO_MAX_SUPP_NETWORKS];
7110 u32 fast_scan_period;
7111 u32 slow_scan_period;
7112 u8 fast_scan_max_cycles;
7113
7114 bool do_passive_scan;
7115
7116 u32 delay_start_time;
7117 u32 active_min_time;
7118 u32 active_max_time;
7119 u32 passive_min_time;
7120 u32 passive_max_time;
7121
7122 /* mac address randomization attributes */
7123 u32 enable_pno_scan_randomization;
7124 u8 mac_addr[ETH_ALEN];
7125 u8 mac_addr_mask[ETH_ALEN];
7126} __packed;
7127
7071enum wmi_host_platform_type { 7128enum wmi_host_platform_type {
7072 WMI_HOST_PLATFORM_HIGH_PERF, 7129 WMI_HOST_PLATFORM_HIGH_PERF,
7073 WMI_HOST_PLATFORM_LOW_PERF, 7130 WMI_HOST_PLATFORM_LOW_PERF,
diff --git a/drivers/net/wireless/ath/ath10k/wow.c b/drivers/net/wireless/ath/ath10k/wow.c
index af444dfecae9..51b26b305885 100644
--- a/drivers/net/wireless/ath/ath10k/wow.c
+++ b/drivers/net/wireless/ath/ath10k/wow.c
@@ -180,6 +180,100 @@ static void ath10k_wow_convert_8023_to_80211
180 } 180 }
181} 181}
182 182
183static 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
183static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif, 277static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif,
184 struct cfg80211_wowlan *wowlan) 278 struct cfg80211_wowlan *wowlan)
185{ 279{
@@ -213,6 +307,26 @@ static int ath10k_vif_wow_set_wakeups(struct ath10k_vif *arvif,
213 307
214 if (wowlan->magic_pkt) 308 if (wowlan->magic_pkt)
215 __set_bit(WOW_MAGIC_PKT_RECVD_EVENT, &wow_mask); 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 }
216 break; 330 break;
217 default: 331 default:
218 break; 332 break;
@@ -299,6 +413,51 @@ static int ath10k_wow_set_wakeups(struct ath10k *ar,
299 return 0; 413 return 0;
300} 414}
301 415
416static 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
442static 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
302static int ath10k_wow_enable(struct ath10k *ar) 461static int ath10k_wow_enable(struct ath10k *ar)
303{ 462{
304 int ret; 463 int ret;
@@ -436,6 +595,10 @@ int ath10k_wow_op_resume(struct ieee80211_hw *hw)
436 if (ret) 595 if (ret)
437 ath10k_warn(ar, "failed to wakeup from wow: %d\n", ret); 596 ath10k_warn(ar, "failed to wakeup from wow: %d\n", ret);
438 597
598 ret = ath10k_wow_nlo_cleanup(ar);
599 if (ret)
600 ath10k_warn(ar, "failed to cleanup nlo: %d\n", ret);
601
439exit: 602exit:
440 if (ret) { 603 if (ret) {
441 switch (ar->state) { 604 switch (ar->state) {
@@ -475,6 +638,11 @@ int ath10k_wow_init(struct ath10k *ar)
475 ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE; 638 ar->wow.wowlan_support.max_pkt_offset -= WOW_MAX_REDUCE;
476 } 639 }
477 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
478 ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns; 646 ar->wow.wowlan_support.n_patterns = ar->wow.max_num_patterns;
479 ar->hw->wiphy->wowlan = &ar->wow.wowlan_support; 647 ar->hw->wiphy->wowlan = &ar->wow.wowlan_support;
480 648