diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath10k')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/Makefile | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/core.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/core.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/htt_rx.c | 128 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/hw.c | 13 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/hw.h | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/mac.c | 168 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/pci.c | 46 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/pci.h | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/rx_desc.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/spectral.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi.h | 1 |
13 files changed, 270 insertions, 120 deletions
diff --git a/drivers/net/wireless/ath/ath10k/Makefile b/drivers/net/wireless/ath/ath10k/Makefile index 899b9b79f4ce..9492177e9063 100644 --- a/drivers/net/wireless/ath/ath10k/Makefile +++ b/drivers/net/wireless/ath/ath10k/Makefile @@ -1,3 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 obj-$(CONFIG_ATH10K) += ath10k_core.o ath10k_core-y += mac.o \ debug.o \ diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index a4f635820f35..b29fdbd21ead 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -74,6 +74,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .spectral_bin_discard = 0, .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, + .n_cipher_suites = 8, }, { .id = QCA9887_HW_1_0_VERSION, @@ -97,6 +98,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .spectral_bin_discard = 0, .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, + .n_cipher_suites = 8, }, { .id = QCA6174_HW_2_1_VERSION, @@ -119,6 +121,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .spectral_bin_discard = 0, .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, + .n_cipher_suites = 8, }, { .id = QCA6174_HW_2_1_VERSION, @@ -141,6 +144,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .spectral_bin_discard = 0, .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, + .n_cipher_suites = 8, }, { .id = QCA6174_HW_3_0_VERSION, @@ -163,6 +167,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .spectral_bin_discard = 0, .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, + .n_cipher_suites = 8, }, { .id = QCA6174_HW_3_2_VERSION, @@ -188,6 +193,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .spectral_bin_discard = 0, .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, + .n_cipher_suites = 8, }, { .id = QCA99X0_HW_2_0_DEV_VERSION, @@ -216,6 +222,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .spectral_bin_discard = 4, .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, + .n_cipher_suites = 11, }, { .id = QCA9984_HW_1_0_DEV_VERSION, @@ -249,6 +256,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { */ .vht160_mcs_rx_highest = 1560, .vht160_mcs_tx_highest = 1560, + .n_cipher_suites = 11, }, { .id = QCA9888_HW_2_0_DEV_VERSION, @@ -281,6 +289,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { */ .vht160_mcs_rx_highest = 780, .vht160_mcs_tx_highest = 780, + .n_cipher_suites = 11, }, { .id = QCA9377_HW_1_0_DEV_VERSION, @@ -303,6 +312,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .spectral_bin_discard = 0, .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, + .n_cipher_suites = 8, }, { .id = QCA9377_HW_1_1_DEV_VERSION, @@ -327,6 +337,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .spectral_bin_discard = 0, .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, + .n_cipher_suites = 8, }, { .id = QCA4019_HW_1_0_DEV_VERSION, @@ -356,6 +367,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .spectral_bin_discard = 4, .vht160_mcs_rx_highest = 0, .vht160_mcs_tx_highest = 0, + .n_cipher_suites = 11, }, }; @@ -377,6 +389,7 @@ static const char *const ath10k_core_fw_feature_str[] = { [ATH10K_FW_FEATURE_BTCOEX_PARAM] = "btcoex-param", [ATH10K_FW_FEATURE_SKIP_NULL_FUNC_WAR] = "skip-null-func-war", [ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST] = "allows-mesh-bcast", + [ATH10K_FW_FEATURE_NO_PS] = "no-ps", }; static unsigned int ath10k_core_get_fw_feature_str(char *buf, diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 949ebb3e967b..643041ef3271 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h @@ -612,6 +612,9 @@ enum ath10k_fw_features { */ ATH10K_FW_FEATURE_ALLOWS_MESH_BCAST = 16, + /* Firmware does not support power save in station mode. */ + ATH10K_FW_FEATURE_NO_PS = 17, + /* keep last */ ATH10K_FW_FEATURE_COUNT, }; diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index a3f5dc78353f..e31438541ee1 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c @@ -200,9 +200,9 @@ static void ath10k_htt_rx_msdu_buff_replenish(struct ath10k_htt *htt) spin_unlock_bh(&htt->rx_ring.lock); } -static void ath10k_htt_rx_ring_refill_retry(unsigned long arg) +static void ath10k_htt_rx_ring_refill_retry(struct timer_list *t) { - struct ath10k_htt *htt = (struct ath10k_htt *)arg; + struct ath10k_htt *htt = from_timer(htt, t, rx_ring.refill_retry_timer); ath10k_htt_rx_msdu_buff_replenish(htt); } @@ -507,7 +507,7 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) *htt->rx_ring.alloc_idx.vaddr = 0; /* Initialize the Rx refill retry timer */ - setup_timer(timer, ath10k_htt_rx_ring_refill_retry, (unsigned long)htt); + timer_setup(timer, ath10k_htt_rx_ring_refill_retry, 0); spin_lock_init(&htt->rx_ring.lock); @@ -550,6 +550,11 @@ static int ath10k_htt_rx_crypto_param_len(struct ath10k *ar, return IEEE80211_TKIP_IV_LEN; case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: return IEEE80211_CCMP_HDR_LEN; + case HTT_RX_MPDU_ENCRYPT_AES_CCM256_WPA2: + return IEEE80211_CCMP_256_HDR_LEN; + case HTT_RX_MPDU_ENCRYPT_AES_GCMP_WPA2: + case HTT_RX_MPDU_ENCRYPT_AES_GCMP256_WPA2: + return IEEE80211_GCMP_HDR_LEN; case HTT_RX_MPDU_ENCRYPT_WEP128: case HTT_RX_MPDU_ENCRYPT_WAPI: break; @@ -575,6 +580,11 @@ static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar, return IEEE80211_TKIP_ICV_LEN; case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: return IEEE80211_CCMP_MIC_LEN; + case HTT_RX_MPDU_ENCRYPT_AES_CCM256_WPA2: + return IEEE80211_CCMP_256_MIC_LEN; + case HTT_RX_MPDU_ENCRYPT_AES_GCMP_WPA2: + case HTT_RX_MPDU_ENCRYPT_AES_GCMP256_WPA2: + return IEEE80211_GCMP_MIC_LEN; case HTT_RX_MPDU_ENCRYPT_WEP128: case HTT_RX_MPDU_ENCRYPT_WAPI: break; @@ -1051,9 +1061,21 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar, hdr = (void *)msdu->data; /* Tail */ - if (status->flag & RX_FLAG_IV_STRIPPED) + if (status->flag & RX_FLAG_IV_STRIPPED) { skb_trim(msdu, msdu->len - ath10k_htt_rx_crypto_tail_len(ar, enctype)); + } else { + /* MIC */ + if ((status->flag & RX_FLAG_MIC_STRIPPED) && + enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) + skb_trim(msdu, msdu->len - 8); + + /* ICV */ + if (status->flag & RX_FLAG_ICV_STRIPPED && + enctype != HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2) + skb_trim(msdu, msdu->len - + ath10k_htt_rx_crypto_tail_len(ar, enctype)); + } /* MMIC */ if ((status->flag & RX_FLAG_MMIC_STRIPPED) && @@ -1075,7 +1097,8 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar, static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar, struct sk_buff *msdu, struct ieee80211_rx_status *status, - const u8 first_hdr[64]) + const u8 first_hdr[64], + enum htt_rx_mpdu_encrypt_type enctype) { struct ieee80211_hdr *hdr; struct htt_rx_desc *rxd; @@ -1083,6 +1106,7 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar, u8 da[ETH_ALEN]; u8 sa[ETH_ALEN]; int l3_pad_bytes; + int bytes_aligned = ar->hw_params.decap_align_bytes; /* Delivered decapped frame: * [nwifi 802.11 header] <-- replaced with 802.11 hdr @@ -1111,6 +1135,14 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar, /* push original 802.11 header */ hdr = (struct ieee80211_hdr *)first_hdr; hdr_len = ieee80211_hdrlen(hdr->frame_control); + + if (!(status->flag & RX_FLAG_IV_STRIPPED)) { + memcpy(skb_push(msdu, + ath10k_htt_rx_crypto_param_len(ar, enctype)), + (void *)hdr + round_up(hdr_len, bytes_aligned), + ath10k_htt_rx_crypto_param_len(ar, enctype)); + } + memcpy(skb_push(msdu, hdr_len), hdr, hdr_len); /* original 802.11 header has a different DA and in @@ -1171,6 +1203,7 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar, u8 sa[ETH_ALEN]; int l3_pad_bytes; struct htt_rx_desc *rxd; + int bytes_aligned = ar->hw_params.decap_align_bytes; /* Delivered decapped frame: * [eth header] <-- replaced with 802.11 hdr & rfc1042/llc @@ -1199,6 +1232,14 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar, /* push original 802.11 header */ hdr = (struct ieee80211_hdr *)first_hdr; hdr_len = ieee80211_hdrlen(hdr->frame_control); + + if (!(status->flag & RX_FLAG_IV_STRIPPED)) { + memcpy(skb_push(msdu, + ath10k_htt_rx_crypto_param_len(ar, enctype)), + (void *)hdr + round_up(hdr_len, bytes_aligned), + ath10k_htt_rx_crypto_param_len(ar, enctype)); + } + memcpy(skb_push(msdu, hdr_len), hdr, hdr_len); /* original 802.11 header has a different DA and in @@ -1212,12 +1253,14 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar, static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar, struct sk_buff *msdu, struct ieee80211_rx_status *status, - const u8 first_hdr[64]) + const u8 first_hdr[64], + enum htt_rx_mpdu_encrypt_type enctype) { struct ieee80211_hdr *hdr; size_t hdr_len; int l3_pad_bytes; struct htt_rx_desc *rxd; + int bytes_aligned = ar->hw_params.decap_align_bytes; /* Delivered decapped frame: * [amsdu header] <-- replaced with 802.11 hdr @@ -1233,6 +1276,14 @@ static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar, hdr = (struct ieee80211_hdr *)first_hdr; hdr_len = ieee80211_hdrlen(hdr->frame_control); + + if (!(status->flag & RX_FLAG_IV_STRIPPED)) { + memcpy(skb_push(msdu, + ath10k_htt_rx_crypto_param_len(ar, enctype)), + (void *)hdr + round_up(hdr_len, bytes_aligned), + ath10k_htt_rx_crypto_param_len(ar, enctype)); + } + memcpy(skb_push(msdu, hdr_len), hdr, hdr_len); } @@ -1267,13 +1318,15 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar, is_decrypted); break; case RX_MSDU_DECAP_NATIVE_WIFI: - ath10k_htt_rx_h_undecap_nwifi(ar, msdu, status, first_hdr); + ath10k_htt_rx_h_undecap_nwifi(ar, msdu, status, first_hdr, + enctype); break; case RX_MSDU_DECAP_ETHERNET2_DIX: ath10k_htt_rx_h_undecap_eth(ar, msdu, status, first_hdr, enctype); break; case RX_MSDU_DECAP_8023_SNAP_LLC: - ath10k_htt_rx_h_undecap_snap(ar, msdu, status, first_hdr); + ath10k_htt_rx_h_undecap_snap(ar, msdu, status, first_hdr, + enctype); break; } } @@ -1316,7 +1369,8 @@ static void ath10k_htt_rx_h_csum_offload(struct sk_buff *msdu) static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, struct sk_buff_head *amsdu, - struct ieee80211_rx_status *status) + struct ieee80211_rx_status *status, + bool fill_crypt_header) { struct sk_buff *first; struct sk_buff *last; @@ -1326,7 +1380,6 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, enum htt_rx_mpdu_encrypt_type enctype; u8 first_hdr[64]; u8 *qos; - size_t hdr_len; bool has_fcs_err; bool has_crypto_err; bool has_tkip_err; @@ -1351,15 +1404,17 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, * decapped header. It'll be used for undecapping of each MSDU. */ hdr = (void *)rxd->rx_hdr_status; - hdr_len = ieee80211_hdrlen(hdr->frame_control); - memcpy(first_hdr, hdr, hdr_len); + memcpy(first_hdr, hdr, RX_HTT_HDR_STATUS_LEN); /* Each A-MSDU subframe will use the original header as the base and be * reported as a separate MSDU so strip the A-MSDU bit from QoS Ctl. */ hdr = (void *)first_hdr; - qos = ieee80211_get_qos_ctl(hdr); - qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; + + if (ieee80211_is_data_qos(hdr->frame_control)) { + qos = ieee80211_get_qos_ctl(hdr); + qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; + } /* Some attention flags are valid only in the last MSDU. */ last = skb_peek_tail(amsdu); @@ -1406,9 +1461,14 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, status->flag |= RX_FLAG_DECRYPTED; if (likely(!is_mgmt)) - status->flag |= RX_FLAG_IV_STRIPPED | - RX_FLAG_MMIC_STRIPPED; -} + status->flag |= RX_FLAG_MMIC_STRIPPED; + + if (fill_crypt_header) + status->flag |= RX_FLAG_MIC_STRIPPED | + RX_FLAG_ICV_STRIPPED; + else + status->flag |= RX_FLAG_IV_STRIPPED; + } skb_queue_walk(amsdu, msdu) { ath10k_htt_rx_h_csum_offload(msdu); @@ -1424,6 +1484,9 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar, if (is_mgmt) continue; + if (fill_crypt_header) + continue; + hdr = (void *)msdu->data; hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED); } @@ -1434,6 +1497,9 @@ static void ath10k_htt_rx_h_deliver(struct ath10k *ar, struct ieee80211_rx_status *status) { struct sk_buff *msdu; + struct sk_buff *first_subframe; + + first_subframe = skb_peek(amsdu); while ((msdu = __skb_dequeue(amsdu))) { /* Setup per-MSDU flags */ @@ -1442,6 +1508,13 @@ static void ath10k_htt_rx_h_deliver(struct ath10k *ar, else status->flag |= RX_FLAG_AMSDU_MORE; + if (msdu == first_subframe) { + first_subframe = NULL; + status->flag &= ~RX_FLAG_ALLOW_SAME_PN; + } else { + status->flag |= RX_FLAG_ALLOW_SAME_PN; + } + ath10k_process_rx(ar, status, msdu); } } @@ -1584,7 +1657,7 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt) ath10k_htt_rx_h_unchain(ar, &amsdu); ath10k_htt_rx_h_filter(ar, &amsdu, rx_status); - ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status); + ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true); ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status); return num_msdus; @@ -1745,8 +1818,7 @@ static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp) } static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list, - struct sk_buff_head *amsdu, - int budget_left) + struct sk_buff_head *amsdu) { struct sk_buff *msdu; struct htt_rx_desc *rxd; @@ -1757,9 +1829,8 @@ static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list, if (WARN_ON(!skb_queue_empty(amsdu))) return -EINVAL; - while ((msdu = __skb_dequeue(list)) && budget_left) { + while ((msdu = __skb_dequeue(list))) { __skb_queue_tail(amsdu, msdu); - budget_left--; rxd = (void *)msdu->data - sizeof(*rxd); if (rxd->msdu_end.common.info0 & @@ -1850,8 +1921,7 @@ static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar, return num_msdu; } -static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb, - int budget_left) +static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb) { struct ath10k_htt *htt = &ar->htt; struct htt_resp *resp = (void *)skb->data; @@ -1908,9 +1978,9 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb, if (offload) num_msdus = ath10k_htt_rx_h_rx_offload(ar, &list); - while (!skb_queue_empty(&list) && budget_left) { + while (!skb_queue_empty(&list)) { __skb_queue_head_init(&amsdu); - ret = ath10k_htt_rx_extract_amsdu(&list, &amsdu, budget_left); + ret = ath10k_htt_rx_extract_amsdu(&list, &amsdu); switch (ret) { case 0: /* Note: The in-order indication may report interleaved @@ -1920,10 +1990,9 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb, * should still give an idea about rx rate to the user. */ num_msdus += skb_queue_len(&amsdu); - budget_left -= skb_queue_len(&amsdu); ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id); ath10k_htt_rx_h_filter(ar, &amsdu, status); - ath10k_htt_rx_h_mpdu(ar, &amsdu, status); + ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false); ath10k_htt_rx_h_deliver(ar, &amsdu, status); break; case -EAGAIN: @@ -2563,8 +2632,7 @@ int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget) } spin_lock_bh(&htt->rx_ring.lock); - num_rx_msdus = ath10k_htt_rx_in_ord_ind(ar, skb, - (budget - quota)); + num_rx_msdus = ath10k_htt_rx_in_ord_ind(ar, skb); spin_unlock_bh(&htt->rx_ring.lock); if (num_rx_msdus < 0) { resched_napi = true; diff --git a/drivers/net/wireless/ath/ath10k/hw.c b/drivers/net/wireless/ath/ath10k/hw.c index a860691d635d..88955bbe20bd 100644 --- a/drivers/net/wireless/ath/ath10k/hw.c +++ b/drivers/net/wireless/ath/ath10k/hw.c @@ -310,7 +310,7 @@ static struct ath10k_hw_ce_dst_src_wm_regs wcn3990_wm_dst_ring = { .wm_high = &wcn3990_dst_wm_high, }; -struct ath10k_hw_ce_regs wcn3990_ce_regs = { +const struct ath10k_hw_ce_regs wcn3990_ce_regs = { .sr_base_addr = 0x00000000, .sr_size_addr = 0x00000008, .dr_base_addr = 0x0000000c, @@ -457,7 +457,7 @@ static struct ath10k_hw_ce_dst_src_wm_regs qcax_wm_dst_ring = { .wm_high = &qcax_dst_wm_high, }; -struct ath10k_hw_ce_regs qcax_ce_regs = { +const struct ath10k_hw_ce_regs qcax_ce_regs = { .sr_base_addr = 0x00000000, .sr_size_addr = 0x00000004, .dr_base_addr = 0x00000008, @@ -604,8 +604,13 @@ static void ath10k_hw_qca988x_set_coverage_class(struct ath10k *ar, /* Only modify registers if the core is started. */ if ((ar->state != ATH10K_STATE_ON) && - (ar->state != ATH10K_STATE_RESTARTED)) + (ar->state != ATH10K_STATE_RESTARTED)) { + spin_lock_bh(&ar->data_lock); + /* Store config value for when radio boots up */ + ar->fw_coverage.coverage_class = value; + spin_unlock_bh(&ar->data_lock); goto unlock; + } /* Retrieve the current values of the two registers that need to be * adjusted. @@ -637,7 +642,7 @@ static void ath10k_hw_qca988x_set_coverage_class(struct ath10k *ar, ar->fw_coverage.reg_ack_cts_timeout_orig = timeout_reg; ar->fw_coverage.reg_phyclk = phyclk_reg; - /* Calculat new value based on the (original) firmware calculation. */ + /* Calculate new value based on the (original) firmware calculation. */ slottime_reg = ar->fw_coverage.reg_slottime_orig; timeout_reg = ar->fw_coverage.reg_ack_cts_timeout_orig; diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 0c089f6dd3d9..05f26e5858ad 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -369,8 +369,8 @@ extern const struct ath10k_hw_values qca99x0_values; extern const struct ath10k_hw_values qca9888_values; extern const struct ath10k_hw_values qca4019_values; extern const struct ath10k_hw_values wcn3990_values; -extern struct ath10k_hw_ce_regs wcn3990_ce_regs; -extern struct ath10k_hw_ce_regs qcax_ce_regs; +extern const struct ath10k_hw_ce_regs wcn3990_ce_regs; +extern const struct ath10k_hw_ce_regs qcax_ce_regs; void ath10k_hw_fill_survey_time(struct ath10k *ar, struct survey_info *survey, u32 cc, u32 rcc, u32 cc_prev, u32 rcc_prev); @@ -550,6 +550,9 @@ struct ath10k_hw_params { */ int vht160_mcs_rx_highest; int vht160_mcs_tx_highest; + + /* Number of ciphers supported (i.e First N) in cipher_suites array */ + int n_cipher_suites; }; struct htt_rx_desc; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 5683f1a5330e..0a947eef348d 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -242,6 +242,16 @@ static int ath10k_send_key(struct ath10k_vif *arvif, case WLAN_CIPHER_SUITE_WEP104: arg.key_cipher = WMI_CIPHER_WEP; break; + case WLAN_CIPHER_SUITE_CCMP_256: + arg.key_cipher = WMI_CIPHER_AES_CCM; + break; + case WLAN_CIPHER_SUITE_GCMP: + case WLAN_CIPHER_SUITE_GCMP_256: + arg.key_cipher = WMI_CIPHER_AES_GCM; + break; + case WLAN_CIPHER_SUITE_BIP_GMAC_128: + case WLAN_CIPHER_SUITE_BIP_GMAC_256: + case WLAN_CIPHER_SUITE_BIP_CMAC_256: case WLAN_CIPHER_SUITE_AES_CMAC: WARN_ON(1); return -EINVAL; @@ -5575,6 +5585,59 @@ static void ath10k_mac_op_set_coverage_class(struct ieee80211_hw *hw, s16 value) ar->hw_params.hw_ops->set_coverage_class(ar, value); } +struct ath10k_mac_tdls_iter_data { + u32 num_tdls_stations; + struct ieee80211_vif *curr_vif; +}; + +static void ath10k_mac_tdls_vif_stations_count_iter(void *data, + struct ieee80211_sta *sta) +{ + struct ath10k_mac_tdls_iter_data *iter_data = data; + struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; + struct ieee80211_vif *sta_vif = arsta->arvif->vif; + + if (sta->tdls && sta_vif == iter_data->curr_vif) + iter_data->num_tdls_stations++; +} + +static int ath10k_mac_tdls_vif_stations_count(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct ath10k_mac_tdls_iter_data data = {}; + + data.curr_vif = vif; + + ieee80211_iterate_stations_atomic(hw, + ath10k_mac_tdls_vif_stations_count_iter, + &data); + return data.num_tdls_stations; +} + +static void ath10k_mac_tdls_vifs_count_iter(void *data, u8 *mac, + struct ieee80211_vif *vif) +{ + struct ath10k_vif *arvif = (void *)vif->drv_priv; + int *num_tdls_vifs = data; + + if (vif->type != NL80211_IFTYPE_STATION) + return; + + if (ath10k_mac_tdls_vif_stations_count(arvif->ar->hw, vif) > 0) + (*num_tdls_vifs)++; +} + +static int ath10k_mac_tdls_vifs_count(struct ieee80211_hw *hw) +{ + int num_tdls_vifs = 0; + + ieee80211_iterate_active_interfaces_atomic(hw, + IEEE80211_IFACE_ITER_NORMAL, + ath10k_mac_tdls_vifs_count_iter, + &num_tdls_vifs); + return num_tdls_vifs; +} + static int ath10k_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_scan_request *hw_req) @@ -5588,6 +5651,11 @@ static int ath10k_hw_scan(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); + if (ath10k_mac_tdls_vif_stations_count(hw, vif) > 0) { + ret = -EBUSY; + goto exit; + } + spin_lock_bh(&ar->data_lock); switch (ar->scan.state) { case ATH10K_SCAN_IDLE: @@ -5723,7 +5791,10 @@ static int ath10k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, u32 flags2; /* this one needs to be done in software */ - if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) + if (key->cipher == WLAN_CIPHER_SUITE_AES_CMAC || + key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_128 || + key->cipher == WLAN_CIPHER_SUITE_BIP_GMAC_256 || + key->cipher == WLAN_CIPHER_SUITE_BIP_CMAC_256) return 1; if (arvif->nohwcrypt) @@ -6000,59 +6071,6 @@ static void ath10k_mac_dec_num_stations(struct ath10k_vif *arvif, ar->num_stations--; } -struct ath10k_mac_tdls_iter_data { - u32 num_tdls_stations; - struct ieee80211_vif *curr_vif; -}; - -static void ath10k_mac_tdls_vif_stations_count_iter(void *data, - struct ieee80211_sta *sta) -{ - struct ath10k_mac_tdls_iter_data *iter_data = data; - struct ath10k_sta *arsta = (struct ath10k_sta *)sta->drv_priv; - struct ieee80211_vif *sta_vif = arsta->arvif->vif; - - if (sta->tdls && sta_vif == iter_data->curr_vif) - iter_data->num_tdls_stations++; -} - -static int ath10k_mac_tdls_vif_stations_count(struct ieee80211_hw *hw, - struct ieee80211_vif *vif) -{ - struct ath10k_mac_tdls_iter_data data = {}; - - data.curr_vif = vif; - - ieee80211_iterate_stations_atomic(hw, - ath10k_mac_tdls_vif_stations_count_iter, - &data); - return data.num_tdls_stations; -} - -static void ath10k_mac_tdls_vifs_count_iter(void *data, u8 *mac, - struct ieee80211_vif *vif) -{ - struct ath10k_vif *arvif = (void *)vif->drv_priv; - int *num_tdls_vifs = data; - - if (vif->type != NL80211_IFTYPE_STATION) - return; - - if (ath10k_mac_tdls_vif_stations_count(arvif->ar->hw, vif) > 0) - (*num_tdls_vifs)++; -} - -static int ath10k_mac_tdls_vifs_count(struct ieee80211_hw *hw) -{ - int num_tdls_vifs = 0; - - ieee80211_iterate_active_interfaces_atomic(hw, - IEEE80211_IFACE_ITER_NORMAL, - ath10k_mac_tdls_vifs_count_iter, - &num_tdls_vifs); - return num_tdls_vifs; -} - static int ath10k_sta_state(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_sta *sta, @@ -6477,6 +6495,11 @@ static int ath10k_remain_on_channel(struct ieee80211_hw *hw, mutex_lock(&ar->conf_mutex); + if (ath10k_mac_tdls_vif_stations_count(hw, vif) > 0) { + ret = -EBUSY; + goto exit; + } + spin_lock_bh(&ar->data_lock); switch (ar->scan.state) { case ATH10K_SCAN_IDLE: @@ -8074,7 +8097,22 @@ int ath10k_mac_register(struct ath10k *ar) WLAN_CIPHER_SUITE_WEP104, WLAN_CIPHER_SUITE_TKIP, WLAN_CIPHER_SUITE_CCMP, + + /* Do not add hardware supported ciphers before this line. + * Allow software encryption for all chips. Don't forget to + * update n_cipher_suites below. + */ WLAN_CIPHER_SUITE_AES_CMAC, + WLAN_CIPHER_SUITE_BIP_CMAC_256, + WLAN_CIPHER_SUITE_BIP_GMAC_128, + WLAN_CIPHER_SUITE_BIP_GMAC_256, + + /* Only QCA99x0 and QCA4019 varients support GCMP-128, GCMP-256 + * and CCMP-256 in hardware. + */ + WLAN_CIPHER_SUITE_GCMP, + WLAN_CIPHER_SUITE_GCMP_256, + WLAN_CIPHER_SUITE_CCMP_256, }; struct ieee80211_supported_band *band; void *channels; @@ -8146,8 +8184,13 @@ int ath10k_mac_register(struct ath10k *ar) BIT(NL80211_IFTYPE_P2P_GO); ieee80211_hw_set(ar->hw, SIGNAL_DBM); - ieee80211_hw_set(ar->hw, SUPPORTS_PS); - ieee80211_hw_set(ar->hw, SUPPORTS_DYNAMIC_PS); + + if (!test_bit(ATH10K_FW_FEATURE_NO_PS, + ar->running_fw->fw_file.fw_features)) { + ieee80211_hw_set(ar->hw, SUPPORTS_PS); + ieee80211_hw_set(ar->hw, SUPPORTS_DYNAMIC_PS); + } + ieee80211_hw_set(ar->hw, MFP_CAPABLE); ieee80211_hw_set(ar->hw, REPORTS_TX_ACK_STATUS); ieee80211_hw_set(ar->hw, HAS_RATE_CONTROL); @@ -8313,7 +8356,18 @@ int ath10k_mac_register(struct ath10k *ar) } ar->hw->wiphy->cipher_suites = cipher_suites; - ar->hw->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites); + + /* QCA988x and QCA6174 family chips do not support CCMP-256, GCMP-128 + * and GCMP-256 ciphers in hardware. Fetch number of ciphers supported + * from chip specific hw_param table. + */ + if (!ar->hw_params.n_cipher_suites || + ar->hw_params.n_cipher_suites > ARRAY_SIZE(cipher_suites)) { + ath10k_err(ar, "invalid hw_params.n_cipher_suites %d\n", + ar->hw_params.n_cipher_suites); + ar->hw_params.n_cipher_suites = 8; + } + ar->hw->wiphy->n_cipher_suites = ar->hw_params.n_cipher_suites; wiphy_ext_feature_set(ar->hw->wiphy, NL80211_EXT_FEATURE_CQM_RSSI_LIST); diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 195dafb98131..ffea348b2190 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -585,10 +585,10 @@ skip: spin_unlock_irqrestore(&ar_pci->ps_lock, flags); } -static void ath10k_pci_ps_timer(unsigned long ptr) +static void ath10k_pci_ps_timer(struct timer_list *t) { - struct ath10k *ar = (void *)ptr; - struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + struct ath10k_pci *ar_pci = from_timer(ar_pci, t, ps_timer); + struct ath10k *ar = ar_pci->ar; unsigned long flags; spin_lock_irqsave(&ar_pci->ps_lock, flags); @@ -838,9 +838,10 @@ void ath10k_pci_rx_post(struct ath10k *ar) ath10k_pci_rx_post_pipe(&ar_pci->pipe_info[i]); } -void ath10k_pci_rx_replenish_retry(unsigned long ptr) +void ath10k_pci_rx_replenish_retry(struct timer_list *t) { - struct ath10k *ar = (void *)ptr; + struct ath10k_pci *ar_pci = from_timer(ar_pci, t, rx_post_retry); + struct ath10k *ar = ar_pci->ar; ath10k_pci_rx_post(ar); } @@ -2577,10 +2578,14 @@ void ath10k_pci_hif_power_down(struct ath10k *ar) */ } -#ifdef CONFIG_PM - static int ath10k_pci_hif_suspend(struct ath10k *ar) { + /* Nothing to do; the important stuff is in the driver suspend. */ + return 0; +} + +static int ath10k_pci_suspend(struct ath10k *ar) +{ /* The grace timer can still be counting down and ar->ps_awake be true. * It is known that the device may be asleep after resuming regardless * of the SoC powersave state before suspending. Hence make sure the @@ -2593,6 +2598,12 @@ static int ath10k_pci_hif_suspend(struct ath10k *ar) static int ath10k_pci_hif_resume(struct ath10k *ar) { + /* Nothing to do; the important stuff is in the driver resume. */ + return 0; +} + +static int ath10k_pci_resume(struct ath10k *ar) +{ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); struct pci_dev *pdev = ar_pci->pdev; u32 val; @@ -2615,7 +2626,6 @@ static int ath10k_pci_hif_resume(struct ath10k *ar) return ret; } -#endif static bool ath10k_pci_validate_cal(void *data, size_t size) { @@ -2770,10 +2780,8 @@ static const struct ath10k_hif_ops ath10k_pci_hif_ops = { .power_down = ath10k_pci_hif_power_down, .read32 = ath10k_pci_read32, .write32 = ath10k_pci_write32, -#ifdef CONFIG_PM .suspend = ath10k_pci_hif_suspend, .resume = ath10k_pci_hif_resume, -#endif .fetch_cal_eeprom = ath10k_pci_hif_fetch_cal_eeprom, }; @@ -3157,8 +3165,7 @@ int ath10k_pci_setup_resource(struct ath10k *ar) spin_lock_init(&ce->ce_lock); spin_lock_init(&ar_pci->ps_lock); - setup_timer(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, - (unsigned long)ar); + timer_setup(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, 0); if (QCA_REV_6174(ar) || QCA_REV_9377(ar)) ath10k_pci_override_ce_config(ar); @@ -3284,8 +3291,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, ar->id.subsystem_vendor = pdev->subsystem_vendor; ar->id.subsystem_device = pdev->subsystem_device; - setup_timer(&ar_pci->ps_timer, ath10k_pci_ps_timer, - (unsigned long)ar); + timer_setup(&ar_pci->ps_timer, ath10k_pci_ps_timer, 0); ret = ath10k_pci_setup_resource(ar); if (ret) { @@ -3401,11 +3407,7 @@ static __maybe_unused int ath10k_pci_pm_suspend(struct device *dev) struct ath10k *ar = dev_get_drvdata(dev); int ret; - if (test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, - ar->running_fw->fw_file.fw_features)) - return 0; - - ret = ath10k_hif_suspend(ar); + ret = ath10k_pci_suspend(ar); if (ret) ath10k_warn(ar, "failed to suspend hif: %d\n", ret); @@ -3417,11 +3419,7 @@ static __maybe_unused int ath10k_pci_pm_resume(struct device *dev) struct ath10k *ar = dev_get_drvdata(dev); int ret; - if (test_bit(ATH10K_FW_FEATURE_WOWLAN_SUPPORT, - ar->running_fw->fw_file.fw_features)) - return 0; - - ret = ath10k_hif_resume(ar); + ret = ath10k_pci_resume(ar); if (ret) ath10k_warn(ar, "failed to resume hif: %d\n", ret); diff --git a/drivers/net/wireless/ath/ath10k/pci.h b/drivers/net/wireless/ath/ath10k/pci.h index 424ff323b2dc..08704fbc11e3 100644 --- a/drivers/net/wireless/ath/ath10k/pci.h +++ b/drivers/net/wireless/ath/ath10k/pci.h @@ -278,7 +278,7 @@ void ath10k_pci_hif_power_down(struct ath10k *ar); int ath10k_pci_alloc_pipes(struct ath10k *ar); void ath10k_pci_free_pipes(struct ath10k *ar); void ath10k_pci_free_pipes(struct ath10k *ar); -void ath10k_pci_rx_replenish_retry(unsigned long ptr); +void ath10k_pci_rx_replenish_retry(struct timer_list *t); void ath10k_pci_ce_deinit(struct ath10k *ar); void ath10k_pci_init_napi(struct ath10k *ar); int ath10k_pci_init_pipes(struct ath10k *ar); diff --git a/drivers/net/wireless/ath/ath10k/rx_desc.h b/drivers/net/wireless/ath/ath10k/rx_desc.h index c1022a1cf855..28da14398951 100644 --- a/drivers/net/wireless/ath/ath10k/rx_desc.h +++ b/drivers/net/wireless/ath/ath10k/rx_desc.h @@ -239,6 +239,9 @@ enum htt_rx_mpdu_encrypt_type { HTT_RX_MPDU_ENCRYPT_WAPI = 5, HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2 = 6, HTT_RX_MPDU_ENCRYPT_NONE = 7, + HTT_RX_MPDU_ENCRYPT_AES_CCM256_WPA2 = 8, + HTT_RX_MPDU_ENCRYPT_AES_GCMP_WPA2 = 9, + HTT_RX_MPDU_ENCRYPT_AES_GCMP256_WPA2 = 10, }; #define RX_MPDU_START_INFO0_PEER_IDX_MASK 0x000007ff diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c index dd9cc0939ea8..2048b1e5262b 100644 --- a/drivers/net/wireless/ath/ath10k/spectral.c +++ b/drivers/net/wireless/ath/ath10k/spectral.c @@ -406,7 +406,7 @@ static ssize_t write_file_spectral_count(struct file *file, if (kstrtoul(buf, 0, &val)) return -EINVAL; - if (val < 0 || val > 255) + if (val > 255) return -EINVAL; mutex_lock(&ar->conf_mutex); diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 38a97086708b..cad2e42dcef6 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -7870,7 +7870,8 @@ ath10k_wmi_10_4_gen_update_fw_tdls_state(struct ath10k *ar, u32 vdev_id, if (!skb) return ERR_PTR(-ENOMEM); - if (test_bit(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, ar->wmi.svc_map)) + if (test_bit(WMI_SERVICE_TDLS_EXPLICIT_MODE_ONLY, ar->wmi.svc_map) && + state == WMI_TDLS_ENABLE_ACTIVE) state = WMI_TDLS_ENABLE_PASSIVE; if (test_bit(WMI_SERVICE_TDLS_UAPSD_BUFFER_STA, ar->wmi.svc_map)) diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 7a3606dde227..c02b21cff38d 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h @@ -4751,6 +4751,7 @@ struct wmi_key_seq_counter { #define WMI_CIPHER_WAPI 0x5 #define WMI_CIPHER_CKIP 0x6 #define WMI_CIPHER_AES_CMAC 0x7 +#define WMI_CIPHER_AES_GCM 0x8 struct wmi_vdev_install_key_cmd { __le32 vdev_id; |