diff options
25 files changed, 422 insertions, 225 deletions
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 39fe4f3350aa..2bdf5408b0d9 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c | |||
| @@ -1139,7 +1139,7 @@ static ssize_t ath10k_read_htt_max_amsdu_ampdu(struct file *file, | |||
| 1139 | { | 1139 | { |
| 1140 | struct ath10k *ar = file->private_data; | 1140 | struct ath10k *ar = file->private_data; |
| 1141 | char buf[64]; | 1141 | char buf[64]; |
| 1142 | u8 amsdu = 3, ampdu = 64; | 1142 | u8 amsdu, ampdu; |
| 1143 | unsigned int len; | 1143 | unsigned int len; |
| 1144 | 1144 | ||
| 1145 | mutex_lock(&ar->conf_mutex); | 1145 | mutex_lock(&ar->conf_mutex); |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index bcb364d5d49f..b4bdeb07a012 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
| @@ -250,7 +250,8 @@ static int ath10k_install_peer_wep_keys(struct ath10k_vif *arvif, | |||
| 250 | lockdep_assert_held(&ar->conf_mutex); | 250 | lockdep_assert_held(&ar->conf_mutex); |
| 251 | 251 | ||
| 252 | if (WARN_ON(arvif->vif->type != NL80211_IFTYPE_AP && | 252 | if (WARN_ON(arvif->vif->type != NL80211_IFTYPE_AP && |
| 253 | arvif->vif->type != NL80211_IFTYPE_ADHOC)) | 253 | arvif->vif->type != NL80211_IFTYPE_ADHOC && |
| 254 | arvif->vif->type != NL80211_IFTYPE_MESH_POINT)) | ||
| 254 | return -EINVAL; | 255 | return -EINVAL; |
| 255 | 256 | ||
| 256 | spin_lock_bh(&ar->data_lock); | 257 | spin_lock_bh(&ar->data_lock); |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 2a44d63a03cd..a7c3d299639b 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
| @@ -4312,34 +4312,58 @@ void ath10k_wmi_event_vdev_resume_req(struct ath10k *ar, struct sk_buff *skb) | |||
| 4312 | ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_RESUME_REQ_EVENTID\n"); | 4312 | ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_VDEV_RESUME_REQ_EVENTID\n"); |
| 4313 | } | 4313 | } |
| 4314 | 4314 | ||
| 4315 | static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id, | 4315 | static int ath10k_wmi_alloc_chunk(struct ath10k *ar, u32 req_id, |
| 4316 | u32 num_units, u32 unit_len) | 4316 | u32 num_units, u32 unit_len) |
| 4317 | { | 4317 | { |
| 4318 | dma_addr_t paddr; | 4318 | dma_addr_t paddr; |
| 4319 | u32 pool_size; | 4319 | u32 pool_size = 0; |
| 4320 | int idx = ar->wmi.num_mem_chunks; | 4320 | int idx = ar->wmi.num_mem_chunks; |
| 4321 | void *vaddr = NULL; | ||
| 4321 | 4322 | ||
| 4322 | pool_size = num_units * round_up(unit_len, 4); | 4323 | if (ar->wmi.num_mem_chunks == ARRAY_SIZE(ar->wmi.mem_chunks)) |
| 4324 | return -ENOMEM; | ||
| 4323 | 4325 | ||
| 4324 | if (!pool_size) | 4326 | while (!vaddr && num_units) { |
| 4325 | return -EINVAL; | 4327 | pool_size = num_units * round_up(unit_len, 4); |
| 4328 | if (!pool_size) | ||
| 4329 | return -EINVAL; | ||
| 4326 | 4330 | ||
| 4327 | ar->wmi.mem_chunks[idx].vaddr = dma_alloc_coherent(ar->dev, | 4331 | vaddr = kzalloc(pool_size, GFP_KERNEL | __GFP_NOWARN); |
| 4328 | pool_size, | 4332 | if (!vaddr) |
| 4329 | &paddr, | 4333 | num_units /= 2; |
| 4330 | GFP_KERNEL); | ||
| 4331 | if (!ar->wmi.mem_chunks[idx].vaddr) { | ||
| 4332 | ath10k_warn(ar, "failed to allocate memory chunk\n"); | ||
| 4333 | return -ENOMEM; | ||
| 4334 | } | 4334 | } |
| 4335 | 4335 | ||
| 4336 | memset(ar->wmi.mem_chunks[idx].vaddr, 0, pool_size); | 4336 | if (!num_units) |
| 4337 | return -ENOMEM; | ||
| 4338 | |||
| 4339 | paddr = dma_map_single(ar->dev, vaddr, pool_size, DMA_TO_DEVICE); | ||
| 4340 | if (dma_mapping_error(ar->dev, paddr)) { | ||
| 4341 | kfree(vaddr); | ||
| 4342 | return -ENOMEM; | ||
| 4343 | } | ||
| 4337 | 4344 | ||
| 4345 | ar->wmi.mem_chunks[idx].vaddr = vaddr; | ||
| 4338 | ar->wmi.mem_chunks[idx].paddr = paddr; | 4346 | ar->wmi.mem_chunks[idx].paddr = paddr; |
| 4339 | ar->wmi.mem_chunks[idx].len = pool_size; | 4347 | ar->wmi.mem_chunks[idx].len = pool_size; |
| 4340 | ar->wmi.mem_chunks[idx].req_id = req_id; | 4348 | ar->wmi.mem_chunks[idx].req_id = req_id; |
| 4341 | ar->wmi.num_mem_chunks++; | 4349 | ar->wmi.num_mem_chunks++; |
| 4342 | 4350 | ||
| 4351 | return num_units; | ||
| 4352 | } | ||
| 4353 | |||
| 4354 | static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id, | ||
| 4355 | u32 num_units, u32 unit_len) | ||
| 4356 | { | ||
| 4357 | int ret; | ||
| 4358 | |||
| 4359 | while (num_units) { | ||
| 4360 | ret = ath10k_wmi_alloc_chunk(ar, req_id, num_units, unit_len); | ||
| 4361 | if (ret < 0) | ||
| 4362 | return ret; | ||
| 4363 | |||
| 4364 | num_units -= ret; | ||
| 4365 | } | ||
| 4366 | |||
| 4343 | return 0; | 4367 | return 0; |
| 4344 | } | 4368 | } |
| 4345 | 4369 | ||
| @@ -7717,10 +7741,11 @@ void ath10k_wmi_free_host_mem(struct ath10k *ar) | |||
| 7717 | 7741 | ||
| 7718 | /* free the host memory chunks requested by firmware */ | 7742 | /* free the host memory chunks requested by firmware */ |
| 7719 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | 7743 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { |
| 7720 | dma_free_coherent(ar->dev, | 7744 | dma_unmap_single(ar->dev, |
| 7721 | ar->wmi.mem_chunks[i].len, | 7745 | ar->wmi.mem_chunks[i].paddr, |
| 7722 | ar->wmi.mem_chunks[i].vaddr, | 7746 | ar->wmi.mem_chunks[i].len, |
| 7723 | ar->wmi.mem_chunks[i].paddr); | 7747 | DMA_TO_DEVICE); |
| 7748 | kfree(ar->wmi.mem_chunks[i].vaddr); | ||
| 7724 | } | 7749 | } |
| 7725 | 7750 | ||
| 7726 | ar->wmi.num_mem_chunks = 0; | 7751 | ar->wmi.num_mem_chunks = 0; |
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c index 342563a3706f..3d946d8b2db2 100644 --- a/drivers/net/wireless/ath/ath5k/base.c +++ b/drivers/net/wireless/ath/ath5k/base.c | |||
| @@ -767,7 +767,7 @@ ath5k_txbuf_setup(struct ath5k_hw *ah, struct ath5k_buf *bf, | |||
| 767 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) | 767 | if (info->flags & IEEE80211_TX_CTL_NO_ACK) |
| 768 | flags |= AR5K_TXDESC_NOACK; | 768 | flags |= AR5K_TXDESC_NOACK; |
| 769 | 769 | ||
| 770 | rc_flags = info->control.rates[0].flags; | 770 | rc_flags = bf->rates[0].flags; |
| 771 | 771 | ||
| 772 | hw_rate = ath5k_get_rate_hw_value(ah->hw, info, bf, 0); | 772 | hw_rate = ath5k_get_rate_hw_value(ah->hw, info, bf, 0); |
| 773 | 773 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index 81ac8c59f0ec..7f3f94fbf157 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
| @@ -3930,8 +3930,8 @@ int ath6kl_cfg80211_init(struct ath6kl *ar) | |||
| 3930 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; | 3930 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; |
| 3931 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff; | 3931 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[1] = 0xff; |
| 3932 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff; | 3932 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[1] = 0xff; |
| 3933 | ar->hw.tx_ant = 2; | 3933 | ar->hw.tx_ant = 0x3; /* mask, 2 antenna */ |
| 3934 | ar->hw.rx_ant = 2; | 3934 | ar->hw.rx_ant = 0x3; |
| 3935 | } else { | 3935 | } else { |
| 3936 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; | 3936 | ath6kl_band_2ghz.ht_cap.mcs.rx_mask[0] = 0xff; |
| 3937 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; | 3937 | ath6kl_band_5ghz.ht_cap.mcs.rx_mask[0] = 0xff; |
diff --git a/drivers/net/wireless/ath/ath6kl/htc_mbox.c b/drivers/net/wireless/ath/ath6kl/htc_mbox.c index fffb65b3e652..65c31da43c47 100644 --- a/drivers/net/wireless/ath/ath6kl/htc_mbox.c +++ b/drivers/net/wireless/ath/ath6kl/htc_mbox.c | |||
| @@ -2222,8 +2222,9 @@ int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target, | |||
| 2222 | } | 2222 | } |
| 2223 | 2223 | ||
| 2224 | if (status) { | 2224 | if (status) { |
| 2225 | ath6kl_err("failed to get pending recv messages: %d\n", | 2225 | if (status != -ECANCELED) |
| 2226 | status); | 2226 | ath6kl_err("failed to get pending recv messages: %d\n", |
| 2227 | status); | ||
| 2227 | 2228 | ||
| 2228 | /* cleanup any packets in sync completion queue */ | 2229 | /* cleanup any packets in sync completion queue */ |
| 2229 | list_for_each_entry_safe(packets, tmp_pkt, &comp_pktq, list) { | 2230 | list_for_each_entry_safe(packets, tmp_pkt, &comp_pktq, list) { |
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c index 6ae0734f86e0..da557dc742e6 100644 --- a/drivers/net/wireless/ath/ath6kl/init.c +++ b/drivers/net/wireless/ath/ath6kl/init.c | |||
| @@ -954,8 +954,10 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) | |||
| 954 | snprintf(filename, sizeof(filename), "%s/%s", ar->hw.fw.dir, name); | 954 | snprintf(filename, sizeof(filename), "%s/%s", ar->hw.fw.dir, name); |
| 955 | 955 | ||
| 956 | ret = request_firmware(&fw, filename, ar->dev); | 956 | ret = request_firmware(&fw, filename, ar->dev); |
| 957 | if (ret) | 957 | if (ret) { |
| 958 | ath6kl_err("Failed request firmware, rv: %d\n", ret); | ||
| 958 | return ret; | 959 | return ret; |
| 960 | } | ||
| 959 | 961 | ||
| 960 | data = fw->data; | 962 | data = fw->data; |
| 961 | len = fw->size; | 963 | len = fw->size; |
| @@ -964,11 +966,15 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) | |||
| 964 | magic_len = strlen(ATH6KL_FIRMWARE_MAGIC) + 1; | 966 | magic_len = strlen(ATH6KL_FIRMWARE_MAGIC) + 1; |
| 965 | 967 | ||
| 966 | if (len < magic_len) { | 968 | if (len < magic_len) { |
| 969 | ath6kl_err("Magic length is invalid, len: %zd magic_len: %zd\n", | ||
| 970 | len, magic_len); | ||
| 967 | ret = -EINVAL; | 971 | ret = -EINVAL; |
| 968 | goto out; | 972 | goto out; |
| 969 | } | 973 | } |
| 970 | 974 | ||
| 971 | if (memcmp(data, ATH6KL_FIRMWARE_MAGIC, magic_len) != 0) { | 975 | if (memcmp(data, ATH6KL_FIRMWARE_MAGIC, magic_len) != 0) { |
| 976 | ath6kl_err("Magic is invalid, magic_len: %zd\n", | ||
| 977 | magic_len); | ||
| 972 | ret = -EINVAL; | 978 | ret = -EINVAL; |
| 973 | goto out; | 979 | goto out; |
| 974 | } | 980 | } |
| @@ -987,7 +993,12 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) | |||
| 987 | len -= sizeof(*hdr); | 993 | len -= sizeof(*hdr); |
| 988 | data += sizeof(*hdr); | 994 | data += sizeof(*hdr); |
| 989 | 995 | ||
| 996 | ath6kl_dbg(ATH6KL_DBG_BOOT, "ie-id: %d len: %zd (0x%zx)\n", | ||
| 997 | ie_id, ie_len, ie_len); | ||
| 998 | |||
| 990 | if (len < ie_len) { | 999 | if (len < ie_len) { |
| 1000 | ath6kl_err("IE len is invalid, len: %zd ie_len: %zd ie-id: %d\n", | ||
| 1001 | len, ie_len, ie_id); | ||
| 991 | ret = -EINVAL; | 1002 | ret = -EINVAL; |
| 992 | goto out; | 1003 | goto out; |
| 993 | } | 1004 | } |
| @@ -1008,6 +1019,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) | |||
| 1008 | ar->fw_otp = kmemdup(data, ie_len, GFP_KERNEL); | 1019 | ar->fw_otp = kmemdup(data, ie_len, GFP_KERNEL); |
| 1009 | 1020 | ||
| 1010 | if (ar->fw_otp == NULL) { | 1021 | if (ar->fw_otp == NULL) { |
| 1022 | ath6kl_err("fw_otp cannot be allocated\n"); | ||
| 1011 | ret = -ENOMEM; | 1023 | ret = -ENOMEM; |
| 1012 | goto out; | 1024 | goto out; |
| 1013 | } | 1025 | } |
| @@ -1025,6 +1037,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) | |||
| 1025 | ar->fw = vmalloc(ie_len); | 1037 | ar->fw = vmalloc(ie_len); |
| 1026 | 1038 | ||
| 1027 | if (ar->fw == NULL) { | 1039 | if (ar->fw == NULL) { |
| 1040 | ath6kl_err("fw storage cannot be allocated, len: %zd\n", ie_len); | ||
| 1028 | ret = -ENOMEM; | 1041 | ret = -ENOMEM; |
| 1029 | goto out; | 1042 | goto out; |
| 1030 | } | 1043 | } |
| @@ -1039,6 +1052,7 @@ static int ath6kl_fetch_fw_apin(struct ath6kl *ar, const char *name) | |||
| 1039 | ar->fw_patch = kmemdup(data, ie_len, GFP_KERNEL); | 1052 | ar->fw_patch = kmemdup(data, ie_len, GFP_KERNEL); |
| 1040 | 1053 | ||
| 1041 | if (ar->fw_patch == NULL) { | 1054 | if (ar->fw_patch == NULL) { |
| 1055 | ath6kl_err("fw_patch storage cannot be allocated, len: %zd\n", ie_len); | ||
| 1042 | ret = -ENOMEM; | 1056 | ret = -ENOMEM; |
| 1043 | goto out; | 1057 | goto out; |
| 1044 | } | 1058 | } |
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index fee0cadb0f5e..40fa915d6f35 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
| @@ -176,3 +176,14 @@ config ATH9K_HTC_DEBUGFS | |||
| 176 | depends on ATH9K_HTC && DEBUG_FS | 176 | depends on ATH9K_HTC && DEBUG_FS |
| 177 | ---help--- | 177 | ---help--- |
| 178 | Say Y, if you need access to ath9k_htc's statistics. | 178 | Say Y, if you need access to ath9k_htc's statistics. |
| 179 | |||
| 180 | config ATH9K_HWRNG | ||
| 181 | bool "Random number generator support" | ||
| 182 | depends on ATH9K && (HW_RANDOM = y || HW_RANDOM = ATH9K) | ||
| 183 | default y | ||
| 184 | ---help--- | ||
| 185 | This option incorporates the ADC register output as a source of | ||
| 186 | randomness into Linux entropy pool (/dev/urandom and /dev/random) | ||
| 187 | |||
| 188 | Say Y, feeds the entropy directly from the WiFi driver to the input | ||
| 189 | pool. | ||
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index ecda613c2d54..76f9dc37500b 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
| @@ -15,6 +15,7 @@ ath9k-$(CONFIG_ATH9K_DFS_DEBUGFS) += dfs_debug.o | |||
| 15 | ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o | 15 | ath9k-$(CONFIG_ATH9K_DFS_CERTIFIED) += dfs.o |
| 16 | ath9k-$(CONFIG_ATH9K_TX99) += tx99.o | 16 | ath9k-$(CONFIG_ATH9K_TX99) += tx99.o |
| 17 | ath9k-$(CONFIG_ATH9K_WOW) += wow.o | 17 | ath9k-$(CONFIG_ATH9K_WOW) += wow.o |
| 18 | ath9k-$(CONFIG_ATH9K_HWRNG) += rng.o | ||
| 18 | 19 | ||
| 19 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o | 20 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o |
| 20 | 21 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index b42f4a963ef4..5294595da5a7 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/leds.h> | 23 | #include <linux/leds.h> |
| 24 | #include <linux/completion.h> | 24 | #include <linux/completion.h> |
| 25 | #include <linux/time.h> | 25 | #include <linux/time.h> |
| 26 | #include <linux/hw_random.h> | ||
| 26 | 27 | ||
| 27 | #include "common.h" | 28 | #include "common.h" |
| 28 | #include "debug.h" | 29 | #include "debug.h" |
| @@ -981,6 +982,7 @@ struct ath_softc { | |||
| 981 | struct ath_offchannel offchannel; | 982 | struct ath_offchannel offchannel; |
| 982 | struct ath_chanctx *next_chan; | 983 | struct ath_chanctx *next_chan; |
| 983 | struct completion go_beacon; | 984 | struct completion go_beacon; |
| 985 | struct timespec last_event_time; | ||
| 984 | #endif | 986 | #endif |
| 985 | 987 | ||
| 986 | unsigned long driver_data; | 988 | unsigned long driver_data; |
| @@ -1040,6 +1042,11 @@ struct ath_softc { | |||
| 1040 | u32 wow_intr_before_sleep; | 1042 | u32 wow_intr_before_sleep; |
| 1041 | bool force_wow; | 1043 | bool force_wow; |
| 1042 | #endif | 1044 | #endif |
| 1045 | |||
| 1046 | #ifdef CONFIG_ATH9K_HWRNG | ||
| 1047 | u32 rng_last; | ||
| 1048 | struct task_struct *rng_task; | ||
| 1049 | #endif | ||
| 1043 | }; | 1050 | }; |
| 1044 | 1051 | ||
| 1045 | /********/ | 1052 | /********/ |
| @@ -1062,6 +1069,22 @@ static inline int ath9k_tx99_send(struct ath_softc *sc, | |||
| 1062 | } | 1069 | } |
| 1063 | #endif /* CONFIG_ATH9K_TX99 */ | 1070 | #endif /* CONFIG_ATH9K_TX99 */ |
| 1064 | 1071 | ||
| 1072 | /***************************/ | ||
| 1073 | /* Random Number Generator */ | ||
| 1074 | /***************************/ | ||
| 1075 | #ifdef CONFIG_ATH9K_HWRNG | ||
| 1076 | void ath9k_rng_start(struct ath_softc *sc); | ||
| 1077 | void ath9k_rng_stop(struct ath_softc *sc); | ||
| 1078 | #else | ||
| 1079 | static inline void ath9k_rng_start(struct ath_softc *sc) | ||
| 1080 | { | ||
| 1081 | } | ||
| 1082 | |||
| 1083 | static inline void ath9k_rng_stop(struct ath_softc *sc) | ||
| 1084 | { | ||
| 1085 | } | ||
| 1086 | #endif | ||
| 1087 | |||
| 1065 | static inline void ath_read_cachesize(struct ath_common *common, int *csz) | 1088 | static inline void ath_read_cachesize(struct ath_common *common, int *csz) |
| 1066 | { | 1089 | { |
| 1067 | common->bus_ops->read_cachesize(common, csz); | 1090 | common->bus_ops->read_cachesize(common, csz); |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index f50a6bc5d06e..5cf0cd7cb2d1 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
| @@ -148,7 +148,8 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw, | |||
| 148 | 148 | ||
| 149 | ath_assign_seq(common, skb); | 149 | ath_assign_seq(common, skb); |
| 150 | 150 | ||
| 151 | if (vif->p2p) | 151 | /* Always assign NOA attr when MCC enabled */ |
| 152 | if (ath9k_is_chanctx_enabled()) | ||
| 152 | ath9k_beacon_add_noa(sc, avp, skb); | 153 | ath9k_beacon_add_noa(sc, avp, skb); |
| 153 | 154 | ||
| 154 | bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, | 155 | bf->bf_buf_addr = dma_map_single(sc->dev, skb->data, |
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 90f5773a1a61..50e614b915f1 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c | |||
| @@ -226,6 +226,20 @@ static const char *chanctx_state_string(enum ath_chanctx_state state) | |||
| 226 | } | 226 | } |
| 227 | } | 227 | } |
| 228 | 228 | ||
| 229 | static const u32 chanctx_event_delta(struct ath_softc *sc) | ||
| 230 | { | ||
| 231 | u64 ms; | ||
| 232 | struct timespec ts, *old; | ||
| 233 | |||
| 234 | getrawmonotonic(&ts); | ||
| 235 | old = &sc->last_event_time; | ||
| 236 | ms = ts.tv_sec * 1000 + ts.tv_nsec / 1000000; | ||
| 237 | ms -= old->tv_sec * 1000 + old->tv_nsec / 1000000; | ||
| 238 | sc->last_event_time = ts; | ||
| 239 | |||
| 240 | return (u32)ms; | ||
| 241 | } | ||
| 242 | |||
| 229 | void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx) | 243 | void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx) |
| 230 | { | 244 | { |
| 231 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 245 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| @@ -356,14 +370,16 @@ static void ath_chanctx_setup_timer(struct ath_softc *sc, u32 tsf_time) | |||
| 356 | { | 370 | { |
| 357 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 371 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
| 358 | struct ath_hw *ah = sc->sc_ah; | 372 | struct ath_hw *ah = sc->sc_ah; |
| 373 | unsigned long timeout; | ||
| 359 | 374 | ||
| 360 | ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, tsf_time, 1000000); | 375 | ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, tsf_time, 1000000); |
| 361 | tsf_time -= ath9k_hw_gettsf32(ah); | 376 | tsf_time -= ath9k_hw_gettsf32(ah); |
| 362 | tsf_time = msecs_to_jiffies(tsf_time / 1000) + 1; | 377 | timeout = msecs_to_jiffies(tsf_time / 1000) + 1; |
| 363 | mod_timer(&sc->sched.timer, jiffies + tsf_time); | 378 | mod_timer(&sc->sched.timer, jiffies + timeout); |
| 364 | 379 | ||
| 365 | ath_dbg(common, CHAN_CTX, | 380 | ath_dbg(common, CHAN_CTX, |
| 366 | "Setup chanctx timer with timeout: %d ms\n", jiffies_to_msecs(tsf_time)); | 381 | "Setup chanctx timer with timeout: %d (%d) ms\n", |
| 382 | tsf_time / 1000, jiffies_to_msecs(timeout)); | ||
| 367 | } | 383 | } |
| 368 | 384 | ||
| 369 | static void ath_chanctx_handle_bmiss(struct ath_softc *sc, | 385 | static void ath_chanctx_handle_bmiss(struct ath_softc *sc, |
| @@ -403,7 +419,7 @@ static void ath_chanctx_offchannel_noa(struct ath_softc *sc, | |||
| 403 | avp->offchannel_duration = sc->sched.offchannel_duration; | 419 | avp->offchannel_duration = sc->sched.offchannel_duration; |
| 404 | 420 | ||
| 405 | ath_dbg(common, CHAN_CTX, | 421 | ath_dbg(common, CHAN_CTX, |
| 406 | "offchannel noa_duration: %d, noa_start: %d, noa_index: %d\n", | 422 | "offchannel noa_duration: %d, noa_start: %u, noa_index: %d\n", |
| 407 | avp->offchannel_duration, | 423 | avp->offchannel_duration, |
| 408 | avp->offchannel_start, | 424 | avp->offchannel_start, |
| 409 | avp->noa_index); | 425 | avp->noa_index); |
| @@ -443,7 +459,7 @@ static void ath_chanctx_set_periodic_noa(struct ath_softc *sc, | |||
| 443 | avp->periodic_noa = true; | 459 | avp->periodic_noa = true; |
| 444 | 460 | ||
| 445 | ath_dbg(common, CHAN_CTX, | 461 | ath_dbg(common, CHAN_CTX, |
| 446 | "noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n", | 462 | "noa_duration: %d, noa_start: %u, noa_index: %d, periodic: %d\n", |
| 447 | avp->noa_duration, | 463 | avp->noa_duration, |
| 448 | avp->noa_start, | 464 | avp->noa_start, |
| 449 | avp->noa_index, | 465 | avp->noa_index, |
| @@ -464,7 +480,7 @@ static void ath_chanctx_set_oneshot_noa(struct ath_softc *sc, | |||
| 464 | avp->noa_duration = duration + sc->sched.channel_switch_time; | 480 | avp->noa_duration = duration + sc->sched.channel_switch_time; |
| 465 | 481 | ||
| 466 | ath_dbg(common, CHAN_CTX, | 482 | ath_dbg(common, CHAN_CTX, |
| 467 | "oneshot noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n", | 483 | "oneshot noa_duration: %d, noa_start: %u, noa_index: %d, periodic: %d\n", |
| 468 | avp->noa_duration, | 484 | avp->noa_duration, |
| 469 | avp->noa_start, | 485 | avp->noa_start, |
| 470 | avp->noa_index, | 486 | avp->noa_index, |
| @@ -487,10 +503,11 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
| 487 | 503 | ||
| 488 | spin_lock_bh(&sc->chan_lock); | 504 | spin_lock_bh(&sc->chan_lock); |
| 489 | 505 | ||
| 490 | ath_dbg(common, CHAN_CTX, "cur_chan: %d MHz, event: %s, state: %s\n", | 506 | ath_dbg(common, CHAN_CTX, "cur_chan: %d MHz, event: %s, state: %s, delta: %u ms\n", |
| 491 | sc->cur_chan->chandef.center_freq1, | 507 | sc->cur_chan->chandef.center_freq1, |
| 492 | chanctx_event_string(ev), | 508 | chanctx_event_string(ev), |
| 493 | chanctx_state_string(sc->sched.state)); | 509 | chanctx_state_string(sc->sched.state), |
| 510 | chanctx_event_delta(sc)); | ||
| 494 | 511 | ||
| 495 | switch (ev) { | 512 | switch (ev) { |
| 496 | case ATH_CHANCTX_EVENT_BEACON_PREPARE: | 513 | case ATH_CHANCTX_EVENT_BEACON_PREPARE: |
| @@ -1099,6 +1116,7 @@ ath_chanctx_send_vif_ps_frame(struct ath_softc *sc, struct ath_vif *avp, | |||
| 1099 | nullfunc->frame_control |= | 1116 | nullfunc->frame_control |= |
| 1100 | cpu_to_le16(IEEE80211_FCTL_PM); | 1117 | cpu_to_le16(IEEE80211_FCTL_PM); |
| 1101 | 1118 | ||
| 1119 | skb->priority = 7; | ||
| 1102 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); | 1120 | skb_set_queue_mapping(skb, IEEE80211_AC_VO); |
| 1103 | if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) { | 1121 | if (!ieee80211_tx_prepare_skb(sc->hw, vif, skb, band, &sta)) { |
| 1104 | dev_kfree_skb_any(skb); | 1122 | dev_kfree_skb_any(skb); |
| @@ -1401,8 +1419,9 @@ void ath9k_chanctx_wake_queues(struct ath_softc *sc, struct ath_chanctx *ctx) | |||
| 1401 | 1419 | ||
| 1402 | static void ath9k_update_p2p_ps_timer(struct ath_softc *sc, struct ath_vif *avp) | 1420 | static void ath9k_update_p2p_ps_timer(struct ath_softc *sc, struct ath_vif *avp) |
| 1403 | { | 1421 | { |
| 1422 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
| 1404 | struct ath_hw *ah = sc->sc_ah; | 1423 | struct ath_hw *ah = sc->sc_ah; |
| 1405 | s32 tsf, target_tsf; | 1424 | u32 tsf, target_tsf; |
| 1406 | 1425 | ||
| 1407 | if (!avp || !avp->noa.has_next_tsf) | 1426 | if (!avp || !avp->noa.has_next_tsf) |
| 1408 | return; | 1427 | return; |
| @@ -1414,11 +1433,17 @@ static void ath9k_update_p2p_ps_timer(struct ath_softc *sc, struct ath_vif *avp) | |||
| 1414 | target_tsf = avp->noa.next_tsf; | 1433 | target_tsf = avp->noa.next_tsf; |
| 1415 | if (!avp->noa.absent) | 1434 | if (!avp->noa.absent) |
| 1416 | target_tsf -= ATH_P2P_PS_STOP_TIME; | 1435 | target_tsf -= ATH_P2P_PS_STOP_TIME; |
| 1436 | else | ||
| 1437 | target_tsf += ATH_P2P_PS_STOP_TIME; | ||
| 1417 | 1438 | ||
| 1418 | if (target_tsf - tsf < ATH_P2P_PS_STOP_TIME) | 1439 | if (target_tsf - tsf < ATH_P2P_PS_STOP_TIME) |
| 1419 | target_tsf = tsf + ATH_P2P_PS_STOP_TIME; | 1440 | target_tsf = tsf + ATH_P2P_PS_STOP_TIME; |
| 1420 | 1441 | ||
| 1421 | ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, (u32) target_tsf, 1000000); | 1442 | ath_dbg(common, CHAN_CTX, "%s absent %d tsf 0x%08X next_tsf 0x%08X (%dms)\n", |
| 1443 | __func__, avp->noa.absent, tsf, target_tsf, | ||
| 1444 | (target_tsf - tsf) / 1000); | ||
| 1445 | |||
| 1446 | ath9k_hw_gen_timer_start(ah, sc->p2p_ps_timer, target_tsf, 1000000); | ||
| 1422 | } | 1447 | } |
| 1423 | 1448 | ||
| 1424 | static void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif) | 1449 | static void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif) |
| @@ -1433,6 +1458,10 @@ static void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif) | |||
| 1433 | return; | 1458 | return; |
| 1434 | 1459 | ||
| 1435 | sc->p2p_ps_vif = avp; | 1460 | sc->p2p_ps_vif = avp; |
| 1461 | |||
| 1462 | if (sc->ps_flags & PS_BEACON_SYNC) | ||
| 1463 | return; | ||
| 1464 | |||
| 1436 | tsf = ath9k_hw_gettsf32(sc->sc_ah); | 1465 | tsf = ath9k_hw_gettsf32(sc->sc_ah); |
| 1437 | ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf); | 1466 | ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf); |
| 1438 | ath9k_update_p2p_ps_timer(sc, avp); | 1467 | ath9k_update_p2p_ps_timer(sc, avp); |
| @@ -1495,6 +1524,8 @@ void ath9k_beacon_add_noa(struct ath_softc *sc, struct ath_vif *avp, | |||
| 1495 | 1524 | ||
| 1496 | noa->index = avp->noa_index; | 1525 | noa->index = avp->noa_index; |
| 1497 | noa->oppps_ctwindow = ath9k_get_ctwin(sc, avp); | 1526 | noa->oppps_ctwindow = ath9k_get_ctwin(sc, avp); |
| 1527 | if (noa->oppps_ctwindow) | ||
| 1528 | noa->oppps_ctwindow |= BIT(7); | ||
| 1498 | 1529 | ||
| 1499 | if (avp->noa_duration) { | 1530 | if (avp->noa_duration) { |
| 1500 | if (avp->periodic_noa) { | 1531 | if (avp->periodic_noa) { |
| @@ -1536,6 +1567,8 @@ void ath9k_p2p_ps_timer(void *priv) | |||
| 1536 | tsf = ath9k_hw_gettsf32(sc->sc_ah); | 1567 | tsf = ath9k_hw_gettsf32(sc->sc_ah); |
| 1537 | if (!avp->noa.absent) | 1568 | if (!avp->noa.absent) |
| 1538 | tsf += ATH_P2P_PS_STOP_TIME; | 1569 | tsf += ATH_P2P_PS_STOP_TIME; |
| 1570 | else | ||
| 1571 | tsf -= ATH_P2P_PS_STOP_TIME; | ||
| 1539 | 1572 | ||
| 1540 | if (!avp->noa.has_next_tsf || | 1573 | if (!avp->noa.has_next_tsf || |
| 1541 | avp->noa.next_tsf - tsf > BIT(31)) | 1574 | avp->noa.next_tsf - tsf > BIT(31)) |
| @@ -1571,8 +1604,7 @@ void ath9k_p2p_bss_info_changed(struct ath_softc *sc, | |||
| 1571 | 1604 | ||
| 1572 | spin_lock_bh(&sc->sc_pcu_lock); | 1605 | spin_lock_bh(&sc->sc_pcu_lock); |
| 1573 | spin_lock_irqsave(&sc->sc_pm_lock, flags); | 1606 | spin_lock_irqsave(&sc->sc_pm_lock, flags); |
| 1574 | if (!(sc->ps_flags & PS_BEACON_SYNC)) | 1607 | ath9k_update_p2p_ps(sc, vif); |
| 1575 | ath9k_update_p2p_ps(sc, vif); | ||
| 1576 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); | 1608 | spin_unlock_irqrestore(&sc->sc_pm_lock, flags); |
| 1577 | spin_unlock_bh(&sc->sc_pcu_lock); | 1609 | spin_unlock_bh(&sc->sc_pcu_lock); |
| 1578 | } | 1610 | } |
diff --git a/drivers/net/wireless/ath/ath9k/common-beacon.c b/drivers/net/wireless/ath/ath9k/common-beacon.c index 6ad44470d0f2..01d6d3205a65 100644 --- a/drivers/net/wireless/ath/ath9k/common-beacon.c +++ b/drivers/net/wireless/ath/ath9k/common-beacon.c | |||
| @@ -18,30 +18,16 @@ | |||
| 18 | 18 | ||
| 19 | #define FUDGE 2 | 19 | #define FUDGE 2 |
| 20 | 20 | ||
| 21 | /* Calculate the modulo of a 64 bit TSF snapshot with a TU divisor */ | ||
| 22 | static u32 ath9k_mod_tsf64_tu(u64 tsf, u32 div_tu) | ||
| 23 | { | ||
| 24 | u32 tsf_mod, tsf_hi, tsf_lo, mod_hi, mod_lo; | ||
| 25 | |||
| 26 | tsf_mod = tsf & (BIT(10) - 1); | ||
| 27 | tsf_hi = tsf >> 32; | ||
| 28 | tsf_lo = ((u32) tsf) >> 10; | ||
| 29 | |||
| 30 | mod_hi = tsf_hi % div_tu; | ||
| 31 | mod_lo = ((mod_hi << 22) + tsf_lo) % div_tu; | ||
| 32 | |||
| 33 | return (mod_lo << 10) | tsf_mod; | ||
| 34 | } | ||
| 35 | |||
| 36 | static u32 ath9k_get_next_tbtt(struct ath_hw *ah, u64 tsf, | 21 | static u32 ath9k_get_next_tbtt(struct ath_hw *ah, u64 tsf, |
| 37 | unsigned int interval) | 22 | unsigned int interval) |
| 38 | { | 23 | { |
| 39 | unsigned int offset; | 24 | unsigned int offset, divisor; |
| 40 | 25 | ||
| 41 | tsf += TU_TO_USEC(FUDGE + ah->config.sw_beacon_response_time); | 26 | tsf += TU_TO_USEC(FUDGE + ah->config.sw_beacon_response_time); |
| 42 | offset = ath9k_mod_tsf64_tu(tsf, interval); | 27 | divisor = TU_TO_USEC(interval); |
| 28 | div_u64_rem(tsf, divisor, &offset); | ||
| 43 | 29 | ||
| 44 | return (u32) tsf + TU_TO_USEC(interval) - offset; | 30 | return (u32) tsf + divisor - offset; |
| 45 | } | 31 | } |
| 46 | 32 | ||
| 47 | /* | 33 | /* |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.c b/drivers/net/wireless/ath/ath9k/eeprom.c index cc81482c934d..f8c5065e5f5f 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.c +++ b/drivers/net/wireless/ath/ath9k/eeprom.c | |||
| @@ -138,6 +138,80 @@ bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data) | |||
| 138 | return ret; | 138 | return ret; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size) | ||
| 142 | { | ||
| 143 | u16 magic; | ||
| 144 | u16 *eepdata; | ||
| 145 | int i; | ||
| 146 | struct ath_common *common = ath9k_hw_common(ah); | ||
| 147 | |||
| 148 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { | ||
| 149 | ath_err(common, "Reading Magic # failed\n"); | ||
| 150 | return -EIO; | ||
| 151 | } | ||
| 152 | |||
| 153 | if (magic == AR5416_EEPROM_MAGIC) { | ||
| 154 | *swap_needed = false; | ||
| 155 | } else if (swab16(magic) == AR5416_EEPROM_MAGIC) { | ||
| 156 | if (ah->ah_flags & AH_NO_EEP_SWAP) { | ||
| 157 | ath_info(common, | ||
| 158 | "Ignoring endianness difference in EEPROM magic bytes.\n"); | ||
| 159 | |||
| 160 | *swap_needed = false; | ||
| 161 | } else { | ||
| 162 | *swap_needed = true; | ||
| 163 | } | ||
| 164 | } else { | ||
| 165 | ath_err(common, | ||
| 166 | "Invalid EEPROM Magic (0x%04x).\n", magic); | ||
| 167 | return -EINVAL; | ||
| 168 | } | ||
| 169 | |||
| 170 | eepdata = (u16 *)(&ah->eeprom); | ||
| 171 | |||
| 172 | if (*swap_needed) { | ||
| 173 | ath_dbg(common, EEPROM, | ||
| 174 | "EEPROM Endianness is not native.. Changing.\n"); | ||
| 175 | |||
| 176 | for (i = 0; i < size; i++) | ||
| 177 | eepdata[i] = swab16(eepdata[i]); | ||
| 178 | } | ||
| 179 | |||
| 180 | return 0; | ||
| 181 | } | ||
| 182 | |||
| 183 | bool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size) | ||
| 184 | { | ||
| 185 | u32 i, sum = 0; | ||
| 186 | u16 *eepdata = (u16 *)(&ah->eeprom); | ||
| 187 | struct ath_common *common = ath9k_hw_common(ah); | ||
| 188 | |||
| 189 | for (i = 0; i < size; i++) | ||
| 190 | sum ^= eepdata[i]; | ||
| 191 | |||
| 192 | if (sum != 0xffff) { | ||
| 193 | ath_err(common, "Bad EEPROM checksum 0x%x\n", sum); | ||
| 194 | return false; | ||
| 195 | } | ||
| 196 | |||
| 197 | return true; | ||
| 198 | } | ||
| 199 | |||
| 200 | bool ath9k_hw_nvram_check_version(struct ath_hw *ah, int version, int minrev) | ||
| 201 | { | ||
| 202 | struct ath_common *common = ath9k_hw_common(ah); | ||
| 203 | |||
| 204 | if (ah->eep_ops->get_eeprom_ver(ah) != version || | ||
| 205 | ah->eep_ops->get_eeprom_rev(ah) < minrev) { | ||
| 206 | ath_err(common, "Bad EEPROM VER 0x%04x or REV 0x%04x\n", | ||
| 207 | ah->eep_ops->get_eeprom_ver(ah), | ||
| 208 | ah->eep_ops->get_eeprom_rev(ah)); | ||
| 209 | return -EINVAL; | ||
| 210 | } | ||
| 211 | |||
| 212 | return true; | ||
| 213 | } | ||
| 214 | |||
| 141 | void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, | 215 | void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, |
| 142 | u8 *pVpdList, u16 numIntercepts, | 216 | u8 *pVpdList, u16 numIntercepts, |
| 143 | u8 *pRetVpdList) | 217 | u8 *pRetVpdList) |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h index 40d4f62d0f16..4465c6566f20 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom.h +++ b/drivers/net/wireless/ath/ath9k/eeprom.h | |||
| @@ -664,6 +664,9 @@ int16_t ath9k_hw_interpolate(u16 target, u16 srcLeft, u16 srcRight, | |||
| 664 | bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, | 664 | bool ath9k_hw_get_lower_upper_index(u8 target, u8 *pList, u16 listSize, |
| 665 | u16 *indexL, u16 *indexR); | 665 | u16 *indexL, u16 *indexR); |
| 666 | bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data); | 666 | bool ath9k_hw_nvram_read(struct ath_hw *ah, u32 off, u16 *data); |
| 667 | int ath9k_hw_nvram_swap_data(struct ath_hw *ah, bool *swap_needed, int size); | ||
| 668 | bool ath9k_hw_nvram_validate_checksum(struct ath_hw *ah, int size); | ||
| 669 | bool ath9k_hw_nvram_check_version(struct ath_hw *ah, int version, int minrev); | ||
| 667 | void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data, | 670 | void ath9k_hw_usb_gen_fill_eeprom(struct ath_hw *ah, u16 *eep_data, |
| 668 | int eep_start_loc, int size); | 671 | int eep_start_loc, int size); |
| 669 | void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, | 672 | void ath9k_hw_fill_vpd_table(u8 pwrMin, u8 pwrMax, u8 *pPwrList, |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c index 4773da6dc6f2..5da0826bf1be 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c | |||
| @@ -177,74 +177,30 @@ static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
| 177 | } | 177 | } |
| 178 | #endif | 178 | #endif |
| 179 | 179 | ||
| 180 | |||
| 181 | #undef SIZE_EEPROM_4K | ||
| 182 | |||
| 183 | static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | 180 | static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) |
| 184 | { | 181 | { |
| 185 | #define EEPROM_4K_SIZE (sizeof(struct ar5416_eeprom_4k) / sizeof(u16)) | ||
| 186 | struct ath_common *common = ath9k_hw_common(ah); | ||
| 187 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; | 182 | struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k; |
| 188 | u16 *eepdata, temp, magic, magic2; | 183 | u32 el; |
| 189 | u32 sum = 0, el; | 184 | bool need_swap; |
| 190 | bool need_swap = false; | 185 | int i, err; |
| 191 | int i, addr; | ||
| 192 | 186 | ||
| 193 | 187 | err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_4K); | |
| 194 | if (!ath9k_hw_use_flash(ah)) { | 188 | if (err) |
| 195 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, | 189 | return err; |
| 196 | &magic)) { | ||
| 197 | ath_err(common, "Reading Magic # failed\n"); | ||
| 198 | return false; | ||
| 199 | } | ||
| 200 | |||
| 201 | ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic); | ||
| 202 | |||
| 203 | if (magic != AR5416_EEPROM_MAGIC) { | ||
| 204 | magic2 = swab16(magic); | ||
| 205 | |||
| 206 | if (magic2 == AR5416_EEPROM_MAGIC) { | ||
| 207 | need_swap = true; | ||
| 208 | eepdata = (u16 *) (&ah->eeprom); | ||
| 209 | |||
| 210 | for (addr = 0; addr < EEPROM_4K_SIZE; addr++) { | ||
| 211 | temp = swab16(*eepdata); | ||
| 212 | *eepdata = temp; | ||
| 213 | eepdata++; | ||
| 214 | } | ||
| 215 | } else { | ||
| 216 | ath_err(common, | ||
| 217 | "Invalid EEPROM Magic. Endianness mismatch.\n"); | ||
| 218 | return -EINVAL; | ||
| 219 | } | ||
| 220 | } | ||
| 221 | } | ||
| 222 | |||
| 223 | ath_dbg(common, EEPROM, "need_swap = %s\n", | ||
| 224 | need_swap ? "True" : "False"); | ||
| 225 | 190 | ||
| 226 | if (need_swap) | 191 | if (need_swap) |
| 227 | el = swab16(ah->eeprom.map4k.baseEepHeader.length); | 192 | el = swab16(eep->baseEepHeader.length); |
| 228 | else | ||
| 229 | el = ah->eeprom.map4k.baseEepHeader.length; | ||
| 230 | |||
| 231 | if (el > sizeof(struct ar5416_eeprom_4k)) | ||
| 232 | el = sizeof(struct ar5416_eeprom_4k) / sizeof(u16); | ||
| 233 | else | 193 | else |
| 234 | el = el / sizeof(u16); | 194 | el = eep->baseEepHeader.length; |
| 235 | 195 | ||
| 236 | eepdata = (u16 *)(&ah->eeprom); | 196 | el = min(el / sizeof(u16), SIZE_EEPROM_4K); |
| 237 | 197 | if (!ath9k_hw_nvram_validate_checksum(ah, el)) | |
| 238 | for (i = 0; i < el; i++) | 198 | return -EINVAL; |
| 239 | sum ^= *eepdata++; | ||
| 240 | 199 | ||
| 241 | if (need_swap) { | 200 | if (need_swap) { |
| 242 | u32 integer; | 201 | u32 integer; |
| 243 | u16 word; | 202 | u16 word; |
| 244 | 203 | ||
| 245 | ath_dbg(common, EEPROM, | ||
| 246 | "EEPROM Endianness is not native.. Changing\n"); | ||
| 247 | |||
| 248 | word = swab16(eep->baseEepHeader.length); | 204 | word = swab16(eep->baseEepHeader.length); |
| 249 | eep->baseEepHeader.length = word; | 205 | eep->baseEepHeader.length = word; |
| 250 | 206 | ||
| @@ -283,17 +239,15 @@ static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) | |||
| 283 | } | 239 | } |
| 284 | } | 240 | } |
| 285 | 241 | ||
| 286 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || | 242 | if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER, |
| 287 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | 243 | AR5416_EEP_NO_BACK_VER)) |
| 288 | ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | ||
| 289 | sum, ah->eep_ops->get_eeprom_ver(ah)); | ||
| 290 | return -EINVAL; | 244 | return -EINVAL; |
| 291 | } | ||
| 292 | 245 | ||
| 293 | return 0; | 246 | return 0; |
| 294 | #undef EEPROM_4K_SIZE | ||
| 295 | } | 247 | } |
| 296 | 248 | ||
| 249 | #undef SIZE_EEPROM_4K | ||
| 250 | |||
| 297 | static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, | 251 | static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah, |
| 298 | enum eeprom_param param) | 252 | enum eeprom_param param) |
| 299 | { | 253 | { |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c index 6ca33dfde1fd..1a019a39eda1 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c | |||
| @@ -177,59 +177,24 @@ static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
| 177 | 177 | ||
| 178 | static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) | 178 | static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) |
| 179 | { | 179 | { |
| 180 | u32 sum = 0, el, integer; | 180 | u32 el, integer; |
| 181 | u16 temp, word, magic, magic2, *eepdata; | 181 | u16 word; |
| 182 | int i, addr; | 182 | int i, err; |
| 183 | bool need_swap = false; | 183 | bool need_swap; |
| 184 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; | 184 | struct ar9287_eeprom *eep = &ah->eeprom.map9287; |
| 185 | struct ath_common *common = ath9k_hw_common(ah); | ||
| 186 | |||
| 187 | if (!ath9k_hw_use_flash(ah)) { | ||
| 188 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, | ||
| 189 | &magic)) { | ||
| 190 | ath_err(common, "Reading Magic # failed\n"); | ||
| 191 | return false; | ||
| 192 | } | ||
| 193 | |||
| 194 | ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic); | ||
| 195 | |||
| 196 | if (magic != AR5416_EEPROM_MAGIC) { | ||
| 197 | magic2 = swab16(magic); | ||
| 198 | |||
| 199 | if (magic2 == AR5416_EEPROM_MAGIC) { | ||
| 200 | need_swap = true; | ||
| 201 | eepdata = (u16 *)(&ah->eeprom); | ||
| 202 | |||
| 203 | for (addr = 0; addr < SIZE_EEPROM_AR9287; addr++) { | ||
| 204 | temp = swab16(*eepdata); | ||
| 205 | *eepdata = temp; | ||
| 206 | eepdata++; | ||
| 207 | } | ||
| 208 | } else { | ||
| 209 | ath_err(common, | ||
| 210 | "Invalid EEPROM Magic. Endianness mismatch.\n"); | ||
| 211 | return -EINVAL; | ||
| 212 | } | ||
| 213 | } | ||
| 214 | } | ||
| 215 | 185 | ||
| 216 | ath_dbg(common, EEPROM, "need_swap = %s\n", | 186 | err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_AR9287); |
| 217 | need_swap ? "True" : "False"); | 187 | if (err) |
| 188 | return err; | ||
| 218 | 189 | ||
| 219 | if (need_swap) | 190 | if (need_swap) |
| 220 | el = swab16(ah->eeprom.map9287.baseEepHeader.length); | 191 | el = swab16(eep->baseEepHeader.length); |
| 221 | else | ||
| 222 | el = ah->eeprom.map9287.baseEepHeader.length; | ||
| 223 | |||
| 224 | if (el > sizeof(struct ar9287_eeprom)) | ||
| 225 | el = sizeof(struct ar9287_eeprom) / sizeof(u16); | ||
| 226 | else | 192 | else |
| 227 | el = el / sizeof(u16); | 193 | el = eep->baseEepHeader.length; |
| 228 | |||
| 229 | eepdata = (u16 *)(&ah->eeprom); | ||
| 230 | 194 | ||
| 231 | for (i = 0; i < el; i++) | 195 | el = min(el / sizeof(u16), SIZE_EEPROM_AR9287); |
| 232 | sum ^= *eepdata++; | 196 | if (!ath9k_hw_nvram_validate_checksum(ah, el)) |
| 197 | return -EINVAL; | ||
| 233 | 198 | ||
| 234 | if (need_swap) { | 199 | if (need_swap) { |
| 235 | word = swab16(eep->baseEepHeader.length); | 200 | word = swab16(eep->baseEepHeader.length); |
| @@ -270,16 +235,15 @@ static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) | |||
| 270 | } | 235 | } |
| 271 | } | 236 | } |
| 272 | 237 | ||
| 273 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR9287_EEP_VER | 238 | if (!ath9k_hw_nvram_check_version(ah, AR9287_EEP_VER, |
| 274 | || ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | 239 | AR5416_EEP_NO_BACK_VER)) |
| 275 | ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | ||
| 276 | sum, ah->eep_ops->get_eeprom_ver(ah)); | ||
| 277 | return -EINVAL; | 240 | return -EINVAL; |
| 278 | } | ||
| 279 | 241 | ||
| 280 | return 0; | 242 | return 0; |
| 281 | } | 243 | } |
| 282 | 244 | ||
| 245 | #undef SIZE_EEPROM_AR9287 | ||
| 246 | |||
| 283 | static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah, | 247 | static u32 ath9k_hw_ar9287_get_eeprom(struct ath_hw *ah, |
| 284 | enum eeprom_param param) | 248 | enum eeprom_param param) |
| 285 | { | 249 | { |
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 056f516bf017..959682f7909c 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
| @@ -126,8 +126,6 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah) | |||
| 126 | return __ath9k_hw_def_fill_eeprom(ah); | 126 | return __ath9k_hw_def_fill_eeprom(ah); |
| 127 | } | 127 | } |
| 128 | 128 | ||
| 129 | #undef SIZE_EEPROM_DEF | ||
| 130 | |||
| 131 | #if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS) | 129 | #if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS) |
| 132 | static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size, | 130 | static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size, |
| 133 | struct modal_eep_header *modal_hdr) | 131 | struct modal_eep_header *modal_hdr) |
| @@ -257,59 +255,31 @@ static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr, | |||
| 257 | } | 255 | } |
| 258 | #endif | 256 | #endif |
| 259 | 257 | ||
| 260 | |||
| 261 | static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | 258 | static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) |
| 262 | { | 259 | { |
| 263 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | 260 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; |
| 264 | struct ath_common *common = ath9k_hw_common(ah); | 261 | struct ath_common *common = ath9k_hw_common(ah); |
| 265 | u16 *eepdata, temp, magic; | 262 | u32 el; |
| 266 | u32 sum = 0, el; | 263 | bool need_swap; |
| 267 | bool need_swap = false; | 264 | int i, err; |
| 268 | int i, addr, size; | ||
| 269 | |||
| 270 | if (!ath9k_hw_nvram_read(ah, AR5416_EEPROM_MAGIC_OFFSET, &magic)) { | ||
| 271 | ath_err(common, "Reading Magic # failed\n"); | ||
| 272 | return false; | ||
| 273 | } | ||
| 274 | |||
| 275 | if (swab16(magic) == AR5416_EEPROM_MAGIC && | ||
| 276 | !(ah->ah_flags & AH_NO_EEP_SWAP)) { | ||
| 277 | size = sizeof(struct ar5416_eeprom_def); | ||
| 278 | need_swap = true; | ||
| 279 | eepdata = (u16 *) (&ah->eeprom); | ||
| 280 | |||
| 281 | for (addr = 0; addr < size / sizeof(u16); addr++) { | ||
| 282 | temp = swab16(*eepdata); | ||
| 283 | *eepdata = temp; | ||
| 284 | eepdata++; | ||
| 285 | } | ||
| 286 | } | ||
| 287 | 265 | ||
| 288 | ath_dbg(common, EEPROM, "need_swap = %s\n", | 266 | err = ath9k_hw_nvram_swap_data(ah, &need_swap, SIZE_EEPROM_DEF); |
| 289 | need_swap ? "True" : "False"); | 267 | if (err) |
| 268 | return err; | ||
| 290 | 269 | ||
| 291 | if (need_swap) | 270 | if (need_swap) |
| 292 | el = swab16(ah->eeprom.def.baseEepHeader.length); | 271 | el = swab16(eep->baseEepHeader.length); |
| 293 | else | 272 | else |
| 294 | el = ah->eeprom.def.baseEepHeader.length; | 273 | el = eep->baseEepHeader.length; |
| 295 | 274 | ||
| 296 | if (el > sizeof(struct ar5416_eeprom_def)) | 275 | el = min(el / sizeof(u16), SIZE_EEPROM_DEF); |
| 297 | el = sizeof(struct ar5416_eeprom_def) / sizeof(u16); | 276 | if (!ath9k_hw_nvram_validate_checksum(ah, el)) |
| 298 | else | 277 | return -EINVAL; |
| 299 | el = el / sizeof(u16); | ||
| 300 | |||
| 301 | eepdata = (u16 *)(&ah->eeprom); | ||
| 302 | |||
| 303 | for (i = 0; i < el; i++) | ||
| 304 | sum ^= *eepdata++; | ||
| 305 | 278 | ||
| 306 | if (need_swap) { | 279 | if (need_swap) { |
| 307 | u32 integer, j; | 280 | u32 integer, j; |
| 308 | u16 word; | 281 | u16 word; |
| 309 | 282 | ||
| 310 | ath_dbg(common, EEPROM, | ||
| 311 | "EEPROM Endianness is not native.. Changing.\n"); | ||
| 312 | |||
| 313 | word = swab16(eep->baseEepHeader.length); | 283 | word = swab16(eep->baseEepHeader.length); |
| 314 | eep->baseEepHeader.length = word; | 284 | eep->baseEepHeader.length = word; |
| 315 | 285 | ||
| @@ -356,12 +326,9 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
| 356 | } | 326 | } |
| 357 | } | 327 | } |
| 358 | 328 | ||
| 359 | if (sum != 0xffff || ah->eep_ops->get_eeprom_ver(ah) != AR5416_EEP_VER || | 329 | if (!ath9k_hw_nvram_check_version(ah, AR5416_EEP_VER, |
| 360 | ah->eep_ops->get_eeprom_rev(ah) < AR5416_EEP_NO_BACK_VER) { | 330 | AR5416_EEP_NO_BACK_VER)) |
| 361 | ath_err(common, "Bad EEPROM checksum 0x%x or revision 0x%04x\n", | ||
| 362 | sum, ah->eep_ops->get_eeprom_ver(ah)); | ||
| 363 | return -EINVAL; | 331 | return -EINVAL; |
| 364 | } | ||
| 365 | 332 | ||
| 366 | /* Enable fixup for AR_AN_TOP2 if necessary */ | 333 | /* Enable fixup for AR_AN_TOP2 if necessary */ |
| 367 | if ((ah->hw_version.devid == AR9280_DEVID_PCI) && | 334 | if ((ah->hw_version.devid == AR9280_DEVID_PCI) && |
| @@ -376,6 +343,8 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
| 376 | return 0; | 343 | return 0; |
| 377 | } | 344 | } |
| 378 | 345 | ||
| 346 | #undef SIZE_EEPROM_DEF | ||
| 347 | |||
| 379 | static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, | 348 | static u32 ath9k_hw_def_get_eeprom(struct ath_hw *ah, |
| 380 | enum eeprom_param param) | 349 | enum eeprom_param param) |
| 381 | { | 350 | { |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 41382f89abe1..257f46ed4a04 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
| @@ -2299,10 +2299,10 @@ void ath9k_hw_set_sta_beacon_timers(struct ath_hw *ah, | |||
| 2299 | else | 2299 | else |
| 2300 | nextTbtt = bs->bs_nexttbtt; | 2300 | nextTbtt = bs->bs_nexttbtt; |
| 2301 | 2301 | ||
| 2302 | ath_dbg(common, BEACON, "next DTIM %d\n", bs->bs_nextdtim); | 2302 | ath_dbg(common, BEACON, "next DTIM %u\n", bs->bs_nextdtim); |
| 2303 | ath_dbg(common, BEACON, "next beacon %d\n", nextTbtt); | 2303 | ath_dbg(common, BEACON, "next beacon %u\n", nextTbtt); |
| 2304 | ath_dbg(common, BEACON, "beacon period %d\n", beaconintval); | 2304 | ath_dbg(common, BEACON, "beacon period %u\n", beaconintval); |
| 2305 | ath_dbg(common, BEACON, "DTIM period %d\n", dtimperiod); | 2305 | ath_dbg(common, BEACON, "DTIM period %u\n", dtimperiod); |
| 2306 | 2306 | ||
| 2307 | ENABLE_REGWRITE_BUFFER(ah); | 2307 | ENABLE_REGWRITE_BUFFER(ah); |
| 2308 | 2308 | ||
| @@ -2761,9 +2761,6 @@ void ath9k_hw_setrxfilter(struct ath_hw *ah, u32 bits) | |||
| 2761 | 2761 | ||
| 2762 | ENABLE_REGWRITE_BUFFER(ah); | 2762 | ENABLE_REGWRITE_BUFFER(ah); |
| 2763 | 2763 | ||
| 2764 | if (AR_SREV_9462(ah) || AR_SREV_9565(ah)) | ||
| 2765 | bits |= ATH9K_RX_FILTER_CONTROL_WRAPPER; | ||
| 2766 | |||
| 2767 | REG_WRITE(ah, AR_RX_FILTER, bits); | 2764 | REG_WRITE(ah, AR_RX_FILTER, bits); |
| 2768 | 2765 | ||
| 2769 | phybits = 0; | 2766 | phybits = 0; |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index d184e682e636..c1b33fdcca08 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
| @@ -739,6 +739,8 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
| 739 | 739 | ||
| 740 | ath9k_ps_restore(sc); | 740 | ath9k_ps_restore(sc); |
| 741 | 741 | ||
| 742 | ath9k_rng_start(sc); | ||
| 743 | |||
| 742 | return 0; | 744 | return 0; |
| 743 | } | 745 | } |
| 744 | 746 | ||
| @@ -828,6 +830,8 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
| 828 | 830 | ||
| 829 | ath9k_deinit_channel_context(sc); | 831 | ath9k_deinit_channel_context(sc); |
| 830 | 832 | ||
| 833 | ath9k_rng_stop(sc); | ||
| 834 | |||
| 831 | mutex_lock(&sc->mutex); | 835 | mutex_lock(&sc->mutex); |
| 832 | 836 | ||
| 833 | ath_cancel_work(sc); | 837 | ath_cancel_work(sc); |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 994daf6c6297..32160fca876a 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
| @@ -424,6 +424,9 @@ u32 ath_calcrxfilter(struct ath_softc *sc) | |||
| 424 | AR_SREV_9561(sc->sc_ah)) | 424 | AR_SREV_9561(sc->sc_ah)) |
| 425 | rfilt |= ATH9K_RX_FILTER_4ADDRESS; | 425 | rfilt |= ATH9K_RX_FILTER_4ADDRESS; |
| 426 | 426 | ||
| 427 | if (AR_SREV_9462(sc->sc_ah) || AR_SREV_9565(sc->sc_ah)) | ||
| 428 | rfilt |= ATH9K_RX_FILTER_CONTROL_WRAPPER; | ||
| 429 | |||
| 427 | if (ath9k_is_chanctx_enabled() && | 430 | if (ath9k_is_chanctx_enabled() && |
| 428 | test_bit(ATH_OP_SCANNING, &common->op_flags)) | 431 | test_bit(ATH_OP_SCANNING, &common->op_flags)) |
| 429 | rfilt |= ATH9K_RX_FILTER_BEACON; | 432 | rfilt |= ATH9K_RX_FILTER_BEACON; |
diff --git a/drivers/net/wireless/ath/ath9k/rng.c b/drivers/net/wireless/ath/ath9k/rng.c new file mode 100644 index 000000000000..c9cb2aad7b6f --- /dev/null +++ b/drivers/net/wireless/ath/ath9k/rng.c | |||
| @@ -0,0 +1,107 @@ | |||
| 1 | /* | ||
| 2 | * Copyright (c) 2015 Qualcomm Atheros, Inc. | ||
| 3 | * | ||
| 4 | * Permission to use, copy, modify, and/or distribute this software for any | ||
| 5 | * purpose with or without fee is hereby granted, provided that the above | ||
| 6 | * copyright notice and this permission notice appear in all copies. | ||
| 7 | * | ||
| 8 | * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES | ||
| 9 | * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF | ||
| 10 | * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR | ||
| 11 | * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
| 12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN | ||
| 13 | * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF | ||
| 14 | * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
| 15 | */ | ||
| 16 | |||
| 17 | #include <linux/hw_random.h> | ||
| 18 | #include <linux/kthread.h> | ||
| 19 | |||
| 20 | #include "ath9k.h" | ||
| 21 | #include "hw.h" | ||
| 22 | #include "ar9003_phy.h" | ||
| 23 | |||
| 24 | #define ATH9K_RNG_BUF_SIZE 320 | ||
| 25 | #define ATH9K_RNG_ENTROPY(x) (((x) * 8 * 320) >> 10) /* quality: 320/1024 */ | ||
| 26 | |||
| 27 | static int ath9k_rng_data_read(struct ath_softc *sc, u32 *buf, u32 buf_size) | ||
| 28 | { | ||
| 29 | int i, j; | ||
| 30 | u32 v1, v2, rng_last = sc->rng_last; | ||
| 31 | struct ath_hw *ah = sc->sc_ah; | ||
| 32 | |||
| 33 | ath9k_ps_wakeup(sc); | ||
| 34 | |||
| 35 | REG_RMW_FIELD(ah, AR_PHY_TEST, AR_PHY_TEST_BBB_OBS_SEL, 1); | ||
| 36 | REG_CLR_BIT(ah, AR_PHY_TEST, AR_PHY_TEST_RX_OBS_SEL_BIT5); | ||
| 37 | REG_RMW_FIELD(ah, AR_PHY_TEST_CTL_STATUS, AR_PHY_TEST_CTL_RX_OBS_SEL, 0); | ||
| 38 | |||
| 39 | for (i = 0, j = 0; i < buf_size; i++) { | ||
| 40 | v1 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff; | ||
| 41 | v2 = REG_READ(ah, AR_PHY_TST_ADC) & 0xffff; | ||
| 42 | |||
| 43 | /* wait for data ready */ | ||
| 44 | if (v1 && v2 && rng_last != v1 && v1 != v2 && v1 != 0xffff && | ||
| 45 | v2 != 0xffff) | ||
| 46 | buf[j++] = (v1 << 16) | v2; | ||
| 47 | |||
| 48 | rng_last = v2; | ||
| 49 | } | ||
| 50 | |||
| 51 | ath9k_ps_restore(sc); | ||
| 52 | |||
| 53 | sc->rng_last = rng_last; | ||
| 54 | |||
| 55 | return j << 2; | ||
| 56 | } | ||
| 57 | |||
| 58 | static int ath9k_rng_kthread(void *data) | ||
| 59 | { | ||
| 60 | int bytes_read; | ||
| 61 | struct ath_softc *sc = data; | ||
| 62 | u32 *rng_buf; | ||
| 63 | |||
| 64 | rng_buf = kmalloc_array(ATH9K_RNG_BUF_SIZE, sizeof(u32), GFP_KERNEL); | ||
| 65 | if (!rng_buf) | ||
| 66 | goto out; | ||
| 67 | |||
| 68 | while (!kthread_should_stop()) { | ||
| 69 | bytes_read = ath9k_rng_data_read(sc, rng_buf, | ||
| 70 | ATH9K_RNG_BUF_SIZE); | ||
| 71 | if (unlikely(!bytes_read)) { | ||
| 72 | msleep_interruptible(10); | ||
| 73 | continue; | ||
| 74 | } | ||
| 75 | |||
| 76 | /* sleep until entropy bits under write_wakeup_threshold */ | ||
| 77 | add_hwgenerator_randomness((void *)rng_buf, bytes_read, | ||
| 78 | ATH9K_RNG_ENTROPY(bytes_read)); | ||
| 79 | } | ||
| 80 | |||
| 81 | kfree(rng_buf); | ||
| 82 | out: | ||
| 83 | sc->rng_task = NULL; | ||
| 84 | |||
| 85 | return 0; | ||
| 86 | } | ||
| 87 | |||
| 88 | void ath9k_rng_start(struct ath_softc *sc) | ||
| 89 | { | ||
| 90 | struct ath_hw *ah = sc->sc_ah; | ||
| 91 | |||
| 92 | if (sc->rng_task) | ||
| 93 | return; | ||
| 94 | |||
| 95 | if (!AR_SREV_9300_20_OR_LATER(ah)) | ||
| 96 | return; | ||
| 97 | |||
| 98 | sc->rng_task = kthread_run(ath9k_rng_kthread, sc, "ath9k-hwrng"); | ||
| 99 | if (IS_ERR(sc->rng_task)) | ||
| 100 | sc->rng_task = NULL; | ||
| 101 | } | ||
| 102 | |||
| 103 | void ath9k_rng_stop(struct ath_softc *sc) | ||
| 104 | { | ||
| 105 | if (sc->rng_task) | ||
| 106 | kthread_stop(sc->rng_task); | ||
| 107 | } | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 3e3dac3d7060..fe795fc5288c 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
| @@ -1473,11 +1473,14 @@ static bool ath_tx_sched_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
| 1473 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | 1473 | int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, |
| 1474 | u16 tid, u16 *ssn) | 1474 | u16 tid, u16 *ssn) |
| 1475 | { | 1475 | { |
| 1476 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
| 1476 | struct ath_atx_tid *txtid; | 1477 | struct ath_atx_tid *txtid; |
| 1477 | struct ath_txq *txq; | 1478 | struct ath_txq *txq; |
| 1478 | struct ath_node *an; | 1479 | struct ath_node *an; |
| 1479 | u8 density; | 1480 | u8 density; |
| 1480 | 1481 | ||
| 1482 | ath_dbg(common, XMIT, "%s called\n", __func__); | ||
| 1483 | |||
| 1481 | an = (struct ath_node *)sta->drv_priv; | 1484 | an = (struct ath_node *)sta->drv_priv; |
| 1482 | txtid = ATH_AN_2_TID(an, tid); | 1485 | txtid = ATH_AN_2_TID(an, tid); |
| 1483 | txq = txtid->txq; | 1486 | txq = txtid->txq; |
| @@ -1512,10 +1515,13 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
| 1512 | 1515 | ||
| 1513 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | 1516 | void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) |
| 1514 | { | 1517 | { |
| 1518 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
| 1515 | struct ath_node *an = (struct ath_node *)sta->drv_priv; | 1519 | struct ath_node *an = (struct ath_node *)sta->drv_priv; |
| 1516 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); | 1520 | struct ath_atx_tid *txtid = ATH_AN_2_TID(an, tid); |
| 1517 | struct ath_txq *txq = txtid->txq; | 1521 | struct ath_txq *txq = txtid->txq; |
| 1518 | 1522 | ||
| 1523 | ath_dbg(common, XMIT, "%s called\n", __func__); | ||
| 1524 | |||
| 1519 | ath_txq_lock(sc, txq); | 1525 | ath_txq_lock(sc, txq); |
| 1520 | txtid->active = false; | 1526 | txtid->active = false; |
| 1521 | ath_tx_flush_tid(sc, txtid); | 1527 | ath_tx_flush_tid(sc, txtid); |
| @@ -1526,11 +1532,14 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid) | |||
| 1526 | void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, | 1532 | void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, |
| 1527 | struct ath_node *an) | 1533 | struct ath_node *an) |
| 1528 | { | 1534 | { |
| 1535 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
| 1529 | struct ath_atx_tid *tid; | 1536 | struct ath_atx_tid *tid; |
| 1530 | struct ath_txq *txq; | 1537 | struct ath_txq *txq; |
| 1531 | bool buffered; | 1538 | bool buffered; |
| 1532 | int tidno; | 1539 | int tidno; |
| 1533 | 1540 | ||
| 1541 | ath_dbg(common, XMIT, "%s called\n", __func__); | ||
| 1542 | |||
| 1534 | for (tidno = 0, tid = &an->tid[tidno]; | 1543 | for (tidno = 0, tid = &an->tid[tidno]; |
| 1535 | tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { | 1544 | tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { |
| 1536 | 1545 | ||
| @@ -1555,10 +1564,13 @@ void ath_tx_aggr_sleep(struct ieee80211_sta *sta, struct ath_softc *sc, | |||
| 1555 | 1564 | ||
| 1556 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) | 1565 | void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) |
| 1557 | { | 1566 | { |
| 1567 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
| 1558 | struct ath_atx_tid *tid; | 1568 | struct ath_atx_tid *tid; |
| 1559 | struct ath_txq *txq; | 1569 | struct ath_txq *txq; |
| 1560 | int tidno; | 1570 | int tidno; |
| 1561 | 1571 | ||
| 1572 | ath_dbg(common, XMIT, "%s called\n", __func__); | ||
| 1573 | |||
| 1562 | for (tidno = 0, tid = &an->tid[tidno]; | 1574 | for (tidno = 0, tid = &an->tid[tidno]; |
| 1563 | tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { | 1575 | tidno < IEEE80211_NUM_TIDS; tidno++, tid++) { |
| 1564 | 1576 | ||
| @@ -1579,10 +1591,13 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) | |||
| 1579 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, | 1591 | void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, |
| 1580 | u16 tidno) | 1592 | u16 tidno) |
| 1581 | { | 1593 | { |
| 1594 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
| 1582 | struct ath_atx_tid *tid; | 1595 | struct ath_atx_tid *tid; |
| 1583 | struct ath_node *an; | 1596 | struct ath_node *an; |
| 1584 | struct ath_txq *txq; | 1597 | struct ath_txq *txq; |
| 1585 | 1598 | ||
| 1599 | ath_dbg(common, XMIT, "%s called\n", __func__); | ||
| 1600 | |||
| 1586 | an = (struct ath_node *)sta->drv_priv; | 1601 | an = (struct ath_node *)sta->drv_priv; |
| 1587 | tid = ATH_AN_2_TID(an, tidno); | 1602 | tid = ATH_AN_2_TID(an, tidno); |
| 1588 | txq = tid->txq; | 1603 | txq = tid->txq; |
| @@ -2316,6 +2331,12 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
| 2316 | 2331 | ||
| 2317 | queue = ieee80211_is_data_present(hdr->frame_control); | 2332 | queue = ieee80211_is_data_present(hdr->frame_control); |
| 2318 | 2333 | ||
| 2334 | /* If chanctx, queue all null frames while NOA could be there */ | ||
| 2335 | if (ath9k_is_chanctx_enabled() && | ||
| 2336 | ieee80211_is_nullfunc(hdr->frame_control) && | ||
| 2337 | !txctl->force_channel) | ||
| 2338 | queue = true; | ||
| 2339 | |||
| 2319 | /* Force queueing of all frames that belong to a virtual interface on | 2340 | /* Force queueing of all frames that belong to a virtual interface on |
| 2320 | * a different channel context, to ensure that they are sent on the | 2341 | * a different channel context, to ensure that they are sent on the |
| 2321 | * correct channel. | 2342 | * correct channel. |
| @@ -2894,7 +2915,7 @@ int ath9k_tx99_send(struct ath_softc *sc, struct sk_buff *skb, | |||
| 2894 | if (skb_headroom(skb) < padsize) { | 2915 | if (skb_headroom(skb) < padsize) { |
| 2895 | ath_dbg(common, XMIT, | 2916 | ath_dbg(common, XMIT, |
| 2896 | "tx99 padding failed\n"); | 2917 | "tx99 padding failed\n"); |
| 2897 | return -EINVAL; | 2918 | return -EINVAL; |
| 2898 | } | 2919 | } |
| 2899 | 2920 | ||
| 2900 | skb_push(skb, padsize); | 2921 | skb_push(skb, padsize); |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 48687f128dc6..09b4daebab9d 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
| @@ -781,8 +781,10 @@ int wil_reset(struct wil6210_priv *wil, bool load_fw) | |||
| 781 | wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); | 781 | wil6210_disconnect(wil, NULL, WLAN_REASON_DEAUTH_LEAVING, false); |
| 782 | wil_bcast_fini(wil); | 782 | wil_bcast_fini(wil); |
| 783 | 783 | ||
| 784 | /* prevent NAPI from being scheduled */ | 784 | /* prevent NAPI from being scheduled and prevent wmi commands */ |
| 785 | mutex_lock(&wil->wmi_mutex); | ||
| 785 | bitmap_zero(wil->status, wil_status_last); | 786 | bitmap_zero(wil->status, wil_status_last); |
| 787 | mutex_unlock(&wil->wmi_mutex); | ||
| 786 | 788 | ||
| 787 | if (wil->scan_request) { | 789 | if (wil->scan_request) { |
| 788 | wil_dbg_misc(wil, "Abort scan_request 0x%p\n", | 790 | wil_dbg_misc(wil, "Abort scan_request 0x%p\n", |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 6ed26baca0e5..e3ea74cdd4aa 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
| @@ -228,6 +228,10 @@ static int __wmi_send(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len) | |||
| 228 | wil_dbg_wmi(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head); | 228 | wil_dbg_wmi(wil, "Head 0x%08x -> 0x%08x\n", r->head, next_head); |
| 229 | /* wait till FW finish with previous command */ | 229 | /* wait till FW finish with previous command */ |
| 230 | for (retry = 5; retry > 0; retry--) { | 230 | for (retry = 5; retry > 0; retry--) { |
| 231 | if (!test_bit(wil_status_fwready, wil->status)) { | ||
| 232 | wil_err(wil, "WMI: cannot send command while FW not ready\n"); | ||
| 233 | return -EAGAIN; | ||
| 234 | } | ||
| 231 | r->tail = wil_r(wil, RGF_MBOX + | 235 | r->tail = wil_r(wil, RGF_MBOX + |
| 232 | offsetof(struct wil6210_mbox_ctl, tx.tail)); | 236 | offsetof(struct wil6210_mbox_ctl, tx.tail)); |
| 233 | if (next_head != r->tail) | 237 | if (next_head != r->tail) |
