diff options
Diffstat (limited to 'drivers/net/wireless')
199 files changed, 7072 insertions, 3612 deletions
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index e5ba6faf3281..ccba4fea7269 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -80,6 +80,7 @@ struct reg_dmn_pair_mapping { | |||
80 | 80 | ||
81 | struct ath_regulatory { | 81 | struct ath_regulatory { |
82 | char alpha2[2]; | 82 | char alpha2[2]; |
83 | enum nl80211_dfs_regions region; | ||
83 | u16 country_code; | 84 | u16 country_code; |
84 | u16 max_power_level; | 85 | u16 max_power_level; |
85 | u16 current_rd; | 86 | u16 current_rd; |
@@ -134,6 +135,11 @@ struct ath_ops { | |||
134 | struct ath_common; | 135 | struct ath_common; |
135 | struct ath_bus_ops; | 136 | struct ath_bus_ops; |
136 | 137 | ||
138 | struct ath_ps_ops { | ||
139 | void (*wakeup)(struct ath_common *common); | ||
140 | void (*restore)(struct ath_common *common); | ||
141 | }; | ||
142 | |||
137 | struct ath_common { | 143 | struct ath_common { |
138 | void *ah; | 144 | void *ah; |
139 | void *priv; | 145 | void *priv; |
@@ -147,7 +153,7 @@ struct ath_common { | |||
147 | u16 cachelsz; | 153 | u16 cachelsz; |
148 | u16 curaid; | 154 | u16 curaid; |
149 | u8 macaddr[ETH_ALEN]; | 155 | u8 macaddr[ETH_ALEN]; |
150 | u8 curbssid[ETH_ALEN]; | 156 | u8 curbssid[ETH_ALEN] __aligned(2); |
151 | u8 bssidmask[ETH_ALEN]; | 157 | u8 bssidmask[ETH_ALEN]; |
152 | 158 | ||
153 | u32 rx_bufsize; | 159 | u32 rx_bufsize; |
@@ -168,6 +174,7 @@ struct ath_common { | |||
168 | struct ath_regulatory reg_world_copy; | 174 | struct ath_regulatory reg_world_copy; |
169 | const struct ath_ops *ops; | 175 | const struct ath_ops *ops; |
170 | const struct ath_bus_ops *bus_ops; | 176 | const struct ath_bus_ops *bus_ops; |
177 | const struct ath_ps_ops *ps_ops; | ||
171 | 178 | ||
172 | bool btcoex_enabled; | 179 | bool btcoex_enabled; |
173 | bool disable_ani; | 180 | bool disable_ani; |
@@ -177,6 +184,11 @@ struct ath_common { | |||
177 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; | 184 | struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; |
178 | }; | 185 | }; |
179 | 186 | ||
187 | static inline const struct ath_ps_ops *ath_ps_ops(struct ath_common *common) | ||
188 | { | ||
189 | return common->ps_ops; | ||
190 | } | ||
191 | |||
180 | struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, | 192 | struct sk_buff *ath_rxbuf_alloc(struct ath_common *common, |
181 | u32 len, | 193 | u32 len, |
182 | gfp_t gfp_mask); | 194 | gfp_t gfp_mask); |
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 101cadb6e4ba..a156e6e48708 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c | |||
@@ -443,12 +443,12 @@ int ath10k_ce_rx_post_buf(struct ath10k_ce_pipe *pipe, void *ctx, u32 paddr) | |||
443 | * Guts of ath10k_ce_completed_recv_next. | 443 | * Guts of ath10k_ce_completed_recv_next. |
444 | * The caller takes responsibility for any necessary locking. | 444 | * The caller takes responsibility for any necessary locking. |
445 | */ | 445 | */ |
446 | static int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, | 446 | int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, |
447 | void **per_transfer_contextp, | 447 | void **per_transfer_contextp, |
448 | u32 *bufferp, | 448 | u32 *bufferp, |
449 | unsigned int *nbytesp, | 449 | unsigned int *nbytesp, |
450 | unsigned int *transfer_idp, | 450 | unsigned int *transfer_idp, |
451 | unsigned int *flagsp) | 451 | unsigned int *flagsp) |
452 | { | 452 | { |
453 | struct ath10k_ce_ring *dest_ring = ce_state->dest_ring; | 453 | struct ath10k_ce_ring *dest_ring = ce_state->dest_ring; |
454 | unsigned int nentries_mask = dest_ring->nentries_mask; | 454 | unsigned int nentries_mask = dest_ring->nentries_mask; |
@@ -558,6 +558,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, | |||
558 | 558 | ||
559 | /* sanity */ | 559 | /* sanity */ |
560 | dest_ring->per_transfer_context[sw_index] = NULL; | 560 | dest_ring->per_transfer_context[sw_index] = NULL; |
561 | desc->nbytes = 0; | ||
561 | 562 | ||
562 | /* Update sw_index */ | 563 | /* Update sw_index */ |
563 | sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); | 564 | sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); |
@@ -576,11 +577,11 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, | |||
576 | * Guts of ath10k_ce_completed_send_next. | 577 | * Guts of ath10k_ce_completed_send_next. |
577 | * The caller takes responsibility for any necessary locking. | 578 | * The caller takes responsibility for any necessary locking. |
578 | */ | 579 | */ |
579 | static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, | 580 | int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, |
580 | void **per_transfer_contextp, | 581 | void **per_transfer_contextp, |
581 | u32 *bufferp, | 582 | u32 *bufferp, |
582 | unsigned int *nbytesp, | 583 | unsigned int *nbytesp, |
583 | unsigned int *transfer_idp) | 584 | unsigned int *transfer_idp) |
584 | { | 585 | { |
585 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; | 586 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; |
586 | u32 ctrl_addr = ce_state->ctrl_addr; | 587 | u32 ctrl_addr = ce_state->ctrl_addr; |
@@ -817,7 +818,10 @@ void ath10k_ce_enable_interrupts(struct ath10k *ar) | |||
817 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 818 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
818 | int ce_id; | 819 | int ce_id; |
819 | 820 | ||
820 | for (ce_id = 0; ce_id < CE_COUNT; ce_id++) | 821 | /* Skip the last copy engine, CE7 the diagnostic window, as that |
822 | * uses polling and isn't initialized for interrupts. | ||
823 | */ | ||
824 | for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++) | ||
821 | ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]); | 825 | ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]); |
822 | } | 826 | } |
823 | 827 | ||
@@ -832,8 +836,8 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar, | |||
832 | 836 | ||
833 | nentries = roundup_pow_of_two(attr->src_nentries); | 837 | nentries = roundup_pow_of_two(attr->src_nentries); |
834 | 838 | ||
835 | memset(src_ring->per_transfer_context, 0, | 839 | memset(src_ring->base_addr_owner_space, 0, |
836 | nentries * sizeof(*src_ring->per_transfer_context)); | 840 | nentries * sizeof(struct ce_desc)); |
837 | 841 | ||
838 | src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); | 842 | src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); |
839 | src_ring->sw_index &= src_ring->nentries_mask; | 843 | src_ring->sw_index &= src_ring->nentries_mask; |
@@ -869,8 +873,8 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, | |||
869 | 873 | ||
870 | nentries = roundup_pow_of_two(attr->dest_nentries); | 874 | nentries = roundup_pow_of_two(attr->dest_nentries); |
871 | 875 | ||
872 | memset(dest_ring->per_transfer_context, 0, | 876 | memset(dest_ring->base_addr_owner_space, 0, |
873 | nentries * sizeof(*dest_ring->per_transfer_context)); | 877 | nentries * sizeof(struct ce_desc)); |
874 | 878 | ||
875 | dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr); | 879 | dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr); |
876 | dest_ring->sw_index &= dest_ring->nentries_mask; | 880 | dest_ring->sw_index &= dest_ring->nentries_mask; |
@@ -1020,37 +1024,10 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id, | |||
1020 | * initialized by software/firmware. | 1024 | * initialized by software/firmware. |
1021 | */ | 1025 | */ |
1022 | int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, | 1026 | int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, |
1023 | const struct ce_attr *attr, | 1027 | const struct ce_attr *attr) |
1024 | void (*send_cb)(struct ath10k_ce_pipe *), | ||
1025 | void (*recv_cb)(struct ath10k_ce_pipe *)) | ||
1026 | { | 1028 | { |
1027 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | ||
1028 | struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; | ||
1029 | int ret; | 1029 | int ret; |
1030 | 1030 | ||
1031 | /* | ||
1032 | * Make sure there's enough CE ringbuffer entries for HTT TX to avoid | ||
1033 | * additional TX locking checks. | ||
1034 | * | ||
1035 | * For the lack of a better place do the check here. | ||
1036 | */ | ||
1037 | BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC > | ||
1038 | (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); | ||
1039 | BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC > | ||
1040 | (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); | ||
1041 | |||
1042 | spin_lock_bh(&ar_pci->ce_lock); | ||
1043 | ce_state->ar = ar; | ||
1044 | ce_state->id = ce_id; | ||
1045 | ce_state->ctrl_addr = ath10k_ce_base_address(ce_id); | ||
1046 | ce_state->attr_flags = attr->flags; | ||
1047 | ce_state->src_sz_max = attr->src_sz_max; | ||
1048 | if (attr->src_nentries) | ||
1049 | ce_state->send_cb = send_cb; | ||
1050 | if (attr->dest_nentries) | ||
1051 | ce_state->recv_cb = recv_cb; | ||
1052 | spin_unlock_bh(&ar_pci->ce_lock); | ||
1053 | |||
1054 | if (attr->src_nentries) { | 1031 | if (attr->src_nentries) { |
1055 | ret = ath10k_ce_init_src_ring(ar, ce_id, attr); | 1032 | ret = ath10k_ce_init_src_ring(ar, ce_id, attr); |
1056 | if (ret) { | 1033 | if (ret) { |
@@ -1098,12 +1075,37 @@ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id) | |||
1098 | } | 1075 | } |
1099 | 1076 | ||
1100 | int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, | 1077 | int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, |
1101 | const struct ce_attr *attr) | 1078 | const struct ce_attr *attr, |
1079 | void (*send_cb)(struct ath10k_ce_pipe *), | ||
1080 | void (*recv_cb)(struct ath10k_ce_pipe *)) | ||
1102 | { | 1081 | { |
1103 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1082 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
1104 | struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; | 1083 | struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; |
1105 | int ret; | 1084 | int ret; |
1106 | 1085 | ||
1086 | /* | ||
1087 | * Make sure there's enough CE ringbuffer entries for HTT TX to avoid | ||
1088 | * additional TX locking checks. | ||
1089 | * | ||
1090 | * For the lack of a better place do the check here. | ||
1091 | */ | ||
1092 | BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC > | ||
1093 | (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); | ||
1094 | BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC > | ||
1095 | (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); | ||
1096 | |||
1097 | ce_state->ar = ar; | ||
1098 | ce_state->id = ce_id; | ||
1099 | ce_state->ctrl_addr = ath10k_ce_base_address(ce_id); | ||
1100 | ce_state->attr_flags = attr->flags; | ||
1101 | ce_state->src_sz_max = attr->src_sz_max; | ||
1102 | |||
1103 | if (attr->src_nentries) | ||
1104 | ce_state->send_cb = send_cb; | ||
1105 | |||
1106 | if (attr->dest_nentries) | ||
1107 | ce_state->recv_cb = recv_cb; | ||
1108 | |||
1107 | if (attr->src_nentries) { | 1109 | if (attr->src_nentries) { |
1108 | ce_state->src_ring = ath10k_ce_alloc_src_ring(ar, ce_id, attr); | 1110 | ce_state->src_ring = ath10k_ce_alloc_src_ring(ar, ce_id, attr); |
1109 | if (IS_ERR(ce_state->src_ring)) { | 1111 | if (IS_ERR(ce_state->src_ring)) { |
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index 329b7340fa72..617a151e8ce4 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h | |||
@@ -192,15 +192,21 @@ int ath10k_ce_completed_send_next(struct ath10k_ce_pipe *ce_state, | |||
192 | unsigned int *nbytesp, | 192 | unsigned int *nbytesp, |
193 | unsigned int *transfer_idp); | 193 | unsigned int *transfer_idp); |
194 | 194 | ||
195 | int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, | ||
196 | void **per_transfer_contextp, | ||
197 | u32 *bufferp, | ||
198 | unsigned int *nbytesp, | ||
199 | unsigned int *transfer_idp); | ||
200 | |||
195 | /*==================CE Engine Initialization=======================*/ | 201 | /*==================CE Engine Initialization=======================*/ |
196 | 202 | ||
197 | int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, | 203 | int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, |
198 | const struct ce_attr *attr, | 204 | const struct ce_attr *attr); |
199 | void (*send_cb)(struct ath10k_ce_pipe *), | ||
200 | void (*recv_cb)(struct ath10k_ce_pipe *)); | ||
201 | void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id); | 205 | void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id); |
202 | int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, | 206 | int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, |
203 | const struct ce_attr *attr); | 207 | const struct ce_attr *attr, |
208 | void (*send_cb)(struct ath10k_ce_pipe *), | ||
209 | void (*recv_cb)(struct ath10k_ce_pipe *)); | ||
204 | void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id); | 210 | void ath10k_ce_free_pipe(struct ath10k *ar, int ce_id); |
205 | 211 | ||
206 | /*==================CE Engine Shutdown=======================*/ | 212 | /*==================CE Engine Shutdown=======================*/ |
@@ -213,6 +219,13 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, | |||
213 | void **per_transfer_contextp, | 219 | void **per_transfer_contextp, |
214 | u32 *bufferp); | 220 | u32 *bufferp); |
215 | 221 | ||
222 | int ath10k_ce_completed_recv_next_nolock(struct ath10k_ce_pipe *ce_state, | ||
223 | void **per_transfer_contextp, | ||
224 | u32 *bufferp, | ||
225 | unsigned int *nbytesp, | ||
226 | unsigned int *transfer_idp, | ||
227 | unsigned int *flagsp); | ||
228 | |||
216 | /* | 229 | /* |
217 | * Support clean shutdown by allowing the caller to cancel | 230 | * Support clean shutdown by allowing the caller to cancel |
218 | * pending sends. Target DMA must be stopped before using | 231 | * pending sends. Target DMA must be stopped before using |
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index cee18c89d7f2..f660553c6c48 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c | |||
@@ -31,12 +31,17 @@ | |||
31 | unsigned int ath10k_debug_mask; | 31 | unsigned int ath10k_debug_mask; |
32 | static bool uart_print; | 32 | static bool uart_print; |
33 | static unsigned int ath10k_p2p; | 33 | static unsigned int ath10k_p2p; |
34 | static bool skip_otp; | ||
35 | |||
34 | module_param_named(debug_mask, ath10k_debug_mask, uint, 0644); | 36 | module_param_named(debug_mask, ath10k_debug_mask, uint, 0644); |
35 | module_param(uart_print, bool, 0644); | 37 | module_param(uart_print, bool, 0644); |
36 | module_param_named(p2p, ath10k_p2p, uint, 0644); | 38 | module_param_named(p2p, ath10k_p2p, uint, 0644); |
39 | module_param(skip_otp, bool, 0644); | ||
40 | |||
37 | MODULE_PARM_DESC(debug_mask, "Debugging mask"); | 41 | MODULE_PARM_DESC(debug_mask, "Debugging mask"); |
38 | MODULE_PARM_DESC(uart_print, "Uart target debugging"); | 42 | MODULE_PARM_DESC(uart_print, "Uart target debugging"); |
39 | MODULE_PARM_DESC(p2p, "Enable ath10k P2P support"); | 43 | MODULE_PARM_DESC(p2p, "Enable ath10k P2P support"); |
44 | MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode"); | ||
40 | 45 | ||
41 | static const struct ath10k_hw_params ath10k_hw_params_list[] = { | 46 | static const struct ath10k_hw_params ath10k_hw_params_list[] = { |
42 | { | 47 | { |
@@ -138,7 +143,8 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar, | |||
138 | return fw; | 143 | return fw; |
139 | } | 144 | } |
140 | 145 | ||
141 | static int ath10k_push_board_ext_data(struct ath10k *ar) | 146 | static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data, |
147 | size_t data_len) | ||
142 | { | 148 | { |
143 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; | 149 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; |
144 | u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ; | 150 | u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ; |
@@ -159,14 +165,14 @@ static int ath10k_push_board_ext_data(struct ath10k *ar) | |||
159 | if (board_ext_data_addr == 0) | 165 | if (board_ext_data_addr == 0) |
160 | return 0; | 166 | return 0; |
161 | 167 | ||
162 | if (ar->board_len != (board_data_size + board_ext_data_size)) { | 168 | if (data_len != (board_data_size + board_ext_data_size)) { |
163 | ath10k_err(ar, "invalid board (ext) data sizes %zu != %d+%d\n", | 169 | ath10k_err(ar, "invalid board (ext) data sizes %zu != %d+%d\n", |
164 | ar->board_len, board_data_size, board_ext_data_size); | 170 | data_len, board_data_size, board_ext_data_size); |
165 | return -EINVAL; | 171 | return -EINVAL; |
166 | } | 172 | } |
167 | 173 | ||
168 | ret = ath10k_bmi_write_memory(ar, board_ext_data_addr, | 174 | ret = ath10k_bmi_write_memory(ar, board_ext_data_addr, |
169 | ar->board_data + board_data_size, | 175 | data + board_data_size, |
170 | board_ext_data_size); | 176 | board_ext_data_size); |
171 | if (ret) { | 177 | if (ret) { |
172 | ath10k_err(ar, "could not write board ext data (%d)\n", ret); | 178 | ath10k_err(ar, "could not write board ext data (%d)\n", ret); |
@@ -184,13 +190,14 @@ static int ath10k_push_board_ext_data(struct ath10k *ar) | |||
184 | return 0; | 190 | return 0; |
185 | } | 191 | } |
186 | 192 | ||
187 | static int ath10k_download_board_data(struct ath10k *ar) | 193 | static int ath10k_download_board_data(struct ath10k *ar, const void *data, |
194 | size_t data_len) | ||
188 | { | 195 | { |
189 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; | 196 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; |
190 | u32 address; | 197 | u32 address; |
191 | int ret; | 198 | int ret; |
192 | 199 | ||
193 | ret = ath10k_push_board_ext_data(ar); | 200 | ret = ath10k_push_board_ext_data(ar, data, data_len); |
194 | if (ret) { | 201 | if (ret) { |
195 | ath10k_err(ar, "could not push board ext data (%d)\n", ret); | 202 | ath10k_err(ar, "could not push board ext data (%d)\n", ret); |
196 | goto exit; | 203 | goto exit; |
@@ -202,9 +209,9 @@ static int ath10k_download_board_data(struct ath10k *ar) | |||
202 | goto exit; | 209 | goto exit; |
203 | } | 210 | } |
204 | 211 | ||
205 | ret = ath10k_bmi_write_memory(ar, address, ar->board_data, | 212 | ret = ath10k_bmi_write_memory(ar, address, data, |
206 | min_t(u32, board_data_size, | 213 | min_t(u32, board_data_size, |
207 | ar->board_len)); | 214 | data_len)); |
208 | if (ret) { | 215 | if (ret) { |
209 | ath10k_err(ar, "could not write board data (%d)\n", ret); | 216 | ath10k_err(ar, "could not write board data (%d)\n", ret); |
210 | goto exit; | 217 | goto exit; |
@@ -220,11 +227,39 @@ exit: | |||
220 | return ret; | 227 | return ret; |
221 | } | 228 | } |
222 | 229 | ||
230 | static int ath10k_download_cal_file(struct ath10k *ar) | ||
231 | { | ||
232 | int ret; | ||
233 | |||
234 | if (!ar->cal_file) | ||
235 | return -ENOENT; | ||
236 | |||
237 | if (IS_ERR(ar->cal_file)) | ||
238 | return PTR_ERR(ar->cal_file); | ||
239 | |||
240 | ret = ath10k_download_board_data(ar, ar->cal_file->data, | ||
241 | ar->cal_file->size); | ||
242 | if (ret) { | ||
243 | ath10k_err(ar, "failed to download cal_file data: %d\n", ret); | ||
244 | return ret; | ||
245 | } | ||
246 | |||
247 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n"); | ||
248 | |||
249 | return 0; | ||
250 | } | ||
251 | |||
223 | static int ath10k_download_and_run_otp(struct ath10k *ar) | 252 | static int ath10k_download_and_run_otp(struct ath10k *ar) |
224 | { | 253 | { |
225 | u32 result, address = ar->hw_params.patch_load_addr; | 254 | u32 result, address = ar->hw_params.patch_load_addr; |
226 | int ret; | 255 | int ret; |
227 | 256 | ||
257 | ret = ath10k_download_board_data(ar, ar->board_data, ar->board_len); | ||
258 | if (ret) { | ||
259 | ath10k_err(ar, "failed to download board data: %d\n", ret); | ||
260 | return ret; | ||
261 | } | ||
262 | |||
228 | /* OTP is optional */ | 263 | /* OTP is optional */ |
229 | 264 | ||
230 | if (!ar->otp_data || !ar->otp_len) { | 265 | if (!ar->otp_data || !ar->otp_len) { |
@@ -250,7 +285,7 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) | |||
250 | 285 | ||
251 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); | 286 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); |
252 | 287 | ||
253 | if (result != 0) { | 288 | if (!skip_otp && result != 0) { |
254 | ath10k_err(ar, "otp calibration failed: %d", result); | 289 | ath10k_err(ar, "otp calibration failed: %d", result); |
255 | return -EINVAL; | 290 | return -EINVAL; |
256 | } | 291 | } |
@@ -308,6 +343,9 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) | |||
308 | if (ar->firmware && !IS_ERR(ar->firmware)) | 343 | if (ar->firmware && !IS_ERR(ar->firmware)) |
309 | release_firmware(ar->firmware); | 344 | release_firmware(ar->firmware); |
310 | 345 | ||
346 | if (ar->cal_file && !IS_ERR(ar->cal_file)) | ||
347 | release_firmware(ar->cal_file); | ||
348 | |||
311 | ar->board = NULL; | 349 | ar->board = NULL; |
312 | ar->board_data = NULL; | 350 | ar->board_data = NULL; |
313 | ar->board_len = 0; | 351 | ar->board_len = 0; |
@@ -319,6 +357,27 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) | |||
319 | ar->firmware = NULL; | 357 | ar->firmware = NULL; |
320 | ar->firmware_data = NULL; | 358 | ar->firmware_data = NULL; |
321 | ar->firmware_len = 0; | 359 | ar->firmware_len = 0; |
360 | |||
361 | ar->cal_file = NULL; | ||
362 | } | ||
363 | |||
364 | static int ath10k_fetch_cal_file(struct ath10k *ar) | ||
365 | { | ||
366 | char filename[100]; | ||
367 | |||
368 | /* cal-<bus>-<id>.bin */ | ||
369 | scnprintf(filename, sizeof(filename), "cal-%s-%s.bin", | ||
370 | ath10k_bus_str(ar->hif.bus), dev_name(ar->dev)); | ||
371 | |||
372 | ar->cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename); | ||
373 | if (IS_ERR(ar->cal_file)) | ||
374 | /* calibration file is optional, don't print any warnings */ | ||
375 | return PTR_ERR(ar->cal_file); | ||
376 | |||
377 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n", | ||
378 | ATH10K_FW_DIR, filename); | ||
379 | |||
380 | return 0; | ||
322 | } | 381 | } |
323 | 382 | ||
324 | static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar) | 383 | static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar) |
@@ -562,6 +621,9 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) | |||
562 | { | 621 | { |
563 | int ret; | 622 | int ret; |
564 | 623 | ||
624 | /* calibration file is optional, don't check for any errors */ | ||
625 | ath10k_fetch_cal_file(ar); | ||
626 | |||
565 | ar->fw_api = 3; | 627 | ar->fw_api = 3; |
566 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); | 628 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); |
567 | 629 | ||
@@ -589,30 +651,32 @@ success: | |||
589 | return 0; | 651 | return 0; |
590 | } | 652 | } |
591 | 653 | ||
592 | static int ath10k_init_download_firmware(struct ath10k *ar, | 654 | static int ath10k_download_cal_data(struct ath10k *ar) |
593 | enum ath10k_firmware_mode mode) | ||
594 | { | 655 | { |
595 | int ret; | 656 | int ret; |
596 | 657 | ||
597 | ret = ath10k_download_board_data(ar); | 658 | ret = ath10k_download_cal_file(ar); |
598 | if (ret) { | 659 | if (ret == 0) { |
599 | ath10k_err(ar, "failed to download board data: %d\n", ret); | 660 | ar->cal_mode = ATH10K_CAL_MODE_FILE; |
600 | return ret; | 661 | goto done; |
601 | } | 662 | } |
602 | 663 | ||
664 | ath10k_dbg(ar, ATH10K_DBG_BOOT, | ||
665 | "boot did not find a calibration file, try OTP next: %d\n", | ||
666 | ret); | ||
667 | |||
603 | ret = ath10k_download_and_run_otp(ar); | 668 | ret = ath10k_download_and_run_otp(ar); |
604 | if (ret) { | 669 | if (ret) { |
605 | ath10k_err(ar, "failed to run otp: %d\n", ret); | 670 | ath10k_err(ar, "failed to run otp: %d\n", ret); |
606 | return ret; | 671 | return ret; |
607 | } | 672 | } |
608 | 673 | ||
609 | ret = ath10k_download_fw(ar, mode); | 674 | ar->cal_mode = ATH10K_CAL_MODE_OTP; |
610 | if (ret) { | ||
611 | ath10k_err(ar, "failed to download firmware: %d\n", ret); | ||
612 | return ret; | ||
613 | } | ||
614 | 675 | ||
615 | return ret; | 676 | done: |
677 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using calibration mode %s\n", | ||
678 | ath10k_cal_mode_str(ar->cal_mode)); | ||
679 | return 0; | ||
616 | } | 680 | } |
617 | 681 | ||
618 | static int ath10k_init_uart(struct ath10k *ar) | 682 | static int ath10k_init_uart(struct ath10k *ar) |
@@ -685,6 +749,25 @@ static void ath10k_core_restart(struct work_struct *work) | |||
685 | { | 749 | { |
686 | struct ath10k *ar = container_of(work, struct ath10k, restart_work); | 750 | struct ath10k *ar = container_of(work, struct ath10k, restart_work); |
687 | 751 | ||
752 | set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); | ||
753 | |||
754 | /* Place a barrier to make sure the compiler doesn't reorder | ||
755 | * CRASH_FLUSH and calling other functions. | ||
756 | */ | ||
757 | barrier(); | ||
758 | |||
759 | ieee80211_stop_queues(ar->hw); | ||
760 | ath10k_drain_tx(ar); | ||
761 | complete_all(&ar->scan.started); | ||
762 | complete_all(&ar->scan.completed); | ||
763 | complete_all(&ar->scan.on_channel); | ||
764 | complete_all(&ar->offchan_tx_completed); | ||
765 | complete_all(&ar->install_key_done); | ||
766 | complete_all(&ar->vdev_setup_done); | ||
767 | wake_up(&ar->htt.empty_tx_wq); | ||
768 | wake_up(&ar->wmi.tx_credits_wq); | ||
769 | wake_up(&ar->peer_mapping_wq); | ||
770 | |||
688 | mutex_lock(&ar->conf_mutex); | 771 | mutex_lock(&ar->conf_mutex); |
689 | 772 | ||
690 | switch (ar->state) { | 773 | switch (ar->state) { |
@@ -722,6 +805,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) | |||
722 | 805 | ||
723 | lockdep_assert_held(&ar->conf_mutex); | 806 | lockdep_assert_held(&ar->conf_mutex); |
724 | 807 | ||
808 | clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); | ||
809 | |||
725 | ath10k_bmi_start(ar); | 810 | ath10k_bmi_start(ar); |
726 | 811 | ||
727 | if (ath10k_init_configure_target(ar)) { | 812 | if (ath10k_init_configure_target(ar)) { |
@@ -729,7 +814,11 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) | |||
729 | goto err; | 814 | goto err; |
730 | } | 815 | } |
731 | 816 | ||
732 | status = ath10k_init_download_firmware(ar, mode); | 817 | status = ath10k_download_cal_data(ar); |
818 | if (status) | ||
819 | goto err; | ||
820 | |||
821 | status = ath10k_download_fw(ar, mode); | ||
733 | if (status) | 822 | if (status) |
734 | goto err; | 823 | goto err; |
735 | 824 | ||
@@ -846,9 +935,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) | |||
846 | goto err_hif_stop; | 935 | goto err_hif_stop; |
847 | 936 | ||
848 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | 937 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) |
849 | ar->free_vdev_map = (1 << TARGET_10X_NUM_VDEVS) - 1; | 938 | ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS) - 1; |
850 | else | 939 | else |
851 | ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1; | 940 | ar->free_vdev_map = (1LL << TARGET_NUM_VDEVS) - 1; |
852 | 941 | ||
853 | INIT_LIST_HEAD(&ar->arvifs); | 942 | INIT_LIST_HEAD(&ar->arvifs); |
854 | 943 | ||
@@ -1084,6 +1173,7 @@ void ath10k_core_unregister(struct ath10k *ar) | |||
1084 | EXPORT_SYMBOL(ath10k_core_unregister); | 1173 | EXPORT_SYMBOL(ath10k_core_unregister); |
1085 | 1174 | ||
1086 | struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, | 1175 | struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, |
1176 | enum ath10k_bus bus, | ||
1087 | const struct ath10k_hif_ops *hif_ops) | 1177 | const struct ath10k_hif_ops *hif_ops) |
1088 | { | 1178 | { |
1089 | struct ath10k *ar; | 1179 | struct ath10k *ar; |
@@ -1100,6 +1190,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, | |||
1100 | ar->dev = dev; | 1190 | ar->dev = dev; |
1101 | 1191 | ||
1102 | ar->hif.ops = hif_ops; | 1192 | ar->hif.ops = hif_ops; |
1193 | ar->hif.bus = bus; | ||
1103 | 1194 | ||
1104 | init_completion(&ar->scan.started); | 1195 | init_completion(&ar->scan.started); |
1105 | init_completion(&ar->scan.completed); | 1196 | init_completion(&ar->scan.completed); |
@@ -1120,6 +1211,8 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, | |||
1120 | 1211 | ||
1121 | INIT_LIST_HEAD(&ar->peers); | 1212 | INIT_LIST_HEAD(&ar->peers); |
1122 | init_waitqueue_head(&ar->peer_mapping_wq); | 1213 | init_waitqueue_head(&ar->peer_mapping_wq); |
1214 | init_waitqueue_head(&ar->htt.empty_tx_wq); | ||
1215 | init_waitqueue_head(&ar->wmi.tx_credits_wq); | ||
1123 | 1216 | ||
1124 | init_completion(&ar->offchan_tx_completed); | 1217 | init_completion(&ar->offchan_tx_completed); |
1125 | INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work); | 1218 | INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work); |
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index fe531ea6926c..8f86bd34e823 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
@@ -63,6 +63,20 @@ | |||
63 | 63 | ||
64 | struct ath10k; | 64 | struct ath10k; |
65 | 65 | ||
66 | enum ath10k_bus { | ||
67 | ATH10K_BUS_PCI, | ||
68 | }; | ||
69 | |||
70 | static inline const char *ath10k_bus_str(enum ath10k_bus bus) | ||
71 | { | ||
72 | switch (bus) { | ||
73 | case ATH10K_BUS_PCI: | ||
74 | return "pci"; | ||
75 | } | ||
76 | |||
77 | return "unknown"; | ||
78 | } | ||
79 | |||
66 | struct ath10k_skb_cb { | 80 | struct ath10k_skb_cb { |
67 | dma_addr_t paddr; | 81 | dma_addr_t paddr; |
68 | u8 vdev_id; | 82 | u8 vdev_id; |
@@ -96,8 +110,6 @@ struct ath10k_bmi { | |||
96 | bool done_sent; | 110 | bool done_sent; |
97 | }; | 111 | }; |
98 | 112 | ||
99 | #define ATH10K_MAX_MEM_REQS 16 | ||
100 | |||
101 | struct ath10k_mem_chunk { | 113 | struct ath10k_mem_chunk { |
102 | void *vaddr; | 114 | void *vaddr; |
103 | dma_addr_t paddr; | 115 | dma_addr_t paddr; |
@@ -115,17 +127,21 @@ struct ath10k_wmi { | |||
115 | struct wmi_pdev_param_map *pdev_param; | 127 | struct wmi_pdev_param_map *pdev_param; |
116 | 128 | ||
117 | u32 num_mem_chunks; | 129 | u32 num_mem_chunks; |
118 | struct ath10k_mem_chunk mem_chunks[ATH10K_MAX_MEM_REQS]; | 130 | struct ath10k_mem_chunk mem_chunks[WMI_MAX_MEM_REQS]; |
119 | }; | 131 | }; |
120 | 132 | ||
121 | struct ath10k_peer_stat { | 133 | struct ath10k_fw_stats_peer { |
134 | struct list_head list; | ||
135 | |||
122 | u8 peer_macaddr[ETH_ALEN]; | 136 | u8 peer_macaddr[ETH_ALEN]; |
123 | u32 peer_rssi; | 137 | u32 peer_rssi; |
124 | u32 peer_tx_rate; | 138 | u32 peer_tx_rate; |
125 | u32 peer_rx_rate; /* 10x only */ | 139 | u32 peer_rx_rate; /* 10x only */ |
126 | }; | 140 | }; |
127 | 141 | ||
128 | struct ath10k_target_stats { | 142 | struct ath10k_fw_stats_pdev { |
143 | struct list_head list; | ||
144 | |||
129 | /* PDEV stats */ | 145 | /* PDEV stats */ |
130 | s32 ch_noise_floor; | 146 | s32 ch_noise_floor; |
131 | u32 tx_frame_count; | 147 | u32 tx_frame_count; |
@@ -180,15 +196,11 @@ struct ath10k_target_stats { | |||
180 | s32 phy_errs; | 196 | s32 phy_errs; |
181 | s32 phy_err_drop; | 197 | s32 phy_err_drop; |
182 | s32 mpdu_errs; | 198 | s32 mpdu_errs; |
199 | }; | ||
183 | 200 | ||
184 | /* VDEV STATS */ | 201 | struct ath10k_fw_stats { |
185 | 202 | struct list_head pdevs; | |
186 | /* PEER STATS */ | 203 | struct list_head peers; |
187 | u8 peers; | ||
188 | struct ath10k_peer_stat peer_stat[TARGET_NUM_PEERS]; | ||
189 | |||
190 | /* TODO: Beacon filter stats */ | ||
191 | |||
192 | }; | 204 | }; |
193 | 205 | ||
194 | struct ath10k_dfs_stats { | 206 | struct ath10k_dfs_stats { |
@@ -234,6 +246,8 @@ struct ath10k_vif { | |||
234 | struct sk_buff *beacon; | 246 | struct sk_buff *beacon; |
235 | /* protected by data_lock */ | 247 | /* protected by data_lock */ |
236 | bool beacon_sent; | 248 | bool beacon_sent; |
249 | void *beacon_buf; | ||
250 | dma_addr_t beacon_paddr; | ||
237 | 251 | ||
238 | struct ath10k *ar; | 252 | struct ath10k *ar; |
239 | struct ieee80211_vif *vif; | 253 | struct ieee80211_vif *vif; |
@@ -273,6 +287,7 @@ struct ath10k_vif { | |||
273 | u8 force_sgi; | 287 | u8 force_sgi; |
274 | bool use_cts_prot; | 288 | bool use_cts_prot; |
275 | int num_legacy_stations; | 289 | int num_legacy_stations; |
290 | int txpower; | ||
276 | }; | 291 | }; |
277 | 292 | ||
278 | struct ath10k_vif_iter { | 293 | struct ath10k_vif_iter { |
@@ -292,17 +307,19 @@ struct ath10k_fw_crash_data { | |||
292 | struct ath10k_debug { | 307 | struct ath10k_debug { |
293 | struct dentry *debugfs_phy; | 308 | struct dentry *debugfs_phy; |
294 | 309 | ||
295 | struct ath10k_target_stats target_stats; | 310 | struct ath10k_fw_stats fw_stats; |
311 | struct completion fw_stats_complete; | ||
312 | bool fw_stats_done; | ||
296 | DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX); | 313 | DECLARE_BITMAP(wmi_service_bitmap, WMI_SERVICE_MAX); |
297 | 314 | ||
298 | struct completion event_stats_compl; | ||
299 | |||
300 | unsigned long htt_stats_mask; | 315 | unsigned long htt_stats_mask; |
301 | struct delayed_work htt_stats_dwork; | 316 | struct delayed_work htt_stats_dwork; |
302 | struct ath10k_dfs_stats dfs_stats; | 317 | struct ath10k_dfs_stats dfs_stats; |
303 | struct ath_dfs_pool_stats dfs_pool_stats; | 318 | struct ath_dfs_pool_stats dfs_pool_stats; |
304 | 319 | ||
320 | /* protected by conf_mutex */ | ||
305 | u32 fw_dbglog_mask; | 321 | u32 fw_dbglog_mask; |
322 | u32 pktlog_filter; | ||
306 | 323 | ||
307 | u8 htt_max_amsdu; | 324 | u8 htt_max_amsdu; |
308 | u8 htt_max_ampdu; | 325 | u8 htt_max_ampdu; |
@@ -321,7 +338,7 @@ enum ath10k_state { | |||
321 | * stopped in ath10k_core_restart() work holding conf_mutex. The state | 338 | * stopped in ath10k_core_restart() work holding conf_mutex. The state |
322 | * RESTARTED means that the device is up and mac80211 has started hw | 339 | * RESTARTED means that the device is up and mac80211 has started hw |
323 | * reconfiguration. Once mac80211 is done with the reconfiguration we | 340 | * reconfiguration. Once mac80211 is done with the reconfiguration we |
324 | * set the state to STATE_ON in restart_complete(). */ | 341 | * set the state to STATE_ON in reconfig_complete(). */ |
325 | ATH10K_STATE_RESTARTING, | 342 | ATH10K_STATE_RESTARTING, |
326 | ATH10K_STATE_RESTARTED, | 343 | ATH10K_STATE_RESTARTED, |
327 | 344 | ||
@@ -369,8 +386,30 @@ enum ath10k_dev_flags { | |||
369 | /* Indicates that ath10k device is during CAC phase of DFS */ | 386 | /* Indicates that ath10k device is during CAC phase of DFS */ |
370 | ATH10K_CAC_RUNNING, | 387 | ATH10K_CAC_RUNNING, |
371 | ATH10K_FLAG_CORE_REGISTERED, | 388 | ATH10K_FLAG_CORE_REGISTERED, |
389 | |||
390 | /* Device has crashed and needs to restart. This indicates any pending | ||
391 | * waiters should immediately cancel instead of waiting for a time out. | ||
392 | */ | ||
393 | ATH10K_FLAG_CRASH_FLUSH, | ||
372 | }; | 394 | }; |
373 | 395 | ||
396 | enum ath10k_cal_mode { | ||
397 | ATH10K_CAL_MODE_FILE, | ||
398 | ATH10K_CAL_MODE_OTP, | ||
399 | }; | ||
400 | |||
401 | static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode) | ||
402 | { | ||
403 | switch (mode) { | ||
404 | case ATH10K_CAL_MODE_FILE: | ||
405 | return "file"; | ||
406 | case ATH10K_CAL_MODE_OTP: | ||
407 | return "otp"; | ||
408 | } | ||
409 | |||
410 | return "unknown"; | ||
411 | } | ||
412 | |||
374 | enum ath10k_scan_state { | 413 | enum ath10k_scan_state { |
375 | ATH10K_SCAN_IDLE, | 414 | ATH10K_SCAN_IDLE, |
376 | ATH10K_SCAN_STARTING, | 415 | ATH10K_SCAN_STARTING, |
@@ -421,6 +460,7 @@ struct ath10k { | |||
421 | bool p2p; | 460 | bool p2p; |
422 | 461 | ||
423 | struct { | 462 | struct { |
463 | enum ath10k_bus bus; | ||
424 | const struct ath10k_hif_ops *ops; | 464 | const struct ath10k_hif_ops *ops; |
425 | } hif; | 465 | } hif; |
426 | 466 | ||
@@ -456,7 +496,10 @@ struct ath10k { | |||
456 | const void *firmware_data; | 496 | const void *firmware_data; |
457 | size_t firmware_len; | 497 | size_t firmware_len; |
458 | 498 | ||
499 | const struct firmware *cal_file; | ||
500 | |||
459 | int fw_api; | 501 | int fw_api; |
502 | enum ath10k_cal_mode cal_mode; | ||
460 | 503 | ||
461 | struct { | 504 | struct { |
462 | struct completion started; | 505 | struct completion started; |
@@ -482,7 +525,7 @@ struct ath10k { | |||
482 | /* current operating channel definition */ | 525 | /* current operating channel definition */ |
483 | struct cfg80211_chan_def chandef; | 526 | struct cfg80211_chan_def chandef; |
484 | 527 | ||
485 | int free_vdev_map; | 528 | unsigned long long free_vdev_map; |
486 | bool monitor; | 529 | bool monitor; |
487 | int monitor_vdev_id; | 530 | int monitor_vdev_id; |
488 | bool monitor_started; | 531 | bool monitor_started; |
@@ -563,11 +606,19 @@ struct ath10k { | |||
563 | bool utf_monitor; | 606 | bool utf_monitor; |
564 | } testmode; | 607 | } testmode; |
565 | 608 | ||
609 | struct { | ||
610 | /* protected by data_lock */ | ||
611 | u32 fw_crash_counter; | ||
612 | u32 fw_warm_reset_counter; | ||
613 | u32 fw_cold_reset_counter; | ||
614 | } stats; | ||
615 | |||
566 | /* must be last */ | 616 | /* must be last */ |
567 | u8 drv_priv[0] __aligned(sizeof(void *)); | 617 | u8 drv_priv[0] __aligned(sizeof(void *)); |
568 | }; | 618 | }; |
569 | 619 | ||
570 | struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, | 620 | struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, |
621 | enum ath10k_bus bus, | ||
571 | const struct ath10k_hif_ops *hif_ops); | 622 | const struct ath10k_hif_ops *hif_ops); |
572 | void ath10k_core_destroy(struct ath10k *ar); | 623 | void ath10k_core_destroy(struct ath10k *ar); |
573 | 624 | ||
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 3756feba3223..a8f5a72ba259 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c | |||
@@ -23,6 +23,7 @@ | |||
23 | 23 | ||
24 | #include "core.h" | 24 | #include "core.h" |
25 | #include "debug.h" | 25 | #include "debug.h" |
26 | #include "hif.h" | ||
26 | 27 | ||
27 | /* ms */ | 28 | /* ms */ |
28 | #define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000 | 29 | #define ATH10K_DEBUG_HTT_STATS_INTERVAL 1000 |
@@ -106,34 +107,36 @@ struct ath10k_dump_file_data { | |||
106 | u8 data[0]; | 107 | u8 data[0]; |
107 | } __packed; | 108 | } __packed; |
108 | 109 | ||
109 | int ath10k_info(struct ath10k *ar, const char *fmt, ...) | 110 | void ath10k_info(struct ath10k *ar, const char *fmt, ...) |
110 | { | 111 | { |
111 | struct va_format vaf = { | 112 | struct va_format vaf = { |
112 | .fmt = fmt, | 113 | .fmt = fmt, |
113 | }; | 114 | }; |
114 | va_list args; | 115 | va_list args; |
115 | int ret; | ||
116 | 116 | ||
117 | va_start(args, fmt); | 117 | va_start(args, fmt); |
118 | vaf.va = &args; | 118 | vaf.va = &args; |
119 | ret = dev_info(ar->dev, "%pV", &vaf); | 119 | dev_info(ar->dev, "%pV", &vaf); |
120 | trace_ath10k_log_info(ar, &vaf); | 120 | trace_ath10k_log_info(ar, &vaf); |
121 | va_end(args); | 121 | va_end(args); |
122 | |||
123 | return ret; | ||
124 | } | 122 | } |
125 | EXPORT_SYMBOL(ath10k_info); | 123 | EXPORT_SYMBOL(ath10k_info); |
126 | 124 | ||
127 | void ath10k_print_driver_info(struct ath10k *ar) | 125 | void ath10k_print_driver_info(struct ath10k *ar) |
128 | { | 126 | { |
129 | ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d\n", | 127 | ath10k_info(ar, "%s (0x%08x, 0x%08x) fw %s api %d htt %d.%d wmi %d.%d.%d.%d cal %s\n", |
130 | ar->hw_params.name, | 128 | ar->hw_params.name, |
131 | ar->target_version, | 129 | ar->target_version, |
132 | ar->chip_id, | 130 | ar->chip_id, |
133 | ar->hw->wiphy->fw_version, | 131 | ar->hw->wiphy->fw_version, |
134 | ar->fw_api, | 132 | ar->fw_api, |
135 | ar->htt.target_version_major, | 133 | ar->htt.target_version_major, |
136 | ar->htt.target_version_minor); | 134 | ar->htt.target_version_minor, |
135 | ar->fw_version_major, | ||
136 | ar->fw_version_minor, | ||
137 | ar->fw_version_release, | ||
138 | ar->fw_version_build, | ||
139 | ath10k_cal_mode_str(ar->cal_mode)); | ||
137 | ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n", | 140 | ath10k_info(ar, "debug %d debugfs %d tracing %d dfs %d testmode %d\n", |
138 | config_enabled(CONFIG_ATH10K_DEBUG), | 141 | config_enabled(CONFIG_ATH10K_DEBUG), |
139 | config_enabled(CONFIG_ATH10K_DEBUGFS), | 142 | config_enabled(CONFIG_ATH10K_DEBUGFS), |
@@ -143,25 +146,22 @@ void ath10k_print_driver_info(struct ath10k *ar) | |||
143 | } | 146 | } |
144 | EXPORT_SYMBOL(ath10k_print_driver_info); | 147 | EXPORT_SYMBOL(ath10k_print_driver_info); |
145 | 148 | ||
146 | int ath10k_err(struct ath10k *ar, const char *fmt, ...) | 149 | void ath10k_err(struct ath10k *ar, const char *fmt, ...) |
147 | { | 150 | { |
148 | struct va_format vaf = { | 151 | struct va_format vaf = { |
149 | .fmt = fmt, | 152 | .fmt = fmt, |
150 | }; | 153 | }; |
151 | va_list args; | 154 | va_list args; |
152 | int ret; | ||
153 | 155 | ||
154 | va_start(args, fmt); | 156 | va_start(args, fmt); |
155 | vaf.va = &args; | 157 | vaf.va = &args; |
156 | ret = dev_err(ar->dev, "%pV", &vaf); | 158 | dev_err(ar->dev, "%pV", &vaf); |
157 | trace_ath10k_log_err(ar, &vaf); | 159 | trace_ath10k_log_err(ar, &vaf); |
158 | va_end(args); | 160 | va_end(args); |
159 | |||
160 | return ret; | ||
161 | } | 161 | } |
162 | EXPORT_SYMBOL(ath10k_err); | 162 | EXPORT_SYMBOL(ath10k_err); |
163 | 163 | ||
164 | int ath10k_warn(struct ath10k *ar, const char *fmt, ...) | 164 | void ath10k_warn(struct ath10k *ar, const char *fmt, ...) |
165 | { | 165 | { |
166 | struct va_format vaf = { | 166 | struct va_format vaf = { |
167 | .fmt = fmt, | 167 | .fmt = fmt, |
@@ -174,15 +174,13 @@ int ath10k_warn(struct ath10k *ar, const char *fmt, ...) | |||
174 | trace_ath10k_log_warn(ar, &vaf); | 174 | trace_ath10k_log_warn(ar, &vaf); |
175 | 175 | ||
176 | va_end(args); | 176 | va_end(args); |
177 | |||
178 | return 0; | ||
179 | } | 177 | } |
180 | EXPORT_SYMBOL(ath10k_warn); | 178 | EXPORT_SYMBOL(ath10k_warn); |
181 | 179 | ||
182 | #ifdef CONFIG_ATH10K_DEBUGFS | 180 | #ifdef CONFIG_ATH10K_DEBUGFS |
183 | 181 | ||
184 | void ath10k_debug_read_service_map(struct ath10k *ar, | 182 | void ath10k_debug_read_service_map(struct ath10k *ar, |
185 | void *service_map, | 183 | const void *service_map, |
186 | size_t map_size) | 184 | size_t map_size) |
187 | { | 185 | { |
188 | memcpy(ar->debug.wmi_service_bitmap, service_map, map_size); | 186 | memcpy(ar->debug.wmi_service_bitmap, service_map, map_size); |
@@ -242,169 +240,182 @@ static const struct file_operations fops_wmi_services = { | |||
242 | .llseek = default_llseek, | 240 | .llseek = default_llseek, |
243 | }; | 241 | }; |
244 | 242 | ||
245 | void ath10k_debug_read_target_stats(struct ath10k *ar, | 243 | static void ath10k_debug_fw_stats_pdevs_free(struct list_head *head) |
246 | struct wmi_stats_event *ev) | ||
247 | { | 244 | { |
248 | u8 *tmp = ev->data; | 245 | struct ath10k_fw_stats_pdev *i, *tmp; |
249 | struct ath10k_target_stats *stats; | 246 | |
250 | int num_pdev_stats, num_vdev_stats, num_peer_stats; | 247 | list_for_each_entry_safe(i, tmp, head, list) { |
251 | struct wmi_pdev_stats_10x *ps; | 248 | list_del(&i->list); |
252 | int i; | 249 | kfree(i); |
250 | } | ||
251 | } | ||
252 | |||
253 | static void ath10k_debug_fw_stats_peers_free(struct list_head *head) | ||
254 | { | ||
255 | struct ath10k_fw_stats_peer *i, *tmp; | ||
256 | |||
257 | list_for_each_entry_safe(i, tmp, head, list) { | ||
258 | list_del(&i->list); | ||
259 | kfree(i); | ||
260 | } | ||
261 | } | ||
253 | 262 | ||
263 | static void ath10k_debug_fw_stats_reset(struct ath10k *ar) | ||
264 | { | ||
254 | spin_lock_bh(&ar->data_lock); | 265 | spin_lock_bh(&ar->data_lock); |
266 | ar->debug.fw_stats_done = false; | ||
267 | ath10k_debug_fw_stats_pdevs_free(&ar->debug.fw_stats.pdevs); | ||
268 | ath10k_debug_fw_stats_peers_free(&ar->debug.fw_stats.peers); | ||
269 | spin_unlock_bh(&ar->data_lock); | ||
270 | } | ||
255 | 271 | ||
256 | stats = &ar->debug.target_stats; | 272 | static size_t ath10k_debug_fw_stats_num_peers(struct list_head *head) |
257 | 273 | { | |
258 | num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); /* 0 or 1 */ | 274 | struct ath10k_fw_stats_peer *i; |
259 | num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); /* 0 or max vdevs */ | 275 | size_t num = 0; |
260 | num_peer_stats = __le32_to_cpu(ev->num_peer_stats); /* 0 or max peers */ | 276 | |
261 | 277 | list_for_each_entry(i, head, list) | |
262 | if (num_pdev_stats) { | 278 | ++num; |
263 | ps = (struct wmi_pdev_stats_10x *)tmp; | 279 | |
264 | 280 | return num; | |
265 | stats->ch_noise_floor = __le32_to_cpu(ps->chan_nf); | 281 | } |
266 | stats->tx_frame_count = __le32_to_cpu(ps->tx_frame_count); | 282 | |
267 | stats->rx_frame_count = __le32_to_cpu(ps->rx_frame_count); | 283 | void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb) |
268 | stats->rx_clear_count = __le32_to_cpu(ps->rx_clear_count); | 284 | { |
269 | stats->cycle_count = __le32_to_cpu(ps->cycle_count); | 285 | struct ath10k_fw_stats stats = {}; |
270 | stats->phy_err_count = __le32_to_cpu(ps->phy_err_count); | 286 | bool is_start, is_started, is_end; |
271 | stats->chan_tx_power = __le32_to_cpu(ps->chan_tx_pwr); | 287 | size_t num_peers; |
272 | 288 | int ret; | |
273 | stats->comp_queued = __le32_to_cpu(ps->wal.tx.comp_queued); | 289 | |
274 | stats->comp_delivered = | 290 | INIT_LIST_HEAD(&stats.pdevs); |
275 | __le32_to_cpu(ps->wal.tx.comp_delivered); | 291 | INIT_LIST_HEAD(&stats.peers); |
276 | stats->msdu_enqued = __le32_to_cpu(ps->wal.tx.msdu_enqued); | 292 | |
277 | stats->mpdu_enqued = __le32_to_cpu(ps->wal.tx.mpdu_enqued); | 293 | spin_lock_bh(&ar->data_lock); |
278 | stats->wmm_drop = __le32_to_cpu(ps->wal.tx.wmm_drop); | 294 | ret = ath10k_wmi_pull_fw_stats(ar, skb, &stats); |
279 | stats->local_enqued = __le32_to_cpu(ps->wal.tx.local_enqued); | 295 | if (ret) { |
280 | stats->local_freed = __le32_to_cpu(ps->wal.tx.local_freed); | 296 | ath10k_warn(ar, "failed to pull fw stats: %d\n", ret); |
281 | stats->hw_queued = __le32_to_cpu(ps->wal.tx.hw_queued); | 297 | goto unlock; |
282 | stats->hw_reaped = __le32_to_cpu(ps->wal.tx.hw_reaped); | ||
283 | stats->underrun = __le32_to_cpu(ps->wal.tx.underrun); | ||
284 | stats->tx_abort = __le32_to_cpu(ps->wal.tx.tx_abort); | ||
285 | stats->mpdus_requed = __le32_to_cpu(ps->wal.tx.mpdus_requed); | ||
286 | stats->tx_ko = __le32_to_cpu(ps->wal.tx.tx_ko); | ||
287 | stats->data_rc = __le32_to_cpu(ps->wal.tx.data_rc); | ||
288 | stats->self_triggers = __le32_to_cpu(ps->wal.tx.self_triggers); | ||
289 | stats->sw_retry_failure = | ||
290 | __le32_to_cpu(ps->wal.tx.sw_retry_failure); | ||
291 | stats->illgl_rate_phy_err = | ||
292 | __le32_to_cpu(ps->wal.tx.illgl_rate_phy_err); | ||
293 | stats->pdev_cont_xretry = | ||
294 | __le32_to_cpu(ps->wal.tx.pdev_cont_xretry); | ||
295 | stats->pdev_tx_timeout = | ||
296 | __le32_to_cpu(ps->wal.tx.pdev_tx_timeout); | ||
297 | stats->pdev_resets = __le32_to_cpu(ps->wal.tx.pdev_resets); | ||
298 | stats->phy_underrun = __le32_to_cpu(ps->wal.tx.phy_underrun); | ||
299 | stats->txop_ovf = __le32_to_cpu(ps->wal.tx.txop_ovf); | ||
300 | |||
301 | stats->mid_ppdu_route_change = | ||
302 | __le32_to_cpu(ps->wal.rx.mid_ppdu_route_change); | ||
303 | stats->status_rcvd = __le32_to_cpu(ps->wal.rx.status_rcvd); | ||
304 | stats->r0_frags = __le32_to_cpu(ps->wal.rx.r0_frags); | ||
305 | stats->r1_frags = __le32_to_cpu(ps->wal.rx.r1_frags); | ||
306 | stats->r2_frags = __le32_to_cpu(ps->wal.rx.r2_frags); | ||
307 | stats->r3_frags = __le32_to_cpu(ps->wal.rx.r3_frags); | ||
308 | stats->htt_msdus = __le32_to_cpu(ps->wal.rx.htt_msdus); | ||
309 | stats->htt_mpdus = __le32_to_cpu(ps->wal.rx.htt_mpdus); | ||
310 | stats->loc_msdus = __le32_to_cpu(ps->wal.rx.loc_msdus); | ||
311 | stats->loc_mpdus = __le32_to_cpu(ps->wal.rx.loc_mpdus); | ||
312 | stats->oversize_amsdu = | ||
313 | __le32_to_cpu(ps->wal.rx.oversize_amsdu); | ||
314 | stats->phy_errs = __le32_to_cpu(ps->wal.rx.phy_errs); | ||
315 | stats->phy_err_drop = __le32_to_cpu(ps->wal.rx.phy_err_drop); | ||
316 | stats->mpdu_errs = __le32_to_cpu(ps->wal.rx.mpdu_errs); | ||
317 | |||
318 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, | ||
319 | ar->fw_features)) { | ||
320 | stats->ack_rx_bad = __le32_to_cpu(ps->ack_rx_bad); | ||
321 | stats->rts_bad = __le32_to_cpu(ps->rts_bad); | ||
322 | stats->rts_good = __le32_to_cpu(ps->rts_good); | ||
323 | stats->fcs_bad = __le32_to_cpu(ps->fcs_bad); | ||
324 | stats->no_beacons = __le32_to_cpu(ps->no_beacons); | ||
325 | stats->mib_int_count = __le32_to_cpu(ps->mib_int_count); | ||
326 | tmp += sizeof(struct wmi_pdev_stats_10x); | ||
327 | } else { | ||
328 | tmp += sizeof(struct wmi_pdev_stats_old); | ||
329 | } | ||
330 | } | 298 | } |
331 | 299 | ||
332 | /* 0 or max vdevs */ | 300 | /* Stat data may exceed htc-wmi buffer limit. In such case firmware |
333 | /* Currently firmware does not support VDEV stats */ | 301 | * splits the stats data and delivers it in a ping-pong fashion of |
334 | if (num_vdev_stats) { | 302 | * request cmd-update event. |
335 | struct wmi_vdev_stats *vdev_stats; | 303 | * |
304 | * However there is no explicit end-of-data. Instead start-of-data is | ||
305 | * used as an implicit one. This works as follows: | ||
306 | * a) discard stat update events until one with pdev stats is | ||
307 | * delivered - this skips session started at end of (b) | ||
308 | * b) consume stat update events until another one with pdev stats is | ||
309 | * delivered which is treated as end-of-data and is itself discarded | ||
310 | */ | ||
336 | 311 | ||
337 | for (i = 0; i < num_vdev_stats; i++) { | 312 | if (ar->debug.fw_stats_done) { |
338 | vdev_stats = (struct wmi_vdev_stats *)tmp; | 313 | ath10k_warn(ar, "received unsolicited stats update event\n"); |
339 | tmp += sizeof(struct wmi_vdev_stats); | 314 | goto free; |
340 | } | ||
341 | } | 315 | } |
342 | 316 | ||
343 | if (num_peer_stats) { | 317 | num_peers = ath10k_debug_fw_stats_num_peers(&ar->debug.fw_stats.peers); |
344 | struct wmi_peer_stats_10x *peer_stats; | 318 | is_start = (list_empty(&ar->debug.fw_stats.pdevs) && |
345 | struct ath10k_peer_stat *s; | 319 | !list_empty(&stats.pdevs)); |
346 | 320 | is_end = (!list_empty(&ar->debug.fw_stats.pdevs) && | |
347 | stats->peers = num_peer_stats; | 321 | !list_empty(&stats.pdevs)); |
348 | 322 | ||
349 | for (i = 0; i < num_peer_stats; i++) { | 323 | if (is_start) |
350 | peer_stats = (struct wmi_peer_stats_10x *)tmp; | 324 | list_splice_tail_init(&stats.pdevs, &ar->debug.fw_stats.pdevs); |
351 | s = &stats->peer_stat[i]; | 325 | |
352 | 326 | if (is_end) | |
353 | memcpy(s->peer_macaddr, &peer_stats->peer_macaddr.addr, | 327 | ar->debug.fw_stats_done = true; |
354 | ETH_ALEN); | 328 | |
355 | s->peer_rssi = __le32_to_cpu(peer_stats->peer_rssi); | 329 | is_started = !list_empty(&ar->debug.fw_stats.pdevs); |
356 | s->peer_tx_rate = | 330 | |
357 | __le32_to_cpu(peer_stats->peer_tx_rate); | 331 | if (is_started && !is_end) { |
358 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, | 332 | if (num_peers >= ATH10K_MAX_NUM_PEER_IDS) { |
359 | ar->fw_features)) { | 333 | /* Although this is unlikely impose a sane limit to |
360 | s->peer_rx_rate = | 334 | * prevent firmware from DoS-ing the host. |
361 | __le32_to_cpu(peer_stats->peer_rx_rate); | 335 | */ |
362 | tmp += sizeof(struct wmi_peer_stats_10x); | 336 | ath10k_warn(ar, "dropping fw peer stats\n"); |
363 | 337 | goto free; | |
364 | } else { | ||
365 | tmp += sizeof(struct wmi_peer_stats_old); | ||
366 | } | ||
367 | } | 338 | } |
339 | |||
340 | list_splice_tail_init(&stats.peers, &ar->debug.fw_stats.peers); | ||
368 | } | 341 | } |
369 | 342 | ||
343 | complete(&ar->debug.fw_stats_complete); | ||
344 | |||
345 | free: | ||
346 | /* In some cases lists have been spliced and cleared. Free up | ||
347 | * resources if that is not the case. | ||
348 | */ | ||
349 | ath10k_debug_fw_stats_pdevs_free(&stats.pdevs); | ||
350 | ath10k_debug_fw_stats_peers_free(&stats.peers); | ||
351 | |||
352 | unlock: | ||
370 | spin_unlock_bh(&ar->data_lock); | 353 | spin_unlock_bh(&ar->data_lock); |
371 | complete(&ar->debug.event_stats_compl); | ||
372 | } | 354 | } |
373 | 355 | ||
374 | static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf, | 356 | static int ath10k_debug_fw_stats_request(struct ath10k *ar) |
375 | size_t count, loff_t *ppos) | ||
376 | { | 357 | { |
377 | struct ath10k *ar = file->private_data; | 358 | unsigned long timeout; |
378 | struct ath10k_target_stats *fw_stats; | ||
379 | char *buf = NULL; | ||
380 | unsigned int len = 0, buf_len = 8000; | ||
381 | ssize_t ret_cnt = 0; | ||
382 | long left; | ||
383 | int i; | ||
384 | int ret; | 359 | int ret; |
385 | 360 | ||
386 | fw_stats = &ar->debug.target_stats; | 361 | lockdep_assert_held(&ar->conf_mutex); |
387 | 362 | ||
388 | mutex_lock(&ar->conf_mutex); | 363 | timeout = jiffies + msecs_to_jiffies(1*HZ); |
389 | 364 | ||
390 | if (ar->state != ATH10K_STATE_ON) | 365 | ath10k_debug_fw_stats_reset(ar); |
391 | goto exit; | ||
392 | 366 | ||
393 | buf = kzalloc(buf_len, GFP_KERNEL); | 367 | for (;;) { |
394 | if (!buf) | 368 | if (time_after(jiffies, timeout)) |
395 | goto exit; | 369 | return -ETIMEDOUT; |
396 | 370 | ||
397 | ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT); | 371 | reinit_completion(&ar->debug.fw_stats_complete); |
398 | if (ret) { | 372 | |
399 | ath10k_warn(ar, "could not request stats (%d)\n", ret); | 373 | ret = ath10k_wmi_request_stats(ar, WMI_REQUEST_PEER_STAT); |
400 | goto exit; | 374 | if (ret) { |
375 | ath10k_warn(ar, "could not request stats (%d)\n", ret); | ||
376 | return ret; | ||
377 | } | ||
378 | |||
379 | ret = wait_for_completion_timeout(&ar->debug.fw_stats_complete, | ||
380 | 1*HZ); | ||
381 | if (ret <= 0) | ||
382 | return -ETIMEDOUT; | ||
383 | |||
384 | spin_lock_bh(&ar->data_lock); | ||
385 | if (ar->debug.fw_stats_done) { | ||
386 | spin_unlock_bh(&ar->data_lock); | ||
387 | break; | ||
388 | } | ||
389 | spin_unlock_bh(&ar->data_lock); | ||
401 | } | 390 | } |
402 | 391 | ||
403 | left = wait_for_completion_timeout(&ar->debug.event_stats_compl, 1*HZ); | 392 | return 0; |
404 | if (left <= 0) | 393 | } |
405 | goto exit; | 394 | |
395 | /* FIXME: How to calculate the buffer size sanely? */ | ||
396 | #define ATH10K_FW_STATS_BUF_SIZE (1024*1024) | ||
397 | |||
398 | static void ath10k_fw_stats_fill(struct ath10k *ar, | ||
399 | struct ath10k_fw_stats *fw_stats, | ||
400 | char *buf) | ||
401 | { | ||
402 | unsigned int len = 0; | ||
403 | unsigned int buf_len = ATH10K_FW_STATS_BUF_SIZE; | ||
404 | const struct ath10k_fw_stats_pdev *pdev; | ||
405 | const struct ath10k_fw_stats_peer *peer; | ||
406 | size_t num_peers; | ||
406 | 407 | ||
407 | spin_lock_bh(&ar->data_lock); | 408 | spin_lock_bh(&ar->data_lock); |
409 | |||
410 | pdev = list_first_entry_or_null(&fw_stats->pdevs, | ||
411 | struct ath10k_fw_stats_pdev, list); | ||
412 | if (!pdev) { | ||
413 | ath10k_warn(ar, "failed to get pdev stats\n"); | ||
414 | goto unlock; | ||
415 | } | ||
416 | |||
417 | num_peers = ath10k_debug_fw_stats_num_peers(&fw_stats->peers); | ||
418 | |||
408 | len += scnprintf(buf + len, buf_len - len, "\n"); | 419 | len += scnprintf(buf + len, buf_len - len, "\n"); |
409 | len += scnprintf(buf + len, buf_len - len, "%30s\n", | 420 | len += scnprintf(buf + len, buf_len - len, "%30s\n", |
410 | "ath10k PDEV stats"); | 421 | "ath10k PDEV stats"); |
@@ -412,29 +423,29 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf, | |||
412 | "================="); | 423 | "================="); |
413 | 424 | ||
414 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 425 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
415 | "Channel noise floor", fw_stats->ch_noise_floor); | 426 | "Channel noise floor", pdev->ch_noise_floor); |
416 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | 427 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", |
417 | "Channel TX power", fw_stats->chan_tx_power); | 428 | "Channel TX power", pdev->chan_tx_power); |
418 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | 429 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", |
419 | "TX frame count", fw_stats->tx_frame_count); | 430 | "TX frame count", pdev->tx_frame_count); |
420 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | 431 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", |
421 | "RX frame count", fw_stats->rx_frame_count); | 432 | "RX frame count", pdev->rx_frame_count); |
422 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | 433 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", |
423 | "RX clear count", fw_stats->rx_clear_count); | 434 | "RX clear count", pdev->rx_clear_count); |
424 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | 435 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", |
425 | "Cycle count", fw_stats->cycle_count); | 436 | "Cycle count", pdev->cycle_count); |
426 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | 437 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", |
427 | "PHY error count", fw_stats->phy_err_count); | 438 | "PHY error count", pdev->phy_err_count); |
428 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | 439 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", |
429 | "RTS bad count", fw_stats->rts_bad); | 440 | "RTS bad count", pdev->rts_bad); |
430 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | 441 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", |
431 | "RTS good count", fw_stats->rts_good); | 442 | "RTS good count", pdev->rts_good); |
432 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | 443 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", |
433 | "FCS bad count", fw_stats->fcs_bad); | 444 | "FCS bad count", pdev->fcs_bad); |
434 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | 445 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", |
435 | "No beacon count", fw_stats->no_beacons); | 446 | "No beacon count", pdev->no_beacons); |
436 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", | 447 | len += scnprintf(buf + len, buf_len - len, "%30s %10u\n", |
437 | "MIB int count", fw_stats->mib_int_count); | 448 | "MIB int count", pdev->mib_int_count); |
438 | 449 | ||
439 | len += scnprintf(buf + len, buf_len - len, "\n"); | 450 | len += scnprintf(buf + len, buf_len - len, "\n"); |
440 | len += scnprintf(buf + len, buf_len - len, "%30s\n", | 451 | len += scnprintf(buf + len, buf_len - len, "%30s\n", |
@@ -443,51 +454,51 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf, | |||
443 | "================="); | 454 | "================="); |
444 | 455 | ||
445 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 456 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
446 | "HTT cookies queued", fw_stats->comp_queued); | 457 | "HTT cookies queued", pdev->comp_queued); |
447 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 458 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
448 | "HTT cookies disp.", fw_stats->comp_delivered); | 459 | "HTT cookies disp.", pdev->comp_delivered); |
449 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 460 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
450 | "MSDU queued", fw_stats->msdu_enqued); | 461 | "MSDU queued", pdev->msdu_enqued); |
451 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 462 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
452 | "MPDU queued", fw_stats->mpdu_enqued); | 463 | "MPDU queued", pdev->mpdu_enqued); |
453 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 464 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
454 | "MSDUs dropped", fw_stats->wmm_drop); | 465 | "MSDUs dropped", pdev->wmm_drop); |
455 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 466 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
456 | "Local enqued", fw_stats->local_enqued); | 467 | "Local enqued", pdev->local_enqued); |
457 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 468 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
458 | "Local freed", fw_stats->local_freed); | 469 | "Local freed", pdev->local_freed); |
459 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 470 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
460 | "HW queued", fw_stats->hw_queued); | 471 | "HW queued", pdev->hw_queued); |
461 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 472 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
462 | "PPDUs reaped", fw_stats->hw_reaped); | 473 | "PPDUs reaped", pdev->hw_reaped); |
463 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 474 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
464 | "Num underruns", fw_stats->underrun); | 475 | "Num underruns", pdev->underrun); |
465 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 476 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
466 | "PPDUs cleaned", fw_stats->tx_abort); | 477 | "PPDUs cleaned", pdev->tx_abort); |
467 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 478 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
468 | "MPDUs requed", fw_stats->mpdus_requed); | 479 | "MPDUs requed", pdev->mpdus_requed); |
469 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 480 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
470 | "Excessive retries", fw_stats->tx_ko); | 481 | "Excessive retries", pdev->tx_ko); |
471 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 482 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
472 | "HW rate", fw_stats->data_rc); | 483 | "HW rate", pdev->data_rc); |
473 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 484 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
474 | "Sched self tiggers", fw_stats->self_triggers); | 485 | "Sched self tiggers", pdev->self_triggers); |
475 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 486 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
476 | "Dropped due to SW retries", | 487 | "Dropped due to SW retries", |
477 | fw_stats->sw_retry_failure); | 488 | pdev->sw_retry_failure); |
478 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 489 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
479 | "Illegal rate phy errors", | 490 | "Illegal rate phy errors", |
480 | fw_stats->illgl_rate_phy_err); | 491 | pdev->illgl_rate_phy_err); |
481 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 492 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
482 | "Pdev continous xretry", fw_stats->pdev_cont_xretry); | 493 | "Pdev continous xretry", pdev->pdev_cont_xretry); |
483 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 494 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
484 | "TX timeout", fw_stats->pdev_tx_timeout); | 495 | "TX timeout", pdev->pdev_tx_timeout); |
485 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 496 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
486 | "PDEV resets", fw_stats->pdev_resets); | 497 | "PDEV resets", pdev->pdev_resets); |
487 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 498 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
488 | "PHY underrun", fw_stats->phy_underrun); | 499 | "PHY underrun", pdev->phy_underrun); |
489 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 500 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
490 | "MPDU is more than txop limit", fw_stats->txop_ovf); | 501 | "MPDU is more than txop limit", pdev->txop_ovf); |
491 | 502 | ||
492 | len += scnprintf(buf + len, buf_len - len, "\n"); | 503 | len += scnprintf(buf + len, buf_len - len, "\n"); |
493 | len += scnprintf(buf + len, buf_len - len, "%30s\n", | 504 | len += scnprintf(buf + len, buf_len - len, "%30s\n", |
@@ -497,70 +508,161 @@ static ssize_t ath10k_read_fw_stats(struct file *file, char __user *user_buf, | |||
497 | 508 | ||
498 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 509 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
499 | "Mid PPDU route change", | 510 | "Mid PPDU route change", |
500 | fw_stats->mid_ppdu_route_change); | 511 | pdev->mid_ppdu_route_change); |
501 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 512 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
502 | "Tot. number of statuses", fw_stats->status_rcvd); | 513 | "Tot. number of statuses", pdev->status_rcvd); |
503 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 514 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
504 | "Extra frags on rings 0", fw_stats->r0_frags); | 515 | "Extra frags on rings 0", pdev->r0_frags); |
505 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 516 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
506 | "Extra frags on rings 1", fw_stats->r1_frags); | 517 | "Extra frags on rings 1", pdev->r1_frags); |
507 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 518 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
508 | "Extra frags on rings 2", fw_stats->r2_frags); | 519 | "Extra frags on rings 2", pdev->r2_frags); |
509 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 520 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
510 | "Extra frags on rings 3", fw_stats->r3_frags); | 521 | "Extra frags on rings 3", pdev->r3_frags); |
511 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 522 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
512 | "MSDUs delivered to HTT", fw_stats->htt_msdus); | 523 | "MSDUs delivered to HTT", pdev->htt_msdus); |
513 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 524 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
514 | "MPDUs delivered to HTT", fw_stats->htt_mpdus); | 525 | "MPDUs delivered to HTT", pdev->htt_mpdus); |
515 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 526 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
516 | "MSDUs delivered to stack", fw_stats->loc_msdus); | 527 | "MSDUs delivered to stack", pdev->loc_msdus); |
517 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 528 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
518 | "MPDUs delivered to stack", fw_stats->loc_mpdus); | 529 | "MPDUs delivered to stack", pdev->loc_mpdus); |
519 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 530 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
520 | "Oversized AMSUs", fw_stats->oversize_amsdu); | 531 | "Oversized AMSUs", pdev->oversize_amsdu); |
521 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 532 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
522 | "PHY errors", fw_stats->phy_errs); | 533 | "PHY errors", pdev->phy_errs); |
523 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 534 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
524 | "PHY errors drops", fw_stats->phy_err_drop); | 535 | "PHY errors drops", pdev->phy_err_drop); |
525 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", | 536 | len += scnprintf(buf + len, buf_len - len, "%30s %10d\n", |
526 | "MPDU errors (FCS, MIC, ENC)", fw_stats->mpdu_errs); | 537 | "MPDU errors (FCS, MIC, ENC)", pdev->mpdu_errs); |
527 | 538 | ||
528 | len += scnprintf(buf + len, buf_len - len, "\n"); | 539 | len += scnprintf(buf + len, buf_len - len, "\n"); |
529 | len += scnprintf(buf + len, buf_len - len, "%30s (%d)\n", | 540 | len += scnprintf(buf + len, buf_len - len, "%30s (%zu)\n", |
530 | "ath10k PEER stats", fw_stats->peers); | 541 | "ath10k PEER stats", num_peers); |
531 | len += scnprintf(buf + len, buf_len - len, "%30s\n\n", | 542 | len += scnprintf(buf + len, buf_len - len, "%30s\n\n", |
532 | "================="); | 543 | "================="); |
533 | 544 | ||
534 | for (i = 0; i < fw_stats->peers; i++) { | 545 | list_for_each_entry(peer, &fw_stats->peers, list) { |
535 | len += scnprintf(buf + len, buf_len - len, "%30s %pM\n", | 546 | len += scnprintf(buf + len, buf_len - len, "%30s %pM\n", |
536 | "Peer MAC address", | 547 | "Peer MAC address", peer->peer_macaddr); |
537 | fw_stats->peer_stat[i].peer_macaddr); | ||
538 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | 548 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", |
539 | "Peer RSSI", fw_stats->peer_stat[i].peer_rssi); | 549 | "Peer RSSI", peer->peer_rssi); |
540 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | 550 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", |
541 | "Peer TX rate", | 551 | "Peer TX rate", peer->peer_tx_rate); |
542 | fw_stats->peer_stat[i].peer_tx_rate); | ||
543 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", | 552 | len += scnprintf(buf + len, buf_len - len, "%30s %u\n", |
544 | "Peer RX rate", | 553 | "Peer RX rate", peer->peer_rx_rate); |
545 | fw_stats->peer_stat[i].peer_rx_rate); | ||
546 | len += scnprintf(buf + len, buf_len - len, "\n"); | 554 | len += scnprintf(buf + len, buf_len - len, "\n"); |
547 | } | 555 | } |
556 | |||
557 | unlock: | ||
548 | spin_unlock_bh(&ar->data_lock); | 558 | spin_unlock_bh(&ar->data_lock); |
549 | 559 | ||
550 | if (len > buf_len) | 560 | if (len >= buf_len) |
551 | len = buf_len; | 561 | buf[len - 1] = 0; |
562 | else | ||
563 | buf[len] = 0; | ||
564 | } | ||
552 | 565 | ||
553 | ret_cnt = simple_read_from_buffer(user_buf, count, ppos, buf, len); | 566 | static int ath10k_fw_stats_open(struct inode *inode, struct file *file) |
567 | { | ||
568 | struct ath10k *ar = inode->i_private; | ||
569 | void *buf = NULL; | ||
570 | int ret; | ||
571 | |||
572 | mutex_lock(&ar->conf_mutex); | ||
573 | |||
574 | if (ar->state != ATH10K_STATE_ON) { | ||
575 | ret = -ENETDOWN; | ||
576 | goto err_unlock; | ||
577 | } | ||
578 | |||
579 | buf = vmalloc(ATH10K_FW_STATS_BUF_SIZE); | ||
580 | if (!buf) { | ||
581 | ret = -ENOMEM; | ||
582 | goto err_unlock; | ||
583 | } | ||
584 | |||
585 | ret = ath10k_debug_fw_stats_request(ar); | ||
586 | if (ret) { | ||
587 | ath10k_warn(ar, "failed to request fw stats: %d\n", ret); | ||
588 | goto err_free; | ||
589 | } | ||
590 | |||
591 | ath10k_fw_stats_fill(ar, &ar->debug.fw_stats, buf); | ||
592 | file->private_data = buf; | ||
554 | 593 | ||
555 | exit: | ||
556 | mutex_unlock(&ar->conf_mutex); | 594 | mutex_unlock(&ar->conf_mutex); |
557 | kfree(buf); | 595 | return 0; |
558 | return ret_cnt; | 596 | |
597 | err_free: | ||
598 | vfree(buf); | ||
599 | |||
600 | err_unlock: | ||
601 | mutex_unlock(&ar->conf_mutex); | ||
602 | return ret; | ||
603 | } | ||
604 | |||
605 | static int ath10k_fw_stats_release(struct inode *inode, struct file *file) | ||
606 | { | ||
607 | vfree(file->private_data); | ||
608 | |||
609 | return 0; | ||
610 | } | ||
611 | |||
612 | static ssize_t ath10k_fw_stats_read(struct file *file, char __user *user_buf, | ||
613 | size_t count, loff_t *ppos) | ||
614 | { | ||
615 | const char *buf = file->private_data; | ||
616 | unsigned int len = strlen(buf); | ||
617 | |||
618 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
559 | } | 619 | } |
560 | 620 | ||
561 | static const struct file_operations fops_fw_stats = { | 621 | static const struct file_operations fops_fw_stats = { |
562 | .read = ath10k_read_fw_stats, | 622 | .open = ath10k_fw_stats_open, |
623 | .release = ath10k_fw_stats_release, | ||
624 | .read = ath10k_fw_stats_read, | ||
625 | .owner = THIS_MODULE, | ||
626 | .llseek = default_llseek, | ||
627 | }; | ||
628 | |||
629 | static ssize_t ath10k_debug_fw_reset_stats_read(struct file *file, | ||
630 | char __user *user_buf, | ||
631 | size_t count, loff_t *ppos) | ||
632 | { | ||
633 | struct ath10k *ar = file->private_data; | ||
634 | int ret, len, buf_len; | ||
635 | char *buf; | ||
636 | |||
637 | buf_len = 500; | ||
638 | buf = kmalloc(buf_len, GFP_KERNEL); | ||
639 | if (!buf) | ||
640 | return -ENOMEM; | ||
641 | |||
642 | spin_lock_bh(&ar->data_lock); | ||
643 | |||
644 | len = 0; | ||
645 | len += scnprintf(buf + len, buf_len - len, | ||
646 | "fw_crash_counter\t\t%d\n", ar->stats.fw_crash_counter); | ||
647 | len += scnprintf(buf + len, buf_len - len, | ||
648 | "fw_warm_reset_counter\t\t%d\n", | ||
649 | ar->stats.fw_warm_reset_counter); | ||
650 | len += scnprintf(buf + len, buf_len - len, | ||
651 | "fw_cold_reset_counter\t\t%d\n", | ||
652 | ar->stats.fw_cold_reset_counter); | ||
653 | |||
654 | spin_unlock_bh(&ar->data_lock); | ||
655 | |||
656 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, len); | ||
657 | |||
658 | kfree(buf); | ||
659 | |||
660 | return ret; | ||
661 | } | ||
662 | |||
663 | static const struct file_operations fops_fw_reset_stats = { | ||
563 | .open = simple_open, | 664 | .open = simple_open, |
665 | .read = ath10k_debug_fw_reset_stats_read, | ||
564 | .owner = THIS_MODULE, | 666 | .owner = THIS_MODULE, |
565 | .llseek = default_llseek, | 667 | .llseek = default_llseek, |
566 | }; | 668 | }; |
@@ -593,7 +695,8 @@ static ssize_t ath10k_read_simulate_fw_crash(struct file *file, | |||
593 | "To simulate firmware crash write one of the keywords to this file:\n" | 695 | "To simulate firmware crash write one of the keywords to this file:\n" |
594 | "`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n" | 696 | "`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n" |
595 | "`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n" | 697 | "`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n" |
596 | "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"; | 698 | "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n" |
699 | "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n"; | ||
597 | 700 | ||
598 | return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); | 701 | return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); |
599 | } | 702 | } |
@@ -646,6 +749,10 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file, | |||
646 | } else if (!strcmp(buf, "assert")) { | 749 | } else if (!strcmp(buf, "assert")) { |
647 | ath10k_info(ar, "simulating firmware assert crash\n"); | 750 | ath10k_info(ar, "simulating firmware assert crash\n"); |
648 | ret = ath10k_debug_fw_assert(ar); | 751 | ret = ath10k_debug_fw_assert(ar); |
752 | } else if (!strcmp(buf, "hw-restart")) { | ||
753 | ath10k_info(ar, "user requested hw restart\n"); | ||
754 | queue_work(ar->workqueue, &ar->restart_work); | ||
755 | ret = 0; | ||
649 | } else { | 756 | } else { |
650 | ret = -EINVAL; | 757 | ret = -EINVAL; |
651 | goto exit; | 758 | goto exit; |
@@ -1029,6 +1136,166 @@ exit: | |||
1029 | return ret; | 1136 | return ret; |
1030 | } | 1137 | } |
1031 | 1138 | ||
1139 | /* TODO: Would be nice to always support ethtool stats, would need to | ||
1140 | * move the stats storage out of ath10k_debug, or always have ath10k_debug | ||
1141 | * struct available.. | ||
1142 | */ | ||
1143 | |||
1144 | /* This generally cooresponds to the debugfs fw_stats file */ | ||
1145 | static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = { | ||
1146 | "tx_pkts_nic", | ||
1147 | "tx_bytes_nic", | ||
1148 | "rx_pkts_nic", | ||
1149 | "rx_bytes_nic", | ||
1150 | "d_noise_floor", | ||
1151 | "d_cycle_count", | ||
1152 | "d_phy_error", | ||
1153 | "d_rts_bad", | ||
1154 | "d_rts_good", | ||
1155 | "d_tx_power", /* in .5 dbM I think */ | ||
1156 | "d_rx_crc_err", /* fcs_bad */ | ||
1157 | "d_no_beacon", | ||
1158 | "d_tx_mpdus_queued", | ||
1159 | "d_tx_msdu_queued", | ||
1160 | "d_tx_msdu_dropped", | ||
1161 | "d_local_enqued", | ||
1162 | "d_local_freed", | ||
1163 | "d_tx_ppdu_hw_queued", | ||
1164 | "d_tx_ppdu_reaped", | ||
1165 | "d_tx_fifo_underrun", | ||
1166 | "d_tx_ppdu_abort", | ||
1167 | "d_tx_mpdu_requed", | ||
1168 | "d_tx_excessive_retries", | ||
1169 | "d_tx_hw_rate", | ||
1170 | "d_tx_dropped_sw_retries", | ||
1171 | "d_tx_illegal_rate", | ||
1172 | "d_tx_continuous_xretries", | ||
1173 | "d_tx_timeout", | ||
1174 | "d_tx_mpdu_txop_limit", | ||
1175 | "d_pdev_resets", | ||
1176 | "d_rx_mid_ppdu_route_change", | ||
1177 | "d_rx_status", | ||
1178 | "d_rx_extra_frags_ring0", | ||
1179 | "d_rx_extra_frags_ring1", | ||
1180 | "d_rx_extra_frags_ring2", | ||
1181 | "d_rx_extra_frags_ring3", | ||
1182 | "d_rx_msdu_htt", | ||
1183 | "d_rx_mpdu_htt", | ||
1184 | "d_rx_msdu_stack", | ||
1185 | "d_rx_mpdu_stack", | ||
1186 | "d_rx_phy_err", | ||
1187 | "d_rx_phy_err_drops", | ||
1188 | "d_rx_mpdu_errors", /* FCS, MIC, ENC */ | ||
1189 | "d_fw_crash_count", | ||
1190 | "d_fw_warm_reset_count", | ||
1191 | "d_fw_cold_reset_count", | ||
1192 | }; | ||
1193 | |||
1194 | #define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats) | ||
1195 | |||
1196 | void ath10k_debug_get_et_strings(struct ieee80211_hw *hw, | ||
1197 | struct ieee80211_vif *vif, | ||
1198 | u32 sset, u8 *data) | ||
1199 | { | ||
1200 | if (sset == ETH_SS_STATS) | ||
1201 | memcpy(data, *ath10k_gstrings_stats, | ||
1202 | sizeof(ath10k_gstrings_stats)); | ||
1203 | } | ||
1204 | |||
1205 | int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw, | ||
1206 | struct ieee80211_vif *vif, int sset) | ||
1207 | { | ||
1208 | if (sset == ETH_SS_STATS) | ||
1209 | return ATH10K_SSTATS_LEN; | ||
1210 | |||
1211 | return 0; | ||
1212 | } | ||
1213 | |||
1214 | void ath10k_debug_get_et_stats(struct ieee80211_hw *hw, | ||
1215 | struct ieee80211_vif *vif, | ||
1216 | struct ethtool_stats *stats, u64 *data) | ||
1217 | { | ||
1218 | struct ath10k *ar = hw->priv; | ||
1219 | static const struct ath10k_fw_stats_pdev zero_stats = {}; | ||
1220 | const struct ath10k_fw_stats_pdev *pdev_stats; | ||
1221 | int i = 0, ret; | ||
1222 | |||
1223 | mutex_lock(&ar->conf_mutex); | ||
1224 | |||
1225 | if (ar->state == ATH10K_STATE_ON) { | ||
1226 | ret = ath10k_debug_fw_stats_request(ar); | ||
1227 | if (ret) { | ||
1228 | /* just print a warning and try to use older results */ | ||
1229 | ath10k_warn(ar, | ||
1230 | "failed to get fw stats for ethtool: %d\n", | ||
1231 | ret); | ||
1232 | } | ||
1233 | } | ||
1234 | |||
1235 | pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs, | ||
1236 | struct ath10k_fw_stats_pdev, | ||
1237 | list); | ||
1238 | if (!pdev_stats) { | ||
1239 | /* no results available so just return zeroes */ | ||
1240 | pdev_stats = &zero_stats; | ||
1241 | } | ||
1242 | |||
1243 | spin_lock_bh(&ar->data_lock); | ||
1244 | |||
1245 | data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */ | ||
1246 | data[i++] = 0; /* tx bytes */ | ||
1247 | data[i++] = pdev_stats->htt_mpdus; | ||
1248 | data[i++] = 0; /* rx bytes */ | ||
1249 | data[i++] = pdev_stats->ch_noise_floor; | ||
1250 | data[i++] = pdev_stats->cycle_count; | ||
1251 | data[i++] = pdev_stats->phy_err_count; | ||
1252 | data[i++] = pdev_stats->rts_bad; | ||
1253 | data[i++] = pdev_stats->rts_good; | ||
1254 | data[i++] = pdev_stats->chan_tx_power; | ||
1255 | data[i++] = pdev_stats->fcs_bad; | ||
1256 | data[i++] = pdev_stats->no_beacons; | ||
1257 | data[i++] = pdev_stats->mpdu_enqued; | ||
1258 | data[i++] = pdev_stats->msdu_enqued; | ||
1259 | data[i++] = pdev_stats->wmm_drop; | ||
1260 | data[i++] = pdev_stats->local_enqued; | ||
1261 | data[i++] = pdev_stats->local_freed; | ||
1262 | data[i++] = pdev_stats->hw_queued; | ||
1263 | data[i++] = pdev_stats->hw_reaped; | ||
1264 | data[i++] = pdev_stats->underrun; | ||
1265 | data[i++] = pdev_stats->tx_abort; | ||
1266 | data[i++] = pdev_stats->mpdus_requed; | ||
1267 | data[i++] = pdev_stats->tx_ko; | ||
1268 | data[i++] = pdev_stats->data_rc; | ||
1269 | data[i++] = pdev_stats->sw_retry_failure; | ||
1270 | data[i++] = pdev_stats->illgl_rate_phy_err; | ||
1271 | data[i++] = pdev_stats->pdev_cont_xretry; | ||
1272 | data[i++] = pdev_stats->pdev_tx_timeout; | ||
1273 | data[i++] = pdev_stats->txop_ovf; | ||
1274 | data[i++] = pdev_stats->pdev_resets; | ||
1275 | data[i++] = pdev_stats->mid_ppdu_route_change; | ||
1276 | data[i++] = pdev_stats->status_rcvd; | ||
1277 | data[i++] = pdev_stats->r0_frags; | ||
1278 | data[i++] = pdev_stats->r1_frags; | ||
1279 | data[i++] = pdev_stats->r2_frags; | ||
1280 | data[i++] = pdev_stats->r3_frags; | ||
1281 | data[i++] = pdev_stats->htt_msdus; | ||
1282 | data[i++] = pdev_stats->htt_mpdus; | ||
1283 | data[i++] = pdev_stats->loc_msdus; | ||
1284 | data[i++] = pdev_stats->loc_mpdus; | ||
1285 | data[i++] = pdev_stats->phy_errs; | ||
1286 | data[i++] = pdev_stats->phy_err_drop; | ||
1287 | data[i++] = pdev_stats->mpdu_errs; | ||
1288 | data[i++] = ar->stats.fw_crash_counter; | ||
1289 | data[i++] = ar->stats.fw_warm_reset_counter; | ||
1290 | data[i++] = ar->stats.fw_cold_reset_counter; | ||
1291 | |||
1292 | spin_unlock_bh(&ar->data_lock); | ||
1293 | |||
1294 | mutex_unlock(&ar->conf_mutex); | ||
1295 | |||
1296 | WARN_ON(i != ATH10K_SSTATS_LEN); | ||
1297 | } | ||
1298 | |||
1032 | static const struct file_operations fops_fw_dbglog = { | 1299 | static const struct file_operations fops_fw_dbglog = { |
1033 | .read = ath10k_read_fw_dbglog, | 1300 | .read = ath10k_read_fw_dbglog, |
1034 | .write = ath10k_write_fw_dbglog, | 1301 | .write = ath10k_write_fw_dbglog, |
@@ -1037,6 +1304,84 @@ static const struct file_operations fops_fw_dbglog = { | |||
1037 | .llseek = default_llseek, | 1304 | .llseek = default_llseek, |
1038 | }; | 1305 | }; |
1039 | 1306 | ||
1307 | static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file) | ||
1308 | { | ||
1309 | struct ath10k *ar = inode->i_private; | ||
1310 | void *buf; | ||
1311 | u32 hi_addr; | ||
1312 | __le32 addr; | ||
1313 | int ret; | ||
1314 | |||
1315 | mutex_lock(&ar->conf_mutex); | ||
1316 | |||
1317 | if (ar->state != ATH10K_STATE_ON && | ||
1318 | ar->state != ATH10K_STATE_UTF) { | ||
1319 | ret = -ENETDOWN; | ||
1320 | goto err; | ||
1321 | } | ||
1322 | |||
1323 | buf = vmalloc(QCA988X_CAL_DATA_LEN); | ||
1324 | if (!buf) { | ||
1325 | ret = -ENOMEM; | ||
1326 | goto err; | ||
1327 | } | ||
1328 | |||
1329 | hi_addr = host_interest_item_address(HI_ITEM(hi_board_data)); | ||
1330 | |||
1331 | ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr)); | ||
1332 | if (ret) { | ||
1333 | ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret); | ||
1334 | goto err_vfree; | ||
1335 | } | ||
1336 | |||
1337 | ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf, | ||
1338 | QCA988X_CAL_DATA_LEN); | ||
1339 | if (ret) { | ||
1340 | ath10k_warn(ar, "failed to read calibration data: %d\n", ret); | ||
1341 | goto err_vfree; | ||
1342 | } | ||
1343 | |||
1344 | file->private_data = buf; | ||
1345 | |||
1346 | mutex_unlock(&ar->conf_mutex); | ||
1347 | |||
1348 | return 0; | ||
1349 | |||
1350 | err_vfree: | ||
1351 | vfree(buf); | ||
1352 | |||
1353 | err: | ||
1354 | mutex_unlock(&ar->conf_mutex); | ||
1355 | |||
1356 | return ret; | ||
1357 | } | ||
1358 | |||
1359 | static ssize_t ath10k_debug_cal_data_read(struct file *file, | ||
1360 | char __user *user_buf, | ||
1361 | size_t count, loff_t *ppos) | ||
1362 | { | ||
1363 | void *buf = file->private_data; | ||
1364 | |||
1365 | return simple_read_from_buffer(user_buf, count, ppos, | ||
1366 | buf, QCA988X_CAL_DATA_LEN); | ||
1367 | } | ||
1368 | |||
1369 | static int ath10k_debug_cal_data_release(struct inode *inode, | ||
1370 | struct file *file) | ||
1371 | { | ||
1372 | vfree(file->private_data); | ||
1373 | |||
1374 | return 0; | ||
1375 | } | ||
1376 | |||
1377 | static const struct file_operations fops_cal_data = { | ||
1378 | .open = ath10k_debug_cal_data_open, | ||
1379 | .read = ath10k_debug_cal_data_read, | ||
1380 | .release = ath10k_debug_cal_data_release, | ||
1381 | .owner = THIS_MODULE, | ||
1382 | .llseek = default_llseek, | ||
1383 | }; | ||
1384 | |||
1040 | int ath10k_debug_start(struct ath10k *ar) | 1385 | int ath10k_debug_start(struct ath10k *ar) |
1041 | { | 1386 | { |
1042 | int ret; | 1387 | int ret; |
@@ -1057,7 +1402,22 @@ int ath10k_debug_start(struct ath10k *ar) | |||
1057 | ret); | 1402 | ret); |
1058 | } | 1403 | } |
1059 | 1404 | ||
1060 | return 0; | 1405 | if (ar->debug.pktlog_filter) { |
1406 | ret = ath10k_wmi_pdev_pktlog_enable(ar, | ||
1407 | ar->debug.pktlog_filter); | ||
1408 | if (ret) | ||
1409 | /* not serious */ | ||
1410 | ath10k_warn(ar, | ||
1411 | "failed to enable pktlog filter %x: %d\n", | ||
1412 | ar->debug.pktlog_filter, ret); | ||
1413 | } else { | ||
1414 | ret = ath10k_wmi_pdev_pktlog_disable(ar); | ||
1415 | if (ret) | ||
1416 | /* not serious */ | ||
1417 | ath10k_warn(ar, "failed to disable pktlog: %d\n", ret); | ||
1418 | } | ||
1419 | |||
1420 | return ret; | ||
1061 | } | 1421 | } |
1062 | 1422 | ||
1063 | void ath10k_debug_stop(struct ath10k *ar) | 1423 | void ath10k_debug_stop(struct ath10k *ar) |
@@ -1072,6 +1432,8 @@ void ath10k_debug_stop(struct ath10k *ar) | |||
1072 | 1432 | ||
1073 | ar->debug.htt_max_amsdu = 0; | 1433 | ar->debug.htt_max_amsdu = 0; |
1074 | ar->debug.htt_max_ampdu = 0; | 1434 | ar->debug.htt_max_ampdu = 0; |
1435 | |||
1436 | ath10k_wmi_pdev_pktlog_disable(ar); | ||
1075 | } | 1437 | } |
1076 | 1438 | ||
1077 | static ssize_t ath10k_write_simulate_radar(struct file *file, | 1439 | static ssize_t ath10k_write_simulate_radar(struct file *file, |
@@ -1154,12 +1516,78 @@ static const struct file_operations fops_dfs_stats = { | |||
1154 | .llseek = default_llseek, | 1516 | .llseek = default_llseek, |
1155 | }; | 1517 | }; |
1156 | 1518 | ||
1519 | static ssize_t ath10k_write_pktlog_filter(struct file *file, | ||
1520 | const char __user *ubuf, | ||
1521 | size_t count, loff_t *ppos) | ||
1522 | { | ||
1523 | struct ath10k *ar = file->private_data; | ||
1524 | u32 filter; | ||
1525 | int ret; | ||
1526 | |||
1527 | if (kstrtouint_from_user(ubuf, count, 0, &filter)) | ||
1528 | return -EINVAL; | ||
1529 | |||
1530 | mutex_lock(&ar->conf_mutex); | ||
1531 | |||
1532 | if (ar->state != ATH10K_STATE_ON) { | ||
1533 | ar->debug.pktlog_filter = filter; | ||
1534 | ret = count; | ||
1535 | goto out; | ||
1536 | } | ||
1537 | |||
1538 | if (filter && (filter != ar->debug.pktlog_filter)) { | ||
1539 | ret = ath10k_wmi_pdev_pktlog_enable(ar, filter); | ||
1540 | if (ret) { | ||
1541 | ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n", | ||
1542 | ar->debug.pktlog_filter, ret); | ||
1543 | goto out; | ||
1544 | } | ||
1545 | } else { | ||
1546 | ret = ath10k_wmi_pdev_pktlog_disable(ar); | ||
1547 | if (ret) { | ||
1548 | ath10k_warn(ar, "failed to disable pktlog: %d\n", ret); | ||
1549 | goto out; | ||
1550 | } | ||
1551 | } | ||
1552 | |||
1553 | ar->debug.pktlog_filter = filter; | ||
1554 | ret = count; | ||
1555 | |||
1556 | out: | ||
1557 | mutex_unlock(&ar->conf_mutex); | ||
1558 | return ret; | ||
1559 | } | ||
1560 | |||
1561 | static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf, | ||
1562 | size_t count, loff_t *ppos) | ||
1563 | { | ||
1564 | char buf[32]; | ||
1565 | struct ath10k *ar = file->private_data; | ||
1566 | int len = 0; | ||
1567 | |||
1568 | mutex_lock(&ar->conf_mutex); | ||
1569 | len = scnprintf(buf, sizeof(buf) - len, "%08x\n", | ||
1570 | ar->debug.pktlog_filter); | ||
1571 | mutex_unlock(&ar->conf_mutex); | ||
1572 | |||
1573 | return simple_read_from_buffer(ubuf, count, ppos, buf, len); | ||
1574 | } | ||
1575 | |||
1576 | static const struct file_operations fops_pktlog_filter = { | ||
1577 | .read = ath10k_read_pktlog_filter, | ||
1578 | .write = ath10k_write_pktlog_filter, | ||
1579 | .open = simple_open | ||
1580 | }; | ||
1581 | |||
1157 | int ath10k_debug_create(struct ath10k *ar) | 1582 | int ath10k_debug_create(struct ath10k *ar) |
1158 | { | 1583 | { |
1159 | ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data)); | 1584 | ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data)); |
1160 | if (!ar->debug.fw_crash_data) | 1585 | if (!ar->debug.fw_crash_data) |
1161 | return -ENOMEM; | 1586 | return -ENOMEM; |
1162 | 1587 | ||
1588 | INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs); | ||
1589 | INIT_LIST_HEAD(&ar->debug.fw_stats.peers); | ||
1590 | |||
1163 | return 0; | 1591 | return 0; |
1164 | } | 1592 | } |
1165 | 1593 | ||
@@ -1167,6 +1595,8 @@ void ath10k_debug_destroy(struct ath10k *ar) | |||
1167 | { | 1595 | { |
1168 | vfree(ar->debug.fw_crash_data); | 1596 | vfree(ar->debug.fw_crash_data); |
1169 | ar->debug.fw_crash_data = NULL; | 1597 | ar->debug.fw_crash_data = NULL; |
1598 | |||
1599 | ath10k_debug_fw_stats_reset(ar); | ||
1170 | } | 1600 | } |
1171 | 1601 | ||
1172 | int ath10k_debug_register(struct ath10k *ar) | 1602 | int ath10k_debug_register(struct ath10k *ar) |
@@ -1183,11 +1613,14 @@ int ath10k_debug_register(struct ath10k *ar) | |||
1183 | INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork, | 1613 | INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork, |
1184 | ath10k_debug_htt_stats_dwork); | 1614 | ath10k_debug_htt_stats_dwork); |
1185 | 1615 | ||
1186 | init_completion(&ar->debug.event_stats_compl); | 1616 | init_completion(&ar->debug.fw_stats_complete); |
1187 | 1617 | ||
1188 | debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar, | 1618 | debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar, |
1189 | &fops_fw_stats); | 1619 | &fops_fw_stats); |
1190 | 1620 | ||
1621 | debugfs_create_file("fw_reset_stats", S_IRUSR, ar->debug.debugfs_phy, | ||
1622 | ar, &fops_fw_reset_stats); | ||
1623 | |||
1191 | debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar, | 1624 | debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar, |
1192 | &fops_wmi_services); | 1625 | &fops_wmi_services); |
1193 | 1626 | ||
@@ -1210,6 +1643,9 @@ int ath10k_debug_register(struct ath10k *ar) | |||
1210 | debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy, | 1643 | debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy, |
1211 | ar, &fops_fw_dbglog); | 1644 | ar, &fops_fw_dbglog); |
1212 | 1645 | ||
1646 | debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy, | ||
1647 | ar, &fops_cal_data); | ||
1648 | |||
1213 | if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) { | 1649 | if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) { |
1214 | debugfs_create_file("dfs_simulate_radar", S_IWUSR, | 1650 | debugfs_create_file("dfs_simulate_radar", S_IWUSR, |
1215 | ar->debug.debugfs_phy, ar, | 1651 | ar->debug.debugfs_phy, ar, |
@@ -1224,6 +1660,9 @@ int ath10k_debug_register(struct ath10k *ar) | |||
1224 | &fops_dfs_stats); | 1660 | &fops_dfs_stats); |
1225 | } | 1661 | } |
1226 | 1662 | ||
1663 | debugfs_create_file("pktlog_filter", S_IRUGO | S_IWUSR, | ||
1664 | ar->debug.debugfs_phy, ar, &fops_pktlog_filter); | ||
1665 | |||
1227 | return 0; | 1666 | return 0; |
1228 | } | 1667 | } |
1229 | 1668 | ||
@@ -1260,11 +1699,26 @@ void ath10k_dbg_dump(struct ath10k *ar, | |||
1260 | const char *msg, const char *prefix, | 1699 | const char *msg, const char *prefix, |
1261 | const void *buf, size_t len) | 1700 | const void *buf, size_t len) |
1262 | { | 1701 | { |
1702 | char linebuf[256]; | ||
1703 | unsigned int linebuflen; | ||
1704 | const void *ptr; | ||
1705 | |||
1263 | if (ath10k_debug_mask & mask) { | 1706 | if (ath10k_debug_mask & mask) { |
1264 | if (msg) | 1707 | if (msg) |
1265 | ath10k_dbg(ar, mask, "%s\n", msg); | 1708 | ath10k_dbg(ar, mask, "%s\n", msg); |
1266 | 1709 | ||
1267 | print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); | 1710 | for (ptr = buf; (ptr - buf) < len; ptr += 16) { |
1711 | linebuflen = 0; | ||
1712 | linebuflen += scnprintf(linebuf + linebuflen, | ||
1713 | sizeof(linebuf) - linebuflen, | ||
1714 | "%s%08x: ", | ||
1715 | (prefix ? prefix : ""), | ||
1716 | (unsigned int)(ptr - buf)); | ||
1717 | hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1, | ||
1718 | linebuf + linebuflen, | ||
1719 | sizeof(linebuf) - linebuflen, true); | ||
1720 | dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf); | ||
1721 | } | ||
1268 | } | 1722 | } |
1269 | 1723 | ||
1270 | /* tracing code doesn't like null strings :/ */ | 1724 | /* tracing code doesn't like null strings :/ */ |
diff --git a/drivers/net/wireless/ath/ath10k/debug.h b/drivers/net/wireless/ath/ath10k/debug.h index b3774f7f492c..0c934a8378db 100644 --- a/drivers/net/wireless/ath/ath10k/debug.h +++ b/drivers/net/wireless/ath/ath10k/debug.h | |||
@@ -38,11 +38,20 @@ enum ath10k_debug_mask { | |||
38 | ATH10K_DBG_ANY = 0xffffffff, | 38 | ATH10K_DBG_ANY = 0xffffffff, |
39 | }; | 39 | }; |
40 | 40 | ||
41 | enum ath10k_pktlog_filter { | ||
42 | ATH10K_PKTLOG_RX = 0x000000001, | ||
43 | ATH10K_PKTLOG_TX = 0x000000002, | ||
44 | ATH10K_PKTLOG_RCFIND = 0x000000004, | ||
45 | ATH10K_PKTLOG_RCUPDATE = 0x000000008, | ||
46 | ATH10K_PKTLOG_DBG_PRINT = 0x000000010, | ||
47 | ATH10K_PKTLOG_ANY = 0x00000001f, | ||
48 | }; | ||
49 | |||
41 | extern unsigned int ath10k_debug_mask; | 50 | extern unsigned int ath10k_debug_mask; |
42 | 51 | ||
43 | __printf(2, 3) int ath10k_info(struct ath10k *ar, const char *fmt, ...); | 52 | __printf(2, 3) void ath10k_info(struct ath10k *ar, const char *fmt, ...); |
44 | __printf(2, 3) int ath10k_err(struct ath10k *ar, const char *fmt, ...); | 53 | __printf(2, 3) void ath10k_err(struct ath10k *ar, const char *fmt, ...); |
45 | __printf(2, 3) int ath10k_warn(struct ath10k *ar, const char *fmt, ...); | 54 | __printf(2, 3) void ath10k_warn(struct ath10k *ar, const char *fmt, ...); |
46 | void ath10k_print_driver_info(struct ath10k *ar); | 55 | void ath10k_print_driver_info(struct ath10k *ar); |
47 | 56 | ||
48 | #ifdef CONFIG_ATH10K_DEBUGFS | 57 | #ifdef CONFIG_ATH10K_DEBUGFS |
@@ -53,17 +62,24 @@ void ath10k_debug_destroy(struct ath10k *ar); | |||
53 | int ath10k_debug_register(struct ath10k *ar); | 62 | int ath10k_debug_register(struct ath10k *ar); |
54 | void ath10k_debug_unregister(struct ath10k *ar); | 63 | void ath10k_debug_unregister(struct ath10k *ar); |
55 | void ath10k_debug_read_service_map(struct ath10k *ar, | 64 | void ath10k_debug_read_service_map(struct ath10k *ar, |
56 | void *service_map, | 65 | const void *service_map, |
57 | size_t map_size); | 66 | size_t map_size); |
58 | void ath10k_debug_read_target_stats(struct ath10k *ar, | 67 | void ath10k_debug_fw_stats_process(struct ath10k *ar, struct sk_buff *skb); |
59 | struct wmi_stats_event *ev); | ||
60 | struct ath10k_fw_crash_data * | 68 | struct ath10k_fw_crash_data * |
61 | ath10k_debug_get_new_fw_crash_data(struct ath10k *ar); | 69 | ath10k_debug_get_new_fw_crash_data(struct ath10k *ar); |
62 | 70 | ||
63 | void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len); | 71 | void ath10k_debug_dbglog_add(struct ath10k *ar, u8 *buffer, int len); |
64 | |||
65 | #define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++) | 72 | #define ATH10K_DFS_STAT_INC(ar, c) (ar->debug.dfs_stats.c++) |
66 | 73 | ||
74 | void ath10k_debug_get_et_strings(struct ieee80211_hw *hw, | ||
75 | struct ieee80211_vif *vif, | ||
76 | u32 sset, u8 *data); | ||
77 | int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw, | ||
78 | struct ieee80211_vif *vif, int sset); | ||
79 | void ath10k_debug_get_et_stats(struct ieee80211_hw *hw, | ||
80 | struct ieee80211_vif *vif, | ||
81 | struct ethtool_stats *stats, u64 *data); | ||
82 | |||
67 | #else | 83 | #else |
68 | static inline int ath10k_debug_start(struct ath10k *ar) | 84 | static inline int ath10k_debug_start(struct ath10k *ar) |
69 | { | 85 | { |
@@ -93,13 +109,13 @@ static inline void ath10k_debug_unregister(struct ath10k *ar) | |||
93 | } | 109 | } |
94 | 110 | ||
95 | static inline void ath10k_debug_read_service_map(struct ath10k *ar, | 111 | static inline void ath10k_debug_read_service_map(struct ath10k *ar, |
96 | void *service_map, | 112 | const void *service_map, |
97 | size_t map_size) | 113 | size_t map_size) |
98 | { | 114 | { |
99 | } | 115 | } |
100 | 116 | ||
101 | static inline void ath10k_debug_read_target_stats(struct ath10k *ar, | 117 | static inline void ath10k_debug_fw_stats_process(struct ath10k *ar, |
102 | struct wmi_stats_event *ev) | 118 | struct sk_buff *skb) |
103 | { | 119 | { |
104 | } | 120 | } |
105 | 121 | ||
@@ -116,6 +132,10 @@ ath10k_debug_get_new_fw_crash_data(struct ath10k *ar) | |||
116 | 132 | ||
117 | #define ATH10K_DFS_STAT_INC(ar, c) do { } while (0) | 133 | #define ATH10K_DFS_STAT_INC(ar, c) do { } while (0) |
118 | 134 | ||
135 | #define ath10k_debug_get_et_strings NULL | ||
136 | #define ath10k_debug_get_et_sset_count NULL | ||
137 | #define ath10k_debug_get_et_stats NULL | ||
138 | |||
119 | #endif /* CONFIG_ATH10K_DEBUGFS */ | 139 | #endif /* CONFIG_ATH10K_DEBUGFS */ |
120 | 140 | ||
121 | #ifdef CONFIG_ATH10K_DEBUG | 141 | #ifdef CONFIG_ATH10K_DEBUG |
diff --git a/drivers/net/wireless/ath/ath10k/hif.h b/drivers/net/wireless/ath/ath10k/hif.h index 62323fea27e1..30301f5b6051 100644 --- a/drivers/net/wireless/ath/ath10k/hif.h +++ b/drivers/net/wireless/ath/ath10k/hif.h | |||
@@ -43,6 +43,10 @@ struct ath10k_hif_ops { | |||
43 | int (*tx_sg)(struct ath10k *ar, u8 pipe_id, | 43 | int (*tx_sg)(struct ath10k *ar, u8 pipe_id, |
44 | struct ath10k_hif_sg_item *items, int n_items); | 44 | struct ath10k_hif_sg_item *items, int n_items); |
45 | 45 | ||
46 | /* read firmware memory through the diagnose interface */ | ||
47 | int (*diag_read)(struct ath10k *ar, u32 address, void *buf, | ||
48 | size_t buf_len); | ||
49 | |||
46 | /* | 50 | /* |
47 | * API to handle HIF-specific BMI message exchanges, this API is | 51 | * API to handle HIF-specific BMI message exchanges, this API is |
48 | * synchronous and only allowed to be called from a context that | 52 | * synchronous and only allowed to be called from a context that |
@@ -98,6 +102,12 @@ static inline int ath10k_hif_tx_sg(struct ath10k *ar, u8 pipe_id, | |||
98 | return ar->hif.ops->tx_sg(ar, pipe_id, items, n_items); | 102 | return ar->hif.ops->tx_sg(ar, pipe_id, items, n_items); |
99 | } | 103 | } |
100 | 104 | ||
105 | static inline int ath10k_hif_diag_read(struct ath10k *ar, u32 address, void *buf, | ||
106 | size_t buf_len) | ||
107 | { | ||
108 | return ar->hif.ops->diag_read(ar, address, buf, buf_len); | ||
109 | } | ||
110 | |||
101 | static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar, | 111 | static inline int ath10k_hif_exchange_bmi_msg(struct ath10k *ar, |
102 | void *request, u32 request_len, | 112 | void *request, u32 request_len, |
103 | void *response, u32 *response_len) | 113 | void *response, u32 *response_len) |
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h index 3b44217a6c19..15c58e884b6a 100644 --- a/drivers/net/wireless/ath/ath10k/htt.h +++ b/drivers/net/wireless/ath/ath10k/htt.h | |||
@@ -725,7 +725,7 @@ static inline u8 *htt_rx_test_get_chars(struct htt_rx_test *rx_test) | |||
725 | */ | 725 | */ |
726 | struct htt_pktlog_msg { | 726 | struct htt_pktlog_msg { |
727 | u8 pad[3]; | 727 | u8 pad[3]; |
728 | __le32 payload[1 /* or more */]; | 728 | u8 payload[0]; |
729 | } __packed; | 729 | } __packed; |
730 | 730 | ||
731 | struct htt_dbg_stats_rx_reorder_stats { | 731 | struct htt_dbg_stats_rx_reorder_stats { |
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index 60d40a04508b..52c630672718 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c | |||
@@ -291,6 +291,13 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt) | |||
291 | htt->rx_ring.sw_rd_idx.msdu_payld = idx; | 291 | htt->rx_ring.sw_rd_idx.msdu_payld = idx; |
292 | htt->rx_ring.fill_cnt--; | 292 | htt->rx_ring.fill_cnt--; |
293 | 293 | ||
294 | dma_unmap_single(htt->ar->dev, | ||
295 | ATH10K_SKB_CB(msdu)->paddr, | ||
296 | msdu->len + skb_tailroom(msdu), | ||
297 | DMA_FROM_DEVICE); | ||
298 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx netbuf pop: ", | ||
299 | msdu->data, msdu->len + skb_tailroom(msdu)); | ||
300 | |||
294 | return msdu; | 301 | return msdu; |
295 | } | 302 | } |
296 | 303 | ||
@@ -328,14 +335,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, | |||
328 | while (msdu) { | 335 | while (msdu) { |
329 | int last_msdu, msdu_len_invalid, msdu_chained; | 336 | int last_msdu, msdu_len_invalid, msdu_chained; |
330 | 337 | ||
331 | dma_unmap_single(htt->ar->dev, | ||
332 | ATH10K_SKB_CB(msdu)->paddr, | ||
333 | msdu->len + skb_tailroom(msdu), | ||
334 | DMA_FROM_DEVICE); | ||
335 | |||
336 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx pop: ", | ||
337 | msdu->data, msdu->len + skb_tailroom(msdu)); | ||
338 | |||
339 | rx_desc = (struct htt_rx_desc *)msdu->data; | 338 | rx_desc = (struct htt_rx_desc *)msdu->data; |
340 | 339 | ||
341 | /* FIXME: we must report msdu payload since this is what caller | 340 | /* FIXME: we must report msdu payload since this is what caller |
@@ -426,14 +425,14 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, | |||
426 | while (msdu_chained--) { | 425 | while (msdu_chained--) { |
427 | struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt); | 426 | struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt); |
428 | 427 | ||
429 | dma_unmap_single(htt->ar->dev, | 428 | if (!next) { |
430 | ATH10K_SKB_CB(next)->paddr, | 429 | ath10k_warn(ar, "failed to pop chained msdu\n"); |
431 | next->len + skb_tailroom(next), | 430 | ath10k_htt_rx_free_msdu_chain(*head_msdu); |
432 | DMA_FROM_DEVICE); | 431 | *head_msdu = NULL; |
433 | 432 | msdu = NULL; | |
434 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, | 433 | htt->rx_confused = true; |
435 | "htt rx chained: ", next->data, | 434 | break; |
436 | next->len + skb_tailroom(next)); | 435 | } |
437 | 436 | ||
438 | skb_trim(next, 0); | 437 | skb_trim(next, 0); |
439 | skb_put(next, min(msdu_len, HTT_RX_BUF_SIZE)); | 438 | skb_put(next, min(msdu_len, HTT_RX_BUF_SIZE)); |
@@ -447,6 +446,8 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, | |||
447 | last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) & | 446 | last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) & |
448 | RX_MSDU_END_INFO0_LAST_MSDU; | 447 | RX_MSDU_END_INFO0_LAST_MSDU; |
449 | 448 | ||
449 | trace_ath10k_htt_rx_desc(ar, &rx_desc->attention, | ||
450 | sizeof(*rx_desc) - sizeof(u32)); | ||
450 | if (last_msdu) { | 451 | if (last_msdu) { |
451 | msdu->next = NULL; | 452 | msdu->next = NULL; |
452 | break; | 453 | break; |
@@ -492,6 +493,8 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) | |||
492 | size_t size; | 493 | size_t size; |
493 | struct timer_list *timer = &htt->rx_ring.refill_retry_timer; | 494 | struct timer_list *timer = &htt->rx_ring.refill_retry_timer; |
494 | 495 | ||
496 | htt->rx_confused = false; | ||
497 | |||
495 | htt->rx_ring.size = ath10k_htt_rx_ring_size(htt); | 498 | htt->rx_ring.size = ath10k_htt_rx_ring_size(htt); |
496 | if (!is_power_of_2(htt->rx_ring.size)) { | 499 | if (!is_power_of_2(htt->rx_ring.size)) { |
497 | ath10k_warn(ar, "htt rx ring size is not power of 2\n"); | 500 | ath10k_warn(ar, "htt rx ring size is not power of 2\n"); |
@@ -581,41 +584,47 @@ static int ath10k_htt_rx_crypto_param_len(struct ath10k *ar, | |||
581 | enum htt_rx_mpdu_encrypt_type type) | 584 | enum htt_rx_mpdu_encrypt_type type) |
582 | { | 585 | { |
583 | switch (type) { | 586 | switch (type) { |
587 | case HTT_RX_MPDU_ENCRYPT_NONE: | ||
588 | return 0; | ||
584 | case HTT_RX_MPDU_ENCRYPT_WEP40: | 589 | case HTT_RX_MPDU_ENCRYPT_WEP40: |
585 | case HTT_RX_MPDU_ENCRYPT_WEP104: | 590 | case HTT_RX_MPDU_ENCRYPT_WEP104: |
586 | return 4; | 591 | return IEEE80211_WEP_IV_LEN; |
587 | case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC: | 592 | case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC: |
588 | case HTT_RX_MPDU_ENCRYPT_WEP128: /* not tested */ | ||
589 | case HTT_RX_MPDU_ENCRYPT_TKIP_WPA: | 593 | case HTT_RX_MPDU_ENCRYPT_TKIP_WPA: |
590 | case HTT_RX_MPDU_ENCRYPT_WAPI: /* not tested */ | 594 | return IEEE80211_TKIP_IV_LEN; |
591 | case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: | 595 | case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: |
592 | return 8; | 596 | return IEEE80211_CCMP_HDR_LEN; |
593 | case HTT_RX_MPDU_ENCRYPT_NONE: | 597 | case HTT_RX_MPDU_ENCRYPT_WEP128: |
594 | return 0; | 598 | case HTT_RX_MPDU_ENCRYPT_WAPI: |
599 | break; | ||
595 | } | 600 | } |
596 | 601 | ||
597 | ath10k_warn(ar, "unknown encryption type %d\n", type); | 602 | ath10k_warn(ar, "unsupported encryption type %d\n", type); |
598 | return 0; | 603 | return 0; |
599 | } | 604 | } |
600 | 605 | ||
606 | #define MICHAEL_MIC_LEN 8 | ||
607 | |||
601 | static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar, | 608 | static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar, |
602 | enum htt_rx_mpdu_encrypt_type type) | 609 | enum htt_rx_mpdu_encrypt_type type) |
603 | { | 610 | { |
604 | switch (type) { | 611 | switch (type) { |
605 | case HTT_RX_MPDU_ENCRYPT_NONE: | 612 | case HTT_RX_MPDU_ENCRYPT_NONE: |
613 | return 0; | ||
606 | case HTT_RX_MPDU_ENCRYPT_WEP40: | 614 | case HTT_RX_MPDU_ENCRYPT_WEP40: |
607 | case HTT_RX_MPDU_ENCRYPT_WEP104: | 615 | case HTT_RX_MPDU_ENCRYPT_WEP104: |
608 | case HTT_RX_MPDU_ENCRYPT_WEP128: | 616 | return IEEE80211_WEP_ICV_LEN; |
609 | case HTT_RX_MPDU_ENCRYPT_WAPI: | ||
610 | return 0; | ||
611 | case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC: | 617 | case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC: |
612 | case HTT_RX_MPDU_ENCRYPT_TKIP_WPA: | 618 | case HTT_RX_MPDU_ENCRYPT_TKIP_WPA: |
613 | return 4; | 619 | return IEEE80211_TKIP_ICV_LEN; |
614 | case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: | 620 | case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: |
615 | return 8; | 621 | return IEEE80211_CCMP_MIC_LEN; |
622 | case HTT_RX_MPDU_ENCRYPT_WEP128: | ||
623 | case HTT_RX_MPDU_ENCRYPT_WAPI: | ||
624 | break; | ||
616 | } | 625 | } |
617 | 626 | ||
618 | ath10k_warn(ar, "unknown encryption type %d\n", type); | 627 | ath10k_warn(ar, "unsupported encryption type %d\n", type); |
619 | return 0; | 628 | return 0; |
620 | } | 629 | } |
621 | 630 | ||
@@ -892,6 +901,8 @@ static void ath10k_process_rx(struct ath10k *ar, | |||
892 | !!(status->flag & RX_FLAG_AMSDU_MORE)); | 901 | !!(status->flag & RX_FLAG_AMSDU_MORE)); |
893 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ", | 902 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ", |
894 | skb->data, skb->len); | 903 | skb->data, skb->len); |
904 | trace_ath10k_rx_hdr(ar, skb->data, skb->len); | ||
905 | trace_ath10k_rx_payload(ar, skb->data, skb->len); | ||
895 | 906 | ||
896 | ieee80211_rx(ar->hw, skb); | 907 | ieee80211_rx(ar->hw, skb); |
897 | } | 908 | } |
@@ -1169,7 +1180,6 @@ static int ath10k_unchain_msdu(struct sk_buff *msdu_head) | |||
1169 | 1180 | ||
1170 | static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt, | 1181 | static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt, |
1171 | struct sk_buff *head, | 1182 | struct sk_buff *head, |
1172 | enum htt_rx_mpdu_status status, | ||
1173 | bool channel_set, | 1183 | bool channel_set, |
1174 | u32 attention) | 1184 | u32 attention) |
1175 | { | 1185 | { |
@@ -1193,22 +1203,11 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt, | |||
1193 | } | 1203 | } |
1194 | 1204 | ||
1195 | /* Skip mgmt frames while we handle this in WMI */ | 1205 | /* Skip mgmt frames while we handle this in WMI */ |
1196 | if (status == HTT_RX_IND_MPDU_STATUS_MGMT_CTRL || | 1206 | if (attention & RX_ATTENTION_FLAGS_MGMT_TYPE) { |
1197 | attention & RX_ATTENTION_FLAGS_MGMT_TYPE) { | ||
1198 | ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx mgmt ctrl\n"); | 1207 | ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx mgmt ctrl\n"); |
1199 | return false; | 1208 | return false; |
1200 | } | 1209 | } |
1201 | 1210 | ||
1202 | if (status != HTT_RX_IND_MPDU_STATUS_OK && | ||
1203 | status != HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR && | ||
1204 | status != HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER && | ||
1205 | !htt->ar->monitor_started) { | ||
1206 | ath10k_dbg(ar, ATH10K_DBG_HTT, | ||
1207 | "htt rx ignoring frame w/ status %d\n", | ||
1208 | status); | ||
1209 | return false; | ||
1210 | } | ||
1211 | |||
1212 | if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) { | 1211 | if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) { |
1213 | ath10k_dbg(ar, ATH10K_DBG_HTT, | 1212 | ath10k_dbg(ar, ATH10K_DBG_HTT, |
1214 | "htt rx CAC running\n"); | 1213 | "htt rx CAC running\n"); |
@@ -1224,8 +1223,6 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
1224 | struct ath10k *ar = htt->ar; | 1223 | struct ath10k *ar = htt->ar; |
1225 | struct ieee80211_rx_status *rx_status = &htt->rx_status; | 1224 | struct ieee80211_rx_status *rx_status = &htt->rx_status; |
1226 | struct htt_rx_indication_mpdu_range *mpdu_ranges; | 1225 | struct htt_rx_indication_mpdu_range *mpdu_ranges; |
1227 | struct htt_rx_desc *rxd; | ||
1228 | enum htt_rx_mpdu_status status; | ||
1229 | struct ieee80211_hdr *hdr; | 1226 | struct ieee80211_hdr *hdr; |
1230 | int num_mpdu_ranges; | 1227 | int num_mpdu_ranges; |
1231 | u32 attention; | 1228 | u32 attention; |
@@ -1273,8 +1270,6 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
1273 | num_mpdu_ranges)); | 1270 | num_mpdu_ranges)); |
1274 | 1271 | ||
1275 | for (i = 0; i < num_mpdu_ranges; i++) { | 1272 | for (i = 0; i < num_mpdu_ranges; i++) { |
1276 | status = mpdu_ranges[i].mpdu_range_status; | ||
1277 | |||
1278 | for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) { | 1273 | for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) { |
1279 | struct sk_buff *msdu_head, *msdu_tail; | 1274 | struct sk_buff *msdu_head, *msdu_tail; |
1280 | 1275 | ||
@@ -1295,12 +1290,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
1295 | continue; | 1290 | continue; |
1296 | } | 1291 | } |
1297 | 1292 | ||
1298 | rxd = container_of((void *)msdu_head->data, | ||
1299 | struct htt_rx_desc, | ||
1300 | msdu_payload); | ||
1301 | |||
1302 | if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head, | 1293 | if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head, |
1303 | status, | ||
1304 | channel_set, | 1294 | channel_set, |
1305 | attention)) { | 1295 | attention)) { |
1306 | ath10k_htt_rx_free_msdu_chain(msdu_head); | 1296 | ath10k_htt_rx_free_msdu_chain(msdu_head); |
@@ -1365,6 +1355,8 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, | |||
1365 | &attention); | 1355 | &attention); |
1366 | spin_unlock_bh(&htt->rx_ring.lock); | 1356 | spin_unlock_bh(&htt->rx_ring.lock); |
1367 | 1357 | ||
1358 | tasklet_schedule(&htt->rx_replenish_task); | ||
1359 | |||
1368 | ath10k_dbg(ar, ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n"); | 1360 | ath10k_dbg(ar, ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n"); |
1369 | 1361 | ||
1370 | if (ret) { | 1362 | if (ret) { |
@@ -1426,7 +1418,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, | |||
1426 | /* last fragment of TKIP frags has MIC */ | 1418 | /* last fragment of TKIP frags has MIC */ |
1427 | if (!ieee80211_has_morefrags(hdr->frame_control) && | 1419 | if (!ieee80211_has_morefrags(hdr->frame_control) && |
1428 | enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) | 1420 | enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) |
1429 | trim += 8; | 1421 | trim += MICHAEL_MIC_LEN; |
1430 | 1422 | ||
1431 | if (trim > msdu_head->len) { | 1423 | if (trim > msdu_head->len) { |
1432 | ath10k_warn(ar, "htt rx fragment: trailer longer than the frame itself? drop\n"); | 1424 | ath10k_warn(ar, "htt rx fragment: trailer longer than the frame itself? drop\n"); |
@@ -1674,6 +1666,15 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
1674 | case HTT_T2H_MSG_TYPE_RX_DELBA: | 1666 | case HTT_T2H_MSG_TYPE_RX_DELBA: |
1675 | ath10k_htt_rx_delba(ar, resp); | 1667 | ath10k_htt_rx_delba(ar, resp); |
1676 | break; | 1668 | break; |
1669 | case HTT_T2H_MSG_TYPE_PKTLOG: { | ||
1670 | struct ath10k_pktlog_hdr *hdr = | ||
1671 | (struct ath10k_pktlog_hdr *)resp->pktlog_msg.payload; | ||
1672 | |||
1673 | trace_ath10k_htt_pktlog(ar, resp->pktlog_msg.payload, | ||
1674 | sizeof(*hdr) + | ||
1675 | __le16_to_cpu(hdr->size)); | ||
1676 | break; | ||
1677 | } | ||
1677 | case HTT_T2H_MSG_TYPE_RX_FLUSH: { | 1678 | case HTT_T2H_MSG_TYPE_RX_FLUSH: { |
1678 | /* Ignore this event because mac80211 takes care of Rx | 1679 | /* Ignore this event because mac80211 takes care of Rx |
1679 | * aggregation reordering. | 1680 | * aggregation reordering. |
@@ -1681,8 +1682,8 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
1681 | break; | 1682 | break; |
1682 | } | 1683 | } |
1683 | default: | 1684 | default: |
1684 | ath10k_dbg(ar, ATH10K_DBG_HTT, "htt event (%d) not handled\n", | 1685 | ath10k_warn(ar, "htt event (%d) not handled\n", |
1685 | resp->hdr.msg_type); | 1686 | resp->hdr.msg_type); |
1686 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ", | 1687 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ", |
1687 | skb->data, skb->len); | 1688 | skb->data, skb->len); |
1688 | break; | 1689 | break; |
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index bd87a35201d8..5b7e42f7377c 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c | |||
@@ -92,7 +92,6 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) | |||
92 | struct ath10k *ar = htt->ar; | 92 | struct ath10k *ar = htt->ar; |
93 | 93 | ||
94 | spin_lock_init(&htt->tx_lock); | 94 | spin_lock_init(&htt->tx_lock); |
95 | init_waitqueue_head(&htt->empty_tx_wq); | ||
96 | 95 | ||
97 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, htt->ar->fw_features)) | 96 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, htt->ar->fw_features)) |
98 | htt->max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC; | 97 | htt->max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC; |
@@ -557,12 +556,15 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
557 | skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr); | 556 | skb_cb->htt.txbuf->cmd_tx.frags_paddr = __cpu_to_le32(frags_paddr); |
558 | skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le32(HTT_INVALID_PEERID); | 557 | skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le32(HTT_INVALID_PEERID); |
559 | 558 | ||
559 | trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid); | ||
560 | ath10k_dbg(ar, ATH10K_DBG_HTT, | 560 | ath10k_dbg(ar, ATH10K_DBG_HTT, |
561 | "htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu\n", | 561 | "htt tx flags0 %hhu flags1 %hu len %d id %hu frags_paddr %08x, msdu_paddr %08x vdev %hhu tid %hhu\n", |
562 | flags0, flags1, msdu->len, msdu_id, frags_paddr, | 562 | flags0, flags1, msdu->len, msdu_id, frags_paddr, |
563 | (u32)skb_cb->paddr, vdev_id, tid); | 563 | (u32)skb_cb->paddr, vdev_id, tid); |
564 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ", | 564 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ", |
565 | msdu->data, msdu->len); | 565 | msdu->data, msdu->len); |
566 | trace_ath10k_tx_hdr(ar, msdu->data, msdu->len); | ||
567 | trace_ath10k_tx_payload(ar, msdu->data, msdu->len); | ||
566 | 568 | ||
567 | sg_items[0].transfer_id = 0; | 569 | sg_items[0].transfer_id = 0; |
568 | sg_items[0].transfer_context = NULL; | 570 | sg_items[0].transfer_context = NULL; |
diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index 3cf5702c1e7e..392c2501d0a1 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h | |||
@@ -20,15 +20,16 @@ | |||
20 | 20 | ||
21 | #include "targaddrs.h" | 21 | #include "targaddrs.h" |
22 | 22 | ||
23 | #define ATH10K_FW_DIR "ath10k" | ||
24 | |||
23 | /* QCA988X 1.0 definitions (unsupported) */ | 25 | /* QCA988X 1.0 definitions (unsupported) */ |
24 | #define QCA988X_HW_1_0_CHIP_ID_REV 0x0 | 26 | #define QCA988X_HW_1_0_CHIP_ID_REV 0x0 |
25 | 27 | ||
26 | /* QCA988X 2.0 definitions */ | 28 | /* QCA988X 2.0 definitions */ |
27 | #define QCA988X_HW_2_0_VERSION 0x4100016c | 29 | #define QCA988X_HW_2_0_VERSION 0x4100016c |
28 | #define QCA988X_HW_2_0_CHIP_ID_REV 0x2 | 30 | #define QCA988X_HW_2_0_CHIP_ID_REV 0x2 |
29 | #define QCA988X_HW_2_0_FW_DIR "ath10k/QCA988X/hw2.0" | 31 | #define QCA988X_HW_2_0_FW_DIR ATH10K_FW_DIR "/QCA988X/hw2.0" |
30 | #define QCA988X_HW_2_0_FW_FILE "firmware.bin" | 32 | #define QCA988X_HW_2_0_FW_FILE "firmware.bin" |
31 | #define QCA988X_HW_2_0_FW_3_FILE "firmware-3.bin" | ||
32 | #define QCA988X_HW_2_0_OTP_FILE "otp.bin" | 33 | #define QCA988X_HW_2_0_OTP_FILE "otp.bin" |
33 | #define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin" | 34 | #define QCA988X_HW_2_0_BOARD_DATA_FILE "board.bin" |
34 | #define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234 | 35 | #define QCA988X_HW_2_0_PATCH_LOAD_ADDR 0x1234 |
@@ -43,6 +44,8 @@ | |||
43 | 44 | ||
44 | #define REG_DUMP_COUNT_QCA988X 60 | 45 | #define REG_DUMP_COUNT_QCA988X 60 |
45 | 46 | ||
47 | #define QCA988X_CAL_DATA_LEN 2116 | ||
48 | |||
46 | struct ath10k_fw_ie { | 49 | struct ath10k_fw_ie { |
47 | __le32 id; | 50 | __le32 id; |
48 | __le32 len; | 51 | __le32 len; |
@@ -78,6 +81,15 @@ enum ath10k_mcast2ucast_mode { | |||
78 | ATH10K_MCAST2UCAST_ENABLED = 1, | 81 | ATH10K_MCAST2UCAST_ENABLED = 1, |
79 | }; | 82 | }; |
80 | 83 | ||
84 | struct ath10k_pktlog_hdr { | ||
85 | __le16 flags; | ||
86 | __le16 missed_cnt; | ||
87 | __le16 log_type; | ||
88 | __le16 size; | ||
89 | __le32 timestamp; | ||
90 | u8 payload[0]; | ||
91 | } __packed; | ||
92 | |||
81 | /* Target specific defines for MAIN firmware */ | 93 | /* Target specific defines for MAIN firmware */ |
82 | #define TARGET_NUM_VDEVS 8 | 94 | #define TARGET_NUM_VDEVS 8 |
83 | #define TARGET_NUM_PEER_AST 2 | 95 | #define TARGET_NUM_PEER_AST 2 |
@@ -279,6 +291,7 @@ enum ath10k_mcast2ucast_mode { | |||
279 | #define SI_RX_DATA1_OFFSET 0x00000014 | 291 | #define SI_RX_DATA1_OFFSET 0x00000014 |
280 | 292 | ||
281 | #define CORE_CTRL_CPU_INTR_MASK 0x00002000 | 293 | #define CORE_CTRL_CPU_INTR_MASK 0x00002000 |
294 | #define CORE_CTRL_PCIE_REG_31_MASK 0x00000800 | ||
282 | #define CORE_CTRL_ADDRESS 0x0000 | 295 | #define CORE_CTRL_ADDRESS 0x0000 |
283 | #define PCIE_INTR_ENABLE_ADDRESS 0x0008 | 296 | #define PCIE_INTR_ENABLE_ADDRESS 0x0008 |
284 | #define PCIE_INTR_CAUSE_ADDRESS 0x000c | 297 | #define PCIE_INTR_CAUSE_ADDRESS 0x000c |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 46709301a51e..1245ac8c5c6f 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -479,12 +479,49 @@ static void ath10k_peer_cleanup_all(struct ath10k *ar) | |||
479 | /* Interface management */ | 479 | /* Interface management */ |
480 | /************************/ | 480 | /************************/ |
481 | 481 | ||
482 | void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif) | ||
483 | { | ||
484 | struct ath10k *ar = arvif->ar; | ||
485 | |||
486 | lockdep_assert_held(&ar->data_lock); | ||
487 | |||
488 | if (!arvif->beacon) | ||
489 | return; | ||
490 | |||
491 | if (!arvif->beacon_buf) | ||
492 | dma_unmap_single(ar->dev, ATH10K_SKB_CB(arvif->beacon)->paddr, | ||
493 | arvif->beacon->len, DMA_TO_DEVICE); | ||
494 | |||
495 | dev_kfree_skb_any(arvif->beacon); | ||
496 | |||
497 | arvif->beacon = NULL; | ||
498 | arvif->beacon_sent = false; | ||
499 | } | ||
500 | |||
501 | static void ath10k_mac_vif_beacon_cleanup(struct ath10k_vif *arvif) | ||
502 | { | ||
503 | struct ath10k *ar = arvif->ar; | ||
504 | |||
505 | lockdep_assert_held(&ar->data_lock); | ||
506 | |||
507 | ath10k_mac_vif_beacon_free(arvif); | ||
508 | |||
509 | if (arvif->beacon_buf) { | ||
510 | dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, | ||
511 | arvif->beacon_buf, arvif->beacon_paddr); | ||
512 | arvif->beacon_buf = NULL; | ||
513 | } | ||
514 | } | ||
515 | |||
482 | static inline int ath10k_vdev_setup_sync(struct ath10k *ar) | 516 | static inline int ath10k_vdev_setup_sync(struct ath10k *ar) |
483 | { | 517 | { |
484 | int ret; | 518 | int ret; |
485 | 519 | ||
486 | lockdep_assert_held(&ar->conf_mutex); | 520 | lockdep_assert_held(&ar->conf_mutex); |
487 | 521 | ||
522 | if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) | ||
523 | return -ESHUTDOWN; | ||
524 | |||
488 | ret = wait_for_completion_timeout(&ar->vdev_setup_done, | 525 | ret = wait_for_completion_timeout(&ar->vdev_setup_done, |
489 | ATH10K_VDEV_SETUP_TIMEOUT_HZ); | 526 | ATH10K_VDEV_SETUP_TIMEOUT_HZ); |
490 | if (ret == 0) | 527 | if (ret == 0) |
@@ -517,6 +554,8 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) | |||
517 | arg.channel.max_reg_power = channel->max_reg_power * 2; | 554 | arg.channel.max_reg_power = channel->max_reg_power * 2; |
518 | arg.channel.max_antenna_gain = channel->max_antenna_gain * 2; | 555 | arg.channel.max_antenna_gain = channel->max_antenna_gain * 2; |
519 | 556 | ||
557 | reinit_completion(&ar->vdev_setup_done); | ||
558 | |||
520 | ret = ath10k_wmi_vdev_start(ar, &arg); | 559 | ret = ath10k_wmi_vdev_start(ar, &arg); |
521 | if (ret) { | 560 | if (ret) { |
522 | ath10k_warn(ar, "failed to request monitor vdev %i start: %d\n", | 561 | ath10k_warn(ar, "failed to request monitor vdev %i start: %d\n", |
@@ -564,6 +603,8 @@ static int ath10k_monitor_vdev_stop(struct ath10k *ar) | |||
564 | ath10k_warn(ar, "failed to put down monitor vdev %i: %d\n", | 603 | ath10k_warn(ar, "failed to put down monitor vdev %i: %d\n", |
565 | ar->monitor_vdev_id, ret); | 604 | ar->monitor_vdev_id, ret); |
566 | 605 | ||
606 | reinit_completion(&ar->vdev_setup_done); | ||
607 | |||
567 | ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); | 608 | ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); |
568 | if (ret) | 609 | if (ret) |
569 | ath10k_warn(ar, "failed to to request monitor vdev %i stop: %d\n", | 610 | ath10k_warn(ar, "failed to to request monitor vdev %i stop: %d\n", |
@@ -590,9 +631,9 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar) | |||
590 | return -ENOMEM; | 631 | return -ENOMEM; |
591 | } | 632 | } |
592 | 633 | ||
593 | bit = ffs(ar->free_vdev_map); | 634 | bit = __ffs64(ar->free_vdev_map); |
594 | 635 | ||
595 | ar->monitor_vdev_id = bit - 1; | 636 | ar->monitor_vdev_id = bit; |
596 | 637 | ||
597 | ret = ath10k_wmi_vdev_create(ar, ar->monitor_vdev_id, | 638 | ret = ath10k_wmi_vdev_create(ar, ar->monitor_vdev_id, |
598 | WMI_VDEV_TYPE_MONITOR, | 639 | WMI_VDEV_TYPE_MONITOR, |
@@ -603,7 +644,7 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar) | |||
603 | return ret; | 644 | return ret; |
604 | } | 645 | } |
605 | 646 | ||
606 | ar->free_vdev_map &= ~(1 << ar->monitor_vdev_id); | 647 | ar->free_vdev_map &= ~(1LL << ar->monitor_vdev_id); |
607 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d created\n", | 648 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d created\n", |
608 | ar->monitor_vdev_id); | 649 | ar->monitor_vdev_id); |
609 | 650 | ||
@@ -623,7 +664,7 @@ static int ath10k_monitor_vdev_delete(struct ath10k *ar) | |||
623 | return ret; | 664 | return ret; |
624 | } | 665 | } |
625 | 666 | ||
626 | ar->free_vdev_map |= 1 << ar->monitor_vdev_id; | 667 | ar->free_vdev_map |= 1LL << ar->monitor_vdev_id; |
627 | 668 | ||
628 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d deleted\n", | 669 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d deleted\n", |
629 | ar->monitor_vdev_id); | 670 | ar->monitor_vdev_id); |
@@ -909,15 +950,7 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif, | |||
909 | arvif->is_up = false; | 950 | arvif->is_up = false; |
910 | 951 | ||
911 | spin_lock_bh(&arvif->ar->data_lock); | 952 | spin_lock_bh(&arvif->ar->data_lock); |
912 | if (arvif->beacon) { | 953 | ath10k_mac_vif_beacon_free(arvif); |
913 | dma_unmap_single(arvif->ar->dev, | ||
914 | ATH10K_SKB_CB(arvif->beacon)->paddr, | ||
915 | arvif->beacon->len, DMA_TO_DEVICE); | ||
916 | dev_kfree_skb_any(arvif->beacon); | ||
917 | |||
918 | arvif->beacon = NULL; | ||
919 | arvif->beacon_sent = false; | ||
920 | } | ||
921 | spin_unlock_bh(&arvif->ar->data_lock); | 954 | spin_unlock_bh(&arvif->ar->data_lock); |
922 | 955 | ||
923 | return; | 956 | return; |
@@ -966,14 +999,6 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif, | |||
966 | if (is_zero_ether_addr(arvif->bssid)) | 999 | if (is_zero_ether_addr(arvif->bssid)) |
967 | return; | 1000 | return; |
968 | 1001 | ||
969 | ret = ath10k_peer_delete(arvif->ar, arvif->vdev_id, | ||
970 | arvif->bssid); | ||
971 | if (ret) { | ||
972 | ath10k_warn(ar, "failed to delete IBSS BSSID peer %pM for vdev %d: %d\n", | ||
973 | arvif->bssid, arvif->vdev_id, ret); | ||
974 | return; | ||
975 | } | ||
976 | |||
977 | memset(arvif->bssid, 0, ETH_ALEN); | 1002 | memset(arvif->bssid, 0, ETH_ALEN); |
978 | 1003 | ||
979 | return; | 1004 | return; |
@@ -1042,51 +1067,45 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif) | |||
1042 | /* Station management */ | 1067 | /* Station management */ |
1043 | /**********************/ | 1068 | /**********************/ |
1044 | 1069 | ||
1070 | static u32 ath10k_peer_assoc_h_listen_intval(struct ath10k *ar, | ||
1071 | struct ieee80211_vif *vif) | ||
1072 | { | ||
1073 | /* Some firmware revisions have unstable STA powersave when listen | ||
1074 | * interval is set too high (e.g. 5). The symptoms are firmware doesn't | ||
1075 | * generate NullFunc frames properly even if buffered frames have been | ||
1076 | * indicated in Beacon TIM. Firmware would seldom wake up to pull | ||
1077 | * buffered frames. Often pinging the device from AP would simply fail. | ||
1078 | * | ||
1079 | * As a workaround set it to 1. | ||
1080 | */ | ||
1081 | if (vif->type == NL80211_IFTYPE_STATION) | ||
1082 | return 1; | ||
1083 | |||
1084 | return ar->hw->conf.listen_interval; | ||
1085 | } | ||
1086 | |||
1045 | static void ath10k_peer_assoc_h_basic(struct ath10k *ar, | 1087 | static void ath10k_peer_assoc_h_basic(struct ath10k *ar, |
1046 | struct ath10k_vif *arvif, | 1088 | struct ieee80211_vif *vif, |
1047 | struct ieee80211_sta *sta, | 1089 | struct ieee80211_sta *sta, |
1048 | struct ieee80211_bss_conf *bss_conf, | ||
1049 | struct wmi_peer_assoc_complete_arg *arg) | 1090 | struct wmi_peer_assoc_complete_arg *arg) |
1050 | { | 1091 | { |
1092 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
1093 | |||
1051 | lockdep_assert_held(&ar->conf_mutex); | 1094 | lockdep_assert_held(&ar->conf_mutex); |
1052 | 1095 | ||
1053 | ether_addr_copy(arg->addr, sta->addr); | 1096 | ether_addr_copy(arg->addr, sta->addr); |
1054 | arg->vdev_id = arvif->vdev_id; | 1097 | arg->vdev_id = arvif->vdev_id; |
1055 | arg->peer_aid = sta->aid; | 1098 | arg->peer_aid = sta->aid; |
1056 | arg->peer_flags |= WMI_PEER_AUTH; | 1099 | arg->peer_flags |= WMI_PEER_AUTH; |
1057 | 1100 | arg->peer_listen_intval = ath10k_peer_assoc_h_listen_intval(ar, vif); | |
1058 | if (arvif->vdev_type == WMI_VDEV_TYPE_STA) | ||
1059 | /* | ||
1060 | * Seems FW have problems with Power Save in STA | ||
1061 | * mode when we setup this parameter to high (eg. 5). | ||
1062 | * Often we see that FW don't send NULL (with clean P flags) | ||
1063 | * frame even there is info about buffered frames in beacons. | ||
1064 | * Sometimes we have to wait more than 10 seconds before FW | ||
1065 | * will wakeup. Often sending one ping from AP to our device | ||
1066 | * just fail (more than 50%). | ||
1067 | * | ||
1068 | * Seems setting this FW parameter to 1 couse FW | ||
1069 | * will check every beacon and will wakup immediately | ||
1070 | * after detection buffered data. | ||
1071 | */ | ||
1072 | arg->peer_listen_intval = 1; | ||
1073 | else | ||
1074 | arg->peer_listen_intval = ar->hw->conf.listen_interval; | ||
1075 | |||
1076 | arg->peer_num_spatial_streams = 1; | 1101 | arg->peer_num_spatial_streams = 1; |
1077 | 1102 | arg->peer_caps = vif->bss_conf.assoc_capability; | |
1078 | /* | ||
1079 | * The assoc capabilities are available only in managed mode. | ||
1080 | */ | ||
1081 | if (arvif->vdev_type == WMI_VDEV_TYPE_STA && bss_conf) | ||
1082 | arg->peer_caps = bss_conf->assoc_capability; | ||
1083 | } | 1103 | } |
1084 | 1104 | ||
1085 | static void ath10k_peer_assoc_h_crypto(struct ath10k *ar, | 1105 | static void ath10k_peer_assoc_h_crypto(struct ath10k *ar, |
1086 | struct ath10k_vif *arvif, | 1106 | struct ieee80211_vif *vif, |
1087 | struct wmi_peer_assoc_complete_arg *arg) | 1107 | struct wmi_peer_assoc_complete_arg *arg) |
1088 | { | 1108 | { |
1089 | struct ieee80211_vif *vif = arvif->vif; | ||
1090 | struct ieee80211_bss_conf *info = &vif->bss_conf; | 1109 | struct ieee80211_bss_conf *info = &vif->bss_conf; |
1091 | struct cfg80211_bss *bss; | 1110 | struct cfg80211_bss *bss; |
1092 | const u8 *rsnie = NULL; | 1111 | const u8 *rsnie = NULL; |
@@ -1343,11 +1362,12 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, | |||
1343 | } | 1362 | } |
1344 | 1363 | ||
1345 | static void ath10k_peer_assoc_h_qos(struct ath10k *ar, | 1364 | static void ath10k_peer_assoc_h_qos(struct ath10k *ar, |
1346 | struct ath10k_vif *arvif, | 1365 | struct ieee80211_vif *vif, |
1347 | struct ieee80211_sta *sta, | 1366 | struct ieee80211_sta *sta, |
1348 | struct ieee80211_bss_conf *bss_conf, | ||
1349 | struct wmi_peer_assoc_complete_arg *arg) | 1367 | struct wmi_peer_assoc_complete_arg *arg) |
1350 | { | 1368 | { |
1369 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
1370 | |||
1351 | switch (arvif->vdev_type) { | 1371 | switch (arvif->vdev_type) { |
1352 | case WMI_VDEV_TYPE_AP: | 1372 | case WMI_VDEV_TYPE_AP: |
1353 | if (sta->wme) | 1373 | if (sta->wme) |
@@ -1359,7 +1379,7 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar, | |||
1359 | } | 1379 | } |
1360 | break; | 1380 | break; |
1361 | case WMI_VDEV_TYPE_STA: | 1381 | case WMI_VDEV_TYPE_STA: |
1362 | if (bss_conf->qos) | 1382 | if (vif->bss_conf.qos) |
1363 | arg->peer_flags |= WMI_PEER_QOS; | 1383 | arg->peer_flags |= WMI_PEER_QOS; |
1364 | break; | 1384 | break; |
1365 | default: | 1385 | default: |
@@ -1368,7 +1388,7 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar, | |||
1368 | } | 1388 | } |
1369 | 1389 | ||
1370 | static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, | 1390 | static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, |
1371 | struct ath10k_vif *arvif, | 1391 | struct ieee80211_vif *vif, |
1372 | struct ieee80211_sta *sta, | 1392 | struct ieee80211_sta *sta, |
1373 | struct wmi_peer_assoc_complete_arg *arg) | 1393 | struct wmi_peer_assoc_complete_arg *arg) |
1374 | { | 1394 | { |
@@ -1419,22 +1439,21 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, | |||
1419 | } | 1439 | } |
1420 | 1440 | ||
1421 | static int ath10k_peer_assoc_prepare(struct ath10k *ar, | 1441 | static int ath10k_peer_assoc_prepare(struct ath10k *ar, |
1422 | struct ath10k_vif *arvif, | 1442 | struct ieee80211_vif *vif, |
1423 | struct ieee80211_sta *sta, | 1443 | struct ieee80211_sta *sta, |
1424 | struct ieee80211_bss_conf *bss_conf, | ||
1425 | struct wmi_peer_assoc_complete_arg *arg) | 1444 | struct wmi_peer_assoc_complete_arg *arg) |
1426 | { | 1445 | { |
1427 | lockdep_assert_held(&ar->conf_mutex); | 1446 | lockdep_assert_held(&ar->conf_mutex); |
1428 | 1447 | ||
1429 | memset(arg, 0, sizeof(*arg)); | 1448 | memset(arg, 0, sizeof(*arg)); |
1430 | 1449 | ||
1431 | ath10k_peer_assoc_h_basic(ar, arvif, sta, bss_conf, arg); | 1450 | ath10k_peer_assoc_h_basic(ar, vif, sta, arg); |
1432 | ath10k_peer_assoc_h_crypto(ar, arvif, arg); | 1451 | ath10k_peer_assoc_h_crypto(ar, vif, arg); |
1433 | ath10k_peer_assoc_h_rates(ar, sta, arg); | 1452 | ath10k_peer_assoc_h_rates(ar, sta, arg); |
1434 | ath10k_peer_assoc_h_ht(ar, sta, arg); | 1453 | ath10k_peer_assoc_h_ht(ar, sta, arg); |
1435 | ath10k_peer_assoc_h_vht(ar, sta, arg); | 1454 | ath10k_peer_assoc_h_vht(ar, sta, arg); |
1436 | ath10k_peer_assoc_h_qos(ar, arvif, sta, bss_conf, arg); | 1455 | ath10k_peer_assoc_h_qos(ar, vif, sta, arg); |
1437 | ath10k_peer_assoc_h_phymode(ar, arvif, sta, arg); | 1456 | ath10k_peer_assoc_h_phymode(ar, vif, sta, arg); |
1438 | 1457 | ||
1439 | return 0; | 1458 | return 0; |
1440 | } | 1459 | } |
@@ -1480,6 +1499,9 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, | |||
1480 | 1499 | ||
1481 | lockdep_assert_held(&ar->conf_mutex); | 1500 | lockdep_assert_held(&ar->conf_mutex); |
1482 | 1501 | ||
1502 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n", | ||
1503 | arvif->vdev_id, arvif->bssid, arvif->aid); | ||
1504 | |||
1483 | rcu_read_lock(); | 1505 | rcu_read_lock(); |
1484 | 1506 | ||
1485 | ap_sta = ieee80211_find_sta(vif, bss_conf->bssid); | 1507 | ap_sta = ieee80211_find_sta(vif, bss_conf->bssid); |
@@ -1494,8 +1516,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, | |||
1494 | * before calling ath10k_setup_peer_smps() which might sleep. */ | 1516 | * before calling ath10k_setup_peer_smps() which might sleep. */ |
1495 | ht_cap = ap_sta->ht_cap; | 1517 | ht_cap = ap_sta->ht_cap; |
1496 | 1518 | ||
1497 | ret = ath10k_peer_assoc_prepare(ar, arvif, ap_sta, | 1519 | ret = ath10k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg); |
1498 | bss_conf, &peer_arg); | ||
1499 | if (ret) { | 1520 | if (ret) { |
1500 | ath10k_warn(ar, "failed to prepare peer assoc for %pM vdev %i: %d\n", | 1521 | ath10k_warn(ar, "failed to prepare peer assoc for %pM vdev %i: %d\n", |
1501 | bss_conf->bssid, arvif->vdev_id, ret); | 1522 | bss_conf->bssid, arvif->vdev_id, ret); |
@@ -1523,6 +1544,8 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, | |||
1523 | "mac vdev %d up (associated) bssid %pM aid %d\n", | 1544 | "mac vdev %d up (associated) bssid %pM aid %d\n", |
1524 | arvif->vdev_id, bss_conf->bssid, bss_conf->aid); | 1545 | arvif->vdev_id, bss_conf->bssid, bss_conf->aid); |
1525 | 1546 | ||
1547 | WARN_ON(arvif->is_up); | ||
1548 | |||
1526 | arvif->aid = bss_conf->aid; | 1549 | arvif->aid = bss_conf->aid; |
1527 | ether_addr_copy(arvif->bssid, bss_conf->bssid); | 1550 | ether_addr_copy(arvif->bssid, bss_conf->bssid); |
1528 | 1551 | ||
@@ -1536,9 +1559,6 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, | |||
1536 | arvif->is_up = true; | 1559 | arvif->is_up = true; |
1537 | } | 1560 | } |
1538 | 1561 | ||
1539 | /* | ||
1540 | * FIXME: flush TIDs | ||
1541 | */ | ||
1542 | static void ath10k_bss_disassoc(struct ieee80211_hw *hw, | 1562 | static void ath10k_bss_disassoc(struct ieee80211_hw *hw, |
1543 | struct ieee80211_vif *vif) | 1563 | struct ieee80211_vif *vif) |
1544 | { | 1564 | { |
@@ -1548,45 +1568,30 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw, | |||
1548 | 1568 | ||
1549 | lockdep_assert_held(&ar->conf_mutex); | 1569 | lockdep_assert_held(&ar->conf_mutex); |
1550 | 1570 | ||
1551 | /* | 1571 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n", |
1552 | * For some reason, calling VDEV-DOWN before VDEV-STOP | 1572 | arvif->vdev_id, arvif->bssid); |
1553 | * makes the FW to send frames via HTT after disassociation. | ||
1554 | * No idea why this happens, even though VDEV-DOWN is supposed | ||
1555 | * to be analogous to link down, so just stop the VDEV. | ||
1556 | */ | ||
1557 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d stop (disassociated\n", | ||
1558 | arvif->vdev_id); | ||
1559 | |||
1560 | /* FIXME: check return value */ | ||
1561 | ret = ath10k_vdev_stop(arvif); | ||
1562 | 1573 | ||
1563 | /* | ||
1564 | * If we don't call VDEV-DOWN after VDEV-STOP FW will remain active and | ||
1565 | * report beacons from previously associated network through HTT. | ||
1566 | * This in turn would spam mac80211 WARN_ON if we bring down all | ||
1567 | * interfaces as it expects there is no rx when no interface is | ||
1568 | * running. | ||
1569 | */ | ||
1570 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d down\n", arvif->vdev_id); | ||
1571 | |||
1572 | /* FIXME: why don't we print error if wmi call fails? */ | ||
1573 | ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); | 1574 | ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); |
1575 | if (ret) | ||
1576 | ath10k_warn(ar, "faield to down vdev %i: %d\n", | ||
1577 | arvif->vdev_id, ret); | ||
1574 | 1578 | ||
1575 | arvif->def_wep_key_idx = 0; | 1579 | arvif->def_wep_key_idx = 0; |
1576 | |||
1577 | arvif->is_started = false; | ||
1578 | arvif->is_up = false; | 1580 | arvif->is_up = false; |
1579 | } | 1581 | } |
1580 | 1582 | ||
1581 | static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif, | 1583 | static int ath10k_station_assoc(struct ath10k *ar, |
1582 | struct ieee80211_sta *sta, bool reassoc) | 1584 | struct ieee80211_vif *vif, |
1585 | struct ieee80211_sta *sta, | ||
1586 | bool reassoc) | ||
1583 | { | 1587 | { |
1588 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
1584 | struct wmi_peer_assoc_complete_arg peer_arg; | 1589 | struct wmi_peer_assoc_complete_arg peer_arg; |
1585 | int ret = 0; | 1590 | int ret = 0; |
1586 | 1591 | ||
1587 | lockdep_assert_held(&ar->conf_mutex); | 1592 | lockdep_assert_held(&ar->conf_mutex); |
1588 | 1593 | ||
1589 | ret = ath10k_peer_assoc_prepare(ar, arvif, sta, NULL, &peer_arg); | 1594 | ret = ath10k_peer_assoc_prepare(ar, vif, sta, &peer_arg); |
1590 | if (ret) { | 1595 | if (ret) { |
1591 | ath10k_warn(ar, "failed to prepare WMI peer assoc for %pM vdev %i: %i\n", | 1596 | ath10k_warn(ar, "failed to prepare WMI peer assoc for %pM vdev %i: %i\n", |
1592 | sta->addr, arvif->vdev_id, ret); | 1597 | sta->addr, arvif->vdev_id, ret); |
@@ -1601,43 +1606,51 @@ static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif, | |||
1601 | return ret; | 1606 | return ret; |
1602 | } | 1607 | } |
1603 | 1608 | ||
1604 | ret = ath10k_setup_peer_smps(ar, arvif, sta->addr, &sta->ht_cap); | 1609 | /* Re-assoc is run only to update supported rates for given station. It |
1605 | if (ret) { | 1610 | * doesn't make much sense to reconfigure the peer completely. |
1606 | ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n", | 1611 | */ |
1607 | arvif->vdev_id, ret); | 1612 | if (!reassoc) { |
1608 | return ret; | 1613 | ret = ath10k_setup_peer_smps(ar, arvif, sta->addr, |
1609 | } | 1614 | &sta->ht_cap); |
1610 | |||
1611 | if (!sta->wme && !reassoc) { | ||
1612 | arvif->num_legacy_stations++; | ||
1613 | ret = ath10k_recalc_rtscts_prot(arvif); | ||
1614 | if (ret) { | 1615 | if (ret) { |
1615 | ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n", | 1616 | ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n", |
1616 | arvif->vdev_id, ret); | 1617 | arvif->vdev_id, ret); |
1617 | return ret; | 1618 | return ret; |
1618 | } | 1619 | } |
1619 | } | ||
1620 | 1620 | ||
1621 | ret = ath10k_install_peer_wep_keys(arvif, sta->addr); | 1621 | ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta); |
1622 | if (ret) { | 1622 | if (ret) { |
1623 | ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n", | 1623 | ath10k_warn(ar, "failed to set qos params for STA %pM for vdev %i: %d\n", |
1624 | arvif->vdev_id, ret); | 1624 | sta->addr, arvif->vdev_id, ret); |
1625 | return ret; | 1625 | return ret; |
1626 | } | 1626 | } |
1627 | 1627 | ||
1628 | ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta); | 1628 | if (!sta->wme) { |
1629 | if (ret) { | 1629 | arvif->num_legacy_stations++; |
1630 | ath10k_warn(ar, "failed to set qos params for STA %pM for vdev %i: %d\n", | 1630 | ret = ath10k_recalc_rtscts_prot(arvif); |
1631 | sta->addr, arvif->vdev_id, ret); | 1631 | if (ret) { |
1632 | return ret; | 1632 | ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n", |
1633 | arvif->vdev_id, ret); | ||
1634 | return ret; | ||
1635 | } | ||
1636 | } | ||
1637 | |||
1638 | ret = ath10k_install_peer_wep_keys(arvif, sta->addr); | ||
1639 | if (ret) { | ||
1640 | ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n", | ||
1641 | arvif->vdev_id, ret); | ||
1642 | return ret; | ||
1643 | } | ||
1633 | } | 1644 | } |
1634 | 1645 | ||
1635 | return ret; | 1646 | return ret; |
1636 | } | 1647 | } |
1637 | 1648 | ||
1638 | static int ath10k_station_disassoc(struct ath10k *ar, struct ath10k_vif *arvif, | 1649 | static int ath10k_station_disassoc(struct ath10k *ar, |
1650 | struct ieee80211_vif *vif, | ||
1639 | struct ieee80211_sta *sta) | 1651 | struct ieee80211_sta *sta) |
1640 | { | 1652 | { |
1653 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
1641 | int ret = 0; | 1654 | int ret = 0; |
1642 | 1655 | ||
1643 | lockdep_assert_held(&ar->conf_mutex); | 1656 | lockdep_assert_held(&ar->conf_mutex); |
@@ -1729,6 +1742,7 @@ static int ath10k_update_channel_list(struct ath10k *ar) | |||
1729 | ch->passive = passive; | 1742 | ch->passive = passive; |
1730 | 1743 | ||
1731 | ch->freq = channel->center_freq; | 1744 | ch->freq = channel->center_freq; |
1745 | ch->band_center_freq1 = channel->center_freq; | ||
1732 | ch->min_power = 0; | 1746 | ch->min_power = 0; |
1733 | ch->max_power = channel->max_power * 2; | 1747 | ch->max_power = channel->max_power * 2; |
1734 | ch->max_reg_power = channel->max_reg_power * 2; | 1748 | ch->max_reg_power = channel->max_reg_power * 2; |
@@ -2343,7 +2357,7 @@ static void ath10k_tx(struct ieee80211_hw *hw, | |||
2343 | } | 2357 | } |
2344 | 2358 | ||
2345 | /* Must not be called with conf_mutex held as workers can use that also. */ | 2359 | /* Must not be called with conf_mutex held as workers can use that also. */ |
2346 | static void ath10k_drain_tx(struct ath10k *ar) | 2360 | void ath10k_drain_tx(struct ath10k *ar) |
2347 | { | 2361 | { |
2348 | /* make sure rcu-protected mac80211 tx path itself is drained */ | 2362 | /* make sure rcu-protected mac80211 tx path itself is drained */ |
2349 | synchronize_net(); | 2363 | synchronize_net(); |
@@ -2376,16 +2390,8 @@ void ath10k_halt(struct ath10k *ar) | |||
2376 | ath10k_hif_power_down(ar); | 2390 | ath10k_hif_power_down(ar); |
2377 | 2391 | ||
2378 | spin_lock_bh(&ar->data_lock); | 2392 | spin_lock_bh(&ar->data_lock); |
2379 | list_for_each_entry(arvif, &ar->arvifs, list) { | 2393 | list_for_each_entry(arvif, &ar->arvifs, list) |
2380 | if (!arvif->beacon) | 2394 | ath10k_mac_vif_beacon_cleanup(arvif); |
2381 | continue; | ||
2382 | |||
2383 | dma_unmap_single(arvif->ar->dev, | ||
2384 | ATH10K_SKB_CB(arvif->beacon)->paddr, | ||
2385 | arvif->beacon->len, DMA_TO_DEVICE); | ||
2386 | dev_kfree_skb_any(arvif->beacon); | ||
2387 | arvif->beacon = NULL; | ||
2388 | } | ||
2389 | spin_unlock_bh(&ar->data_lock); | 2395 | spin_unlock_bh(&ar->data_lock); |
2390 | } | 2396 | } |
2391 | 2397 | ||
@@ -2677,12 +2683,68 @@ static void ath10k_config_chan(struct ath10k *ar) | |||
2677 | ath10k_monitor_recalc(ar); | 2683 | ath10k_monitor_recalc(ar); |
2678 | } | 2684 | } |
2679 | 2685 | ||
2686 | static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower) | ||
2687 | { | ||
2688 | int ret; | ||
2689 | u32 param; | ||
2690 | |||
2691 | lockdep_assert_held(&ar->conf_mutex); | ||
2692 | |||
2693 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac txpower %d\n", txpower); | ||
2694 | |||
2695 | param = ar->wmi.pdev_param->txpower_limit2g; | ||
2696 | ret = ath10k_wmi_pdev_set_param(ar, param, txpower * 2); | ||
2697 | if (ret) { | ||
2698 | ath10k_warn(ar, "failed to set 2g txpower %d: %d\n", | ||
2699 | txpower, ret); | ||
2700 | return ret; | ||
2701 | } | ||
2702 | |||
2703 | param = ar->wmi.pdev_param->txpower_limit5g; | ||
2704 | ret = ath10k_wmi_pdev_set_param(ar, param, txpower * 2); | ||
2705 | if (ret) { | ||
2706 | ath10k_warn(ar, "failed to set 5g txpower %d: %d\n", | ||
2707 | txpower, ret); | ||
2708 | return ret; | ||
2709 | } | ||
2710 | |||
2711 | return 0; | ||
2712 | } | ||
2713 | |||
2714 | static int ath10k_mac_txpower_recalc(struct ath10k *ar) | ||
2715 | { | ||
2716 | struct ath10k_vif *arvif; | ||
2717 | int ret, txpower = -1; | ||
2718 | |||
2719 | lockdep_assert_held(&ar->conf_mutex); | ||
2720 | |||
2721 | list_for_each_entry(arvif, &ar->arvifs, list) { | ||
2722 | WARN_ON(arvif->txpower < 0); | ||
2723 | |||
2724 | if (txpower == -1) | ||
2725 | txpower = arvif->txpower; | ||
2726 | else | ||
2727 | txpower = min(txpower, arvif->txpower); | ||
2728 | } | ||
2729 | |||
2730 | if (WARN_ON(txpower == -1)) | ||
2731 | return -EINVAL; | ||
2732 | |||
2733 | ret = ath10k_mac_txpower_setup(ar, txpower); | ||
2734 | if (ret) { | ||
2735 | ath10k_warn(ar, "failed to setup tx power %d: %d\n", | ||
2736 | txpower, ret); | ||
2737 | return ret; | ||
2738 | } | ||
2739 | |||
2740 | return 0; | ||
2741 | } | ||
2742 | |||
2680 | static int ath10k_config(struct ieee80211_hw *hw, u32 changed) | 2743 | static int ath10k_config(struct ieee80211_hw *hw, u32 changed) |
2681 | { | 2744 | { |
2682 | struct ath10k *ar = hw->priv; | 2745 | struct ath10k *ar = hw->priv; |
2683 | struct ieee80211_conf *conf = &hw->conf; | 2746 | struct ieee80211_conf *conf = &hw->conf; |
2684 | int ret = 0; | 2747 | int ret = 0; |
2685 | u32 param; | ||
2686 | 2748 | ||
2687 | mutex_lock(&ar->conf_mutex); | 2749 | mutex_lock(&ar->conf_mutex); |
2688 | 2750 | ||
@@ -2706,25 +2768,6 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed) | |||
2706 | } | 2768 | } |
2707 | } | 2769 | } |
2708 | 2770 | ||
2709 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | ||
2710 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac config power %d\n", | ||
2711 | hw->conf.power_level); | ||
2712 | |||
2713 | param = ar->wmi.pdev_param->txpower_limit2g; | ||
2714 | ret = ath10k_wmi_pdev_set_param(ar, param, | ||
2715 | hw->conf.power_level * 2); | ||
2716 | if (ret) | ||
2717 | ath10k_warn(ar, "failed to set 2g txpower %d: %d\n", | ||
2718 | hw->conf.power_level, ret); | ||
2719 | |||
2720 | param = ar->wmi.pdev_param->txpower_limit5g; | ||
2721 | ret = ath10k_wmi_pdev_set_param(ar, param, | ||
2722 | hw->conf.power_level * 2); | ||
2723 | if (ret) | ||
2724 | ath10k_warn(ar, "failed to set 5g txpower %d: %d\n", | ||
2725 | hw->conf.power_level, ret); | ||
2726 | } | ||
2727 | |||
2728 | if (changed & IEEE80211_CONF_CHANGE_PS) | 2771 | if (changed & IEEE80211_CONF_CHANGE_PS) |
2729 | ath10k_config_ps(ar); | 2772 | ath10k_config_ps(ar); |
2730 | 2773 | ||
@@ -2772,9 +2815,12 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2772 | ret = -EBUSY; | 2815 | ret = -EBUSY; |
2773 | goto err; | 2816 | goto err; |
2774 | } | 2817 | } |
2775 | bit = ffs(ar->free_vdev_map); | 2818 | bit = __ffs64(ar->free_vdev_map); |
2819 | |||
2820 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac create vdev %i map %llx\n", | ||
2821 | bit, ar->free_vdev_map); | ||
2776 | 2822 | ||
2777 | arvif->vdev_id = bit - 1; | 2823 | arvif->vdev_id = bit; |
2778 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; | 2824 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; |
2779 | 2825 | ||
2780 | if (ar->p2p) | 2826 | if (ar->p2p) |
@@ -2804,8 +2850,39 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2804 | break; | 2850 | break; |
2805 | } | 2851 | } |
2806 | 2852 | ||
2807 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d\n", | 2853 | /* Some firmware revisions don't wait for beacon tx completion before |
2808 | arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype); | 2854 | * sending another SWBA event. This could lead to hardware using old |
2855 | * (freed) beacon data in some cases, e.g. tx credit starvation | ||
2856 | * combined with missed TBTT. This is very very rare. | ||
2857 | * | ||
2858 | * On non-IOMMU-enabled hosts this could be a possible security issue | ||
2859 | * because hw could beacon some random data on the air. On | ||
2860 | * IOMMU-enabled hosts DMAR faults would occur in most cases and target | ||
2861 | * device would crash. | ||
2862 | * | ||
2863 | * Since there are no beacon tx completions (implicit nor explicit) | ||
2864 | * propagated to host the only workaround for this is to allocate a | ||
2865 | * DMA-coherent buffer for a lifetime of a vif and use it for all | ||
2866 | * beacon tx commands. Worst case for this approach is some beacons may | ||
2867 | * become corrupted, e.g. have garbled IEs or out-of-date TIM bitmap. | ||
2868 | */ | ||
2869 | if (vif->type == NL80211_IFTYPE_ADHOC || | ||
2870 | vif->type == NL80211_IFTYPE_AP) { | ||
2871 | arvif->beacon_buf = dma_zalloc_coherent(ar->dev, | ||
2872 | IEEE80211_MAX_FRAME_LEN, | ||
2873 | &arvif->beacon_paddr, | ||
2874 | GFP_ATOMIC); | ||
2875 | if (!arvif->beacon_buf) { | ||
2876 | ret = -ENOMEM; | ||
2877 | ath10k_warn(ar, "failed to allocate beacon buffer: %d\n", | ||
2878 | ret); | ||
2879 | goto err; | ||
2880 | } | ||
2881 | } | ||
2882 | |||
2883 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d bcnmode %s\n", | ||
2884 | arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype, | ||
2885 | arvif->beacon_buf ? "single-buf" : "per-skb"); | ||
2809 | 2886 | ||
2810 | ret = ath10k_wmi_vdev_create(ar, arvif->vdev_id, arvif->vdev_type, | 2887 | ret = ath10k_wmi_vdev_create(ar, arvif->vdev_id, arvif->vdev_type, |
2811 | arvif->vdev_subtype, vif->addr); | 2888 | arvif->vdev_subtype, vif->addr); |
@@ -2815,7 +2892,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2815 | goto err; | 2892 | goto err; |
2816 | } | 2893 | } |
2817 | 2894 | ||
2818 | ar->free_vdev_map &= ~(1 << arvif->vdev_id); | 2895 | ar->free_vdev_map &= ~(1LL << arvif->vdev_id); |
2819 | list_add(&arvif->list, &ar->arvifs); | 2896 | list_add(&arvif->list, &ar->arvifs); |
2820 | 2897 | ||
2821 | vdev_param = ar->wmi.vdev_param->def_keyid; | 2898 | vdev_param = ar->wmi.vdev_param->def_keyid; |
@@ -2899,6 +2976,13 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2899 | goto err_peer_delete; | 2976 | goto err_peer_delete; |
2900 | } | 2977 | } |
2901 | 2978 | ||
2979 | arvif->txpower = vif->bss_conf.txpower; | ||
2980 | ret = ath10k_mac_txpower_recalc(ar); | ||
2981 | if (ret) { | ||
2982 | ath10k_warn(ar, "failed to recalc tx power: %d\n", ret); | ||
2983 | goto err_peer_delete; | ||
2984 | } | ||
2985 | |||
2902 | mutex_unlock(&ar->conf_mutex); | 2986 | mutex_unlock(&ar->conf_mutex); |
2903 | return 0; | 2987 | return 0; |
2904 | 2988 | ||
@@ -2908,10 +2992,16 @@ err_peer_delete: | |||
2908 | 2992 | ||
2909 | err_vdev_delete: | 2993 | err_vdev_delete: |
2910 | ath10k_wmi_vdev_delete(ar, arvif->vdev_id); | 2994 | ath10k_wmi_vdev_delete(ar, arvif->vdev_id); |
2911 | ar->free_vdev_map |= 1 << arvif->vdev_id; | 2995 | ar->free_vdev_map |= 1LL << arvif->vdev_id; |
2912 | list_del(&arvif->list); | 2996 | list_del(&arvif->list); |
2913 | 2997 | ||
2914 | err: | 2998 | err: |
2999 | if (arvif->beacon_buf) { | ||
3000 | dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, | ||
3001 | arvif->beacon_buf, arvif->beacon_paddr); | ||
3002 | arvif->beacon_buf = NULL; | ||
3003 | } | ||
3004 | |||
2915 | mutex_unlock(&ar->conf_mutex); | 3005 | mutex_unlock(&ar->conf_mutex); |
2916 | 3006 | ||
2917 | return ret; | 3007 | return ret; |
@@ -2929,14 +3019,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, | |||
2929 | cancel_work_sync(&arvif->wep_key_work); | 3019 | cancel_work_sync(&arvif->wep_key_work); |
2930 | 3020 | ||
2931 | spin_lock_bh(&ar->data_lock); | 3021 | spin_lock_bh(&ar->data_lock); |
2932 | if (arvif->beacon) { | 3022 | ath10k_mac_vif_beacon_cleanup(arvif); |
2933 | dma_unmap_single(arvif->ar->dev, | ||
2934 | ATH10K_SKB_CB(arvif->beacon)->paddr, | ||
2935 | arvif->beacon->len, DMA_TO_DEVICE); | ||
2936 | dev_kfree_skb_any(arvif->beacon); | ||
2937 | arvif->beacon = NULL; | ||
2938 | } | ||
2939 | |||
2940 | spin_unlock_bh(&ar->data_lock); | 3023 | spin_unlock_bh(&ar->data_lock); |
2941 | 3024 | ||
2942 | ret = ath10k_spectral_vif_stop(arvif); | 3025 | ret = ath10k_spectral_vif_stop(arvif); |
@@ -2944,7 +3027,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, | |||
2944 | ath10k_warn(ar, "failed to stop spectral for vdev %i: %d\n", | 3027 | ath10k_warn(ar, "failed to stop spectral for vdev %i: %d\n", |
2945 | arvif->vdev_id, ret); | 3028 | arvif->vdev_id, ret); |
2946 | 3029 | ||
2947 | ar->free_vdev_map |= 1 << arvif->vdev_id; | 3030 | ar->free_vdev_map |= 1LL << arvif->vdev_id; |
2948 | list_del(&arvif->list); | 3031 | list_del(&arvif->list); |
2949 | 3032 | ||
2950 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { | 3033 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { |
@@ -3068,54 +3151,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
3068 | arvif->u.ap.hidden_ssid = info->hidden_ssid; | 3151 | arvif->u.ap.hidden_ssid = info->hidden_ssid; |
3069 | } | 3152 | } |
3070 | 3153 | ||
3071 | /* | 3154 | if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) |
3072 | * Firmware manages AP self-peer internally so make sure to not create | 3155 | ether_addr_copy(arvif->bssid, info->bssid); |
3073 | * it in driver. Otherwise AP self-peer deletion may timeout later. | ||
3074 | */ | ||
3075 | if (changed & BSS_CHANGED_BSSID && | ||
3076 | vif->type != NL80211_IFTYPE_AP) { | ||
3077 | if (!is_zero_ether_addr(info->bssid)) { | ||
3078 | ath10k_dbg(ar, ATH10K_DBG_MAC, | ||
3079 | "mac vdev %d create peer %pM\n", | ||
3080 | arvif->vdev_id, info->bssid); | ||
3081 | |||
3082 | ret = ath10k_peer_create(ar, arvif->vdev_id, | ||
3083 | info->bssid); | ||
3084 | if (ret) | ||
3085 | ath10k_warn(ar, "failed to add peer %pM for vdev %d when changing bssid: %i\n", | ||
3086 | info->bssid, arvif->vdev_id, ret); | ||
3087 | |||
3088 | if (vif->type == NL80211_IFTYPE_STATION) { | ||
3089 | /* | ||
3090 | * this is never erased as we it for crypto key | ||
3091 | * clearing; this is FW requirement | ||
3092 | */ | ||
3093 | ether_addr_copy(arvif->bssid, info->bssid); | ||
3094 | |||
3095 | ath10k_dbg(ar, ATH10K_DBG_MAC, | ||
3096 | "mac vdev %d start %pM\n", | ||
3097 | arvif->vdev_id, info->bssid); | ||
3098 | |||
3099 | ret = ath10k_vdev_start(arvif); | ||
3100 | if (ret) { | ||
3101 | ath10k_warn(ar, "failed to start vdev %i: %d\n", | ||
3102 | arvif->vdev_id, ret); | ||
3103 | goto exit; | ||
3104 | } | ||
3105 | |||
3106 | arvif->is_started = true; | ||
3107 | } | ||
3108 | |||
3109 | /* | ||
3110 | * Mac80211 does not keep IBSS bssid when leaving IBSS, | ||
3111 | * so driver need to store it. It is needed when leaving | ||
3112 | * IBSS in order to remove BSSID peer. | ||
3113 | */ | ||
3114 | if (vif->type == NL80211_IFTYPE_ADHOC) | ||
3115 | memcpy(arvif->bssid, info->bssid, | ||
3116 | ETH_ALEN); | ||
3117 | } | ||
3118 | } | ||
3119 | 3156 | ||
3120 | if (changed & BSS_CHANGED_BEACON_ENABLED) | 3157 | if (changed & BSS_CHANGED_BEACON_ENABLED) |
3121 | ath10k_control_beaconing(arvif, info); | 3158 | ath10k_control_beaconing(arvif, info); |
@@ -3177,10 +3214,21 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
3177 | ath10k_monitor_stop(ar); | 3214 | ath10k_monitor_stop(ar); |
3178 | ath10k_bss_assoc(hw, vif, info); | 3215 | ath10k_bss_assoc(hw, vif, info); |
3179 | ath10k_monitor_recalc(ar); | 3216 | ath10k_monitor_recalc(ar); |
3217 | } else { | ||
3218 | ath10k_bss_disassoc(hw, vif); | ||
3180 | } | 3219 | } |
3181 | } | 3220 | } |
3182 | 3221 | ||
3183 | exit: | 3222 | if (changed & BSS_CHANGED_TXPOWER) { |
3223 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev_id %i txpower %d\n", | ||
3224 | arvif->vdev_id, info->txpower); | ||
3225 | |||
3226 | arvif->txpower = info->txpower; | ||
3227 | ret = ath10k_mac_txpower_recalc(ar); | ||
3228 | if (ret) | ||
3229 | ath10k_warn(ar, "failed to recalc tx power: %d\n", ret); | ||
3230 | } | ||
3231 | |||
3184 | mutex_unlock(&ar->conf_mutex); | 3232 | mutex_unlock(&ar->conf_mutex); |
3185 | } | 3233 | } |
3186 | 3234 | ||
@@ -3266,9 +3314,10 @@ static void ath10k_cancel_hw_scan(struct ieee80211_hw *hw, | |||
3266 | struct ath10k *ar = hw->priv; | 3314 | struct ath10k *ar = hw->priv; |
3267 | 3315 | ||
3268 | mutex_lock(&ar->conf_mutex); | 3316 | mutex_lock(&ar->conf_mutex); |
3269 | cancel_delayed_work_sync(&ar->scan.timeout); | ||
3270 | ath10k_scan_abort(ar); | 3317 | ath10k_scan_abort(ar); |
3271 | mutex_unlock(&ar->conf_mutex); | 3318 | mutex_unlock(&ar->conf_mutex); |
3319 | |||
3320 | cancel_delayed_work_sync(&ar->scan.timeout); | ||
3272 | } | 3321 | } |
3273 | 3322 | ||
3274 | static void ath10k_set_key_h_def_keyidx(struct ath10k *ar, | 3323 | static void ath10k_set_key_h_def_keyidx(struct ath10k *ar, |
@@ -3453,7 +3502,7 @@ static void ath10k_sta_rc_update_wk(struct work_struct *wk) | |||
3453 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates\n", | 3502 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates\n", |
3454 | sta->addr); | 3503 | sta->addr); |
3455 | 3504 | ||
3456 | err = ath10k_station_assoc(ar, arvif, sta, true); | 3505 | err = ath10k_station_assoc(ar, arvif->vif, sta, true); |
3457 | if (err) | 3506 | if (err) |
3458 | ath10k_warn(ar, "failed to reassociate station: %pM\n", | 3507 | ath10k_warn(ar, "failed to reassociate station: %pM\n", |
3459 | sta->addr); | 3508 | sta->addr); |
@@ -3489,8 +3538,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
3489 | mutex_lock(&ar->conf_mutex); | 3538 | mutex_lock(&ar->conf_mutex); |
3490 | 3539 | ||
3491 | if (old_state == IEEE80211_STA_NOTEXIST && | 3540 | if (old_state == IEEE80211_STA_NOTEXIST && |
3492 | new_state == IEEE80211_STA_NONE && | 3541 | new_state == IEEE80211_STA_NONE) { |
3493 | vif->type != NL80211_IFTYPE_STATION) { | ||
3494 | /* | 3542 | /* |
3495 | * New station addition. | 3543 | * New station addition. |
3496 | */ | 3544 | */ |
@@ -3514,6 +3562,21 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
3514 | if (ret) | 3562 | if (ret) |
3515 | ath10k_warn(ar, "failed to add peer %pM for vdev %d when adding a new sta: %i\n", | 3563 | ath10k_warn(ar, "failed to add peer %pM for vdev %d when adding a new sta: %i\n", |
3516 | sta->addr, arvif->vdev_id, ret); | 3564 | sta->addr, arvif->vdev_id, ret); |
3565 | |||
3566 | if (vif->type == NL80211_IFTYPE_STATION) { | ||
3567 | WARN_ON(arvif->is_started); | ||
3568 | |||
3569 | ret = ath10k_vdev_start(arvif); | ||
3570 | if (ret) { | ||
3571 | ath10k_warn(ar, "failed to start vdev %i: %d\n", | ||
3572 | arvif->vdev_id, ret); | ||
3573 | WARN_ON(ath10k_peer_delete(ar, arvif->vdev_id, | ||
3574 | sta->addr)); | ||
3575 | goto exit; | ||
3576 | } | ||
3577 | |||
3578 | arvif->is_started = true; | ||
3579 | } | ||
3517 | } else if ((old_state == IEEE80211_STA_NONE && | 3580 | } else if ((old_state == IEEE80211_STA_NONE && |
3518 | new_state == IEEE80211_STA_NOTEXIST)) { | 3581 | new_state == IEEE80211_STA_NOTEXIST)) { |
3519 | /* | 3582 | /* |
@@ -3522,13 +3585,23 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
3522 | ath10k_dbg(ar, ATH10K_DBG_MAC, | 3585 | ath10k_dbg(ar, ATH10K_DBG_MAC, |
3523 | "mac vdev %d peer delete %pM (sta gone)\n", | 3586 | "mac vdev %d peer delete %pM (sta gone)\n", |
3524 | arvif->vdev_id, sta->addr); | 3587 | arvif->vdev_id, sta->addr); |
3588 | |||
3589 | if (vif->type == NL80211_IFTYPE_STATION) { | ||
3590 | WARN_ON(!arvif->is_started); | ||
3591 | |||
3592 | ret = ath10k_vdev_stop(arvif); | ||
3593 | if (ret) | ||
3594 | ath10k_warn(ar, "failed to stop vdev %i: %d\n", | ||
3595 | arvif->vdev_id, ret); | ||
3596 | |||
3597 | arvif->is_started = false; | ||
3598 | } | ||
3599 | |||
3525 | ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr); | 3600 | ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr); |
3526 | if (ret) | 3601 | if (ret) |
3527 | ath10k_warn(ar, "failed to delete peer %pM for vdev %d: %i\n", | 3602 | ath10k_warn(ar, "failed to delete peer %pM for vdev %d: %i\n", |
3528 | sta->addr, arvif->vdev_id, ret); | 3603 | sta->addr, arvif->vdev_id, ret); |
3529 | 3604 | ||
3530 | if (vif->type == NL80211_IFTYPE_STATION) | ||
3531 | ath10k_bss_disassoc(hw, vif); | ||
3532 | } else if (old_state == IEEE80211_STA_AUTH && | 3605 | } else if (old_state == IEEE80211_STA_AUTH && |
3533 | new_state == IEEE80211_STA_ASSOC && | 3606 | new_state == IEEE80211_STA_ASSOC && |
3534 | (vif->type == NL80211_IFTYPE_AP || | 3607 | (vif->type == NL80211_IFTYPE_AP || |
@@ -3539,7 +3612,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
3539 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM associated\n", | 3612 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM associated\n", |
3540 | sta->addr); | 3613 | sta->addr); |
3541 | 3614 | ||
3542 | ret = ath10k_station_assoc(ar, arvif, sta, false); | 3615 | ret = ath10k_station_assoc(ar, vif, sta, false); |
3543 | if (ret) | 3616 | if (ret) |
3544 | ath10k_warn(ar, "failed to associate station %pM for vdev %i: %i\n", | 3617 | ath10k_warn(ar, "failed to associate station %pM for vdev %i: %i\n", |
3545 | sta->addr, arvif->vdev_id, ret); | 3618 | sta->addr, arvif->vdev_id, ret); |
@@ -3553,7 +3626,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
3553 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM disassociated\n", | 3626 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM disassociated\n", |
3554 | sta->addr); | 3627 | sta->addr); |
3555 | 3628 | ||
3556 | ret = ath10k_station_disassoc(ar, arvif, sta); | 3629 | ret = ath10k_station_disassoc(ar, vif, sta); |
3557 | if (ret) | 3630 | if (ret) |
3558 | ath10k_warn(ar, "failed to disassociate station: %pM vdev %i: %i\n", | 3631 | ath10k_warn(ar, "failed to disassociate station: %pM vdev %i: %i\n", |
3559 | sta->addr, arvif->vdev_id, ret); | 3632 | sta->addr, arvif->vdev_id, ret); |
@@ -3761,10 +3834,11 @@ static int ath10k_cancel_remain_on_channel(struct ieee80211_hw *hw) | |||
3761 | struct ath10k *ar = hw->priv; | 3834 | struct ath10k *ar = hw->priv; |
3762 | 3835 | ||
3763 | mutex_lock(&ar->conf_mutex); | 3836 | mutex_lock(&ar->conf_mutex); |
3764 | cancel_delayed_work_sync(&ar->scan.timeout); | ||
3765 | ath10k_scan_abort(ar); | 3837 | ath10k_scan_abort(ar); |
3766 | mutex_unlock(&ar->conf_mutex); | 3838 | mutex_unlock(&ar->conf_mutex); |
3767 | 3839 | ||
3840 | cancel_delayed_work_sync(&ar->scan.timeout); | ||
3841 | |||
3768 | return 0; | 3842 | return 0; |
3769 | } | 3843 | } |
3770 | 3844 | ||
@@ -3807,7 +3881,7 @@ static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value) | |||
3807 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d fragmentation threshold %d\n", | 3881 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d fragmentation threshold %d\n", |
3808 | arvif->vdev_id, value); | 3882 | arvif->vdev_id, value); |
3809 | 3883 | ||
3810 | ret = ath10k_mac_set_rts(arvif, value); | 3884 | ret = ath10k_mac_set_frag(arvif, value); |
3811 | if (ret) { | 3885 | if (ret) { |
3812 | ath10k_warn(ar, "failed to set fragmentation threshold for vdev %d: %d\n", | 3886 | ath10k_warn(ar, "failed to set fragmentation threshold for vdev %d: %d\n", |
3813 | arvif->vdev_id, ret); | 3887 | arvif->vdev_id, ret); |
@@ -3843,7 +3917,9 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
3843 | empty = (ar->htt.num_pending_tx == 0); | 3917 | empty = (ar->htt.num_pending_tx == 0); |
3844 | spin_unlock_bh(&ar->htt.tx_lock); | 3918 | spin_unlock_bh(&ar->htt.tx_lock); |
3845 | 3919 | ||
3846 | skip = (ar->state == ATH10K_STATE_WEDGED); | 3920 | skip = (ar->state == ATH10K_STATE_WEDGED) || |
3921 | test_bit(ATH10K_FLAG_CRASH_FLUSH, | ||
3922 | &ar->dev_flags); | ||
3847 | 3923 | ||
3848 | (empty || skip); | 3924 | (empty || skip); |
3849 | }), ATH10K_FLUSH_TIMEOUT_HZ); | 3925 | }), ATH10K_FLUSH_TIMEOUT_HZ); |
@@ -3929,10 +4005,14 @@ exit: | |||
3929 | } | 4005 | } |
3930 | #endif | 4006 | #endif |
3931 | 4007 | ||
3932 | static void ath10k_restart_complete(struct ieee80211_hw *hw) | 4008 | static void ath10k_reconfig_complete(struct ieee80211_hw *hw, |
4009 | enum ieee80211_reconfig_type reconfig_type) | ||
3933 | { | 4010 | { |
3934 | struct ath10k *ar = hw->priv; | 4011 | struct ath10k *ar = hw->priv; |
3935 | 4012 | ||
4013 | if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART) | ||
4014 | return; | ||
4015 | |||
3936 | mutex_lock(&ar->conf_mutex); | 4016 | mutex_lock(&ar->conf_mutex); |
3937 | 4017 | ||
3938 | /* If device failed to restart it will be in a different state, e.g. | 4018 | /* If device failed to restart it will be in a different state, e.g. |
@@ -3940,6 +4020,7 @@ static void ath10k_restart_complete(struct ieee80211_hw *hw) | |||
3940 | if (ar->state == ATH10K_STATE_RESTARTED) { | 4020 | if (ar->state == ATH10K_STATE_RESTARTED) { |
3941 | ath10k_info(ar, "device successfully recovered\n"); | 4021 | ath10k_info(ar, "device successfully recovered\n"); |
3942 | ar->state = ATH10K_STATE_ON; | 4022 | ar->state = ATH10K_STATE_ON; |
4023 | ieee80211_wake_queues(ar->hw); | ||
3943 | } | 4024 | } |
3944 | 4025 | ||
3945 | mutex_unlock(&ar->conf_mutex); | 4026 | mutex_unlock(&ar->conf_mutex); |
@@ -3975,6 +4056,9 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int idx, | |||
3975 | 4056 | ||
3976 | survey->channel = &sband->channels[idx]; | 4057 | survey->channel = &sband->channels[idx]; |
3977 | 4058 | ||
4059 | if (ar->rx_channel == survey->channel) | ||
4060 | survey->filled |= SURVEY_INFO_IN_USE; | ||
4061 | |||
3978 | exit: | 4062 | exit: |
3979 | mutex_unlock(&ar->conf_mutex); | 4063 | mutex_unlock(&ar->conf_mutex); |
3980 | return ret; | 4064 | return ret; |
@@ -4450,12 +4534,15 @@ static const struct ieee80211_ops ath10k_ops = { | |||
4450 | .tx_last_beacon = ath10k_tx_last_beacon, | 4534 | .tx_last_beacon = ath10k_tx_last_beacon, |
4451 | .set_antenna = ath10k_set_antenna, | 4535 | .set_antenna = ath10k_set_antenna, |
4452 | .get_antenna = ath10k_get_antenna, | 4536 | .get_antenna = ath10k_get_antenna, |
4453 | .restart_complete = ath10k_restart_complete, | 4537 | .reconfig_complete = ath10k_reconfig_complete, |
4454 | .get_survey = ath10k_get_survey, | 4538 | .get_survey = ath10k_get_survey, |
4455 | .set_bitrate_mask = ath10k_set_bitrate_mask, | 4539 | .set_bitrate_mask = ath10k_set_bitrate_mask, |
4456 | .sta_rc_update = ath10k_sta_rc_update, | 4540 | .sta_rc_update = ath10k_sta_rc_update, |
4457 | .get_tsf = ath10k_get_tsf, | 4541 | .get_tsf = ath10k_get_tsf, |
4458 | .ampdu_action = ath10k_ampdu_action, | 4542 | .ampdu_action = ath10k_ampdu_action, |
4543 | .get_et_sset_count = ath10k_debug_get_et_sset_count, | ||
4544 | .get_et_stats = ath10k_debug_get_et_stats, | ||
4545 | .get_et_strings = ath10k_debug_get_et_strings, | ||
4459 | 4546 | ||
4460 | CFG80211_TESTMODE_CMD(ath10k_tm_cmd) | 4547 | CFG80211_TESTMODE_CMD(ath10k_tm_cmd) |
4461 | 4548 | ||
@@ -4800,15 +4887,6 @@ int ath10k_mac_register(struct ath10k *ar) | |||
4800 | BIT(NL80211_IFTYPE_STATION) | | 4887 | BIT(NL80211_IFTYPE_STATION) | |
4801 | BIT(NL80211_IFTYPE_AP); | 4888 | BIT(NL80211_IFTYPE_AP); |
4802 | 4889 | ||
4803 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { | ||
4804 | /* TODO: Have to deal with 2x2 chips if/when the come out. */ | ||
4805 | ar->supp_tx_chainmask = TARGET_10X_TX_CHAIN_MASK; | ||
4806 | ar->supp_rx_chainmask = TARGET_10X_RX_CHAIN_MASK; | ||
4807 | } else { | ||
4808 | ar->supp_tx_chainmask = TARGET_TX_CHAIN_MASK; | ||
4809 | ar->supp_rx_chainmask = TARGET_RX_CHAIN_MASK; | ||
4810 | } | ||
4811 | |||
4812 | ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask; | 4890 | ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask; |
4813 | ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask; | 4891 | ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask; |
4814 | 4892 | ||
@@ -4854,6 +4932,8 @@ int ath10k_mac_register(struct ath10k *ar) | |||
4854 | ar->hw->wiphy->max_remain_on_channel_duration = 5000; | 4932 | ar->hw->wiphy->max_remain_on_channel_duration = 5000; |
4855 | 4933 | ||
4856 | ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; | 4934 | ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; |
4935 | ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE; | ||
4936 | |||
4857 | /* | 4937 | /* |
4858 | * on LL hardware queues are managed entirely by the FW | 4938 | * on LL hardware queues are managed entirely by the FW |
4859 | * so we only advertise to mac we can do the queues thing | 4939 | * so we only advertise to mac we can do the queues thing |
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index 6c80eeada3e2..4e3c989aa841 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h | |||
@@ -39,6 +39,8 @@ void ath10k_offchan_tx_work(struct work_struct *work); | |||
39 | void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar); | 39 | void ath10k_mgmt_over_wmi_tx_purge(struct ath10k *ar); |
40 | void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work); | 40 | void ath10k_mgmt_over_wmi_tx_work(struct work_struct *work); |
41 | void ath10k_halt(struct ath10k *ar); | 41 | void ath10k_halt(struct ath10k *ar); |
42 | void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif); | ||
43 | void ath10k_drain_tx(struct ath10k *ar); | ||
42 | 44 | ||
43 | static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) | 45 | static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) |
44 | { | 46 | { |
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 59e0ea83be50..3a6b8a5ca96c 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c | |||
@@ -485,6 +485,8 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, | |||
485 | void *data_buf = NULL; | 485 | void *data_buf = NULL; |
486 | int i; | 486 | int i; |
487 | 487 | ||
488 | spin_lock_bh(&ar_pci->ce_lock); | ||
489 | |||
488 | ce_diag = ar_pci->ce_diag; | 490 | ce_diag = ar_pci->ce_diag; |
489 | 491 | ||
490 | /* | 492 | /* |
@@ -511,7 +513,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, | |||
511 | nbytes = min_t(unsigned int, remaining_bytes, | 513 | nbytes = min_t(unsigned int, remaining_bytes, |
512 | DIAG_TRANSFER_LIMIT); | 514 | DIAG_TRANSFER_LIMIT); |
513 | 515 | ||
514 | ret = ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data); | 516 | ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, ce_data); |
515 | if (ret != 0) | 517 | if (ret != 0) |
516 | goto done; | 518 | goto done; |
517 | 519 | ||
@@ -527,15 +529,15 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, | |||
527 | address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem, | 529 | address = TARG_CPU_SPACE_TO_CE_SPACE(ar, ar_pci->mem, |
528 | address); | 530 | address); |
529 | 531 | ||
530 | ret = ath10k_ce_send(ce_diag, NULL, (u32)address, nbytes, 0, | 532 | ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)address, nbytes, 0, |
531 | 0); | 533 | 0); |
532 | if (ret) | 534 | if (ret) |
533 | goto done; | 535 | goto done; |
534 | 536 | ||
535 | i = 0; | 537 | i = 0; |
536 | while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf, | 538 | while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf, |
537 | &completed_nbytes, | 539 | &completed_nbytes, |
538 | &id) != 0) { | 540 | &id) != 0) { |
539 | mdelay(1); | 541 | mdelay(1); |
540 | if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { | 542 | if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { |
541 | ret = -EBUSY; | 543 | ret = -EBUSY; |
@@ -554,9 +556,9 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data, | |||
554 | } | 556 | } |
555 | 557 | ||
556 | i = 0; | 558 | i = 0; |
557 | while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf, | 559 | while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, |
558 | &completed_nbytes, | 560 | &completed_nbytes, |
559 | &id, &flags) != 0) { | 561 | &id, &flags) != 0) { |
560 | mdelay(1); | 562 | mdelay(1); |
561 | 563 | ||
562 | if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { | 564 | if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { |
@@ -591,6 +593,8 @@ done: | |||
591 | dma_free_coherent(ar->dev, orig_nbytes, data_buf, | 593 | dma_free_coherent(ar->dev, orig_nbytes, data_buf, |
592 | ce_data_base); | 594 | ce_data_base); |
593 | 595 | ||
596 | spin_unlock_bh(&ar_pci->ce_lock); | ||
597 | |||
594 | return ret; | 598 | return ret; |
595 | } | 599 | } |
596 | 600 | ||
@@ -648,6 +652,8 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, | |||
648 | dma_addr_t ce_data_base = 0; | 652 | dma_addr_t ce_data_base = 0; |
649 | int i; | 653 | int i; |
650 | 654 | ||
655 | spin_lock_bh(&ar_pci->ce_lock); | ||
656 | |||
651 | ce_diag = ar_pci->ce_diag; | 657 | ce_diag = ar_pci->ce_diag; |
652 | 658 | ||
653 | /* | 659 | /* |
@@ -688,7 +694,7 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, | |||
688 | nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT); | 694 | nbytes = min_t(int, remaining_bytes, DIAG_TRANSFER_LIMIT); |
689 | 695 | ||
690 | /* Set up to receive directly into Target(!) address */ | 696 | /* Set up to receive directly into Target(!) address */ |
691 | ret = ath10k_ce_rx_post_buf(ce_diag, NULL, address); | 697 | ret = __ath10k_ce_rx_post_buf(ce_diag, NULL, address); |
692 | if (ret != 0) | 698 | if (ret != 0) |
693 | goto done; | 699 | goto done; |
694 | 700 | ||
@@ -696,15 +702,15 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, | |||
696 | * Request CE to send caller-supplied data that | 702 | * Request CE to send caller-supplied data that |
697 | * was copied to bounce buffer to Target(!) address. | 703 | * was copied to bounce buffer to Target(!) address. |
698 | */ | 704 | */ |
699 | ret = ath10k_ce_send(ce_diag, NULL, (u32)ce_data, | 705 | ret = ath10k_ce_send_nolock(ce_diag, NULL, (u32)ce_data, |
700 | nbytes, 0, 0); | 706 | nbytes, 0, 0); |
701 | if (ret != 0) | 707 | if (ret != 0) |
702 | goto done; | 708 | goto done; |
703 | 709 | ||
704 | i = 0; | 710 | i = 0; |
705 | while (ath10k_ce_completed_send_next(ce_diag, NULL, &buf, | 711 | while (ath10k_ce_completed_send_next_nolock(ce_diag, NULL, &buf, |
706 | &completed_nbytes, | 712 | &completed_nbytes, |
707 | &id) != 0) { | 713 | &id) != 0) { |
708 | mdelay(1); | 714 | mdelay(1); |
709 | 715 | ||
710 | if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { | 716 | if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { |
@@ -724,9 +730,9 @@ static int ath10k_pci_diag_write_mem(struct ath10k *ar, u32 address, | |||
724 | } | 730 | } |
725 | 731 | ||
726 | i = 0; | 732 | i = 0; |
727 | while (ath10k_ce_completed_recv_next(ce_diag, NULL, &buf, | 733 | while (ath10k_ce_completed_recv_next_nolock(ce_diag, NULL, &buf, |
728 | &completed_nbytes, | 734 | &completed_nbytes, |
729 | &id, &flags) != 0) { | 735 | &id, &flags) != 0) { |
730 | mdelay(1); | 736 | mdelay(1); |
731 | 737 | ||
732 | if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { | 738 | if (i++ > DIAG_ACCESS_CE_TIMEOUT_MS) { |
@@ -760,6 +766,8 @@ done: | |||
760 | ath10k_warn(ar, "failed to write diag value at 0x%x: %d\n", | 766 | ath10k_warn(ar, "failed to write diag value at 0x%x: %d\n", |
761 | address, ret); | 767 | address, ret); |
762 | 768 | ||
769 | spin_unlock_bh(&ar_pci->ce_lock); | ||
770 | |||
763 | return ret; | 771 | return ret; |
764 | } | 772 | } |
765 | 773 | ||
@@ -861,6 +869,12 @@ static void ath10k_pci_ce_recv_data(struct ath10k_ce_pipe *ce_state) | |||
861 | } | 869 | } |
862 | 870 | ||
863 | skb_put(skb, nbytes); | 871 | skb_put(skb, nbytes); |
872 | |||
873 | ath10k_dbg(ar, ATH10K_DBG_PCI, "pci rx ce pipe %d len %d\n", | ||
874 | ce_state->id, skb->len); | ||
875 | ath10k_dbg_dump(ar, ATH10K_DBG_PCI_DUMP, NULL, "pci rx: ", | ||
876 | skb->data, skb->len); | ||
877 | |||
864 | cb->rx_completion(ar, skb, pipe_info->pipe_num); | 878 | cb->rx_completion(ar, skb, pipe_info->pipe_num); |
865 | } | 879 | } |
866 | 880 | ||
@@ -936,6 +950,12 @@ err: | |||
936 | return err; | 950 | return err; |
937 | } | 951 | } |
938 | 952 | ||
953 | static int ath10k_pci_hif_diag_read(struct ath10k *ar, u32 address, void *buf, | ||
954 | size_t buf_len) | ||
955 | { | ||
956 | return ath10k_pci_diag_read_mem(ar, address, buf, buf_len); | ||
957 | } | ||
958 | |||
939 | static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) | 959 | static u16 ath10k_pci_hif_get_free_queue_number(struct ath10k *ar, u8 pipe) |
940 | { | 960 | { |
941 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 961 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
@@ -986,6 +1006,8 @@ static void ath10k_pci_fw_crashed_dump(struct ath10k *ar) | |||
986 | 1006 | ||
987 | spin_lock_bh(&ar->data_lock); | 1007 | spin_lock_bh(&ar->data_lock); |
988 | 1008 | ||
1009 | ar->stats.fw_crash_counter++; | ||
1010 | |||
989 | crash_data = ath10k_debug_get_new_fw_crash_data(ar); | 1011 | crash_data = ath10k_debug_get_new_fw_crash_data(ar); |
990 | 1012 | ||
991 | if (crash_data) | 1013 | if (crash_data) |
@@ -1121,14 +1143,37 @@ static void ath10k_pci_hif_get_default_pipe(struct ath10k *ar, | |||
1121 | &dl_is_polled); | 1143 | &dl_is_polled); |
1122 | } | 1144 | } |
1123 | 1145 | ||
1124 | static void ath10k_pci_irq_disable(struct ath10k *ar) | 1146 | static void ath10k_pci_irq_msi_fw_mask(struct ath10k *ar) |
1125 | { | 1147 | { |
1126 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1148 | u32 val; |
1127 | int i; | 1149 | |
1150 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS); | ||
1151 | val &= ~CORE_CTRL_PCIE_REG_31_MASK; | ||
1152 | |||
1153 | ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val); | ||
1154 | } | ||
1155 | |||
1156 | static void ath10k_pci_irq_msi_fw_unmask(struct ath10k *ar) | ||
1157 | { | ||
1158 | u32 val; | ||
1128 | 1159 | ||
1160 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS); | ||
1161 | val |= CORE_CTRL_PCIE_REG_31_MASK; | ||
1162 | |||
1163 | ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + CORE_CTRL_ADDRESS, val); | ||
1164 | } | ||
1165 | |||
1166 | static void ath10k_pci_irq_disable(struct ath10k *ar) | ||
1167 | { | ||
1129 | ath10k_ce_disable_interrupts(ar); | 1168 | ath10k_ce_disable_interrupts(ar); |
1130 | ath10k_pci_disable_and_clear_legacy_irq(ar); | 1169 | ath10k_pci_disable_and_clear_legacy_irq(ar); |
1131 | /* FIXME: How to mask all MSI interrupts? */ | 1170 | ath10k_pci_irq_msi_fw_mask(ar); |
1171 | } | ||
1172 | |||
1173 | static void ath10k_pci_irq_sync(struct ath10k *ar) | ||
1174 | { | ||
1175 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | ||
1176 | int i; | ||
1132 | 1177 | ||
1133 | for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++) | 1178 | for (i = 0; i < max(1, ar_pci->num_msi_intrs); i++) |
1134 | synchronize_irq(ar_pci->pdev->irq + i); | 1179 | synchronize_irq(ar_pci->pdev->irq + i); |
@@ -1138,7 +1183,7 @@ static void ath10k_pci_irq_enable(struct ath10k *ar) | |||
1138 | { | 1183 | { |
1139 | ath10k_ce_enable_interrupts(ar); | 1184 | ath10k_ce_enable_interrupts(ar); |
1140 | ath10k_pci_enable_legacy_irq(ar); | 1185 | ath10k_pci_enable_legacy_irq(ar); |
1141 | /* FIXME: How to unmask all MSI interrupts? */ | 1186 | ath10k_pci_irq_msi_fw_unmask(ar); |
1142 | } | 1187 | } |
1143 | 1188 | ||
1144 | static int ath10k_pci_hif_start(struct ath10k *ar) | 1189 | static int ath10k_pci_hif_start(struct ath10k *ar) |
@@ -1151,64 +1196,74 @@ static int ath10k_pci_hif_start(struct ath10k *ar) | |||
1151 | return 0; | 1196 | return 0; |
1152 | } | 1197 | } |
1153 | 1198 | ||
1154 | static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info) | 1199 | static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) |
1155 | { | 1200 | { |
1156 | struct ath10k *ar; | 1201 | struct ath10k *ar; |
1157 | struct ath10k_pci *ar_pci; | 1202 | struct ath10k_ce_pipe *ce_pipe; |
1158 | struct ath10k_ce_pipe *ce_hdl; | 1203 | struct ath10k_ce_ring *ce_ring; |
1159 | u32 buf_sz; | 1204 | struct sk_buff *skb; |
1160 | struct sk_buff *netbuf; | 1205 | int i; |
1161 | u32 ce_data; | ||
1162 | 1206 | ||
1163 | buf_sz = pipe_info->buf_sz; | 1207 | ar = pci_pipe->hif_ce_state; |
1208 | ce_pipe = pci_pipe->ce_hdl; | ||
1209 | ce_ring = ce_pipe->dest_ring; | ||
1164 | 1210 | ||
1165 | /* Unused Copy Engine */ | 1211 | if (!ce_ring) |
1166 | if (buf_sz == 0) | ||
1167 | return; | 1212 | return; |
1168 | 1213 | ||
1169 | ar = pipe_info->hif_ce_state; | 1214 | if (!pci_pipe->buf_sz) |
1170 | ar_pci = ath10k_pci_priv(ar); | 1215 | return; |
1171 | ce_hdl = pipe_info->ce_hdl; | ||
1172 | 1216 | ||
1173 | while (ath10k_ce_revoke_recv_next(ce_hdl, (void **)&netbuf, | 1217 | for (i = 0; i < ce_ring->nentries; i++) { |
1174 | &ce_data) == 0) { | 1218 | skb = ce_ring->per_transfer_context[i]; |
1175 | dma_unmap_single(ar->dev, ATH10K_SKB_CB(netbuf)->paddr, | 1219 | if (!skb) |
1176 | netbuf->len + skb_tailroom(netbuf), | 1220 | continue; |
1221 | |||
1222 | ce_ring->per_transfer_context[i] = NULL; | ||
1223 | |||
1224 | dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr, | ||
1225 | skb->len + skb_tailroom(skb), | ||
1177 | DMA_FROM_DEVICE); | 1226 | DMA_FROM_DEVICE); |
1178 | dev_kfree_skb_any(netbuf); | 1227 | dev_kfree_skb_any(skb); |
1179 | } | 1228 | } |
1180 | } | 1229 | } |
1181 | 1230 | ||
1182 | static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info) | 1231 | static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) |
1183 | { | 1232 | { |
1184 | struct ath10k *ar; | 1233 | struct ath10k *ar; |
1185 | struct ath10k_pci *ar_pci; | 1234 | struct ath10k_pci *ar_pci; |
1186 | struct ath10k_ce_pipe *ce_hdl; | 1235 | struct ath10k_ce_pipe *ce_pipe; |
1187 | struct sk_buff *netbuf; | 1236 | struct ath10k_ce_ring *ce_ring; |
1188 | u32 ce_data; | 1237 | struct ce_desc *ce_desc; |
1189 | unsigned int nbytes; | 1238 | struct sk_buff *skb; |
1190 | unsigned int id; | 1239 | unsigned int id; |
1191 | u32 buf_sz; | 1240 | int i; |
1192 | 1241 | ||
1193 | buf_sz = pipe_info->buf_sz; | 1242 | ar = pci_pipe->hif_ce_state; |
1243 | ar_pci = ath10k_pci_priv(ar); | ||
1244 | ce_pipe = pci_pipe->ce_hdl; | ||
1245 | ce_ring = ce_pipe->src_ring; | ||
1194 | 1246 | ||
1195 | /* Unused Copy Engine */ | 1247 | if (!ce_ring) |
1196 | if (buf_sz == 0) | ||
1197 | return; | 1248 | return; |
1198 | 1249 | ||
1199 | ar = pipe_info->hif_ce_state; | 1250 | if (!pci_pipe->buf_sz) |
1200 | ar_pci = ath10k_pci_priv(ar); | 1251 | return; |
1201 | ce_hdl = pipe_info->ce_hdl; | ||
1202 | 1252 | ||
1203 | while (ath10k_ce_cancel_send_next(ce_hdl, (void **)&netbuf, | 1253 | ce_desc = ce_ring->shadow_base; |
1204 | &ce_data, &nbytes, &id) == 0) { | 1254 | if (WARN_ON(!ce_desc)) |
1205 | /* no need to call tx completion for NULL pointers */ | 1255 | return; |
1206 | if (!netbuf) | 1256 | |
1257 | for (i = 0; i < ce_ring->nentries; i++) { | ||
1258 | skb = ce_ring->per_transfer_context[i]; | ||
1259 | if (!skb) | ||
1207 | continue; | 1260 | continue; |
1208 | 1261 | ||
1209 | ar_pci->msg_callbacks_current.tx_completion(ar, | 1262 | ce_ring->per_transfer_context[i] = NULL; |
1210 | netbuf, | 1263 | id = MS(__le16_to_cpu(ce_desc[i].flags), |
1211 | id); | 1264 | CE_DESC_FLAGS_META_DATA); |
1265 | |||
1266 | ar_pci->msg_callbacks_current.tx_completion(ar, skb, id); | ||
1212 | } | 1267 | } |
1213 | } | 1268 | } |
1214 | 1269 | ||
@@ -1266,6 +1321,7 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) | |||
1266 | ath10k_pci_warm_reset(ar); | 1321 | ath10k_pci_warm_reset(ar); |
1267 | 1322 | ||
1268 | ath10k_pci_irq_disable(ar); | 1323 | ath10k_pci_irq_disable(ar); |
1324 | ath10k_pci_irq_sync(ar); | ||
1269 | ath10k_pci_flush(ar); | 1325 | ath10k_pci_flush(ar); |
1270 | } | 1326 | } |
1271 | 1327 | ||
@@ -1386,6 +1442,9 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) | |||
1386 | &nbytes, &transfer_id, &flags)) | 1442 | &nbytes, &transfer_id, &flags)) |
1387 | return; | 1443 | return; |
1388 | 1444 | ||
1445 | if (WARN_ON_ONCE(!xfer)) | ||
1446 | return; | ||
1447 | |||
1389 | if (!xfer->wait_for_resp) { | 1448 | if (!xfer->wait_for_resp) { |
1390 | ath10k_warn(ar, "unexpected: BMI data received; ignoring\n"); | 1449 | ath10k_warn(ar, "unexpected: BMI data received; ignoring\n"); |
1391 | return; | 1450 | return; |
@@ -1569,23 +1628,40 @@ static int ath10k_pci_init_config(struct ath10k *ar) | |||
1569 | return 0; | 1628 | return 0; |
1570 | } | 1629 | } |
1571 | 1630 | ||
1572 | static int ath10k_pci_alloc_ce(struct ath10k *ar) | 1631 | static int ath10k_pci_alloc_pipes(struct ath10k *ar) |
1573 | { | 1632 | { |
1633 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | ||
1634 | struct ath10k_pci_pipe *pipe; | ||
1574 | int i, ret; | 1635 | int i, ret; |
1575 | 1636 | ||
1576 | for (i = 0; i < CE_COUNT; i++) { | 1637 | for (i = 0; i < CE_COUNT; i++) { |
1577 | ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i]); | 1638 | pipe = &ar_pci->pipe_info[i]; |
1639 | pipe->ce_hdl = &ar_pci->ce_states[i]; | ||
1640 | pipe->pipe_num = i; | ||
1641 | pipe->hif_ce_state = ar; | ||
1642 | |||
1643 | ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i], | ||
1644 | ath10k_pci_ce_send_done, | ||
1645 | ath10k_pci_ce_recv_data); | ||
1578 | if (ret) { | 1646 | if (ret) { |
1579 | ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n", | 1647 | ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n", |
1580 | i, ret); | 1648 | i, ret); |
1581 | return ret; | 1649 | return ret; |
1582 | } | 1650 | } |
1651 | |||
1652 | /* Last CE is Diagnostic Window */ | ||
1653 | if (i == CE_COUNT - 1) { | ||
1654 | ar_pci->ce_diag = pipe->ce_hdl; | ||
1655 | continue; | ||
1656 | } | ||
1657 | |||
1658 | pipe->buf_sz = (size_t)(host_ce_config_wlan[i].src_sz_max); | ||
1583 | } | 1659 | } |
1584 | 1660 | ||
1585 | return 0; | 1661 | return 0; |
1586 | } | 1662 | } |
1587 | 1663 | ||
1588 | static void ath10k_pci_free_ce(struct ath10k *ar) | 1664 | static void ath10k_pci_free_pipes(struct ath10k *ar) |
1589 | { | 1665 | { |
1590 | int i; | 1666 | int i; |
1591 | 1667 | ||
@@ -1593,39 +1669,17 @@ static void ath10k_pci_free_ce(struct ath10k *ar) | |||
1593 | ath10k_ce_free_pipe(ar, i); | 1669 | ath10k_ce_free_pipe(ar, i); |
1594 | } | 1670 | } |
1595 | 1671 | ||
1596 | static int ath10k_pci_ce_init(struct ath10k *ar) | 1672 | static int ath10k_pci_init_pipes(struct ath10k *ar) |
1597 | { | 1673 | { |
1598 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1674 | int i, ret; |
1599 | struct ath10k_pci_pipe *pipe_info; | ||
1600 | const struct ce_attr *attr; | ||
1601 | int pipe_num, ret; | ||
1602 | 1675 | ||
1603 | for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) { | 1676 | for (i = 0; i < CE_COUNT; i++) { |
1604 | pipe_info = &ar_pci->pipe_info[pipe_num]; | 1677 | ret = ath10k_ce_init_pipe(ar, i, &host_ce_config_wlan[i]); |
1605 | pipe_info->ce_hdl = &ar_pci->ce_states[pipe_num]; | ||
1606 | pipe_info->pipe_num = pipe_num; | ||
1607 | pipe_info->hif_ce_state = ar; | ||
1608 | attr = &host_ce_config_wlan[pipe_num]; | ||
1609 | |||
1610 | ret = ath10k_ce_init_pipe(ar, pipe_num, attr, | ||
1611 | ath10k_pci_ce_send_done, | ||
1612 | ath10k_pci_ce_recv_data); | ||
1613 | if (ret) { | 1678 | if (ret) { |
1614 | ath10k_err(ar, "failed to initialize copy engine pipe %d: %d\n", | 1679 | ath10k_err(ar, "failed to initialize copy engine pipe %d: %d\n", |
1615 | pipe_num, ret); | 1680 | i, ret); |
1616 | return ret; | 1681 | return ret; |
1617 | } | 1682 | } |
1618 | |||
1619 | if (pipe_num == CE_COUNT - 1) { | ||
1620 | /* | ||
1621 | * Reserve the ultimate CE for | ||
1622 | * diagnostic Window support | ||
1623 | */ | ||
1624 | ar_pci->ce_diag = pipe_info->ce_hdl; | ||
1625 | continue; | ||
1626 | } | ||
1627 | |||
1628 | pipe_info->buf_sz = (size_t)(attr->src_sz_max); | ||
1629 | } | 1683 | } |
1630 | 1684 | ||
1631 | return 0; | 1685 | return 0; |
@@ -1666,93 +1720,167 @@ static void ath10k_pci_warm_reset_si0(struct ath10k *ar) | |||
1666 | msleep(10); | 1720 | msleep(10); |
1667 | } | 1721 | } |
1668 | 1722 | ||
1669 | static int ath10k_pci_warm_reset(struct ath10k *ar) | 1723 | static void ath10k_pci_warm_reset_cpu(struct ath10k *ar) |
1670 | { | 1724 | { |
1671 | u32 val; | 1725 | u32 val; |
1672 | 1726 | ||
1673 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n"); | 1727 | ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, 0); |
1674 | |||
1675 | /* debug */ | ||
1676 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + | ||
1677 | PCIE_INTR_CAUSE_ADDRESS); | ||
1678 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n", | ||
1679 | val); | ||
1680 | 1728 | ||
1681 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + | 1729 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + |
1682 | CPU_INTR_ADDRESS); | 1730 | SOC_RESET_CONTROL_ADDRESS); |
1683 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n", | 1731 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, |
1684 | val); | 1732 | val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK); |
1733 | } | ||
1685 | 1734 | ||
1686 | /* disable pending irqs */ | 1735 | static void ath10k_pci_warm_reset_ce(struct ath10k *ar) |
1687 | ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + | 1736 | { |
1688 | PCIE_INTR_ENABLE_ADDRESS, 0); | 1737 | u32 val; |
1689 | 1738 | ||
1690 | ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + | 1739 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + |
1691 | PCIE_INTR_CLR_ADDRESS, ~0); | 1740 | SOC_RESET_CONTROL_ADDRESS); |
1692 | 1741 | ||
1693 | msleep(100); | 1742 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, |
1743 | val | SOC_RESET_CONTROL_CE_RST_MASK); | ||
1744 | msleep(10); | ||
1745 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, | ||
1746 | val & ~SOC_RESET_CONTROL_CE_RST_MASK); | ||
1747 | } | ||
1694 | 1748 | ||
1695 | /* clear fw indicator */ | 1749 | static void ath10k_pci_warm_reset_clear_lf(struct ath10k *ar) |
1696 | ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, 0); | 1750 | { |
1751 | u32 val; | ||
1697 | 1752 | ||
1698 | /* clear target LF timer interrupts */ | ||
1699 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + | 1753 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + |
1700 | SOC_LF_TIMER_CONTROL0_ADDRESS); | 1754 | SOC_LF_TIMER_CONTROL0_ADDRESS); |
1701 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + | 1755 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + |
1702 | SOC_LF_TIMER_CONTROL0_ADDRESS, | 1756 | SOC_LF_TIMER_CONTROL0_ADDRESS, |
1703 | val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK); | 1757 | val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK); |
1758 | } | ||
1704 | 1759 | ||
1705 | /* reset CE */ | 1760 | static int ath10k_pci_warm_reset(struct ath10k *ar) |
1706 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + | 1761 | { |
1707 | SOC_RESET_CONTROL_ADDRESS); | 1762 | int ret; |
1708 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, | ||
1709 | val | SOC_RESET_CONTROL_CE_RST_MASK); | ||
1710 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + | ||
1711 | SOC_RESET_CONTROL_ADDRESS); | ||
1712 | msleep(10); | ||
1713 | 1763 | ||
1714 | /* unreset CE */ | 1764 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n"); |
1715 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, | 1765 | |
1716 | val & ~SOC_RESET_CONTROL_CE_RST_MASK); | 1766 | spin_lock_bh(&ar->data_lock); |
1717 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + | 1767 | ar->stats.fw_warm_reset_counter++; |
1718 | SOC_RESET_CONTROL_ADDRESS); | 1768 | spin_unlock_bh(&ar->data_lock); |
1719 | msleep(10); | 1769 | |
1770 | ath10k_pci_irq_disable(ar); | ||
1720 | 1771 | ||
1772 | /* Make sure the target CPU is not doing anything dangerous, e.g. if it | ||
1773 | * were to access copy engine while host performs copy engine reset | ||
1774 | * then it is possible for the device to confuse pci-e controller to | ||
1775 | * the point of bringing host system to a complete stop (i.e. hang). | ||
1776 | */ | ||
1721 | ath10k_pci_warm_reset_si0(ar); | 1777 | ath10k_pci_warm_reset_si0(ar); |
1778 | ath10k_pci_warm_reset_cpu(ar); | ||
1779 | ath10k_pci_init_pipes(ar); | ||
1780 | ath10k_pci_wait_for_target_init(ar); | ||
1722 | 1781 | ||
1723 | /* debug */ | 1782 | ath10k_pci_warm_reset_clear_lf(ar); |
1724 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + | 1783 | ath10k_pci_warm_reset_ce(ar); |
1725 | PCIE_INTR_CAUSE_ADDRESS); | 1784 | ath10k_pci_warm_reset_cpu(ar); |
1726 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n", | 1785 | ath10k_pci_init_pipes(ar); |
1727 | val); | ||
1728 | 1786 | ||
1729 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + | 1787 | ret = ath10k_pci_wait_for_target_init(ar); |
1730 | CPU_INTR_ADDRESS); | 1788 | if (ret) { |
1731 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n", | 1789 | ath10k_warn(ar, "failed to wait for target init: %d\n", ret); |
1732 | val); | 1790 | return ret; |
1791 | } | ||
1733 | 1792 | ||
1734 | /* CPU warm reset */ | 1793 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset complete\n"); |
1735 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + | ||
1736 | SOC_RESET_CONTROL_ADDRESS); | ||
1737 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, | ||
1738 | val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK); | ||
1739 | 1794 | ||
1740 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + | 1795 | return 0; |
1741 | SOC_RESET_CONTROL_ADDRESS); | 1796 | } |
1742 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target reset state: 0x%08x\n", | 1797 | |
1743 | val); | 1798 | static int ath10k_pci_chip_reset(struct ath10k *ar) |
1799 | { | ||
1800 | int i, ret; | ||
1801 | u32 val; | ||
1744 | 1802 | ||
1745 | msleep(100); | 1803 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset\n"); |
1746 | 1804 | ||
1747 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset complete\n"); | 1805 | /* Some hardware revisions (e.g. CUS223v2) has issues with cold reset. |
1806 | * It is thus preferred to use warm reset which is safer but may not be | ||
1807 | * able to recover the device from all possible fail scenarios. | ||
1808 | * | ||
1809 | * Warm reset doesn't always work on first try so attempt it a few | ||
1810 | * times before giving up. | ||
1811 | */ | ||
1812 | for (i = 0; i < ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS; i++) { | ||
1813 | ret = ath10k_pci_warm_reset(ar); | ||
1814 | if (ret) { | ||
1815 | ath10k_warn(ar, "failed to warm reset attempt %d of %d: %d\n", | ||
1816 | i + 1, ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS, | ||
1817 | ret); | ||
1818 | continue; | ||
1819 | } | ||
1820 | |||
1821 | /* FIXME: Sometimes copy engine doesn't recover after warm | ||
1822 | * reset. In most cases this needs cold reset. In some of these | ||
1823 | * cases the device is in such a state that a cold reset may | ||
1824 | * lock up the host. | ||
1825 | * | ||
1826 | * Reading any host interest register via copy engine is | ||
1827 | * sufficient to verify if device is capable of booting | ||
1828 | * firmware blob. | ||
1829 | */ | ||
1830 | ret = ath10k_pci_init_pipes(ar); | ||
1831 | if (ret) { | ||
1832 | ath10k_warn(ar, "failed to init copy engine: %d\n", | ||
1833 | ret); | ||
1834 | continue; | ||
1835 | } | ||
1836 | |||
1837 | ret = ath10k_pci_diag_read32(ar, QCA988X_HOST_INTEREST_ADDRESS, | ||
1838 | &val); | ||
1839 | if (ret) { | ||
1840 | ath10k_warn(ar, "failed to poke copy engine: %d\n", | ||
1841 | ret); | ||
1842 | continue; | ||
1843 | } | ||
1844 | |||
1845 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset complete (warm)\n"); | ||
1846 | return 0; | ||
1847 | } | ||
1848 | |||
1849 | if (ath10k_pci_reset_mode == ATH10K_PCI_RESET_WARM_ONLY) { | ||
1850 | ath10k_warn(ar, "refusing cold reset as requested\n"); | ||
1851 | return -EPERM; | ||
1852 | } | ||
1853 | |||
1854 | ret = ath10k_pci_cold_reset(ar); | ||
1855 | if (ret) { | ||
1856 | ath10k_warn(ar, "failed to cold reset: %d\n", ret); | ||
1857 | return ret; | ||
1858 | } | ||
1859 | |||
1860 | ret = ath10k_pci_wait_for_target_init(ar); | ||
1861 | if (ret) { | ||
1862 | ath10k_warn(ar, "failed to wait for target after cold reset: %d\n", | ||
1863 | ret); | ||
1864 | return ret; | ||
1865 | } | ||
1866 | |||
1867 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset complete (cold)\n"); | ||
1748 | 1868 | ||
1749 | return 0; | 1869 | return 0; |
1750 | } | 1870 | } |
1751 | 1871 | ||
1752 | static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset) | 1872 | static int ath10k_pci_hif_power_up(struct ath10k *ar) |
1753 | { | 1873 | { |
1754 | int ret; | 1874 | int ret; |
1755 | 1875 | ||
1876 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power up\n"); | ||
1877 | |||
1878 | ret = ath10k_pci_wake(ar); | ||
1879 | if (ret) { | ||
1880 | ath10k_err(ar, "failed to wake up target: %d\n", ret); | ||
1881 | return ret; | ||
1882 | } | ||
1883 | |||
1756 | /* | 1884 | /* |
1757 | * Bring the target up cleanly. | 1885 | * Bring the target up cleanly. |
1758 | * | 1886 | * |
@@ -1763,26 +1891,16 @@ static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset) | |||
1763 | * is in an unexpected state. We try to catch that here in order to | 1891 | * is in an unexpected state. We try to catch that here in order to |
1764 | * reset the Target and retry the probe. | 1892 | * reset the Target and retry the probe. |
1765 | */ | 1893 | */ |
1766 | if (cold_reset) | 1894 | ret = ath10k_pci_chip_reset(ar); |
1767 | ret = ath10k_pci_cold_reset(ar); | ||
1768 | else | ||
1769 | ret = ath10k_pci_warm_reset(ar); | ||
1770 | |||
1771 | if (ret) { | 1895 | if (ret) { |
1772 | ath10k_err(ar, "failed to reset target: %d\n", ret); | 1896 | ath10k_err(ar, "failed to reset chip: %d\n", ret); |
1773 | goto err; | 1897 | goto err_sleep; |
1774 | } | 1898 | } |
1775 | 1899 | ||
1776 | ret = ath10k_pci_ce_init(ar); | 1900 | ret = ath10k_pci_init_pipes(ar); |
1777 | if (ret) { | 1901 | if (ret) { |
1778 | ath10k_err(ar, "failed to initialize CE: %d\n", ret); | 1902 | ath10k_err(ar, "failed to initialize CE: %d\n", ret); |
1779 | goto err; | 1903 | goto err_sleep; |
1780 | } | ||
1781 | |||
1782 | ret = ath10k_pci_wait_for_target_init(ar); | ||
1783 | if (ret) { | ||
1784 | ath10k_err(ar, "failed to wait for target to init: %d\n", ret); | ||
1785 | goto err_ce; | ||
1786 | } | 1904 | } |
1787 | 1905 | ||
1788 | ret = ath10k_pci_init_config(ar); | 1906 | ret = ath10k_pci_init_config(ar); |
@@ -1801,73 +1919,21 @@ static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset) | |||
1801 | 1919 | ||
1802 | err_ce: | 1920 | err_ce: |
1803 | ath10k_pci_ce_deinit(ar); | 1921 | ath10k_pci_ce_deinit(ar); |
1804 | ath10k_pci_warm_reset(ar); | ||
1805 | err: | ||
1806 | return ret; | ||
1807 | } | ||
1808 | |||
1809 | static int ath10k_pci_hif_power_up_warm(struct ath10k *ar) | ||
1810 | { | ||
1811 | int i, ret; | ||
1812 | |||
1813 | /* | ||
1814 | * Sometime warm reset succeeds after retries. | ||
1815 | * | ||
1816 | * FIXME: It might be possible to tune ath10k_pci_warm_reset() to work | ||
1817 | * at first try. | ||
1818 | */ | ||
1819 | for (i = 0; i < ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS; i++) { | ||
1820 | ret = __ath10k_pci_hif_power_up(ar, false); | ||
1821 | if (ret == 0) | ||
1822 | break; | ||
1823 | |||
1824 | ath10k_warn(ar, "failed to warm reset (attempt %d out of %d): %d\n", | ||
1825 | i + 1, ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS, ret); | ||
1826 | } | ||
1827 | 1922 | ||
1923 | err_sleep: | ||
1924 | ath10k_pci_sleep(ar); | ||
1828 | return ret; | 1925 | return ret; |
1829 | } | 1926 | } |
1830 | 1927 | ||
1831 | static int ath10k_pci_hif_power_up(struct ath10k *ar) | ||
1832 | { | ||
1833 | int ret; | ||
1834 | |||
1835 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power up\n"); | ||
1836 | |||
1837 | /* | ||
1838 | * Hardware CUS232 version 2 has some issues with cold reset and the | ||
1839 | * preferred (and safer) way to perform a device reset is through a | ||
1840 | * warm reset. | ||
1841 | * | ||
1842 | * Warm reset doesn't always work though so fall back to cold reset may | ||
1843 | * be necessary. | ||
1844 | */ | ||
1845 | ret = ath10k_pci_hif_power_up_warm(ar); | ||
1846 | if (ret) { | ||
1847 | ath10k_warn(ar, "failed to power up target using warm reset: %d\n", | ||
1848 | ret); | ||
1849 | |||
1850 | if (ath10k_pci_reset_mode == ATH10K_PCI_RESET_WARM_ONLY) | ||
1851 | return ret; | ||
1852 | |||
1853 | ath10k_warn(ar, "trying cold reset\n"); | ||
1854 | |||
1855 | ret = __ath10k_pci_hif_power_up(ar, true); | ||
1856 | if (ret) { | ||
1857 | ath10k_err(ar, "failed to power up target using cold reset too (%d)\n", | ||
1858 | ret); | ||
1859 | return ret; | ||
1860 | } | ||
1861 | } | ||
1862 | |||
1863 | return 0; | ||
1864 | } | ||
1865 | |||
1866 | static void ath10k_pci_hif_power_down(struct ath10k *ar) | 1928 | static void ath10k_pci_hif_power_down(struct ath10k *ar) |
1867 | { | 1929 | { |
1868 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power down\n"); | 1930 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power down\n"); |
1869 | 1931 | ||
1870 | ath10k_pci_warm_reset(ar); | 1932 | /* Currently hif_power_up performs effectively a reset and hif_stop |
1933 | * resets the chip as well so there's no point in resetting here. | ||
1934 | */ | ||
1935 | |||
1936 | ath10k_pci_sleep(ar); | ||
1871 | } | 1937 | } |
1872 | 1938 | ||
1873 | #ifdef CONFIG_PM | 1939 | #ifdef CONFIG_PM |
@@ -1921,6 +1987,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar) | |||
1921 | 1987 | ||
1922 | static const struct ath10k_hif_ops ath10k_pci_hif_ops = { | 1988 | static const struct ath10k_hif_ops ath10k_pci_hif_ops = { |
1923 | .tx_sg = ath10k_pci_hif_tx_sg, | 1989 | .tx_sg = ath10k_pci_hif_tx_sg, |
1990 | .diag_read = ath10k_pci_hif_diag_read, | ||
1924 | .exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg, | 1991 | .exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg, |
1925 | .start = ath10k_pci_hif_start, | 1992 | .start = ath10k_pci_hif_start, |
1926 | .stop = ath10k_pci_hif_stop, | 1993 | .stop = ath10k_pci_hif_stop, |
@@ -2250,14 +2317,14 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar) | |||
2250 | 2317 | ||
2251 | if (ar_pci->num_msi_intrs == 0) | 2318 | if (ar_pci->num_msi_intrs == 0) |
2252 | /* Fix potential race by repeating CORE_BASE writes */ | 2319 | /* Fix potential race by repeating CORE_BASE writes */ |
2253 | ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + | 2320 | ath10k_pci_enable_legacy_irq(ar); |
2254 | PCIE_INTR_ENABLE_ADDRESS, | ||
2255 | PCIE_INTR_FIRMWARE_MASK | | ||
2256 | PCIE_INTR_CE_MASK_ALL); | ||
2257 | 2321 | ||
2258 | mdelay(10); | 2322 | mdelay(10); |
2259 | } while (time_before(jiffies, timeout)); | 2323 | } while (time_before(jiffies, timeout)); |
2260 | 2324 | ||
2325 | ath10k_pci_disable_and_clear_legacy_irq(ar); | ||
2326 | ath10k_pci_irq_msi_fw_mask(ar); | ||
2327 | |||
2261 | if (val == 0xffffffff) { | 2328 | if (val == 0xffffffff) { |
2262 | ath10k_err(ar, "failed to read device register, device is gone\n"); | 2329 | ath10k_err(ar, "failed to read device register, device is gone\n"); |
2263 | return -EIO; | 2330 | return -EIO; |
@@ -2287,6 +2354,12 @@ static int ath10k_pci_cold_reset(struct ath10k *ar) | |||
2287 | 2354 | ||
2288 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n"); | 2355 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n"); |
2289 | 2356 | ||
2357 | spin_lock_bh(&ar->data_lock); | ||
2358 | |||
2359 | ar->stats.fw_cold_reset_counter++; | ||
2360 | |||
2361 | spin_unlock_bh(&ar->data_lock); | ||
2362 | |||
2290 | /* Put Target, including PCIe, into RESET. */ | 2363 | /* Put Target, including PCIe, into RESET. */ |
2291 | val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS); | 2364 | val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS); |
2292 | val |= 1; | 2365 | val |= 1; |
@@ -2400,6 +2473,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
2400 | u32 chip_id; | 2473 | u32 chip_id; |
2401 | 2474 | ||
2402 | ar = ath10k_core_create(sizeof(*ar_pci), &pdev->dev, | 2475 | ar = ath10k_core_create(sizeof(*ar_pci), &pdev->dev, |
2476 | ATH10K_BUS_PCI, | ||
2403 | &ath10k_pci_hif_ops); | 2477 | &ath10k_pci_hif_ops); |
2404 | if (!ar) { | 2478 | if (!ar) { |
2405 | dev_err(&pdev->dev, "failed to allocate core\n"); | 2479 | dev_err(&pdev->dev, "failed to allocate core\n"); |
@@ -2435,7 +2509,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
2435 | goto err_sleep; | 2509 | goto err_sleep; |
2436 | } | 2510 | } |
2437 | 2511 | ||
2438 | ret = ath10k_pci_alloc_ce(ar); | 2512 | ret = ath10k_pci_alloc_pipes(ar); |
2439 | if (ret) { | 2513 | if (ret) { |
2440 | ath10k_err(ar, "failed to allocate copy engine pipes: %d\n", | 2514 | ath10k_err(ar, "failed to allocate copy engine pipes: %d\n", |
2441 | ret); | 2515 | ret); |
@@ -2443,25 +2517,12 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
2443 | } | 2517 | } |
2444 | 2518 | ||
2445 | ath10k_pci_ce_deinit(ar); | 2519 | ath10k_pci_ce_deinit(ar); |
2446 | 2520 | ath10k_pci_irq_disable(ar); | |
2447 | ret = ath10k_ce_disable_interrupts(ar); | ||
2448 | if (ret) { | ||
2449 | ath10k_err(ar, "failed to disable copy engine interrupts: %d\n", | ||
2450 | ret); | ||
2451 | goto err_free_ce; | ||
2452 | } | ||
2453 | |||
2454 | /* Workaround: There's no known way to mask all possible interrupts via | ||
2455 | * device CSR. The only way to make sure device doesn't assert | ||
2456 | * interrupts is to reset it. Interrupts are then disabled on host | ||
2457 | * after handlers are registered. | ||
2458 | */ | ||
2459 | ath10k_pci_warm_reset(ar); | ||
2460 | 2521 | ||
2461 | ret = ath10k_pci_init_irq(ar); | 2522 | ret = ath10k_pci_init_irq(ar); |
2462 | if (ret) { | 2523 | if (ret) { |
2463 | ath10k_err(ar, "failed to init irqs: %d\n", ret); | 2524 | ath10k_err(ar, "failed to init irqs: %d\n", ret); |
2464 | goto err_free_ce; | 2525 | goto err_free_pipes; |
2465 | } | 2526 | } |
2466 | 2527 | ||
2467 | ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n", | 2528 | ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n", |
@@ -2474,8 +2535,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
2474 | goto err_deinit_irq; | 2535 | goto err_deinit_irq; |
2475 | } | 2536 | } |
2476 | 2537 | ||
2477 | /* This shouldn't race as the device has been reset above. */ | 2538 | ath10k_pci_sleep(ar); |
2478 | ath10k_pci_irq_disable(ar); | ||
2479 | 2539 | ||
2480 | ret = ath10k_core_register(ar, chip_id); | 2540 | ret = ath10k_core_register(ar, chip_id); |
2481 | if (ret) { | 2541 | if (ret) { |
@@ -2492,8 +2552,8 @@ err_free_irq: | |||
2492 | err_deinit_irq: | 2552 | err_deinit_irq: |
2493 | ath10k_pci_deinit_irq(ar); | 2553 | ath10k_pci_deinit_irq(ar); |
2494 | 2554 | ||
2495 | err_free_ce: | 2555 | err_free_pipes: |
2496 | ath10k_pci_free_ce(ar); | 2556 | ath10k_pci_free_pipes(ar); |
2497 | 2557 | ||
2498 | err_sleep: | 2558 | err_sleep: |
2499 | ath10k_pci_sleep(ar); | 2559 | ath10k_pci_sleep(ar); |
@@ -2527,8 +2587,7 @@ static void ath10k_pci_remove(struct pci_dev *pdev) | |||
2527 | ath10k_pci_kill_tasklet(ar); | 2587 | ath10k_pci_kill_tasklet(ar); |
2528 | ath10k_pci_deinit_irq(ar); | 2588 | ath10k_pci_deinit_irq(ar); |
2529 | ath10k_pci_ce_deinit(ar); | 2589 | ath10k_pci_ce_deinit(ar); |
2530 | ath10k_pci_free_ce(ar); | 2590 | ath10k_pci_free_pipes(ar); |
2531 | ath10k_pci_sleep(ar); | ||
2532 | ath10k_pci_release(ar); | 2591 | ath10k_pci_release(ar); |
2533 | ath10k_core_destroy(ar); | 2592 | ath10k_core_destroy(ar); |
2534 | } | 2593 | } |
@@ -2565,5 +2624,7 @@ module_exit(ath10k_pci_exit); | |||
2565 | MODULE_AUTHOR("Qualcomm Atheros"); | 2624 | MODULE_AUTHOR("Qualcomm Atheros"); |
2566 | MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices"); | 2625 | MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices"); |
2567 | MODULE_LICENSE("Dual BSD/GPL"); | 2626 | MODULE_LICENSE("Dual BSD/GPL"); |
2568 | MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_3_FILE); | 2627 | MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_FILE); |
2628 | MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API2_FILE); | ||
2629 | MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API3_FILE); | ||
2569 | MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE); | 2630 | MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_BOARD_DATA_FILE); |
diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c index 3e1454b74e00..63ce61fcdac8 100644 --- a/drivers/net/wireless/ath/ath10k/spectral.c +++ b/drivers/net/wireless/ath/ath10k/spectral.c | |||
@@ -56,14 +56,14 @@ static uint8_t get_max_exp(s8 max_index, u16 max_magnitude, size_t bin_len, | |||
56 | } | 56 | } |
57 | 57 | ||
58 | int ath10k_spectral_process_fft(struct ath10k *ar, | 58 | int ath10k_spectral_process_fft(struct ath10k *ar, |
59 | struct wmi_single_phyerr_rx_event *event, | 59 | const struct wmi_phyerr *phyerr, |
60 | struct phyerr_fft_report *fftr, | 60 | const struct phyerr_fft_report *fftr, |
61 | size_t bin_len, u64 tsf) | 61 | size_t bin_len, u64 tsf) |
62 | { | 62 | { |
63 | struct fft_sample_ath10k *fft_sample; | 63 | struct fft_sample_ath10k *fft_sample; |
64 | u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS]; | 64 | u8 buf[sizeof(*fft_sample) + SPECTRAL_ATH10K_MAX_NUM_BINS]; |
65 | u16 freq1, freq2, total_gain_db, base_pwr_db, length, peak_mag; | 65 | u16 freq1, freq2, total_gain_db, base_pwr_db, length, peak_mag; |
66 | u32 reg0, reg1, nf_list1, nf_list2; | 66 | u32 reg0, reg1; |
67 | u8 chain_idx, *bins; | 67 | u8 chain_idx, *bins; |
68 | int dc_pos; | 68 | int dc_pos; |
69 | 69 | ||
@@ -82,7 +82,7 @@ int ath10k_spectral_process_fft(struct ath10k *ar, | |||
82 | /* TODO: there might be a reason why the hardware reports 20/40/80 MHz, | 82 | /* TODO: there might be a reason why the hardware reports 20/40/80 MHz, |
83 | * but the results/plots suggest that its actually 22/44/88 MHz. | 83 | * but the results/plots suggest that its actually 22/44/88 MHz. |
84 | */ | 84 | */ |
85 | switch (event->hdr.chan_width_mhz) { | 85 | switch (phyerr->chan_width_mhz) { |
86 | case 20: | 86 | case 20: |
87 | fft_sample->chan_width_mhz = 22; | 87 | fft_sample->chan_width_mhz = 22; |
88 | break; | 88 | break; |
@@ -101,7 +101,7 @@ int ath10k_spectral_process_fft(struct ath10k *ar, | |||
101 | fft_sample->chan_width_mhz = 88; | 101 | fft_sample->chan_width_mhz = 88; |
102 | break; | 102 | break; |
103 | default: | 103 | default: |
104 | fft_sample->chan_width_mhz = event->hdr.chan_width_mhz; | 104 | fft_sample->chan_width_mhz = phyerr->chan_width_mhz; |
105 | } | 105 | } |
106 | 106 | ||
107 | fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB); | 107 | fft_sample->relpwr_db = MS(reg1, SEARCH_FFT_REPORT_REG1_RELPWR_DB); |
@@ -110,36 +110,22 @@ int ath10k_spectral_process_fft(struct ath10k *ar, | |||
110 | peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG); | 110 | peak_mag = MS(reg1, SEARCH_FFT_REPORT_REG1_PEAK_MAG); |
111 | fft_sample->max_magnitude = __cpu_to_be16(peak_mag); | 111 | fft_sample->max_magnitude = __cpu_to_be16(peak_mag); |
112 | fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX); | 112 | fft_sample->max_index = MS(reg0, SEARCH_FFT_REPORT_REG0_PEAK_SIDX); |
113 | fft_sample->rssi = event->hdr.rssi_combined; | 113 | fft_sample->rssi = phyerr->rssi_combined; |
114 | 114 | ||
115 | total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB); | 115 | total_gain_db = MS(reg0, SEARCH_FFT_REPORT_REG0_TOTAL_GAIN_DB); |
116 | base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB); | 116 | base_pwr_db = MS(reg0, SEARCH_FFT_REPORT_REG0_BASE_PWR_DB); |
117 | fft_sample->total_gain_db = __cpu_to_be16(total_gain_db); | 117 | fft_sample->total_gain_db = __cpu_to_be16(total_gain_db); |
118 | fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db); | 118 | fft_sample->base_pwr_db = __cpu_to_be16(base_pwr_db); |
119 | 119 | ||
120 | freq1 = __le16_to_cpu(event->hdr.freq1); | 120 | freq1 = __le16_to_cpu(phyerr->freq1); |
121 | freq2 = __le16_to_cpu(event->hdr.freq2); | 121 | freq2 = __le16_to_cpu(phyerr->freq2); |
122 | fft_sample->freq1 = __cpu_to_be16(freq1); | 122 | fft_sample->freq1 = __cpu_to_be16(freq1); |
123 | fft_sample->freq2 = __cpu_to_be16(freq2); | 123 | fft_sample->freq2 = __cpu_to_be16(freq2); |
124 | 124 | ||
125 | nf_list1 = __le32_to_cpu(event->hdr.nf_list_1); | ||
126 | nf_list2 = __le32_to_cpu(event->hdr.nf_list_2); | ||
127 | chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX); | 125 | chain_idx = MS(reg0, SEARCH_FFT_REPORT_REG0_FFT_CHN_IDX); |
128 | 126 | ||
129 | switch (chain_idx) { | 127 | fft_sample->noise = __cpu_to_be16( |
130 | case 0: | 128 | __le16_to_cpu(phyerr->nf_chains[chain_idx])); |
131 | fft_sample->noise = __cpu_to_be16(nf_list1 & 0xffffu); | ||
132 | break; | ||
133 | case 1: | ||
134 | fft_sample->noise = __cpu_to_be16((nf_list1 >> 16) & 0xffffu); | ||
135 | break; | ||
136 | case 2: | ||
137 | fft_sample->noise = __cpu_to_be16(nf_list2 & 0xffffu); | ||
138 | break; | ||
139 | case 3: | ||
140 | fft_sample->noise = __cpu_to_be16((nf_list2 >> 16) & 0xffffu); | ||
141 | break; | ||
142 | } | ||
143 | 129 | ||
144 | bins = (u8 *)fftr; | 130 | bins = (u8 *)fftr; |
145 | bins += sizeof(*fftr); | 131 | bins += sizeof(*fftr); |
diff --git a/drivers/net/wireless/ath/ath10k/spectral.h b/drivers/net/wireless/ath/ath10k/spectral.h index ddc57c557272..042f5b302c75 100644 --- a/drivers/net/wireless/ath/ath10k/spectral.h +++ b/drivers/net/wireless/ath/ath10k/spectral.h | |||
@@ -47,8 +47,8 @@ enum ath10k_spectral_mode { | |||
47 | #ifdef CONFIG_ATH10K_DEBUGFS | 47 | #ifdef CONFIG_ATH10K_DEBUGFS |
48 | 48 | ||
49 | int ath10k_spectral_process_fft(struct ath10k *ar, | 49 | int ath10k_spectral_process_fft(struct ath10k *ar, |
50 | struct wmi_single_phyerr_rx_event *event, | 50 | const struct wmi_phyerr *phyerr, |
51 | struct phyerr_fft_report *fftr, | 51 | const struct phyerr_fft_report *fftr, |
52 | size_t bin_len, u64 tsf); | 52 | size_t bin_len, u64 tsf); |
53 | int ath10k_spectral_start(struct ath10k *ar); | 53 | int ath10k_spectral_start(struct ath10k *ar); |
54 | int ath10k_spectral_vif_stop(struct ath10k_vif *arvif); | 54 | int ath10k_spectral_vif_stop(struct ath10k_vif *arvif); |
@@ -59,8 +59,8 @@ void ath10k_spectral_destroy(struct ath10k *ar); | |||
59 | 59 | ||
60 | static inline int | 60 | static inline int |
61 | ath10k_spectral_process_fft(struct ath10k *ar, | 61 | ath10k_spectral_process_fft(struct ath10k *ar, |
62 | struct wmi_single_phyerr_rx_event *event, | 62 | const struct wmi_phyerr *phyerr, |
63 | struct phyerr_fft_report *fftr, | 63 | const struct phyerr_fft_report *fftr, |
64 | size_t bin_len, u64 tsf) | 64 | size_t bin_len, u64 tsf) |
65 | { | 65 | { |
66 | return 0; | 66 | return 0; |
diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h index 574b75ab2609..ceea5668f3f6 100644 --- a/drivers/net/wireless/ath/ath10k/trace.h +++ b/drivers/net/wireless/ath/ath10k/trace.h | |||
@@ -20,6 +20,13 @@ | |||
20 | #include <linux/tracepoint.h> | 20 | #include <linux/tracepoint.h> |
21 | #include "core.h" | 21 | #include "core.h" |
22 | 22 | ||
23 | #if !defined(_TRACE_H_) | ||
24 | static inline u32 ath10k_frm_hdr_len(void *buf) | ||
25 | { | ||
26 | return ieee80211_hdrlen(((struct ieee80211_hdr *)buf)->frame_control); | ||
27 | } | ||
28 | #endif | ||
29 | |||
23 | #define _TRACE_H_ | 30 | #define _TRACE_H_ |
24 | 31 | ||
25 | /* create empty functions when tracing is disabled */ | 32 | /* create empty functions when tracing is disabled */ |
@@ -254,6 +261,195 @@ TRACE_EVENT(ath10k_wmi_dbglog, | |||
254 | ) | 261 | ) |
255 | ); | 262 | ); |
256 | 263 | ||
264 | TRACE_EVENT(ath10k_htt_pktlog, | ||
265 | TP_PROTO(struct ath10k *ar, void *buf, u16 buf_len), | ||
266 | |||
267 | TP_ARGS(ar, buf, buf_len), | ||
268 | |||
269 | TP_STRUCT__entry( | ||
270 | __string(device, dev_name(ar->dev)) | ||
271 | __string(driver, dev_driver_string(ar->dev)) | ||
272 | __field(u16, buf_len) | ||
273 | __dynamic_array(u8, pktlog, buf_len) | ||
274 | ), | ||
275 | |||
276 | TP_fast_assign( | ||
277 | __assign_str(device, dev_name(ar->dev)); | ||
278 | __assign_str(driver, dev_driver_string(ar->dev)); | ||
279 | __entry->buf_len = buf_len; | ||
280 | memcpy(__get_dynamic_array(pktlog), buf, buf_len); | ||
281 | ), | ||
282 | |||
283 | TP_printk( | ||
284 | "%s %s size %hu", | ||
285 | __get_str(driver), | ||
286 | __get_str(device), | ||
287 | __entry->buf_len | ||
288 | ) | ||
289 | ); | ||
290 | |||
291 | TRACE_EVENT(ath10k_htt_tx, | ||
292 | TP_PROTO(struct ath10k *ar, u16 msdu_id, u16 msdu_len, | ||
293 | u8 vdev_id, u8 tid), | ||
294 | |||
295 | TP_ARGS(ar, msdu_id, msdu_len, vdev_id, tid), | ||
296 | |||
297 | TP_STRUCT__entry( | ||
298 | __string(device, dev_name(ar->dev)) | ||
299 | __string(driver, dev_driver_string(ar->dev)) | ||
300 | __field(u16, msdu_id) | ||
301 | __field(u16, msdu_len) | ||
302 | __field(u8, vdev_id) | ||
303 | __field(u8, tid) | ||
304 | ), | ||
305 | |||
306 | TP_fast_assign( | ||
307 | __assign_str(device, dev_name(ar->dev)); | ||
308 | __assign_str(driver, dev_driver_string(ar->dev)); | ||
309 | __entry->msdu_id = msdu_id; | ||
310 | __entry->msdu_len = msdu_len; | ||
311 | __entry->vdev_id = vdev_id; | ||
312 | __entry->tid = tid; | ||
313 | ), | ||
314 | |||
315 | TP_printk( | ||
316 | "%s %s msdu_id %d msdu_len %d vdev_id %d tid %d", | ||
317 | __get_str(driver), | ||
318 | __get_str(device), | ||
319 | __entry->msdu_id, | ||
320 | __entry->msdu_len, | ||
321 | __entry->vdev_id, | ||
322 | __entry->tid | ||
323 | ) | ||
324 | ); | ||
325 | |||
326 | TRACE_EVENT(ath10k_txrx_tx_unref, | ||
327 | TP_PROTO(struct ath10k *ar, u16 msdu_id), | ||
328 | |||
329 | TP_ARGS(ar, msdu_id), | ||
330 | |||
331 | TP_STRUCT__entry( | ||
332 | __string(device, dev_name(ar->dev)) | ||
333 | __string(driver, dev_driver_string(ar->dev)) | ||
334 | __field(u16, msdu_id) | ||
335 | ), | ||
336 | |||
337 | TP_fast_assign( | ||
338 | __assign_str(device, dev_name(ar->dev)); | ||
339 | __assign_str(driver, dev_driver_string(ar->dev)); | ||
340 | __entry->msdu_id = msdu_id; | ||
341 | ), | ||
342 | |||
343 | TP_printk( | ||
344 | "%s %s msdu_id %d", | ||
345 | __get_str(driver), | ||
346 | __get_str(device), | ||
347 | __entry->msdu_id | ||
348 | ) | ||
349 | ); | ||
350 | |||
351 | DECLARE_EVENT_CLASS(ath10k_hdr_event, | ||
352 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | ||
353 | |||
354 | TP_ARGS(ar, data, len), | ||
355 | |||
356 | TP_STRUCT__entry( | ||
357 | __string(device, dev_name(ar->dev)) | ||
358 | __string(driver, dev_driver_string(ar->dev)) | ||
359 | __field(size_t, len) | ||
360 | __dynamic_array(u8, data, ath10k_frm_hdr_len(data)) | ||
361 | ), | ||
362 | |||
363 | TP_fast_assign( | ||
364 | __assign_str(device, dev_name(ar->dev)); | ||
365 | __assign_str(driver, dev_driver_string(ar->dev)); | ||
366 | __entry->len = ath10k_frm_hdr_len(data); | ||
367 | memcpy(__get_dynamic_array(data), data, __entry->len); | ||
368 | ), | ||
369 | |||
370 | TP_printk( | ||
371 | "%s %s len %zu\n", | ||
372 | __get_str(driver), | ||
373 | __get_str(device), | ||
374 | __entry->len | ||
375 | ) | ||
376 | ); | ||
377 | |||
378 | DECLARE_EVENT_CLASS(ath10k_payload_event, | ||
379 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | ||
380 | |||
381 | TP_ARGS(ar, data, len), | ||
382 | |||
383 | TP_STRUCT__entry( | ||
384 | __string(device, dev_name(ar->dev)) | ||
385 | __string(driver, dev_driver_string(ar->dev)) | ||
386 | __field(size_t, len) | ||
387 | __dynamic_array(u8, payload, (len - ath10k_frm_hdr_len(data))) | ||
388 | ), | ||
389 | |||
390 | TP_fast_assign( | ||
391 | __assign_str(device, dev_name(ar->dev)); | ||
392 | __assign_str(driver, dev_driver_string(ar->dev)); | ||
393 | __entry->len = len - ath10k_frm_hdr_len(data); | ||
394 | memcpy(__get_dynamic_array(payload), | ||
395 | data + ath10k_frm_hdr_len(data), __entry->len); | ||
396 | ), | ||
397 | |||
398 | TP_printk( | ||
399 | "%s %s len %zu\n", | ||
400 | __get_str(driver), | ||
401 | __get_str(device), | ||
402 | __entry->len | ||
403 | ) | ||
404 | ); | ||
405 | |||
406 | DEFINE_EVENT(ath10k_hdr_event, ath10k_tx_hdr, | ||
407 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | ||
408 | TP_ARGS(ar, data, len) | ||
409 | ); | ||
410 | |||
411 | DEFINE_EVENT(ath10k_payload_event, ath10k_tx_payload, | ||
412 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | ||
413 | TP_ARGS(ar, data, len) | ||
414 | ); | ||
415 | |||
416 | DEFINE_EVENT(ath10k_hdr_event, ath10k_rx_hdr, | ||
417 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | ||
418 | TP_ARGS(ar, data, len) | ||
419 | ); | ||
420 | |||
421 | DEFINE_EVENT(ath10k_payload_event, ath10k_rx_payload, | ||
422 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | ||
423 | TP_ARGS(ar, data, len) | ||
424 | ); | ||
425 | |||
426 | TRACE_EVENT(ath10k_htt_rx_desc, | ||
427 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | ||
428 | |||
429 | TP_ARGS(ar, data, len), | ||
430 | |||
431 | TP_STRUCT__entry( | ||
432 | __string(device, dev_name(ar->dev)) | ||
433 | __string(driver, dev_driver_string(ar->dev)) | ||
434 | __field(u16, len) | ||
435 | __dynamic_array(u8, rxdesc, len) | ||
436 | ), | ||
437 | |||
438 | TP_fast_assign( | ||
439 | __assign_str(device, dev_name(ar->dev)); | ||
440 | __assign_str(driver, dev_driver_string(ar->dev)); | ||
441 | __entry->len = len; | ||
442 | memcpy(__get_dynamic_array(rxdesc), data, len); | ||
443 | ), | ||
444 | |||
445 | TP_printk( | ||
446 | "%s %s rxdesc len %d", | ||
447 | __get_str(driver), | ||
448 | __get_str(device), | ||
449 | __entry->len | ||
450 | ) | ||
451 | ); | ||
452 | |||
257 | #endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/ | 453 | #endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/ |
258 | 454 | ||
259 | /* we don't want to use include/trace/events */ | 455 | /* we don't want to use include/trace/events */ |
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index a0cbc21d0d4b..7579de8e7a8c 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c | |||
@@ -78,6 +78,7 @@ void ath10k_txrx_tx_unref(struct ath10k_htt *htt, | |||
78 | 78 | ||
79 | info = IEEE80211_SKB_CB(msdu); | 79 | info = IEEE80211_SKB_CB(msdu); |
80 | memset(&info->status, 0, sizeof(info->status)); | 80 | memset(&info->status, 0, sizeof(info->status)); |
81 | trace_ath10k_txrx_tx_unref(ar, tx_done->msdu_id); | ||
81 | 82 | ||
82 | if (tx_done->discard) { | 83 | if (tx_done->discard) { |
83 | ieee80211_free_txskb(htt->ar->hw, msdu); | 84 | ieee80211_free_txskb(htt->ar->hw, msdu); |
@@ -145,7 +146,8 @@ static int ath10k_wait_for_peer_common(struct ath10k *ar, int vdev_id, | |||
145 | mapped = !!ath10k_peer_find(ar, vdev_id, addr); | 146 | mapped = !!ath10k_peer_find(ar, vdev_id, addr); |
146 | spin_unlock_bh(&ar->data_lock); | 147 | spin_unlock_bh(&ar->data_lock); |
147 | 148 | ||
148 | mapped == expect_mapped; | 149 | (mapped == expect_mapped || |
150 | test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)); | ||
149 | }), 3*HZ); | 151 | }), 3*HZ); |
150 | 152 | ||
151 | if (ret <= 0) | 153 | if (ret <= 0) |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 2c42bd504b79..c2bc8282f6cb 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
@@ -609,6 +609,40 @@ static struct wmi_cmd_map wmi_10_2_cmd_map = { | |||
609 | .gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID, | 609 | .gpio_output_cmdid = WMI_10_2_GPIO_OUTPUT_CMDID, |
610 | }; | 610 | }; |
611 | 611 | ||
612 | static void | ||
613 | ath10k_wmi_put_wmi_channel(struct wmi_channel *ch, | ||
614 | const struct wmi_channel_arg *arg) | ||
615 | { | ||
616 | u32 flags = 0; | ||
617 | |||
618 | memset(ch, 0, sizeof(*ch)); | ||
619 | |||
620 | if (arg->passive) | ||
621 | flags |= WMI_CHAN_FLAG_PASSIVE; | ||
622 | if (arg->allow_ibss) | ||
623 | flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED; | ||
624 | if (arg->allow_ht) | ||
625 | flags |= WMI_CHAN_FLAG_ALLOW_HT; | ||
626 | if (arg->allow_vht) | ||
627 | flags |= WMI_CHAN_FLAG_ALLOW_VHT; | ||
628 | if (arg->ht40plus) | ||
629 | flags |= WMI_CHAN_FLAG_HT40_PLUS; | ||
630 | if (arg->chan_radar) | ||
631 | flags |= WMI_CHAN_FLAG_DFS; | ||
632 | |||
633 | ch->mhz = __cpu_to_le32(arg->freq); | ||
634 | ch->band_center_freq1 = __cpu_to_le32(arg->band_center_freq1); | ||
635 | ch->band_center_freq2 = 0; | ||
636 | ch->min_power = arg->min_power; | ||
637 | ch->max_power = arg->max_power; | ||
638 | ch->reg_power = arg->max_reg_power; | ||
639 | ch->antenna_max = arg->max_antenna_gain; | ||
640 | |||
641 | /* mode & flags share storage */ | ||
642 | ch->mode = arg->mode; | ||
643 | ch->flags |= __cpu_to_le32(flags); | ||
644 | } | ||
645 | |||
612 | int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) | 646 | int ath10k_wmi_wait_for_service_ready(struct ath10k *ar) |
613 | { | 647 | { |
614 | int ret; | 648 | int ret; |
@@ -745,6 +779,10 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id) | |||
745 | ath10k_wmi_tx_beacons_nowait(ar); | 779 | ath10k_wmi_tx_beacons_nowait(ar); |
746 | 780 | ||
747 | ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id); | 781 | ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id); |
782 | |||
783 | if (ret && test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) | ||
784 | ret = -ESHUTDOWN; | ||
785 | |||
748 | (ret != -EAGAIN); | 786 | (ret != -EAGAIN); |
749 | }), 3*HZ); | 787 | }), 3*HZ); |
750 | 788 | ||
@@ -800,6 +838,8 @@ int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb) | |||
800 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n", | 838 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n", |
801 | wmi_skb, wmi_skb->len, fc & IEEE80211_FCTL_FTYPE, | 839 | wmi_skb, wmi_skb->len, fc & IEEE80211_FCTL_FTYPE, |
802 | fc & IEEE80211_FCTL_STYPE); | 840 | fc & IEEE80211_FCTL_STYPE); |
841 | trace_ath10k_tx_hdr(ar, skb->data, skb->len); | ||
842 | trace_ath10k_tx_payload(ar, skb->data, skb->len); | ||
803 | 843 | ||
804 | /* Send the management frame buffer to the target */ | 844 | /* Send the management frame buffer to the target */ |
805 | ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid); | 845 | ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid); |
@@ -1079,7 +1119,6 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) | |||
1079 | struct wmi_mgmt_rx_event_v2 *ev_v2; | 1119 | struct wmi_mgmt_rx_event_v2 *ev_v2; |
1080 | struct wmi_mgmt_rx_hdr_v1 *ev_hdr; | 1120 | struct wmi_mgmt_rx_hdr_v1 *ev_hdr; |
1081 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 1121 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
1082 | struct ieee80211_channel *ch; | ||
1083 | struct ieee80211_hdr *hdr; | 1122 | struct ieee80211_hdr *hdr; |
1084 | u32 rx_status; | 1123 | u32 rx_status; |
1085 | u32 channel; | 1124 | u32 channel; |
@@ -1132,25 +1171,26 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) | |||
1132 | if (rx_status & WMI_RX_STATUS_ERR_MIC) | 1171 | if (rx_status & WMI_RX_STATUS_ERR_MIC) |
1133 | status->flag |= RX_FLAG_MMIC_ERROR; | 1172 | status->flag |= RX_FLAG_MMIC_ERROR; |
1134 | 1173 | ||
1135 | /* HW can Rx CCK rates on 5GHz. In that case phy_mode is set to | 1174 | /* Hardware can Rx CCK rates on 5GHz. In that case phy_mode is set to |
1136 | * MODE_11B. This means phy_mode is not a reliable source for the band | 1175 | * MODE_11B. This means phy_mode is not a reliable source for the band |
1137 | * of mgmt rx. */ | 1176 | * of mgmt rx. |
1138 | 1177 | */ | |
1139 | ch = ar->scan_channel; | 1178 | if (channel >= 1 && channel <= 14) { |
1140 | if (!ch) | 1179 | status->band = IEEE80211_BAND_2GHZ; |
1141 | ch = ar->rx_channel; | 1180 | } else if (channel >= 36 && channel <= 165) { |
1142 | 1181 | status->band = IEEE80211_BAND_5GHZ; | |
1143 | if (ch) { | ||
1144 | status->band = ch->band; | ||
1145 | |||
1146 | if (phy_mode == MODE_11B && | ||
1147 | status->band == IEEE80211_BAND_5GHZ) | ||
1148 | ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n"); | ||
1149 | } else { | 1182 | } else { |
1150 | ath10k_warn(ar, "using (unreliable) phy_mode to extract band for mgmt rx\n"); | 1183 | /* Shouldn't happen unless list of advertised channels to |
1151 | status->band = phy_mode_to_band(phy_mode); | 1184 | * mac80211 has been changed. |
1185 | */ | ||
1186 | WARN_ON_ONCE(1); | ||
1187 | dev_kfree_skb(skb); | ||
1188 | return 0; | ||
1152 | } | 1189 | } |
1153 | 1190 | ||
1191 | if (phy_mode == MODE_11B && status->band == IEEE80211_BAND_5GHZ) | ||
1192 | ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n"); | ||
1193 | |||
1154 | status->freq = ieee80211_channel_to_frequency(channel, status->band); | 1194 | status->freq = ieee80211_channel_to_frequency(channel, status->band); |
1155 | status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; | 1195 | status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; |
1156 | status->rate_idx = get_rate_idx(rate, status->band); | 1196 | status->rate_idx = get_rate_idx(rate, status->band); |
@@ -1295,14 +1335,196 @@ static int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb) | |||
1295 | return 0; | 1335 | return 0; |
1296 | } | 1336 | } |
1297 | 1337 | ||
1338 | static void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src, | ||
1339 | struct ath10k_fw_stats_pdev *dst) | ||
1340 | { | ||
1341 | const struct wal_dbg_tx_stats *tx = &src->wal.tx; | ||
1342 | const struct wal_dbg_rx_stats *rx = &src->wal.rx; | ||
1343 | |||
1344 | dst->ch_noise_floor = __le32_to_cpu(src->chan_nf); | ||
1345 | dst->tx_frame_count = __le32_to_cpu(src->tx_frame_count); | ||
1346 | dst->rx_frame_count = __le32_to_cpu(src->rx_frame_count); | ||
1347 | dst->rx_clear_count = __le32_to_cpu(src->rx_clear_count); | ||
1348 | dst->cycle_count = __le32_to_cpu(src->cycle_count); | ||
1349 | dst->phy_err_count = __le32_to_cpu(src->phy_err_count); | ||
1350 | dst->chan_tx_power = __le32_to_cpu(src->chan_tx_pwr); | ||
1351 | |||
1352 | dst->comp_queued = __le32_to_cpu(tx->comp_queued); | ||
1353 | dst->comp_delivered = __le32_to_cpu(tx->comp_delivered); | ||
1354 | dst->msdu_enqued = __le32_to_cpu(tx->msdu_enqued); | ||
1355 | dst->mpdu_enqued = __le32_to_cpu(tx->mpdu_enqued); | ||
1356 | dst->wmm_drop = __le32_to_cpu(tx->wmm_drop); | ||
1357 | dst->local_enqued = __le32_to_cpu(tx->local_enqued); | ||
1358 | dst->local_freed = __le32_to_cpu(tx->local_freed); | ||
1359 | dst->hw_queued = __le32_to_cpu(tx->hw_queued); | ||
1360 | dst->hw_reaped = __le32_to_cpu(tx->hw_reaped); | ||
1361 | dst->underrun = __le32_to_cpu(tx->underrun); | ||
1362 | dst->tx_abort = __le32_to_cpu(tx->tx_abort); | ||
1363 | dst->mpdus_requed = __le32_to_cpu(tx->mpdus_requed); | ||
1364 | dst->tx_ko = __le32_to_cpu(tx->tx_ko); | ||
1365 | dst->data_rc = __le32_to_cpu(tx->data_rc); | ||
1366 | dst->self_triggers = __le32_to_cpu(tx->self_triggers); | ||
1367 | dst->sw_retry_failure = __le32_to_cpu(tx->sw_retry_failure); | ||
1368 | dst->illgl_rate_phy_err = __le32_to_cpu(tx->illgl_rate_phy_err); | ||
1369 | dst->pdev_cont_xretry = __le32_to_cpu(tx->pdev_cont_xretry); | ||
1370 | dst->pdev_tx_timeout = __le32_to_cpu(tx->pdev_tx_timeout); | ||
1371 | dst->pdev_resets = __le32_to_cpu(tx->pdev_resets); | ||
1372 | dst->phy_underrun = __le32_to_cpu(tx->phy_underrun); | ||
1373 | dst->txop_ovf = __le32_to_cpu(tx->txop_ovf); | ||
1374 | |||
1375 | dst->mid_ppdu_route_change = __le32_to_cpu(rx->mid_ppdu_route_change); | ||
1376 | dst->status_rcvd = __le32_to_cpu(rx->status_rcvd); | ||
1377 | dst->r0_frags = __le32_to_cpu(rx->r0_frags); | ||
1378 | dst->r1_frags = __le32_to_cpu(rx->r1_frags); | ||
1379 | dst->r2_frags = __le32_to_cpu(rx->r2_frags); | ||
1380 | dst->r3_frags = __le32_to_cpu(rx->r3_frags); | ||
1381 | dst->htt_msdus = __le32_to_cpu(rx->htt_msdus); | ||
1382 | dst->htt_mpdus = __le32_to_cpu(rx->htt_mpdus); | ||
1383 | dst->loc_msdus = __le32_to_cpu(rx->loc_msdus); | ||
1384 | dst->loc_mpdus = __le32_to_cpu(rx->loc_mpdus); | ||
1385 | dst->oversize_amsdu = __le32_to_cpu(rx->oversize_amsdu); | ||
1386 | dst->phy_errs = __le32_to_cpu(rx->phy_errs); | ||
1387 | dst->phy_err_drop = __le32_to_cpu(rx->phy_err_drop); | ||
1388 | dst->mpdu_errs = __le32_to_cpu(rx->mpdu_errs); | ||
1389 | } | ||
1390 | |||
1391 | static void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src, | ||
1392 | struct ath10k_fw_stats_peer *dst) | ||
1393 | { | ||
1394 | ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr); | ||
1395 | dst->peer_rssi = __le32_to_cpu(src->peer_rssi); | ||
1396 | dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate); | ||
1397 | } | ||
1398 | |||
1399 | static int ath10k_wmi_main_pull_fw_stats(struct ath10k *ar, | ||
1400 | struct sk_buff *skb, | ||
1401 | struct ath10k_fw_stats *stats) | ||
1402 | { | ||
1403 | const struct wmi_stats_event *ev = (void *)skb->data; | ||
1404 | u32 num_pdev_stats, num_vdev_stats, num_peer_stats; | ||
1405 | int i; | ||
1406 | |||
1407 | if (!skb_pull(skb, sizeof(*ev))) | ||
1408 | return -EPROTO; | ||
1409 | |||
1410 | num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); | ||
1411 | num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); | ||
1412 | num_peer_stats = __le32_to_cpu(ev->num_peer_stats); | ||
1413 | |||
1414 | for (i = 0; i < num_pdev_stats; i++) { | ||
1415 | const struct wmi_pdev_stats *src; | ||
1416 | struct ath10k_fw_stats_pdev *dst; | ||
1417 | |||
1418 | src = (void *)skb->data; | ||
1419 | if (!skb_pull(skb, sizeof(*src))) | ||
1420 | return -EPROTO; | ||
1421 | |||
1422 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); | ||
1423 | if (!dst) | ||
1424 | continue; | ||
1425 | |||
1426 | ath10k_wmi_pull_pdev_stats(src, dst); | ||
1427 | list_add_tail(&dst->list, &stats->pdevs); | ||
1428 | } | ||
1429 | |||
1430 | /* fw doesn't implement vdev stats */ | ||
1431 | |||
1432 | for (i = 0; i < num_peer_stats; i++) { | ||
1433 | const struct wmi_peer_stats *src; | ||
1434 | struct ath10k_fw_stats_peer *dst; | ||
1435 | |||
1436 | src = (void *)skb->data; | ||
1437 | if (!skb_pull(skb, sizeof(*src))) | ||
1438 | return -EPROTO; | ||
1439 | |||
1440 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); | ||
1441 | if (!dst) | ||
1442 | continue; | ||
1443 | |||
1444 | ath10k_wmi_pull_peer_stats(src, dst); | ||
1445 | list_add_tail(&dst->list, &stats->peers); | ||
1446 | } | ||
1447 | |||
1448 | return 0; | ||
1449 | } | ||
1450 | |||
1451 | static int ath10k_wmi_10x_pull_fw_stats(struct ath10k *ar, | ||
1452 | struct sk_buff *skb, | ||
1453 | struct ath10k_fw_stats *stats) | ||
1454 | { | ||
1455 | const struct wmi_stats_event *ev = (void *)skb->data; | ||
1456 | u32 num_pdev_stats, num_vdev_stats, num_peer_stats; | ||
1457 | int i; | ||
1458 | |||
1459 | if (!skb_pull(skb, sizeof(*ev))) | ||
1460 | return -EPROTO; | ||
1461 | |||
1462 | num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); | ||
1463 | num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); | ||
1464 | num_peer_stats = __le32_to_cpu(ev->num_peer_stats); | ||
1465 | |||
1466 | for (i = 0; i < num_pdev_stats; i++) { | ||
1467 | const struct wmi_10x_pdev_stats *src; | ||
1468 | struct ath10k_fw_stats_pdev *dst; | ||
1469 | |||
1470 | src = (void *)skb->data; | ||
1471 | if (!skb_pull(skb, sizeof(*src))) | ||
1472 | return -EPROTO; | ||
1473 | |||
1474 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); | ||
1475 | if (!dst) | ||
1476 | continue; | ||
1477 | |||
1478 | ath10k_wmi_pull_pdev_stats(&src->old, dst); | ||
1479 | |||
1480 | dst->ack_rx_bad = __le32_to_cpu(src->ack_rx_bad); | ||
1481 | dst->rts_bad = __le32_to_cpu(src->rts_bad); | ||
1482 | dst->rts_good = __le32_to_cpu(src->rts_good); | ||
1483 | dst->fcs_bad = __le32_to_cpu(src->fcs_bad); | ||
1484 | dst->no_beacons = __le32_to_cpu(src->no_beacons); | ||
1485 | dst->mib_int_count = __le32_to_cpu(src->mib_int_count); | ||
1486 | |||
1487 | list_add_tail(&dst->list, &stats->pdevs); | ||
1488 | } | ||
1489 | |||
1490 | /* fw doesn't implement vdev stats */ | ||
1491 | |||
1492 | for (i = 0; i < num_peer_stats; i++) { | ||
1493 | const struct wmi_10x_peer_stats *src; | ||
1494 | struct ath10k_fw_stats_peer *dst; | ||
1495 | |||
1496 | src = (void *)skb->data; | ||
1497 | if (!skb_pull(skb, sizeof(*src))) | ||
1498 | return -EPROTO; | ||
1499 | |||
1500 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); | ||
1501 | if (!dst) | ||
1502 | continue; | ||
1503 | |||
1504 | ath10k_wmi_pull_peer_stats(&src->old, dst); | ||
1505 | |||
1506 | dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); | ||
1507 | |||
1508 | list_add_tail(&dst->list, &stats->peers); | ||
1509 | } | ||
1510 | |||
1511 | return 0; | ||
1512 | } | ||
1513 | |||
1514 | int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb, | ||
1515 | struct ath10k_fw_stats *stats) | ||
1516 | { | ||
1517 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | ||
1518 | return ath10k_wmi_10x_pull_fw_stats(ar, skb, stats); | ||
1519 | else | ||
1520 | return ath10k_wmi_main_pull_fw_stats(ar, skb, stats); | ||
1521 | } | ||
1522 | |||
1298 | static void ath10k_wmi_event_update_stats(struct ath10k *ar, | 1523 | static void ath10k_wmi_event_update_stats(struct ath10k *ar, |
1299 | struct sk_buff *skb) | 1524 | struct sk_buff *skb) |
1300 | { | 1525 | { |
1301 | struct wmi_stats_event *ev = (struct wmi_stats_event *)skb->data; | ||
1302 | |||
1303 | ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n"); | 1526 | ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n"); |
1304 | 1527 | ath10k_debug_fw_stats_process(ar, skb); | |
1305 | ath10k_debug_read_target_stats(ar, ev); | ||
1306 | } | 1528 | } |
1307 | 1529 | ||
1308 | static void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar, | 1530 | static void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar, |
@@ -1579,6 +1801,7 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
1579 | struct wmi_bcn_info *bcn_info; | 1801 | struct wmi_bcn_info *bcn_info; |
1580 | struct ath10k_vif *arvif; | 1802 | struct ath10k_vif *arvif; |
1581 | struct sk_buff *bcn; | 1803 | struct sk_buff *bcn; |
1804 | dma_addr_t paddr; | ||
1582 | int ret, vdev_id = 0; | 1805 | int ret, vdev_id = 0; |
1583 | 1806 | ||
1584 | ev = (struct wmi_host_swba_event *)skb->data; | 1807 | ev = (struct wmi_host_swba_event *)skb->data; |
@@ -1647,27 +1870,37 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
1647 | ath10k_warn(ar, "SWBA overrun on vdev %d\n", | 1870 | ath10k_warn(ar, "SWBA overrun on vdev %d\n", |
1648 | arvif->vdev_id); | 1871 | arvif->vdev_id); |
1649 | 1872 | ||
1650 | dma_unmap_single(arvif->ar->dev, | 1873 | ath10k_mac_vif_beacon_free(arvif); |
1651 | ATH10K_SKB_CB(arvif->beacon)->paddr, | ||
1652 | arvif->beacon->len, DMA_TO_DEVICE); | ||
1653 | dev_kfree_skb_any(arvif->beacon); | ||
1654 | arvif->beacon = NULL; | ||
1655 | } | 1874 | } |
1656 | 1875 | ||
1657 | ATH10K_SKB_CB(bcn)->paddr = dma_map_single(arvif->ar->dev, | 1876 | if (!arvif->beacon_buf) { |
1658 | bcn->data, bcn->len, | 1877 | paddr = dma_map_single(arvif->ar->dev, bcn->data, |
1659 | DMA_TO_DEVICE); | 1878 | bcn->len, DMA_TO_DEVICE); |
1660 | ret = dma_mapping_error(arvif->ar->dev, | 1879 | ret = dma_mapping_error(arvif->ar->dev, paddr); |
1661 | ATH10K_SKB_CB(bcn)->paddr); | 1880 | if (ret) { |
1662 | if (ret) { | 1881 | ath10k_warn(ar, "failed to map beacon: %d\n", |
1663 | ath10k_warn(ar, "failed to map beacon: %d\n", ret); | 1882 | ret); |
1664 | dev_kfree_skb_any(bcn); | 1883 | dev_kfree_skb_any(bcn); |
1665 | goto skip; | 1884 | goto skip; |
1885 | } | ||
1886 | |||
1887 | ATH10K_SKB_CB(bcn)->paddr = paddr; | ||
1888 | } else { | ||
1889 | if (bcn->len > IEEE80211_MAX_FRAME_LEN) { | ||
1890 | ath10k_warn(ar, "trimming beacon %d -> %d bytes!\n", | ||
1891 | bcn->len, IEEE80211_MAX_FRAME_LEN); | ||
1892 | skb_trim(bcn, IEEE80211_MAX_FRAME_LEN); | ||
1893 | } | ||
1894 | memcpy(arvif->beacon_buf, bcn->data, bcn->len); | ||
1895 | ATH10K_SKB_CB(bcn)->paddr = arvif->beacon_paddr; | ||
1666 | } | 1896 | } |
1667 | 1897 | ||
1668 | arvif->beacon = bcn; | 1898 | arvif->beacon = bcn; |
1669 | arvif->beacon_sent = false; | 1899 | arvif->beacon_sent = false; |
1670 | 1900 | ||
1901 | trace_ath10k_tx_hdr(ar, bcn->data, bcn->len); | ||
1902 | trace_ath10k_tx_payload(ar, bcn->data, bcn->len); | ||
1903 | |||
1671 | ath10k_wmi_tx_beacon_nowait(arvif); | 1904 | ath10k_wmi_tx_beacon_nowait(arvif); |
1672 | skip: | 1905 | skip: |
1673 | spin_unlock_bh(&ar->data_lock); | 1906 | spin_unlock_bh(&ar->data_lock); |
@@ -1681,8 +1914,8 @@ static void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, | |||
1681 | } | 1914 | } |
1682 | 1915 | ||
1683 | static void ath10k_dfs_radar_report(struct ath10k *ar, | 1916 | static void ath10k_dfs_radar_report(struct ath10k *ar, |
1684 | struct wmi_single_phyerr_rx_event *event, | 1917 | const struct wmi_phyerr *phyerr, |
1685 | struct phyerr_radar_report *rr, | 1918 | const struct phyerr_radar_report *rr, |
1686 | u64 tsf) | 1919 | u64 tsf) |
1687 | { | 1920 | { |
1688 | u32 reg0, reg1, tsf32l; | 1921 | u32 reg0, reg1, tsf32l; |
@@ -1715,12 +1948,12 @@ static void ath10k_dfs_radar_report(struct ath10k *ar, | |||
1715 | return; | 1948 | return; |
1716 | 1949 | ||
1717 | /* report event to DFS pattern detector */ | 1950 | /* report event to DFS pattern detector */ |
1718 | tsf32l = __le32_to_cpu(event->hdr.tsf_timestamp); | 1951 | tsf32l = __le32_to_cpu(phyerr->tsf_timestamp); |
1719 | tsf64 = tsf & (~0xFFFFFFFFULL); | 1952 | tsf64 = tsf & (~0xFFFFFFFFULL); |
1720 | tsf64 |= tsf32l; | 1953 | tsf64 |= tsf32l; |
1721 | 1954 | ||
1722 | width = MS(reg1, RADAR_REPORT_REG1_PULSE_DUR); | 1955 | width = MS(reg1, RADAR_REPORT_REG1_PULSE_DUR); |
1723 | rssi = event->hdr.rssi_combined; | 1956 | rssi = phyerr->rssi_combined; |
1724 | 1957 | ||
1725 | /* hardware store this as 8 bit signed value, | 1958 | /* hardware store this as 8 bit signed value, |
1726 | * set to zero if negative number | 1959 | * set to zero if negative number |
@@ -1759,8 +1992,8 @@ static void ath10k_dfs_radar_report(struct ath10k *ar, | |||
1759 | } | 1992 | } |
1760 | 1993 | ||
1761 | static int ath10k_dfs_fft_report(struct ath10k *ar, | 1994 | static int ath10k_dfs_fft_report(struct ath10k *ar, |
1762 | struct wmi_single_phyerr_rx_event *event, | 1995 | const struct wmi_phyerr *phyerr, |
1763 | struct phyerr_fft_report *fftr, | 1996 | const struct phyerr_fft_report *fftr, |
1764 | u64 tsf) | 1997 | u64 tsf) |
1765 | { | 1998 | { |
1766 | u32 reg0, reg1; | 1999 | u32 reg0, reg1; |
@@ -1768,7 +2001,7 @@ static int ath10k_dfs_fft_report(struct ath10k *ar, | |||
1768 | 2001 | ||
1769 | reg0 = __le32_to_cpu(fftr->reg0); | 2002 | reg0 = __le32_to_cpu(fftr->reg0); |
1770 | reg1 = __le32_to_cpu(fftr->reg1); | 2003 | reg1 = __le32_to_cpu(fftr->reg1); |
1771 | rssi = event->hdr.rssi_combined; | 2004 | rssi = phyerr->rssi_combined; |
1772 | 2005 | ||
1773 | ath10k_dbg(ar, ATH10K_DBG_REGULATORY, | 2006 | ath10k_dbg(ar, ATH10K_DBG_REGULATORY, |
1774 | "wmi phyerr fft report total_gain_db %d base_pwr_db %d fft_chn_idx %d peak_sidx %d\n", | 2007 | "wmi phyerr fft report total_gain_db %d base_pwr_db %d fft_chn_idx %d peak_sidx %d\n", |
@@ -1797,20 +2030,20 @@ static int ath10k_dfs_fft_report(struct ath10k *ar, | |||
1797 | } | 2030 | } |
1798 | 2031 | ||
1799 | static void ath10k_wmi_event_dfs(struct ath10k *ar, | 2032 | static void ath10k_wmi_event_dfs(struct ath10k *ar, |
1800 | struct wmi_single_phyerr_rx_event *event, | 2033 | const struct wmi_phyerr *phyerr, |
1801 | u64 tsf) | 2034 | u64 tsf) |
1802 | { | 2035 | { |
1803 | int buf_len, tlv_len, res, i = 0; | 2036 | int buf_len, tlv_len, res, i = 0; |
1804 | struct phyerr_tlv *tlv; | 2037 | const struct phyerr_tlv *tlv; |
1805 | struct phyerr_radar_report *rr; | 2038 | const struct phyerr_radar_report *rr; |
1806 | struct phyerr_fft_report *fftr; | 2039 | const struct phyerr_fft_report *fftr; |
1807 | u8 *tlv_buf; | 2040 | const u8 *tlv_buf; |
1808 | 2041 | ||
1809 | buf_len = __le32_to_cpu(event->hdr.buf_len); | 2042 | buf_len = __le32_to_cpu(phyerr->buf_len); |
1810 | ath10k_dbg(ar, ATH10K_DBG_REGULATORY, | 2043 | ath10k_dbg(ar, ATH10K_DBG_REGULATORY, |
1811 | "wmi event dfs err_code %d rssi %d tsfl 0x%X tsf64 0x%llX len %d\n", | 2044 | "wmi event dfs err_code %d rssi %d tsfl 0x%X tsf64 0x%llX len %d\n", |
1812 | event->hdr.phy_err_code, event->hdr.rssi_combined, | 2045 | phyerr->phy_err_code, phyerr->rssi_combined, |
1813 | __le32_to_cpu(event->hdr.tsf_timestamp), tsf, buf_len); | 2046 | __le32_to_cpu(phyerr->tsf_timestamp), tsf, buf_len); |
1814 | 2047 | ||
1815 | /* Skip event if DFS disabled */ | 2048 | /* Skip event if DFS disabled */ |
1816 | if (!config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) | 2049 | if (!config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) |
@@ -1825,9 +2058,9 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar, | |||
1825 | return; | 2058 | return; |
1826 | } | 2059 | } |
1827 | 2060 | ||
1828 | tlv = (struct phyerr_tlv *)&event->bufp[i]; | 2061 | tlv = (struct phyerr_tlv *)&phyerr->buf[i]; |
1829 | tlv_len = __le16_to_cpu(tlv->len); | 2062 | tlv_len = __le16_to_cpu(tlv->len); |
1830 | tlv_buf = &event->bufp[i + sizeof(*tlv)]; | 2063 | tlv_buf = &phyerr->buf[i + sizeof(*tlv)]; |
1831 | ath10k_dbg(ar, ATH10K_DBG_REGULATORY, | 2064 | ath10k_dbg(ar, ATH10K_DBG_REGULATORY, |
1832 | "wmi event dfs tlv_len %d tlv_tag 0x%02X tlv_sig 0x%02X\n", | 2065 | "wmi event dfs tlv_len %d tlv_tag 0x%02X tlv_sig 0x%02X\n", |
1833 | tlv_len, tlv->tag, tlv->sig); | 2066 | tlv_len, tlv->tag, tlv->sig); |
@@ -1841,7 +2074,7 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar, | |||
1841 | } | 2074 | } |
1842 | 2075 | ||
1843 | rr = (struct phyerr_radar_report *)tlv_buf; | 2076 | rr = (struct phyerr_radar_report *)tlv_buf; |
1844 | ath10k_dfs_radar_report(ar, event, rr, tsf); | 2077 | ath10k_dfs_radar_report(ar, phyerr, rr, tsf); |
1845 | break; | 2078 | break; |
1846 | case PHYERR_TLV_TAG_SEARCH_FFT_REPORT: | 2079 | case PHYERR_TLV_TAG_SEARCH_FFT_REPORT: |
1847 | if (i + sizeof(*tlv) + sizeof(*fftr) > buf_len) { | 2080 | if (i + sizeof(*tlv) + sizeof(*fftr) > buf_len) { |
@@ -1851,7 +2084,7 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar, | |||
1851 | } | 2084 | } |
1852 | 2085 | ||
1853 | fftr = (struct phyerr_fft_report *)tlv_buf; | 2086 | fftr = (struct phyerr_fft_report *)tlv_buf; |
1854 | res = ath10k_dfs_fft_report(ar, event, fftr, tsf); | 2087 | res = ath10k_dfs_fft_report(ar, phyerr, fftr, tsf); |
1855 | if (res) | 2088 | if (res) |
1856 | return; | 2089 | return; |
1857 | break; | 2090 | break; |
@@ -1863,16 +2096,16 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar, | |||
1863 | 2096 | ||
1864 | static void | 2097 | static void |
1865 | ath10k_wmi_event_spectral_scan(struct ath10k *ar, | 2098 | ath10k_wmi_event_spectral_scan(struct ath10k *ar, |
1866 | struct wmi_single_phyerr_rx_event *event, | 2099 | const struct wmi_phyerr *phyerr, |
1867 | u64 tsf) | 2100 | u64 tsf) |
1868 | { | 2101 | { |
1869 | int buf_len, tlv_len, res, i = 0; | 2102 | int buf_len, tlv_len, res, i = 0; |
1870 | struct phyerr_tlv *tlv; | 2103 | struct phyerr_tlv *tlv; |
1871 | u8 *tlv_buf; | 2104 | const void *tlv_buf; |
1872 | struct phyerr_fft_report *fftr; | 2105 | const struct phyerr_fft_report *fftr; |
1873 | size_t fftr_len; | 2106 | size_t fftr_len; |
1874 | 2107 | ||
1875 | buf_len = __le32_to_cpu(event->hdr.buf_len); | 2108 | buf_len = __le32_to_cpu(phyerr->buf_len); |
1876 | 2109 | ||
1877 | while (i < buf_len) { | 2110 | while (i < buf_len) { |
1878 | if (i + sizeof(*tlv) > buf_len) { | 2111 | if (i + sizeof(*tlv) > buf_len) { |
@@ -1881,9 +2114,9 @@ ath10k_wmi_event_spectral_scan(struct ath10k *ar, | |||
1881 | return; | 2114 | return; |
1882 | } | 2115 | } |
1883 | 2116 | ||
1884 | tlv = (struct phyerr_tlv *)&event->bufp[i]; | 2117 | tlv = (struct phyerr_tlv *)&phyerr->buf[i]; |
1885 | tlv_len = __le16_to_cpu(tlv->len); | 2118 | tlv_len = __le16_to_cpu(tlv->len); |
1886 | tlv_buf = &event->bufp[i + sizeof(*tlv)]; | 2119 | tlv_buf = &phyerr->buf[i + sizeof(*tlv)]; |
1887 | 2120 | ||
1888 | if (i + sizeof(*tlv) + tlv_len > buf_len) { | 2121 | if (i + sizeof(*tlv) + tlv_len > buf_len) { |
1889 | ath10k_warn(ar, "failed to parse phyerr tlv payload at byte %d\n", | 2122 | ath10k_warn(ar, "failed to parse phyerr tlv payload at byte %d\n", |
@@ -1900,8 +2133,8 @@ ath10k_wmi_event_spectral_scan(struct ath10k *ar, | |||
1900 | } | 2133 | } |
1901 | 2134 | ||
1902 | fftr_len = tlv_len - sizeof(*fftr); | 2135 | fftr_len = tlv_len - sizeof(*fftr); |
1903 | fftr = (struct phyerr_fft_report *)tlv_buf; | 2136 | fftr = tlv_buf; |
1904 | res = ath10k_spectral_process_fft(ar, event, | 2137 | res = ath10k_spectral_process_fft(ar, phyerr, |
1905 | fftr, fftr_len, | 2138 | fftr, fftr_len, |
1906 | tsf); | 2139 | tsf); |
1907 | if (res < 0) { | 2140 | if (res < 0) { |
@@ -1918,8 +2151,8 @@ ath10k_wmi_event_spectral_scan(struct ath10k *ar, | |||
1918 | 2151 | ||
1919 | static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) | 2152 | static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) |
1920 | { | 2153 | { |
1921 | struct wmi_comb_phyerr_rx_event *comb_event; | 2154 | const struct wmi_phyerr_event *ev; |
1922 | struct wmi_single_phyerr_rx_event *event; | 2155 | const struct wmi_phyerr *phyerr; |
1923 | u32 count, i, buf_len, phy_err_code; | 2156 | u32 count, i, buf_len, phy_err_code; |
1924 | u64 tsf; | 2157 | u64 tsf; |
1925 | int left_len = skb->len; | 2158 | int left_len = skb->len; |
@@ -1927,38 +2160,38 @@ static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) | |||
1927 | ATH10K_DFS_STAT_INC(ar, phy_errors); | 2160 | ATH10K_DFS_STAT_INC(ar, phy_errors); |
1928 | 2161 | ||
1929 | /* Check if combined event available */ | 2162 | /* Check if combined event available */ |
1930 | if (left_len < sizeof(*comb_event)) { | 2163 | if (left_len < sizeof(*ev)) { |
1931 | ath10k_warn(ar, "wmi phyerr combined event wrong len\n"); | 2164 | ath10k_warn(ar, "wmi phyerr combined event wrong len\n"); |
1932 | return; | 2165 | return; |
1933 | } | 2166 | } |
1934 | 2167 | ||
1935 | left_len -= sizeof(*comb_event); | 2168 | left_len -= sizeof(*ev); |
1936 | 2169 | ||
1937 | /* Check number of included events */ | 2170 | /* Check number of included events */ |
1938 | comb_event = (struct wmi_comb_phyerr_rx_event *)skb->data; | 2171 | ev = (const struct wmi_phyerr_event *)skb->data; |
1939 | count = __le32_to_cpu(comb_event->hdr.num_phyerr_events); | 2172 | count = __le32_to_cpu(ev->num_phyerrs); |
1940 | 2173 | ||
1941 | tsf = __le32_to_cpu(comb_event->hdr.tsf_u32); | 2174 | tsf = __le32_to_cpu(ev->tsf_u32); |
1942 | tsf <<= 32; | 2175 | tsf <<= 32; |
1943 | tsf |= __le32_to_cpu(comb_event->hdr.tsf_l32); | 2176 | tsf |= __le32_to_cpu(ev->tsf_l32); |
1944 | 2177 | ||
1945 | ath10k_dbg(ar, ATH10K_DBG_WMI, | 2178 | ath10k_dbg(ar, ATH10K_DBG_WMI, |
1946 | "wmi event phyerr count %d tsf64 0x%llX\n", | 2179 | "wmi event phyerr count %d tsf64 0x%llX\n", |
1947 | count, tsf); | 2180 | count, tsf); |
1948 | 2181 | ||
1949 | event = (struct wmi_single_phyerr_rx_event *)comb_event->bufp; | 2182 | phyerr = ev->phyerrs; |
1950 | for (i = 0; i < count; i++) { | 2183 | for (i = 0; i < count; i++) { |
1951 | /* Check if we can read event header */ | 2184 | /* Check if we can read event header */ |
1952 | if (left_len < sizeof(*event)) { | 2185 | if (left_len < sizeof(*phyerr)) { |
1953 | ath10k_warn(ar, "single event (%d) wrong head len\n", | 2186 | ath10k_warn(ar, "single event (%d) wrong head len\n", |
1954 | i); | 2187 | i); |
1955 | return; | 2188 | return; |
1956 | } | 2189 | } |
1957 | 2190 | ||
1958 | left_len -= sizeof(*event); | 2191 | left_len -= sizeof(*phyerr); |
1959 | 2192 | ||
1960 | buf_len = __le32_to_cpu(event->hdr.buf_len); | 2193 | buf_len = __le32_to_cpu(phyerr->buf_len); |
1961 | phy_err_code = event->hdr.phy_err_code; | 2194 | phy_err_code = phyerr->phy_err_code; |
1962 | 2195 | ||
1963 | if (left_len < buf_len) { | 2196 | if (left_len < buf_len) { |
1964 | ath10k_warn(ar, "single event (%d) wrong buf len\n", i); | 2197 | ath10k_warn(ar, "single event (%d) wrong buf len\n", i); |
@@ -1969,20 +2202,20 @@ static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) | |||
1969 | 2202 | ||
1970 | switch (phy_err_code) { | 2203 | switch (phy_err_code) { |
1971 | case PHY_ERROR_RADAR: | 2204 | case PHY_ERROR_RADAR: |
1972 | ath10k_wmi_event_dfs(ar, event, tsf); | 2205 | ath10k_wmi_event_dfs(ar, phyerr, tsf); |
1973 | break; | 2206 | break; |
1974 | case PHY_ERROR_SPECTRAL_SCAN: | 2207 | case PHY_ERROR_SPECTRAL_SCAN: |
1975 | ath10k_wmi_event_spectral_scan(ar, event, tsf); | 2208 | ath10k_wmi_event_spectral_scan(ar, phyerr, tsf); |
1976 | break; | 2209 | break; |
1977 | case PHY_ERROR_FALSE_RADAR_EXT: | 2210 | case PHY_ERROR_FALSE_RADAR_EXT: |
1978 | ath10k_wmi_event_dfs(ar, event, tsf); | 2211 | ath10k_wmi_event_dfs(ar, phyerr, tsf); |
1979 | ath10k_wmi_event_spectral_scan(ar, event, tsf); | 2212 | ath10k_wmi_event_spectral_scan(ar, phyerr, tsf); |
1980 | break; | 2213 | break; |
1981 | default: | 2214 | default: |
1982 | break; | 2215 | break; |
1983 | } | 2216 | } |
1984 | 2217 | ||
1985 | event += sizeof(*event) + buf_len; | 2218 | phyerr = (void *)phyerr + sizeof(*phyerr) + buf_len; |
1986 | } | 2219 | } |
1987 | } | 2220 | } |
1988 | 2221 | ||
@@ -2163,30 +2396,113 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id, | |||
2163 | return 0; | 2396 | return 0; |
2164 | } | 2397 | } |
2165 | 2398 | ||
2166 | static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, | 2399 | static int ath10k_wmi_main_pull_svc_rdy_ev(struct sk_buff *skb, |
2167 | struct sk_buff *skb) | 2400 | struct wmi_svc_rdy_ev_arg *arg) |
2168 | { | 2401 | { |
2169 | struct wmi_service_ready_event *ev = (void *)skb->data; | 2402 | struct wmi_service_ready_event *ev; |
2403 | size_t i, n; | ||
2404 | |||
2405 | if (skb->len < sizeof(*ev)) | ||
2406 | return -EPROTO; | ||
2407 | |||
2408 | ev = (void *)skb->data; | ||
2409 | skb_pull(skb, sizeof(*ev)); | ||
2410 | arg->min_tx_power = ev->hw_min_tx_power; | ||
2411 | arg->max_tx_power = ev->hw_max_tx_power; | ||
2412 | arg->ht_cap = ev->ht_cap_info; | ||
2413 | arg->vht_cap = ev->vht_cap_info; | ||
2414 | arg->sw_ver0 = ev->sw_version; | ||
2415 | arg->sw_ver1 = ev->sw_version_1; | ||
2416 | arg->phy_capab = ev->phy_capability; | ||
2417 | arg->num_rf_chains = ev->num_rf_chains; | ||
2418 | arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd; | ||
2419 | arg->num_mem_reqs = ev->num_mem_reqs; | ||
2420 | arg->service_map = ev->wmi_service_bitmap; | ||
2421 | |||
2422 | n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs), | ||
2423 | ARRAY_SIZE(arg->mem_reqs)); | ||
2424 | for (i = 0; i < n; i++) | ||
2425 | arg->mem_reqs[i] = &ev->mem_reqs[i]; | ||
2426 | |||
2427 | if (skb->len < | ||
2428 | __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0])) | ||
2429 | return -EPROTO; | ||
2430 | |||
2431 | return 0; | ||
2432 | } | ||
2433 | |||
2434 | static int ath10k_wmi_10x_pull_svc_rdy_ev(struct sk_buff *skb, | ||
2435 | struct wmi_svc_rdy_ev_arg *arg) | ||
2436 | { | ||
2437 | struct wmi_10x_service_ready_event *ev; | ||
2438 | int i, n; | ||
2439 | |||
2440 | if (skb->len < sizeof(*ev)) | ||
2441 | return -EPROTO; | ||
2442 | |||
2443 | ev = (void *)skb->data; | ||
2444 | skb_pull(skb, sizeof(*ev)); | ||
2445 | arg->min_tx_power = ev->hw_min_tx_power; | ||
2446 | arg->max_tx_power = ev->hw_max_tx_power; | ||
2447 | arg->ht_cap = ev->ht_cap_info; | ||
2448 | arg->vht_cap = ev->vht_cap_info; | ||
2449 | arg->sw_ver0 = ev->sw_version; | ||
2450 | arg->phy_capab = ev->phy_capability; | ||
2451 | arg->num_rf_chains = ev->num_rf_chains; | ||
2452 | arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd; | ||
2453 | arg->num_mem_reqs = ev->num_mem_reqs; | ||
2454 | arg->service_map = ev->wmi_service_bitmap; | ||
2455 | |||
2456 | n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs), | ||
2457 | ARRAY_SIZE(arg->mem_reqs)); | ||
2458 | for (i = 0; i < n; i++) | ||
2459 | arg->mem_reqs[i] = &ev->mem_reqs[i]; | ||
2460 | |||
2461 | if (skb->len < | ||
2462 | __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0])) | ||
2463 | return -EPROTO; | ||
2464 | |||
2465 | return 0; | ||
2466 | } | ||
2467 | |||
2468 | static void ath10k_wmi_event_service_ready(struct ath10k *ar, | ||
2469 | struct sk_buff *skb) | ||
2470 | { | ||
2471 | struct wmi_svc_rdy_ev_arg arg = {}; | ||
2472 | u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i; | ||
2170 | DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {}; | 2473 | DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {}; |
2474 | int ret; | ||
2475 | |||
2476 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { | ||
2477 | ret = ath10k_wmi_10x_pull_svc_rdy_ev(skb, &arg); | ||
2478 | wmi_10x_svc_map(arg.service_map, svc_bmap); | ||
2479 | } else { | ||
2480 | ret = ath10k_wmi_main_pull_svc_rdy_ev(skb, &arg); | ||
2481 | wmi_main_svc_map(arg.service_map, svc_bmap); | ||
2482 | } | ||
2171 | 2483 | ||
2172 | if (skb->len < sizeof(*ev)) { | 2484 | if (ret) { |
2173 | ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n", | 2485 | ath10k_warn(ar, "failed to parse service ready: %d\n", ret); |
2174 | skb->len, sizeof(*ev)); | ||
2175 | return; | 2486 | return; |
2176 | } | 2487 | } |
2177 | 2488 | ||
2178 | ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power); | 2489 | ar->hw_min_tx_power = __le32_to_cpu(arg.min_tx_power); |
2179 | ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power); | 2490 | ar->hw_max_tx_power = __le32_to_cpu(arg.max_tx_power); |
2180 | ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info); | 2491 | ar->ht_cap_info = __le32_to_cpu(arg.ht_cap); |
2181 | ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info); | 2492 | ar->vht_cap_info = __le32_to_cpu(arg.vht_cap); |
2182 | ar->fw_version_major = | 2493 | ar->fw_version_major = |
2183 | (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24; | 2494 | (__le32_to_cpu(arg.sw_ver0) & 0xff000000) >> 24; |
2184 | ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff); | 2495 | ar->fw_version_minor = (__le32_to_cpu(arg.sw_ver0) & 0x00ffffff); |
2185 | ar->fw_version_release = | 2496 | ar->fw_version_release = |
2186 | (__le32_to_cpu(ev->sw_version_1) & 0xffff0000) >> 16; | 2497 | (__le32_to_cpu(arg.sw_ver1) & 0xffff0000) >> 16; |
2187 | ar->fw_version_build = (__le32_to_cpu(ev->sw_version_1) & 0x0000ffff); | 2498 | ar->fw_version_build = (__le32_to_cpu(arg.sw_ver1) & 0x0000ffff); |
2188 | ar->phy_capability = __le32_to_cpu(ev->phy_capability); | 2499 | ar->phy_capability = __le32_to_cpu(arg.phy_capab); |
2189 | ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); | 2500 | ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains); |
2501 | ar->ath_common.regulatory.current_rd = __le32_to_cpu(arg.eeprom_rd); | ||
2502 | |||
2503 | ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap)); | ||
2504 | ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ", | ||
2505 | arg.service_map, sizeof(arg.service_map)); | ||
2190 | 2506 | ||
2191 | /* only manually set fw features when not using FW IE format */ | 2507 | /* only manually set fw features when not using FW IE format */ |
2192 | if (ar->fw_api == 1 && ar->fw_version_build > 636) | 2508 | if (ar->fw_api == 1 && ar->fw_version_build > 636) |
@@ -2198,13 +2514,8 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, | |||
2198 | ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM; | 2514 | ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM; |
2199 | } | 2515 | } |
2200 | 2516 | ||
2201 | ar->ath_common.regulatory.current_rd = | 2517 | ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1; |
2202 | __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd); | 2518 | ar->supp_rx_chainmask = (1 << ar->num_rf_chains) - 1; |
2203 | |||
2204 | wmi_main_svc_map(ev->wmi_service_bitmap, svc_bmap); | ||
2205 | ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap)); | ||
2206 | ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ", | ||
2207 | ev->wmi_service_bitmap, sizeof(ev->wmi_service_bitmap)); | ||
2208 | 2519 | ||
2209 | if (strlen(ar->hw->wiphy->fw_version) == 0) { | 2520 | if (strlen(ar->hw->wiphy->fw_version) == 0) { |
2210 | snprintf(ar->hw->wiphy->fw_version, | 2521 | snprintf(ar->hw->wiphy->fw_version, |
@@ -2216,93 +2527,18 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, | |||
2216 | ar->fw_version_build); | 2527 | ar->fw_version_build); |
2217 | } | 2528 | } |
2218 | 2529 | ||
2219 | /* FIXME: it probably should be better to support this */ | 2530 | num_mem_reqs = __le32_to_cpu(arg.num_mem_reqs); |
2220 | if (__le32_to_cpu(ev->num_mem_reqs) > 0) { | 2531 | if (num_mem_reqs > WMI_MAX_MEM_REQS) { |
2221 | ath10k_warn(ar, "target requested %d memory chunks; ignoring\n", | ||
2222 | __le32_to_cpu(ev->num_mem_reqs)); | ||
2223 | } | ||
2224 | |||
2225 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
2226 | "wmi event service ready sw_ver 0x%08x sw_ver1 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n", | ||
2227 | __le32_to_cpu(ev->sw_version), | ||
2228 | __le32_to_cpu(ev->sw_version_1), | ||
2229 | __le32_to_cpu(ev->abi_version), | ||
2230 | __le32_to_cpu(ev->phy_capability), | ||
2231 | __le32_to_cpu(ev->ht_cap_info), | ||
2232 | __le32_to_cpu(ev->vht_cap_info), | ||
2233 | __le32_to_cpu(ev->vht_supp_mcs), | ||
2234 | __le32_to_cpu(ev->sys_cap_info), | ||
2235 | __le32_to_cpu(ev->num_mem_reqs), | ||
2236 | __le32_to_cpu(ev->num_rf_chains)); | ||
2237 | |||
2238 | complete(&ar->wmi.service_ready); | ||
2239 | } | ||
2240 | |||
2241 | static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar, | ||
2242 | struct sk_buff *skb) | ||
2243 | { | ||
2244 | u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i; | ||
2245 | int ret; | ||
2246 | struct wmi_service_ready_event_10x *ev = (void *)skb->data; | ||
2247 | DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {}; | ||
2248 | |||
2249 | if (skb->len < sizeof(*ev)) { | ||
2250 | ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n", | ||
2251 | skb->len, sizeof(*ev)); | ||
2252 | return; | ||
2253 | } | ||
2254 | |||
2255 | ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power); | ||
2256 | ar->hw_max_tx_power = __le32_to_cpu(ev->hw_max_tx_power); | ||
2257 | ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info); | ||
2258 | ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info); | ||
2259 | ar->fw_version_major = | ||
2260 | (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24; | ||
2261 | ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff); | ||
2262 | ar->phy_capability = __le32_to_cpu(ev->phy_capability); | ||
2263 | ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); | ||
2264 | |||
2265 | if (ar->num_rf_chains > WMI_MAX_SPATIAL_STREAM) { | ||
2266 | ath10k_warn(ar, "hardware advertises support for more spatial streams than it should (%d > %d)\n", | ||
2267 | ar->num_rf_chains, WMI_MAX_SPATIAL_STREAM); | ||
2268 | ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM; | ||
2269 | } | ||
2270 | |||
2271 | ar->ath_common.regulatory.current_rd = | ||
2272 | __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd); | ||
2273 | |||
2274 | wmi_10x_svc_map(ev->wmi_service_bitmap, svc_bmap); | ||
2275 | ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap)); | ||
2276 | ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ", | ||
2277 | ev->wmi_service_bitmap, sizeof(ev->wmi_service_bitmap)); | ||
2278 | |||
2279 | if (strlen(ar->hw->wiphy->fw_version) == 0) { | ||
2280 | snprintf(ar->hw->wiphy->fw_version, | ||
2281 | sizeof(ar->hw->wiphy->fw_version), | ||
2282 | "%u.%u", | ||
2283 | ar->fw_version_major, | ||
2284 | ar->fw_version_minor); | ||
2285 | } | ||
2286 | |||
2287 | num_mem_reqs = __le32_to_cpu(ev->num_mem_reqs); | ||
2288 | |||
2289 | if (num_mem_reqs > ATH10K_MAX_MEM_REQS) { | ||
2290 | ath10k_warn(ar, "requested memory chunks number (%d) exceeds the limit\n", | 2532 | ath10k_warn(ar, "requested memory chunks number (%d) exceeds the limit\n", |
2291 | num_mem_reqs); | 2533 | num_mem_reqs); |
2292 | return; | 2534 | return; |
2293 | } | 2535 | } |
2294 | 2536 | ||
2295 | if (!num_mem_reqs) | ||
2296 | goto exit; | ||
2297 | |||
2298 | ath10k_dbg(ar, ATH10K_DBG_WMI, "firmware has requested %d memory chunks\n", | ||
2299 | num_mem_reqs); | ||
2300 | |||
2301 | for (i = 0; i < num_mem_reqs; ++i) { | 2537 | for (i = 0; i < num_mem_reqs; ++i) { |
2302 | req_id = __le32_to_cpu(ev->mem_reqs[i].req_id); | 2538 | req_id = __le32_to_cpu(arg.mem_reqs[i]->req_id); |
2303 | num_units = __le32_to_cpu(ev->mem_reqs[i].num_units); | 2539 | num_units = __le32_to_cpu(arg.mem_reqs[i]->num_units); |
2304 | unit_size = __le32_to_cpu(ev->mem_reqs[i].unit_size); | 2540 | unit_size = __le32_to_cpu(arg.mem_reqs[i]->unit_size); |
2305 | num_unit_info = __le32_to_cpu(ev->mem_reqs[i].num_unit_info); | 2541 | num_unit_info = __le32_to_cpu(arg.mem_reqs[i]->num_unit_info); |
2306 | 2542 | ||
2307 | if (num_unit_info & NUM_UNITS_IS_NUM_PEERS) | 2543 | if (num_unit_info & NUM_UNITS_IS_NUM_PEERS) |
2308 | /* number of units to allocate is number of | 2544 | /* number of units to allocate is number of |
@@ -2316,7 +2552,7 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar, | |||
2316 | ath10k_dbg(ar, ATH10K_DBG_WMI, | 2552 | ath10k_dbg(ar, ATH10K_DBG_WMI, |
2317 | "wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n", | 2553 | "wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n", |
2318 | req_id, | 2554 | req_id, |
2319 | __le32_to_cpu(ev->mem_reqs[i].num_units), | 2555 | __le32_to_cpu(arg.mem_reqs[i]->num_units), |
2320 | num_unit_info, | 2556 | num_unit_info, |
2321 | unit_size, | 2557 | unit_size, |
2322 | num_units); | 2558 | num_units); |
@@ -2327,23 +2563,23 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar, | |||
2327 | return; | 2563 | return; |
2328 | } | 2564 | } |
2329 | 2565 | ||
2330 | exit: | ||
2331 | ath10k_dbg(ar, ATH10K_DBG_WMI, | 2566 | ath10k_dbg(ar, ATH10K_DBG_WMI, |
2332 | "wmi event service ready sw_ver 0x%08x abi_ver %u phy_cap 0x%08x ht_cap 0x%08x vht_cap 0x%08x vht_supp_msc 0x%08x sys_cap_info 0x%08x mem_reqs %u num_rf_chains %u\n", | 2567 | "wmi event service ready min_tx_power 0x%08x max_tx_power 0x%08x ht_cap 0x%08x vht_cap 0x%08x sw_ver0 0x%08x sw_ver1 0x%08x phy_capab 0x%08x num_rf_chains 0x%08x eeprom_rd 0x%08x num_mem_reqs 0x%08x\n", |
2333 | __le32_to_cpu(ev->sw_version), | 2568 | __le32_to_cpu(arg.min_tx_power), |
2334 | __le32_to_cpu(ev->abi_version), | 2569 | __le32_to_cpu(arg.max_tx_power), |
2335 | __le32_to_cpu(ev->phy_capability), | 2570 | __le32_to_cpu(arg.ht_cap), |
2336 | __le32_to_cpu(ev->ht_cap_info), | 2571 | __le32_to_cpu(arg.vht_cap), |
2337 | __le32_to_cpu(ev->vht_cap_info), | 2572 | __le32_to_cpu(arg.sw_ver0), |
2338 | __le32_to_cpu(ev->vht_supp_mcs), | 2573 | __le32_to_cpu(arg.sw_ver1), |
2339 | __le32_to_cpu(ev->sys_cap_info), | 2574 | __le32_to_cpu(arg.phy_capab), |
2340 | __le32_to_cpu(ev->num_mem_reqs), | 2575 | __le32_to_cpu(arg.num_rf_chains), |
2341 | __le32_to_cpu(ev->num_rf_chains)); | 2576 | __le32_to_cpu(arg.eeprom_rd), |
2577 | __le32_to_cpu(arg.num_mem_reqs)); | ||
2342 | 2578 | ||
2343 | complete(&ar->wmi.service_ready); | 2579 | complete(&ar->wmi.service_ready); |
2344 | } | 2580 | } |
2345 | 2581 | ||
2346 | static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb) | 2582 | static int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb) |
2347 | { | 2583 | { |
2348 | struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data; | 2584 | struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data; |
2349 | 2585 | ||
@@ -2466,10 +2702,10 @@ static void ath10k_wmi_main_process_rx(struct ath10k *ar, struct sk_buff *skb) | |||
2466 | ath10k_wmi_event_vdev_install_key_complete(ar, skb); | 2702 | ath10k_wmi_event_vdev_install_key_complete(ar, skb); |
2467 | break; | 2703 | break; |
2468 | case WMI_SERVICE_READY_EVENTID: | 2704 | case WMI_SERVICE_READY_EVENTID: |
2469 | ath10k_wmi_service_ready_event_rx(ar, skb); | 2705 | ath10k_wmi_event_service_ready(ar, skb); |
2470 | break; | 2706 | break; |
2471 | case WMI_READY_EVENTID: | 2707 | case WMI_READY_EVENTID: |
2472 | ath10k_wmi_ready_event_rx(ar, skb); | 2708 | ath10k_wmi_event_ready(ar, skb); |
2473 | break; | 2709 | break; |
2474 | default: | 2710 | default: |
2475 | ath10k_warn(ar, "Unknown eventid: %d\n", id); | 2711 | ath10k_warn(ar, "Unknown eventid: %d\n", id); |
@@ -2586,10 +2822,10 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb) | |||
2586 | ath10k_wmi_event_vdev_resume_req(ar, skb); | 2822 | ath10k_wmi_event_vdev_resume_req(ar, skb); |
2587 | break; | 2823 | break; |
2588 | case WMI_10X_SERVICE_READY_EVENTID: | 2824 | case WMI_10X_SERVICE_READY_EVENTID: |
2589 | ath10k_wmi_10x_service_ready_event_rx(ar, skb); | 2825 | ath10k_wmi_event_service_ready(ar, skb); |
2590 | break; | 2826 | break; |
2591 | case WMI_10X_READY_EVENTID: | 2827 | case WMI_10X_READY_EVENTID: |
2592 | ath10k_wmi_ready_event_rx(ar, skb); | 2828 | ath10k_wmi_event_ready(ar, skb); |
2593 | break; | 2829 | break; |
2594 | case WMI_10X_PDEV_UTF_EVENTID: | 2830 | case WMI_10X_PDEV_UTF_EVENTID: |
2595 | /* ignore utf events */ | 2831 | /* ignore utf events */ |
@@ -2697,10 +2933,10 @@ static void ath10k_wmi_10_2_process_rx(struct ath10k *ar, struct sk_buff *skb) | |||
2697 | ath10k_wmi_event_vdev_resume_req(ar, skb); | 2933 | ath10k_wmi_event_vdev_resume_req(ar, skb); |
2698 | break; | 2934 | break; |
2699 | case WMI_10_2_SERVICE_READY_EVENTID: | 2935 | case WMI_10_2_SERVICE_READY_EVENTID: |
2700 | ath10k_wmi_10x_service_ready_event_rx(ar, skb); | 2936 | ath10k_wmi_event_service_ready(ar, skb); |
2701 | break; | 2937 | break; |
2702 | case WMI_10_2_READY_EVENTID: | 2938 | case WMI_10_2_READY_EVENTID: |
2703 | ath10k_wmi_ready_event_rx(ar, skb); | 2939 | ath10k_wmi_event_ready(ar, skb); |
2704 | break; | 2940 | break; |
2705 | case WMI_10_2_RTT_KEEPALIVE_EVENTID: | 2941 | case WMI_10_2_RTT_KEEPALIVE_EVENTID: |
2706 | case WMI_10_2_GPIO_INPUT_EVENTID: | 2942 | case WMI_10_2_GPIO_INPUT_EVENTID: |
@@ -2732,45 +2968,6 @@ static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb) | |||
2732 | } | 2968 | } |
2733 | } | 2969 | } |
2734 | 2970 | ||
2735 | /* WMI Initialization functions */ | ||
2736 | int ath10k_wmi_attach(struct ath10k *ar) | ||
2737 | { | ||
2738 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { | ||
2739 | if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features)) | ||
2740 | ar->wmi.cmd = &wmi_10_2_cmd_map; | ||
2741 | else | ||
2742 | ar->wmi.cmd = &wmi_10x_cmd_map; | ||
2743 | |||
2744 | ar->wmi.vdev_param = &wmi_10x_vdev_param_map; | ||
2745 | ar->wmi.pdev_param = &wmi_10x_pdev_param_map; | ||
2746 | } else { | ||
2747 | ar->wmi.cmd = &wmi_cmd_map; | ||
2748 | ar->wmi.vdev_param = &wmi_vdev_param_map; | ||
2749 | ar->wmi.pdev_param = &wmi_pdev_param_map; | ||
2750 | } | ||
2751 | |||
2752 | init_completion(&ar->wmi.service_ready); | ||
2753 | init_completion(&ar->wmi.unified_ready); | ||
2754 | init_waitqueue_head(&ar->wmi.tx_credits_wq); | ||
2755 | |||
2756 | return 0; | ||
2757 | } | ||
2758 | |||
2759 | void ath10k_wmi_detach(struct ath10k *ar) | ||
2760 | { | ||
2761 | int i; | ||
2762 | |||
2763 | /* free the host memory chunks requested by firmware */ | ||
2764 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | ||
2765 | dma_free_coherent(ar->dev, | ||
2766 | ar->wmi.mem_chunks[i].len, | ||
2767 | ar->wmi.mem_chunks[i].vaddr, | ||
2768 | ar->wmi.mem_chunks[i].paddr); | ||
2769 | } | ||
2770 | |||
2771 | ar->wmi.num_mem_chunks = 0; | ||
2772 | } | ||
2773 | |||
2774 | int ath10k_wmi_connect(struct ath10k *ar) | 2971 | int ath10k_wmi_connect(struct ath10k *ar) |
2775 | { | 2972 | { |
2776 | int status; | 2973 | int status; |
@@ -2865,42 +3062,6 @@ int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, | |||
2865 | ctl2g, ctl5g); | 3062 | ctl2g, ctl5g); |
2866 | } | 3063 | } |
2867 | 3064 | ||
2868 | int ath10k_wmi_pdev_set_channel(struct ath10k *ar, | ||
2869 | const struct wmi_channel_arg *arg) | ||
2870 | { | ||
2871 | struct wmi_set_channel_cmd *cmd; | ||
2872 | struct sk_buff *skb; | ||
2873 | u32 ch_flags = 0; | ||
2874 | |||
2875 | if (arg->passive) | ||
2876 | return -EINVAL; | ||
2877 | |||
2878 | skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); | ||
2879 | if (!skb) | ||
2880 | return -ENOMEM; | ||
2881 | |||
2882 | if (arg->chan_radar) | ||
2883 | ch_flags |= WMI_CHAN_FLAG_DFS; | ||
2884 | |||
2885 | cmd = (struct wmi_set_channel_cmd *)skb->data; | ||
2886 | cmd->chan.mhz = __cpu_to_le32(arg->freq); | ||
2887 | cmd->chan.band_center_freq1 = __cpu_to_le32(arg->freq); | ||
2888 | cmd->chan.mode = arg->mode; | ||
2889 | cmd->chan.flags |= __cpu_to_le32(ch_flags); | ||
2890 | cmd->chan.min_power = arg->min_power; | ||
2891 | cmd->chan.max_power = arg->max_power; | ||
2892 | cmd->chan.reg_power = arg->max_reg_power; | ||
2893 | cmd->chan.reg_classid = arg->reg_class_id; | ||
2894 | cmd->chan.antenna_max = arg->max_antenna_gain; | ||
2895 | |||
2896 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
2897 | "wmi set channel mode %d freq %d\n", | ||
2898 | arg->mode, arg->freq); | ||
2899 | |||
2900 | return ath10k_wmi_cmd_send(ar, skb, | ||
2901 | ar->wmi.cmd->pdev_set_channel_cmdid); | ||
2902 | } | ||
2903 | |||
2904 | int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt) | 3065 | int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt) |
2905 | { | 3066 | { |
2906 | struct wmi_pdev_suspend_cmd *cmd; | 3067 | struct wmi_pdev_suspend_cmd *cmd; |
@@ -2951,13 +3112,34 @@ int ath10k_wmi_pdev_set_param(struct ath10k *ar, u32 id, u32 value) | |||
2951 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_set_param_cmdid); | 3112 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_set_param_cmdid); |
2952 | } | 3113 | } |
2953 | 3114 | ||
3115 | static void ath10k_wmi_put_host_mem_chunks(struct ath10k *ar, | ||
3116 | struct wmi_host_mem_chunks *chunks) | ||
3117 | { | ||
3118 | struct host_memory_chunk *chunk; | ||
3119 | int i; | ||
3120 | |||
3121 | chunks->count = __cpu_to_le32(ar->wmi.num_mem_chunks); | ||
3122 | |||
3123 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | ||
3124 | chunk = &chunks->items[i]; | ||
3125 | chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); | ||
3126 | chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len); | ||
3127 | chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); | ||
3128 | |||
3129 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
3130 | "wmi chunk %d len %d requested, addr 0x%llx\n", | ||
3131 | i, | ||
3132 | ar->wmi.mem_chunks[i].len, | ||
3133 | (unsigned long long)ar->wmi.mem_chunks[i].paddr); | ||
3134 | } | ||
3135 | } | ||
3136 | |||
2954 | static int ath10k_wmi_main_cmd_init(struct ath10k *ar) | 3137 | static int ath10k_wmi_main_cmd_init(struct ath10k *ar) |
2955 | { | 3138 | { |
2956 | struct wmi_init_cmd *cmd; | 3139 | struct wmi_init_cmd *cmd; |
2957 | struct sk_buff *buf; | 3140 | struct sk_buff *buf; |
2958 | struct wmi_resource_config config = {}; | 3141 | struct wmi_resource_config config = {}; |
2959 | u32 len, val; | 3142 | u32 len, val; |
2960 | int i; | ||
2961 | 3143 | ||
2962 | config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS); | 3144 | config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS); |
2963 | config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS); | 3145 | config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS); |
@@ -3019,32 +3201,8 @@ static int ath10k_wmi_main_cmd_init(struct ath10k *ar) | |||
3019 | 3201 | ||
3020 | cmd = (struct wmi_init_cmd *)buf->data; | 3202 | cmd = (struct wmi_init_cmd *)buf->data; |
3021 | 3203 | ||
3022 | if (ar->wmi.num_mem_chunks == 0) { | ||
3023 | cmd->num_host_mem_chunks = 0; | ||
3024 | goto out; | ||
3025 | } | ||
3026 | |||
3027 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", | ||
3028 | ar->wmi.num_mem_chunks); | ||
3029 | |||
3030 | cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); | ||
3031 | |||
3032 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | ||
3033 | cmd->host_mem_chunks[i].ptr = | ||
3034 | __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); | ||
3035 | cmd->host_mem_chunks[i].size = | ||
3036 | __cpu_to_le32(ar->wmi.mem_chunks[i].len); | ||
3037 | cmd->host_mem_chunks[i].req_id = | ||
3038 | __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); | ||
3039 | |||
3040 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
3041 | "wmi chunk %d len %d requested, addr 0x%llx\n", | ||
3042 | i, | ||
3043 | ar->wmi.mem_chunks[i].len, | ||
3044 | (unsigned long long)ar->wmi.mem_chunks[i].paddr); | ||
3045 | } | ||
3046 | out: | ||
3047 | memcpy(&cmd->resource_config, &config, sizeof(config)); | 3204 | memcpy(&cmd->resource_config, &config, sizeof(config)); |
3205 | ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks); | ||
3048 | 3206 | ||
3049 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init\n"); | 3207 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init\n"); |
3050 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); | 3208 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); |
@@ -3056,7 +3214,6 @@ static int ath10k_wmi_10x_cmd_init(struct ath10k *ar) | |||
3056 | struct sk_buff *buf; | 3214 | struct sk_buff *buf; |
3057 | struct wmi_resource_config_10x config = {}; | 3215 | struct wmi_resource_config_10x config = {}; |
3058 | u32 len, val; | 3216 | u32 len, val; |
3059 | int i; | ||
3060 | 3217 | ||
3061 | config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); | 3218 | config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); |
3062 | config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); | 3219 | config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); |
@@ -3110,32 +3267,8 @@ static int ath10k_wmi_10x_cmd_init(struct ath10k *ar) | |||
3110 | 3267 | ||
3111 | cmd = (struct wmi_init_cmd_10x *)buf->data; | 3268 | cmd = (struct wmi_init_cmd_10x *)buf->data; |
3112 | 3269 | ||
3113 | if (ar->wmi.num_mem_chunks == 0) { | ||
3114 | cmd->num_host_mem_chunks = 0; | ||
3115 | goto out; | ||
3116 | } | ||
3117 | |||
3118 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", | ||
3119 | ar->wmi.num_mem_chunks); | ||
3120 | |||
3121 | cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); | ||
3122 | |||
3123 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | ||
3124 | cmd->host_mem_chunks[i].ptr = | ||
3125 | __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); | ||
3126 | cmd->host_mem_chunks[i].size = | ||
3127 | __cpu_to_le32(ar->wmi.mem_chunks[i].len); | ||
3128 | cmd->host_mem_chunks[i].req_id = | ||
3129 | __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); | ||
3130 | |||
3131 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
3132 | "wmi chunk %d len %d requested, addr 0x%llx\n", | ||
3133 | i, | ||
3134 | ar->wmi.mem_chunks[i].len, | ||
3135 | (unsigned long long)ar->wmi.mem_chunks[i].paddr); | ||
3136 | } | ||
3137 | out: | ||
3138 | memcpy(&cmd->resource_config, &config, sizeof(config)); | 3270 | memcpy(&cmd->resource_config, &config, sizeof(config)); |
3271 | ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks); | ||
3139 | 3272 | ||
3140 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10x\n"); | 3273 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10x\n"); |
3141 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); | 3274 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); |
@@ -3147,7 +3280,6 @@ static int ath10k_wmi_10_2_cmd_init(struct ath10k *ar) | |||
3147 | struct sk_buff *buf; | 3280 | struct sk_buff *buf; |
3148 | struct wmi_resource_config_10x config = {}; | 3281 | struct wmi_resource_config_10x config = {}; |
3149 | u32 len, val; | 3282 | u32 len, val; |
3150 | int i; | ||
3151 | 3283 | ||
3152 | config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); | 3284 | config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); |
3153 | config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); | 3285 | config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); |
@@ -3201,32 +3333,8 @@ static int ath10k_wmi_10_2_cmd_init(struct ath10k *ar) | |||
3201 | 3333 | ||
3202 | cmd = (struct wmi_init_cmd_10_2 *)buf->data; | 3334 | cmd = (struct wmi_init_cmd_10_2 *)buf->data; |
3203 | 3335 | ||
3204 | if (ar->wmi.num_mem_chunks == 0) { | ||
3205 | cmd->num_host_mem_chunks = 0; | ||
3206 | goto out; | ||
3207 | } | ||
3208 | |||
3209 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi sending %d memory chunks info.\n", | ||
3210 | ar->wmi.num_mem_chunks); | ||
3211 | |||
3212 | cmd->num_host_mem_chunks = __cpu_to_le32(ar->wmi.num_mem_chunks); | ||
3213 | |||
3214 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | ||
3215 | cmd->host_mem_chunks[i].ptr = | ||
3216 | __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); | ||
3217 | cmd->host_mem_chunks[i].size = | ||
3218 | __cpu_to_le32(ar->wmi.mem_chunks[i].len); | ||
3219 | cmd->host_mem_chunks[i].req_id = | ||
3220 | __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); | ||
3221 | |||
3222 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
3223 | "wmi chunk %d len %d requested, addr 0x%llx\n", | ||
3224 | i, | ||
3225 | ar->wmi.mem_chunks[i].len, | ||
3226 | (unsigned long long)ar->wmi.mem_chunks[i].paddr); | ||
3227 | } | ||
3228 | out: | ||
3229 | memcpy(&cmd->resource_config.common, &config, sizeof(config)); | 3336 | memcpy(&cmd->resource_config.common, &config, sizeof(config)); |
3337 | ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks); | ||
3230 | 3338 | ||
3231 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10.2\n"); | 3339 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10.2\n"); |
3232 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); | 3340 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); |
@@ -3248,52 +3356,50 @@ int ath10k_wmi_cmd_init(struct ath10k *ar) | |||
3248 | return ret; | 3356 | return ret; |
3249 | } | 3357 | } |
3250 | 3358 | ||
3251 | static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar, | 3359 | static int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg) |
3252 | const struct wmi_start_scan_arg *arg) | ||
3253 | { | 3360 | { |
3254 | int len; | 3361 | if (arg->ie_len && !arg->ie) |
3362 | return -EINVAL; | ||
3363 | if (arg->n_channels && !arg->channels) | ||
3364 | return -EINVAL; | ||
3365 | if (arg->n_ssids && !arg->ssids) | ||
3366 | return -EINVAL; | ||
3367 | if (arg->n_bssids && !arg->bssids) | ||
3368 | return -EINVAL; | ||
3255 | 3369 | ||
3256 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | 3370 | if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN) |
3257 | len = sizeof(struct wmi_start_scan_cmd_10x); | 3371 | return -EINVAL; |
3258 | else | 3372 | if (arg->n_channels > ARRAY_SIZE(arg->channels)) |
3259 | len = sizeof(struct wmi_start_scan_cmd); | 3373 | return -EINVAL; |
3374 | if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID) | ||
3375 | return -EINVAL; | ||
3376 | if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID) | ||
3377 | return -EINVAL; | ||
3260 | 3378 | ||
3261 | if (arg->ie_len) { | 3379 | return 0; |
3262 | if (!arg->ie) | 3380 | } |
3263 | return -EINVAL; | 3381 | |
3264 | if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN) | 3382 | static size_t |
3265 | return -EINVAL; | 3383 | ath10k_wmi_start_scan_tlvs_len(const struct wmi_start_scan_arg *arg) |
3384 | { | ||
3385 | int len = 0; | ||
3266 | 3386 | ||
3387 | if (arg->ie_len) { | ||
3267 | len += sizeof(struct wmi_ie_data); | 3388 | len += sizeof(struct wmi_ie_data); |
3268 | len += roundup(arg->ie_len, 4); | 3389 | len += roundup(arg->ie_len, 4); |
3269 | } | 3390 | } |
3270 | 3391 | ||
3271 | if (arg->n_channels) { | 3392 | if (arg->n_channels) { |
3272 | if (!arg->channels) | ||
3273 | return -EINVAL; | ||
3274 | if (arg->n_channels > ARRAY_SIZE(arg->channels)) | ||
3275 | return -EINVAL; | ||
3276 | |||
3277 | len += sizeof(struct wmi_chan_list); | 3393 | len += sizeof(struct wmi_chan_list); |
3278 | len += sizeof(__le32) * arg->n_channels; | 3394 | len += sizeof(__le32) * arg->n_channels; |
3279 | } | 3395 | } |
3280 | 3396 | ||
3281 | if (arg->n_ssids) { | 3397 | if (arg->n_ssids) { |
3282 | if (!arg->ssids) | ||
3283 | return -EINVAL; | ||
3284 | if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID) | ||
3285 | return -EINVAL; | ||
3286 | |||
3287 | len += sizeof(struct wmi_ssid_list); | 3398 | len += sizeof(struct wmi_ssid_list); |
3288 | len += sizeof(struct wmi_ssid) * arg->n_ssids; | 3399 | len += sizeof(struct wmi_ssid) * arg->n_ssids; |
3289 | } | 3400 | } |
3290 | 3401 | ||
3291 | if (arg->n_bssids) { | 3402 | if (arg->n_bssids) { |
3292 | if (!arg->bssids) | ||
3293 | return -EINVAL; | ||
3294 | if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID) | ||
3295 | return -EINVAL; | ||
3296 | |||
3297 | len += sizeof(struct wmi_bssid_list); | 3403 | len += sizeof(struct wmi_bssid_list); |
3298 | len += sizeof(struct wmi_mac_addr) * arg->n_bssids; | 3404 | len += sizeof(struct wmi_mac_addr) * arg->n_bssids; |
3299 | } | 3405 | } |
@@ -3301,28 +3407,12 @@ static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar, | |||
3301 | return len; | 3407 | return len; |
3302 | } | 3408 | } |
3303 | 3409 | ||
3304 | int ath10k_wmi_start_scan(struct ath10k *ar, | 3410 | static void |
3305 | const struct wmi_start_scan_arg *arg) | 3411 | ath10k_wmi_put_start_scan_common(struct wmi_start_scan_common *cmn, |
3412 | const struct wmi_start_scan_arg *arg) | ||
3306 | { | 3413 | { |
3307 | struct wmi_start_scan_cmd *cmd; | ||
3308 | struct sk_buff *skb; | ||
3309 | struct wmi_ie_data *ie; | ||
3310 | struct wmi_chan_list *channels; | ||
3311 | struct wmi_ssid_list *ssids; | ||
3312 | struct wmi_bssid_list *bssids; | ||
3313 | u32 scan_id; | 3414 | u32 scan_id; |
3314 | u32 scan_req_id; | 3415 | u32 scan_req_id; |
3315 | int off; | ||
3316 | int len = 0; | ||
3317 | int i; | ||
3318 | |||
3319 | len = ath10k_wmi_start_scan_calc_len(ar, arg); | ||
3320 | if (len < 0) | ||
3321 | return len; /* len contains error code here */ | ||
3322 | |||
3323 | skb = ath10k_wmi_alloc_skb(ar, len); | ||
3324 | if (!skb) | ||
3325 | return -ENOMEM; | ||
3326 | 3416 | ||
3327 | scan_id = WMI_HOST_SCAN_REQ_ID_PREFIX; | 3417 | scan_id = WMI_HOST_SCAN_REQ_ID_PREFIX; |
3328 | scan_id |= arg->scan_id; | 3418 | scan_id |= arg->scan_id; |
@@ -3330,35 +3420,36 @@ int ath10k_wmi_start_scan(struct ath10k *ar, | |||
3330 | scan_req_id = WMI_HOST_SCAN_REQUESTOR_ID_PREFIX; | 3420 | scan_req_id = WMI_HOST_SCAN_REQUESTOR_ID_PREFIX; |
3331 | scan_req_id |= arg->scan_req_id; | 3421 | scan_req_id |= arg->scan_req_id; |
3332 | 3422 | ||
3333 | cmd = (struct wmi_start_scan_cmd *)skb->data; | 3423 | cmn->scan_id = __cpu_to_le32(scan_id); |
3334 | cmd->scan_id = __cpu_to_le32(scan_id); | 3424 | cmn->scan_req_id = __cpu_to_le32(scan_req_id); |
3335 | cmd->scan_req_id = __cpu_to_le32(scan_req_id); | 3425 | cmn->vdev_id = __cpu_to_le32(arg->vdev_id); |
3336 | cmd->vdev_id = __cpu_to_le32(arg->vdev_id); | 3426 | cmn->scan_priority = __cpu_to_le32(arg->scan_priority); |
3337 | cmd->scan_priority = __cpu_to_le32(arg->scan_priority); | 3427 | cmn->notify_scan_events = __cpu_to_le32(arg->notify_scan_events); |
3338 | cmd->notify_scan_events = __cpu_to_le32(arg->notify_scan_events); | 3428 | cmn->dwell_time_active = __cpu_to_le32(arg->dwell_time_active); |
3339 | cmd->dwell_time_active = __cpu_to_le32(arg->dwell_time_active); | 3429 | cmn->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive); |
3340 | cmd->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive); | 3430 | cmn->min_rest_time = __cpu_to_le32(arg->min_rest_time); |
3341 | cmd->min_rest_time = __cpu_to_le32(arg->min_rest_time); | 3431 | cmn->max_rest_time = __cpu_to_le32(arg->max_rest_time); |
3342 | cmd->max_rest_time = __cpu_to_le32(arg->max_rest_time); | 3432 | cmn->repeat_probe_time = __cpu_to_le32(arg->repeat_probe_time); |
3343 | cmd->repeat_probe_time = __cpu_to_le32(arg->repeat_probe_time); | 3433 | cmn->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time); |
3344 | cmd->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time); | 3434 | cmn->idle_time = __cpu_to_le32(arg->idle_time); |
3345 | cmd->idle_time = __cpu_to_le32(arg->idle_time); | 3435 | cmn->max_scan_time = __cpu_to_le32(arg->max_scan_time); |
3346 | cmd->max_scan_time = __cpu_to_le32(arg->max_scan_time); | 3436 | cmn->probe_delay = __cpu_to_le32(arg->probe_delay); |
3347 | cmd->probe_delay = __cpu_to_le32(arg->probe_delay); | 3437 | cmn->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags); |
3348 | cmd->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags); | 3438 | } |
3349 | 3439 | ||
3350 | /* TLV list starts after fields included in the struct */ | 3440 | static void |
3351 | /* There's just one filed that differes the two start_scan | 3441 | ath10k_wmi_put_start_scan_tlvs(struct wmi_start_scan_tlvs *tlvs, |
3352 | * structures - burst_duration, which we are not using btw, | 3442 | const struct wmi_start_scan_arg *arg) |
3353 | no point to make the split here, just shift the buffer to fit with | 3443 | { |
3354 | given FW */ | 3444 | struct wmi_ie_data *ie; |
3355 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | 3445 | struct wmi_chan_list *channels; |
3356 | off = sizeof(struct wmi_start_scan_cmd_10x); | 3446 | struct wmi_ssid_list *ssids; |
3357 | else | 3447 | struct wmi_bssid_list *bssids; |
3358 | off = sizeof(struct wmi_start_scan_cmd); | 3448 | void *ptr = tlvs->tlvs; |
3449 | int i; | ||
3359 | 3450 | ||
3360 | if (arg->n_channels) { | 3451 | if (arg->n_channels) { |
3361 | channels = (void *)skb->data + off; | 3452 | channels = ptr; |
3362 | channels->tag = __cpu_to_le32(WMI_CHAN_LIST_TAG); | 3453 | channels->tag = __cpu_to_le32(WMI_CHAN_LIST_TAG); |
3363 | channels->num_chan = __cpu_to_le32(arg->n_channels); | 3454 | channels->num_chan = __cpu_to_le32(arg->n_channels); |
3364 | 3455 | ||
@@ -3366,12 +3457,12 @@ int ath10k_wmi_start_scan(struct ath10k *ar, | |||
3366 | channels->channel_list[i].freq = | 3457 | channels->channel_list[i].freq = |
3367 | __cpu_to_le16(arg->channels[i]); | 3458 | __cpu_to_le16(arg->channels[i]); |
3368 | 3459 | ||
3369 | off += sizeof(*channels); | 3460 | ptr += sizeof(*channels); |
3370 | off += sizeof(__le32) * arg->n_channels; | 3461 | ptr += sizeof(__le32) * arg->n_channels; |
3371 | } | 3462 | } |
3372 | 3463 | ||
3373 | if (arg->n_ssids) { | 3464 | if (arg->n_ssids) { |
3374 | ssids = (void *)skb->data + off; | 3465 | ssids = ptr; |
3375 | ssids->tag = __cpu_to_le32(WMI_SSID_LIST_TAG); | 3466 | ssids->tag = __cpu_to_le32(WMI_SSID_LIST_TAG); |
3376 | ssids->num_ssids = __cpu_to_le32(arg->n_ssids); | 3467 | ssids->num_ssids = __cpu_to_le32(arg->n_ssids); |
3377 | 3468 | ||
@@ -3383,12 +3474,12 @@ int ath10k_wmi_start_scan(struct ath10k *ar, | |||
3383 | arg->ssids[i].len); | 3474 | arg->ssids[i].len); |
3384 | } | 3475 | } |
3385 | 3476 | ||
3386 | off += sizeof(*ssids); | 3477 | ptr += sizeof(*ssids); |
3387 | off += sizeof(struct wmi_ssid) * arg->n_ssids; | 3478 | ptr += sizeof(struct wmi_ssid) * arg->n_ssids; |
3388 | } | 3479 | } |
3389 | 3480 | ||
3390 | if (arg->n_bssids) { | 3481 | if (arg->n_bssids) { |
3391 | bssids = (void *)skb->data + off; | 3482 | bssids = ptr; |
3392 | bssids->tag = __cpu_to_le32(WMI_BSSID_LIST_TAG); | 3483 | bssids->tag = __cpu_to_le32(WMI_BSSID_LIST_TAG); |
3393 | bssids->num_bssid = __cpu_to_le32(arg->n_bssids); | 3484 | bssids->num_bssid = __cpu_to_le32(arg->n_bssids); |
3394 | 3485 | ||
@@ -3397,23 +3488,57 @@ int ath10k_wmi_start_scan(struct ath10k *ar, | |||
3397 | arg->bssids[i].bssid, | 3488 | arg->bssids[i].bssid, |
3398 | ETH_ALEN); | 3489 | ETH_ALEN); |
3399 | 3490 | ||
3400 | off += sizeof(*bssids); | 3491 | ptr += sizeof(*bssids); |
3401 | off += sizeof(struct wmi_mac_addr) * arg->n_bssids; | 3492 | ptr += sizeof(struct wmi_mac_addr) * arg->n_bssids; |
3402 | } | 3493 | } |
3403 | 3494 | ||
3404 | if (arg->ie_len) { | 3495 | if (arg->ie_len) { |
3405 | ie = (void *)skb->data + off; | 3496 | ie = ptr; |
3406 | ie->tag = __cpu_to_le32(WMI_IE_TAG); | 3497 | ie->tag = __cpu_to_le32(WMI_IE_TAG); |
3407 | ie->ie_len = __cpu_to_le32(arg->ie_len); | 3498 | ie->ie_len = __cpu_to_le32(arg->ie_len); |
3408 | memcpy(ie->ie_data, arg->ie, arg->ie_len); | 3499 | memcpy(ie->ie_data, arg->ie, arg->ie_len); |
3409 | 3500 | ||
3410 | off += sizeof(*ie); | 3501 | ptr += sizeof(*ie); |
3411 | off += roundup(arg->ie_len, 4); | 3502 | ptr += roundup(arg->ie_len, 4); |
3412 | } | 3503 | } |
3504 | } | ||
3413 | 3505 | ||
3414 | if (off != skb->len) { | 3506 | int ath10k_wmi_start_scan(struct ath10k *ar, |
3415 | dev_kfree_skb(skb); | 3507 | const struct wmi_start_scan_arg *arg) |
3416 | return -EINVAL; | 3508 | { |
3509 | struct sk_buff *skb; | ||
3510 | size_t len; | ||
3511 | int ret; | ||
3512 | |||
3513 | ret = ath10k_wmi_start_scan_verify(arg); | ||
3514 | if (ret) | ||
3515 | return ret; | ||
3516 | |||
3517 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | ||
3518 | len = sizeof(struct wmi_10x_start_scan_cmd) + | ||
3519 | ath10k_wmi_start_scan_tlvs_len(arg); | ||
3520 | else | ||
3521 | len = sizeof(struct wmi_start_scan_cmd) + | ||
3522 | ath10k_wmi_start_scan_tlvs_len(arg); | ||
3523 | |||
3524 | skb = ath10k_wmi_alloc_skb(ar, len); | ||
3525 | if (!skb) | ||
3526 | return -ENOMEM; | ||
3527 | |||
3528 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { | ||
3529 | struct wmi_10x_start_scan_cmd *cmd; | ||
3530 | |||
3531 | cmd = (struct wmi_10x_start_scan_cmd *)skb->data; | ||
3532 | ath10k_wmi_put_start_scan_common(&cmd->common, arg); | ||
3533 | ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg); | ||
3534 | } else { | ||
3535 | struct wmi_start_scan_cmd *cmd; | ||
3536 | |||
3537 | cmd = (struct wmi_start_scan_cmd *)skb->data; | ||
3538 | cmd->burst_duration_ms = __cpu_to_le32(0); | ||
3539 | |||
3540 | ath10k_wmi_put_start_scan_common(&cmd->common, arg); | ||
3541 | ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg); | ||
3417 | } | 3542 | } |
3418 | 3543 | ||
3419 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi start scan\n"); | 3544 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi start scan\n"); |
@@ -3532,7 +3657,6 @@ ath10k_wmi_vdev_start_restart(struct ath10k *ar, | |||
3532 | struct sk_buff *skb; | 3657 | struct sk_buff *skb; |
3533 | const char *cmdname; | 3658 | const char *cmdname; |
3534 | u32 flags = 0; | 3659 | u32 flags = 0; |
3535 | u32 ch_flags = 0; | ||
3536 | 3660 | ||
3537 | if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid && | 3661 | if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid && |
3538 | cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid) | 3662 | cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid) |
@@ -3559,8 +3683,6 @@ ath10k_wmi_vdev_start_restart(struct ath10k *ar, | |||
3559 | flags |= WMI_VDEV_START_HIDDEN_SSID; | 3683 | flags |= WMI_VDEV_START_HIDDEN_SSID; |
3560 | if (arg->pmf_enabled) | 3684 | if (arg->pmf_enabled) |
3561 | flags |= WMI_VDEV_START_PMF_ENABLED; | 3685 | flags |= WMI_VDEV_START_PMF_ENABLED; |
3562 | if (arg->channel.chan_radar) | ||
3563 | ch_flags |= WMI_CHAN_FLAG_DFS; | ||
3564 | 3686 | ||
3565 | cmd = (struct wmi_vdev_start_request_cmd *)skb->data; | 3687 | cmd = (struct wmi_vdev_start_request_cmd *)skb->data; |
3566 | cmd->vdev_id = __cpu_to_le32(arg->vdev_id); | 3688 | cmd->vdev_id = __cpu_to_le32(arg->vdev_id); |
@@ -3576,18 +3698,7 @@ ath10k_wmi_vdev_start_restart(struct ath10k *ar, | |||
3576 | memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len); | 3698 | memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len); |
3577 | } | 3699 | } |
3578 | 3700 | ||
3579 | cmd->chan.mhz = __cpu_to_le32(arg->channel.freq); | 3701 | ath10k_wmi_put_wmi_channel(&cmd->chan, &arg->channel); |
3580 | |||
3581 | cmd->chan.band_center_freq1 = | ||
3582 | __cpu_to_le32(arg->channel.band_center_freq1); | ||
3583 | |||
3584 | cmd->chan.mode = arg->channel.mode; | ||
3585 | cmd->chan.flags |= __cpu_to_le32(ch_flags); | ||
3586 | cmd->chan.min_power = arg->channel.min_power; | ||
3587 | cmd->chan.max_power = arg->channel.max_power; | ||
3588 | cmd->chan.reg_power = arg->channel.max_reg_power; | ||
3589 | cmd->chan.reg_classid = arg->channel.reg_class_id; | ||
3590 | cmd->chan.antenna_max = arg->channel.max_antenna_gain; | ||
3591 | 3702 | ||
3592 | ath10k_dbg(ar, ATH10K_DBG_WMI, | 3703 | ath10k_dbg(ar, ATH10K_DBG_WMI, |
3593 | "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, ch_flags: 0x%0X, max_power: %d\n", | 3704 | "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, ch_flags: 0x%0X, max_power: %d\n", |
@@ -3968,35 +4079,10 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar, | |||
3968 | cmd->num_scan_chans = __cpu_to_le32(arg->n_channels); | 4079 | cmd->num_scan_chans = __cpu_to_le32(arg->n_channels); |
3969 | 4080 | ||
3970 | for (i = 0; i < arg->n_channels; i++) { | 4081 | for (i = 0; i < arg->n_channels; i++) { |
3971 | u32 flags = 0; | ||
3972 | |||
3973 | ch = &arg->channels[i]; | 4082 | ch = &arg->channels[i]; |
3974 | ci = &cmd->chan_info[i]; | 4083 | ci = &cmd->chan_info[i]; |
3975 | 4084 | ||
3976 | if (ch->passive) | 4085 | ath10k_wmi_put_wmi_channel(ci, ch); |
3977 | flags |= WMI_CHAN_FLAG_PASSIVE; | ||
3978 | if (ch->allow_ibss) | ||
3979 | flags |= WMI_CHAN_FLAG_ADHOC_ALLOWED; | ||
3980 | if (ch->allow_ht) | ||
3981 | flags |= WMI_CHAN_FLAG_ALLOW_HT; | ||
3982 | if (ch->allow_vht) | ||
3983 | flags |= WMI_CHAN_FLAG_ALLOW_VHT; | ||
3984 | if (ch->ht40plus) | ||
3985 | flags |= WMI_CHAN_FLAG_HT40_PLUS; | ||
3986 | if (ch->chan_radar) | ||
3987 | flags |= WMI_CHAN_FLAG_DFS; | ||
3988 | |||
3989 | ci->mhz = __cpu_to_le32(ch->freq); | ||
3990 | ci->band_center_freq1 = __cpu_to_le32(ch->freq); | ||
3991 | ci->band_center_freq2 = 0; | ||
3992 | ci->min_power = ch->min_power; | ||
3993 | ci->max_power = ch->max_power; | ||
3994 | ci->reg_power = ch->max_reg_power; | ||
3995 | ci->antenna_max = ch->max_antenna_gain; | ||
3996 | |||
3997 | /* mode & flags share storage */ | ||
3998 | ci->mode = ch->mode; | ||
3999 | ci->flags |= __cpu_to_le32(flags); | ||
4000 | } | 4086 | } |
4001 | 4087 | ||
4002 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid); | 4088 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid); |
@@ -4108,9 +4194,9 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar, | |||
4108 | 4194 | ||
4109 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { | 4195 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { |
4110 | if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features)) | 4196 | if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features)) |
4111 | ath10k_wmi_peer_assoc_fill_10_1(ar, skb->data, arg); | ||
4112 | else | ||
4113 | ath10k_wmi_peer_assoc_fill_10_2(ar, skb->data, arg); | 4197 | ath10k_wmi_peer_assoc_fill_10_2(ar, skb->data, arg); |
4198 | else | ||
4199 | ath10k_wmi_peer_assoc_fill_10_1(ar, skb->data, arg); | ||
4114 | } else { | 4200 | } else { |
4115 | ath10k_wmi_peer_assoc_fill_main(ar, skb->data, arg); | 4201 | ath10k_wmi_peer_assoc_fill_main(ar, skb->data, arg); |
4116 | } | 4202 | } |
@@ -4267,3 +4353,73 @@ int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable) | |||
4267 | 4353 | ||
4268 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->dbglog_cfg_cmdid); | 4354 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->dbglog_cfg_cmdid); |
4269 | } | 4355 | } |
4356 | |||
4357 | int ath10k_wmi_pdev_pktlog_enable(struct ath10k *ar, u32 ev_bitmap) | ||
4358 | { | ||
4359 | struct wmi_pdev_pktlog_enable_cmd *cmd; | ||
4360 | struct sk_buff *skb; | ||
4361 | |||
4362 | skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); | ||
4363 | if (!skb) | ||
4364 | return -ENOMEM; | ||
4365 | |||
4366 | ev_bitmap &= ATH10K_PKTLOG_ANY; | ||
4367 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
4368 | "wmi enable pktlog filter:%x\n", ev_bitmap); | ||
4369 | |||
4370 | cmd = (struct wmi_pdev_pktlog_enable_cmd *)skb->data; | ||
4371 | cmd->ev_bitmap = __cpu_to_le32(ev_bitmap); | ||
4372 | return ath10k_wmi_cmd_send(ar, skb, | ||
4373 | ar->wmi.cmd->pdev_pktlog_enable_cmdid); | ||
4374 | } | ||
4375 | |||
4376 | int ath10k_wmi_pdev_pktlog_disable(struct ath10k *ar) | ||
4377 | { | ||
4378 | struct sk_buff *skb; | ||
4379 | |||
4380 | skb = ath10k_wmi_alloc_skb(ar, 0); | ||
4381 | if (!skb) | ||
4382 | return -ENOMEM; | ||
4383 | |||
4384 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi disable pktlog\n"); | ||
4385 | |||
4386 | return ath10k_wmi_cmd_send(ar, skb, | ||
4387 | ar->wmi.cmd->pdev_pktlog_disable_cmdid); | ||
4388 | } | ||
4389 | |||
4390 | int ath10k_wmi_attach(struct ath10k *ar) | ||
4391 | { | ||
4392 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { | ||
4393 | if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features)) | ||
4394 | ar->wmi.cmd = &wmi_10_2_cmd_map; | ||
4395 | else | ||
4396 | ar->wmi.cmd = &wmi_10x_cmd_map; | ||
4397 | |||
4398 | ar->wmi.vdev_param = &wmi_10x_vdev_param_map; | ||
4399 | ar->wmi.pdev_param = &wmi_10x_pdev_param_map; | ||
4400 | } else { | ||
4401 | ar->wmi.cmd = &wmi_cmd_map; | ||
4402 | ar->wmi.vdev_param = &wmi_vdev_param_map; | ||
4403 | ar->wmi.pdev_param = &wmi_pdev_param_map; | ||
4404 | } | ||
4405 | |||
4406 | init_completion(&ar->wmi.service_ready); | ||
4407 | init_completion(&ar->wmi.unified_ready); | ||
4408 | |||
4409 | return 0; | ||
4410 | } | ||
4411 | |||
4412 | void ath10k_wmi_detach(struct ath10k *ar) | ||
4413 | { | ||
4414 | int i; | ||
4415 | |||
4416 | /* free the host memory chunks requested by firmware */ | ||
4417 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | ||
4418 | dma_free_coherent(ar->dev, | ||
4419 | ar->wmi.mem_chunks[i].len, | ||
4420 | ar->wmi.mem_chunks[i].vaddr, | ||
4421 | ar->wmi.mem_chunks[i].paddr); | ||
4422 | } | ||
4423 | |||
4424 | ar->wmi.num_mem_chunks = 0; | ||
4425 | } | ||
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h index 86f5ebccfe79..a38d788a6101 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.h +++ b/drivers/net/wireless/ath/ath10k/wmi.h | |||
@@ -1428,11 +1428,11 @@ struct wmi_service_ready_event { | |||
1428 | * where FW can access this memory directly (or) by DMA. | 1428 | * where FW can access this memory directly (or) by DMA. |
1429 | */ | 1429 | */ |
1430 | __le32 num_mem_reqs; | 1430 | __le32 num_mem_reqs; |
1431 | struct wlan_host_mem_req mem_reqs[1]; | 1431 | struct wlan_host_mem_req mem_reqs[0]; |
1432 | } __packed; | 1432 | } __packed; |
1433 | 1433 | ||
1434 | /* This is the definition from 10.X firmware branch */ | 1434 | /* This is the definition from 10.X firmware branch */ |
1435 | struct wmi_service_ready_event_10x { | 1435 | struct wmi_10x_service_ready_event { |
1436 | __le32 sw_version; | 1436 | __le32 sw_version; |
1437 | __le32 abi_version; | 1437 | __le32 abi_version; |
1438 | 1438 | ||
@@ -1467,7 +1467,7 @@ struct wmi_service_ready_event_10x { | |||
1467 | */ | 1467 | */ |
1468 | __le32 num_mem_reqs; | 1468 | __le32 num_mem_reqs; |
1469 | 1469 | ||
1470 | struct wlan_host_mem_req mem_reqs[1]; | 1470 | struct wlan_host_mem_req mem_reqs[0]; |
1471 | } __packed; | 1471 | } __packed; |
1472 | 1472 | ||
1473 | #define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ) | 1473 | #define WMI_SERVICE_READY_TIMEOUT_HZ (5*HZ) |
@@ -1883,38 +1883,26 @@ struct host_memory_chunk { | |||
1883 | __le32 size; | 1883 | __le32 size; |
1884 | } __packed; | 1884 | } __packed; |
1885 | 1885 | ||
1886 | struct wmi_host_mem_chunks { | ||
1887 | __le32 count; | ||
1888 | /* some fw revisions require at least 1 chunk regardless of count */ | ||
1889 | struct host_memory_chunk items[1]; | ||
1890 | } __packed; | ||
1891 | |||
1886 | struct wmi_init_cmd { | 1892 | struct wmi_init_cmd { |
1887 | struct wmi_resource_config resource_config; | 1893 | struct wmi_resource_config resource_config; |
1888 | __le32 num_host_mem_chunks; | 1894 | struct wmi_host_mem_chunks mem_chunks; |
1889 | |||
1890 | /* | ||
1891 | * variable number of host memory chunks. | ||
1892 | * This should be the last element in the structure | ||
1893 | */ | ||
1894 | struct host_memory_chunk host_mem_chunks[1]; | ||
1895 | } __packed; | 1895 | } __packed; |
1896 | 1896 | ||
1897 | /* _10x stucture is from 10.X FW API */ | 1897 | /* _10x stucture is from 10.X FW API */ |
1898 | struct wmi_init_cmd_10x { | 1898 | struct wmi_init_cmd_10x { |
1899 | struct wmi_resource_config_10x resource_config; | 1899 | struct wmi_resource_config_10x resource_config; |
1900 | __le32 num_host_mem_chunks; | 1900 | struct wmi_host_mem_chunks mem_chunks; |
1901 | |||
1902 | /* | ||
1903 | * variable number of host memory chunks. | ||
1904 | * This should be the last element in the structure | ||
1905 | */ | ||
1906 | struct host_memory_chunk host_mem_chunks[1]; | ||
1907 | } __packed; | 1901 | } __packed; |
1908 | 1902 | ||
1909 | struct wmi_init_cmd_10_2 { | 1903 | struct wmi_init_cmd_10_2 { |
1910 | struct wmi_resource_config_10_2 resource_config; | 1904 | struct wmi_resource_config_10_2 resource_config; |
1911 | __le32 num_host_mem_chunks; | 1905 | struct wmi_host_mem_chunks mem_chunks; |
1912 | |||
1913 | /* | ||
1914 | * variable number of host memory chunks. | ||
1915 | * This should be the last element in the structure | ||
1916 | */ | ||
1917 | struct host_memory_chunk host_mem_chunks[1]; | ||
1918 | } __packed; | 1906 | } __packed; |
1919 | 1907 | ||
1920 | struct wmi_chan_list_entry { | 1908 | struct wmi_chan_list_entry { |
@@ -1974,7 +1962,7 @@ enum wmi_scan_priority { | |||
1974 | WMI_SCAN_PRIORITY_COUNT /* number of priorities supported */ | 1962 | WMI_SCAN_PRIORITY_COUNT /* number of priorities supported */ |
1975 | }; | 1963 | }; |
1976 | 1964 | ||
1977 | struct wmi_start_scan_cmd { | 1965 | struct wmi_start_scan_common { |
1978 | /* Scan ID */ | 1966 | /* Scan ID */ |
1979 | __le32 scan_id; | 1967 | __le32 scan_id; |
1980 | /* Scan requestor ID */ | 1968 | /* Scan requestor ID */ |
@@ -2032,95 +2020,25 @@ struct wmi_start_scan_cmd { | |||
2032 | __le32 probe_delay; | 2020 | __le32 probe_delay; |
2033 | /* Scan control flags */ | 2021 | /* Scan control flags */ |
2034 | __le32 scan_ctrl_flags; | 2022 | __le32 scan_ctrl_flags; |
2035 | |||
2036 | /* Burst duration time in msecs */ | ||
2037 | __le32 burst_duration; | ||
2038 | /* | ||
2039 | * TLV (tag length value ) paramerters follow the scan_cmd structure. | ||
2040 | * TLV can contain channel list, bssid list, ssid list and | ||
2041 | * ie. the TLV tags are defined above; | ||
2042 | */ | ||
2043 | } __packed; | 2023 | } __packed; |
2044 | 2024 | ||
2045 | /* This is the definition from 10.X firmware branch */ | 2025 | struct wmi_start_scan_tlvs { |
2046 | struct wmi_start_scan_cmd_10x { | 2026 | /* TLV parameters. These includes channel list, ssid list, bssid list, |
2047 | /* Scan ID */ | 2027 | * extra ies. |
2048 | __le32 scan_id; | ||
2049 | |||
2050 | /* Scan requestor ID */ | ||
2051 | __le32 scan_req_id; | ||
2052 | |||
2053 | /* VDEV id(interface) that is requesting scan */ | ||
2054 | __le32 vdev_id; | ||
2055 | |||
2056 | /* Scan Priority, input to scan scheduler */ | ||
2057 | __le32 scan_priority; | ||
2058 | |||
2059 | /* Scan events subscription */ | ||
2060 | __le32 notify_scan_events; | ||
2061 | |||
2062 | /* dwell time in msec on active channels */ | ||
2063 | __le32 dwell_time_active; | ||
2064 | |||
2065 | /* dwell time in msec on passive channels */ | ||
2066 | __le32 dwell_time_passive; | ||
2067 | |||
2068 | /* | ||
2069 | * min time in msec on the BSS channel,only valid if atleast one | ||
2070 | * VDEV is active | ||
2071 | */ | ||
2072 | __le32 min_rest_time; | ||
2073 | |||
2074 | /* | ||
2075 | * max rest time in msec on the BSS channel,only valid if at least | ||
2076 | * one VDEV is active | ||
2077 | */ | ||
2078 | /* | ||
2079 | * the scanner will rest on the bss channel at least min_rest_time | ||
2080 | * after min_rest_time the scanner will start checking for tx/rx | ||
2081 | * activity on all VDEVs. if there is no activity the scanner will | ||
2082 | * switch to off channel. if there is activity the scanner will let | ||
2083 | * the radio on the bss channel until max_rest_time expires.at | ||
2084 | * max_rest_time scanner will switch to off channel irrespective of | ||
2085 | * activity. activity is determined by the idle_time parameter. | ||
2086 | */ | ||
2087 | __le32 max_rest_time; | ||
2088 | |||
2089 | /* | ||
2090 | * time before sending next set of probe requests. | ||
2091 | * The scanner keeps repeating probe requests transmission with | ||
2092 | * period specified by repeat_probe_time. | ||
2093 | * The number of probe requests specified depends on the ssid_list | ||
2094 | * and bssid_list | ||
2095 | */ | ||
2096 | __le32 repeat_probe_time; | ||
2097 | |||
2098 | /* time in msec between 2 consequetive probe requests with in a set. */ | ||
2099 | __le32 probe_spacing_time; | ||
2100 | |||
2101 | /* | ||
2102 | * data inactivity time in msec on bss channel that will be used by | ||
2103 | * scanner for measuring the inactivity. | ||
2104 | */ | ||
2105 | __le32 idle_time; | ||
2106 | |||
2107 | /* maximum time in msec allowed for scan */ | ||
2108 | __le32 max_scan_time; | ||
2109 | |||
2110 | /* | ||
2111 | * delay in msec before sending first probe request after switching | ||
2112 | * to a channel | ||
2113 | */ | 2028 | */ |
2114 | __le32 probe_delay; | 2029 | u8 tlvs[0]; |
2030 | } __packed; | ||
2115 | 2031 | ||
2116 | /* Scan control flags */ | 2032 | struct wmi_start_scan_cmd { |
2117 | __le32 scan_ctrl_flags; | 2033 | struct wmi_start_scan_common common; |
2034 | __le32 burst_duration_ms; | ||
2035 | struct wmi_start_scan_tlvs tlvs; | ||
2036 | } __packed; | ||
2118 | 2037 | ||
2119 | /* | 2038 | /* This is the definition from 10.X firmware branch */ |
2120 | * TLV (tag length value ) paramerters follow the scan_cmd structure. | 2039 | struct wmi_10x_start_scan_cmd { |
2121 | * TLV can contain channel list, bssid list, ssid list and | 2040 | struct wmi_start_scan_common common; |
2122 | * ie. the TLV tags are defined above; | 2041 | struct wmi_start_scan_tlvs tlvs; |
2123 | */ | ||
2124 | } __packed; | 2042 | } __packed; |
2125 | 2043 | ||
2126 | struct wmi_ssid_arg { | 2044 | struct wmi_ssid_arg { |
@@ -2306,94 +2224,25 @@ struct wmi_mgmt_rx_event_v2 { | |||
2306 | #define PHY_ERROR_FALSE_RADAR_EXT 0x24 | 2224 | #define PHY_ERROR_FALSE_RADAR_EXT 0x24 |
2307 | #define PHY_ERROR_RADAR 0x05 | 2225 | #define PHY_ERROR_RADAR 0x05 |
2308 | 2226 | ||
2309 | struct wmi_single_phyerr_rx_hdr { | 2227 | struct wmi_phyerr { |
2310 | /* TSF timestamp */ | ||
2311 | __le32 tsf_timestamp; | 2228 | __le32 tsf_timestamp; |
2312 | |||
2313 | /* | ||
2314 | * Current freq1, freq2 | ||
2315 | * | ||
2316 | * [7:0]: freq1[lo] | ||
2317 | * [15:8] : freq1[hi] | ||
2318 | * [23:16]: freq2[lo] | ||
2319 | * [31:24]: freq2[hi] | ||
2320 | */ | ||
2321 | __le16 freq1; | 2229 | __le16 freq1; |
2322 | __le16 freq2; | 2230 | __le16 freq2; |
2323 | |||
2324 | /* | ||
2325 | * Combined RSSI over all chains and channel width for this PHY error | ||
2326 | * | ||
2327 | * [7:0]: RSSI combined | ||
2328 | * [15:8]: Channel width (MHz) | ||
2329 | * [23:16]: PHY error code | ||
2330 | * [24:16]: reserved (future use) | ||
2331 | */ | ||
2332 | u8 rssi_combined; | 2231 | u8 rssi_combined; |
2333 | u8 chan_width_mhz; | 2232 | u8 chan_width_mhz; |
2334 | u8 phy_err_code; | 2233 | u8 phy_err_code; |
2335 | u8 rsvd0; | 2234 | u8 rsvd0; |
2336 | 2235 | __le32 rssi_chains[4]; | |
2337 | /* | 2236 | __le16 nf_chains[4]; |
2338 | * RSSI on chain 0 through 3 | ||
2339 | * | ||
2340 | * This is formatted the same as the PPDU_START RX descriptor | ||
2341 | * field: | ||
2342 | * | ||
2343 | * [7:0]: pri20 | ||
2344 | * [15:8]: sec20 | ||
2345 | * [23:16]: sec40 | ||
2346 | * [31:24]: sec80 | ||
2347 | */ | ||
2348 | |||
2349 | __le32 rssi_chain0; | ||
2350 | __le32 rssi_chain1; | ||
2351 | __le32 rssi_chain2; | ||
2352 | __le32 rssi_chain3; | ||
2353 | |||
2354 | /* | ||
2355 | * Last calibrated NF value for chain 0 through 3 | ||
2356 | * | ||
2357 | * nf_list_1: | ||
2358 | * | ||
2359 | * + [15:0] - chain 0 | ||
2360 | * + [31:16] - chain 1 | ||
2361 | * | ||
2362 | * nf_list_2: | ||
2363 | * | ||
2364 | * + [15:0] - chain 2 | ||
2365 | * + [31:16] - chain 3 | ||
2366 | */ | ||
2367 | __le32 nf_list_1; | ||
2368 | __le32 nf_list_2; | ||
2369 | |||
2370 | /* Length of the frame */ | ||
2371 | __le32 buf_len; | 2237 | __le32 buf_len; |
2238 | u8 buf[0]; | ||
2372 | } __packed; | 2239 | } __packed; |
2373 | 2240 | ||
2374 | struct wmi_single_phyerr_rx_event { | 2241 | struct wmi_phyerr_event { |
2375 | /* Phy error event header */ | 2242 | __le32 num_phyerrs; |
2376 | struct wmi_single_phyerr_rx_hdr hdr; | ||
2377 | /* frame buffer */ | ||
2378 | u8 bufp[0]; | ||
2379 | } __packed; | ||
2380 | |||
2381 | struct wmi_comb_phyerr_rx_hdr { | ||
2382 | /* Phy error phy error count */ | ||
2383 | __le32 num_phyerr_events; | ||
2384 | __le32 tsf_l32; | 2243 | __le32 tsf_l32; |
2385 | __le32 tsf_u32; | 2244 | __le32 tsf_u32; |
2386 | } __packed; | 2245 | struct wmi_phyerr phyerrs[0]; |
2387 | |||
2388 | struct wmi_comb_phyerr_rx_event { | ||
2389 | /* Phy error phy error count */ | ||
2390 | struct wmi_comb_phyerr_rx_hdr hdr; | ||
2391 | /* | ||
2392 | * frame buffer - contains multiple payloads in the order: | ||
2393 | * header - payload, header - payload... | ||
2394 | * (The header is of type: wmi_single_phyerr_rx_hdr) | ||
2395 | */ | ||
2396 | u8 bufp[0]; | ||
2397 | } __packed; | 2246 | } __packed; |
2398 | 2247 | ||
2399 | #define PHYERR_TLV_SIG 0xBB | 2248 | #define PHYERR_TLV_SIG 0xBB |
@@ -2908,11 +2757,6 @@ enum wmi_tp_scale { | |||
2908 | WMI_TP_SCALE_SIZE = 5, /* max num of enum */ | 2757 | WMI_TP_SCALE_SIZE = 5, /* max num of enum */ |
2909 | }; | 2758 | }; |
2910 | 2759 | ||
2911 | struct wmi_set_channel_cmd { | ||
2912 | /* channel (only frequency and mode info are used) */ | ||
2913 | struct wmi_channel chan; | ||
2914 | } __packed; | ||
2915 | |||
2916 | struct wmi_pdev_chanlist_update_event { | 2760 | struct wmi_pdev_chanlist_update_event { |
2917 | /* number of channels */ | 2761 | /* number of channels */ |
2918 | __le32 num_chan; | 2762 | __le32 num_chan; |
@@ -2943,6 +2787,10 @@ struct wmi_pdev_set_channel_cmd { | |||
2943 | struct wmi_channel chan; | 2787 | struct wmi_channel chan; |
2944 | } __packed; | 2788 | } __packed; |
2945 | 2789 | ||
2790 | struct wmi_pdev_pktlog_enable_cmd { | ||
2791 | __le32 ev_bitmap; | ||
2792 | } __packed; | ||
2793 | |||
2946 | /* Customize the DSCP (bit) to TID (0-7) mapping for QOS */ | 2794 | /* Customize the DSCP (bit) to TID (0-7) mapping for QOS */ |
2947 | #define WMI_DSCP_MAP_MAX (64) | 2795 | #define WMI_DSCP_MAP_MAX (64) |
2948 | struct wmi_pdev_set_dscp_tid_map_cmd { | 2796 | struct wmi_pdev_set_dscp_tid_map_cmd { |
@@ -3177,7 +3025,7 @@ struct wmi_stats_event { | |||
3177 | * PDEV statistics | 3025 | * PDEV statistics |
3178 | * TODO: add all PDEV stats here | 3026 | * TODO: add all PDEV stats here |
3179 | */ | 3027 | */ |
3180 | struct wmi_pdev_stats_old { | 3028 | struct wmi_pdev_stats { |
3181 | __le32 chan_nf; /* Channel noise floor */ | 3029 | __le32 chan_nf; /* Channel noise floor */ |
3182 | __le32 tx_frame_count; /* TX frame count */ | 3030 | __le32 tx_frame_count; /* TX frame count */ |
3183 | __le32 rx_frame_count; /* RX frame count */ | 3031 | __le32 rx_frame_count; /* RX frame count */ |
@@ -3188,15 +3036,8 @@ struct wmi_pdev_stats_old { | |||
3188 | struct wal_dbg_stats wal; /* WAL dbg stats */ | 3036 | struct wal_dbg_stats wal; /* WAL dbg stats */ |
3189 | } __packed; | 3037 | } __packed; |
3190 | 3038 | ||
3191 | struct wmi_pdev_stats_10x { | 3039 | struct wmi_10x_pdev_stats { |
3192 | __le32 chan_nf; /* Channel noise floor */ | 3040 | struct wmi_pdev_stats old; |
3193 | __le32 tx_frame_count; /* TX frame count */ | ||
3194 | __le32 rx_frame_count; /* RX frame count */ | ||
3195 | __le32 rx_clear_count; /* rx clear count */ | ||
3196 | __le32 cycle_count; /* cycle count */ | ||
3197 | __le32 phy_err_count; /* Phy error count */ | ||
3198 | __le32 chan_tx_pwr; /* channel tx power */ | ||
3199 | struct wal_dbg_stats wal; /* WAL dbg stats */ | ||
3200 | __le32 ack_rx_bad; | 3041 | __le32 ack_rx_bad; |
3201 | __le32 rts_bad; | 3042 | __le32 rts_bad; |
3202 | __le32 rts_good; | 3043 | __le32 rts_good; |
@@ -3217,16 +3058,14 @@ struct wmi_vdev_stats { | |||
3217 | * peer statistics. | 3058 | * peer statistics. |
3218 | * TODO: add more stats | 3059 | * TODO: add more stats |
3219 | */ | 3060 | */ |
3220 | struct wmi_peer_stats_old { | 3061 | struct wmi_peer_stats { |
3221 | struct wmi_mac_addr peer_macaddr; | 3062 | struct wmi_mac_addr peer_macaddr; |
3222 | __le32 peer_rssi; | 3063 | __le32 peer_rssi; |
3223 | __le32 peer_tx_rate; | 3064 | __le32 peer_tx_rate; |
3224 | } __packed; | 3065 | } __packed; |
3225 | 3066 | ||
3226 | struct wmi_peer_stats_10x { | 3067 | struct wmi_10x_peer_stats { |
3227 | struct wmi_mac_addr peer_macaddr; | 3068 | struct wmi_peer_stats old; |
3228 | __le32 peer_rssi; | ||
3229 | __le32 peer_tx_rate; | ||
3230 | __le32 peer_rx_rate; | 3069 | __le32 peer_rx_rate; |
3231 | } __packed; | 3070 | } __packed; |
3232 | 3071 | ||
@@ -4719,8 +4558,26 @@ struct wmi_dbglog_cfg_cmd { | |||
4719 | /* By default disable power save for IBSS */ | 4558 | /* By default disable power save for IBSS */ |
4720 | #define ATH10K_DEFAULT_ATIM 0 | 4559 | #define ATH10K_DEFAULT_ATIM 0 |
4721 | 4560 | ||
4561 | #define WMI_MAX_MEM_REQS 16 | ||
4562 | |||
4563 | struct wmi_svc_rdy_ev_arg { | ||
4564 | __le32 min_tx_power; | ||
4565 | __le32 max_tx_power; | ||
4566 | __le32 ht_cap; | ||
4567 | __le32 vht_cap; | ||
4568 | __le32 sw_ver0; | ||
4569 | __le32 sw_ver1; | ||
4570 | __le32 phy_capab; | ||
4571 | __le32 num_rf_chains; | ||
4572 | __le32 eeprom_rd; | ||
4573 | __le32 num_mem_reqs; | ||
4574 | const __le32 *service_map; | ||
4575 | const struct wlan_host_mem_req *mem_reqs[WMI_MAX_MEM_REQS]; | ||
4576 | }; | ||
4577 | |||
4722 | struct ath10k; | 4578 | struct ath10k; |
4723 | struct ath10k_vif; | 4579 | struct ath10k_vif; |
4580 | struct ath10k_fw_stats; | ||
4724 | 4581 | ||
4725 | int ath10k_wmi_attach(struct ath10k *ar); | 4582 | int ath10k_wmi_attach(struct ath10k *ar); |
4726 | void ath10k_wmi_detach(struct ath10k *ar); | 4583 | void ath10k_wmi_detach(struct ath10k *ar); |
@@ -4732,8 +4589,6 @@ int ath10k_wmi_connect(struct ath10k *ar); | |||
4732 | struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len); | 4589 | struct sk_buff *ath10k_wmi_alloc_skb(struct ath10k *ar, u32 len); |
4733 | int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); | 4590 | int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id); |
4734 | 4591 | ||
4735 | int ath10k_wmi_pdev_set_channel(struct ath10k *ar, | ||
4736 | const struct wmi_channel_arg *); | ||
4737 | int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt); | 4592 | int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt); |
4738 | int ath10k_wmi_pdev_resume_target(struct ath10k *ar); | 4593 | int ath10k_wmi_pdev_resume_target(struct ath10k *ar); |
4739 | int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, | 4594 | int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, |
@@ -4794,5 +4649,9 @@ int ath10k_wmi_force_fw_hang(struct ath10k *ar, | |||
4794 | enum wmi_force_fw_hang_type type, u32 delay_ms); | 4649 | enum wmi_force_fw_hang_type type, u32 delay_ms); |
4795 | int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb); | 4650 | int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb); |
4796 | int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable); | 4651 | int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable); |
4652 | int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb, | ||
4653 | struct ath10k_fw_stats *stats); | ||
4654 | int ath10k_wmi_pdev_pktlog_enable(struct ath10k *ar, u32 ev_list); | ||
4655 | int ath10k_wmi_pdev_pktlog_disable(struct ath10k *ar); | ||
4797 | 4656 | ||
4798 | #endif /* _WMI_H_ */ | 4657 | #endif /* _WMI_H_ */ |
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c index ab2709a43768..19eab2a69ad5 100644 --- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c +++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c | |||
@@ -547,7 +547,9 @@ ath5k_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
547 | 547 | ||
548 | 548 | ||
549 | static void | 549 | static void |
550 | ath5k_sw_scan_start(struct ieee80211_hw *hw) | 550 | ath5k_sw_scan_start(struct ieee80211_hw *hw, |
551 | struct ieee80211_vif *vif, | ||
552 | const u8 *mac_addr) | ||
551 | { | 553 | { |
552 | struct ath5k_hw *ah = hw->priv; | 554 | struct ath5k_hw *ah = hw->priv; |
553 | if (!ah->assoc) | 555 | if (!ah->assoc) |
@@ -556,7 +558,7 @@ ath5k_sw_scan_start(struct ieee80211_hw *hw) | |||
556 | 558 | ||
557 | 559 | ||
558 | static void | 560 | static void |
559 | ath5k_sw_scan_complete(struct ieee80211_hw *hw) | 561 | ath5k_sw_scan_complete(struct ieee80211_hw *hw, struct ieee80211_vif *vif) |
560 | { | 562 | { |
561 | struct ath5k_hw *ah = hw->priv; | 563 | struct ath5k_hw *ah = hw->priv; |
562 | ath5k_hw_set_ledstate(ah, ah->assoc ? | 564 | ath5k_hw_set_ledstate(ah, ah->assoc ? |
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index ba60e37213eb..7a5337877a0c 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c | |||
@@ -2976,11 +2976,11 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev) | |||
2976 | static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; | 2976 | static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
2977 | 2977 | ||
2978 | static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev, | 2978 | static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev, |
2979 | const u8 *mac) | 2979 | struct station_del_parameters *params) |
2980 | { | 2980 | { |
2981 | struct ath6kl *ar = ath6kl_priv(dev); | 2981 | struct ath6kl *ar = ath6kl_priv(dev); |
2982 | struct ath6kl_vif *vif = netdev_priv(dev); | 2982 | struct ath6kl_vif *vif = netdev_priv(dev); |
2983 | const u8 *addr = mac ? mac : bcast_addr; | 2983 | const u8 *addr = params->mac ? params->mac : bcast_addr; |
2984 | 2984 | ||
2985 | return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, WMI_AP_DEAUTH, | 2985 | return ath6kl_wmi_ap_set_mlme(ar->wmi, vif->fw_vif_idx, WMI_AP_DEAUTH, |
2986 | addr, WLAN_REASON_PREV_AUTH_NOT_VALID); | 2986 | addr, WLAN_REASON_PREV_AUTH_NOT_VALID); |
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h index 05debf700a84..4f82e8632d37 100644 --- a/drivers/net/wireless/ath/ath6kl/common.h +++ b/drivers/net/wireless/ath/ath6kl/common.h | |||
@@ -22,7 +22,7 @@ | |||
22 | 22 | ||
23 | #define ATH6KL_MAX_IE 256 | 23 | #define ATH6KL_MAX_IE 256 |
24 | 24 | ||
25 | __printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...); | 25 | __printf(2, 3) void ath6kl_printk(const char *level, const char *fmt, ...); |
26 | 26 | ||
27 | /* | 27 | /* |
28 | * Reflects the version of binary interface exposed by ATH6KL target | 28 | * Reflects the version of binary interface exposed by ATH6KL target |
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c index 55c4064dd506..81ba48d2938b 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.c +++ b/drivers/net/wireless/ath/ath6kl/debug.c | |||
@@ -37,76 +37,64 @@ struct ath6kl_fwlog_slot { | |||
37 | 37 | ||
38 | #define ATH6KL_FWLOG_VALID_MASK 0x1ffff | 38 | #define ATH6KL_FWLOG_VALID_MASK 0x1ffff |
39 | 39 | ||
40 | int ath6kl_printk(const char *level, const char *fmt, ...) | 40 | void ath6kl_printk(const char *level, const char *fmt, ...) |
41 | { | 41 | { |
42 | struct va_format vaf; | 42 | struct va_format vaf; |
43 | va_list args; | 43 | va_list args; |
44 | int rtn; | ||
45 | 44 | ||
46 | va_start(args, fmt); | 45 | va_start(args, fmt); |
47 | 46 | ||
48 | vaf.fmt = fmt; | 47 | vaf.fmt = fmt; |
49 | vaf.va = &args; | 48 | vaf.va = &args; |
50 | 49 | ||
51 | rtn = printk("%sath6kl: %pV", level, &vaf); | 50 | printk("%sath6kl: %pV", level, &vaf); |
52 | 51 | ||
53 | va_end(args); | 52 | va_end(args); |
54 | |||
55 | return rtn; | ||
56 | } | 53 | } |
57 | EXPORT_SYMBOL(ath6kl_printk); | 54 | EXPORT_SYMBOL(ath6kl_printk); |
58 | 55 | ||
59 | int ath6kl_info(const char *fmt, ...) | 56 | void ath6kl_info(const char *fmt, ...) |
60 | { | 57 | { |
61 | struct va_format vaf = { | 58 | struct va_format vaf = { |
62 | .fmt = fmt, | 59 | .fmt = fmt, |
63 | }; | 60 | }; |
64 | va_list args; | 61 | va_list args; |
65 | int ret; | ||
66 | 62 | ||
67 | va_start(args, fmt); | 63 | va_start(args, fmt); |
68 | vaf.va = &args; | 64 | vaf.va = &args; |
69 | ret = ath6kl_printk(KERN_INFO, "%pV", &vaf); | 65 | ath6kl_printk(KERN_INFO, "%pV", &vaf); |
70 | trace_ath6kl_log_info(&vaf); | 66 | trace_ath6kl_log_info(&vaf); |
71 | va_end(args); | 67 | va_end(args); |
72 | |||
73 | return ret; | ||
74 | } | 68 | } |
75 | EXPORT_SYMBOL(ath6kl_info); | 69 | EXPORT_SYMBOL(ath6kl_info); |
76 | 70 | ||
77 | int ath6kl_err(const char *fmt, ...) | 71 | void ath6kl_err(const char *fmt, ...) |
78 | { | 72 | { |
79 | struct va_format vaf = { | 73 | struct va_format vaf = { |
80 | .fmt = fmt, | 74 | .fmt = fmt, |
81 | }; | 75 | }; |
82 | va_list args; | 76 | va_list args; |
83 | int ret; | ||
84 | 77 | ||
85 | va_start(args, fmt); | 78 | va_start(args, fmt); |
86 | vaf.va = &args; | 79 | vaf.va = &args; |
87 | ret = ath6kl_printk(KERN_ERR, "%pV", &vaf); | 80 | ath6kl_printk(KERN_ERR, "%pV", &vaf); |
88 | trace_ath6kl_log_err(&vaf); | 81 | trace_ath6kl_log_err(&vaf); |
89 | va_end(args); | 82 | va_end(args); |
90 | |||
91 | return ret; | ||
92 | } | 83 | } |
93 | EXPORT_SYMBOL(ath6kl_err); | 84 | EXPORT_SYMBOL(ath6kl_err); |
94 | 85 | ||
95 | int ath6kl_warn(const char *fmt, ...) | 86 | void ath6kl_warn(const char *fmt, ...) |
96 | { | 87 | { |
97 | struct va_format vaf = { | 88 | struct va_format vaf = { |
98 | .fmt = fmt, | 89 | .fmt = fmt, |
99 | }; | 90 | }; |
100 | va_list args; | 91 | va_list args; |
101 | int ret; | ||
102 | 92 | ||
103 | va_start(args, fmt); | 93 | va_start(args, fmt); |
104 | vaf.va = &args; | 94 | vaf.va = &args; |
105 | ret = ath6kl_printk(KERN_WARNING, "%pV", &vaf); | 95 | ath6kl_printk(KERN_WARNING, "%pV", &vaf); |
106 | trace_ath6kl_log_warn(&vaf); | 96 | trace_ath6kl_log_warn(&vaf); |
107 | va_end(args); | 97 | va_end(args); |
108 | |||
109 | return ret; | ||
110 | } | 98 | } |
111 | EXPORT_SYMBOL(ath6kl_warn); | 99 | EXPORT_SYMBOL(ath6kl_warn); |
112 | 100 | ||
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h index e194c10d9f00..19106ed28961 100644 --- a/drivers/net/wireless/ath/ath6kl/debug.h +++ b/drivers/net/wireless/ath/ath6kl/debug.h | |||
@@ -50,10 +50,10 @@ enum ATH6K_DEBUG_MASK { | |||
50 | }; | 50 | }; |
51 | 51 | ||
52 | extern unsigned int debug_mask; | 52 | extern unsigned int debug_mask; |
53 | __printf(2, 3) int ath6kl_printk(const char *level, const char *fmt, ...); | 53 | __printf(2, 3) void ath6kl_printk(const char *level, const char *fmt, ...); |
54 | __printf(1, 2) int ath6kl_info(const char *fmt, ...); | 54 | __printf(1, 2) void ath6kl_info(const char *fmt, ...); |
55 | __printf(1, 2) int ath6kl_err(const char *fmt, ...); | 55 | __printf(1, 2) void ath6kl_err(const char *fmt, ...); |
56 | __printf(1, 2) int ath6kl_warn(const char *fmt, ...); | 56 | __printf(1, 2) void ath6kl_warn(const char *fmt, ...); |
57 | 57 | ||
58 | enum ath6kl_war { | 58 | enum ath6kl_war { |
59 | ATH6KL_WAR_INVALID_RATE, | 59 | ATH6KL_WAR_INVALID_RATE, |
@@ -81,10 +81,9 @@ int ath6kl_debug_init_fs(struct ath6kl *ar); | |||
81 | void ath6kl_debug_cleanup(struct ath6kl *ar); | 81 | void ath6kl_debug_cleanup(struct ath6kl *ar); |
82 | 82 | ||
83 | #else | 83 | #else |
84 | static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask, | 84 | static inline void ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask, |
85 | const char *fmt, ...) | 85 | const char *fmt, ...) |
86 | { | 86 | { |
87 | return 0; | ||
88 | } | 87 | } |
89 | 88 | ||
90 | static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, | 89 | static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask, |
diff --git a/drivers/net/wireless/ath/ath6kl/usb.c b/drivers/net/wireless/ath/ath6kl/usb.c index a6a5e40b3e98..9da3594fd010 100644 --- a/drivers/net/wireless/ath/ath6kl/usb.c +++ b/drivers/net/wireless/ath/ath6kl/usb.c | |||
@@ -1193,18 +1193,10 @@ static int ath6kl_usb_pm_resume(struct usb_interface *interface) | |||
1193 | return 0; | 1193 | return 0; |
1194 | } | 1194 | } |
1195 | 1195 | ||
1196 | static int ath6kl_usb_pm_reset_resume(struct usb_interface *intf) | ||
1197 | { | ||
1198 | if (usb_get_intfdata(intf)) | ||
1199 | ath6kl_usb_remove(intf); | ||
1200 | return 0; | ||
1201 | } | ||
1202 | |||
1203 | #else | 1196 | #else |
1204 | 1197 | ||
1205 | #define ath6kl_usb_pm_suspend NULL | 1198 | #define ath6kl_usb_pm_suspend NULL |
1206 | #define ath6kl_usb_pm_resume NULL | 1199 | #define ath6kl_usb_pm_resume NULL |
1207 | #define ath6kl_usb_pm_reset_resume NULL | ||
1208 | 1200 | ||
1209 | #endif | 1201 | #endif |
1210 | 1202 | ||
@@ -1222,7 +1214,6 @@ static struct usb_driver ath6kl_usb_driver = { | |||
1222 | .probe = ath6kl_usb_probe, | 1214 | .probe = ath6kl_usb_probe, |
1223 | .suspend = ath6kl_usb_pm_suspend, | 1215 | .suspend = ath6kl_usb_pm_suspend, |
1224 | .resume = ath6kl_usb_pm_resume, | 1216 | .resume = ath6kl_usb_pm_resume, |
1225 | .reset_resume = ath6kl_usb_pm_reset_resume, | ||
1226 | .disconnect = ath6kl_usb_remove, | 1217 | .disconnect = ath6kl_usb_remove, |
1227 | .id_table = ath6kl_usb_ids, | 1218 | .id_table = ath6kl_usb_ids, |
1228 | .supports_autosuspend = true, | 1219 | .supports_autosuspend = true, |
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 896e63281b3b..fee0cadb0f5e 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -3,6 +3,8 @@ config ATH9K_HW | |||
3 | config ATH9K_COMMON | 3 | config ATH9K_COMMON |
4 | tristate | 4 | tristate |
5 | select ATH_COMMON | 5 | select ATH_COMMON |
6 | select DEBUG_FS | ||
7 | select RELAY | ||
6 | config ATH9K_DFS_DEBUGFS | 8 | config ATH9K_DFS_DEBUGFS |
7 | def_bool y | 9 | def_bool y |
8 | depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED | 10 | depends on ATH9K_DEBUGFS && ATH9K_DFS_CERTIFIED |
@@ -148,6 +150,11 @@ config ATH9K_CHANNEL_CONTEXT | |||
148 | for multi-channel concurrency. Enable this if P2P PowerSave support | 150 | for multi-channel concurrency. Enable this if P2P PowerSave support |
149 | is required. | 151 | is required. |
150 | 152 | ||
153 | config ATH9K_PCOEM | ||
154 | bool "Atheros ath9k support for PC OEM cards" if EXPERT | ||
155 | depends on ATH9K | ||
156 | default y | ||
157 | |||
151 | config ATH9K_HTC | 158 | config ATH9K_HTC |
152 | tristate "Atheros HTC based wireless cards support" | 159 | tristate "Atheros HTC based wireless cards support" |
153 | depends on USB && MAC80211 | 160 | depends on USB && MAC80211 |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 73704c1be736..473972288a84 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -16,8 +16,7 @@ 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 | 18 | ||
19 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o \ | 19 | ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o |
20 | spectral.o | ||
21 | 20 | ||
22 | ath9k-$(CONFIG_ATH9K_STATION_STATISTICS) += debug_sta.o | 21 | ath9k-$(CONFIG_ATH9K_STATION_STATISTICS) += debug_sta.o |
23 | 22 | ||
@@ -32,7 +31,6 @@ ath9k_hw-y:= \ | |||
32 | ar5008_phy.o \ | 31 | ar5008_phy.o \ |
33 | ar9002_calib.o \ | 32 | ar9002_calib.o \ |
34 | ar9003_calib.o \ | 33 | ar9003_calib.o \ |
35 | ar9003_rtt.o \ | ||
36 | calib.o \ | 34 | calib.o \ |
37 | eeprom.o \ | 35 | eeprom.o \ |
38 | eeprom_def.o \ | 36 | eeprom_def.o \ |
@@ -50,6 +48,8 @@ ath9k_hw-$(CONFIG_ATH9K_WOW) += ar9003_wow.o | |||
50 | ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \ | 48 | ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \ |
51 | ar9003_mci.o | 49 | ar9003_mci.o |
52 | 50 | ||
51 | ath9k_hw-$(CONFIG_ATH9K_PCOEM) += ar9003_rtt.o | ||
52 | |||
53 | ath9k_hw-$(CONFIG_ATH9K_DYNACK) += dynack.o | 53 | ath9k_hw-$(CONFIG_ATH9K_DYNACK) += dynack.o |
54 | 54 | ||
55 | obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o | 55 | obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o |
@@ -58,7 +58,8 @@ obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o | |||
58 | ath9k_common-y:= common.o \ | 58 | ath9k_common-y:= common.o \ |
59 | common-init.o \ | 59 | common-init.o \ |
60 | common-beacon.o \ | 60 | common-beacon.o \ |
61 | common-debug.o | 61 | common-debug.o \ |
62 | common-spectral.o | ||
62 | 63 | ||
63 | ath9k_htc-y += htc_hst.o \ | 64 | ath9k_htc-y += htc_hst.o \ |
64 | hif_usb.o \ | 65 | hif_usb.o \ |
diff --git a/drivers/net/wireless/ath/ath9k/ar5008_phy.c b/drivers/net/wireless/ath/ath9k/ar5008_phy.c index b72d0be716db..5829074208fa 100644 --- a/drivers/net/wireless/ath/ath9k/ar5008_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar5008_phy.c | |||
@@ -1190,7 +1190,7 @@ static void ar5008_hw_set_nf_limits(struct ath_hw *ah) | |||
1190 | static void ar5008_hw_set_radar_params(struct ath_hw *ah, | 1190 | static void ar5008_hw_set_radar_params(struct ath_hw *ah, |
1191 | struct ath_hw_radar_conf *conf) | 1191 | struct ath_hw_radar_conf *conf) |
1192 | { | 1192 | { |
1193 | u32 radar_0 = 0, radar_1 = 0; | 1193 | u32 radar_0 = 0, radar_1; |
1194 | 1194 | ||
1195 | if (!conf) { | 1195 | if (!conf) { |
1196 | REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); | 1196 | REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); |
@@ -1204,6 +1204,9 @@ static void ar5008_hw_set_radar_params(struct ath_hw *ah, | |||
1204 | radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI); | 1204 | radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI); |
1205 | radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND); | 1205 | radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND); |
1206 | 1206 | ||
1207 | radar_1 = REG_READ(ah, AR_PHY_RADAR_1); | ||
1208 | radar_1 &= ~(AR_PHY_RADAR_1_MAXLEN | AR_PHY_RADAR_1_RELSTEP_THRESH | | ||
1209 | AR_PHY_RADAR_1_RELPWR_THRESH); | ||
1207 | radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI; | 1210 | radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI; |
1208 | radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK; | 1211 | radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK; |
1209 | radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN); | 1212 | radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN); |
@@ -1225,7 +1228,7 @@ static void ar5008_hw_set_radar_conf(struct ath_hw *ah) | |||
1225 | conf->fir_power = -33; | 1228 | conf->fir_power = -33; |
1226 | conf->radar_rssi = 20; | 1229 | conf->radar_rssi = 20; |
1227 | conf->pulse_height = 10; | 1230 | conf->pulse_height = 10; |
1228 | conf->pulse_rssi = 24; | 1231 | conf->pulse_rssi = 15; |
1229 | conf->pulse_inband = 15; | 1232 | conf->pulse_inband = 15; |
1230 | conf->pulse_maxlen = 255; | 1233 | conf->pulse_maxlen = 255; |
1231 | conf->pulse_inband_step = 12; | 1234 | conf->pulse_inband_step = 12; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_calib.c b/drivers/net/wireless/ath/ath9k/ar9002_calib.c index cdc74005650c..42190b67c671 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_calib.c | |||
@@ -657,31 +657,29 @@ static void ar9002_hw_olc_temp_compensation(struct ath_hw *ah) | |||
657 | ar9280_hw_olc_temp_compensation(ah); | 657 | ar9280_hw_olc_temp_compensation(ah); |
658 | } | 658 | } |
659 | 659 | ||
660 | static bool ar9002_hw_calibrate(struct ath_hw *ah, | 660 | static int ar9002_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, |
661 | struct ath9k_channel *chan, | 661 | u8 rxchainmask, bool longcal) |
662 | u8 rxchainmask, | ||
663 | bool longcal) | ||
664 | { | 662 | { |
665 | bool iscaldone = true; | ||
666 | struct ath9k_cal_list *currCal = ah->cal_list_curr; | 663 | struct ath9k_cal_list *currCal = ah->cal_list_curr; |
667 | bool nfcal, nfcal_pending = false; | 664 | bool nfcal, nfcal_pending = false, percal_pending; |
665 | int ret; | ||
668 | 666 | ||
669 | nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF); | 667 | nfcal = !!(REG_READ(ah, AR_PHY_AGC_CONTROL) & AR_PHY_AGC_CONTROL_NF); |
670 | if (ah->caldata) | 668 | if (ah->caldata) |
671 | nfcal_pending = test_bit(NFCAL_PENDING, &ah->caldata->cal_flags); | 669 | nfcal_pending = test_bit(NFCAL_PENDING, &ah->caldata->cal_flags); |
672 | 670 | ||
673 | if (currCal && !nfcal && | 671 | percal_pending = (currCal && |
674 | (currCal->calState == CAL_RUNNING || | 672 | (currCal->calState == CAL_RUNNING || |
675 | currCal->calState == CAL_WAITING)) { | 673 | currCal->calState == CAL_WAITING)); |
676 | iscaldone = ar9002_hw_per_calibration(ah, chan, | 674 | |
677 | rxchainmask, currCal); | 675 | if (percal_pending && !nfcal) { |
678 | if (iscaldone) { | 676 | if (!ar9002_hw_per_calibration(ah, chan, rxchainmask, currCal)) |
679 | ah->cal_list_curr = currCal = currCal->calNext; | 677 | return 0; |
680 | 678 | ||
681 | if (currCal->calState == CAL_WAITING) { | 679 | ah->cal_list_curr = currCal = currCal->calNext; |
682 | iscaldone = false; | 680 | if (currCal->calState == CAL_WAITING) { |
683 | ath9k_hw_reset_calibration(ah, currCal); | 681 | ath9k_hw_reset_calibration(ah, currCal); |
684 | } | 682 | return 0; |
685 | } | 683 | } |
686 | } | 684 | } |
687 | 685 | ||
@@ -698,7 +696,9 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, | |||
698 | * NF is slow time-variant, so it is OK to use a | 696 | * NF is slow time-variant, so it is OK to use a |
699 | * historical value. | 697 | * historical value. |
700 | */ | 698 | */ |
701 | ath9k_hw_loadnf(ah, ah->curchan); | 699 | ret = ath9k_hw_loadnf(ah, ah->curchan); |
700 | if (ret < 0) | ||
701 | return ret; | ||
702 | } | 702 | } |
703 | 703 | ||
704 | if (longcal) { | 704 | if (longcal) { |
@@ -709,7 +709,7 @@ static bool ar9002_hw_calibrate(struct ath_hw *ah, | |||
709 | } | 709 | } |
710 | } | 710 | } |
711 | 711 | ||
712 | return iscaldone; | 712 | return !percal_pending; |
713 | } | 713 | } |
714 | 714 | ||
715 | /* Carrier leakage Calibration fix */ | 715 | /* Carrier leakage Calibration fix */ |
@@ -856,6 +856,8 @@ static bool ar9002_hw_init_cal(struct ath_hw *ah, struct ath9k_channel *chan) | |||
856 | 856 | ||
857 | /* Do PA Calibration */ | 857 | /* Do PA Calibration */ |
858 | ar9002_hw_pa_cal(ah, true); | 858 | ar9002_hw_pa_cal(ah, true); |
859 | ath9k_hw_loadnf(ah, chan); | ||
860 | ath9k_hw_start_nfcal(ah, true); | ||
859 | 861 | ||
860 | if (ah->caldata) | 862 | if (ah->caldata) |
861 | set_bit(NFCAL_PENDING, &ah->caldata->cal_flags); | 863 | set_bit(NFCAL_PENDING, &ah->caldata->cal_flags); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9002_phy.c b/drivers/net/wireless/ath/ath9k/ar9002_phy.c index 9a2afa2c690b..fc08162b5820 100644 --- a/drivers/net/wireless/ath/ath9k/ar9002_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9002_phy.c | |||
@@ -643,9 +643,12 @@ static void ar9002_hw_spectral_scan_config(struct ath_hw *ah, | |||
643 | * and fix otherwise. | 643 | * and fix otherwise. |
644 | */ | 644 | */ |
645 | count = param->count; | 645 | count = param->count; |
646 | if (param->endless) | 646 | if (param->endless) { |
647 | count = 0x80; | 647 | if (AR_SREV_9271(ah)) |
648 | else if (count & 0x80) | 648 | count = 0; |
649 | else | ||
650 | count = 0x80; | ||
651 | } else if (count & 0x80) | ||
649 | count = 0x7f; | 652 | count = 0x7f; |
650 | 653 | ||
651 | REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, | 654 | REG_RMW_FIELD(ah, AR_PHY_SPECTRAL_SCAN, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_calib.c b/drivers/net/wireless/ath/ath9k/ar9003_calib.c index ac8301ef5242..06ab71db6e80 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_calib.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_calib.c | |||
@@ -121,13 +121,12 @@ static bool ar9003_hw_per_calibration(struct ath_hw *ah, | |||
121 | return iscaldone; | 121 | return iscaldone; |
122 | } | 122 | } |
123 | 123 | ||
124 | static bool ar9003_hw_calibrate(struct ath_hw *ah, | 124 | static int ar9003_hw_calibrate(struct ath_hw *ah, struct ath9k_channel *chan, |
125 | struct ath9k_channel *chan, | 125 | u8 rxchainmask, bool longcal) |
126 | u8 rxchainmask, | ||
127 | bool longcal) | ||
128 | { | 126 | { |
129 | bool iscaldone = true; | 127 | bool iscaldone = true; |
130 | struct ath9k_cal_list *currCal = ah->cal_list_curr; | 128 | struct ath9k_cal_list *currCal = ah->cal_list_curr; |
129 | int ret; | ||
131 | 130 | ||
132 | /* | 131 | /* |
133 | * For given calibration: | 132 | * For given calibration: |
@@ -163,7 +162,9 @@ static bool ar9003_hw_calibrate(struct ath_hw *ah, | |||
163 | * NF is slow time-variant, so it is OK to use a historical | 162 | * NF is slow time-variant, so it is OK to use a historical |
164 | * value. | 163 | * value. |
165 | */ | 164 | */ |
166 | ath9k_hw_loadnf(ah, ah->curchan); | 165 | ret = ath9k_hw_loadnf(ah, ah->curchan); |
166 | if (ret < 0) | ||
167 | return ret; | ||
167 | 168 | ||
168 | /* start NF calibration, without updating BB NF register */ | 169 | /* start NF calibration, without updating BB NF register */ |
169 | ath9k_hw_start_nfcal(ah, false); | 170 | ath9k_hw_start_nfcal(ah, false); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c index 80c6eacbda53..e726e405152c 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c | |||
@@ -4079,27 +4079,28 @@ static int ar9003_hw_get_thermometer(struct ath_hw *ah) | |||
4079 | 4079 | ||
4080 | static void ar9003_hw_thermometer_apply(struct ath_hw *ah) | 4080 | static void ar9003_hw_thermometer_apply(struct ath_hw *ah) |
4081 | { | 4081 | { |
4082 | struct ath9k_hw_capabilities *pCap = &ah->caps; | ||
4082 | int thermometer = ar9003_hw_get_thermometer(ah); | 4083 | int thermometer = ar9003_hw_get_thermometer(ah); |
4083 | u8 therm_on = (thermometer < 0) ? 0 : 1; | 4084 | u8 therm_on = (thermometer < 0) ? 0 : 1; |
4084 | 4085 | ||
4085 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4, | 4086 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4, |
4086 | AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on); | 4087 | AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on); |
4087 | if (ah->caps.tx_chainmask & BIT(1)) | 4088 | if (pCap->chip_chainmask & BIT(1)) |
4088 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4, | 4089 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4, |
4089 | AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on); | 4090 | AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on); |
4090 | if (ah->caps.tx_chainmask & BIT(2)) | 4091 | if (pCap->chip_chainmask & BIT(2)) |
4091 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, | 4092 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, |
4092 | AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on); | 4093 | AR_PHY_65NM_CH0_RXTX4_THERM_ON_OVR, therm_on); |
4093 | 4094 | ||
4094 | therm_on = (thermometer < 0) ? 0 : (thermometer == 0); | 4095 | therm_on = (thermometer < 0) ? 0 : (thermometer == 0); |
4095 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4, | 4096 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_RXTX4, |
4096 | AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); | 4097 | AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); |
4097 | if (ah->caps.tx_chainmask & BIT(1)) { | 4098 | if (pCap->chip_chainmask & BIT(1)) { |
4098 | therm_on = (thermometer < 0) ? 0 : (thermometer == 1); | 4099 | therm_on = (thermometer < 0) ? 0 : (thermometer == 1); |
4099 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4, | 4100 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH1_RXTX4, |
4100 | AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); | 4101 | AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); |
4101 | } | 4102 | } |
4102 | if (ah->caps.tx_chainmask & BIT(2)) { | 4103 | if (pCap->chip_chainmask & BIT(2)) { |
4103 | therm_on = (thermometer < 0) ? 0 : (thermometer == 2); | 4104 | therm_on = (thermometer < 0) ? 0 : (thermometer == 2); |
4104 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, | 4105 | REG_RMW_FIELD(ah, AR_PHY_65NM_CH2_RXTX4, |
4105 | AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); | 4106 | AR_PHY_65NM_CH0_RXTX4_THERM_ON, therm_on); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index ddef9eedbac6..06ad2172030e 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
@@ -333,12 +333,29 @@ static void ar9003_hw_init_mode_regs(struct ath_hw *ah) | |||
333 | qca953x_1p0_soc_preamble); | 333 | qca953x_1p0_soc_preamble); |
334 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], | 334 | INIT_INI_ARRAY(&ah->iniSOC[ATH_INI_POST], |
335 | qca953x_1p0_soc_postamble); | 335 | qca953x_1p0_soc_postamble); |
336 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 336 | |
337 | qca953x_1p0_common_wo_xlna_rx_gain_table); | 337 | if (AR_SREV_9531_20(ah)) { |
338 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, | 338 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
339 | qca953x_1p0_common_wo_xlna_rx_gain_bounds); | 339 | qca953x_2p0_common_wo_xlna_rx_gain_table); |
340 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 340 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, |
341 | qca953x_1p0_modes_no_xpa_tx_gain_table); | 341 | qca953x_2p0_common_wo_xlna_rx_gain_bounds); |
342 | } else { | ||
343 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
344 | qca953x_1p0_common_wo_xlna_rx_gain_table); | ||
345 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, | ||
346 | qca953x_1p0_common_wo_xlna_rx_gain_bounds); | ||
347 | } | ||
348 | |||
349 | if (AR_SREV_9531_20(ah)) | ||
350 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
351 | qca953x_2p0_modes_no_xpa_tx_gain_table); | ||
352 | else if (AR_SREV_9531_11(ah)) | ||
353 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
354 | qca953x_1p1_modes_no_xpa_tx_gain_table); | ||
355 | else | ||
356 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
357 | qca953x_1p0_modes_no_xpa_tx_gain_table); | ||
358 | |||
342 | INIT_INI_ARRAY(&ah->iniModesFastClock, | 359 | INIT_INI_ARRAY(&ah->iniModesFastClock, |
343 | qca953x_1p0_modes_fast_clock); | 360 | qca953x_1p0_modes_fast_clock); |
344 | } else if (AR_SREV_9580(ah)) { | 361 | } else if (AR_SREV_9580(ah)) { |
@@ -518,9 +535,15 @@ static void ar9003_tx_gain_table_mode0(struct ath_hw *ah) | |||
518 | else if (AR_SREV_9550(ah)) | 535 | else if (AR_SREV_9550(ah)) |
519 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 536 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
520 | ar955x_1p0_modes_xpa_tx_gain_table); | 537 | ar955x_1p0_modes_xpa_tx_gain_table); |
521 | else if (AR_SREV_9531(ah)) | 538 | else if (AR_SREV_9531_10(ah)) |
539 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
540 | qca953x_1p0_modes_xpa_tx_gain_table); | ||
541 | else if (AR_SREV_9531_11(ah)) | ||
542 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
543 | qca953x_1p1_modes_xpa_tx_gain_table); | ||
544 | else if (AR_SREV_9531_20(ah)) | ||
522 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 545 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
523 | qca953x_1p0_modes_xpa_tx_gain_table); | 546 | qca953x_2p0_modes_xpa_tx_gain_table); |
524 | else if (AR_SREV_9580(ah)) | 547 | else if (AR_SREV_9580(ah)) |
525 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 548 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
526 | ar9580_1p0_lowest_ob_db_tx_gain_table); | 549 | ar9580_1p0_lowest_ob_db_tx_gain_table); |
@@ -562,7 +585,10 @@ static void ar9003_tx_gain_table_mode1(struct ath_hw *ah) | |||
562 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 585 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
563 | ar955x_1p0_modes_no_xpa_tx_gain_table); | 586 | ar955x_1p0_modes_no_xpa_tx_gain_table); |
564 | else if (AR_SREV_9531(ah)) { | 587 | else if (AR_SREV_9531(ah)) { |
565 | if (AR_SREV_9531_11(ah)) | 588 | if (AR_SREV_9531_20(ah)) |
589 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
590 | qca953x_2p0_modes_no_xpa_tx_gain_table); | ||
591 | else if (AR_SREV_9531_11(ah)) | ||
566 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 592 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
567 | qca953x_1p1_modes_no_xpa_tx_gain_table); | 593 | qca953x_1p1_modes_no_xpa_tx_gain_table); |
568 | else | 594 | else |
@@ -670,9 +696,6 @@ static void ar9003_tx_gain_table_mode5(struct ath_hw *ah) | |||
670 | if (AR_SREV_9485_11_OR_LATER(ah)) | 696 | if (AR_SREV_9485_11_OR_LATER(ah)) |
671 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 697 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
672 | ar9485Modes_green_ob_db_tx_gain_1_1); | 698 | ar9485Modes_green_ob_db_tx_gain_1_1); |
673 | else if (AR_SREV_9340(ah)) | ||
674 | INIT_INI_ARRAY(&ah->iniModesTxGain, | ||
675 | ar9340Modes_ub124_tx_gain_table_1p0); | ||
676 | else if (AR_SREV_9580(ah)) | 699 | else if (AR_SREV_9580(ah)) |
677 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 700 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
678 | ar9580_1p0_type5_tx_gain_table); | 701 | ar9580_1p0_type5_tx_gain_table); |
@@ -792,11 +815,16 @@ static void ar9003_rx_gain_table_mode1(struct ath_hw *ah) | |||
792 | ar955x_1p0_common_wo_xlna_rx_gain_table); | 815 | ar955x_1p0_common_wo_xlna_rx_gain_table); |
793 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, | 816 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, |
794 | ar955x_1p0_common_wo_xlna_rx_gain_bounds); | 817 | ar955x_1p0_common_wo_xlna_rx_gain_bounds); |
795 | } else if (AR_SREV_9531(ah)) { | 818 | } else if (AR_SREV_9531_10(ah) || AR_SREV_9531_11(ah)) { |
796 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 819 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
797 | qca953x_1p0_common_wo_xlna_rx_gain_table); | 820 | qca953x_1p0_common_wo_xlna_rx_gain_table); |
798 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, | 821 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, |
799 | qca953x_1p0_common_wo_xlna_rx_gain_bounds); | 822 | qca953x_1p0_common_wo_xlna_rx_gain_bounds); |
823 | } else if (AR_SREV_9531_20(ah)) { | ||
824 | INIT_INI_ARRAY(&ah->iniModesRxGain, | ||
825 | qca953x_2p0_common_wo_xlna_rx_gain_table); | ||
826 | INIT_INI_ARRAY(&ah->ini_modes_rx_gain_bounds, | ||
827 | qca953x_2p0_common_wo_xlna_rx_gain_bounds); | ||
800 | } else if (AR_SREV_9580(ah)) | 828 | } else if (AR_SREV_9580(ah)) |
801 | INIT_INI_ARRAY(&ah->iniModesRxGain, | 829 | INIT_INI_ARRAY(&ah->iniModesRxGain, |
802 | ar9580_1p0_wo_xlna_rx_gain_table); | 830 | ar9580_1p0_wo_xlna_rx_gain_table); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 697c4ae90af0..2df6d2ee70c2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -664,6 +664,19 @@ static void ar9003_hw_override_ini(struct ath_hw *ah) | |||
664 | ah->enabled_cals |= TX_CL_CAL; | 664 | ah->enabled_cals |= TX_CL_CAL; |
665 | else | 665 | else |
666 | ah->enabled_cals &= ~TX_CL_CAL; | 666 | ah->enabled_cals &= ~TX_CL_CAL; |
667 | |||
668 | if (AR_SREV_9340(ah) || AR_SREV_9531(ah) || AR_SREV_9550(ah)) { | ||
669 | if (ah->is_clk_25mhz) { | ||
670 | REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); | ||
671 | REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); | ||
672 | REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae); | ||
673 | } else { | ||
674 | REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1); | ||
675 | REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400); | ||
676 | REG_WRITE(ah, AR_SLP32_INC, 0x0001e800); | ||
677 | } | ||
678 | udelay(100); | ||
679 | } | ||
667 | } | 680 | } |
668 | 681 | ||
669 | static void ar9003_hw_prog_ini(struct ath_hw *ah, | 682 | static void ar9003_hw_prog_ini(struct ath_hw *ah, |
@@ -1348,7 +1361,7 @@ static void ar9003_hw_set_radar_params(struct ath_hw *ah, | |||
1348 | struct ath_hw_radar_conf *conf) | 1361 | struct ath_hw_radar_conf *conf) |
1349 | { | 1362 | { |
1350 | unsigned int regWrites = 0; | 1363 | unsigned int regWrites = 0; |
1351 | u32 radar_0 = 0, radar_1 = 0; | 1364 | u32 radar_0 = 0, radar_1; |
1352 | 1365 | ||
1353 | if (!conf) { | 1366 | if (!conf) { |
1354 | REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); | 1367 | REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); |
@@ -1362,6 +1375,9 @@ static void ar9003_hw_set_radar_params(struct ath_hw *ah, | |||
1362 | radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI); | 1375 | radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI); |
1363 | radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND); | 1376 | radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND); |
1364 | 1377 | ||
1378 | radar_1 = REG_READ(ah, AR_PHY_RADAR_1); | ||
1379 | radar_1 &= ~(AR_PHY_RADAR_1_MAXLEN | AR_PHY_RADAR_1_RELSTEP_THRESH | | ||
1380 | AR_PHY_RADAR_1_RELPWR_THRESH); | ||
1365 | radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI; | 1381 | radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI; |
1366 | radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK; | 1382 | radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK; |
1367 | radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN); | 1383 | radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN); |
@@ -1388,7 +1404,7 @@ static void ar9003_hw_set_radar_conf(struct ath_hw *ah) | |||
1388 | conf->fir_power = -28; | 1404 | conf->fir_power = -28; |
1389 | conf->radar_rssi = 0; | 1405 | conf->radar_rssi = 0; |
1390 | conf->pulse_height = 10; | 1406 | conf->pulse_height = 10; |
1391 | conf->pulse_rssi = 24; | 1407 | conf->pulse_rssi = 15; |
1392 | conf->pulse_inband = 8; | 1408 | conf->pulse_inband = 8; |
1393 | conf->pulse_maxlen = 255; | 1409 | conf->pulse_maxlen = 255; |
1394 | conf->pulse_inband_step = 12; | 1410 | conf->pulse_inband_step = 12; |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h index a43b30d723a4..6290467a75a0 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_rtt.h +++ b/drivers/net/wireless/ath/ath9k/ar9003_rtt.h | |||
@@ -17,6 +17,7 @@ | |||
17 | #ifndef AR9003_RTT_H | 17 | #ifndef AR9003_RTT_H |
18 | #define AR9003_RTT_H | 18 | #define AR9003_RTT_H |
19 | 19 | ||
20 | #ifdef CONFIG_ATH9K_PCOEM | ||
20 | void ar9003_hw_rtt_enable(struct ath_hw *ah); | 21 | void ar9003_hw_rtt_enable(struct ath_hw *ah); |
21 | void ar9003_hw_rtt_disable(struct ath_hw *ah); | 22 | void ar9003_hw_rtt_disable(struct ath_hw *ah); |
22 | void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask); | 23 | void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask); |
@@ -25,5 +26,40 @@ void ar9003_hw_rtt_load_hist(struct ath_hw *ah); | |||
25 | void ar9003_hw_rtt_fill_hist(struct ath_hw *ah); | 26 | void ar9003_hw_rtt_fill_hist(struct ath_hw *ah); |
26 | void ar9003_hw_rtt_clear_hist(struct ath_hw *ah); | 27 | void ar9003_hw_rtt_clear_hist(struct ath_hw *ah); |
27 | bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan); | 28 | bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan); |
29 | #else | ||
30 | static inline void ar9003_hw_rtt_enable(struct ath_hw *ah) | ||
31 | { | ||
32 | } | ||
33 | |||
34 | static inline void ar9003_hw_rtt_disable(struct ath_hw *ah) | ||
35 | { | ||
36 | } | ||
37 | |||
38 | static inline void ar9003_hw_rtt_set_mask(struct ath_hw *ah, u32 rtt_mask) | ||
39 | { | ||
40 | } | ||
41 | |||
42 | static inline bool ar9003_hw_rtt_force_restore(struct ath_hw *ah) | ||
43 | { | ||
44 | return false; | ||
45 | } | ||
46 | |||
47 | static inline void ar9003_hw_rtt_load_hist(struct ath_hw *ah) | ||
48 | { | ||
49 | } | ||
50 | |||
51 | static inline void ar9003_hw_rtt_fill_hist(struct ath_hw *ah) | ||
52 | { | ||
53 | } | ||
54 | |||
55 | static inline void ar9003_hw_rtt_clear_hist(struct ath_hw *ah) | ||
56 | { | ||
57 | } | ||
58 | |||
59 | static inline bool ar9003_hw_rtt_restore(struct ath_hw *ah, struct ath9k_channel *chan) | ||
60 | { | ||
61 | return false; | ||
62 | } | ||
63 | #endif | ||
28 | 64 | ||
29 | #endif | 65 | #endif |
diff --git a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h index 812a9d787bf3..159cc6fd2362 100644 --- a/drivers/net/wireless/ath/ath9k/ar953x_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar953x_initvals.h | |||
@@ -20,6 +20,8 @@ | |||
20 | 20 | ||
21 | #define qca953x_1p0_mac_postamble ar9300_2p2_mac_postamble | 21 | #define qca953x_1p0_mac_postamble ar9300_2p2_mac_postamble |
22 | 22 | ||
23 | #define qca953x_1p0_soc_preamble ar955x_1p0_soc_preamble | ||
24 | |||
23 | #define qca953x_1p0_soc_postamble ar9300_2p2_soc_postamble | 25 | #define qca953x_1p0_soc_postamble ar9300_2p2_soc_postamble |
24 | 26 | ||
25 | #define qca953x_1p0_common_rx_gain_table ar9300Common_rx_gain_table_2p2 | 27 | #define qca953x_1p0_common_rx_gain_table ar9300Common_rx_gain_table_2p2 |
@@ -28,6 +30,10 @@ | |||
28 | 30 | ||
29 | #define qca953x_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2 | 31 | #define qca953x_1p0_modes_fast_clock ar9300Modes_fast_clock_2p2 |
30 | 32 | ||
33 | #define qca953x_1p0_common_wo_xlna_rx_gain_bounds ar955x_1p0_common_wo_xlna_rx_gain_bounds | ||
34 | |||
35 | #define qca953x_1p0_common_rx_gain_bounds ar955x_1p0_common_rx_gain_bounds | ||
36 | |||
31 | static const u32 qca953x_1p0_mac_core[][2] = { | 37 | static const u32 qca953x_1p0_mac_core[][2] = { |
32 | /* Addr allmodes */ | 38 | /* Addr allmodes */ |
33 | {0x00000008, 0x00000000}, | 39 | {0x00000008, 0x00000000}, |
@@ -490,35 +496,6 @@ static const u32 qca953x_1p0_radio_postamble[][5] = { | |||
490 | {0x00016540, 0x10804008, 0x10804008, 0x50804000, 0x50804000}, | 496 | {0x00016540, 0x10804008, 0x10804008, 0x50804000, 0x50804000}, |
491 | }; | 497 | }; |
492 | 498 | ||
493 | static const u32 qca953x_1p0_soc_preamble[][2] = { | ||
494 | /* Addr allmodes */ | ||
495 | {0x00007000, 0x00000000}, | ||
496 | {0x00007004, 0x00000000}, | ||
497 | {0x00007008, 0x00000000}, | ||
498 | {0x0000700c, 0x00000000}, | ||
499 | {0x0000701c, 0x00000000}, | ||
500 | {0x00007020, 0x00000000}, | ||
501 | {0x00007024, 0x00000000}, | ||
502 | {0x00007028, 0x00000000}, | ||
503 | {0x0000702c, 0x00000000}, | ||
504 | {0x00007030, 0x00000000}, | ||
505 | {0x00007034, 0x00000002}, | ||
506 | {0x00007038, 0x000004c2}, | ||
507 | {0x00007048, 0x00000000}, | ||
508 | }; | ||
509 | |||
510 | static const u32 qca953x_1p0_common_rx_gain_bounds[][5] = { | ||
511 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
512 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, | ||
513 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302018, 0x50302018}, | ||
514 | }; | ||
515 | |||
516 | static const u32 qca953x_1p0_common_wo_xlna_rx_gain_bounds[][5] = { | ||
517 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
518 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, | ||
519 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | ||
520 | }; | ||
521 | |||
522 | static const u32 qca953x_1p0_modes_xpa_tx_gain_table[][2] = { | 499 | static const u32 qca953x_1p0_modes_xpa_tx_gain_table[][2] = { |
523 | /* Addr allmodes */ | 500 | /* Addr allmodes */ |
524 | {0x0000a2dc, 0xfffd5aaa}, | 501 | {0x0000a2dc, 0xfffd5aaa}, |
@@ -715,8 +692,73 @@ static const u32 qca953x_1p1_modes_no_xpa_tx_gain_table[][2] = { | |||
715 | {0x00016448, 0x6c927a70}, | 692 | {0x00016448, 0x6c927a70}, |
716 | }; | 693 | }; |
717 | 694 | ||
695 | static const u32 qca953x_1p1_modes_xpa_tx_gain_table[][2] = { | ||
696 | /* Addr allmodes */ | ||
697 | {0x0000a2dc, 0xfffb52aa}, | ||
698 | {0x0000a2e0, 0xfffd64cc}, | ||
699 | {0x0000a2e4, 0xfffe80f0}, | ||
700 | {0x0000a2e8, 0xffffff00}, | ||
701 | {0x0000a410, 0x000050d5}, | ||
702 | {0x0000a500, 0x00000000}, | ||
703 | {0x0000a504, 0x04000002}, | ||
704 | {0x0000a508, 0x08000004}, | ||
705 | {0x0000a50c, 0x0c000006}, | ||
706 | {0x0000a510, 0x1000000a}, | ||
707 | {0x0000a514, 0x1400000c}, | ||
708 | {0x0000a518, 0x1800000e}, | ||
709 | {0x0000a51c, 0x1c000048}, | ||
710 | {0x0000a520, 0x2000004a}, | ||
711 | {0x0000a524, 0x2400004c}, | ||
712 | {0x0000a528, 0x2800004e}, | ||
713 | {0x0000a52c, 0x2b00024a}, | ||
714 | {0x0000a530, 0x2f00024c}, | ||
715 | {0x0000a534, 0x3300024e}, | ||
716 | {0x0000a538, 0x36000668}, | ||
717 | {0x0000a53c, 0x38000669}, | ||
718 | {0x0000a540, 0x3a000868}, | ||
719 | {0x0000a544, 0x3d00086a}, | ||
720 | {0x0000a548, 0x4000086c}, | ||
721 | {0x0000a54c, 0x4200086e}, | ||
722 | {0x0000a550, 0x43000a6e}, | ||
723 | {0x0000a554, 0x43000a6e}, | ||
724 | {0x0000a558, 0x43000a6e}, | ||
725 | {0x0000a55c, 0x43000a6e}, | ||
726 | {0x0000a560, 0x43000a6e}, | ||
727 | {0x0000a564, 0x43000a6e}, | ||
728 | {0x0000a568, 0x43000a6e}, | ||
729 | {0x0000a56c, 0x43000a6e}, | ||
730 | {0x0000a570, 0x43000a6e}, | ||
731 | {0x0000a574, 0x43000a6e}, | ||
732 | {0x0000a578, 0x43000a6e}, | ||
733 | {0x0000a57c, 0x43000a6e}, | ||
734 | {0x0000a600, 0x00000000}, | ||
735 | {0x0000a604, 0x00000000}, | ||
736 | {0x0000a608, 0x00000000}, | ||
737 | {0x0000a60c, 0x03804000}, | ||
738 | {0x0000a610, 0x03804e01}, | ||
739 | {0x0000a614, 0x03804e01}, | ||
740 | {0x0000a618, 0x03804e01}, | ||
741 | {0x0000a61c, 0x04009002}, | ||
742 | {0x0000a620, 0x04009002}, | ||
743 | {0x0000a624, 0x04009002}, | ||
744 | {0x0000a628, 0x04009002}, | ||
745 | {0x0000a62c, 0x04009002}, | ||
746 | {0x0000a630, 0x04009002}, | ||
747 | {0x0000a634, 0x04009002}, | ||
748 | {0x0000a638, 0x04009002}, | ||
749 | {0x0000a63c, 0x04009002}, | ||
750 | {0x0000b2dc, 0xfffb52aa}, | ||
751 | {0x0000b2e0, 0xfffd64cc}, | ||
752 | {0x0000b2e4, 0xfffe80f0}, | ||
753 | {0x0000b2e8, 0xffffff00}, | ||
754 | {0x00016044, 0x024922db}, | ||
755 | {0x00016048, 0x6c927a70}, | ||
756 | {0x00016444, 0x024922db}, | ||
757 | {0x00016448, 0x6c927a70}, | ||
758 | }; | ||
759 | |||
718 | static const u32 qca953x_2p0_baseband_core[][2] = { | 760 | static const u32 qca953x_2p0_baseband_core[][2] = { |
719 | /* Addr allmodes */ | 761 | /* Addr allmodes */ |
720 | {0x00009800, 0xafe68e30}, | 762 | {0x00009800, 0xafe68e30}, |
721 | {0x00009804, 0xfd14e000}, | 763 | {0x00009804, 0xfd14e000}, |
722 | {0x00009808, 0x9c0a9f6b}, | 764 | {0x00009808, 0x9c0a9f6b}, |
@@ -914,4 +956,400 @@ static const u32 qca953x_2p0_baseband_postamble[][5] = { | |||
914 | {0x0000b284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, | 956 | {0x0000b284, 0x00000000, 0x00000000, 0x00000010, 0x00000010}, |
915 | }; | 957 | }; |
916 | 958 | ||
959 | static const u32 qca953x_2p0_common_wo_xlna_rx_gain_table[][2] = { | ||
960 | /* Addr allmodes */ | ||
961 | {0x0000a000, 0x00010000}, | ||
962 | {0x0000a004, 0x00030002}, | ||
963 | {0x0000a008, 0x00050004}, | ||
964 | {0x0000a00c, 0x00810080}, | ||
965 | {0x0000a010, 0x00830082}, | ||
966 | {0x0000a014, 0x01810180}, | ||
967 | {0x0000a018, 0x01830182}, | ||
968 | {0x0000a01c, 0x01850184}, | ||
969 | {0x0000a020, 0x01890188}, | ||
970 | {0x0000a024, 0x018b018a}, | ||
971 | {0x0000a028, 0x018d018c}, | ||
972 | {0x0000a02c, 0x03820190}, | ||
973 | {0x0000a030, 0x03840383}, | ||
974 | {0x0000a034, 0x03880385}, | ||
975 | {0x0000a038, 0x038a0389}, | ||
976 | {0x0000a03c, 0x038c038b}, | ||
977 | {0x0000a040, 0x0390038d}, | ||
978 | {0x0000a044, 0x03920391}, | ||
979 | {0x0000a048, 0x03940393}, | ||
980 | {0x0000a04c, 0x03960395}, | ||
981 | {0x0000a050, 0x00000000}, | ||
982 | {0x0000a054, 0x00000000}, | ||
983 | {0x0000a058, 0x00000000}, | ||
984 | {0x0000a05c, 0x00000000}, | ||
985 | {0x0000a060, 0x00000000}, | ||
986 | {0x0000a064, 0x00000000}, | ||
987 | {0x0000a068, 0x00000000}, | ||
988 | {0x0000a06c, 0x00000000}, | ||
989 | {0x0000a070, 0x00000000}, | ||
990 | {0x0000a074, 0x00000000}, | ||
991 | {0x0000a078, 0x00000000}, | ||
992 | {0x0000a07c, 0x00000000}, | ||
993 | {0x0000a080, 0x29292929}, | ||
994 | {0x0000a084, 0x29292929}, | ||
995 | {0x0000a088, 0x29292929}, | ||
996 | {0x0000a08c, 0x29292929}, | ||
997 | {0x0000a090, 0x22292929}, | ||
998 | {0x0000a094, 0x1d1d2222}, | ||
999 | {0x0000a098, 0x0c111117}, | ||
1000 | {0x0000a09c, 0x00030303}, | ||
1001 | {0x0000a0a0, 0x00000000}, | ||
1002 | {0x0000a0a4, 0x00000000}, | ||
1003 | {0x0000a0a8, 0x00000000}, | ||
1004 | {0x0000a0ac, 0x00000000}, | ||
1005 | {0x0000a0b0, 0x00000000}, | ||
1006 | {0x0000a0b4, 0x00000000}, | ||
1007 | {0x0000a0b8, 0x00000000}, | ||
1008 | {0x0000a0bc, 0x00000000}, | ||
1009 | {0x0000a0c0, 0x001f0000}, | ||
1010 | {0x0000a0c4, 0x01000101}, | ||
1011 | {0x0000a0c8, 0x011e011f}, | ||
1012 | {0x0000a0cc, 0x011c011d}, | ||
1013 | {0x0000a0d0, 0x02030204}, | ||
1014 | {0x0000a0d4, 0x02010202}, | ||
1015 | {0x0000a0d8, 0x021f0200}, | ||
1016 | {0x0000a0dc, 0x0302021e}, | ||
1017 | {0x0000a0e0, 0x03000301}, | ||
1018 | {0x0000a0e4, 0x031e031f}, | ||
1019 | {0x0000a0e8, 0x0402031d}, | ||
1020 | {0x0000a0ec, 0x04000401}, | ||
1021 | {0x0000a0f0, 0x041e041f}, | ||
1022 | {0x0000a0f4, 0x0502041d}, | ||
1023 | {0x0000a0f8, 0x05000501}, | ||
1024 | {0x0000a0fc, 0x051e051f}, | ||
1025 | {0x0000a100, 0x06010602}, | ||
1026 | {0x0000a104, 0x061f0600}, | ||
1027 | {0x0000a108, 0x061d061e}, | ||
1028 | {0x0000a10c, 0x07020703}, | ||
1029 | {0x0000a110, 0x07000701}, | ||
1030 | {0x0000a114, 0x00000000}, | ||
1031 | {0x0000a118, 0x00000000}, | ||
1032 | {0x0000a11c, 0x00000000}, | ||
1033 | {0x0000a120, 0x00000000}, | ||
1034 | {0x0000a124, 0x00000000}, | ||
1035 | {0x0000a128, 0x00000000}, | ||
1036 | {0x0000a12c, 0x00000000}, | ||
1037 | {0x0000a130, 0x00000000}, | ||
1038 | {0x0000a134, 0x00000000}, | ||
1039 | {0x0000a138, 0x00000000}, | ||
1040 | {0x0000a13c, 0x00000000}, | ||
1041 | {0x0000a140, 0x001f0000}, | ||
1042 | {0x0000a144, 0x01000101}, | ||
1043 | {0x0000a148, 0x011e011f}, | ||
1044 | {0x0000a14c, 0x011c011d}, | ||
1045 | {0x0000a150, 0x02030204}, | ||
1046 | {0x0000a154, 0x02010202}, | ||
1047 | {0x0000a158, 0x021f0200}, | ||
1048 | {0x0000a15c, 0x0302021e}, | ||
1049 | {0x0000a160, 0x03000301}, | ||
1050 | {0x0000a164, 0x031e031f}, | ||
1051 | {0x0000a168, 0x0402031d}, | ||
1052 | {0x0000a16c, 0x04000401}, | ||
1053 | {0x0000a170, 0x041e041f}, | ||
1054 | {0x0000a174, 0x0502041d}, | ||
1055 | {0x0000a178, 0x05000501}, | ||
1056 | {0x0000a17c, 0x051e051f}, | ||
1057 | {0x0000a180, 0x06010602}, | ||
1058 | {0x0000a184, 0x061f0600}, | ||
1059 | {0x0000a188, 0x061d061e}, | ||
1060 | {0x0000a18c, 0x07020703}, | ||
1061 | {0x0000a190, 0x07000701}, | ||
1062 | {0x0000a194, 0x00000000}, | ||
1063 | {0x0000a198, 0x00000000}, | ||
1064 | {0x0000a19c, 0x00000000}, | ||
1065 | {0x0000a1a0, 0x00000000}, | ||
1066 | {0x0000a1a4, 0x00000000}, | ||
1067 | {0x0000a1a8, 0x00000000}, | ||
1068 | {0x0000a1ac, 0x00000000}, | ||
1069 | {0x0000a1b0, 0x00000000}, | ||
1070 | {0x0000a1b4, 0x00000000}, | ||
1071 | {0x0000a1b8, 0x00000000}, | ||
1072 | {0x0000a1bc, 0x00000000}, | ||
1073 | {0x0000a1c0, 0x00000000}, | ||
1074 | {0x0000a1c4, 0x00000000}, | ||
1075 | {0x0000a1c8, 0x00000000}, | ||
1076 | {0x0000a1cc, 0x00000000}, | ||
1077 | {0x0000a1d0, 0x00000000}, | ||
1078 | {0x0000a1d4, 0x00000000}, | ||
1079 | {0x0000a1d8, 0x00000000}, | ||
1080 | {0x0000a1dc, 0x00000000}, | ||
1081 | {0x0000a1e0, 0x00000000}, | ||
1082 | {0x0000a1e4, 0x00000000}, | ||
1083 | {0x0000a1e8, 0x00000000}, | ||
1084 | {0x0000a1ec, 0x00000000}, | ||
1085 | {0x0000a1f0, 0x00000396}, | ||
1086 | {0x0000a1f4, 0x00000396}, | ||
1087 | {0x0000a1f8, 0x00000396}, | ||
1088 | {0x0000a1fc, 0x00000196}, | ||
1089 | {0x0000b000, 0x00010000}, | ||
1090 | {0x0000b004, 0x00030002}, | ||
1091 | {0x0000b008, 0x00050004}, | ||
1092 | {0x0000b00c, 0x00810080}, | ||
1093 | {0x0000b010, 0x00830082}, | ||
1094 | {0x0000b014, 0x01810180}, | ||
1095 | {0x0000b018, 0x01830182}, | ||
1096 | {0x0000b01c, 0x01850184}, | ||
1097 | {0x0000b020, 0x02810280}, | ||
1098 | {0x0000b024, 0x02830282}, | ||
1099 | {0x0000b028, 0x02850284}, | ||
1100 | {0x0000b02c, 0x02890288}, | ||
1101 | {0x0000b030, 0x028b028a}, | ||
1102 | {0x0000b034, 0x0388028c}, | ||
1103 | {0x0000b038, 0x038a0389}, | ||
1104 | {0x0000b03c, 0x038c038b}, | ||
1105 | {0x0000b040, 0x0390038d}, | ||
1106 | {0x0000b044, 0x03920391}, | ||
1107 | {0x0000b048, 0x03940393}, | ||
1108 | {0x0000b04c, 0x03960395}, | ||
1109 | {0x0000b050, 0x00000000}, | ||
1110 | {0x0000b054, 0x00000000}, | ||
1111 | {0x0000b058, 0x00000000}, | ||
1112 | {0x0000b05c, 0x00000000}, | ||
1113 | {0x0000b060, 0x00000000}, | ||
1114 | {0x0000b064, 0x00000000}, | ||
1115 | {0x0000b068, 0x00000000}, | ||
1116 | {0x0000b06c, 0x00000000}, | ||
1117 | {0x0000b070, 0x00000000}, | ||
1118 | {0x0000b074, 0x00000000}, | ||
1119 | {0x0000b078, 0x00000000}, | ||
1120 | {0x0000b07c, 0x00000000}, | ||
1121 | {0x0000b080, 0x32323232}, | ||
1122 | {0x0000b084, 0x2f2f3232}, | ||
1123 | {0x0000b088, 0x23282a2d}, | ||
1124 | {0x0000b08c, 0x1c1e2123}, | ||
1125 | {0x0000b090, 0x14171919}, | ||
1126 | {0x0000b094, 0x0e0e1214}, | ||
1127 | {0x0000b098, 0x03050707}, | ||
1128 | {0x0000b09c, 0x00030303}, | ||
1129 | {0x0000b0a0, 0x00000000}, | ||
1130 | {0x0000b0a4, 0x00000000}, | ||
1131 | {0x0000b0a8, 0x00000000}, | ||
1132 | {0x0000b0ac, 0x00000000}, | ||
1133 | {0x0000b0b0, 0x00000000}, | ||
1134 | {0x0000b0b4, 0x00000000}, | ||
1135 | {0x0000b0b8, 0x00000000}, | ||
1136 | {0x0000b0bc, 0x00000000}, | ||
1137 | {0x0000b0c0, 0x003f0020}, | ||
1138 | {0x0000b0c4, 0x00400041}, | ||
1139 | {0x0000b0c8, 0x0140005f}, | ||
1140 | {0x0000b0cc, 0x0160015f}, | ||
1141 | {0x0000b0d0, 0x017e017f}, | ||
1142 | {0x0000b0d4, 0x02410242}, | ||
1143 | {0x0000b0d8, 0x025f0240}, | ||
1144 | {0x0000b0dc, 0x027f0260}, | ||
1145 | {0x0000b0e0, 0x0341027e}, | ||
1146 | {0x0000b0e4, 0x035f0340}, | ||
1147 | {0x0000b0e8, 0x037f0360}, | ||
1148 | {0x0000b0ec, 0x04400441}, | ||
1149 | {0x0000b0f0, 0x0460045f}, | ||
1150 | {0x0000b0f4, 0x0541047f}, | ||
1151 | {0x0000b0f8, 0x055f0540}, | ||
1152 | {0x0000b0fc, 0x057f0560}, | ||
1153 | {0x0000b100, 0x06400641}, | ||
1154 | {0x0000b104, 0x0660065f}, | ||
1155 | {0x0000b108, 0x067e067f}, | ||
1156 | {0x0000b10c, 0x07410742}, | ||
1157 | {0x0000b110, 0x075f0740}, | ||
1158 | {0x0000b114, 0x077f0760}, | ||
1159 | {0x0000b118, 0x07800781}, | ||
1160 | {0x0000b11c, 0x07a0079f}, | ||
1161 | {0x0000b120, 0x07c107bf}, | ||
1162 | {0x0000b124, 0x000007c0}, | ||
1163 | {0x0000b128, 0x00000000}, | ||
1164 | {0x0000b12c, 0x00000000}, | ||
1165 | {0x0000b130, 0x00000000}, | ||
1166 | {0x0000b134, 0x00000000}, | ||
1167 | {0x0000b138, 0x00000000}, | ||
1168 | {0x0000b13c, 0x00000000}, | ||
1169 | {0x0000b140, 0x003f0020}, | ||
1170 | {0x0000b144, 0x00400041}, | ||
1171 | {0x0000b148, 0x0140005f}, | ||
1172 | {0x0000b14c, 0x0160015f}, | ||
1173 | {0x0000b150, 0x017e017f}, | ||
1174 | {0x0000b154, 0x02410242}, | ||
1175 | {0x0000b158, 0x025f0240}, | ||
1176 | {0x0000b15c, 0x027f0260}, | ||
1177 | {0x0000b160, 0x0341027e}, | ||
1178 | {0x0000b164, 0x035f0340}, | ||
1179 | {0x0000b168, 0x037f0360}, | ||
1180 | {0x0000b16c, 0x04400441}, | ||
1181 | {0x0000b170, 0x0460045f}, | ||
1182 | {0x0000b174, 0x0541047f}, | ||
1183 | {0x0000b178, 0x055f0540}, | ||
1184 | {0x0000b17c, 0x057f0560}, | ||
1185 | {0x0000b180, 0x06400641}, | ||
1186 | {0x0000b184, 0x0660065f}, | ||
1187 | {0x0000b188, 0x067e067f}, | ||
1188 | {0x0000b18c, 0x07410742}, | ||
1189 | {0x0000b190, 0x075f0740}, | ||
1190 | {0x0000b194, 0x077f0760}, | ||
1191 | {0x0000b198, 0x07800781}, | ||
1192 | {0x0000b19c, 0x07a0079f}, | ||
1193 | {0x0000b1a0, 0x07c107bf}, | ||
1194 | {0x0000b1a4, 0x000007c0}, | ||
1195 | {0x0000b1a8, 0x00000000}, | ||
1196 | {0x0000b1ac, 0x00000000}, | ||
1197 | {0x0000b1b0, 0x00000000}, | ||
1198 | {0x0000b1b4, 0x00000000}, | ||
1199 | {0x0000b1b8, 0x00000000}, | ||
1200 | {0x0000b1bc, 0x00000000}, | ||
1201 | {0x0000b1c0, 0x00000000}, | ||
1202 | {0x0000b1c4, 0x00000000}, | ||
1203 | {0x0000b1c8, 0x00000000}, | ||
1204 | {0x0000b1cc, 0x00000000}, | ||
1205 | {0x0000b1d0, 0x00000000}, | ||
1206 | {0x0000b1d4, 0x00000000}, | ||
1207 | {0x0000b1d8, 0x00000000}, | ||
1208 | {0x0000b1dc, 0x00000000}, | ||
1209 | {0x0000b1e0, 0x00000000}, | ||
1210 | {0x0000b1e4, 0x00000000}, | ||
1211 | {0x0000b1e8, 0x00000000}, | ||
1212 | {0x0000b1ec, 0x00000000}, | ||
1213 | {0x0000b1f0, 0x00000396}, | ||
1214 | {0x0000b1f4, 0x00000396}, | ||
1215 | {0x0000b1f8, 0x00000396}, | ||
1216 | {0x0000b1fc, 0x00000196}, | ||
1217 | }; | ||
1218 | |||
1219 | static const u32 qca953x_2p0_common_wo_xlna_rx_gain_bounds[][5] = { | ||
1220 | /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ | ||
1221 | {0x00009e44, 0xfe321e27, 0xfe321e27, 0xfe291e27, 0xfe291e27}, | ||
1222 | {0x00009e48, 0x5030201a, 0x5030201a, 0x50302012, 0x50302012}, | ||
1223 | }; | ||
1224 | |||
1225 | static const u32 qca953x_2p0_modes_xpa_tx_gain_table[][2] = { | ||
1226 | /* Addr allmodes */ | ||
1227 | {0x0000a2dc, 0xfffb52aa}, | ||
1228 | {0x0000a2e0, 0xfffd64cc}, | ||
1229 | {0x0000a2e4, 0xfffe80f0}, | ||
1230 | {0x0000a2e8, 0xffffff00}, | ||
1231 | {0x0000a410, 0x000050d5}, | ||
1232 | {0x0000a500, 0x00000000}, | ||
1233 | {0x0000a504, 0x04000002}, | ||
1234 | {0x0000a508, 0x08000004}, | ||
1235 | {0x0000a50c, 0x0c000006}, | ||
1236 | {0x0000a510, 0x1000000a}, | ||
1237 | {0x0000a514, 0x1400000c}, | ||
1238 | {0x0000a518, 0x1800000e}, | ||
1239 | {0x0000a51c, 0x1c000048}, | ||
1240 | {0x0000a520, 0x2000004a}, | ||
1241 | {0x0000a524, 0x2400004c}, | ||
1242 | {0x0000a528, 0x2800004e}, | ||
1243 | {0x0000a52c, 0x2b00024a}, | ||
1244 | {0x0000a530, 0x2f00024c}, | ||
1245 | {0x0000a534, 0x3300024e}, | ||
1246 | {0x0000a538, 0x36000668}, | ||
1247 | {0x0000a53c, 0x38000669}, | ||
1248 | {0x0000a540, 0x3a000868}, | ||
1249 | {0x0000a544, 0x3d00086a}, | ||
1250 | {0x0000a548, 0x4000086c}, | ||
1251 | {0x0000a54c, 0x4200086e}, | ||
1252 | {0x0000a550, 0x43000a6e}, | ||
1253 | {0x0000a554, 0x43000a6e}, | ||
1254 | {0x0000a558, 0x43000a6e}, | ||
1255 | {0x0000a55c, 0x43000a6e}, | ||
1256 | {0x0000a560, 0x43000a6e}, | ||
1257 | {0x0000a564, 0x43000a6e}, | ||
1258 | {0x0000a568, 0x43000a6e}, | ||
1259 | {0x0000a56c, 0x43000a6e}, | ||
1260 | {0x0000a570, 0x43000a6e}, | ||
1261 | {0x0000a574, 0x43000a6e}, | ||
1262 | {0x0000a578, 0x43000a6e}, | ||
1263 | {0x0000a57c, 0x43000a6e}, | ||
1264 | {0x0000a600, 0x00000000}, | ||
1265 | {0x0000a604, 0x00000000}, | ||
1266 | {0x0000a608, 0x00000000}, | ||
1267 | {0x0000a60c, 0x03804000}, | ||
1268 | {0x0000a610, 0x03804e01}, | ||
1269 | {0x0000a614, 0x03804e01}, | ||
1270 | {0x0000a618, 0x03804e01}, | ||
1271 | {0x0000a61c, 0x04009002}, | ||
1272 | {0x0000a620, 0x04009002}, | ||
1273 | {0x0000a624, 0x04009002}, | ||
1274 | {0x0000a628, 0x04009002}, | ||
1275 | {0x0000a62c, 0x04009002}, | ||
1276 | {0x0000a630, 0x04009002}, | ||
1277 | {0x0000a634, 0x04009002}, | ||
1278 | {0x0000a638, 0x04009002}, | ||
1279 | {0x0000a63c, 0x04009002}, | ||
1280 | {0x0000b2dc, 0xfffb52aa}, | ||
1281 | {0x0000b2e0, 0xfffd64cc}, | ||
1282 | {0x0000b2e4, 0xfffe80f0}, | ||
1283 | {0x0000b2e8, 0xffffff00}, | ||
1284 | {0x00016044, 0x024922db}, | ||
1285 | {0x00016048, 0x6c927a70}, | ||
1286 | {0x00016444, 0x024922db}, | ||
1287 | {0x00016448, 0x6c927a70}, | ||
1288 | }; | ||
1289 | |||
1290 | static const u32 qca953x_2p0_modes_no_xpa_tx_gain_table[][2] = { | ||
1291 | /* Addr allmodes */ | ||
1292 | {0x0000a2dc, 0xffd5f552}, | ||
1293 | {0x0000a2e0, 0xffe60664}, | ||
1294 | {0x0000a2e4, 0xfff80780}, | ||
1295 | {0x0000a2e8, 0xfffff800}, | ||
1296 | {0x0000a410, 0x000050de}, | ||
1297 | {0x0000a500, 0x00000061}, | ||
1298 | {0x0000a504, 0x04000063}, | ||
1299 | {0x0000a508, 0x08000065}, | ||
1300 | {0x0000a50c, 0x0c000261}, | ||
1301 | {0x0000a510, 0x10000263}, | ||
1302 | {0x0000a514, 0x14000265}, | ||
1303 | {0x0000a518, 0x18000482}, | ||
1304 | {0x0000a51c, 0x1b000484}, | ||
1305 | {0x0000a520, 0x1f000486}, | ||
1306 | {0x0000a524, 0x240008c2}, | ||
1307 | {0x0000a528, 0x28000cc1}, | ||
1308 | {0x0000a52c, 0x2d000ce3}, | ||
1309 | {0x0000a530, 0x31000ce5}, | ||
1310 | {0x0000a534, 0x350010e5}, | ||
1311 | {0x0000a538, 0x360012e5}, | ||
1312 | {0x0000a53c, 0x380014e5}, | ||
1313 | {0x0000a540, 0x3b0018e5}, | ||
1314 | {0x0000a544, 0x3d001d04}, | ||
1315 | {0x0000a548, 0x3e001d05}, | ||
1316 | {0x0000a54c, 0x40001d07}, | ||
1317 | {0x0000a550, 0x42001f27}, | ||
1318 | {0x0000a554, 0x43001f67}, | ||
1319 | {0x0000a558, 0x46001fe7}, | ||
1320 | {0x0000a55c, 0x47001f2b}, | ||
1321 | {0x0000a560, 0x49001f0d}, | ||
1322 | {0x0000a564, 0x4b001ed2}, | ||
1323 | {0x0000a568, 0x4c001ed4}, | ||
1324 | {0x0000a56c, 0x4e001f15}, | ||
1325 | {0x0000a570, 0x4f001ff6}, | ||
1326 | {0x0000a574, 0x4f001ff6}, | ||
1327 | {0x0000a578, 0x4f001ff6}, | ||
1328 | {0x0000a57c, 0x4f001ff6}, | ||
1329 | {0x0000a600, 0x00000000}, | ||
1330 | {0x0000a604, 0x00000000}, | ||
1331 | {0x0000a608, 0x00000000}, | ||
1332 | {0x0000a60c, 0x00804201}, | ||
1333 | {0x0000a610, 0x01008201}, | ||
1334 | {0x0000a614, 0x0180c402}, | ||
1335 | {0x0000a618, 0x0180c603}, | ||
1336 | {0x0000a61c, 0x0180c603}, | ||
1337 | {0x0000a620, 0x01c10603}, | ||
1338 | {0x0000a624, 0x01c10704}, | ||
1339 | {0x0000a628, 0x02c18b05}, | ||
1340 | {0x0000a62c, 0x02c14c07}, | ||
1341 | {0x0000a630, 0x01008704}, | ||
1342 | {0x0000a634, 0x01c10402}, | ||
1343 | {0x0000a638, 0x0301cc07}, | ||
1344 | {0x0000a63c, 0x0301cc07}, | ||
1345 | {0x0000b2dc, 0xffd5f552}, | ||
1346 | {0x0000b2e0, 0xffe60664}, | ||
1347 | {0x0000b2e4, 0xfff80780}, | ||
1348 | {0x0000b2e8, 0xfffff800}, | ||
1349 | {0x00016044, 0x049242db}, | ||
1350 | {0x00016048, 0x6c927a70}, | ||
1351 | {0x00016444, 0x049242db}, | ||
1352 | {0x00016448, 0x6c927a70}, | ||
1353 | }; | ||
1354 | |||
917 | #endif /* INITVALS_953X_H */ | 1355 | #endif /* INITVALS_953X_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h index 74d8bc05b317..fd6a84ccd49e 100644 --- a/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar955x_1p0_initvals.h | |||
@@ -507,7 +507,7 @@ static const u32 ar955x_1p0_baseband_core[][2] = { | |||
507 | {0x00009d04, 0x40206c10}, | 507 | {0x00009d04, 0x40206c10}, |
508 | {0x00009d08, 0x009c4060}, | 508 | {0x00009d08, 0x009c4060}, |
509 | {0x00009d0c, 0x9883800a}, | 509 | {0x00009d0c, 0x9883800a}, |
510 | {0x00009d10, 0x01834061}, | 510 | {0x00009d10, 0x01884061}, |
511 | {0x00009d14, 0x00c0040b}, | 511 | {0x00009d14, 0x00c0040b}, |
512 | {0x00009d18, 0x00000000}, | 512 | {0x00009d18, 0x00000000}, |
513 | {0x00009e08, 0x0038230c}, | 513 | {0x00009e08, 0x0038230c}, |
@@ -545,9 +545,9 @@ static const u32 ar955x_1p0_baseband_core[][2] = { | |||
545 | {0x0000a370, 0x00000000}, | 545 | {0x0000a370, 0x00000000}, |
546 | {0x0000a390, 0x00000001}, | 546 | {0x0000a390, 0x00000001}, |
547 | {0x0000a394, 0x00000444}, | 547 | {0x0000a394, 0x00000444}, |
548 | {0x0000a398, 0x1f020503}, | 548 | {0x0000a398, 0x001f0e0f}, |
549 | {0x0000a39c, 0x29180c03}, | 549 | {0x0000a39c, 0x0075393f}, |
550 | {0x0000a3a0, 0x9a8b6844}, | 550 | {0x0000a3a0, 0xb79f6427}, |
551 | {0x0000a3a4, 0x00000000}, | 551 | {0x0000a3a4, 0x00000000}, |
552 | {0x0000a3a8, 0xaaaaaaaa}, | 552 | {0x0000a3a8, 0xaaaaaaaa}, |
553 | {0x0000a3ac, 0x3c466478}, | 553 | {0x0000a3ac, 0x3c466478}, |
diff --git a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h index a5ca65240af3..5d4629f96c15 100644 --- a/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h +++ b/drivers/net/wireless/ath/ath9k/ar9580_1p0_initvals.h | |||
@@ -24,7 +24,149 @@ | |||
24 | 24 | ||
25 | #define ar9580_1p0_soc_postamble ar9300_2p2_soc_postamble | 25 | #define ar9580_1p0_soc_postamble ar9300_2p2_soc_postamble |
26 | 26 | ||
27 | #define ar9580_1p0_radio_core ar9300_2p2_radio_core | 27 | static const u32 ar9580_1p0_radio_core[][2] = { |
28 | /* Addr allmodes */ | ||
29 | {0x00016000, 0x36db2db6}, | ||
30 | {0x00016004, 0x6db6db40}, | ||
31 | {0x00016008, 0x73f00000}, | ||
32 | {0x0001600c, 0x00000000}, | ||
33 | {0x00016040, 0x7f80fff8}, | ||
34 | {0x0001604c, 0x76d005b5}, | ||
35 | {0x00016050, 0x556cf031}, | ||
36 | {0x00016054, 0x13449440}, | ||
37 | {0x00016058, 0x0c51c92c}, | ||
38 | {0x0001605c, 0x3db7fffc}, | ||
39 | {0x00016060, 0xfffffffc}, | ||
40 | {0x00016064, 0x000f0278}, | ||
41 | {0x0001606c, 0x6db60000}, | ||
42 | {0x00016080, 0x00000000}, | ||
43 | {0x00016084, 0x0e48048c}, | ||
44 | {0x00016088, 0x54214514}, | ||
45 | {0x0001608c, 0x119f481e}, | ||
46 | {0x00016090, 0x24926490}, | ||
47 | {0x00016098, 0xd2888888}, | ||
48 | {0x000160a0, 0x0a108ffe}, | ||
49 | {0x000160a4, 0x812fc370}, | ||
50 | {0x000160a8, 0x423c8000}, | ||
51 | {0x000160b4, 0x92480080}, | ||
52 | {0x000160c0, 0x00adb6d0}, | ||
53 | {0x000160c4, 0x6db6db60}, | ||
54 | {0x000160c8, 0x6db6db6c}, | ||
55 | {0x000160cc, 0x01e6c000}, | ||
56 | {0x00016100, 0x3fffbe01}, | ||
57 | {0x00016104, 0xfff80000}, | ||
58 | {0x00016108, 0x00080010}, | ||
59 | {0x00016144, 0x02084080}, | ||
60 | {0x00016148, 0x00000000}, | ||
61 | {0x00016280, 0x058a0001}, | ||
62 | {0x00016284, 0x3d840208}, | ||
63 | {0x00016288, 0x05a20408}, | ||
64 | {0x0001628c, 0x00038c07}, | ||
65 | {0x00016290, 0x00000004}, | ||
66 | {0x00016294, 0x458a214f}, | ||
67 | {0x00016380, 0x00000000}, | ||
68 | {0x00016384, 0x00000000}, | ||
69 | {0x00016388, 0x00800700}, | ||
70 | {0x0001638c, 0x00800700}, | ||
71 | {0x00016390, 0x00800700}, | ||
72 | {0x00016394, 0x00000000}, | ||
73 | {0x00016398, 0x00000000}, | ||
74 | {0x0001639c, 0x00000000}, | ||
75 | {0x000163a0, 0x00000001}, | ||
76 | {0x000163a4, 0x00000001}, | ||
77 | {0x000163a8, 0x00000000}, | ||
78 | {0x000163ac, 0x00000000}, | ||
79 | {0x000163b0, 0x00000000}, | ||
80 | {0x000163b4, 0x00000000}, | ||
81 | {0x000163b8, 0x00000000}, | ||
82 | {0x000163bc, 0x00000000}, | ||
83 | {0x000163c0, 0x000000a0}, | ||
84 | {0x000163c4, 0x000c0000}, | ||
85 | {0x000163c8, 0x14021402}, | ||
86 | {0x000163cc, 0x00001402}, | ||
87 | {0x000163d0, 0x00000000}, | ||
88 | {0x000163d4, 0x00000000}, | ||
89 | {0x00016400, 0x36db2db6}, | ||
90 | {0x00016404, 0x6db6db40}, | ||
91 | {0x00016408, 0x73f00000}, | ||
92 | {0x0001640c, 0x00000000}, | ||
93 | {0x00016440, 0x7f80fff8}, | ||
94 | {0x0001644c, 0x76d005b5}, | ||
95 | {0x00016450, 0x556cf031}, | ||
96 | {0x00016454, 0x13449440}, | ||
97 | {0x00016458, 0x0c51c92c}, | ||
98 | {0x0001645c, 0x3db7fffc}, | ||
99 | {0x00016460, 0xfffffffc}, | ||
100 | {0x00016464, 0x000f0278}, | ||
101 | {0x0001646c, 0x6db60000}, | ||
102 | {0x00016500, 0x3fffbe01}, | ||
103 | {0x00016504, 0xfff80000}, | ||
104 | {0x00016508, 0x00080010}, | ||
105 | {0x00016544, 0x02084080}, | ||
106 | {0x00016548, 0x00000000}, | ||
107 | {0x00016780, 0x00000000}, | ||
108 | {0x00016784, 0x00000000}, | ||
109 | {0x00016788, 0x00800700}, | ||
110 | {0x0001678c, 0x00800700}, | ||
111 | {0x00016790, 0x00800700}, | ||
112 | {0x00016794, 0x00000000}, | ||
113 | {0x00016798, 0x00000000}, | ||
114 | {0x0001679c, 0x00000000}, | ||
115 | {0x000167a0, 0x00000001}, | ||
116 | {0x000167a4, 0x00000001}, | ||
117 | {0x000167a8, 0x00000000}, | ||
118 | {0x000167ac, 0x00000000}, | ||
119 | {0x000167b0, 0x00000000}, | ||
120 | {0x000167b4, 0x00000000}, | ||
121 | {0x000167b8, 0x00000000}, | ||
122 | {0x000167bc, 0x00000000}, | ||
123 | {0x000167c0, 0x000000a0}, | ||
124 | {0x000167c4, 0x000c0000}, | ||
125 | {0x000167c8, 0x14021402}, | ||
126 | {0x000167cc, 0x00001402}, | ||
127 | {0x000167d0, 0x00000000}, | ||
128 | {0x000167d4, 0x00000000}, | ||
129 | {0x00016800, 0x36db2db6}, | ||
130 | {0x00016804, 0x6db6db40}, | ||
131 | {0x00016808, 0x73f00000}, | ||
132 | {0x0001680c, 0x00000000}, | ||
133 | {0x00016840, 0x7f80fff8}, | ||
134 | {0x0001684c, 0x76d005b5}, | ||
135 | {0x00016850, 0x556cf031}, | ||
136 | {0x00016854, 0x13449440}, | ||
137 | {0x00016858, 0x0c51c92c}, | ||
138 | {0x0001685c, 0x3db7fffc}, | ||
139 | {0x00016860, 0xfffffffc}, | ||
140 | {0x00016864, 0x000f0278}, | ||
141 | {0x0001686c, 0x6db60000}, | ||
142 | {0x00016900, 0x3fffbe01}, | ||
143 | {0x00016904, 0xfff80000}, | ||
144 | {0x00016908, 0x00080010}, | ||
145 | {0x00016944, 0x02084080}, | ||
146 | {0x00016948, 0x00000000}, | ||
147 | {0x00016b80, 0x00000000}, | ||
148 | {0x00016b84, 0x00000000}, | ||
149 | {0x00016b88, 0x00800700}, | ||
150 | {0x00016b8c, 0x00800700}, | ||
151 | {0x00016b90, 0x00800700}, | ||
152 | {0x00016b94, 0x00000000}, | ||
153 | {0x00016b98, 0x00000000}, | ||
154 | {0x00016b9c, 0x00000000}, | ||
155 | {0x00016ba0, 0x00000001}, | ||
156 | {0x00016ba4, 0x00000001}, | ||
157 | {0x00016ba8, 0x00000000}, | ||
158 | {0x00016bac, 0x00000000}, | ||
159 | {0x00016bb0, 0x00000000}, | ||
160 | {0x00016bb4, 0x00000000}, | ||
161 | {0x00016bb8, 0x00000000}, | ||
162 | {0x00016bbc, 0x00000000}, | ||
163 | {0x00016bc0, 0x000000a0}, | ||
164 | {0x00016bc4, 0x000c0000}, | ||
165 | {0x00016bc8, 0x14021402}, | ||
166 | {0x00016bcc, 0x00001402}, | ||
167 | {0x00016bd0, 0x00000000}, | ||
168 | {0x00016bd4, 0x00000000}, | ||
169 | }; | ||
28 | 170 | ||
29 | #define ar9580_1p0_mac_postamble ar9300_2p2_mac_postamble | 171 | #define ar9580_1p0_mac_postamble ar9300_2p2_mac_postamble |
30 | 172 | ||
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index bfa0b1518da1..abe8bd6b972d 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -28,7 +28,6 @@ | |||
28 | #include "debug.h" | 28 | #include "debug.h" |
29 | #include "mci.h" | 29 | #include "mci.h" |
30 | #include "dfs.h" | 30 | #include "dfs.h" |
31 | #include "spectral.h" | ||
32 | 31 | ||
33 | struct ath_node; | 32 | struct ath_node; |
34 | struct ath_vif; | 33 | struct ath_vif; |
@@ -294,7 +293,6 @@ struct ath_tx_control { | |||
294 | * (axq_qnum). | 293 | * (axq_qnum). |
295 | */ | 294 | */ |
296 | struct ath_tx { | 295 | struct ath_tx { |
297 | u16 seq_no; | ||
298 | u32 txqsetup; | 296 | u32 txqsetup; |
299 | spinlock_t txbuflock; | 297 | spinlock_t txbuflock; |
300 | struct list_head txbuf; | 298 | struct list_head txbuf; |
@@ -346,7 +344,9 @@ struct ath_chanctx { | |||
346 | u64 tsf_val; | 344 | u64 tsf_val; |
347 | u32 last_beacon; | 345 | u32 last_beacon; |
348 | 346 | ||
347 | int flush_timeout; | ||
349 | u16 txpower; | 348 | u16 txpower; |
349 | u16 cur_txpower; | ||
350 | bool offchannel; | 350 | bool offchannel; |
351 | bool stopped; | 351 | bool stopped; |
352 | bool active; | 352 | bool active; |
@@ -363,7 +363,7 @@ enum ath_chanctx_event { | |||
363 | ATH_CHANCTX_EVENT_BEACON_SENT, | 363 | ATH_CHANCTX_EVENT_BEACON_SENT, |
364 | ATH_CHANCTX_EVENT_TSF_TIMER, | 364 | ATH_CHANCTX_EVENT_TSF_TIMER, |
365 | ATH_CHANCTX_EVENT_BEACON_RECEIVED, | 365 | ATH_CHANCTX_EVENT_BEACON_RECEIVED, |
366 | ATH_CHANCTX_EVENT_ASSOC, | 366 | ATH_CHANCTX_EVENT_AUTHORIZED, |
367 | ATH_CHANCTX_EVENT_SWITCH, | 367 | ATH_CHANCTX_EVENT_SWITCH, |
368 | ATH_CHANCTX_EVENT_ASSIGN, | 368 | ATH_CHANCTX_EVENT_ASSIGN, |
369 | ATH_CHANCTX_EVENT_UNASSIGN, | 369 | ATH_CHANCTX_EVENT_UNASSIGN, |
@@ -381,10 +381,12 @@ enum ath_chanctx_state { | |||
381 | 381 | ||
382 | struct ath_chanctx_sched { | 382 | struct ath_chanctx_sched { |
383 | bool beacon_pending; | 383 | bool beacon_pending; |
384 | bool beacon_adjust; | ||
384 | bool offchannel_pending; | 385 | bool offchannel_pending; |
385 | bool wait_switch; | 386 | bool wait_switch; |
386 | bool force_noa_update; | 387 | bool force_noa_update; |
387 | bool extend_absence; | 388 | bool extend_absence; |
389 | bool mgd_prepare_tx; | ||
388 | enum ath_chanctx_state state; | 390 | enum ath_chanctx_state state; |
389 | u8 beacon_miss; | 391 | u8 beacon_miss; |
390 | 392 | ||
@@ -469,6 +471,7 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force); | |||
469 | void ath_offchannel_next(struct ath_softc *sc); | 471 | void ath_offchannel_next(struct ath_softc *sc); |
470 | void ath_scan_complete(struct ath_softc *sc, bool abort); | 472 | void ath_scan_complete(struct ath_softc *sc, bool abort); |
471 | void ath_roc_complete(struct ath_softc *sc, bool abort); | 473 | void ath_roc_complete(struct ath_softc *sc, bool abort); |
474 | struct ath_chanctx* ath_is_go_chanctx_present(struct ath_softc *sc); | ||
472 | 475 | ||
473 | #else | 476 | #else |
474 | 477 | ||
@@ -541,7 +544,6 @@ static inline void ath_chanctx_check_active(struct ath_softc *sc, | |||
541 | 544 | ||
542 | #endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */ | 545 | #endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */ |
543 | 546 | ||
544 | int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan); | ||
545 | void ath_startrecv(struct ath_softc *sc); | 547 | void ath_startrecv(struct ath_softc *sc); |
546 | bool ath_stoprecv(struct ath_softc *sc); | 548 | bool ath_stoprecv(struct ath_softc *sc); |
547 | u32 ath_calcrxfilter(struct ath_softc *sc); | 549 | u32 ath_calcrxfilter(struct ath_softc *sc); |
@@ -563,6 +565,7 @@ int ath_tx_init(struct ath_softc *sc, int nbufs); | |||
563 | int ath_txq_update(struct ath_softc *sc, int qnum, | 565 | int ath_txq_update(struct ath_softc *sc, int qnum, |
564 | struct ath9k_tx_queue_info *q); | 566 | struct ath9k_tx_queue_info *q); |
565 | void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop); | 567 | void ath_update_max_aggr_framelen(struct ath_softc *sc, int queue, int txop); |
568 | void ath_assign_seq(struct ath_common *common, struct sk_buff *skb); | ||
566 | int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | 569 | int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, |
567 | struct ath_tx_control *txctl); | 570 | struct ath_tx_control *txctl); |
568 | void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 571 | void ath_tx_cabq(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
@@ -592,8 +595,10 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw, | |||
592 | struct ath_vif { | 595 | struct ath_vif { |
593 | struct list_head list; | 596 | struct list_head list; |
594 | 597 | ||
598 | u16 seq_no; | ||
599 | |||
595 | /* BSS info */ | 600 | /* BSS info */ |
596 | u8 bssid[ETH_ALEN]; | 601 | u8 bssid[ETH_ALEN] __aligned(2); |
597 | u16 aid; | 602 | u16 aid; |
598 | bool assoc; | 603 | bool assoc; |
599 | 604 | ||
@@ -616,6 +621,7 @@ struct ath_vif { | |||
616 | u32 noa_start; | 621 | u32 noa_start; |
617 | u32 noa_duration; | 622 | u32 noa_duration; |
618 | bool periodic_noa; | 623 | bool periodic_noa; |
624 | bool oneshot_noa; | ||
619 | }; | 625 | }; |
620 | 626 | ||
621 | struct ath9k_vif_iter_data { | 627 | struct ath9k_vif_iter_data { |
@@ -713,7 +719,8 @@ int ath_update_survey_stats(struct ath_softc *sc); | |||
713 | void ath_update_survey_nf(struct ath_softc *sc, int channel); | 719 | void ath_update_survey_nf(struct ath_softc *sc, int channel); |
714 | void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type); | 720 | void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type); |
715 | void ath_ps_full_sleep(unsigned long data); | 721 | void ath_ps_full_sleep(unsigned long data); |
716 | void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop); | 722 | void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop, |
723 | bool sw_pending, bool timeout_override); | ||
717 | 724 | ||
718 | /**********/ | 725 | /**********/ |
719 | /* BTCOEX */ | 726 | /* BTCOEX */ |
@@ -925,6 +932,7 @@ void ath_ant_comb_scan(struct ath_softc *sc, struct ath_rx_status *rs); | |||
925 | #define ATH9K_PCI_AR9565_2ANT 0x0100 | 932 | #define ATH9K_PCI_AR9565_2ANT 0x0100 |
926 | #define ATH9K_PCI_NO_PLL_PWRSAVE 0x0200 | 933 | #define ATH9K_PCI_NO_PLL_PWRSAVE 0x0200 |
927 | #define ATH9K_PCI_KILLER 0x0400 | 934 | #define ATH9K_PCI_KILLER 0x0400 |
935 | #define ATH9K_PCI_LED_ACT_HI 0x0800 | ||
928 | 936 | ||
929 | /* | 937 | /* |
930 | * Default cache line size, in bytes. | 938 | * Default cache line size, in bytes. |
@@ -973,6 +981,7 @@ struct ath_softc { | |||
973 | struct ath_chanctx_sched sched; | 981 | struct ath_chanctx_sched sched; |
974 | struct ath_offchannel offchannel; | 982 | struct ath_offchannel offchannel; |
975 | struct ath_chanctx *next_chan; | 983 | struct ath_chanctx *next_chan; |
984 | struct completion go_beacon; | ||
976 | #endif | 985 | #endif |
977 | 986 | ||
978 | unsigned long driver_data; | 987 | unsigned long driver_data; |
@@ -980,7 +989,6 @@ struct ath_softc { | |||
980 | u8 gtt_cnt; | 989 | u8 gtt_cnt; |
981 | u32 intrstatus; | 990 | u32 intrstatus; |
982 | u16 ps_flags; /* PS_* */ | 991 | u16 ps_flags; /* PS_* */ |
983 | u16 curtxpow; | ||
984 | bool ps_enabled; | 992 | bool ps_enabled; |
985 | bool ps_idle; | 993 | bool ps_idle; |
986 | short nbcnvifs; | 994 | short nbcnvifs; |
@@ -1021,10 +1029,8 @@ struct ath_softc { | |||
1021 | struct dfs_pattern_detector *dfs_detector; | 1029 | struct dfs_pattern_detector *dfs_detector; |
1022 | u64 dfs_prev_pulse_ts; | 1030 | u64 dfs_prev_pulse_ts; |
1023 | u32 wow_enabled; | 1031 | u32 wow_enabled; |
1024 | /* relay(fs) channel for spectral scan */ | 1032 | |
1025 | struct rchan *rfs_chan_spec_scan; | 1033 | struct ath_spec_scan_priv spec_priv; |
1026 | enum spectral_mode spectral_mode; | ||
1027 | struct ath_spec_scan spec_config; | ||
1028 | 1034 | ||
1029 | struct ieee80211_vif *tx99_vif; | 1035 | struct ieee80211_vif *tx99_vif; |
1030 | struct sk_buff *tx99_skb; | 1036 | struct sk_buff *tx99_skb; |
@@ -1067,7 +1073,7 @@ void ath9k_tasklet(unsigned long data); | |||
1067 | int ath_cabq_update(struct ath_softc *); | 1073 | int ath_cabq_update(struct ath_softc *); |
1068 | u8 ath9k_parse_mpdudensity(u8 mpdudensity); | 1074 | u8 ath9k_parse_mpdudensity(u8 mpdudensity); |
1069 | irqreturn_t ath_isr(int irq, void *dev); | 1075 | irqreturn_t ath_isr(int irq, void *dev); |
1070 | int ath_reset(struct ath_softc *sc); | 1076 | int ath_reset(struct ath_softc *sc, struct ath9k_channel *hchan); |
1071 | void ath_cancel_work(struct ath_softc *sc); | 1077 | void ath_cancel_work(struct ath_softc *sc); |
1072 | void ath_restart_work(struct ath_softc *sc); | 1078 | void ath_restart_work(struct ath_softc *sc); |
1073 | int ath9k_init_device(u16 devid, struct ath_softc *sc, | 1079 | int ath9k_init_device(u16 devid, struct ath_softc *sc, |
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c index a6af855ef6ed..ecb783beeec2 100644 --- a/drivers/net/wireless/ath/ath9k/beacon.c +++ b/drivers/net/wireless/ath/ath9k/beacon.c | |||
@@ -144,16 +144,8 @@ static struct ath_buf *ath9k_beacon_generate(struct ieee80211_hw *hw, | |||
144 | mgmt_hdr->u.beacon.timestamp = avp->tsf_adjust; | 144 | mgmt_hdr->u.beacon.timestamp = avp->tsf_adjust; |
145 | 145 | ||
146 | info = IEEE80211_SKB_CB(skb); | 146 | info = IEEE80211_SKB_CB(skb); |
147 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | 147 | |
148 | /* | 148 | ath_assign_seq(common, skb); |
149 | * TODO: make sure the seq# gets assigned properly (vs. other | ||
150 | * TX frames) | ||
151 | */ | ||
152 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; | ||
153 | sc->tx.seq_no += 0x10; | ||
154 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
155 | hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); | ||
156 | } | ||
157 | 149 | ||
158 | if (vif->p2p) | 150 | if (vif->p2p) |
159 | ath9k_beacon_add_noa(sc, avp, skb); | 151 | ath9k_beacon_add_noa(sc, avp, skb); |
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c index 278365b8a895..e200a6e3aca5 100644 --- a/drivers/net/wireless/ath/ath9k/calib.c +++ b/drivers/net/wireless/ath/ath9k/calib.c | |||
@@ -234,7 +234,7 @@ void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update) | |||
234 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); | 234 | REG_SET_BIT(ah, AR_PHY_AGC_CONTROL, AR_PHY_AGC_CONTROL_NF); |
235 | } | 235 | } |
236 | 236 | ||
237 | void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | 237 | int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) |
238 | { | 238 | { |
239 | struct ath9k_nfcal_hist *h = NULL; | 239 | struct ath9k_nfcal_hist *h = NULL; |
240 | unsigned i, j; | 240 | unsigned i, j; |
@@ -301,7 +301,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
301 | ath_dbg(common, ANY, | 301 | ath_dbg(common, ANY, |
302 | "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n", | 302 | "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n", |
303 | REG_READ(ah, AR_PHY_AGC_CONTROL)); | 303 | REG_READ(ah, AR_PHY_AGC_CONTROL)); |
304 | return; | 304 | return -ETIMEDOUT; |
305 | } | 305 | } |
306 | 306 | ||
307 | /* | 307 | /* |
@@ -322,6 +322,8 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan) | |||
322 | } | 322 | } |
323 | } | 323 | } |
324 | REGWRITE_BUFFER_FLUSH(ah); | 324 | REGWRITE_BUFFER_FLUSH(ah); |
325 | |||
326 | return 0; | ||
325 | } | 327 | } |
326 | 328 | ||
327 | 329 | ||
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h index b8ed95e9a335..87badf4bb8a4 100644 --- a/drivers/net/wireless/ath/ath9k/calib.h +++ b/drivers/net/wireless/ath/ath9k/calib.h | |||
@@ -109,7 +109,7 @@ struct ath9k_pacal_info{ | |||
109 | 109 | ||
110 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah); | 110 | bool ath9k_hw_reset_calvalid(struct ath_hw *ah); |
111 | void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update); | 111 | void ath9k_hw_start_nfcal(struct ath_hw *ah, bool update); |
112 | void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); | 112 | int ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan); |
113 | bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); | 113 | bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan); |
114 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, | 114 | void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah, |
115 | struct ath9k_channel *chan); | 115 | struct ath9k_channel *chan); |
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 945c89826b14..206665059d66 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c | |||
@@ -66,7 +66,7 @@ static int ath_set_channel(struct ath_softc *sc) | |||
66 | } | 66 | } |
67 | 67 | ||
68 | hchan = &sc->sc_ah->channels[pos]; | 68 | hchan = &sc->sc_ah->channels[pos]; |
69 | r = ath_reset_internal(sc, hchan); | 69 | r = ath_reset(sc, hchan); |
70 | if (r) | 70 | if (r) |
71 | return r; | 71 | return r; |
72 | 72 | ||
@@ -92,8 +92,8 @@ static int ath_set_channel(struct ath_softc *sc) | |||
92 | } else { | 92 | } else { |
93 | /* perform spectral scan if requested. */ | 93 | /* perform spectral scan if requested. */ |
94 | if (test_bit(ATH_OP_SCANNING, &common->op_flags) && | 94 | if (test_bit(ATH_OP_SCANNING, &common->op_flags) && |
95 | sc->spectral_mode == SPECTRAL_CHANSCAN) | 95 | sc->spec_priv.spectral_mode == SPECTRAL_CHANSCAN) |
96 | ath9k_spectral_scan_trigger(hw); | 96 | ath9k_cmn_spectral_scan_trigger(common, &sc->spec_priv); |
97 | } | 97 | } |
98 | 98 | ||
99 | return 0; | 99 | return 0; |
@@ -117,6 +117,7 @@ void ath_chanctx_init(struct ath_softc *sc) | |||
117 | cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20); | 117 | cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20); |
118 | INIT_LIST_HEAD(&ctx->vifs); | 118 | INIT_LIST_HEAD(&ctx->vifs); |
119 | ctx->txpower = ATH_TXPOWER_MAX; | 119 | ctx->txpower = ATH_TXPOWER_MAX; |
120 | ctx->flush_timeout = HZ / 5; /* 200ms */ | ||
120 | for (j = 0; j < ARRAY_SIZE(ctx->acq); j++) | 121 | for (j = 0; j < ARRAY_SIZE(ctx->acq); j++) |
121 | INIT_LIST_HEAD(&ctx->acq[j]); | 122 | INIT_LIST_HEAD(&ctx->acq[j]); |
122 | } | 123 | } |
@@ -145,6 +146,36 @@ void ath_chanctx_set_channel(struct ath_softc *sc, struct ath_chanctx *ctx, | |||
145 | 146 | ||
146 | #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT | 147 | #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT |
147 | 148 | ||
149 | /*************/ | ||
150 | /* Utilities */ | ||
151 | /*************/ | ||
152 | |||
153 | struct ath_chanctx* ath_is_go_chanctx_present(struct ath_softc *sc) | ||
154 | { | ||
155 | struct ath_chanctx *ctx; | ||
156 | struct ath_vif *avp; | ||
157 | struct ieee80211_vif *vif; | ||
158 | |||
159 | spin_lock_bh(&sc->chan_lock); | ||
160 | |||
161 | ath_for_each_chanctx(sc, ctx) { | ||
162 | if (!ctx->active) | ||
163 | continue; | ||
164 | |||
165 | list_for_each_entry(avp, &ctx->vifs, list) { | ||
166 | vif = avp->vif; | ||
167 | |||
168 | if (ieee80211_vif_type_p2p(vif) == NL80211_IFTYPE_P2P_GO) { | ||
169 | spin_unlock_bh(&sc->chan_lock); | ||
170 | return ctx; | ||
171 | } | ||
172 | } | ||
173 | } | ||
174 | |||
175 | spin_unlock_bh(&sc->chan_lock); | ||
176 | return NULL; | ||
177 | } | ||
178 | |||
148 | /**********************************************************/ | 179 | /**********************************************************/ |
149 | /* Functions to handle the channel context state machine. */ | 180 | /* Functions to handle the channel context state machine. */ |
150 | /**********************************************************/ | 181 | /**********************************************************/ |
@@ -171,7 +202,7 @@ static const char *chanctx_event_string(enum ath_chanctx_event ev) | |||
171 | case_rtn_string(ATH_CHANCTX_EVENT_BEACON_SENT); | 202 | case_rtn_string(ATH_CHANCTX_EVENT_BEACON_SENT); |
172 | case_rtn_string(ATH_CHANCTX_EVENT_TSF_TIMER); | 203 | case_rtn_string(ATH_CHANCTX_EVENT_TSF_TIMER); |
173 | case_rtn_string(ATH_CHANCTX_EVENT_BEACON_RECEIVED); | 204 | case_rtn_string(ATH_CHANCTX_EVENT_BEACON_RECEIVED); |
174 | case_rtn_string(ATH_CHANCTX_EVENT_ASSOC); | 205 | case_rtn_string(ATH_CHANCTX_EVENT_AUTHORIZED); |
175 | case_rtn_string(ATH_CHANCTX_EVENT_SWITCH); | 206 | case_rtn_string(ATH_CHANCTX_EVENT_SWITCH); |
176 | case_rtn_string(ATH_CHANCTX_EVENT_ASSIGN); | 207 | case_rtn_string(ATH_CHANCTX_EVENT_ASSIGN); |
177 | case_rtn_string(ATH_CHANCTX_EVENT_UNASSIGN); | 208 | case_rtn_string(ATH_CHANCTX_EVENT_UNASSIGN); |
@@ -198,6 +229,7 @@ static const char *chanctx_state_string(enum ath_chanctx_state state) | |||
198 | void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx) | 229 | void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx) |
199 | { | 230 | { |
200 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 231 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
232 | struct ath_chanctx *ictx; | ||
201 | struct ath_vif *avp; | 233 | struct ath_vif *avp; |
202 | bool active = false; | 234 | bool active = false; |
203 | u8 n_active = 0; | 235 | u8 n_active = 0; |
@@ -205,6 +237,28 @@ void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx) | |||
205 | if (!ctx) | 237 | if (!ctx) |
206 | return; | 238 | return; |
207 | 239 | ||
240 | if (ctx == &sc->offchannel.chan) { | ||
241 | spin_lock_bh(&sc->chan_lock); | ||
242 | |||
243 | if (likely(sc->sched.channel_switch_time)) | ||
244 | ctx->flush_timeout = | ||
245 | usecs_to_jiffies(sc->sched.channel_switch_time); | ||
246 | else | ||
247 | ctx->flush_timeout = | ||
248 | msecs_to_jiffies(10); | ||
249 | |||
250 | spin_unlock_bh(&sc->chan_lock); | ||
251 | |||
252 | /* | ||
253 | * There is no need to iterate over the | ||
254 | * active/assigned channel contexts if | ||
255 | * the current context is offchannel. | ||
256 | */ | ||
257 | return; | ||
258 | } | ||
259 | |||
260 | ictx = ctx; | ||
261 | |||
208 | list_for_each_entry(avp, &ctx->vifs, list) { | 262 | list_for_each_entry(avp, &ctx->vifs, list) { |
209 | struct ieee80211_vif *vif = avp->vif; | 263 | struct ieee80211_vif *vif = avp->vif; |
210 | 264 | ||
@@ -227,12 +281,23 @@ void ath_chanctx_check_active(struct ath_softc *sc, struct ath_chanctx *ctx) | |||
227 | n_active++; | 281 | n_active++; |
228 | } | 282 | } |
229 | 283 | ||
284 | spin_lock_bh(&sc->chan_lock); | ||
285 | |||
230 | if (n_active <= 1) { | 286 | if (n_active <= 1) { |
287 | ictx->flush_timeout = HZ / 5; | ||
231 | clear_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags); | 288 | clear_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags); |
289 | spin_unlock_bh(&sc->chan_lock); | ||
232 | return; | 290 | return; |
233 | } | 291 | } |
234 | if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) | 292 | |
293 | ictx->flush_timeout = usecs_to_jiffies(sc->sched.channel_switch_time); | ||
294 | |||
295 | if (test_and_set_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) { | ||
296 | spin_unlock_bh(&sc->chan_lock); | ||
235 | return; | 297 | return; |
298 | } | ||
299 | |||
300 | spin_unlock_bh(&sc->chan_lock); | ||
236 | 301 | ||
237 | if (ath9k_is_chanctx_enabled()) { | 302 | if (ath9k_is_chanctx_enabled()) { |
238 | ath_chanctx_event(sc, NULL, | 303 | ath_chanctx_event(sc, NULL, |
@@ -301,6 +366,111 @@ static void ath_chanctx_setup_timer(struct ath_softc *sc, u32 tsf_time) | |||
301 | "Setup chanctx timer with timeout: %d ms\n", jiffies_to_msecs(tsf_time)); | 366 | "Setup chanctx timer with timeout: %d ms\n", jiffies_to_msecs(tsf_time)); |
302 | } | 367 | } |
303 | 368 | ||
369 | static void ath_chanctx_handle_bmiss(struct ath_softc *sc, | ||
370 | struct ath_chanctx *ctx, | ||
371 | struct ath_vif *avp) | ||
372 | { | ||
373 | /* | ||
374 | * Clear the extend_absence flag if it had been | ||
375 | * set during the previous beacon transmission, | ||
376 | * since we need to revert to the normal NoA | ||
377 | * schedule. | ||
378 | */ | ||
379 | if (ctx->active && sc->sched.extend_absence) { | ||
380 | avp->noa_duration = 0; | ||
381 | sc->sched.extend_absence = false; | ||
382 | } | ||
383 | |||
384 | /* If at least two consecutive beacons were missed on the STA | ||
385 | * chanctx, stay on the STA channel for one extra beacon period, | ||
386 | * to resync the timer properly. | ||
387 | */ | ||
388 | if (ctx->active && sc->sched.beacon_miss >= 2) { | ||
389 | avp->noa_duration = 0; | ||
390 | sc->sched.extend_absence = true; | ||
391 | } | ||
392 | } | ||
393 | |||
394 | static void ath_chanctx_offchannel_noa(struct ath_softc *sc, | ||
395 | struct ath_chanctx *ctx, | ||
396 | struct ath_vif *avp, | ||
397 | u32 tsf_time) | ||
398 | { | ||
399 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
400 | |||
401 | avp->noa_index++; | ||
402 | avp->offchannel_start = tsf_time; | ||
403 | avp->offchannel_duration = sc->sched.offchannel_duration; | ||
404 | |||
405 | ath_dbg(common, CHAN_CTX, | ||
406 | "offchannel noa_duration: %d, noa_start: %d, noa_index: %d\n", | ||
407 | avp->offchannel_duration, | ||
408 | avp->offchannel_start, | ||
409 | avp->noa_index); | ||
410 | |||
411 | /* | ||
412 | * When multiple contexts are active, the NoA | ||
413 | * has to be recalculated and advertised after | ||
414 | * an offchannel operation. | ||
415 | */ | ||
416 | if (ctx->active && avp->noa_duration) | ||
417 | avp->noa_duration = 0; | ||
418 | } | ||
419 | |||
420 | static void ath_chanctx_set_periodic_noa(struct ath_softc *sc, | ||
421 | struct ath_vif *avp, | ||
422 | struct ath_beacon_config *cur_conf, | ||
423 | u32 tsf_time, | ||
424 | u32 beacon_int) | ||
425 | { | ||
426 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
427 | |||
428 | avp->noa_index++; | ||
429 | avp->noa_start = tsf_time; | ||
430 | |||
431 | if (sc->sched.extend_absence) | ||
432 | avp->noa_duration = (3 * beacon_int / 2) + | ||
433 | sc->sched.channel_switch_time; | ||
434 | else | ||
435 | avp->noa_duration = | ||
436 | TU_TO_USEC(cur_conf->beacon_interval) / 2 + | ||
437 | sc->sched.channel_switch_time; | ||
438 | |||
439 | if (test_bit(ATH_OP_SCANNING, &common->op_flags) || | ||
440 | sc->sched.extend_absence) | ||
441 | avp->periodic_noa = false; | ||
442 | else | ||
443 | avp->periodic_noa = true; | ||
444 | |||
445 | ath_dbg(common, CHAN_CTX, | ||
446 | "noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n", | ||
447 | avp->noa_duration, | ||
448 | avp->noa_start, | ||
449 | avp->noa_index, | ||
450 | avp->periodic_noa); | ||
451 | } | ||
452 | |||
453 | static void ath_chanctx_set_oneshot_noa(struct ath_softc *sc, | ||
454 | struct ath_vif *avp, | ||
455 | u32 tsf_time, | ||
456 | u32 duration) | ||
457 | { | ||
458 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
459 | |||
460 | avp->noa_index++; | ||
461 | avp->noa_start = tsf_time; | ||
462 | avp->periodic_noa = false; | ||
463 | avp->oneshot_noa = true; | ||
464 | avp->noa_duration = duration + sc->sched.channel_switch_time; | ||
465 | |||
466 | ath_dbg(common, CHAN_CTX, | ||
467 | "oneshot noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n", | ||
468 | avp->noa_duration, | ||
469 | avp->noa_start, | ||
470 | avp->noa_index, | ||
471 | avp->periodic_noa); | ||
472 | } | ||
473 | |||
304 | void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, | 474 | void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, |
305 | enum ath_chanctx_event ev) | 475 | enum ath_chanctx_event ev) |
306 | { | 476 | { |
@@ -327,6 +497,14 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
327 | if (avp->offchannel_duration) | 497 | if (avp->offchannel_duration) |
328 | avp->offchannel_duration = 0; | 498 | avp->offchannel_duration = 0; |
329 | 499 | ||
500 | if (avp->oneshot_noa) { | ||
501 | avp->noa_duration = 0; | ||
502 | avp->oneshot_noa = false; | ||
503 | |||
504 | ath_dbg(common, CHAN_CTX, | ||
505 | "Clearing oneshot NoA\n"); | ||
506 | } | ||
507 | |||
330 | if (avp->chanctx != sc->cur_chan) { | 508 | if (avp->chanctx != sc->cur_chan) { |
331 | ath_dbg(common, CHAN_CTX, | 509 | ath_dbg(common, CHAN_CTX, |
332 | "Contexts differ, not preparing beacon\n"); | 510 | "Contexts differ, not preparing beacon\n"); |
@@ -356,6 +534,24 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
356 | "Move chanctx state from WAIT_FOR_TIMER to WAIT_FOR_BEACON\n"); | 534 | "Move chanctx state from WAIT_FOR_TIMER to WAIT_FOR_BEACON\n"); |
357 | } | 535 | } |
358 | 536 | ||
537 | if (sc->sched.mgd_prepare_tx) | ||
538 | sc->sched.state = ATH_CHANCTX_STATE_WAIT_FOR_BEACON; | ||
539 | |||
540 | /* | ||
541 | * When a context becomes inactive, for example, | ||
542 | * disassociation of a station context, the NoA | ||
543 | * attribute needs to be removed from subsequent | ||
544 | * beacons. | ||
545 | */ | ||
546 | if (!ctx->active && avp->noa_duration && | ||
547 | sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON) { | ||
548 | avp->noa_duration = 0; | ||
549 | avp->periodic_noa = false; | ||
550 | |||
551 | ath_dbg(common, CHAN_CTX, | ||
552 | "Clearing NoA schedule\n"); | ||
553 | } | ||
554 | |||
359 | if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON) | 555 | if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON) |
360 | break; | 556 | break; |
361 | 557 | ||
@@ -378,45 +574,22 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
378 | * values and increment the index. | 574 | * values and increment the index. |
379 | */ | 575 | */ |
380 | if (sc->next_chan == &sc->offchannel.chan) { | 576 | if (sc->next_chan == &sc->offchannel.chan) { |
381 | avp->noa_index++; | 577 | ath_chanctx_offchannel_noa(sc, ctx, avp, tsf_time); |
382 | avp->offchannel_start = tsf_time; | ||
383 | avp->offchannel_duration = sc->sched.offchannel_duration; | ||
384 | |||
385 | ath_dbg(common, CHAN_CTX, | ||
386 | "offchannel noa_duration: %d, noa_start: %d, noa_index: %d\n", | ||
387 | avp->offchannel_duration, | ||
388 | avp->offchannel_start, | ||
389 | avp->noa_index); | ||
390 | |||
391 | /* | ||
392 | * When multiple contexts are active, the NoA | ||
393 | * has to be recalculated and advertised after | ||
394 | * an offchannel operation. | ||
395 | */ | ||
396 | if (ctx->active && avp->noa_duration) | ||
397 | avp->noa_duration = 0; | ||
398 | |||
399 | break; | 578 | break; |
400 | } | 579 | } |
401 | 580 | ||
402 | /* | 581 | ath_chanctx_handle_bmiss(sc, ctx, avp); |
403 | * Clear the extend_absence flag if it had been | ||
404 | * set during the previous beacon transmission, | ||
405 | * since we need to revert to the normal NoA | ||
406 | * schedule. | ||
407 | */ | ||
408 | if (ctx->active && sc->sched.extend_absence) { | ||
409 | avp->noa_duration = 0; | ||
410 | sc->sched.extend_absence = false; | ||
411 | } | ||
412 | 582 | ||
413 | /* If at least two consecutive beacons were missed on the STA | 583 | /* |
414 | * chanctx, stay on the STA channel for one extra beacon period, | 584 | * If a mgd_prepare_tx() has been called by mac80211, |
415 | * to resync the timer properly. | 585 | * a one-shot NoA needs to be sent. This can happen |
586 | * with one or more active channel contexts - in both | ||
587 | * cases, a new NoA schedule has to be advertised. | ||
416 | */ | 588 | */ |
417 | if (ctx->active && sc->sched.beacon_miss >= 2) { | 589 | if (sc->sched.mgd_prepare_tx) { |
418 | avp->noa_duration = 0; | 590 | ath_chanctx_set_oneshot_noa(sc, avp, tsf_time, |
419 | sc->sched.extend_absence = true; | 591 | jiffies_to_usecs(HZ / 5)); |
592 | break; | ||
420 | } | 593 | } |
421 | 594 | ||
422 | /* Prevent wrap-around issues */ | 595 | /* Prevent wrap-around issues */ |
@@ -429,31 +602,9 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
429 | * announcement. | 602 | * announcement. |
430 | */ | 603 | */ |
431 | if (ctx->active && | 604 | if (ctx->active && |
432 | (!avp->noa_duration || sc->sched.force_noa_update)) { | 605 | (!avp->noa_duration || sc->sched.force_noa_update)) |
433 | avp->noa_index++; | 606 | ath_chanctx_set_periodic_noa(sc, avp, cur_conf, |
434 | avp->noa_start = tsf_time; | 607 | tsf_time, beacon_int); |
435 | |||
436 | if (sc->sched.extend_absence) | ||
437 | avp->noa_duration = (3 * beacon_int / 2) + | ||
438 | sc->sched.channel_switch_time; | ||
439 | else | ||
440 | avp->noa_duration = | ||
441 | TU_TO_USEC(cur_conf->beacon_interval) / 2 + | ||
442 | sc->sched.channel_switch_time; | ||
443 | |||
444 | if (test_bit(ATH_OP_SCANNING, &common->op_flags) || | ||
445 | sc->sched.extend_absence) | ||
446 | avp->periodic_noa = false; | ||
447 | else | ||
448 | avp->periodic_noa = true; | ||
449 | |||
450 | ath_dbg(common, CHAN_CTX, | ||
451 | "noa_duration: %d, noa_start: %d, noa_index: %d, periodic: %d\n", | ||
452 | avp->noa_duration, | ||
453 | avp->noa_start, | ||
454 | avp->noa_index, | ||
455 | avp->periodic_noa); | ||
456 | } | ||
457 | 608 | ||
458 | if (ctx->active && sc->sched.force_noa_update) | 609 | if (ctx->active && sc->sched.force_noa_update) |
459 | sc->sched.force_noa_update = false; | 610 | sc->sched.force_noa_update = false; |
@@ -467,6 +618,15 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
467 | } | 618 | } |
468 | 619 | ||
469 | sc->sched.beacon_pending = false; | 620 | sc->sched.beacon_pending = false; |
621 | |||
622 | if (sc->sched.mgd_prepare_tx) { | ||
623 | sc->sched.mgd_prepare_tx = false; | ||
624 | complete(&sc->go_beacon); | ||
625 | ath_dbg(common, CHAN_CTX, | ||
626 | "Beacon sent, complete go_beacon\n"); | ||
627 | break; | ||
628 | } | ||
629 | |||
470 | if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON) | 630 | if (sc->sched.state != ATH_CHANCTX_STATE_WAIT_FOR_BEACON) |
471 | break; | 631 | break; |
472 | 632 | ||
@@ -495,10 +655,16 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
495 | sc->cur_chan == &sc->offchannel.chan) | 655 | sc->cur_chan == &sc->offchannel.chan) |
496 | break; | 656 | break; |
497 | 657 | ||
498 | ath_chanctx_adjust_tbtt_delta(sc); | ||
499 | sc->sched.beacon_pending = false; | 658 | sc->sched.beacon_pending = false; |
500 | sc->sched.beacon_miss = 0; | 659 | sc->sched.beacon_miss = 0; |
501 | 660 | ||
661 | if (sc->sched.state == ATH_CHANCTX_STATE_FORCE_ACTIVE || | ||
662 | !sc->sched.beacon_adjust || | ||
663 | !sc->cur_chan->tsf_val) | ||
664 | break; | ||
665 | |||
666 | ath_chanctx_adjust_tbtt_delta(sc); | ||
667 | |||
502 | /* TSF time might have been updated by the incoming beacon, | 668 | /* TSF time might have been updated by the incoming beacon, |
503 | * need update the channel switch timer to reflect the change. | 669 | * need update the channel switch timer to reflect the change. |
504 | */ | 670 | */ |
@@ -507,10 +673,10 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
507 | ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL); | 673 | ath9k_hw_get_tsf_offset(&sc->cur_chan->tsf_ts, NULL); |
508 | tsf_time += ath9k_hw_gettsf32(ah); | 674 | tsf_time += ath9k_hw_gettsf32(ah); |
509 | 675 | ||
510 | 676 | sc->sched.beacon_adjust = false; | |
511 | ath_chanctx_setup_timer(sc, tsf_time); | 677 | ath_chanctx_setup_timer(sc, tsf_time); |
512 | break; | 678 | break; |
513 | case ATH_CHANCTX_EVENT_ASSOC: | 679 | case ATH_CHANCTX_EVENT_AUTHORIZED: |
514 | if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE || | 680 | if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE || |
515 | avp->chanctx != sc->cur_chan) | 681 | avp->chanctx != sc->cur_chan) |
516 | break; | 682 | break; |
@@ -552,6 +718,7 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
552 | 718 | ||
553 | ath_chanctx_setup_timer(sc, tsf_time); | 719 | ath_chanctx_setup_timer(sc, tsf_time); |
554 | sc->sched.beacon_pending = true; | 720 | sc->sched.beacon_pending = true; |
721 | sc->sched.beacon_adjust = true; | ||
555 | break; | 722 | break; |
556 | case ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL: | 723 | case ATH_CHANCTX_EVENT_ENABLE_MULTICHANNEL: |
557 | if (sc->cur_chan == &sc->offchannel.chan || | 724 | if (sc->cur_chan == &sc->offchannel.chan || |
@@ -578,22 +745,6 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
578 | ieee80211_queue_work(sc->hw, &sc->chanctx_work); | 745 | ieee80211_queue_work(sc->hw, &sc->chanctx_work); |
579 | break; | 746 | break; |
580 | case ATH_CHANCTX_EVENT_ASSIGN: | 747 | case ATH_CHANCTX_EVENT_ASSIGN: |
581 | /* | ||
582 | * When adding a new channel context, check if a scan | ||
583 | * is in progress and abort it since the addition of | ||
584 | * a new channel context is usually followed by VIF | ||
585 | * assignment, in which case we have to start multi-channel | ||
586 | * operation. | ||
587 | */ | ||
588 | if (test_bit(ATH_OP_SCANNING, &common->op_flags)) { | ||
589 | ath_dbg(common, CHAN_CTX, | ||
590 | "Aborting HW scan to add new context\n"); | ||
591 | |||
592 | spin_unlock_bh(&sc->chan_lock); | ||
593 | del_timer_sync(&sc->offchannel.timer); | ||
594 | ath_scan_complete(sc, true); | ||
595 | spin_lock_bh(&sc->chan_lock); | ||
596 | } | ||
597 | break; | 748 | break; |
598 | case ATH_CHANCTX_EVENT_CHANGE: | 749 | case ATH_CHANCTX_EVENT_CHANGE: |
599 | break; | 750 | break; |
@@ -751,6 +902,11 @@ void ath_offchannel_next(struct ath_softc *sc) | |||
751 | sc->offchannel.state = ATH_OFFCHANNEL_ROC_START; | 902 | sc->offchannel.state = ATH_OFFCHANNEL_ROC_START; |
752 | ath_chanctx_offchan_switch(sc, sc->offchannel.roc_chan); | 903 | ath_chanctx_offchan_switch(sc, sc->offchannel.roc_chan); |
753 | } else { | 904 | } else { |
905 | spin_lock_bh(&sc->chan_lock); | ||
906 | sc->sched.offchannel_pending = false; | ||
907 | sc->sched.wait_switch = false; | ||
908 | spin_unlock_bh(&sc->chan_lock); | ||
909 | |||
754 | ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false), | 910 | ath_chanctx_switch(sc, ath_chanctx_get_oper_chan(sc, false), |
755 | NULL); | 911 | NULL); |
756 | sc->offchannel.state = ATH_OFFCHANNEL_IDLE; | 912 | sc->offchannel.state = ATH_OFFCHANNEL_IDLE; |
@@ -770,8 +926,7 @@ void ath_roc_complete(struct ath_softc *sc, bool abort) | |||
770 | 926 | ||
771 | sc->offchannel.roc_vif = NULL; | 927 | sc->offchannel.roc_vif = NULL; |
772 | sc->offchannel.roc_chan = NULL; | 928 | sc->offchannel.roc_chan = NULL; |
773 | if (!abort) | 929 | ieee80211_remain_on_channel_expired(sc->hw); |
774 | ieee80211_remain_on_channel_expired(sc->hw); | ||
775 | ath_offchannel_next(sc); | 930 | ath_offchannel_next(sc); |
776 | ath9k_ps_restore(sc); | 931 | ath9k_ps_restore(sc); |
777 | } | 932 | } |
@@ -808,7 +963,7 @@ static void ath_scan_send_probe(struct ath_softc *sc, | |||
808 | struct ieee80211_tx_info *info; | 963 | struct ieee80211_tx_info *info; |
809 | int band = sc->offchannel.chan.chandef.chan->band; | 964 | int band = sc->offchannel.chan.chandef.chan->band; |
810 | 965 | ||
811 | skb = ieee80211_probereq_get(sc->hw, vif, | 966 | skb = ieee80211_probereq_get(sc->hw, vif->addr, |
812 | ssid->ssid, ssid->ssid_len, req->ie_len); | 967 | ssid->ssid, ssid->ssid_len, req->ie_len); |
813 | if (!skb) | 968 | if (!skb) |
814 | return; | 969 | return; |
@@ -902,9 +1057,8 @@ static void ath_offchannel_timer(unsigned long data) | |||
902 | break; | 1057 | break; |
903 | case ATH_OFFCHANNEL_ROC_START: | 1058 | case ATH_OFFCHANNEL_ROC_START: |
904 | case ATH_OFFCHANNEL_ROC_WAIT: | 1059 | case ATH_OFFCHANNEL_ROC_WAIT: |
905 | ctx = ath_chanctx_get_oper_chan(sc, false); | ||
906 | sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE; | 1060 | sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE; |
907 | ath_chanctx_switch(sc, ctx, NULL); | 1061 | ath_roc_complete(sc, false); |
908 | break; | 1062 | break; |
909 | default: | 1063 | default: |
910 | break; | 1064 | break; |
@@ -1034,7 +1188,6 @@ static void ath_offchannel_channel_change(struct ath_softc *sc) | |||
1034 | ieee80211_ready_on_channel(sc->hw); | 1188 | ieee80211_ready_on_channel(sc->hw); |
1035 | break; | 1189 | break; |
1036 | case ATH_OFFCHANNEL_ROC_DONE: | 1190 | case ATH_OFFCHANNEL_ROC_DONE: |
1037 | ath_roc_complete(sc, false); | ||
1038 | break; | 1191 | break; |
1039 | default: | 1192 | default: |
1040 | break; | 1193 | break; |
@@ -1082,10 +1235,11 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force) | |||
1082 | ath9k_chanctx_stop_queues(sc, sc->cur_chan); | 1235 | ath9k_chanctx_stop_queues(sc, sc->cur_chan); |
1083 | queues_stopped = true; | 1236 | queues_stopped = true; |
1084 | 1237 | ||
1085 | __ath9k_flush(sc->hw, ~0, true); | 1238 | __ath9k_flush(sc->hw, ~0, true, false, false); |
1086 | 1239 | ||
1087 | if (ath_chanctx_send_ps_frame(sc, true)) | 1240 | if (ath_chanctx_send_ps_frame(sc, true)) |
1088 | __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), false); | 1241 | __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), |
1242 | false, false, false); | ||
1089 | 1243 | ||
1090 | send_ps = true; | 1244 | send_ps = true; |
1091 | spin_lock_bh(&sc->chan_lock); | 1245 | spin_lock_bh(&sc->chan_lock); |
@@ -1177,6 +1331,8 @@ void ath9k_init_channel_context(struct ath_softc *sc) | |||
1177 | (unsigned long)sc); | 1331 | (unsigned long)sc); |
1178 | setup_timer(&sc->sched.timer, ath_chanctx_timer, | 1332 | setup_timer(&sc->sched.timer, ath_chanctx_timer, |
1179 | (unsigned long)sc); | 1333 | (unsigned long)sc); |
1334 | |||
1335 | init_completion(&sc->go_beacon); | ||
1180 | } | 1336 | } |
1181 | 1337 | ||
1182 | void ath9k_deinit_channel_context(struct ath_softc *sc) | 1338 | void ath9k_deinit_channel_context(struct ath_softc *sc) |
diff --git a/drivers/net/wireless/ath/ath9k/spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c index 8f68426ca653..ec93ddf0863a 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.c +++ b/drivers/net/wireless/ath/ath9k/common-spectral.c | |||
@@ -24,23 +24,24 @@ static s8 fix_rssi_inv_only(u8 rssi_val) | |||
24 | return (s8) rssi_val; | 24 | return (s8) rssi_val; |
25 | } | 25 | } |
26 | 26 | ||
27 | static void ath_debug_send_fft_sample(struct ath_softc *sc, | 27 | static void ath_debug_send_fft_sample(struct ath_spec_scan_priv *spec_priv, |
28 | struct fft_sample_tlv *fft_sample_tlv) | 28 | struct fft_sample_tlv *fft_sample_tlv) |
29 | { | 29 | { |
30 | int length; | 30 | int length; |
31 | if (!sc->rfs_chan_spec_scan) | 31 | if (!spec_priv->rfs_chan_spec_scan) |
32 | return; | 32 | return; |
33 | 33 | ||
34 | length = __be16_to_cpu(fft_sample_tlv->length) + | 34 | length = __be16_to_cpu(fft_sample_tlv->length) + |
35 | sizeof(*fft_sample_tlv); | 35 | sizeof(*fft_sample_tlv); |
36 | relay_write(sc->rfs_chan_spec_scan, fft_sample_tlv, length); | 36 | relay_write(spec_priv->rfs_chan_spec_scan, fft_sample_tlv, length); |
37 | } | 37 | } |
38 | 38 | ||
39 | /* returns 1 if this was a spectral frame, even if not handled. */ | 39 | /* returns 1 if this was a spectral frame, even if not handled. */ |
40 | int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | 40 | int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, |
41 | struct ath_rx_status *rs, u64 tsf) | 41 | struct ath_rx_status *rs, u64 tsf) |
42 | { | 42 | { |
43 | struct ath_hw *ah = sc->sc_ah; | 43 | struct ath_hw *ah = spec_priv->ah; |
44 | struct ath_common *common = ath9k_hw_common(spec_priv->ah); | ||
44 | u8 num_bins, *bins, *vdata = (u8 *)hdr; | 45 | u8 num_bins, *bins, *vdata = (u8 *)hdr; |
45 | struct fft_sample_ht20 fft_sample_20; | 46 | struct fft_sample_ht20 fft_sample_20; |
46 | struct fft_sample_ht20_40 fft_sample_40; | 47 | struct fft_sample_ht20_40 fft_sample_40; |
@@ -67,7 +68,7 @@ int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | |||
67 | if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) | 68 | if (!(radar_info->pulse_bw_info & SPECTRAL_SCAN_BITMASK)) |
68 | return 0; | 69 | return 0; |
69 | 70 | ||
70 | chan_type = cfg80211_get_chandef_type(&sc->hw->conf.chandef); | 71 | chan_type = cfg80211_get_chandef_type(&common->hw->conf.chandef); |
71 | if ((chan_type == NL80211_CHAN_HT40MINUS) || | 72 | if ((chan_type == NL80211_CHAN_HT40MINUS) || |
72 | (chan_type == NL80211_CHAN_HT40PLUS)) { | 73 | (chan_type == NL80211_CHAN_HT40PLUS)) { |
73 | fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN; | 74 | fft_len = SPECTRAL_HT20_40_TOTAL_DATA_LEN; |
@@ -199,10 +200,11 @@ int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | |||
199 | tlv = (struct fft_sample_tlv *)&fft_sample_20; | 200 | tlv = (struct fft_sample_tlv *)&fft_sample_20; |
200 | } | 201 | } |
201 | 202 | ||
202 | ath_debug_send_fft_sample(sc, tlv); | 203 | ath_debug_send_fft_sample(spec_priv, tlv); |
203 | 204 | ||
204 | return 1; | 205 | return 1; |
205 | } | 206 | } |
207 | EXPORT_SYMBOL(ath_cmn_process_fft); | ||
206 | 208 | ||
207 | /*********************/ | 209 | /*********************/ |
208 | /* spectral_scan_ctl */ | 210 | /* spectral_scan_ctl */ |
@@ -211,11 +213,11 @@ int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | |||
211 | static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf, | 213 | static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf, |
212 | size_t count, loff_t *ppos) | 214 | size_t count, loff_t *ppos) |
213 | { | 215 | { |
214 | struct ath_softc *sc = file->private_data; | 216 | struct ath_spec_scan_priv *spec_priv = file->private_data; |
215 | char *mode = ""; | 217 | char *mode = ""; |
216 | unsigned int len; | 218 | unsigned int len; |
217 | 219 | ||
218 | switch (sc->spectral_mode) { | 220 | switch (spec_priv->spectral_mode) { |
219 | case SPECTRAL_DISABLED: | 221 | case SPECTRAL_DISABLED: |
220 | mode = "disable"; | 222 | mode = "disable"; |
221 | break; | 223 | break; |
@@ -233,12 +235,84 @@ static ssize_t read_file_spec_scan_ctl(struct file *file, char __user *user_buf, | |||
233 | return simple_read_from_buffer(user_buf, count, ppos, mode, len); | 235 | return simple_read_from_buffer(user_buf, count, ppos, mode, len); |
234 | } | 236 | } |
235 | 237 | ||
238 | void ath9k_cmn_spectral_scan_trigger(struct ath_common *common, | ||
239 | struct ath_spec_scan_priv *spec_priv) | ||
240 | { | ||
241 | struct ath_hw *ah = spec_priv->ah; | ||
242 | u32 rxfilter; | ||
243 | |||
244 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
245 | return; | ||
246 | |||
247 | if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { | ||
248 | ath_err(common, "spectrum analyzer not implemented on this hardware\n"); | ||
249 | return; | ||
250 | } | ||
251 | |||
252 | ath_ps_ops(common)->wakeup(common); | ||
253 | rxfilter = ath9k_hw_getrxfilter(ah); | ||
254 | ath9k_hw_setrxfilter(ah, rxfilter | | ||
255 | ATH9K_RX_FILTER_PHYRADAR | | ||
256 | ATH9K_RX_FILTER_PHYERR); | ||
257 | |||
258 | /* TODO: usually this should not be neccesary, but for some reason | ||
259 | * (or in some mode?) the trigger must be called after the | ||
260 | * configuration, otherwise the register will have its values reset | ||
261 | * (on my ar9220 to value 0x01002310) | ||
262 | */ | ||
263 | ath9k_cmn_spectral_scan_config(common, spec_priv, spec_priv->spectral_mode); | ||
264 | ath9k_hw_ops(ah)->spectral_scan_trigger(ah); | ||
265 | ath_ps_ops(common)->restore(common); | ||
266 | } | ||
267 | EXPORT_SYMBOL(ath9k_cmn_spectral_scan_trigger); | ||
268 | |||
269 | int ath9k_cmn_spectral_scan_config(struct ath_common *common, | ||
270 | struct ath_spec_scan_priv *spec_priv, | ||
271 | enum spectral_mode spectral_mode) | ||
272 | { | ||
273 | struct ath_hw *ah = spec_priv->ah; | ||
274 | |||
275 | if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { | ||
276 | ath_err(common, "spectrum analyzer not implemented on this hardware\n"); | ||
277 | return -1; | ||
278 | } | ||
279 | |||
280 | switch (spectral_mode) { | ||
281 | case SPECTRAL_DISABLED: | ||
282 | spec_priv->spec_config.enabled = 0; | ||
283 | break; | ||
284 | case SPECTRAL_BACKGROUND: | ||
285 | /* send endless samples. | ||
286 | * TODO: is this really useful for "background"? | ||
287 | */ | ||
288 | spec_priv->spec_config.endless = 1; | ||
289 | spec_priv->spec_config.enabled = 1; | ||
290 | break; | ||
291 | case SPECTRAL_CHANSCAN: | ||
292 | case SPECTRAL_MANUAL: | ||
293 | spec_priv->spec_config.endless = 0; | ||
294 | spec_priv->spec_config.enabled = 1; | ||
295 | break; | ||
296 | default: | ||
297 | return -1; | ||
298 | } | ||
299 | |||
300 | ath_ps_ops(common)->wakeup(common); | ||
301 | ath9k_hw_ops(ah)->spectral_scan_config(ah, &spec_priv->spec_config); | ||
302 | ath_ps_ops(common)->restore(common); | ||
303 | |||
304 | spec_priv->spectral_mode = spectral_mode; | ||
305 | |||
306 | return 0; | ||
307 | } | ||
308 | EXPORT_SYMBOL(ath9k_cmn_spectral_scan_config); | ||
309 | |||
236 | static ssize_t write_file_spec_scan_ctl(struct file *file, | 310 | static ssize_t write_file_spec_scan_ctl(struct file *file, |
237 | const char __user *user_buf, | 311 | const char __user *user_buf, |
238 | size_t count, loff_t *ppos) | 312 | size_t count, loff_t *ppos) |
239 | { | 313 | { |
240 | struct ath_softc *sc = file->private_data; | 314 | struct ath_spec_scan_priv *spec_priv = file->private_data; |
241 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 315 | struct ath_common *common = ath9k_hw_common(spec_priv->ah); |
242 | char buf[32]; | 316 | char buf[32]; |
243 | ssize_t len; | 317 | ssize_t len; |
244 | 318 | ||
@@ -252,18 +326,18 @@ static ssize_t write_file_spec_scan_ctl(struct file *file, | |||
252 | buf[len] = '\0'; | 326 | buf[len] = '\0'; |
253 | 327 | ||
254 | if (strncmp("trigger", buf, 7) == 0) { | 328 | if (strncmp("trigger", buf, 7) == 0) { |
255 | ath9k_spectral_scan_trigger(sc->hw); | 329 | ath9k_cmn_spectral_scan_trigger(common, spec_priv); |
256 | } else if (strncmp("background", buf, 10) == 0) { | 330 | } else if (strncmp("background", buf, 10) == 0) { |
257 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_BACKGROUND); | 331 | ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_BACKGROUND); |
258 | ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n"); | 332 | ath_dbg(common, CONFIG, "spectral scan: background mode enabled\n"); |
259 | } else if (strncmp("chanscan", buf, 8) == 0) { | 333 | } else if (strncmp("chanscan", buf, 8) == 0) { |
260 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_CHANSCAN); | 334 | ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_CHANSCAN); |
261 | ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n"); | 335 | ath_dbg(common, CONFIG, "spectral scan: channel scan mode enabled\n"); |
262 | } else if (strncmp("manual", buf, 6) == 0) { | 336 | } else if (strncmp("manual", buf, 6) == 0) { |
263 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_MANUAL); | 337 | ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_MANUAL); |
264 | ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n"); | 338 | ath_dbg(common, CONFIG, "spectral scan: manual mode enabled\n"); |
265 | } else if (strncmp("disable", buf, 7) == 0) { | 339 | } else if (strncmp("disable", buf, 7) == 0) { |
266 | ath9k_spectral_scan_config(sc->hw, SPECTRAL_DISABLED); | 340 | ath9k_cmn_spectral_scan_config(common, spec_priv, SPECTRAL_DISABLED); |
267 | ath_dbg(common, CONFIG, "spectral scan: disabled\n"); | 341 | ath_dbg(common, CONFIG, "spectral scan: disabled\n"); |
268 | } else { | 342 | } else { |
269 | return -EINVAL; | 343 | return -EINVAL; |
@@ -288,11 +362,11 @@ static ssize_t read_file_spectral_short_repeat(struct file *file, | |||
288 | char __user *user_buf, | 362 | char __user *user_buf, |
289 | size_t count, loff_t *ppos) | 363 | size_t count, loff_t *ppos) |
290 | { | 364 | { |
291 | struct ath_softc *sc = file->private_data; | 365 | struct ath_spec_scan_priv *spec_priv = file->private_data; |
292 | char buf[32]; | 366 | char buf[32]; |
293 | unsigned int len; | 367 | unsigned int len; |
294 | 368 | ||
295 | len = sprintf(buf, "%d\n", sc->spec_config.short_repeat); | 369 | len = sprintf(buf, "%d\n", spec_priv->spec_config.short_repeat); |
296 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 370 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
297 | } | 371 | } |
298 | 372 | ||
@@ -300,7 +374,7 @@ static ssize_t write_file_spectral_short_repeat(struct file *file, | |||
300 | const char __user *user_buf, | 374 | const char __user *user_buf, |
301 | size_t count, loff_t *ppos) | 375 | size_t count, loff_t *ppos) |
302 | { | 376 | { |
303 | struct ath_softc *sc = file->private_data; | 377 | struct ath_spec_scan_priv *spec_priv = file->private_data; |
304 | unsigned long val; | 378 | unsigned long val; |
305 | char buf[32]; | 379 | char buf[32]; |
306 | ssize_t len; | 380 | ssize_t len; |
@@ -316,7 +390,7 @@ static ssize_t write_file_spectral_short_repeat(struct file *file, | |||
316 | if (val > 1) | 390 | if (val > 1) |
317 | return -EINVAL; | 391 | return -EINVAL; |
318 | 392 | ||
319 | sc->spec_config.short_repeat = val; | 393 | spec_priv->spec_config.short_repeat = val; |
320 | return count; | 394 | return count; |
321 | } | 395 | } |
322 | 396 | ||
@@ -336,11 +410,11 @@ static ssize_t read_file_spectral_count(struct file *file, | |||
336 | char __user *user_buf, | 410 | char __user *user_buf, |
337 | size_t count, loff_t *ppos) | 411 | size_t count, loff_t *ppos) |
338 | { | 412 | { |
339 | struct ath_softc *sc = file->private_data; | 413 | struct ath_spec_scan_priv *spec_priv = file->private_data; |
340 | char buf[32]; | 414 | char buf[32]; |
341 | unsigned int len; | 415 | unsigned int len; |
342 | 416 | ||
343 | len = sprintf(buf, "%d\n", sc->spec_config.count); | 417 | len = sprintf(buf, "%d\n", spec_priv->spec_config.count); |
344 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 418 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
345 | } | 419 | } |
346 | 420 | ||
@@ -348,7 +422,7 @@ static ssize_t write_file_spectral_count(struct file *file, | |||
348 | const char __user *user_buf, | 422 | const char __user *user_buf, |
349 | size_t count, loff_t *ppos) | 423 | size_t count, loff_t *ppos) |
350 | { | 424 | { |
351 | struct ath_softc *sc = file->private_data; | 425 | struct ath_spec_scan_priv *spec_priv = file->private_data; |
352 | unsigned long val; | 426 | unsigned long val; |
353 | char buf[32]; | 427 | char buf[32]; |
354 | ssize_t len; | 428 | ssize_t len; |
@@ -364,7 +438,7 @@ static ssize_t write_file_spectral_count(struct file *file, | |||
364 | if (val > 255) | 438 | if (val > 255) |
365 | return -EINVAL; | 439 | return -EINVAL; |
366 | 440 | ||
367 | sc->spec_config.count = val; | 441 | spec_priv->spec_config.count = val; |
368 | return count; | 442 | return count; |
369 | } | 443 | } |
370 | 444 | ||
@@ -384,11 +458,11 @@ static ssize_t read_file_spectral_period(struct file *file, | |||
384 | char __user *user_buf, | 458 | char __user *user_buf, |
385 | size_t count, loff_t *ppos) | 459 | size_t count, loff_t *ppos) |
386 | { | 460 | { |
387 | struct ath_softc *sc = file->private_data; | 461 | struct ath_spec_scan_priv *spec_priv = file->private_data; |
388 | char buf[32]; | 462 | char buf[32]; |
389 | unsigned int len; | 463 | unsigned int len; |
390 | 464 | ||
391 | len = sprintf(buf, "%d\n", sc->spec_config.period); | 465 | len = sprintf(buf, "%d\n", spec_priv->spec_config.period); |
392 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 466 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
393 | } | 467 | } |
394 | 468 | ||
@@ -396,7 +470,7 @@ static ssize_t write_file_spectral_period(struct file *file, | |||
396 | const char __user *user_buf, | 470 | const char __user *user_buf, |
397 | size_t count, loff_t *ppos) | 471 | size_t count, loff_t *ppos) |
398 | { | 472 | { |
399 | struct ath_softc *sc = file->private_data; | 473 | struct ath_spec_scan_priv *spec_priv = file->private_data; |
400 | unsigned long val; | 474 | unsigned long val; |
401 | char buf[32]; | 475 | char buf[32]; |
402 | ssize_t len; | 476 | ssize_t len; |
@@ -412,7 +486,7 @@ static ssize_t write_file_spectral_period(struct file *file, | |||
412 | if (val > 255) | 486 | if (val > 255) |
413 | return -EINVAL; | 487 | return -EINVAL; |
414 | 488 | ||
415 | sc->spec_config.period = val; | 489 | spec_priv->spec_config.period = val; |
416 | return count; | 490 | return count; |
417 | } | 491 | } |
418 | 492 | ||
@@ -432,11 +506,11 @@ static ssize_t read_file_spectral_fft_period(struct file *file, | |||
432 | char __user *user_buf, | 506 | char __user *user_buf, |
433 | size_t count, loff_t *ppos) | 507 | size_t count, loff_t *ppos) |
434 | { | 508 | { |
435 | struct ath_softc *sc = file->private_data; | 509 | struct ath_spec_scan_priv *spec_priv = file->private_data; |
436 | char buf[32]; | 510 | char buf[32]; |
437 | unsigned int len; | 511 | unsigned int len; |
438 | 512 | ||
439 | len = sprintf(buf, "%d\n", sc->spec_config.fft_period); | 513 | len = sprintf(buf, "%d\n", spec_priv->spec_config.fft_period); |
440 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); | 514 | return simple_read_from_buffer(user_buf, count, ppos, buf, len); |
441 | } | 515 | } |
442 | 516 | ||
@@ -444,7 +518,7 @@ static ssize_t write_file_spectral_fft_period(struct file *file, | |||
444 | const char __user *user_buf, | 518 | const char __user *user_buf, |
445 | size_t count, loff_t *ppos) | 519 | size_t count, loff_t *ppos) |
446 | { | 520 | { |
447 | struct ath_softc *sc = file->private_data; | 521 | struct ath_spec_scan_priv *spec_priv = file->private_data; |
448 | unsigned long val; | 522 | unsigned long val; |
449 | char buf[32]; | 523 | char buf[32]; |
450 | ssize_t len; | 524 | ssize_t len; |
@@ -460,7 +534,7 @@ static ssize_t write_file_spectral_fft_period(struct file *file, | |||
460 | if (val > 15) | 534 | if (val > 15) |
461 | return -EINVAL; | 535 | return -EINVAL; |
462 | 536 | ||
463 | sc->spec_config.fft_period = val; | 537 | spec_priv->spec_config.fft_period = val; |
464 | return count; | 538 | return count; |
465 | } | 539 | } |
466 | 540 | ||
@@ -506,38 +580,41 @@ static struct rchan_callbacks rfs_spec_scan_cb = { | |||
506 | /* Debug Init/Deinit */ | 580 | /* Debug Init/Deinit */ |
507 | /*********************/ | 581 | /*********************/ |
508 | 582 | ||
509 | void ath9k_spectral_deinit_debug(struct ath_softc *sc) | 583 | void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv) |
510 | { | 584 | { |
511 | if (config_enabled(CONFIG_ATH9K_DEBUGFS) && sc->rfs_chan_spec_scan) { | 585 | if (config_enabled(CONFIG_ATH9K_DEBUGFS) && spec_priv->rfs_chan_spec_scan) { |
512 | relay_close(sc->rfs_chan_spec_scan); | 586 | relay_close(spec_priv->rfs_chan_spec_scan); |
513 | sc->rfs_chan_spec_scan = NULL; | 587 | spec_priv->rfs_chan_spec_scan = NULL; |
514 | } | 588 | } |
515 | } | 589 | } |
590 | EXPORT_SYMBOL(ath9k_cmn_spectral_deinit_debug); | ||
516 | 591 | ||
517 | void ath9k_spectral_init_debug(struct ath_softc *sc) | 592 | void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, |
593 | struct dentry *debugfs_phy) | ||
518 | { | 594 | { |
519 | sc->rfs_chan_spec_scan = relay_open("spectral_scan", | 595 | spec_priv->rfs_chan_spec_scan = relay_open("spectral_scan", |
520 | sc->debug.debugfs_phy, | 596 | debugfs_phy, |
521 | 1024, 256, &rfs_spec_scan_cb, | 597 | 1024, 256, &rfs_spec_scan_cb, |
522 | NULL); | 598 | NULL); |
523 | debugfs_create_file("spectral_scan_ctl", | 599 | debugfs_create_file("spectral_scan_ctl", |
524 | S_IRUSR | S_IWUSR, | 600 | S_IRUSR | S_IWUSR, |
525 | sc->debug.debugfs_phy, sc, | 601 | debugfs_phy, spec_priv, |
526 | &fops_spec_scan_ctl); | 602 | &fops_spec_scan_ctl); |
527 | debugfs_create_file("spectral_short_repeat", | 603 | debugfs_create_file("spectral_short_repeat", |
528 | S_IRUSR | S_IWUSR, | 604 | S_IRUSR | S_IWUSR, |
529 | sc->debug.debugfs_phy, sc, | 605 | debugfs_phy, spec_priv, |
530 | &fops_spectral_short_repeat); | 606 | &fops_spectral_short_repeat); |
531 | debugfs_create_file("spectral_count", | 607 | debugfs_create_file("spectral_count", |
532 | S_IRUSR | S_IWUSR, | 608 | S_IRUSR | S_IWUSR, |
533 | sc->debug.debugfs_phy, sc, | 609 | debugfs_phy, spec_priv, |
534 | &fops_spectral_count); | 610 | &fops_spectral_count); |
535 | debugfs_create_file("spectral_period", | 611 | debugfs_create_file("spectral_period", |
536 | S_IRUSR | S_IWUSR, | 612 | S_IRUSR | S_IWUSR, |
537 | sc->debug.debugfs_phy, sc, | 613 | debugfs_phy, spec_priv, |
538 | &fops_spectral_period); | 614 | &fops_spectral_period); |
539 | debugfs_create_file("spectral_fft_period", | 615 | debugfs_create_file("spectral_fft_period", |
540 | S_IRUSR | S_IWUSR, | 616 | S_IRUSR | S_IWUSR, |
541 | sc->debug.debugfs_phy, sc, | 617 | debugfs_phy, spec_priv, |
542 | &fops_spectral_fft_period); | 618 | &fops_spectral_fft_period); |
543 | } | 619 | } |
620 | EXPORT_SYMBOL(ath9k_cmn_spectral_init_debug); | ||
diff --git a/drivers/net/wireless/ath/ath9k/spectral.h b/drivers/net/wireless/ath/ath9k/common-spectral.h index 7b410c6858b0..82d9dd29652c 100644 --- a/drivers/net/wireless/ath/ath9k/spectral.h +++ b/drivers/net/wireless/ath/ath9k/common-spectral.h | |||
@@ -92,6 +92,13 @@ struct ath_ht20_40_fft_packet { | |||
92 | struct ath_radar_info radar_info; | 92 | struct ath_radar_info radar_info; |
93 | } __packed; | 93 | } __packed; |
94 | 94 | ||
95 | struct ath_spec_scan_priv { | ||
96 | struct ath_hw *ah; | ||
97 | /* relay(fs) channel for spectral scan */ | ||
98 | struct rchan *rfs_chan_spec_scan; | ||
99 | enum spectral_mode spectral_mode; | ||
100 | struct ath_spec_scan spec_config; | ||
101 | }; | ||
95 | 102 | ||
96 | #define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet)) | 103 | #define SPECTRAL_HT20_40_TOTAL_DATA_LEN (sizeof(struct ath_ht20_40_fft_packet)) |
97 | 104 | ||
@@ -123,23 +130,15 @@ static inline u8 spectral_bitmap_weight(u8 *bins) | |||
123 | return bins[0] & 0x3f; | 130 | return bins[0] & 0x3f; |
124 | } | 131 | } |
125 | 132 | ||
126 | void ath9k_spectral_init_debug(struct ath_softc *sc); | 133 | void ath9k_cmn_spectral_init_debug(struct ath_spec_scan_priv *spec_priv, struct dentry *debugfs_phy); |
127 | void ath9k_spectral_deinit_debug(struct ath_softc *sc); | 134 | void ath9k_cmn_spectral_deinit_debug(struct ath_spec_scan_priv *spec_priv); |
128 | 135 | ||
129 | void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw); | 136 | void ath9k_cmn_spectral_scan_trigger(struct ath_common *common, |
130 | int ath9k_spectral_scan_config(struct ieee80211_hw *hw, | 137 | struct ath_spec_scan_priv *spec_priv); |
138 | int ath9k_cmn_spectral_scan_config(struct ath_common *common, | ||
139 | struct ath_spec_scan_priv *spec_priv, | ||
131 | enum spectral_mode spectral_mode); | 140 | enum spectral_mode spectral_mode); |
132 | 141 | int ath_cmn_process_fft(struct ath_spec_scan_priv *spec_priv, struct ieee80211_hdr *hdr, | |
133 | #ifdef CONFIG_ATH9K_DEBUGFS | ||
134 | int ath_process_fft(struct ath_softc *sc, struct ieee80211_hdr *hdr, | ||
135 | struct ath_rx_status *rs, u64 tsf); | 142 | struct ath_rx_status *rs, u64 tsf); |
136 | #else | ||
137 | static inline int ath_process_fft(struct ath_softc *sc, | ||
138 | struct ieee80211_hdr *hdr, | ||
139 | struct ath_rx_status *rs, u64 tsf) | ||
140 | { | ||
141 | return 0; | ||
142 | } | ||
143 | #endif /* CONFIG_ATH9K_DEBUGFS */ | ||
144 | 143 | ||
145 | #endif /* SPECTRAL_H */ | 144 | #endif /* SPECTRAL_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c index c6dd7f1fed65..e8c699446470 100644 --- a/drivers/net/wireless/ath/ath9k/common.c +++ b/drivers/net/wireless/ath/ath9k/common.c | |||
@@ -159,7 +159,7 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common, | |||
159 | if (test_bit(keyix, common->keymap)) | 159 | if (test_bit(keyix, common->keymap)) |
160 | rxs->flag |= RX_FLAG_DECRYPTED; | 160 | rxs->flag |= RX_FLAG_DECRYPTED; |
161 | } | 161 | } |
162 | if (ah->sw_mgmt_crypto && | 162 | if (ah->sw_mgmt_crypto_rx && |
163 | (rxs->flag & RX_FLAG_DECRYPTED) && | 163 | (rxs->flag & RX_FLAG_DECRYPTED) && |
164 | ieee80211_is_mgmt(fc)) | 164 | ieee80211_is_mgmt(fc)) |
165 | /* Use software decrypt for management frames. */ | 165 | /* Use software decrypt for management frames. */ |
@@ -368,11 +368,11 @@ void ath9k_cmn_update_txpow(struct ath_hw *ah, u16 cur_txpow, | |||
368 | { | 368 | { |
369 | struct ath_regulatory *reg = ath9k_hw_regulatory(ah); | 369 | struct ath_regulatory *reg = ath9k_hw_regulatory(ah); |
370 | 370 | ||
371 | if (reg->power_limit != new_txpow) { | 371 | if (reg->power_limit != new_txpow) |
372 | ath9k_hw_set_txpowerlimit(ah, new_txpow, false); | 372 | ath9k_hw_set_txpowerlimit(ah, new_txpow, false); |
373 | /* read back in case value is clamped */ | 373 | |
374 | *txpower = reg->max_power_level; | 374 | /* read back in case value is clamped */ |
375 | } | 375 | *txpower = reg->max_power_level; |
376 | } | 376 | } |
377 | EXPORT_SYMBOL(ath9k_cmn_update_txpow); | 377 | EXPORT_SYMBOL(ath9k_cmn_update_txpow); |
378 | 378 | ||
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h index ffc454b18637..2b79a568e803 100644 --- a/drivers/net/wireless/ath/ath9k/common.h +++ b/drivers/net/wireless/ath/ath9k/common.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "common-init.h" | 24 | #include "common-init.h" |
25 | #include "common-beacon.h" | 25 | #include "common-beacon.h" |
26 | #include "common-debug.h" | 26 | #include "common-debug.h" |
27 | #include "common-spectral.h" | ||
27 | 28 | ||
28 | /* Common header for Atheros 802.11n base driver cores */ | 29 | /* Common header for Atheros 802.11n base driver cores */ |
29 | 30 | ||
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 46f20a309b5f..696e3d5309c6 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -455,7 +455,7 @@ static ssize_t read_file_dma(struct file *file, char __user *user_buf, | |||
455 | "%2d %2x %1x %2x %2x\n", | 455 | "%2d %2x %1x %2x %2x\n", |
456 | i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, | 456 | i, (*qcuBase & (0x7 << qcuOffset)) >> qcuOffset, |
457 | (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3), | 457 | (*qcuBase & (0x8 << qcuOffset)) >> (qcuOffset + 3), |
458 | val[2] & (0x7 << (i * 3)) >> (i * 3), | 458 | (val[2] & (0x7 << (i * 3))) >> (i * 3), |
459 | (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); | 459 | (*dcuBase & (0x1f << dcuOffset)) >> dcuOffset); |
460 | } | 460 | } |
461 | 461 | ||
@@ -828,13 +828,14 @@ static ssize_t read_file_misc(struct file *file, char __user *user_buf, | |||
828 | 828 | ||
829 | i = 0; | 829 | i = 0; |
830 | ath_for_each_chanctx(sc, ctx) { | 830 | ath_for_each_chanctx(sc, ctx) { |
831 | if (!ctx->assigned || list_empty(&ctx->vifs)) | 831 | if (list_empty(&ctx->vifs)) |
832 | continue; | 832 | continue; |
833 | ath9k_calculate_iter_data(sc, ctx, &iter_data); | 833 | ath9k_calculate_iter_data(sc, ctx, &iter_data); |
834 | 834 | ||
835 | len += scnprintf(buf + len, sizeof(buf) - len, | 835 | len += scnprintf(buf + len, sizeof(buf) - len, |
836 | "VIF-COUNTS: CTX %i AP: %i STA: %i MESH: %i WDS: %i", | 836 | "VIFS: CTX %i(%i) AP: %i STA: %i MESH: %i WDS: %i", |
837 | i++, iter_data.naps, iter_data.nstations, | 837 | i++, (int)(ctx->assigned), iter_data.naps, |
838 | iter_data.nstations, | ||
838 | iter_data.nmeshes, iter_data.nwds); | 839 | iter_data.nmeshes, iter_data.nwds); |
839 | len += scnprintf(buf + len, sizeof(buf) - len, | 840 | len += scnprintf(buf + len, sizeof(buf) - len, |
840 | " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n", | 841 | " ADHOC: %i TOTAL: %hi BEACON-VIF: %hi\n", |
@@ -852,36 +853,31 @@ static ssize_t read_file_reset(struct file *file, char __user *user_buf, | |||
852 | size_t count, loff_t *ppos) | 853 | size_t count, loff_t *ppos) |
853 | { | 854 | { |
854 | struct ath_softc *sc = file->private_data; | 855 | struct ath_softc *sc = file->private_data; |
856 | static const char * const reset_cause[__RESET_TYPE_MAX] = { | ||
857 | [RESET_TYPE_BB_HANG] = "Baseband Hang", | ||
858 | [RESET_TYPE_BB_WATCHDOG] = "Baseband Watchdog", | ||
859 | [RESET_TYPE_FATAL_INT] = "Fatal HW Error", | ||
860 | [RESET_TYPE_TX_ERROR] = "TX HW error", | ||
861 | [RESET_TYPE_TX_GTT] = "Transmit timeout", | ||
862 | [RESET_TYPE_TX_HANG] = "TX Path Hang", | ||
863 | [RESET_TYPE_PLL_HANG] = "PLL RX Hang", | ||
864 | [RESET_TYPE_MAC_HANG] = "MAC Hang", | ||
865 | [RESET_TYPE_BEACON_STUCK] = "Stuck Beacon", | ||
866 | [RESET_TYPE_MCI] = "MCI Reset", | ||
867 | [RESET_TYPE_CALIBRATION] = "Calibration error", | ||
868 | }; | ||
855 | char buf[512]; | 869 | char buf[512]; |
856 | unsigned int len = 0; | 870 | unsigned int len = 0; |
871 | int i; | ||
857 | 872 | ||
858 | len += scnprintf(buf + len, sizeof(buf) - len, | 873 | for (i = 0; i < ARRAY_SIZE(reset_cause); i++) { |
859 | "%17s: %2d\n", "Baseband Hang", | 874 | if (!reset_cause[i]) |
860 | sc->debug.stats.reset[RESET_TYPE_BB_HANG]); | 875 | continue; |
861 | len += scnprintf(buf + len, sizeof(buf) - len, | 876 | |
862 | "%17s: %2d\n", "Baseband Watchdog", | 877 | len += scnprintf(buf + len, sizeof(buf) - len, |
863 | sc->debug.stats.reset[RESET_TYPE_BB_WATCHDOG]); | 878 | "%17s: %2d\n", reset_cause[i], |
864 | len += scnprintf(buf + len, sizeof(buf) - len, | 879 | sc->debug.stats.reset[i]); |
865 | "%17s: %2d\n", "Fatal HW Error", | 880 | } |
866 | sc->debug.stats.reset[RESET_TYPE_FATAL_INT]); | ||
867 | len += scnprintf(buf + len, sizeof(buf) - len, | ||
868 | "%17s: %2d\n", "TX HW error", | ||
869 | sc->debug.stats.reset[RESET_TYPE_TX_ERROR]); | ||
870 | len += scnprintf(buf + len, sizeof(buf) - len, | ||
871 | "%17s: %2d\n", "TX Path Hang", | ||
872 | sc->debug.stats.reset[RESET_TYPE_TX_HANG]); | ||
873 | len += scnprintf(buf + len, sizeof(buf) - len, | ||
874 | "%17s: %2d\n", "PLL RX Hang", | ||
875 | sc->debug.stats.reset[RESET_TYPE_PLL_HANG]); | ||
876 | len += scnprintf(buf + len, sizeof(buf) - len, | ||
877 | "%17s: %2d\n", "MAC Hang", | ||
878 | sc->debug.stats.reset[RESET_TYPE_MAC_HANG]); | ||
879 | len += scnprintf(buf + len, sizeof(buf) - len, | ||
880 | "%17s: %2d\n", "Stuck Beacon", | ||
881 | sc->debug.stats.reset[RESET_TYPE_BEACON_STUCK]); | ||
882 | len += scnprintf(buf + len, sizeof(buf) - len, | ||
883 | "%17s: %2d\n", "MCI Reset", | ||
884 | sc->debug.stats.reset[RESET_TYPE_MCI]); | ||
885 | 881 | ||
886 | if (len > sizeof(buf)) | 882 | if (len > sizeof(buf)) |
887 | len = sizeof(buf); | 883 | len = sizeof(buf); |
@@ -1315,7 +1311,7 @@ void ath9k_get_et_stats(struct ieee80211_hw *hw, | |||
1315 | 1311 | ||
1316 | void ath9k_deinit_debug(struct ath_softc *sc) | 1312 | void ath9k_deinit_debug(struct ath_softc *sc) |
1317 | { | 1313 | { |
1318 | ath9k_spectral_deinit_debug(sc); | 1314 | ath9k_cmn_spectral_deinit_debug(&sc->spec_priv); |
1319 | } | 1315 | } |
1320 | 1316 | ||
1321 | int ath9k_init_debug(struct ath_hw *ah) | 1317 | int ath9k_init_debug(struct ath_hw *ah) |
@@ -1335,7 +1331,7 @@ int ath9k_init_debug(struct ath_hw *ah) | |||
1335 | 1331 | ||
1336 | ath9k_dfs_init_debug(sc); | 1332 | ath9k_dfs_init_debug(sc); |
1337 | ath9k_tx99_init_debug(sc); | 1333 | ath9k_tx99_init_debug(sc); |
1338 | ath9k_spectral_init_debug(sc); | 1334 | ath9k_cmn_spectral_init_debug(&sc->spec_priv, sc->debug.debugfs_phy); |
1339 | 1335 | ||
1340 | debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, | 1336 | debugfs_create_file("dma", S_IRUSR, sc->debug.debugfs_phy, sc, |
1341 | &fops_dma); | 1337 | &fops_dma); |
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h index 53ae15bd0c9d..bd75b1f716db 100644 --- a/drivers/net/wireless/ath/ath9k/debug.h +++ b/drivers/net/wireless/ath/ath9k/debug.h | |||
@@ -49,6 +49,7 @@ enum ath_reset_type { | |||
49 | RESET_TYPE_MAC_HANG, | 49 | RESET_TYPE_MAC_HANG, |
50 | RESET_TYPE_BEACON_STUCK, | 50 | RESET_TYPE_BEACON_STUCK, |
51 | RESET_TYPE_MCI, | 51 | RESET_TYPE_MCI, |
52 | RESET_TYPE_CALIBRATION, | ||
52 | __RESET_TYPE_MAX | 53 | __RESET_TYPE_MAX |
53 | }; | 54 | }; |
54 | 55 | ||
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c index 3218ca994746..122b846b8ec0 100644 --- a/drivers/net/wireless/ath/ath9k/eeprom_def.c +++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c | |||
@@ -262,7 +262,7 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
262 | { | 262 | { |
263 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; | 263 | struct ar5416_eeprom_def *eep = &ah->eeprom.def; |
264 | struct ath_common *common = ath9k_hw_common(ah); | 264 | struct ath_common *common = ath9k_hw_common(ah); |
265 | u16 *eepdata, temp, magic, magic2; | 265 | u16 *eepdata, temp, magic; |
266 | u32 sum = 0, el; | 266 | u32 sum = 0, el; |
267 | bool need_swap = false; | 267 | bool need_swap = false; |
268 | int i, addr, size; | 268 | int i, addr, size; |
@@ -272,27 +272,16 @@ static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) | |||
272 | return false; | 272 | return false; |
273 | } | 273 | } |
274 | 274 | ||
275 | if (!ath9k_hw_use_flash(ah)) { | 275 | if (swab16(magic) == AR5416_EEPROM_MAGIC && |
276 | ath_dbg(common, EEPROM, "Read Magic = 0x%04X\n", magic); | 276 | !(ah->ah_flags & AH_NO_EEP_SWAP)) { |
277 | 277 | size = sizeof(struct ar5416_eeprom_def); | |
278 | if (magic != AR5416_EEPROM_MAGIC) { | 278 | need_swap = true; |
279 | magic2 = swab16(magic); | 279 | eepdata = (u16 *) (&ah->eeprom); |
280 | |||
281 | if (magic2 == AR5416_EEPROM_MAGIC) { | ||
282 | size = sizeof(struct ar5416_eeprom_def); | ||
283 | need_swap = true; | ||
284 | eepdata = (u16 *) (&ah->eeprom); | ||
285 | 280 | ||
286 | for (addr = 0; addr < size / sizeof(u16); addr++) { | 281 | for (addr = 0; addr < size / sizeof(u16); addr++) { |
287 | temp = swab16(*eepdata); | 282 | temp = swab16(*eepdata); |
288 | *eepdata = temp; | 283 | *eepdata = temp; |
289 | eepdata++; | 284 | eepdata++; |
290 | } | ||
291 | } else { | ||
292 | ath_err(common, | ||
293 | "Invalid EEPROM Magic. Endianness mismatch.\n"); | ||
294 | return -EINVAL; | ||
295 | } | ||
296 | } | 285 | } |
297 | } | 286 | } |
298 | 287 | ||
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c index b1956bf6e01e..2fef7a480fec 100644 --- a/drivers/net/wireless/ath/ath9k/gpio.c +++ b/drivers/net/wireless/ath/ath9k/gpio.c | |||
@@ -25,7 +25,12 @@ static void ath_led_brightness(struct led_classdev *led_cdev, | |||
25 | enum led_brightness brightness) | 25 | enum led_brightness brightness) |
26 | { | 26 | { |
27 | struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev); | 27 | struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev); |
28 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (brightness == LED_OFF)); | 28 | u32 val = (brightness == LED_OFF); |
29 | |||
30 | if (sc->sc_ah->config.led_active_high) | ||
31 | val = !val; | ||
32 | |||
33 | ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, val); | ||
29 | } | 34 | } |
30 | 35 | ||
31 | void ath_deinit_leds(struct ath_softc *sc) | 36 | void ath_deinit_leds(struct ath_softc *sc) |
@@ -82,7 +87,7 @@ void ath_fill_led_pin(struct ath_softc *sc) | |||
82 | ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | 87 | ath9k_hw_cfg_output(ah, ah->led_pin, AR_GPIO_OUTPUT_MUX_AS_OUTPUT); |
83 | 88 | ||
84 | /* LED off, active low */ | 89 | /* LED off, active low */ |
85 | ath9k_hw_set_gpio(ah, ah->led_pin, 1); | 90 | ath9k_hw_set_gpio(ah, ah->led_pin, (ah->config.led_active_high) ? 0 : 1); |
86 | } | 91 | } |
87 | #endif | 92 | #endif |
88 | 93 | ||
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h index 09a5d72f3ff5..9dde265d3f84 100644 --- a/drivers/net/wireless/ath/ath9k/htc.h +++ b/drivers/net/wireless/ath/ath9k/htc.h | |||
@@ -481,6 +481,7 @@ struct ath9k_htc_priv { | |||
481 | unsigned long op_flags; | 481 | unsigned long op_flags; |
482 | 482 | ||
483 | struct ath9k_hw_cal_data caldata; | 483 | struct ath9k_hw_cal_data caldata; |
484 | struct ath_spec_scan_priv spec_priv; | ||
484 | 485 | ||
485 | spinlock_t beacon_lock; | 486 | spinlock_t beacon_lock; |
486 | struct ath_beacon_config cur_beacon_conf; | 487 | struct ath_beacon_config cur_beacon_conf; |
@@ -625,8 +626,12 @@ int ath9k_htc_resume(struct htc_target *htc_handle); | |||
625 | #endif | 626 | #endif |
626 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS | 627 | #ifdef CONFIG_ATH9K_HTC_DEBUGFS |
627 | int ath9k_htc_init_debug(struct ath_hw *ah); | 628 | int ath9k_htc_init_debug(struct ath_hw *ah); |
629 | void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv); | ||
628 | #else | 630 | #else |
629 | static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; }; | 631 | static inline int ath9k_htc_init_debug(struct ath_hw *ah) { return 0; }; |
632 | static inline void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv) | ||
633 | { | ||
634 | } | ||
630 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ | 635 | #endif /* CONFIG_ATH9K_HTC_DEBUGFS */ |
631 | 636 | ||
632 | #endif /* HTC_H */ | 637 | #endif /* HTC_H */ |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c index 8b529e4b8ac4..8cef1edcc621 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c | |||
@@ -490,6 +490,10 @@ void ath9k_htc_get_et_stats(struct ieee80211_hw *hw, | |||
490 | WARN_ON(i != ATH9K_HTC_SSTATS_LEN); | 490 | WARN_ON(i != ATH9K_HTC_SSTATS_LEN); |
491 | } | 491 | } |
492 | 492 | ||
493 | void ath9k_htc_deinit_debug(struct ath9k_htc_priv *priv) | ||
494 | { | ||
495 | ath9k_cmn_spectral_deinit_debug(&priv->spec_priv); | ||
496 | } | ||
493 | 497 | ||
494 | int ath9k_htc_init_debug(struct ath_hw *ah) | 498 | int ath9k_htc_init_debug(struct ath_hw *ah) |
495 | { | 499 | { |
@@ -501,6 +505,8 @@ int ath9k_htc_init_debug(struct ath_hw *ah) | |||
501 | if (!priv->debug.debugfs_phy) | 505 | if (!priv->debug.debugfs_phy) |
502 | return -ENOMEM; | 506 | return -ENOMEM; |
503 | 507 | ||
508 | ath9k_cmn_spectral_init_debug(&priv->spec_priv, priv->debug.debugfs_phy); | ||
509 | |||
504 | debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy, | 510 | debugfs_create_file("tgt_int_stats", S_IRUSR, priv->debug.debugfs_phy, |
505 | priv, &fops_tgt_int_stats); | 511 | priv, &fops_tgt_int_stats); |
506 | debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy, | 512 | debugfs_create_file("tgt_tx_stats", S_IRUSR, priv->debug.debugfs_phy, |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c index d779f4fa50e3..e8fa9448da24 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c | |||
@@ -53,6 +53,21 @@ static const struct ieee80211_tpt_blink ath9k_htc_tpt_blink[] = { | |||
53 | }; | 53 | }; |
54 | #endif | 54 | #endif |
55 | 55 | ||
56 | static void ath9k_htc_op_ps_wakeup(struct ath_common *common) | ||
57 | { | ||
58 | ath9k_htc_ps_wakeup((struct ath9k_htc_priv *) common->priv); | ||
59 | } | ||
60 | |||
61 | static void ath9k_htc_op_ps_restore(struct ath_common *common) | ||
62 | { | ||
63 | ath9k_htc_ps_restore((struct ath9k_htc_priv *) common->priv); | ||
64 | } | ||
65 | |||
66 | static struct ath_ps_ops ath9k_htc_ps_ops = { | ||
67 | .wakeup = ath9k_htc_op_ps_wakeup, | ||
68 | .restore = ath9k_htc_op_ps_restore, | ||
69 | }; | ||
70 | |||
56 | static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) | 71 | static int ath9k_htc_wait_for_target(struct ath9k_htc_priv *priv) |
57 | { | 72 | { |
58 | int time_left; | 73 | int time_left; |
@@ -87,6 +102,7 @@ static void ath9k_deinit_device(struct ath9k_htc_priv *priv) | |||
87 | 102 | ||
88 | wiphy_rfkill_stop_polling(hw->wiphy); | 103 | wiphy_rfkill_stop_polling(hw->wiphy); |
89 | ath9k_deinit_leds(priv); | 104 | ath9k_deinit_leds(priv); |
105 | ath9k_htc_deinit_debug(priv); | ||
90 | ieee80211_unregister_hw(hw); | 106 | ieee80211_unregister_hw(hw); |
91 | ath9k_rx_cleanup(priv); | 107 | ath9k_rx_cleanup(priv); |
92 | ath9k_tx_cleanup(priv); | 108 | ath9k_tx_cleanup(priv); |
@@ -449,6 +465,14 @@ static void ath9k_init_misc(struct ath9k_htc_priv *priv) | |||
449 | 465 | ||
450 | common->last_rssi = ATH_RSSI_DUMMY_MARKER; | 466 | common->last_rssi = ATH_RSSI_DUMMY_MARKER; |
451 | priv->ah->opmode = NL80211_IFTYPE_STATION; | 467 | priv->ah->opmode = NL80211_IFTYPE_STATION; |
468 | |||
469 | priv->spec_priv.ah = priv->ah; | ||
470 | priv->spec_priv.spec_config.enabled = 0; | ||
471 | priv->spec_priv.spec_config.short_repeat = false; | ||
472 | priv->spec_priv.spec_config.count = 8; | ||
473 | priv->spec_priv.spec_config.endless = false; | ||
474 | priv->spec_priv.spec_config.period = 0x12; | ||
475 | priv->spec_priv.spec_config.fft_period = 0x02; | ||
452 | } | 476 | } |
453 | 477 | ||
454 | static int ath9k_init_priv(struct ath9k_htc_priv *priv, | 478 | static int ath9k_init_priv(struct ath9k_htc_priv *priv, |
@@ -464,6 +488,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, | |||
464 | return -ENOMEM; | 488 | return -ENOMEM; |
465 | 489 | ||
466 | ah->dev = priv->dev; | 490 | ah->dev = priv->dev; |
491 | ah->hw = priv->hw; | ||
467 | ah->hw_version.devid = devid; | 492 | ah->hw_version.devid = devid; |
468 | ah->hw_version.usbdev = drv_info; | 493 | ah->hw_version.usbdev = drv_info; |
469 | ah->ah_flags |= AH_USE_EEPROM; | 494 | ah->ah_flags |= AH_USE_EEPROM; |
@@ -477,6 +502,7 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv, | |||
477 | 502 | ||
478 | common = ath9k_hw_common(ah); | 503 | common = ath9k_hw_common(ah); |
479 | common->ops = &ah->reg_ops; | 504 | common->ops = &ah->reg_ops; |
505 | common->ps_ops = &ath9k_htc_ps_ops; | ||
480 | common->bus_ops = &ath9k_usb_bus_ops; | 506 | common->bus_ops = &ath9k_usb_bus_ops; |
481 | common->ah = ah; | 507 | common->ah = ah; |
482 | common->hw = priv->hw; | 508 | common->hw = priv->hw; |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c index 994fff1ff519..92d5a6c5a225 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c | |||
@@ -314,6 +314,10 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv, | |||
314 | mod_timer(&priv->tx.cleanup_timer, | 314 | mod_timer(&priv->tx.cleanup_timer, |
315 | jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); | 315 | jiffies + msecs_to_jiffies(ATH9K_HTC_TX_CLEANUP_INTERVAL)); |
316 | 316 | ||
317 | /* perform spectral scan if requested. */ | ||
318 | if (test_bit(ATH_OP_SCANNING, &common->op_flags) && | ||
319 | priv->spec_priv.spectral_mode == SPECTRAL_CHANSCAN) | ||
320 | ath9k_cmn_spectral_scan_trigger(common, &priv->spec_priv); | ||
317 | err: | 321 | err: |
318 | ath9k_htc_ps_restore(priv); | 322 | ath9k_htc_ps_restore(priv); |
319 | return ret; | 323 | return ret; |
@@ -1443,7 +1447,7 @@ static int ath9k_htc_set_key(struct ieee80211_hw *hw, | |||
1443 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1447 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1444 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) | 1448 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) |
1445 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | 1449 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
1446 | if (priv->ah->sw_mgmt_crypto && | 1450 | if (priv->ah->sw_mgmt_crypto_tx && |
1447 | key->cipher == WLAN_CIPHER_SUITE_CCMP) | 1451 | key->cipher == WLAN_CIPHER_SUITE_CCMP) |
1448 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; | 1452 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; |
1449 | ret = 0; | 1453 | ret = 0; |
@@ -1687,7 +1691,9 @@ static int ath9k_htc_ampdu_action(struct ieee80211_hw *hw, | |||
1687 | return ret; | 1691 | return ret; |
1688 | } | 1692 | } |
1689 | 1693 | ||
1690 | static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) | 1694 | static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw, |
1695 | struct ieee80211_vif *vif, | ||
1696 | const u8 *mac_addr) | ||
1691 | { | 1697 | { |
1692 | struct ath9k_htc_priv *priv = hw->priv; | 1698 | struct ath9k_htc_priv *priv = hw->priv; |
1693 | struct ath_common *common = ath9k_hw_common(priv->ah); | 1699 | struct ath_common *common = ath9k_hw_common(priv->ah); |
@@ -1701,7 +1707,8 @@ static void ath9k_htc_sw_scan_start(struct ieee80211_hw *hw) | |||
1701 | mutex_unlock(&priv->mutex); | 1707 | mutex_unlock(&priv->mutex); |
1702 | } | 1708 | } |
1703 | 1709 | ||
1704 | static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw) | 1710 | static void ath9k_htc_sw_scan_complete(struct ieee80211_hw *hw, |
1711 | struct ieee80211_vif *vif) | ||
1705 | { | 1712 | { |
1706 | struct ath9k_htc_priv *priv = hw->priv; | 1713 | struct ath9k_htc_priv *priv = hw->priv; |
1707 | struct ath_common *common = ath9k_hw_common(priv->ah); | 1714 | struct ath_common *common = ath9k_hw_common(priv->ah); |
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index f0484b1b617e..a0f58e2aa553 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c | |||
@@ -946,7 +946,7 @@ static inline void convert_htc_flag(struct ath_rx_status *rx_stats, | |||
946 | static void rx_status_htc_to_ath(struct ath_rx_status *rx_stats, | 946 | static void rx_status_htc_to_ath(struct ath_rx_status *rx_stats, |
947 | struct ath_htc_rx_status *rxstatus) | 947 | struct ath_htc_rx_status *rxstatus) |
948 | { | 948 | { |
949 | rx_stats->rs_datalen = rxstatus->rs_datalen; | 949 | rx_stats->rs_datalen = be16_to_cpu(rxstatus->rs_datalen); |
950 | rx_stats->rs_status = rxstatus->rs_status; | 950 | rx_stats->rs_status = rxstatus->rs_status; |
951 | rx_stats->rs_phyerr = rxstatus->rs_phyerr; | 951 | rx_stats->rs_phyerr = rxstatus->rs_phyerr; |
952 | rx_stats->rs_rssi = rxstatus->rs_rssi; | 952 | rx_stats->rs_rssi = rxstatus->rs_rssi; |
@@ -1012,6 +1012,20 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, | |||
1012 | * separately to avoid doing two lookups for a rate for each frame. | 1012 | * separately to avoid doing two lookups for a rate for each frame. |
1013 | */ | 1013 | */ |
1014 | hdr = (struct ieee80211_hdr *)skb->data; | 1014 | hdr = (struct ieee80211_hdr *)skb->data; |
1015 | |||
1016 | /* | ||
1017 | * Process PHY errors and return so that the packet | ||
1018 | * can be dropped. | ||
1019 | */ | ||
1020 | if (rx_stats.rs_status & ATH9K_RXERR_PHY) { | ||
1021 | /* TODO: Not using DFS processing now. */ | ||
1022 | if (ath_cmn_process_fft(&priv->spec_priv, hdr, | ||
1023 | &rx_stats, rx_status->mactime)) { | ||
1024 | /* TODO: Code to collect spectral scan statistics */ | ||
1025 | } | ||
1026 | goto rx_next; | ||
1027 | } | ||
1028 | |||
1015 | if (!ath9k_cmn_rx_accept(common, hdr, rx_status, &rx_stats, | 1029 | if (!ath9k_cmn_rx_accept(common, hdr, rx_status, &rx_stats, |
1016 | &decrypt_error, priv->rxfilter)) | 1030 | &decrypt_error, priv->rxfilter)) |
1017 | goto rx_next; | 1031 | goto rx_next; |
diff --git a/drivers/net/wireless/ath/ath9k/hw-ops.h b/drivers/net/wireless/ath/ath9k/hw-ops.h index 8e85efeaeffc..88769b64b20b 100644 --- a/drivers/net/wireless/ath/ath9k/hw-ops.h +++ b/drivers/net/wireless/ath/ath9k/hw-ops.h | |||
@@ -41,10 +41,9 @@ static inline void ath9k_hw_set_desc_link(struct ath_hw *ah, void *ds, | |||
41 | ath9k_hw_ops(ah)->set_desc_link(ds, link); | 41 | ath9k_hw_ops(ah)->set_desc_link(ds, link); |
42 | } | 42 | } |
43 | 43 | ||
44 | static inline bool ath9k_hw_calibrate(struct ath_hw *ah, | 44 | static inline int ath9k_hw_calibrate(struct ath_hw *ah, |
45 | struct ath9k_channel *chan, | 45 | struct ath9k_channel *chan, |
46 | u8 rxchainmask, | 46 | u8 rxchainmask, bool longcal) |
47 | bool longcal) | ||
48 | { | 47 | { |
49 | return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal); | 48 | return ath9k_hw_ops(ah)->calibrate(ah, chan, rxchainmask, longcal); |
50 | } | 49 | } |
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c index 8be4b1453394..6d4b273469b1 100644 --- a/drivers/net/wireless/ath/ath9k/hw.c +++ b/drivers/net/wireless/ath/ath9k/hw.c | |||
@@ -19,6 +19,7 @@ | |||
19 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/time.h> | 20 | #include <linux/time.h> |
21 | #include <linux/bitops.h> | 21 | #include <linux/bitops.h> |
22 | #include <linux/etherdevice.h> | ||
22 | #include <asm/unaligned.h> | 23 | #include <asm/unaligned.h> |
23 | 24 | ||
24 | #include "hw.h" | 25 | #include "hw.h" |
@@ -446,8 +447,16 @@ static int ath9k_hw_init_macaddr(struct ath_hw *ah) | |||
446 | common->macaddr[2 * i] = eeval >> 8; | 447 | common->macaddr[2 * i] = eeval >> 8; |
447 | common->macaddr[2 * i + 1] = eeval & 0xff; | 448 | common->macaddr[2 * i + 1] = eeval & 0xff; |
448 | } | 449 | } |
449 | if (sum == 0 || sum == 0xffff * 3) | 450 | if (!is_valid_ether_addr(common->macaddr)) { |
450 | return -EADDRNOTAVAIL; | 451 | ath_err(common, |
452 | "eeprom contains invalid mac address: %pM\n", | ||
453 | common->macaddr); | ||
454 | |||
455 | random_ether_addr(common->macaddr); | ||
456 | ath_err(common, | ||
457 | "random mac address will be used: %pM\n", | ||
458 | common->macaddr); | ||
459 | } | ||
451 | 460 | ||
452 | return 0; | 461 | return 0; |
453 | } | 462 | } |
@@ -861,19 +870,6 @@ static void ath9k_hw_init_pll(struct ath_hw *ah, | |||
861 | udelay(RTC_PLL_SETTLE_DELAY); | 870 | udelay(RTC_PLL_SETTLE_DELAY); |
862 | 871 | ||
863 | REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); | 872 | REG_WRITE(ah, AR_RTC_SLEEP_CLK, AR_RTC_FORCE_DERIVED_CLK); |
864 | |||
865 | if (AR_SREV_9340(ah) || AR_SREV_9550(ah)) { | ||
866 | if (ah->is_clk_25mhz) { | ||
867 | REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x17c << 1); | ||
868 | REG_WRITE(ah, AR_SLP32_MODE, 0x0010f3d7); | ||
869 | REG_WRITE(ah, AR_SLP32_INC, 0x0001e7ae); | ||
870 | } else { | ||
871 | REG_WRITE(ah, AR_RTC_DERIVED_CLK, 0x261 << 1); | ||
872 | REG_WRITE(ah, AR_SLP32_MODE, 0x0010f400); | ||
873 | REG_WRITE(ah, AR_SLP32_INC, 0x0001e800); | ||
874 | } | ||
875 | udelay(100); | ||
876 | } | ||
877 | } | 873 | } |
878 | 874 | ||
879 | static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, | 875 | static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah, |
@@ -1589,16 +1585,22 @@ static void ath9k_hw_init_mfp(struct ath_hw *ah) | |||
1589 | * frames when constructing CCMP AAD. */ | 1585 | * frames when constructing CCMP AAD. */ |
1590 | REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, | 1586 | REG_RMW_FIELD(ah, AR_AES_MUTE_MASK1, AR_AES_MUTE_MASK1_FC_MGMT, |
1591 | 0xc7ff); | 1587 | 0xc7ff); |
1592 | ah->sw_mgmt_crypto = false; | 1588 | if (AR_SREV_9271(ah) || AR_DEVID_7010(ah)) |
1589 | ah->sw_mgmt_crypto_tx = true; | ||
1590 | else | ||
1591 | ah->sw_mgmt_crypto_tx = false; | ||
1592 | ah->sw_mgmt_crypto_rx = false; | ||
1593 | } else if (AR_SREV_9160_10_OR_LATER(ah)) { | 1593 | } else if (AR_SREV_9160_10_OR_LATER(ah)) { |
1594 | /* Disable hardware crypto for management frames */ | 1594 | /* Disable hardware crypto for management frames */ |
1595 | REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, | 1595 | REG_CLR_BIT(ah, AR_PCU_MISC_MODE2, |
1596 | AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); | 1596 | AR_PCU_MISC_MODE2_MGMT_CRYPTO_ENABLE); |
1597 | REG_SET_BIT(ah, AR_PCU_MISC_MODE2, | 1597 | REG_SET_BIT(ah, AR_PCU_MISC_MODE2, |
1598 | AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); | 1598 | AR_PCU_MISC_MODE2_NO_CRYPTO_FOR_NON_DATA_PKT); |
1599 | ah->sw_mgmt_crypto = true; | 1599 | ah->sw_mgmt_crypto_tx = true; |
1600 | ah->sw_mgmt_crypto_rx = true; | ||
1600 | } else { | 1601 | } else { |
1601 | ah->sw_mgmt_crypto = true; | 1602 | ah->sw_mgmt_crypto_tx = true; |
1603 | ah->sw_mgmt_crypto_rx = true; | ||
1602 | } | 1604 | } |
1603 | } | 1605 | } |
1604 | 1606 | ||
@@ -1945,6 +1947,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1945 | 1947 | ||
1946 | REGWRITE_BUFFER_FLUSH(ah); | 1948 | REGWRITE_BUFFER_FLUSH(ah); |
1947 | 1949 | ||
1950 | ath9k_hw_gen_timer_start_tsf2(ah); | ||
1951 | |||
1948 | ath9k_hw_init_desc(ah); | 1952 | ath9k_hw_init_desc(ah); |
1949 | 1953 | ||
1950 | if (ath9k_hw_btcoex_is_enabled(ah)) | 1954 | if (ath9k_hw_btcoex_is_enabled(ah)) |
@@ -1953,8 +1957,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1953 | if (ath9k_hw_mci_is_enabled(ah)) | 1957 | if (ath9k_hw_mci_is_enabled(ah)) |
1954 | ar9003_mci_check_bt(ah); | 1958 | ar9003_mci_check_bt(ah); |
1955 | 1959 | ||
1956 | ath9k_hw_loadnf(ah, chan); | 1960 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
1957 | ath9k_hw_start_nfcal(ah, true); | 1961 | ath9k_hw_loadnf(ah, chan); |
1962 | ath9k_hw_start_nfcal(ah, true); | ||
1963 | } | ||
1958 | 1964 | ||
1959 | if (AR_SREV_9300_20_OR_LATER(ah)) | 1965 | if (AR_SREV_9300_20_OR_LATER(ah)) |
1960 | ar9003_hw_bb_watchdog_config(ah); | 1966 | ar9003_hw_bb_watchdog_config(ah); |
@@ -2322,7 +2328,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2322 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 2328 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
2323 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); | 2329 | struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); |
2324 | struct ath_common *common = ath9k_hw_common(ah); | 2330 | struct ath_common *common = ath9k_hw_common(ah); |
2325 | unsigned int chip_chainmask; | ||
2326 | 2331 | ||
2327 | u16 eeval; | 2332 | u16 eeval; |
2328 | u8 ant_div_ctl1, tx_chainmask, rx_chainmask; | 2333 | u8 ant_div_ctl1, tx_chainmask, rx_chainmask; |
@@ -2342,31 +2347,40 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2342 | } | 2347 | } |
2343 | 2348 | ||
2344 | eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); | 2349 | eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); |
2345 | if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) { | 2350 | |
2346 | ath_err(common, | 2351 | if (eeval & AR5416_OPFLAGS_11A) { |
2347 | "no band has been marked as supported in EEPROM\n"); | 2352 | if (ah->disable_5ghz) |
2348 | return -EINVAL; | 2353 | ath_warn(common, "disabling 5GHz band\n"); |
2354 | else | ||
2355 | pCap->hw_caps |= ATH9K_HW_CAP_5GHZ; | ||
2349 | } | 2356 | } |
2350 | 2357 | ||
2351 | if (eeval & AR5416_OPFLAGS_11A) | 2358 | if (eeval & AR5416_OPFLAGS_11G) { |
2352 | pCap->hw_caps |= ATH9K_HW_CAP_5GHZ; | 2359 | if (ah->disable_2ghz) |
2360 | ath_warn(common, "disabling 2GHz band\n"); | ||
2361 | else | ||
2362 | pCap->hw_caps |= ATH9K_HW_CAP_2GHZ; | ||
2363 | } | ||
2353 | 2364 | ||
2354 | if (eeval & AR5416_OPFLAGS_11G) | 2365 | if ((pCap->hw_caps & (ATH9K_HW_CAP_2GHZ | ATH9K_HW_CAP_5GHZ)) == 0) { |
2355 | pCap->hw_caps |= ATH9K_HW_CAP_2GHZ; | 2366 | ath_err(common, "both bands are disabled\n"); |
2367 | return -EINVAL; | ||
2368 | } | ||
2356 | 2369 | ||
2357 | if (AR_SREV_9485(ah) || | 2370 | if (AR_SREV_9485(ah) || |
2358 | AR_SREV_9285(ah) || | 2371 | AR_SREV_9285(ah) || |
2359 | AR_SREV_9330(ah) || | 2372 | AR_SREV_9330(ah) || |
2360 | AR_SREV_9565(ah)) | 2373 | AR_SREV_9565(ah)) |
2361 | chip_chainmask = 1; | 2374 | pCap->chip_chainmask = 1; |
2362 | else if (AR_SREV_9462(ah)) | ||
2363 | chip_chainmask = 3; | ||
2364 | else if (!AR_SREV_9280_20_OR_LATER(ah)) | 2375 | else if (!AR_SREV_9280_20_OR_LATER(ah)) |
2365 | chip_chainmask = 7; | 2376 | pCap->chip_chainmask = 7; |
2366 | else if (!AR_SREV_9300_20_OR_LATER(ah) || AR_SREV_9340(ah)) | 2377 | else if (!AR_SREV_9300_20_OR_LATER(ah) || |
2367 | chip_chainmask = 3; | 2378 | AR_SREV_9340(ah) || |
2379 | AR_SREV_9462(ah) || | ||
2380 | AR_SREV_9531(ah)) | ||
2381 | pCap->chip_chainmask = 3; | ||
2368 | else | 2382 | else |
2369 | chip_chainmask = 7; | 2383 | pCap->chip_chainmask = 7; |
2370 | 2384 | ||
2371 | pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK); | 2385 | pCap->tx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_TX_MASK); |
2372 | /* | 2386 | /* |
@@ -2384,8 +2398,8 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2384 | /* Use rx_chainmask from EEPROM. */ | 2398 | /* Use rx_chainmask from EEPROM. */ |
2385 | pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); | 2399 | pCap->rx_chainmask = ah->eep_ops->get_eeprom(ah, EEP_RX_MASK); |
2386 | 2400 | ||
2387 | pCap->tx_chainmask = fixup_chainmask(chip_chainmask, pCap->tx_chainmask); | 2401 | pCap->tx_chainmask = fixup_chainmask(pCap->chip_chainmask, pCap->tx_chainmask); |
2388 | pCap->rx_chainmask = fixup_chainmask(chip_chainmask, pCap->rx_chainmask); | 2402 | pCap->rx_chainmask = fixup_chainmask(pCap->chip_chainmask, pCap->rx_chainmask); |
2389 | ah->txchainmask = pCap->tx_chainmask; | 2403 | ah->txchainmask = pCap->tx_chainmask; |
2390 | ah->rxchainmask = pCap->rx_chainmask; | 2404 | ah->rxchainmask = pCap->rx_chainmask; |
2391 | 2405 | ||
@@ -2899,6 +2913,16 @@ u32 ath9k_hw_gettsf32(struct ath_hw *ah) | |||
2899 | } | 2913 | } |
2900 | EXPORT_SYMBOL(ath9k_hw_gettsf32); | 2914 | EXPORT_SYMBOL(ath9k_hw_gettsf32); |
2901 | 2915 | ||
2916 | void ath9k_hw_gen_timer_start_tsf2(struct ath_hw *ah) | ||
2917 | { | ||
2918 | struct ath_gen_timer_table *timer_table = &ah->hw_gen_timers; | ||
2919 | |||
2920 | if (timer_table->tsf2_enabled) { | ||
2921 | REG_SET_BIT(ah, AR_DIRECT_CONNECT, AR_DC_AP_STA_EN); | ||
2922 | REG_SET_BIT(ah, AR_RESET_TSF, AR_RESET_TSF2_ONCE); | ||
2923 | } | ||
2924 | } | ||
2925 | |||
2902 | struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, | 2926 | struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, |
2903 | void (*trigger)(void *), | 2927 | void (*trigger)(void *), |
2904 | void (*overflow)(void *), | 2928 | void (*overflow)(void *), |
@@ -2909,7 +2933,11 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, | |||
2909 | struct ath_gen_timer *timer; | 2933 | struct ath_gen_timer *timer; |
2910 | 2934 | ||
2911 | if ((timer_index < AR_FIRST_NDP_TIMER) || | 2935 | if ((timer_index < AR_FIRST_NDP_TIMER) || |
2912 | (timer_index >= ATH_MAX_GEN_TIMER)) | 2936 | (timer_index >= ATH_MAX_GEN_TIMER)) |
2937 | return NULL; | ||
2938 | |||
2939 | if ((timer_index > AR_FIRST_NDP_TIMER) && | ||
2940 | !AR_SREV_9300_20_OR_LATER(ah)) | ||
2913 | return NULL; | 2941 | return NULL; |
2914 | 2942 | ||
2915 | timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); | 2943 | timer = kzalloc(sizeof(struct ath_gen_timer), GFP_KERNEL); |
@@ -2923,6 +2951,11 @@ struct ath_gen_timer *ath_gen_timer_alloc(struct ath_hw *ah, | |||
2923 | timer->overflow = overflow; | 2951 | timer->overflow = overflow; |
2924 | timer->arg = arg; | 2952 | timer->arg = arg; |
2925 | 2953 | ||
2954 | if ((timer_index > AR_FIRST_NDP_TIMER) && !timer_table->tsf2_enabled) { | ||
2955 | timer_table->tsf2_enabled = true; | ||
2956 | ath9k_hw_gen_timer_start_tsf2(ah); | ||
2957 | } | ||
2958 | |||
2926 | return timer; | 2959 | return timer; |
2927 | } | 2960 | } |
2928 | EXPORT_SYMBOL(ath_gen_timer_alloc); | 2961 | EXPORT_SYMBOL(ath_gen_timer_alloc); |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 975074fc11bc..4cf9e0ac0743 100644 --- a/drivers/net/wireless/ath/ath9k/hw.h +++ b/drivers/net/wireless/ath/ath9k/hw.h | |||
@@ -244,13 +244,20 @@ enum ath9k_hw_caps { | |||
244 | ATH9K_HW_CAP_2GHZ = BIT(11), | 244 | ATH9K_HW_CAP_2GHZ = BIT(11), |
245 | ATH9K_HW_CAP_5GHZ = BIT(12), | 245 | ATH9K_HW_CAP_5GHZ = BIT(12), |
246 | ATH9K_HW_CAP_APM = BIT(13), | 246 | ATH9K_HW_CAP_APM = BIT(13), |
247 | #ifdef CONFIG_ATH9K_PCOEM | ||
247 | ATH9K_HW_CAP_RTT = BIT(14), | 248 | ATH9K_HW_CAP_RTT = BIT(14), |
248 | ATH9K_HW_CAP_MCI = BIT(15), | 249 | ATH9K_HW_CAP_MCI = BIT(15), |
249 | ATH9K_HW_CAP_DFS = BIT(16), | 250 | ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(16), |
250 | ATH9K_HW_WOW_DEVICE_CAPABLE = BIT(17), | 251 | ATH9K_HW_CAP_BT_ANT_DIV = BIT(17), |
251 | ATH9K_HW_CAP_PAPRD = BIT(18), | 252 | #else |
252 | ATH9K_HW_CAP_FCC_BAND_SWITCH = BIT(19), | 253 | ATH9K_HW_CAP_RTT = 0, |
253 | ATH9K_HW_CAP_BT_ANT_DIV = BIT(20), | 254 | ATH9K_HW_CAP_MCI = 0, |
255 | ATH9K_HW_WOW_DEVICE_CAPABLE = 0, | ||
256 | ATH9K_HW_CAP_BT_ANT_DIV = 0, | ||
257 | #endif | ||
258 | ATH9K_HW_CAP_DFS = BIT(18), | ||
259 | ATH9K_HW_CAP_PAPRD = BIT(19), | ||
260 | ATH9K_HW_CAP_FCC_BAND_SWITCH = BIT(20), | ||
254 | }; | 261 | }; |
255 | 262 | ||
256 | /* | 263 | /* |
@@ -269,6 +276,7 @@ struct ath9k_hw_capabilities { | |||
269 | u16 rts_aggr_limit; | 276 | u16 rts_aggr_limit; |
270 | u8 tx_chainmask; | 277 | u8 tx_chainmask; |
271 | u8 rx_chainmask; | 278 | u8 rx_chainmask; |
279 | u8 chip_chainmask; | ||
272 | u8 max_txchains; | 280 | u8 max_txchains; |
273 | u8 max_rxchains; | 281 | u8 max_rxchains; |
274 | u8 num_gpio_pins; | 282 | u8 num_gpio_pins; |
@@ -322,6 +330,7 @@ struct ath9k_ops_config { | |||
322 | bool alt_mingainidx; | 330 | bool alt_mingainidx; |
323 | bool no_pll_pwrsave; | 331 | bool no_pll_pwrsave; |
324 | bool tx_gain_buffalo; | 332 | bool tx_gain_buffalo; |
333 | bool led_active_high; | ||
325 | }; | 334 | }; |
326 | 335 | ||
327 | enum ath9k_int { | 336 | enum ath9k_int { |
@@ -517,6 +526,7 @@ struct ath_gen_timer { | |||
517 | struct ath_gen_timer_table { | 526 | struct ath_gen_timer_table { |
518 | struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER]; | 527 | struct ath_gen_timer *timers[ATH_MAX_GEN_TIMER]; |
519 | u16 timer_mask; | 528 | u16 timer_mask; |
529 | bool tsf2_enabled; | ||
520 | }; | 530 | }; |
521 | 531 | ||
522 | struct ath_hw_antcomb_conf { | 532 | struct ath_hw_antcomb_conf { |
@@ -681,10 +691,8 @@ struct ath_hw_ops { | |||
681 | bool power_off); | 691 | bool power_off); |
682 | void (*rx_enable)(struct ath_hw *ah); | 692 | void (*rx_enable)(struct ath_hw *ah); |
683 | void (*set_desc_link)(void *ds, u32 link); | 693 | void (*set_desc_link)(void *ds, u32 link); |
684 | bool (*calibrate)(struct ath_hw *ah, | 694 | int (*calibrate)(struct ath_hw *ah, struct ath9k_channel *chan, |
685 | struct ath9k_channel *chan, | 695 | u8 rxchainmask, bool longcal); |
686 | u8 rxchainmask, | ||
687 | bool longcal); | ||
688 | bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked, | 696 | bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked, |
689 | u32 *sync_cause_p); | 697 | u32 *sync_cause_p); |
690 | void (*set_txdesc)(struct ath_hw *ah, void *ds, | 698 | void (*set_txdesc)(struct ath_hw *ah, void *ds, |
@@ -726,6 +734,7 @@ enum ath_cal_list { | |||
726 | #define AH_USE_EEPROM 0x1 | 734 | #define AH_USE_EEPROM 0x1 |
727 | #define AH_UNPLUGGED 0x2 /* The card has been physically removed. */ | 735 | #define AH_UNPLUGGED 0x2 /* The card has been physically removed. */ |
728 | #define AH_FASTCC 0x4 | 736 | #define AH_FASTCC 0x4 |
737 | #define AH_NO_EEP_SWAP 0x8 /* Do not swap EEPROM data */ | ||
729 | 738 | ||
730 | struct ath_hw { | 739 | struct ath_hw { |
731 | struct ath_ops reg_ops; | 740 | struct ath_ops reg_ops; |
@@ -747,7 +756,8 @@ struct ath_hw { | |||
747 | } eeprom; | 756 | } eeprom; |
748 | const struct eeprom_ops *eep_ops; | 757 | const struct eeprom_ops *eep_ops; |
749 | 758 | ||
750 | bool sw_mgmt_crypto; | 759 | bool sw_mgmt_crypto_tx; |
760 | bool sw_mgmt_crypto_rx; | ||
751 | bool is_pciexpress; | 761 | bool is_pciexpress; |
752 | bool aspm_enabled; | 762 | bool aspm_enabled; |
753 | bool is_monitoring; | 763 | bool is_monitoring; |
@@ -924,6 +934,8 @@ struct ath_hw { | |||
924 | bool is_clk_25mhz; | 934 | bool is_clk_25mhz; |
925 | int (*get_mac_revision)(void); | 935 | int (*get_mac_revision)(void); |
926 | int (*external_reset)(void); | 936 | int (*external_reset)(void); |
937 | bool disable_2ghz; | ||
938 | bool disable_5ghz; | ||
927 | 939 | ||
928 | const struct firmware *eeprom_blob; | 940 | const struct firmware *eeprom_blob; |
929 | 941 | ||
@@ -1027,6 +1039,7 @@ void ath9k_hw_gen_timer_start(struct ath_hw *ah, | |||
1027 | struct ath_gen_timer *timer, | 1039 | struct ath_gen_timer *timer, |
1028 | u32 timer_next, | 1040 | u32 timer_next, |
1029 | u32 timer_period); | 1041 | u32 timer_period); |
1042 | void ath9k_hw_gen_timer_start_tsf2(struct ath_hw *ah); | ||
1030 | void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer); | 1043 | void ath9k_hw_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer); |
1031 | 1044 | ||
1032 | void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer); | 1045 | void ath_gen_timer_free(struct ath_hw *ah, struct ath_gen_timer *timer); |
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 156a944134dc..59d679cebc89 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -88,6 +88,21 @@ static const struct ieee80211_tpt_blink ath9k_tpt_blink[] = { | |||
88 | 88 | ||
89 | static void ath9k_deinit_softc(struct ath_softc *sc); | 89 | static void ath9k_deinit_softc(struct ath_softc *sc); |
90 | 90 | ||
91 | static void ath9k_op_ps_wakeup(struct ath_common *common) | ||
92 | { | ||
93 | ath9k_ps_wakeup((struct ath_softc *) common->priv); | ||
94 | } | ||
95 | |||
96 | static void ath9k_op_ps_restore(struct ath_common *common) | ||
97 | { | ||
98 | ath9k_ps_restore((struct ath_softc *) common->priv); | ||
99 | } | ||
100 | |||
101 | static struct ath_ps_ops ath9k_ps_ops = { | ||
102 | .wakeup = ath9k_op_ps_wakeup, | ||
103 | .restore = ath9k_op_ps_restore, | ||
104 | }; | ||
105 | |||
91 | /* | 106 | /* |
92 | * Read and write, they both share the same lock. We do this to serialize | 107 | * Read and write, they both share the same lock. We do this to serialize |
93 | * reads and writes on Atheros 802.11n PCI devices only. This is required | 108 | * reads and writes on Atheros 802.11n PCI devices only. This is required |
@@ -172,17 +187,20 @@ static void ath9k_reg_notifier(struct wiphy *wiphy, | |||
172 | ath_reg_notifier_apply(wiphy, request, reg); | 187 | ath_reg_notifier_apply(wiphy, request, reg); |
173 | 188 | ||
174 | /* Set tx power */ | 189 | /* Set tx power */ |
175 | if (ah->curchan) { | 190 | if (!ah->curchan) |
176 | sc->cur_chan->txpower = 2 * ah->curchan->chan->max_power; | 191 | return; |
177 | ath9k_ps_wakeup(sc); | 192 | |
178 | ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false); | 193 | sc->cur_chan->txpower = 2 * ah->curchan->chan->max_power; |
179 | sc->curtxpow = ath9k_hw_regulatory(ah)->power_limit; | 194 | ath9k_ps_wakeup(sc); |
180 | /* synchronize DFS detector if regulatory domain changed */ | 195 | ath9k_hw_set_txpowerlimit(ah, sc->cur_chan->txpower, false); |
181 | if (sc->dfs_detector != NULL) | 196 | ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower, |
182 | sc->dfs_detector->set_dfs_domain(sc->dfs_detector, | 197 | sc->cur_chan->txpower, |
183 | request->dfs_region); | 198 | &sc->cur_chan->cur_txpower); |
184 | ath9k_ps_restore(sc); | 199 | /* synchronize DFS detector if regulatory domain changed */ |
185 | } | 200 | if (sc->dfs_detector != NULL) |
201 | sc->dfs_detector->set_dfs_domain(sc->dfs_detector, | ||
202 | request->dfs_region); | ||
203 | ath9k_ps_restore(sc); | ||
186 | } | 204 | } |
187 | 205 | ||
188 | /* | 206 | /* |
@@ -348,12 +366,13 @@ static void ath9k_init_misc(struct ath_softc *sc) | |||
348 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) | 366 | if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_ANT_DIV_COMB) |
349 | sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; | 367 | sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; |
350 | 368 | ||
351 | sc->spec_config.enabled = 0; | 369 | sc->spec_priv.ah = sc->sc_ah; |
352 | sc->spec_config.short_repeat = true; | 370 | sc->spec_priv.spec_config.enabled = 0; |
353 | sc->spec_config.count = 8; | 371 | sc->spec_priv.spec_config.short_repeat = true; |
354 | sc->spec_config.endless = false; | 372 | sc->spec_priv.spec_config.count = 8; |
355 | sc->spec_config.period = 0xFF; | 373 | sc->spec_priv.spec_config.endless = false; |
356 | sc->spec_config.fft_period = 0xF; | 374 | sc->spec_priv.spec_config.period = 0xFF; |
375 | sc->spec_priv.spec_config.fft_period = 0xF; | ||
357 | } | 376 | } |
358 | 377 | ||
359 | static void ath9k_init_pcoem_platform(struct ath_softc *sc) | 378 | static void ath9k_init_pcoem_platform(struct ath_softc *sc) |
@@ -362,6 +381,9 @@ static void ath9k_init_pcoem_platform(struct ath_softc *sc) | |||
362 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 381 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
363 | struct ath_common *common = ath9k_hw_common(ah); | 382 | struct ath_common *common = ath9k_hw_common(ah); |
364 | 383 | ||
384 | if (!IS_ENABLED(CONFIG_ATH9K_PCOEM)) | ||
385 | return; | ||
386 | |||
365 | if (common->bus_ops->ath_bus_type != ATH_PCI) | 387 | if (common->bus_ops->ath_bus_type != ATH_PCI) |
366 | return; | 388 | return; |
367 | 389 | ||
@@ -419,6 +441,9 @@ static void ath9k_init_pcoem_platform(struct ath_softc *sc) | |||
419 | ah->config.no_pll_pwrsave = true; | 441 | ah->config.no_pll_pwrsave = true; |
420 | ath_info(common, "Disable PLL PowerSave\n"); | 442 | ath_info(common, "Disable PLL PowerSave\n"); |
421 | } | 443 | } |
444 | |||
445 | if (sc->driver_data & ATH9K_PCI_LED_ACT_HI) | ||
446 | ah->config.led_active_high = true; | ||
422 | } | 447 | } |
423 | 448 | ||
424 | static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob, | 449 | static void ath9k_eeprom_request_cb(const struct firmware *eeprom_blob, |
@@ -528,10 +553,15 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
528 | ah->is_clk_25mhz = pdata->is_clk_25mhz; | 553 | ah->is_clk_25mhz = pdata->is_clk_25mhz; |
529 | ah->get_mac_revision = pdata->get_mac_revision; | 554 | ah->get_mac_revision = pdata->get_mac_revision; |
530 | ah->external_reset = pdata->external_reset; | 555 | ah->external_reset = pdata->external_reset; |
556 | ah->disable_2ghz = pdata->disable_2ghz; | ||
557 | ah->disable_5ghz = pdata->disable_5ghz; | ||
558 | if (!pdata->endian_check) | ||
559 | ah->ah_flags |= AH_NO_EEP_SWAP; | ||
531 | } | 560 | } |
532 | 561 | ||
533 | common->ops = &ah->reg_ops; | 562 | common->ops = &ah->reg_ops; |
534 | common->bus_ops = bus_ops; | 563 | common->bus_ops = bus_ops; |
564 | common->ps_ops = &ath9k_ps_ops; | ||
535 | common->ah = ah; | 565 | common->ah = ah; |
536 | common->hw = sc->hw; | 566 | common->hw = sc->hw; |
537 | common->priv = sc; | 567 | common->priv = sc; |
@@ -734,6 +764,32 @@ static const struct ieee80211_iface_combination if_comb[] = { | |||
734 | #endif | 764 | #endif |
735 | }; | 765 | }; |
736 | 766 | ||
767 | #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT | ||
768 | static void ath9k_set_mcc_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | ||
769 | { | ||
770 | struct ath_hw *ah = sc->sc_ah; | ||
771 | struct ath_common *common = ath9k_hw_common(ah); | ||
772 | |||
773 | if (!ath9k_is_chanctx_enabled()) | ||
774 | return; | ||
775 | |||
776 | hw->flags |= IEEE80211_HW_QUEUE_CONTROL; | ||
777 | hw->queues = ATH9K_NUM_TX_QUEUES; | ||
778 | hw->offchannel_tx_hw_queue = hw->queues - 1; | ||
779 | hw->wiphy->interface_modes &= ~ BIT(NL80211_IFTYPE_WDS); | ||
780 | hw->wiphy->iface_combinations = if_comb_multi; | ||
781 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_multi); | ||
782 | hw->wiphy->max_scan_ssids = 255; | ||
783 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; | ||
784 | hw->wiphy->max_remain_on_channel_duration = 10000; | ||
785 | hw->chanctx_data_size = sizeof(void *); | ||
786 | hw->extra_beacon_tailroom = | ||
787 | sizeof(struct ieee80211_p2p_noa_attr) + 9; | ||
788 | |||
789 | ath_dbg(common, CHAN_CTX, "Use channel contexts\n"); | ||
790 | } | ||
791 | #endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */ | ||
792 | |||
737 | static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | 793 | static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) |
738 | { | 794 | { |
739 | struct ath_hw *ah = sc->sc_ah; | 795 | struct ath_hw *ah = sc->sc_ah; |
@@ -746,7 +802,6 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
746 | IEEE80211_HW_SPECTRUM_MGMT | | 802 | IEEE80211_HW_SPECTRUM_MGMT | |
747 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | | 803 | IEEE80211_HW_REPORTS_TX_ACK_STATUS | |
748 | IEEE80211_HW_SUPPORTS_RC_TABLE | | 804 | IEEE80211_HW_SUPPORTS_RC_TABLE | |
749 | IEEE80211_HW_QUEUE_CONTROL | | ||
750 | IEEE80211_HW_SUPPORTS_HT_CCK_RATES; | 805 | IEEE80211_HW_SUPPORTS_HT_CCK_RATES; |
751 | 806 | ||
752 | if (ath9k_ps_enable) | 807 | if (ath9k_ps_enable) |
@@ -781,24 +836,6 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
781 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); | 836 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb); |
782 | } | 837 | } |
783 | 838 | ||
784 | #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT | ||
785 | |||
786 | if (ath9k_is_chanctx_enabled()) { | ||
787 | hw->wiphy->interface_modes &= ~ BIT(NL80211_IFTYPE_WDS); | ||
788 | hw->wiphy->iface_combinations = if_comb_multi; | ||
789 | hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb_multi); | ||
790 | hw->wiphy->max_scan_ssids = 255; | ||
791 | hw->wiphy->max_scan_ie_len = IEEE80211_MAX_DATA_LEN; | ||
792 | hw->wiphy->max_remain_on_channel_duration = 10000; | ||
793 | hw->chanctx_data_size = sizeof(void *); | ||
794 | hw->extra_beacon_tailroom = | ||
795 | sizeof(struct ieee80211_p2p_noa_attr) + 9; | ||
796 | |||
797 | ath_dbg(common, CHAN_CTX, "Use channel contexts\n"); | ||
798 | } | ||
799 | |||
800 | #endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */ | ||
801 | |||
802 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; | 839 | hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; |
803 | 840 | ||
804 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; | 841 | hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; |
@@ -808,12 +845,7 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
808 | hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; | 845 | hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; |
809 | hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; | 846 | hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; |
810 | 847 | ||
811 | /* allow 4 queues per channel context + | 848 | hw->queues = 4; |
812 | * 1 cab queue + 1 offchannel tx queue | ||
813 | */ | ||
814 | hw->queues = ATH9K_NUM_TX_QUEUES; | ||
815 | /* last queue for offchannel */ | ||
816 | hw->offchannel_tx_hw_queue = hw->queues - 1; | ||
817 | hw->max_rates = 4; | 849 | hw->max_rates = 4; |
818 | hw->max_listen_interval = 10; | 850 | hw->max_listen_interval = 10; |
819 | hw->max_rate_tries = 10; | 851 | hw->max_rate_tries = 10; |
@@ -837,6 +869,9 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw) | |||
837 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = | 869 | hw->wiphy->bands[IEEE80211_BAND_5GHZ] = |
838 | &common->sbands[IEEE80211_BAND_5GHZ]; | 870 | &common->sbands[IEEE80211_BAND_5GHZ]; |
839 | 871 | ||
872 | #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT | ||
873 | ath9k_set_mcc_capab(sc, hw); | ||
874 | #endif | ||
840 | ath9k_init_wow(hw); | 875 | ath9k_init_wow(hw); |
841 | ath9k_cmn_reload_chainmask(ah); | 876 | ath9k_cmn_reload_chainmask(ah); |
842 | 877 | ||
diff --git a/drivers/net/wireless/ath/ath9k/link.c b/drivers/net/wireless/ath/ath9k/link.c index 2343f56e6498..b829263e3d0a 100644 --- a/drivers/net/wireless/ath/ath9k/link.c +++ b/drivers/net/wireless/ath/ath9k/link.c | |||
@@ -371,9 +371,15 @@ void ath_ani_calibrate(unsigned long data) | |||
371 | 371 | ||
372 | /* Perform calibration if necessary */ | 372 | /* Perform calibration if necessary */ |
373 | if (longcal || shortcal) { | 373 | if (longcal || shortcal) { |
374 | common->ani.caldone = | 374 | int ret = ath9k_hw_calibrate(ah, ah->curchan, ah->rxchainmask, |
375 | ath9k_hw_calibrate(ah, ah->curchan, | 375 | longcal); |
376 | ah->rxchainmask, longcal); | 376 | if (ret < 0) { |
377 | common->ani.caldone = 0; | ||
378 | ath9k_queue_reset(sc, RESET_TYPE_CALIBRATION); | ||
379 | return; | ||
380 | } | ||
381 | |||
382 | common->ani.caldone = ret; | ||
377 | } | 383 | } |
378 | 384 | ||
379 | ath_dbg(common, ANI, | 385 | ath_dbg(common, ANI, |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 205162449b72..7c63976b5b0c 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -54,7 +54,8 @@ u8 ath9k_parse_mpdudensity(u8 mpdudensity) | |||
54 | } | 54 | } |
55 | } | 55 | } |
56 | 56 | ||
57 | static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq) | 57 | static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq, |
58 | bool sw_pending) | ||
58 | { | 59 | { |
59 | bool pending = false; | 60 | bool pending = false; |
60 | 61 | ||
@@ -65,6 +66,9 @@ static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq) | |||
65 | goto out; | 66 | goto out; |
66 | } | 67 | } |
67 | 68 | ||
69 | if (!sw_pending) | ||
70 | goto out; | ||
71 | |||
68 | if (txq->mac80211_qnum >= 0) { | 72 | if (txq->mac80211_qnum >= 0) { |
69 | struct list_head *list; | 73 | struct list_head *list; |
70 | 74 | ||
@@ -229,8 +233,9 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
229 | 233 | ||
230 | ath9k_calculate_summary_state(sc, sc->cur_chan); | 234 | ath9k_calculate_summary_state(sc, sc->cur_chan); |
231 | ath_startrecv(sc); | 235 | ath_startrecv(sc); |
232 | ath9k_cmn_update_txpow(ah, sc->curtxpow, | 236 | ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower, |
233 | sc->cur_chan->txpower, &sc->curtxpow); | 237 | sc->cur_chan->txpower, |
238 | &sc->cur_chan->cur_txpower); | ||
234 | clear_bit(ATH_OP_HW_RESET, &common->op_flags); | 239 | clear_bit(ATH_OP_HW_RESET, &common->op_flags); |
235 | 240 | ||
236 | if (!sc->cur_chan->offchannel && start) { | 241 | if (!sc->cur_chan->offchannel && start) { |
@@ -270,7 +275,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
270 | return true; | 275 | return true; |
271 | } | 276 | } |
272 | 277 | ||
273 | int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) | 278 | static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) |
274 | { | 279 | { |
275 | struct ath_hw *ah = sc->sc_ah; | 280 | struct ath_hw *ah = sc->sc_ah; |
276 | struct ath_common *common = ath9k_hw_common(ah); | 281 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -281,6 +286,7 @@ int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) | |||
281 | __ath_cancel_work(sc); | 286 | __ath_cancel_work(sc); |
282 | 287 | ||
283 | tasklet_disable(&sc->intr_tq); | 288 | tasklet_disable(&sc->intr_tq); |
289 | tasklet_disable(&sc->bcon_tasklet); | ||
284 | spin_lock_bh(&sc->sc_pcu_lock); | 290 | spin_lock_bh(&sc->sc_pcu_lock); |
285 | 291 | ||
286 | if (!sc->cur_chan->offchannel) { | 292 | if (!sc->cur_chan->offchannel) { |
@@ -326,6 +332,7 @@ int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) | |||
326 | 332 | ||
327 | out: | 333 | out: |
328 | spin_unlock_bh(&sc->sc_pcu_lock); | 334 | spin_unlock_bh(&sc->sc_pcu_lock); |
335 | tasklet_enable(&sc->bcon_tasklet); | ||
329 | tasklet_enable(&sc->intr_tq); | 336 | tasklet_enable(&sc->intr_tq); |
330 | 337 | ||
331 | return r; | 338 | return r; |
@@ -539,11 +546,10 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
539 | sched = true; | 546 | sched = true; |
540 | 547 | ||
541 | /* | 548 | /* |
542 | * If a FATAL or RXORN interrupt is received, we have to reset the | 549 | * If a FATAL interrupt is received, we have to reset the chip |
543 | * chip immediately. | 550 | * immediately. |
544 | */ | 551 | */ |
545 | if ((status & ATH9K_INT_FATAL) || ((status & ATH9K_INT_RXORN) && | 552 | if (status & ATH9K_INT_FATAL) |
546 | !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))) | ||
547 | goto chip_reset; | 553 | goto chip_reset; |
548 | 554 | ||
549 | if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) && | 555 | if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) && |
@@ -598,17 +604,29 @@ chip_reset: | |||
598 | #undef SCHED_INTR | 604 | #undef SCHED_INTR |
599 | } | 605 | } |
600 | 606 | ||
601 | int ath_reset(struct ath_softc *sc) | 607 | /* |
608 | * This function is called when a HW reset cannot be deferred | ||
609 | * and has to be immediate. | ||
610 | */ | ||
611 | int ath_reset(struct ath_softc *sc, struct ath9k_channel *hchan) | ||
602 | { | 612 | { |
613 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
603 | int r; | 614 | int r; |
604 | 615 | ||
616 | set_bit(ATH_OP_HW_RESET, &common->op_flags); | ||
617 | |||
605 | ath9k_ps_wakeup(sc); | 618 | ath9k_ps_wakeup(sc); |
606 | r = ath_reset_internal(sc, NULL); | 619 | r = ath_reset_internal(sc, hchan); |
607 | ath9k_ps_restore(sc); | 620 | ath9k_ps_restore(sc); |
608 | 621 | ||
609 | return r; | 622 | return r; |
610 | } | 623 | } |
611 | 624 | ||
625 | /* | ||
626 | * When a HW reset can be deferred, it is added to the | ||
627 | * hw_reset_work workqueue, but we set ATH_OP_HW_RESET before | ||
628 | * queueing. | ||
629 | */ | ||
612 | void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type) | 630 | void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type) |
613 | { | 631 | { |
614 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 632 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
@@ -623,7 +641,9 @@ void ath_reset_work(struct work_struct *work) | |||
623 | { | 641 | { |
624 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work); | 642 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work); |
625 | 643 | ||
626 | ath_reset(sc); | 644 | ath9k_ps_wakeup(sc); |
645 | ath_reset_internal(sc, NULL); | ||
646 | ath9k_ps_restore(sc); | ||
627 | } | 647 | } |
628 | 648 | ||
629 | /**********************/ | 649 | /**********************/ |
@@ -707,7 +727,8 @@ static int ath9k_start(struct ieee80211_hw *hw) | |||
707 | if (ah->led_pin >= 0) { | 727 | if (ah->led_pin >= 0) { |
708 | ath9k_hw_cfg_output(ah, ah->led_pin, | 728 | ath9k_hw_cfg_output(ah, ah->led_pin, |
709 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); | 729 | AR_GPIO_OUTPUT_MUX_AS_OUTPUT); |
710 | ath9k_hw_set_gpio(ah, ah->led_pin, 0); | 730 | ath9k_hw_set_gpio(ah, ah->led_pin, |
731 | (ah->config.led_active_high) ? 1 : 0); | ||
711 | } | 732 | } |
712 | 733 | ||
713 | /* | 734 | /* |
@@ -849,7 +870,8 @@ static void ath9k_stop(struct ieee80211_hw *hw) | |||
849 | spin_lock_bh(&sc->sc_pcu_lock); | 870 | spin_lock_bh(&sc->sc_pcu_lock); |
850 | 871 | ||
851 | if (ah->led_pin >= 0) { | 872 | if (ah->led_pin >= 0) { |
852 | ath9k_hw_set_gpio(ah, ah->led_pin, 1); | 873 | ath9k_hw_set_gpio(ah, ah->led_pin, |
874 | (ah->config.led_active_high) ? 0 : 1); | ||
853 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); | 875 | ath9k_hw_cfg_gpio_input(ah, ah->led_pin); |
854 | } | 876 | } |
855 | 877 | ||
@@ -1037,7 +1059,7 @@ static void ath9k_set_offchannel_state(struct ath_softc *sc) | |||
1037 | 1059 | ||
1038 | eth_zero_addr(common->curbssid); | 1060 | eth_zero_addr(common->curbssid); |
1039 | eth_broadcast_addr(common->bssidmask); | 1061 | eth_broadcast_addr(common->bssidmask); |
1040 | ether_addr_copy(common->macaddr, vif->addr); | 1062 | memcpy(common->macaddr, vif->addr, ETH_ALEN); |
1041 | common->curaid = 0; | 1063 | common->curaid = 0; |
1042 | ah->opmode = vif->type; | 1064 | ah->opmode = vif->type; |
1043 | ah->imask &= ~ATH9K_INT_SWBA; | 1065 | ah->imask &= ~ATH9K_INT_SWBA; |
@@ -1078,7 +1100,7 @@ void ath9k_calculate_summary_state(struct ath_softc *sc, | |||
1078 | ath9k_calculate_iter_data(sc, ctx, &iter_data); | 1100 | ath9k_calculate_iter_data(sc, ctx, &iter_data); |
1079 | 1101 | ||
1080 | if (iter_data.has_hw_macaddr) | 1102 | if (iter_data.has_hw_macaddr) |
1081 | ether_addr_copy(common->macaddr, iter_data.hw_macaddr); | 1103 | memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN); |
1082 | 1104 | ||
1083 | memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); | 1105 | memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); |
1084 | ath_hw_setbssidmask(common); | 1106 | ath_hw_setbssidmask(common); |
@@ -1162,10 +1184,14 @@ static void ath9k_assign_hw_queues(struct ieee80211_hw *hw, | |||
1162 | { | 1184 | { |
1163 | int i; | 1185 | int i; |
1164 | 1186 | ||
1187 | if (!ath9k_is_chanctx_enabled()) | ||
1188 | return; | ||
1189 | |||
1165 | for (i = 0; i < IEEE80211_NUM_ACS; i++) | 1190 | for (i = 0; i < IEEE80211_NUM_ACS; i++) |
1166 | vif->hw_queue[i] = i; | 1191 | vif->hw_queue[i] = i; |
1167 | 1192 | ||
1168 | if (vif->type == NL80211_IFTYPE_AP) | 1193 | if (vif->type == NL80211_IFTYPE_AP || |
1194 | vif->type == NL80211_IFTYPE_MESH_POINT) | ||
1169 | vif->cab_queue = hw->queues - 2; | 1195 | vif->cab_queue = hw->queues - 2; |
1170 | else | 1196 | else |
1171 | vif->cab_queue = IEEE80211_INVAL_HW_QUEUE; | 1197 | vif->cab_queue = IEEE80211_INVAL_HW_QUEUE; |
@@ -1317,78 +1343,6 @@ static void ath9k_disable_ps(struct ath_softc *sc) | |||
1317 | ath_dbg(common, PS, "PowerSave disabled\n"); | 1343 | ath_dbg(common, PS, "PowerSave disabled\n"); |
1318 | } | 1344 | } |
1319 | 1345 | ||
1320 | void ath9k_spectral_scan_trigger(struct ieee80211_hw *hw) | ||
1321 | { | ||
1322 | struct ath_softc *sc = hw->priv; | ||
1323 | struct ath_hw *ah = sc->sc_ah; | ||
1324 | struct ath_common *common = ath9k_hw_common(ah); | ||
1325 | u32 rxfilter; | ||
1326 | |||
1327 | if (config_enabled(CONFIG_ATH9K_TX99)) | ||
1328 | return; | ||
1329 | |||
1330 | if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { | ||
1331 | ath_err(common, "spectrum analyzer not implemented on this hardware\n"); | ||
1332 | return; | ||
1333 | } | ||
1334 | |||
1335 | ath9k_ps_wakeup(sc); | ||
1336 | rxfilter = ath9k_hw_getrxfilter(ah); | ||
1337 | ath9k_hw_setrxfilter(ah, rxfilter | | ||
1338 | ATH9K_RX_FILTER_PHYRADAR | | ||
1339 | ATH9K_RX_FILTER_PHYERR); | ||
1340 | |||
1341 | /* TODO: usually this should not be neccesary, but for some reason | ||
1342 | * (or in some mode?) the trigger must be called after the | ||
1343 | * configuration, otherwise the register will have its values reset | ||
1344 | * (on my ar9220 to value 0x01002310) | ||
1345 | */ | ||
1346 | ath9k_spectral_scan_config(hw, sc->spectral_mode); | ||
1347 | ath9k_hw_ops(ah)->spectral_scan_trigger(ah); | ||
1348 | ath9k_ps_restore(sc); | ||
1349 | } | ||
1350 | |||
1351 | int ath9k_spectral_scan_config(struct ieee80211_hw *hw, | ||
1352 | enum spectral_mode spectral_mode) | ||
1353 | { | ||
1354 | struct ath_softc *sc = hw->priv; | ||
1355 | struct ath_hw *ah = sc->sc_ah; | ||
1356 | struct ath_common *common = ath9k_hw_common(ah); | ||
1357 | |||
1358 | if (!ath9k_hw_ops(ah)->spectral_scan_trigger) { | ||
1359 | ath_err(common, "spectrum analyzer not implemented on this hardware\n"); | ||
1360 | return -1; | ||
1361 | } | ||
1362 | |||
1363 | switch (spectral_mode) { | ||
1364 | case SPECTRAL_DISABLED: | ||
1365 | sc->spec_config.enabled = 0; | ||
1366 | break; | ||
1367 | case SPECTRAL_BACKGROUND: | ||
1368 | /* send endless samples. | ||
1369 | * TODO: is this really useful for "background"? | ||
1370 | */ | ||
1371 | sc->spec_config.endless = 1; | ||
1372 | sc->spec_config.enabled = 1; | ||
1373 | break; | ||
1374 | case SPECTRAL_CHANSCAN: | ||
1375 | case SPECTRAL_MANUAL: | ||
1376 | sc->spec_config.endless = 0; | ||
1377 | sc->spec_config.enabled = 1; | ||
1378 | break; | ||
1379 | default: | ||
1380 | return -1; | ||
1381 | } | ||
1382 | |||
1383 | ath9k_ps_wakeup(sc); | ||
1384 | ath9k_hw_ops(ah)->spectral_scan_config(ah, &sc->spec_config); | ||
1385 | ath9k_ps_restore(sc); | ||
1386 | |||
1387 | sc->spectral_mode = spectral_mode; | ||
1388 | |||
1389 | return 0; | ||
1390 | } | ||
1391 | |||
1392 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | 1346 | static int ath9k_config(struct ieee80211_hw *hw, u32 changed) |
1393 | { | 1347 | { |
1394 | struct ath_softc *sc = hw->priv; | 1348 | struct ath_softc *sc = hw->priv; |
@@ -1449,8 +1403,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
1449 | if (changed & IEEE80211_CONF_CHANGE_POWER) { | 1403 | if (changed & IEEE80211_CONF_CHANGE_POWER) { |
1450 | ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level); | 1404 | ath_dbg(common, CONFIG, "Set power: %d\n", conf->power_level); |
1451 | sc->cur_chan->txpower = 2 * conf->power_level; | 1405 | sc->cur_chan->txpower = 2 * conf->power_level; |
1452 | ath9k_cmn_update_txpow(ah, sc->curtxpow, | 1406 | ath9k_cmn_update_txpow(ah, sc->cur_chan->cur_txpower, |
1453 | sc->cur_chan->txpower, &sc->curtxpow); | 1407 | sc->cur_chan->txpower, |
1408 | &sc->cur_chan->cur_txpower); | ||
1454 | } | 1409 | } |
1455 | 1410 | ||
1456 | mutex_unlock(&sc->mutex); | 1411 | mutex_unlock(&sc->mutex); |
@@ -1547,6 +1502,40 @@ static int ath9k_sta_remove(struct ieee80211_hw *hw, | |||
1547 | return 0; | 1502 | return 0; |
1548 | } | 1503 | } |
1549 | 1504 | ||
1505 | static int ath9k_sta_state(struct ieee80211_hw *hw, | ||
1506 | struct ieee80211_vif *vif, | ||
1507 | struct ieee80211_sta *sta, | ||
1508 | enum ieee80211_sta_state old_state, | ||
1509 | enum ieee80211_sta_state new_state) | ||
1510 | { | ||
1511 | struct ath_softc *sc = hw->priv; | ||
1512 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1513 | int ret = 0; | ||
1514 | |||
1515 | if (old_state == IEEE80211_STA_AUTH && | ||
1516 | new_state == IEEE80211_STA_ASSOC) { | ||
1517 | ret = ath9k_sta_add(hw, vif, sta); | ||
1518 | ath_dbg(common, CONFIG, | ||
1519 | "Add station: %pM\n", sta->addr); | ||
1520 | } else if (old_state == IEEE80211_STA_ASSOC && | ||
1521 | new_state == IEEE80211_STA_AUTH) { | ||
1522 | ret = ath9k_sta_remove(hw, vif, sta); | ||
1523 | ath_dbg(common, CONFIG, | ||
1524 | "Remove station: %pM\n", sta->addr); | ||
1525 | } | ||
1526 | |||
1527 | if (ath9k_is_chanctx_enabled()) { | ||
1528 | if (vif->type == NL80211_IFTYPE_STATION) { | ||
1529 | if (old_state == IEEE80211_STA_ASSOC && | ||
1530 | new_state == IEEE80211_STA_AUTHORIZED) | ||
1531 | ath_chanctx_event(sc, vif, | ||
1532 | ATH_CHANCTX_EVENT_AUTHORIZED); | ||
1533 | } | ||
1534 | } | ||
1535 | |||
1536 | return ret; | ||
1537 | } | ||
1538 | |||
1550 | static void ath9k_sta_set_tx_filter(struct ath_hw *ah, | 1539 | static void ath9k_sta_set_tx_filter(struct ath_hw *ah, |
1551 | struct ath_node *an, | 1540 | struct ath_node *an, |
1552 | bool set) | 1541 | bool set) |
@@ -1671,7 +1660,7 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
1671 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 1660 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
1672 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) | 1661 | if (key->cipher == WLAN_CIPHER_SUITE_TKIP) |
1673 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | 1662 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
1674 | if (sc->sc_ah->sw_mgmt_crypto && | 1663 | if (sc->sc_ah->sw_mgmt_crypto_tx && |
1675 | key->cipher == WLAN_CIPHER_SUITE_CCMP) | 1664 | key->cipher == WLAN_CIPHER_SUITE_CCMP) |
1676 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; | 1665 | key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX; |
1677 | ret = 0; | 1666 | ret = 0; |
@@ -1731,17 +1720,11 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
1731 | ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n", | 1720 | ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n", |
1732 | bss_conf->bssid, bss_conf->assoc); | 1721 | bss_conf->bssid, bss_conf->assoc); |
1733 | 1722 | ||
1734 | ether_addr_copy(avp->bssid, bss_conf->bssid); | 1723 | memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); |
1735 | avp->aid = bss_conf->aid; | 1724 | avp->aid = bss_conf->aid; |
1736 | avp->assoc = bss_conf->assoc; | 1725 | avp->assoc = bss_conf->assoc; |
1737 | 1726 | ||
1738 | ath9k_calculate_summary_state(sc, avp->chanctx); | 1727 | ath9k_calculate_summary_state(sc, avp->chanctx); |
1739 | |||
1740 | if (ath9k_is_chanctx_enabled()) { | ||
1741 | if (bss_conf->assoc) | ||
1742 | ath_chanctx_event(sc, vif, | ||
1743 | ATH_CHANCTX_EVENT_ASSOC); | ||
1744 | } | ||
1745 | } | 1728 | } |
1746 | 1729 | ||
1747 | if (changed & BSS_CHANGED_IBSS) { | 1730 | if (changed & BSS_CHANGED_IBSS) { |
@@ -1837,6 +1820,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1837 | u16 tid, u16 *ssn, u8 buf_size) | 1820 | u16 tid, u16 *ssn, u8 buf_size) |
1838 | { | 1821 | { |
1839 | struct ath_softc *sc = hw->priv; | 1822 | struct ath_softc *sc = hw->priv; |
1823 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1840 | bool flush = false; | 1824 | bool flush = false; |
1841 | int ret = 0; | 1825 | int ret = 0; |
1842 | 1826 | ||
@@ -1848,6 +1832,12 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1848 | case IEEE80211_AMPDU_RX_STOP: | 1832 | case IEEE80211_AMPDU_RX_STOP: |
1849 | break; | 1833 | break; |
1850 | case IEEE80211_AMPDU_TX_START: | 1834 | case IEEE80211_AMPDU_TX_START: |
1835 | if (ath9k_is_chanctx_enabled()) { | ||
1836 | if (test_bit(ATH_OP_SCANNING, &common->op_flags)) { | ||
1837 | ret = -EBUSY; | ||
1838 | break; | ||
1839 | } | ||
1840 | } | ||
1851 | ath9k_ps_wakeup(sc); | 1841 | ath9k_ps_wakeup(sc); |
1852 | ret = ath_tx_aggr_start(sc, sta, tid, ssn); | 1842 | ret = ath_tx_aggr_start(sc, sta, tid, ssn); |
1853 | if (!ret) | 1843 | if (!ret) |
@@ -1961,7 +1951,8 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, | |||
1961 | mutex_unlock(&sc->mutex); | 1951 | mutex_unlock(&sc->mutex); |
1962 | } | 1952 | } |
1963 | 1953 | ||
1964 | static bool ath9k_has_tx_pending(struct ath_softc *sc) | 1954 | static bool ath9k_has_tx_pending(struct ath_softc *sc, |
1955 | bool sw_pending) | ||
1965 | { | 1956 | { |
1966 | int i, npend = 0; | 1957 | int i, npend = 0; |
1967 | 1958 | ||
@@ -1969,7 +1960,8 @@ static bool ath9k_has_tx_pending(struct ath_softc *sc) | |||
1969 | if (!ATH_TXQ_SETUP(sc, i)) | 1960 | if (!ATH_TXQ_SETUP(sc, i)) |
1970 | continue; | 1961 | continue; |
1971 | 1962 | ||
1972 | npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]); | 1963 | npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i], |
1964 | sw_pending); | ||
1973 | if (npend) | 1965 | if (npend) |
1974 | break; | 1966 | break; |
1975 | } | 1967 | } |
@@ -1981,18 +1973,38 @@ static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
1981 | u32 queues, bool drop) | 1973 | u32 queues, bool drop) |
1982 | { | 1974 | { |
1983 | struct ath_softc *sc = hw->priv; | 1975 | struct ath_softc *sc = hw->priv; |
1976 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1984 | 1977 | ||
1978 | if (ath9k_is_chanctx_enabled()) { | ||
1979 | if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) | ||
1980 | goto flush; | ||
1981 | |||
1982 | /* | ||
1983 | * If MCC is active, extend the flush timeout | ||
1984 | * and wait for the HW/SW queues to become | ||
1985 | * empty. This needs to be done outside the | ||
1986 | * sc->mutex lock to allow the channel scheduler | ||
1987 | * to switch channel contexts. | ||
1988 | * | ||
1989 | * The vif queues have been stopped in mac80211, | ||
1990 | * so there won't be any incoming frames. | ||
1991 | */ | ||
1992 | __ath9k_flush(hw, queues, drop, true, true); | ||
1993 | return; | ||
1994 | } | ||
1995 | flush: | ||
1985 | mutex_lock(&sc->mutex); | 1996 | mutex_lock(&sc->mutex); |
1986 | __ath9k_flush(hw, queues, drop); | 1997 | __ath9k_flush(hw, queues, drop, true, false); |
1987 | mutex_unlock(&sc->mutex); | 1998 | mutex_unlock(&sc->mutex); |
1988 | } | 1999 | } |
1989 | 2000 | ||
1990 | void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | 2001 | void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop, |
2002 | bool sw_pending, bool timeout_override) | ||
1991 | { | 2003 | { |
1992 | struct ath_softc *sc = hw->priv; | 2004 | struct ath_softc *sc = hw->priv; |
1993 | struct ath_hw *ah = sc->sc_ah; | 2005 | struct ath_hw *ah = sc->sc_ah; |
1994 | struct ath_common *common = ath9k_hw_common(ah); | 2006 | struct ath_common *common = ath9k_hw_common(ah); |
1995 | int timeout = HZ / 5; /* 200 ms */ | 2007 | int timeout; |
1996 | bool drain_txq; | 2008 | bool drain_txq; |
1997 | 2009 | ||
1998 | cancel_delayed_work_sync(&sc->tx_complete_work); | 2010 | cancel_delayed_work_sync(&sc->tx_complete_work); |
@@ -2007,7 +2019,17 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | |||
2007 | return; | 2019 | return; |
2008 | } | 2020 | } |
2009 | 2021 | ||
2010 | if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc), | 2022 | spin_lock_bh(&sc->chan_lock); |
2023 | if (timeout_override) | ||
2024 | timeout = HZ / 5; | ||
2025 | else | ||
2026 | timeout = sc->cur_chan->flush_timeout; | ||
2027 | spin_unlock_bh(&sc->chan_lock); | ||
2028 | |||
2029 | ath_dbg(common, CHAN_CTX, | ||
2030 | "Flush timeout: %d\n", jiffies_to_msecs(timeout)); | ||
2031 | |||
2032 | if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc, sw_pending), | ||
2011 | timeout) > 0) | 2033 | timeout) > 0) |
2012 | drop = false; | 2034 | drop = false; |
2013 | 2035 | ||
@@ -2018,7 +2040,7 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | |||
2018 | spin_unlock_bh(&sc->sc_pcu_lock); | 2040 | spin_unlock_bh(&sc->sc_pcu_lock); |
2019 | 2041 | ||
2020 | if (!drain_txq) | 2042 | if (!drain_txq) |
2021 | ath_reset(sc); | 2043 | ath_reset(sc, NULL); |
2022 | 2044 | ||
2023 | ath9k_ps_restore(sc); | 2045 | ath9k_ps_restore(sc); |
2024 | } | 2046 | } |
@@ -2030,7 +2052,7 @@ static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) | |||
2030 | { | 2052 | { |
2031 | struct ath_softc *sc = hw->priv; | 2053 | struct ath_softc *sc = hw->priv; |
2032 | 2054 | ||
2033 | return ath9k_has_tx_pending(sc); | 2055 | return ath9k_has_tx_pending(sc, true); |
2034 | } | 2056 | } |
2035 | 2057 | ||
2036 | static int ath9k_tx_last_beacon(struct ieee80211_hw *hw) | 2058 | static int ath9k_tx_last_beacon(struct ieee80211_hw *hw) |
@@ -2161,14 +2183,17 @@ static int ath9k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant) | |||
2161 | return 0; | 2183 | return 0; |
2162 | } | 2184 | } |
2163 | 2185 | ||
2164 | static void ath9k_sw_scan_start(struct ieee80211_hw *hw) | 2186 | static void ath9k_sw_scan_start(struct ieee80211_hw *hw, |
2187 | struct ieee80211_vif *vif, | ||
2188 | const u8 *mac_addr) | ||
2165 | { | 2189 | { |
2166 | struct ath_softc *sc = hw->priv; | 2190 | struct ath_softc *sc = hw->priv; |
2167 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 2191 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
2168 | set_bit(ATH_OP_SCANNING, &common->op_flags); | 2192 | set_bit(ATH_OP_SCANNING, &common->op_flags); |
2169 | } | 2193 | } |
2170 | 2194 | ||
2171 | static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | 2195 | static void ath9k_sw_scan_complete(struct ieee80211_hw *hw, |
2196 | struct ieee80211_vif *vif) | ||
2172 | { | 2197 | { |
2173 | struct ath_softc *sc = hw->priv; | 2198 | struct ath_softc *sc = hw->priv; |
2174 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 2199 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
@@ -2177,6 +2202,28 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw) | |||
2177 | 2202 | ||
2178 | #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT | 2203 | #ifdef CONFIG_ATH9K_CHANNEL_CONTEXT |
2179 | 2204 | ||
2205 | static void ath9k_cancel_pending_offchannel(struct ath_softc *sc) | ||
2206 | { | ||
2207 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
2208 | |||
2209 | if (sc->offchannel.roc_vif) { | ||
2210 | ath_dbg(common, CHAN_CTX, | ||
2211 | "%s: Aborting RoC\n", __func__); | ||
2212 | |||
2213 | del_timer_sync(&sc->offchannel.timer); | ||
2214 | if (sc->offchannel.state >= ATH_OFFCHANNEL_ROC_START) | ||
2215 | ath_roc_complete(sc, true); | ||
2216 | } | ||
2217 | |||
2218 | if (test_bit(ATH_OP_SCANNING, &common->op_flags)) { | ||
2219 | ath_dbg(common, CHAN_CTX, | ||
2220 | "%s: Aborting HW scan\n", __func__); | ||
2221 | |||
2222 | del_timer_sync(&sc->offchannel.timer); | ||
2223 | ath_scan_complete(sc, true); | ||
2224 | } | ||
2225 | } | ||
2226 | |||
2180 | static int ath9k_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 2227 | static int ath9k_hw_scan(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
2181 | struct ieee80211_scan_request *hw_req) | 2228 | struct ieee80211_scan_request *hw_req) |
2182 | { | 2229 | { |
@@ -2307,7 +2354,6 @@ static int ath9k_add_chanctx(struct ieee80211_hw *hw, | |||
2307 | conf->def.chan->center_freq); | 2354 | conf->def.chan->center_freq); |
2308 | 2355 | ||
2309 | ath_chanctx_set_channel(sc, ctx, &conf->def); | 2356 | ath_chanctx_set_channel(sc, ctx, &conf->def); |
2310 | ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_ASSIGN); | ||
2311 | 2357 | ||
2312 | mutex_unlock(&sc->mutex); | 2358 | mutex_unlock(&sc->mutex); |
2313 | return 0; | 2359 | return 0; |
@@ -2332,7 +2378,7 @@ static void ath9k_remove_chanctx(struct ieee80211_hw *hw, | |||
2332 | conf->def.chan->center_freq); | 2378 | conf->def.chan->center_freq); |
2333 | 2379 | ||
2334 | ctx->assigned = false; | 2380 | ctx->assigned = false; |
2335 | ctx->hw_queue_base = -1; | 2381 | ctx->hw_queue_base = 0; |
2336 | ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_UNASSIGN); | 2382 | ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_UNASSIGN); |
2337 | 2383 | ||
2338 | mutex_unlock(&sc->mutex); | 2384 | mutex_unlock(&sc->mutex); |
@@ -2364,6 +2410,8 @@ static int ath9k_assign_vif_chanctx(struct ieee80211_hw *hw, | |||
2364 | struct ath_chanctx *ctx = ath_chanctx_get(conf); | 2410 | struct ath_chanctx *ctx = ath_chanctx_get(conf); |
2365 | int i; | 2411 | int i; |
2366 | 2412 | ||
2413 | ath9k_cancel_pending_offchannel(sc); | ||
2414 | |||
2367 | mutex_lock(&sc->mutex); | 2415 | mutex_lock(&sc->mutex); |
2368 | 2416 | ||
2369 | ath_dbg(common, CHAN_CTX, | 2417 | ath_dbg(common, CHAN_CTX, |
@@ -2393,6 +2441,8 @@ static void ath9k_unassign_vif_chanctx(struct ieee80211_hw *hw, | |||
2393 | struct ath_chanctx *ctx = ath_chanctx_get(conf); | 2441 | struct ath_chanctx *ctx = ath_chanctx_get(conf); |
2394 | int ac; | 2442 | int ac; |
2395 | 2443 | ||
2444 | ath9k_cancel_pending_offchannel(sc); | ||
2445 | |||
2396 | mutex_lock(&sc->mutex); | 2446 | mutex_lock(&sc->mutex); |
2397 | 2447 | ||
2398 | ath_dbg(common, CHAN_CTX, | 2448 | ath_dbg(common, CHAN_CTX, |
@@ -2416,7 +2466,11 @@ static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw, | |||
2416 | struct ath_softc *sc = hw->priv; | 2466 | struct ath_softc *sc = hw->priv; |
2417 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 2467 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
2418 | struct ath_vif *avp = (struct ath_vif *) vif->drv_priv; | 2468 | struct ath_vif *avp = (struct ath_vif *) vif->drv_priv; |
2469 | struct ath_beacon_config *cur_conf; | ||
2470 | struct ath_chanctx *go_ctx; | ||
2471 | unsigned long timeout; | ||
2419 | bool changed = false; | 2472 | bool changed = false; |
2473 | u32 beacon_int; | ||
2420 | 2474 | ||
2421 | if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) | 2475 | if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) |
2422 | return; | 2476 | return; |
@@ -2427,19 +2481,57 @@ static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw, | |||
2427 | mutex_lock(&sc->mutex); | 2481 | mutex_lock(&sc->mutex); |
2428 | 2482 | ||
2429 | spin_lock_bh(&sc->chan_lock); | 2483 | spin_lock_bh(&sc->chan_lock); |
2430 | if (sc->next_chan || (sc->cur_chan != avp->chanctx)) { | 2484 | if (sc->next_chan || (sc->cur_chan != avp->chanctx)) |
2431 | sc->next_chan = avp->chanctx; | ||
2432 | changed = true; | 2485 | changed = true; |
2486 | spin_unlock_bh(&sc->chan_lock); | ||
2487 | |||
2488 | if (!changed) | ||
2489 | goto out; | ||
2490 | |||
2491 | ath9k_cancel_pending_offchannel(sc); | ||
2492 | |||
2493 | go_ctx = ath_is_go_chanctx_present(sc); | ||
2494 | |||
2495 | if (go_ctx) { | ||
2496 | /* | ||
2497 | * Wait till the GO interface gets a chance | ||
2498 | * to send out an NoA. | ||
2499 | */ | ||
2500 | spin_lock_bh(&sc->chan_lock); | ||
2501 | sc->sched.mgd_prepare_tx = true; | ||
2502 | cur_conf = &go_ctx->beacon; | ||
2503 | beacon_int = TU_TO_USEC(cur_conf->beacon_interval); | ||
2504 | spin_unlock_bh(&sc->chan_lock); | ||
2505 | |||
2506 | timeout = usecs_to_jiffies(beacon_int * 2); | ||
2507 | init_completion(&sc->go_beacon); | ||
2508 | |||
2509 | mutex_unlock(&sc->mutex); | ||
2510 | |||
2511 | if (wait_for_completion_timeout(&sc->go_beacon, | ||
2512 | timeout) == 0) { | ||
2513 | ath_dbg(common, CHAN_CTX, | ||
2514 | "Failed to send new NoA\n"); | ||
2515 | |||
2516 | spin_lock_bh(&sc->chan_lock); | ||
2517 | sc->sched.mgd_prepare_tx = false; | ||
2518 | spin_unlock_bh(&sc->chan_lock); | ||
2519 | } | ||
2520 | |||
2521 | mutex_lock(&sc->mutex); | ||
2433 | } | 2522 | } |
2523 | |||
2434 | ath_dbg(common, CHAN_CTX, | 2524 | ath_dbg(common, CHAN_CTX, |
2435 | "%s: Set chanctx state to FORCE_ACTIVE, changed: %d\n", | 2525 | "%s: Set chanctx state to FORCE_ACTIVE for vif: %pM\n", |
2436 | __func__, changed); | 2526 | __func__, vif->addr); |
2527 | |||
2528 | spin_lock_bh(&sc->chan_lock); | ||
2529 | sc->next_chan = avp->chanctx; | ||
2437 | sc->sched.state = ATH_CHANCTX_STATE_FORCE_ACTIVE; | 2530 | sc->sched.state = ATH_CHANCTX_STATE_FORCE_ACTIVE; |
2438 | spin_unlock_bh(&sc->chan_lock); | 2531 | spin_unlock_bh(&sc->chan_lock); |
2439 | 2532 | ||
2440 | if (changed) | 2533 | ath_chanctx_set_next(sc, true); |
2441 | ath_chanctx_set_next(sc, true); | 2534 | out: |
2442 | |||
2443 | mutex_unlock(&sc->mutex); | 2535 | mutex_unlock(&sc->mutex); |
2444 | } | 2536 | } |
2445 | 2537 | ||
@@ -2462,6 +2554,24 @@ void ath9k_fill_chanctx_ops(void) | |||
2462 | 2554 | ||
2463 | #endif | 2555 | #endif |
2464 | 2556 | ||
2557 | static int ath9k_get_txpower(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | ||
2558 | int *dbm) | ||
2559 | { | ||
2560 | struct ath_softc *sc = hw->priv; | ||
2561 | struct ath_vif *avp = (void *)vif->drv_priv; | ||
2562 | |||
2563 | mutex_lock(&sc->mutex); | ||
2564 | if (avp->chanctx) | ||
2565 | *dbm = avp->chanctx->cur_txpower; | ||
2566 | else | ||
2567 | *dbm = sc->cur_chan->cur_txpower; | ||
2568 | mutex_unlock(&sc->mutex); | ||
2569 | |||
2570 | *dbm /= 2; | ||
2571 | |||
2572 | return 0; | ||
2573 | } | ||
2574 | |||
2465 | struct ieee80211_ops ath9k_ops = { | 2575 | struct ieee80211_ops ath9k_ops = { |
2466 | .tx = ath9k_tx, | 2576 | .tx = ath9k_tx, |
2467 | .start = ath9k_start, | 2577 | .start = ath9k_start, |
@@ -2471,8 +2581,7 @@ struct ieee80211_ops ath9k_ops = { | |||
2471 | .remove_interface = ath9k_remove_interface, | 2581 | .remove_interface = ath9k_remove_interface, |
2472 | .config = ath9k_config, | 2582 | .config = ath9k_config, |
2473 | .configure_filter = ath9k_configure_filter, | 2583 | .configure_filter = ath9k_configure_filter, |
2474 | .sta_add = ath9k_sta_add, | 2584 | .sta_state = ath9k_sta_state, |
2475 | .sta_remove = ath9k_sta_remove, | ||
2476 | .sta_notify = ath9k_sta_notify, | 2585 | .sta_notify = ath9k_sta_notify, |
2477 | .conf_tx = ath9k_conf_tx, | 2586 | .conf_tx = ath9k_conf_tx, |
2478 | .bss_info_changed = ath9k_bss_info_changed, | 2587 | .bss_info_changed = ath9k_bss_info_changed, |
@@ -2509,4 +2618,5 @@ struct ieee80211_ops ath9k_ops = { | |||
2509 | #endif | 2618 | #endif |
2510 | .sw_scan_start = ath9k_sw_scan_start, | 2619 | .sw_scan_start = ath9k_sw_scan_start, |
2511 | .sw_scan_complete = ath9k_sw_scan_complete, | 2620 | .sw_scan_complete = ath9k_sw_scan_complete, |
2621 | .get_txpower = ath9k_get_txpower, | ||
2512 | }; | 2622 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index c018dea0b2e8..f009b5b57e5e 100644 --- a/drivers/net/wireless/ath/ath9k/pci.c +++ b/drivers/net/wireless/ath/ath9k/pci.c | |||
@@ -30,6 +30,7 @@ static const struct pci_device_id ath_pci_id_table[] = { | |||
30 | { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ | 30 | { PCI_VDEVICE(ATHEROS, 0x0029) }, /* PCI */ |
31 | { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ | 31 | { PCI_VDEVICE(ATHEROS, 0x002A) }, /* PCI-E */ |
32 | 32 | ||
33 | #ifdef CONFIG_ATH9K_PCOEM | ||
33 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 34 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
34 | 0x002A, | 35 | 0x002A, |
35 | PCI_VENDOR_ID_AZWAVE, | 36 | PCI_VENDOR_ID_AZWAVE, |
@@ -82,6 +83,7 @@ static const struct pci_device_id ath_pci_id_table[] = { | |||
82 | PCI_VENDOR_ID_AZWAVE, | 83 | PCI_VENDOR_ID_AZWAVE, |
83 | 0x2C37), | 84 | 0x2C37), |
84 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | 85 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, |
86 | #endif | ||
85 | 87 | ||
86 | { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ | 88 | { PCI_VDEVICE(ATHEROS, 0x002B) }, /* PCI-E */ |
87 | { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ | 89 | { PCI_VDEVICE(ATHEROS, 0x002C) }, /* PCI-E 802.11n bonded out */ |
@@ -102,6 +104,7 @@ static const struct pci_device_id ath_pci_id_table[] = { | |||
102 | 104 | ||
103 | { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ | 105 | { PCI_VDEVICE(ATHEROS, 0x0030) }, /* PCI-E AR9300 */ |
104 | 106 | ||
107 | #ifdef CONFIG_ATH9K_PCOEM | ||
105 | /* PCI-E CUS198 */ | 108 | /* PCI-E CUS198 */ |
106 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 109 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
107 | 0x0032, | 110 | 0x0032, |
@@ -294,10 +297,12 @@ static const struct pci_device_id ath_pci_id_table[] = { | |||
294 | PCI_VENDOR_ID_ASUSTEK, | 297 | PCI_VENDOR_ID_ASUSTEK, |
295 | 0x850D), | 298 | 0x850D), |
296 | .driver_data = ATH9K_PCI_NO_PLL_PWRSAVE }, | 299 | .driver_data = ATH9K_PCI_NO_PLL_PWRSAVE }, |
300 | #endif | ||
297 | 301 | ||
298 | { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ | 302 | { PCI_VDEVICE(ATHEROS, 0x0032) }, /* PCI-E AR9485 */ |
299 | { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ | 303 | { PCI_VDEVICE(ATHEROS, 0x0033) }, /* PCI-E AR9580 */ |
300 | 304 | ||
305 | #ifdef CONFIG_ATH9K_PCOEM | ||
301 | /* PCI-E CUS217 */ | 306 | /* PCI-E CUS217 */ |
302 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, | 307 | { PCI_DEVICE_SUB(PCI_VENDOR_ID_ATHEROS, |
303 | 0x0034, | 308 | 0x0034, |
@@ -652,11 +657,14 @@ static const struct pci_device_id ath_pci_id_table[] = { | |||
652 | 0x0036, | 657 | 0x0036, |
653 | PCI_VENDOR_ID_DELL, | 658 | PCI_VENDOR_ID_DELL, |
654 | 0x020E), | 659 | 0x020E), |
655 | .driver_data = ATH9K_PCI_AR9565_2ANT | ATH9K_PCI_BT_ANT_DIV }, | 660 | .driver_data = ATH9K_PCI_AR9565_2ANT | |
661 | ATH9K_PCI_BT_ANT_DIV | | ||
662 | ATH9K_PCI_LED_ACT_HI}, | ||
656 | 663 | ||
657 | /* PCI-E AR9565 (WB335) */ | 664 | /* PCI-E AR9565 (WB335) */ |
658 | { PCI_VDEVICE(ATHEROS, 0x0036), | 665 | { PCI_VDEVICE(ATHEROS, 0x0036), |
659 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | 666 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, |
667 | #endif | ||
660 | 668 | ||
661 | { 0 } | 669 | { 0 } |
662 | }; | 670 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c index 6914e21816e4..7395afbc5124 100644 --- a/drivers/net/wireless/ath/ath9k/recv.c +++ b/drivers/net/wireless/ath/ath9k/recv.c | |||
@@ -870,7 +870,7 @@ static int ath9k_rx_skb_preprocess(struct ath_softc *sc, | |||
870 | */ | 870 | */ |
871 | if (rx_stats->rs_status & ATH9K_RXERR_PHY) { | 871 | if (rx_stats->rs_status & ATH9K_RXERR_PHY) { |
872 | ath9k_dfs_process_phyerr(sc, hdr, rx_stats, rx_status->mactime); | 872 | ath9k_dfs_process_phyerr(sc, hdr, rx_stats, rx_status->mactime); |
873 | if (ath_process_fft(sc, hdr, rx_stats, rx_status->mactime)) | 873 | if (ath_cmn_process_fft(&sc->spec_priv, hdr, rx_stats, rx_status->mactime)) |
874 | RX_STAT_INC(rx_spectral); | 874 | RX_STAT_INC(rx_spectral); |
875 | 875 | ||
876 | return -EINVAL; | 876 | return -EINVAL; |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 2a938f4feac5..ced36b475acc 100644 --- a/drivers/net/wireless/ath/ath9k/reg.h +++ b/drivers/net/wireless/ath/ath9k/reg.h | |||
@@ -892,10 +892,21 @@ | |||
892 | (AR_SREV_9330((_ah)) && \ | 892 | (AR_SREV_9330((_ah)) && \ |
893 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_12)) | 893 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9330_12)) |
894 | 894 | ||
895 | #ifdef CONFIG_ATH9K_PCOEM | ||
896 | #define AR_SREV_9462(_ah) \ | ||
897 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462)) | ||
895 | #define AR_SREV_9485(_ah) \ | 898 | #define AR_SREV_9485(_ah) \ |
896 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) | 899 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485)) |
900 | #define AR_SREV_9565(_ah) \ | ||
901 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) | ||
902 | #else | ||
903 | #define AR_SREV_9462(_ah) 0 | ||
904 | #define AR_SREV_9485(_ah) 0 | ||
905 | #define AR_SREV_9565(_ah) 0 | ||
906 | #endif | ||
907 | |||
897 | #define AR_SREV_9485_11_OR_LATER(_ah) \ | 908 | #define AR_SREV_9485_11_OR_LATER(_ah) \ |
898 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9485) && \ | 909 | (AR_SREV_9485(_ah) && \ |
899 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9485_11)) | 910 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9485_11)) |
900 | #define AR_SREV_9485_OR_LATER(_ah) \ | 911 | #define AR_SREV_9485_OR_LATER(_ah) \ |
901 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485)) | 912 | (((_ah)->hw_version.macVersion >= AR_SREV_VERSION_9485)) |
@@ -915,34 +926,30 @@ | |||
915 | (AR_SREV_9285_12_OR_LATER(_ah) && \ | 926 | (AR_SREV_9285_12_OR_LATER(_ah) && \ |
916 | ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) | 927 | ((REG_READ(_ah, AR_AN_SYNTH9) & 0x7) == 0x1)) |
917 | 928 | ||
918 | #define AR_SREV_9462(_ah) \ | ||
919 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462)) | ||
920 | #define AR_SREV_9462_20(_ah) \ | 929 | #define AR_SREV_9462_20(_ah) \ |
921 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ | 930 | (AR_SREV_9462(_ah) && \ |
922 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20)) | 931 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_20)) |
923 | #define AR_SREV_9462_21(_ah) \ | 932 | #define AR_SREV_9462_21(_ah) \ |
924 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ | 933 | (AR_SREV_9462(_ah) && \ |
925 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_21)) | 934 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9462_21)) |
926 | #define AR_SREV_9462_20_OR_LATER(_ah) \ | 935 | #define AR_SREV_9462_20_OR_LATER(_ah) \ |
927 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ | 936 | (AR_SREV_9462(_ah) && \ |
928 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20)) | 937 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_20)) |
929 | #define AR_SREV_9462_21_OR_LATER(_ah) \ | 938 | #define AR_SREV_9462_21_OR_LATER(_ah) \ |
930 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9462) && \ | 939 | (AR_SREV_9462(_ah) && \ |
931 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_21)) | 940 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9462_21)) |
932 | 941 | ||
933 | #define AR_SREV_9565(_ah) \ | ||
934 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565)) | ||
935 | #define AR_SREV_9565_10(_ah) \ | 942 | #define AR_SREV_9565_10(_ah) \ |
936 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ | 943 | (AR_SREV_9565(_ah) && \ |
937 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_10)) | 944 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_10)) |
938 | #define AR_SREV_9565_101(_ah) \ | 945 | #define AR_SREV_9565_101(_ah) \ |
939 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ | 946 | (AR_SREV_9565(_ah) && \ |
940 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_101)) | 947 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_101)) |
941 | #define AR_SREV_9565_11(_ah) \ | 948 | #define AR_SREV_9565_11(_ah) \ |
942 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ | 949 | (AR_SREV_9565(_ah) && \ |
943 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_11)) | 950 | ((_ah)->hw_version.macRev == AR_SREV_REVISION_9565_11)) |
944 | #define AR_SREV_9565_11_OR_LATER(_ah) \ | 951 | #define AR_SREV_9565_11_OR_LATER(_ah) \ |
945 | (((_ah)->hw_version.macVersion == AR_SREV_VERSION_9565) && \ | 952 | (AR_SREV_9565(_ah) && \ |
946 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9565_11)) | 953 | ((_ah)->hw_version.macRev >= AR_SREV_REVISION_9565_11)) |
947 | 954 | ||
948 | #define AR_SREV_9550(_ah) \ | 955 | #define AR_SREV_9550(_ah) \ |
@@ -1598,6 +1605,7 @@ enum { | |||
1598 | 1605 | ||
1599 | #define AR_RESET_TSF 0x8020 | 1606 | #define AR_RESET_TSF 0x8020 |
1600 | #define AR_RESET_TSF_ONCE 0x01000000 | 1607 | #define AR_RESET_TSF_ONCE 0x01000000 |
1608 | #define AR_RESET_TSF2_ONCE 0x02000000 | ||
1601 | 1609 | ||
1602 | #define AR_MAX_CFP_DUR 0x8038 | 1610 | #define AR_MAX_CFP_DUR 0x8038 |
1603 | #define AR_CFP_VAL 0x0000FFFF | 1611 | #define AR_CFP_VAL 0x0000FFFF |
@@ -1959,6 +1967,8 @@ enum { | |||
1959 | #define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000 | 1967 | #define AR_MAC_PCU_ASYNC_FIFO_REG3_SOFT_RESET 0x80000000 |
1960 | #define AR_MAC_PCU_GEN_TIMER_TSF_SEL 0x83d8 | 1968 | #define AR_MAC_PCU_GEN_TIMER_TSF_SEL 0x83d8 |
1961 | 1969 | ||
1970 | #define AR_DIRECT_CONNECT 0x83a0 | ||
1971 | #define AR_DC_AP_STA_EN 0x00000001 | ||
1962 | 1972 | ||
1963 | #define AR_AES_MUTE_MASK0 0x805c | 1973 | #define AR_AES_MUTE_MASK0 0x805c |
1964 | #define AR_AES_MUTE_MASK0_FC 0x0000FFFF | 1974 | #define AR_AES_MUTE_MASK0_FC 0x0000FFFF |
diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c index 8a69d08ec55c..ac4781f37e78 100644 --- a/drivers/net/wireless/ath/ath9k/tx99.c +++ b/drivers/net/wireless/ath/ath9k/tx99.c | |||
@@ -54,6 +54,12 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) | |||
54 | struct ieee80211_hdr *hdr; | 54 | struct ieee80211_hdr *hdr; |
55 | struct ieee80211_tx_info *tx_info; | 55 | struct ieee80211_tx_info *tx_info; |
56 | struct sk_buff *skb; | 56 | struct sk_buff *skb; |
57 | struct ath_vif *avp; | ||
58 | |||
59 | if (!sc->tx99_vif) | ||
60 | return NULL; | ||
61 | |||
62 | avp = (struct ath_vif *)sc->tx99_vif->drv_priv; | ||
57 | 63 | ||
58 | skb = alloc_skb(len, GFP_KERNEL); | 64 | skb = alloc_skb(len, GFP_KERNEL); |
59 | if (!skb) | 65 | if (!skb) |
@@ -71,7 +77,7 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) | |||
71 | memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); | 77 | memcpy(hdr->addr2, hw->wiphy->perm_addr, ETH_ALEN); |
72 | memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); | 78 | memcpy(hdr->addr3, hw->wiphy->perm_addr, ETH_ALEN); |
73 | 79 | ||
74 | hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); | 80 | hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); |
75 | 81 | ||
76 | tx_info = IEEE80211_SKB_CB(skb); | 82 | tx_info = IEEE80211_SKB_CB(skb); |
77 | memset(tx_info, 0, sizeof(*tx_info)); | 83 | memset(tx_info, 0, sizeof(*tx_info)); |
@@ -93,7 +99,7 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) | |||
93 | 99 | ||
94 | static void ath9k_tx99_deinit(struct ath_softc *sc) | 100 | static void ath9k_tx99_deinit(struct ath_softc *sc) |
95 | { | 101 | { |
96 | ath_reset(sc); | 102 | ath_reset(sc, NULL); |
97 | 103 | ||
98 | ath9k_ps_wakeup(sc); | 104 | ath9k_ps_wakeup(sc); |
99 | ath9k_tx99_stop(sc); | 105 | ath9k_tx99_stop(sc); |
@@ -121,7 +127,7 @@ static int ath9k_tx99_init(struct ath_softc *sc) | |||
121 | memset(&txctl, 0, sizeof(txctl)); | 127 | memset(&txctl, 0, sizeof(txctl)); |
122 | txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; | 128 | txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; |
123 | 129 | ||
124 | ath_reset(sc); | 130 | ath_reset(sc, NULL); |
125 | 131 | ||
126 | ath9k_ps_wakeup(sc); | 132 | ath9k_ps_wakeup(sc); |
127 | 133 | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 151ae49fa57e..d6e54a3c88f6 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -169,7 +169,10 @@ static void ath_txq_skb_done(struct ath_softc *sc, struct ath_txq *txq, | |||
169 | 169 | ||
170 | if (txq->stopped && | 170 | if (txq->stopped && |
171 | txq->pending_frames < sc->tx.txq_max_pending[q]) { | 171 | txq->pending_frames < sc->tx.txq_max_pending[q]) { |
172 | ieee80211_wake_queue(sc->hw, info->hw_queue); | 172 | if (ath9k_is_chanctx_enabled()) |
173 | ieee80211_wake_queue(sc->hw, info->hw_queue); | ||
174 | else | ||
175 | ieee80211_wake_queue(sc->hw, q); | ||
173 | txq->stopped = false; | 176 | txq->stopped = false; |
174 | } | 177 | } |
175 | } | 178 | } |
@@ -2139,6 +2142,28 @@ static struct ath_buf *ath_tx_setup_buffer(struct ath_softc *sc, | |||
2139 | return bf; | 2142 | return bf; |
2140 | } | 2143 | } |
2141 | 2144 | ||
2145 | void ath_assign_seq(struct ath_common *common, struct sk_buff *skb) | ||
2146 | { | ||
2147 | struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data; | ||
2148 | struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); | ||
2149 | struct ieee80211_vif *vif = info->control.vif; | ||
2150 | struct ath_vif *avp; | ||
2151 | |||
2152 | if (!(info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ)) | ||
2153 | return; | ||
2154 | |||
2155 | if (!vif) | ||
2156 | return; | ||
2157 | |||
2158 | avp = (struct ath_vif *)vif->drv_priv; | ||
2159 | |||
2160 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | ||
2161 | avp->seq_no += 0x10; | ||
2162 | |||
2163 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
2164 | hdr->seq_ctrl |= cpu_to_le16(avp->seq_no); | ||
2165 | } | ||
2166 | |||
2142 | static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, | 2167 | static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, |
2143 | struct ath_tx_control *txctl) | 2168 | struct ath_tx_control *txctl) |
2144 | { | 2169 | { |
@@ -2162,17 +2187,7 @@ static int ath_tx_prepare(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2162 | if (info->control.hw_key) | 2187 | if (info->control.hw_key) |
2163 | frmlen += info->control.hw_key->icv_len; | 2188 | frmlen += info->control.hw_key->icv_len; |
2164 | 2189 | ||
2165 | /* | 2190 | ath_assign_seq(ath9k_hw_common(sc->sc_ah), skb); |
2166 | * As a temporary workaround, assign seq# here; this will likely need | ||
2167 | * to be cleaned up to work better with Beacon transmission and virtual | ||
2168 | * BSSes. | ||
2169 | */ | ||
2170 | if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { | ||
2171 | if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) | ||
2172 | sc->tx.seq_no += 0x10; | ||
2173 | hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); | ||
2174 | hdr->seq_ctrl |= cpu_to_le16(sc->tx.seq_no); | ||
2175 | } | ||
2176 | 2191 | ||
2177 | if ((vif && vif->type != NL80211_IFTYPE_AP && | 2192 | if ((vif && vif->type != NL80211_IFTYPE_AP && |
2178 | vif->type != NL80211_IFTYPE_AP_VLAN) || | 2193 | vif->type != NL80211_IFTYPE_AP_VLAN) || |
@@ -2235,7 +2250,10 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2235 | fi->txq = q; | 2250 | fi->txq = q; |
2236 | if (++txq->pending_frames > sc->tx.txq_max_pending[q] && | 2251 | if (++txq->pending_frames > sc->tx.txq_max_pending[q] && |
2237 | !txq->stopped) { | 2252 | !txq->stopped) { |
2238 | ieee80211_stop_queue(sc->hw, info->hw_queue); | 2253 | if (ath9k_is_chanctx_enabled()) |
2254 | ieee80211_stop_queue(sc->hw, info->hw_queue); | ||
2255 | else | ||
2256 | ieee80211_stop_queue(sc->hw, q); | ||
2239 | txq->stopped = true; | 2257 | txq->stopped = true; |
2240 | } | 2258 | } |
2241 | } | 2259 | } |
diff --git a/drivers/net/wireless/ath/carl9170/phy.c b/drivers/net/wireless/ath/carl9170/phy.c index b80b2138ce3c..dca6df13fd5b 100644 --- a/drivers/net/wireless/ath/carl9170/phy.c +++ b/drivers/net/wireless/ath/carl9170/phy.c | |||
@@ -994,7 +994,7 @@ static int carl9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz, | |||
994 | refsel0 = 0; | 994 | refsel0 = 0; |
995 | refsel1 = 1; | 995 | refsel1 = 1; |
996 | } | 996 | } |
997 | chansel = byte_rev_table[chansel]; | 997 | chansel = bitrev8(chansel); |
998 | } else { | 998 | } else { |
999 | if (freq == 2484) { | 999 | if (freq == 2484) { |
1000 | chansel = 10 + (freq - 2274) / 5; | 1000 | chansel = 10 + (freq - 2274) / 5; |
@@ -1002,7 +1002,7 @@ static int carl9170_init_rf_bank4_pwr(struct ar9170 *ar, bool band5ghz, | |||
1002 | } else | 1002 | } else |
1003 | chansel = 16 + (freq - 2272) / 5; | 1003 | chansel = 16 + (freq - 2272) / 5; |
1004 | chansel *= 4; | 1004 | chansel *= 4; |
1005 | chansel = byte_rev_table[chansel]; | 1005 | chansel = bitrev8(chansel); |
1006 | } | 1006 | } |
1007 | 1007 | ||
1008 | d1 = chansel; | 1008 | d1 = chansel; |
diff --git a/drivers/net/wireless/ath/main.c b/drivers/net/wireless/ath/main.c index 83f47af19280..338d72337604 100644 --- a/drivers/net/wireless/ath/main.c +++ b/drivers/net/wireless/ath/main.c | |||
@@ -79,13 +79,13 @@ void ath_printk(const char *level, const struct ath_common* common, | |||
79 | vaf.fmt = fmt; | 79 | vaf.fmt = fmt; |
80 | vaf.va = &args; | 80 | vaf.va = &args; |
81 | 81 | ||
82 | if (common && common->hw && common->hw->wiphy) | 82 | if (common && common->hw && common->hw->wiphy) { |
83 | printk("%sath: %s: %pV", | 83 | printk("%sath: %s: %pV", |
84 | level, wiphy_name(common->hw->wiphy), &vaf); | 84 | level, wiphy_name(common->hw->wiphy), &vaf); |
85 | else | 85 | trace_ath_log(common->hw->wiphy, &vaf); |
86 | } else { | ||
86 | printk("%sath: %pV", level, &vaf); | 87 | printk("%sath: %pV", level, &vaf); |
87 | 88 | } | |
88 | trace_ath_log(common->hw->wiphy, &vaf); | ||
89 | 89 | ||
90 | va_end(args); | 90 | va_end(args); |
91 | } | 91 | } |
diff --git a/drivers/net/wireless/ath/regd.c b/drivers/net/wireless/ath/regd.c index 415393dfb6fc..06ea6cc9e30a 100644 --- a/drivers/net/wireless/ath/regd.c +++ b/drivers/net/wireless/ath/regd.c | |||
@@ -515,6 +515,7 @@ void ath_reg_notifier_apply(struct wiphy *wiphy, | |||
515 | if (!request) | 515 | if (!request) |
516 | return; | 516 | return; |
517 | 517 | ||
518 | reg->region = request->dfs_region; | ||
518 | switch (request->initiator) { | 519 | switch (request->initiator) { |
519 | case NL80211_REGDOM_SET_BY_CORE: | 520 | case NL80211_REGDOM_SET_BY_CORE: |
520 | /* | 521 | /* |
@@ -779,6 +780,19 @@ u32 ath_regd_get_band_ctl(struct ath_regulatory *reg, | |||
779 | return SD_NO_CTL; | 780 | return SD_NO_CTL; |
780 | } | 781 | } |
781 | 782 | ||
783 | if (ath_regd_get_eepromRD(reg) == CTRY_DEFAULT) { | ||
784 | switch (reg->region) { | ||
785 | case NL80211_DFS_FCC: | ||
786 | return CTL_FCC; | ||
787 | case NL80211_DFS_ETSI: | ||
788 | return CTL_ETSI; | ||
789 | case NL80211_DFS_JP: | ||
790 | return CTL_MKK; | ||
791 | default: | ||
792 | break; | ||
793 | } | ||
794 | } | ||
795 | |||
782 | switch (band) { | 796 | switch (band) { |
783 | case IEEE80211_BAND_2GHZ: | 797 | case IEEE80211_BAND_2GHZ: |
784 | return reg->regpair->reg_2ghz_ctl; | 798 | return reg->regpair->reg_2ghz_ctl; |
diff --git a/drivers/net/wireless/ath/wcn36xx/main.c b/drivers/net/wireless/ath/wcn36xx/main.c index b71d2b33532d..267c35d1f699 100644 --- a/drivers/net/wireless/ath/wcn36xx/main.c +++ b/drivers/net/wireless/ath/wcn36xx/main.c | |||
@@ -494,7 +494,9 @@ out: | |||
494 | return ret; | 494 | return ret; |
495 | } | 495 | } |
496 | 496 | ||
497 | static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw) | 497 | static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw, |
498 | struct ieee80211_vif *vif, | ||
499 | const u8 *mac_addr) | ||
498 | { | 500 | { |
499 | struct wcn36xx *wcn = hw->priv; | 501 | struct wcn36xx *wcn = hw->priv; |
500 | 502 | ||
@@ -502,7 +504,8 @@ static void wcn36xx_sw_scan_start(struct ieee80211_hw *hw) | |||
502 | wcn36xx_smd_start_scan(wcn); | 504 | wcn36xx_smd_start_scan(wcn); |
503 | } | 505 | } |
504 | 506 | ||
505 | static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw) | 507 | static void wcn36xx_sw_scan_complete(struct ieee80211_hw *hw, |
508 | struct ieee80211_vif *vif) | ||
506 | { | 509 | { |
507 | struct wcn36xx *wcn = hw->priv; | 510 | struct wcn36xx *wcn = hw->priv; |
508 | 511 | ||
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c index d9f4b30dd343..0fc0b9f8e605 100644 --- a/drivers/net/wireless/ath/wil6210/cfg80211.c +++ b/drivers/net/wireless/ath/wil6210/cfg80211.c | |||
@@ -792,12 +792,13 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy, | |||
792 | } | 792 | } |
793 | 793 | ||
794 | static int wil_cfg80211_del_station(struct wiphy *wiphy, | 794 | static int wil_cfg80211_del_station(struct wiphy *wiphy, |
795 | struct net_device *dev, const u8 *mac) | 795 | struct net_device *dev, |
796 | struct station_del_parameters *params) | ||
796 | { | 797 | { |
797 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); | 798 | struct wil6210_priv *wil = wiphy_to_wil(wiphy); |
798 | 799 | ||
799 | mutex_lock(&wil->mutex); | 800 | mutex_lock(&wil->mutex); |
800 | wil6210_disconnect(wil, mac); | 801 | wil6210_disconnect(wil, params->mac, false); |
801 | mutex_unlock(&wil->mutex); | 802 | mutex_unlock(&wil->mutex); |
802 | 803 | ||
803 | return 0; | 804 | return 0; |
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c index 6500caf8d609..6212983fede2 100644 --- a/drivers/net/wireless/ath/wil6210/main.c +++ b/drivers/net/wireless/ath/wil6210/main.c | |||
@@ -38,6 +38,35 @@ static unsigned int itr_trsh = WIL6210_ITR_TRSH_DEFAULT; | |||
38 | module_param(itr_trsh, uint, S_IRUGO); | 38 | module_param(itr_trsh, uint, S_IRUGO); |
39 | MODULE_PARM_DESC(itr_trsh, " Interrupt moderation threshold, usecs."); | 39 | MODULE_PARM_DESC(itr_trsh, " Interrupt moderation threshold, usecs."); |
40 | 40 | ||
41 | /* We allow allocation of more than 1 page buffers to support large packets. | ||
42 | * It is suboptimal behavior performance wise in case MTU above page size. | ||
43 | */ | ||
44 | unsigned int mtu_max = TXRX_BUF_LEN_DEFAULT - ETH_HLEN; | ||
45 | static int mtu_max_set(const char *val, const struct kernel_param *kp) | ||
46 | { | ||
47 | int ret; | ||
48 | |||
49 | /* sets mtu_max directly. no need to restore it in case of | ||
50 | * illegal value since we assume this will fail insmod | ||
51 | */ | ||
52 | ret = param_set_uint(val, kp); | ||
53 | if (ret) | ||
54 | return ret; | ||
55 | |||
56 | if (mtu_max < 68 || mtu_max > IEEE80211_MAX_DATA_LEN_DMG) | ||
57 | ret = -EINVAL; | ||
58 | |||
59 | return ret; | ||
60 | } | ||
61 | |||
62 | static struct kernel_param_ops mtu_max_ops = { | ||
63 | .set = mtu_max_set, | ||
64 | .get = param_get_uint, | ||
65 | }; | ||
66 | |||
67 | module_param_cb(mtu_max, &mtu_max_ops, &mtu_max, S_IRUGO); | ||
68 | MODULE_PARM_DESC(mtu_max, " Max MTU value."); | ||
69 | |||
41 | #define RST_DELAY (20) /* msec, for loop in @wil_target_reset */ | 70 | #define RST_DELAY (20) /* msec, for loop in @wil_target_reset */ |
42 | #define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */ | 71 | #define RST_COUNT (1 + 1000/RST_DELAY) /* round up to be above 1 sec total */ |
43 | 72 | ||
@@ -74,7 +103,8 @@ void wil_memcpy_toio_32(volatile void __iomem *dst, const void *src, | |||
74 | __raw_writel(*s++, d++); | 103 | __raw_writel(*s++, d++); |
75 | } | 104 | } |
76 | 105 | ||
77 | static void wil_disconnect_cid(struct wil6210_priv *wil, int cid) | 106 | static void wil_disconnect_cid(struct wil6210_priv *wil, int cid, |
107 | bool from_event) | ||
78 | { | 108 | { |
79 | uint i; | 109 | uint i; |
80 | struct net_device *ndev = wil_to_ndev(wil); | 110 | struct net_device *ndev = wil_to_ndev(wil); |
@@ -86,7 +116,10 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid) | |||
86 | 116 | ||
87 | sta->data_port_open = false; | 117 | sta->data_port_open = false; |
88 | if (sta->status != wil_sta_unused) { | 118 | if (sta->status != wil_sta_unused) { |
89 | wmi_disconnect_sta(wil, sta->addr, WLAN_REASON_DEAUTH_LEAVING); | 119 | if (!from_event) |
120 | wmi_disconnect_sta(wil, sta->addr, | ||
121 | WLAN_REASON_DEAUTH_LEAVING); | ||
122 | |||
90 | switch (wdev->iftype) { | 123 | switch (wdev->iftype) { |
91 | case NL80211_IFTYPE_AP: | 124 | case NL80211_IFTYPE_AP: |
92 | case NL80211_IFTYPE_P2P_GO: | 125 | case NL80211_IFTYPE_P2P_GO: |
@@ -118,7 +151,8 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid) | |||
118 | memset(&sta->stats, 0, sizeof(sta->stats)); | 151 | memset(&sta->stats, 0, sizeof(sta->stats)); |
119 | } | 152 | } |
120 | 153 | ||
121 | static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) | 154 | static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, |
155 | bool from_event) | ||
122 | { | 156 | { |
123 | int cid = -ENOENT; | 157 | int cid = -ENOENT; |
124 | struct net_device *ndev = wil_to_ndev(wil); | 158 | struct net_device *ndev = wil_to_ndev(wil); |
@@ -133,10 +167,10 @@ static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) | |||
133 | } | 167 | } |
134 | 168 | ||
135 | if (cid >= 0) /* disconnect 1 peer */ | 169 | if (cid >= 0) /* disconnect 1 peer */ |
136 | wil_disconnect_cid(wil, cid); | 170 | wil_disconnect_cid(wil, cid, from_event); |
137 | else /* disconnect all */ | 171 | else /* disconnect all */ |
138 | for (cid = 0; cid < WIL6210_MAX_CID; cid++) | 172 | for (cid = 0; cid < WIL6210_MAX_CID; cid++) |
139 | wil_disconnect_cid(wil, cid); | 173 | wil_disconnect_cid(wil, cid, from_event); |
140 | 174 | ||
141 | /* link state */ | 175 | /* link state */ |
142 | switch (wdev->iftype) { | 176 | switch (wdev->iftype) { |
@@ -166,7 +200,7 @@ static void wil_disconnect_worker(struct work_struct *work) | |||
166 | struct wil6210_priv, disconnect_worker); | 200 | struct wil6210_priv, disconnect_worker); |
167 | 201 | ||
168 | mutex_lock(&wil->mutex); | 202 | mutex_lock(&wil->mutex); |
169 | _wil6210_disconnect(wil, NULL); | 203 | _wil6210_disconnect(wil, NULL, false); |
170 | mutex_unlock(&wil->mutex); | 204 | mutex_unlock(&wil->mutex); |
171 | } | 205 | } |
172 | 206 | ||
@@ -223,6 +257,11 @@ static void wil_fw_error_worker(struct work_struct *work) | |||
223 | 257 | ||
224 | wil_dbg_misc(wil, "fw error worker\n"); | 258 | wil_dbg_misc(wil, "fw error worker\n"); |
225 | 259 | ||
260 | if (!netif_running(wil_to_ndev(wil))) { | ||
261 | wil_info(wil, "No recovery - interface is down\n"); | ||
262 | return; | ||
263 | } | ||
264 | |||
226 | /* increment @recovery_count if less then WIL6210_FW_RECOVERY_TO | 265 | /* increment @recovery_count if less then WIL6210_FW_RECOVERY_TO |
227 | * passed since last recovery attempt | 266 | * passed since last recovery attempt |
228 | */ | 267 | */ |
@@ -257,9 +296,12 @@ static void wil_fw_error_worker(struct work_struct *work) | |||
257 | break; | 296 | break; |
258 | case NL80211_IFTYPE_AP: | 297 | case NL80211_IFTYPE_AP: |
259 | case NL80211_IFTYPE_P2P_GO: | 298 | case NL80211_IFTYPE_P2P_GO: |
299 | wil_info(wil, "No recovery for AP-like interface\n"); | ||
260 | /* recovery in these modes is done by upper layers */ | 300 | /* recovery in these modes is done by upper layers */ |
261 | break; | 301 | break; |
262 | default: | 302 | default: |
303 | wil_err(wil, "No recovery - unknown interface type %d\n", | ||
304 | wdev->iftype); | ||
263 | break; | 305 | break; |
264 | } | 306 | } |
265 | mutex_unlock(&wil->mutex); | 307 | mutex_unlock(&wil->mutex); |
@@ -346,12 +388,22 @@ int wil_priv_init(struct wil6210_priv *wil) | |||
346 | return 0; | 388 | return 0; |
347 | } | 389 | } |
348 | 390 | ||
349 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid) | 391 | /** |
392 | * wil6210_disconnect - disconnect one connection | ||
393 | * @wil: driver context | ||
394 | * @bssid: peer to disconnect, NULL to disconnect all | ||
395 | * @from_event: whether is invoked from FW event handler | ||
396 | * | ||
397 | * Disconnect and release associated resources. If invoked not from the | ||
398 | * FW event handler, issue WMI command(s) to trigger MAC disconnect. | ||
399 | */ | ||
400 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, | ||
401 | bool from_event) | ||
350 | { | 402 | { |
351 | wil_dbg_misc(wil, "%s()\n", __func__); | 403 | wil_dbg_misc(wil, "%s()\n", __func__); |
352 | 404 | ||
353 | del_timer_sync(&wil->connect_timer); | 405 | del_timer_sync(&wil->connect_timer); |
354 | _wil6210_disconnect(wil, bssid); | 406 | _wil6210_disconnect(wil, bssid, from_event); |
355 | } | 407 | } |
356 | 408 | ||
357 | void wil_priv_deinit(struct wil6210_priv *wil) | 409 | void wil_priv_deinit(struct wil6210_priv *wil) |
@@ -363,7 +415,7 @@ void wil_priv_deinit(struct wil6210_priv *wil) | |||
363 | cancel_work_sync(&wil->disconnect_worker); | 415 | cancel_work_sync(&wil->disconnect_worker); |
364 | cancel_work_sync(&wil->fw_error_worker); | 416 | cancel_work_sync(&wil->fw_error_worker); |
365 | mutex_lock(&wil->mutex); | 417 | mutex_lock(&wil->mutex); |
366 | wil6210_disconnect(wil, NULL); | 418 | wil6210_disconnect(wil, NULL, false); |
367 | mutex_unlock(&wil->mutex); | 419 | mutex_unlock(&wil->mutex); |
368 | wmi_event_flush(wil); | 420 | wmi_event_flush(wil); |
369 | destroy_workqueue(wil->wmi_wq_conn); | 421 | destroy_workqueue(wil->wmi_wq_conn); |
@@ -395,7 +447,7 @@ static inline void wil_release_cpu(struct wil6210_priv *wil) | |||
395 | static int wil_target_reset(struct wil6210_priv *wil) | 447 | static int wil_target_reset(struct wil6210_priv *wil) |
396 | { | 448 | { |
397 | int delay = 0; | 449 | int delay = 0; |
398 | u32 hw_state; | 450 | u32 x; |
399 | u32 rev_id; | 451 | u32 rev_id; |
400 | bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW); | 452 | bool is_sparrow = (wil->board->board == WIL_BOARD_SPARROW); |
401 | 453 | ||
@@ -410,9 +462,22 @@ static int wil_target_reset(struct wil6210_priv *wil) | |||
410 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT_CAR_PERST_RST); | 462 | S(RGF_USER_CLKS_CTL_SW_RST_MASK_0, BIT_CAR_PERST_RST); |
411 | 463 | ||
412 | wil_halt_cpu(wil); | 464 | wil_halt_cpu(wil); |
413 | C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL); /* 40 MHz */ | ||
414 | 465 | ||
415 | if (is_sparrow) { | 466 | if (is_sparrow) { |
467 | S(RGF_CAF_OSC_CONTROL, BIT_CAF_OSC_XTAL_EN); | ||
468 | /* XTAL stabilization should take about 3ms */ | ||
469 | usleep_range(5000, 7000); | ||
470 | x = R(RGF_CAF_PLL_LOCK_STATUS); | ||
471 | if (!(x & BIT_CAF_OSC_DIG_XTAL_STABLE)) { | ||
472 | wil_err(wil, "Xtal stabilization timeout\n" | ||
473 | "RGF_CAF_PLL_LOCK_STATUS = 0x%08x\n", x); | ||
474 | return -ETIME; | ||
475 | } | ||
476 | /* switch 10k to XTAL*/ | ||
477 | C(RGF_USER_SPARROW_M_4, BIT_SPARROW_M_4_SEL_SLEEP_OR_REF); | ||
478 | /* 40 MHz */ | ||
479 | C(RGF_USER_CLKS_CTL_0, BIT_USER_CLKS_CAR_AHB_SW_SEL); | ||
480 | |||
416 | W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f); | 481 | W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0, 0x3ff81f); |
417 | W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf); | 482 | W(RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1, 0xf); |
418 | } | 483 | } |
@@ -453,13 +518,13 @@ static int wil_target_reset(struct wil6210_priv *wil) | |||
453 | /* wait until device ready. typical time is 200..250 msec */ | 518 | /* wait until device ready. typical time is 200..250 msec */ |
454 | do { | 519 | do { |
455 | msleep(RST_DELAY); | 520 | msleep(RST_DELAY); |
456 | hw_state = R(RGF_USER_HW_MACHINE_STATE); | 521 | x = R(RGF_USER_HW_MACHINE_STATE); |
457 | if (delay++ > RST_COUNT) { | 522 | if (delay++ > RST_COUNT) { |
458 | wil_err(wil, "Reset not completed, hw_state 0x%08x\n", | 523 | wil_err(wil, "Reset not completed, hw_state 0x%08x\n", |
459 | hw_state); | 524 | x); |
460 | return -ETIME; | 525 | return -ETIME; |
461 | } | 526 | } |
462 | } while (hw_state != HW_MACHINE_BOOT_DONE); | 527 | } while (x != HW_MACHINE_BOOT_DONE); |
463 | 528 | ||
464 | /* TODO: Erez check rev_id != 1 */ | 529 | /* TODO: Erez check rev_id != 1 */ |
465 | if (!is_sparrow && (rev_id != 1)) | 530 | if (!is_sparrow && (rev_id != 1)) |
@@ -535,7 +600,7 @@ int wil_reset(struct wil6210_priv *wil) | |||
535 | WARN_ON(test_bit(wil_status_napi_en, &wil->status)); | 600 | WARN_ON(test_bit(wil_status_napi_en, &wil->status)); |
536 | 601 | ||
537 | cancel_work_sync(&wil->disconnect_worker); | 602 | cancel_work_sync(&wil->disconnect_worker); |
538 | wil6210_disconnect(wil, NULL); | 603 | wil6210_disconnect(wil, NULL, false); |
539 | 604 | ||
540 | wil->status = 0; /* prevent NAPI from being scheduled */ | 605 | wil->status = 0; /* prevent NAPI from being scheduled */ |
541 | 606 | ||
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c index 239965106c05..e81703ca7701 100644 --- a/drivers/net/wireless/ath/wil6210/netdev.c +++ b/drivers/net/wireless/ath/wil6210/netdev.c | |||
@@ -41,7 +41,7 @@ static int wil_change_mtu(struct net_device *ndev, int new_mtu) | |||
41 | { | 41 | { |
42 | struct wil6210_priv *wil = ndev_to_wil(ndev); | 42 | struct wil6210_priv *wil = ndev_to_wil(ndev); |
43 | 43 | ||
44 | if (new_mtu < 68 || new_mtu > (TX_BUF_LEN - ETH_HLEN)) { | 44 | if (new_mtu < 68 || new_mtu > mtu_max) { |
45 | wil_err(wil, "invalid MTU %d\n", new_mtu); | 45 | wil_err(wil, "invalid MTU %d\n", new_mtu); |
46 | return -EINVAL; | 46 | return -EINVAL; |
47 | } | 47 | } |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c index 2936ef0c18cb..c680906bc0dc 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.c +++ b/drivers/net/wireless/ath/wil6210/txrx.c | |||
@@ -206,7 +206,7 @@ static int wil_vring_alloc_skb(struct wil6210_priv *wil, struct vring *vring, | |||
206 | u32 i, int headroom) | 206 | u32 i, int headroom) |
207 | { | 207 | { |
208 | struct device *dev = wil_to_dev(wil); | 208 | struct device *dev = wil_to_dev(wil); |
209 | unsigned int sz = RX_BUF_LEN; | 209 | unsigned int sz = mtu_max + ETH_HLEN; |
210 | struct vring_rx_desc dd, *d = ⅆ | 210 | struct vring_rx_desc dd, *d = ⅆ |
211 | volatile struct vring_rx_desc *_d = &vring->va[i].rx; | 211 | volatile struct vring_rx_desc *_d = &vring->va[i].rx; |
212 | dma_addr_t pa; | 212 | dma_addr_t pa; |
@@ -385,7 +385,7 @@ static struct sk_buff *wil_vring_reap_rx(struct wil6210_priv *wil, | |||
385 | struct vring_rx_desc *d; | 385 | struct vring_rx_desc *d; |
386 | struct sk_buff *skb; | 386 | struct sk_buff *skb; |
387 | dma_addr_t pa; | 387 | dma_addr_t pa; |
388 | unsigned int sz = RX_BUF_LEN; | 388 | unsigned int sz = mtu_max + ETH_HLEN; |
389 | u16 dmalen; | 389 | u16 dmalen; |
390 | u8 ftype; | 390 | u8 ftype; |
391 | u8 ds_bits; | 391 | u8 ds_bits; |
@@ -646,7 +646,8 @@ int wil_vring_init_tx(struct wil6210_priv *wil, int id, int size, | |||
646 | .action = cpu_to_le32(WMI_VRING_CMD_ADD), | 646 | .action = cpu_to_le32(WMI_VRING_CMD_ADD), |
647 | .vring_cfg = { | 647 | .vring_cfg = { |
648 | .tx_sw_ring = { | 648 | .tx_sw_ring = { |
649 | .max_mpdu_size = cpu_to_le16(TX_BUF_LEN), | 649 | .max_mpdu_size = |
650 | cpu_to_le16(mtu_max + ETH_HLEN), | ||
650 | .ring_size = cpu_to_le16(size), | 651 | .ring_size = cpu_to_le16(size), |
651 | }, | 652 | }, |
652 | .ringid = id, | 653 | .ringid = id, |
diff --git a/drivers/net/wireless/ath/wil6210/txrx.h b/drivers/net/wireless/ath/wil6210/txrx.h index de046716d2b7..630aeb5fa7f4 100644 --- a/drivers/net/wireless/ath/wil6210/txrx.h +++ b/drivers/net/wireless/ath/wil6210/txrx.h | |||
@@ -21,8 +21,8 @@ | |||
21 | #define BUF_HW_OWNED (0) | 21 | #define BUF_HW_OWNED (0) |
22 | 22 | ||
23 | /* size of max. Tx/Rx buffers, as supported by FW */ | 23 | /* size of max. Tx/Rx buffers, as supported by FW */ |
24 | #define RX_BUF_LEN (2242) | 24 | #define TXRX_BUF_LEN_DEFAULT (2242) |
25 | #define TX_BUF_LEN (2242) | 25 | |
26 | /* how many bytes to reserve for rtap header? */ | 26 | /* how many bytes to reserve for rtap header? */ |
27 | #define WIL6210_RTAP_SIZE (128) | 27 | #define WIL6210_RTAP_SIZE (128) |
28 | 28 | ||
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h index ce6488e42091..95d3a062d35c 100644 --- a/drivers/net/wireless/ath/wil6210/wil6210.h +++ b/drivers/net/wireless/ath/wil6210/wil6210.h | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "wil_platform.h" | 24 | #include "wil_platform.h" |
25 | 25 | ||
26 | extern bool no_fw_recovery; | 26 | extern bool no_fw_recovery; |
27 | extern unsigned int mtu_max; | ||
27 | 28 | ||
28 | #define WIL_NAME "wil6210" | 29 | #define WIL_NAME "wil6210" |
29 | #define WIL_FW_NAME "wil6210.fw" | 30 | #define WIL_FW_NAME "wil6210.fw" |
@@ -117,6 +118,8 @@ struct RGF_ICR { | |||
117 | #define BIT_USER_USER_ICR_SW_INT_2 BIT(18) | 118 | #define BIT_USER_USER_ICR_SW_INT_2 BIT(18) |
118 | #define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0 (0x880c18) | 119 | #define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_0 (0x880c18) |
119 | #define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1 (0x880c2c) | 120 | #define RGF_USER_CLKS_CTL_EXT_SW_RST_VEC_1 (0x880c2c) |
121 | #define RGF_USER_SPARROW_M_4 (0x880c50) /* Sparrow */ | ||
122 | #define BIT_SPARROW_M_4_SEL_SLEEP_OR_REF BIT(2) | ||
120 | 123 | ||
121 | #define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ | 124 | #define RGF_DMA_EP_TX_ICR (0x881bb4) /* struct RGF_ICR */ |
122 | #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) | 125 | #define BIT_DMA_EP_TX_ICR_TX_DONE BIT(0) |
@@ -152,6 +155,10 @@ struct RGF_ICR { | |||
152 | #define RGF_MAC_MTRL_COUNTER_0 (0x886aa8) | 155 | #define RGF_MAC_MTRL_COUNTER_0 (0x886aa8) |
153 | 156 | ||
154 | #define RGF_CAF_ICR (0x88946c) /* struct RGF_ICR */ | 157 | #define RGF_CAF_ICR (0x88946c) /* struct RGF_ICR */ |
158 | #define RGF_CAF_OSC_CONTROL (0x88afa4) | ||
159 | #define BIT_CAF_OSC_XTAL_EN BIT(0) | ||
160 | #define RGF_CAF_PLL_LOCK_STATUS (0x88afec) | ||
161 | #define BIT_CAF_OSC_DIG_XTAL_STABLE BIT(0) | ||
155 | 162 | ||
156 | /* popular locations */ | 163 | /* popular locations */ |
157 | #define HOST_MBOX HOSTADDR(RGF_USER_USER_SCRATCH_PAD) | 164 | #define HOST_MBOX HOSTADDR(RGF_USER_USER_SCRATCH_PAD) |
@@ -463,8 +470,11 @@ struct wil6210_priv { | |||
463 | #define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr)) | 470 | #define ndev_to_wil(n) (wdev_to_wil(n->ieee80211_ptr)) |
464 | #define wil_to_pcie_dev(i) (&i->pdev->dev) | 471 | #define wil_to_pcie_dev(i) (&i->pdev->dev) |
465 | 472 | ||
473 | __printf(2, 3) | ||
466 | void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...); | 474 | void wil_dbg_trace(struct wil6210_priv *wil, const char *fmt, ...); |
475 | __printf(2, 3) | ||
467 | void wil_err(struct wil6210_priv *wil, const char *fmt, ...); | 476 | void wil_err(struct wil6210_priv *wil, const char *fmt, ...); |
477 | __printf(2, 3) | ||
468 | void wil_info(struct wil6210_priv *wil, const char *fmt, ...); | 478 | void wil_info(struct wil6210_priv *wil, const char *fmt, ...); |
469 | #define wil_dbg(wil, fmt, arg...) do { \ | 479 | #define wil_dbg(wil, fmt, arg...) do { \ |
470 | netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \ | 480 | netdev_dbg(wil_to_ndev(wil), fmt, ##arg); \ |
@@ -575,7 +585,8 @@ void wil_wdev_free(struct wil6210_priv *wil); | |||
575 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); | 585 | int wmi_set_mac_address(struct wil6210_priv *wil, void *addr); |
576 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); | 586 | int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan); |
577 | int wmi_pcp_stop(struct wil6210_priv *wil); | 587 | int wmi_pcp_stop(struct wil6210_priv *wil); |
578 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid); | 588 | void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid, |
589 | bool from_event); | ||
579 | 590 | ||
580 | int wil_rx_init(struct wil6210_priv *wil); | 591 | int wil_rx_init(struct wil6210_priv *wil); |
581 | void wil_rx_fini(struct wil6210_priv *wil); | 592 | void wil_rx_fini(struct wil6210_priv *wil); |
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c index 4311df982c60..bb1e066f756a 100644 --- a/drivers/net/wireless/ath/wil6210/wmi.c +++ b/drivers/net/wireless/ath/wil6210/wmi.c | |||
@@ -486,7 +486,7 @@ static void wmi_evt_disconnect(struct wil6210_priv *wil, int id, | |||
486 | wil->sinfo_gen++; | 486 | wil->sinfo_gen++; |
487 | 487 | ||
488 | mutex_lock(&wil->mutex); | 488 | mutex_lock(&wil->mutex); |
489 | wil6210_disconnect(wil, evt->bssid); | 489 | wil6210_disconnect(wil, evt->bssid, true); |
490 | mutex_unlock(&wil->mutex); | 490 | mutex_unlock(&wil->mutex); |
491 | } | 491 | } |
492 | 492 | ||
@@ -1025,7 +1025,7 @@ int wmi_rx_chain_add(struct wil6210_priv *wil, struct vring *vring) | |||
1025 | struct wmi_cfg_rx_chain_cmd cmd = { | 1025 | struct wmi_cfg_rx_chain_cmd cmd = { |
1026 | .action = WMI_RX_CHAIN_ADD, | 1026 | .action = WMI_RX_CHAIN_ADD, |
1027 | .rx_sw_ring = { | 1027 | .rx_sw_ring = { |
1028 | .max_mpdu_size = cpu_to_le16(RX_BUF_LEN), | 1028 | .max_mpdu_size = cpu_to_le16(mtu_max + ETH_HLEN), |
1029 | .ring_mem_base = cpu_to_le64(vring->pa), | 1029 | .ring_mem_base = cpu_to_le64(vring->pa), |
1030 | .ring_size = cpu_to_le16(vring->size), | 1030 | .ring_size = cpu_to_le16(vring->size), |
1031 | }, | 1031 | }, |
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index 5d4173ee55bc..47731cb0d815 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -5110,7 +5110,9 @@ static void b43_op_sta_notify(struct ieee80211_hw *hw, | |||
5110 | B43_WARN_ON(!vif || wl->vif != vif); | 5110 | B43_WARN_ON(!vif || wl->vif != vif); |
5111 | } | 5111 | } |
5112 | 5112 | ||
5113 | static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw) | 5113 | static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw, |
5114 | struct ieee80211_vif *vif, | ||
5115 | const u8 *mac_addr) | ||
5114 | { | 5116 | { |
5115 | struct b43_wl *wl = hw_to_b43_wl(hw); | 5117 | struct b43_wl *wl = hw_to_b43_wl(hw); |
5116 | struct b43_wldev *dev; | 5118 | struct b43_wldev *dev; |
@@ -5124,7 +5126,8 @@ static void b43_op_sw_scan_start_notifier(struct ieee80211_hw *hw) | |||
5124 | mutex_unlock(&wl->mutex); | 5126 | mutex_unlock(&wl->mutex); |
5125 | } | 5127 | } |
5126 | 5128 | ||
5127 | static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw) | 5129 | static void b43_op_sw_scan_complete_notifier(struct ieee80211_hw *hw, |
5130 | struct ieee80211_vif *vif) | ||
5128 | { | 5131 | { |
5129 | struct b43_wl *wl = hw_to_b43_wl(hw); | 5132 | struct b43_wl *wl = hw_to_b43_wl(hw); |
5130 | struct b43_wldev *dev; | 5133 | struct b43_wldev *dev; |
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index 1dfc682a8055..ee27b06074e1 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c | |||
@@ -300,9 +300,7 @@ void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value) | |||
300 | 300 | ||
301 | void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg) | 301 | void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg) |
302 | { | 302 | { |
303 | assert_mac_suspended(dev); | 303 | b43_phy_write(dev, destreg, b43_phy_read(dev, srcreg)); |
304 | dev->phy.ops->phy_write(dev, destreg, | ||
305 | dev->phy.ops->phy_read(dev, srcreg)); | ||
306 | } | 304 | } |
307 | 305 | ||
308 | void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask) | 306 | void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index 90a977fe9a64..dc4c75083085 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile | |||
@@ -23,15 +23,15 @@ ccflags-y += -D__CHECK_ENDIAN__ | |||
23 | 23 | ||
24 | obj-$(CONFIG_BRCMFMAC) += brcmfmac.o | 24 | obj-$(CONFIG_BRCMFMAC) += brcmfmac.o |
25 | brcmfmac-objs += \ | 25 | brcmfmac-objs += \ |
26 | wl_cfg80211.o \ | 26 | cfg80211.o \ |
27 | chip.o \ | 27 | chip.o \ |
28 | fwil.o \ | 28 | fwil.o \ |
29 | fweh.o \ | 29 | fweh.o \ |
30 | fwsignal.o \ | 30 | fwsignal.o \ |
31 | p2p.o \ | 31 | p2p.o \ |
32 | proto.o \ | 32 | proto.o \ |
33 | dhd_common.o \ | 33 | common.o \ |
34 | dhd_linux.o \ | 34 | core.o \ |
35 | firmware.o \ | 35 | firmware.o \ |
36 | feature.o \ | 36 | feature.o \ |
37 | btcoex.o \ | 37 | btcoex.o \ |
@@ -43,14 +43,14 @@ brcmfmac-$(CONFIG_BRCMFMAC_PROTO_MSGBUF) += \ | |||
43 | flowring.o \ | 43 | flowring.o \ |
44 | msgbuf.o | 44 | msgbuf.o |
45 | brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ | 45 | brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ |
46 | dhd_sdio.o \ | 46 | sdio.o \ |
47 | bcmsdh.o | 47 | bcmsdh.o |
48 | brcmfmac-$(CONFIG_BRCMFMAC_USB) += \ | 48 | brcmfmac-$(CONFIG_BRCMFMAC_USB) += \ |
49 | usb.o | 49 | usb.o |
50 | brcmfmac-$(CONFIG_BRCMFMAC_PCIE) += \ | 50 | brcmfmac-$(CONFIG_BRCMFMAC_PCIE) += \ |
51 | pcie.o | 51 | pcie.o |
52 | brcmfmac-$(CONFIG_BRCMDBG) += \ | 52 | brcmfmac-$(CONFIG_BRCMDBG) += \ |
53 | dhd_dbg.o | 53 | debug.o |
54 | brcmfmac-$(CONFIG_BRCM_TRACING) += \ | 54 | brcmfmac-$(CONFIG_BRCM_TRACING) += \ |
55 | tracepoint.o | 55 | tracepoint.o |
56 | brcmfmac-$(CONFIG_OF) += \ | 56 | brcmfmac-$(CONFIG_OF) += \ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c index a159ff3427de..8e0e91c4a0b1 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.c | |||
@@ -25,10 +25,10 @@ | |||
25 | #include <brcmu_utils.h> | 25 | #include <brcmu_utils.h> |
26 | #include <brcmu_wifi.h> | 26 | #include <brcmu_wifi.h> |
27 | 27 | ||
28 | #include "dhd.h" | 28 | #include "core.h" |
29 | #include "dhd_bus.h" | 29 | #include "bus.h" |
30 | #include "fwsignal.h" | 30 | #include "fwsignal.h" |
31 | #include "dhd_dbg.h" | 31 | #include "debug.h" |
32 | #include "tracepoint.h" | 32 | #include "tracepoint.h" |
33 | #include "proto.h" | 33 | #include "proto.h" |
34 | #include "bcdc.h" | 34 | #include "bcdc.h" |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c index 8dbd5dbb78fd..f754ffcd0308 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcmsdh.c | |||
@@ -41,9 +41,9 @@ | |||
41 | #include <chipcommon.h> | 41 | #include <chipcommon.h> |
42 | #include <soc.h> | 42 | #include <soc.h> |
43 | #include "chip.h" | 43 | #include "chip.h" |
44 | #include "dhd_bus.h" | 44 | #include "bus.h" |
45 | #include "dhd_dbg.h" | 45 | #include "debug.h" |
46 | #include "sdio_host.h" | 46 | #include "sdio.h" |
47 | #include "of.h" | 47 | #include "of.h" |
48 | 48 | ||
49 | #define SDIOH_API_ACCESS_RETRY_LIMIT 2 | 49 | #define SDIOH_API_ACCESS_RETRY_LIMIT 2 |
@@ -1064,6 +1064,16 @@ static int brcmf_ops_sdio_probe(struct sdio_func *func, | |||
1064 | if (!sdiodev->pdata) | 1064 | if (!sdiodev->pdata) |
1065 | brcmf_of_probe(sdiodev); | 1065 | brcmf_of_probe(sdiodev); |
1066 | 1066 | ||
1067 | #ifdef CONFIG_PM_SLEEP | ||
1068 | /* wowl can be supported when KEEP_POWER is true and (WAKE_SDIO_IRQ | ||
1069 | * is true or when platform data OOB irq is true). | ||
1070 | */ | ||
1071 | if ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_KEEP_POWER) && | ||
1072 | ((sdio_get_host_pm_caps(sdiodev->func[1]) & MMC_PM_WAKE_SDIO_IRQ) || | ||
1073 | (sdiodev->pdata->oob_irq_supported))) | ||
1074 | bus_if->wowl_supported = true; | ||
1075 | #endif | ||
1076 | |||
1067 | atomic_set(&sdiodev->suspend, false); | 1077 | atomic_set(&sdiodev->suspend, false); |
1068 | init_waitqueue_head(&sdiodev->request_word_wait); | 1078 | init_waitqueue_head(&sdiodev->request_word_wait); |
1069 | init_waitqueue_head(&sdiodev->request_buffer_wait); | 1079 | init_waitqueue_head(&sdiodev->request_buffer_wait); |
@@ -1116,34 +1126,39 @@ static void brcmf_ops_sdio_remove(struct sdio_func *func) | |||
1116 | brcmf_dbg(SDIO, "Exit\n"); | 1126 | brcmf_dbg(SDIO, "Exit\n"); |
1117 | } | 1127 | } |
1118 | 1128 | ||
1129 | void brcmf_sdio_wowl_config(struct device *dev, bool enabled) | ||
1130 | { | ||
1131 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
1132 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | ||
1133 | |||
1134 | brcmf_dbg(SDIO, "Configuring WOWL, enabled=%d\n", enabled); | ||
1135 | sdiodev->wowl_enabled = enabled; | ||
1136 | } | ||
1137 | |||
1119 | #ifdef CONFIG_PM_SLEEP | 1138 | #ifdef CONFIG_PM_SLEEP |
1120 | static int brcmf_ops_sdio_suspend(struct device *dev) | 1139 | static int brcmf_ops_sdio_suspend(struct device *dev) |
1121 | { | 1140 | { |
1122 | mmc_pm_flag_t sdio_flags; | ||
1123 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | 1141 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); |
1124 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 1142 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
1125 | int ret = 0; | 1143 | mmc_pm_flag_t sdio_flags; |
1126 | 1144 | ||
1127 | brcmf_dbg(SDIO, "Enter\n"); | 1145 | brcmf_dbg(SDIO, "Enter\n"); |
1128 | 1146 | ||
1129 | sdio_flags = sdio_get_host_pm_caps(sdiodev->func[1]); | ||
1130 | if (!(sdio_flags & MMC_PM_KEEP_POWER)) { | ||
1131 | brcmf_err("Host can't keep power while suspended\n"); | ||
1132 | return -EINVAL; | ||
1133 | } | ||
1134 | |||
1135 | atomic_set(&sdiodev->suspend, true); | 1147 | atomic_set(&sdiodev->suspend, true); |
1136 | 1148 | ||
1137 | ret = sdio_set_host_pm_flags(sdiodev->func[1], MMC_PM_KEEP_POWER); | 1149 | if (sdiodev->wowl_enabled) { |
1138 | if (ret) { | 1150 | sdio_flags = MMC_PM_KEEP_POWER; |
1139 | brcmf_err("Failed to set pm_flags\n"); | 1151 | if (sdiodev->pdata->oob_irq_supported) |
1140 | atomic_set(&sdiodev->suspend, false); | 1152 | enable_irq_wake(sdiodev->pdata->oob_irq_nr); |
1141 | return ret; | 1153 | else |
1154 | sdio_flags = MMC_PM_WAKE_SDIO_IRQ; | ||
1155 | if (sdio_set_host_pm_flags(sdiodev->func[1], sdio_flags)) | ||
1156 | brcmf_err("Failed to set pm_flags %x\n", sdio_flags); | ||
1142 | } | 1157 | } |
1143 | 1158 | ||
1144 | brcmf_sdio_wd_timer(sdiodev->bus, 0); | 1159 | brcmf_sdio_wd_timer(sdiodev->bus, 0); |
1145 | 1160 | ||
1146 | return ret; | 1161 | return 0; |
1147 | } | 1162 | } |
1148 | 1163 | ||
1149 | static int brcmf_ops_sdio_resume(struct device *dev) | 1164 | static int brcmf_ops_sdio_resume(struct device *dev) |
@@ -1152,6 +1167,8 @@ static int brcmf_ops_sdio_resume(struct device *dev) | |||
1152 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; | 1167 | struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio; |
1153 | 1168 | ||
1154 | brcmf_dbg(SDIO, "Enter\n"); | 1169 | brcmf_dbg(SDIO, "Enter\n"); |
1170 | if (sdiodev->pdata->oob_irq_supported) | ||
1171 | disable_irq_wake(sdiodev->pdata->oob_irq_nr); | ||
1155 | brcmf_sdio_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS); | 1172 | brcmf_sdio_wd_timer(sdiodev->bus, BRCMF_WD_POLL_MS); |
1156 | atomic_set(&sdiodev->suspend, false); | 1173 | atomic_set(&sdiodev->suspend, false); |
1157 | return 0; | 1174 | return 0; |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c index a29ac4977b3a..0445163991b7 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/btcoex.c | |||
@@ -20,13 +20,13 @@ | |||
20 | #include <brcmu_wifi.h> | 20 | #include <brcmu_wifi.h> |
21 | #include <brcmu_utils.h> | 21 | #include <brcmu_utils.h> |
22 | #include <defs.h> | 22 | #include <defs.h> |
23 | #include <dhd.h> | 23 | #include "core.h" |
24 | #include <dhd_dbg.h> | 24 | #include "debug.h" |
25 | #include "fwil.h" | 25 | #include "fwil.h" |
26 | #include "fwil_types.h" | 26 | #include "fwil_types.h" |
27 | #include "btcoex.h" | 27 | #include "btcoex.h" |
28 | #include "p2p.h" | 28 | #include "p2p.h" |
29 | #include "wl_cfg80211.h" | 29 | #include "cfg80211.h" |
30 | 30 | ||
31 | /* T1 start SCO/eSCO priority suppression */ | 31 | /* T1 start SCO/eSCO priority suppression */ |
32 | #define BRCMF_BTCOEX_OPPR_WIN_TIME 2000 | 32 | #define BRCMF_BTCOEX_OPPR_WIN_TIME 2000 |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/bus.h index 80e73a1262be..ef344e47218a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/bus.h | |||
@@ -14,10 +14,10 @@ | |||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef _BRCMF_BUS_H_ | 17 | #ifndef BRCMFMAC_BUS_H |
18 | #define _BRCMF_BUS_H_ | 18 | #define BRCMFMAC_BUS_H |
19 | 19 | ||
20 | #include "dhd_dbg.h" | 20 | #include "debug.h" |
21 | 21 | ||
22 | /* IDs of the 6 default common rings of msgbuf protocol */ | 22 | /* IDs of the 6 default common rings of msgbuf protocol */ |
23 | #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0 | 23 | #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT 0 |
@@ -227,8 +227,7 @@ void brcmf_txflowblock(struct device *dev, bool state); | |||
227 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); | 227 | void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success); |
228 | 228 | ||
229 | int brcmf_bus_start(struct device *dev); | 229 | int brcmf_bus_start(struct device *dev); |
230 | s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, | 230 | s32 brcmf_iovar_data_set(struct device *dev, char *name, void *data, u32 len); |
231 | u32 len); | ||
232 | void brcmf_bus_add_txhdrlen(struct device *dev, uint len); | 231 | void brcmf_bus_add_txhdrlen(struct device *dev, uint len); |
233 | 232 | ||
234 | #ifdef CONFIG_BRCMFMAC_SDIO | 233 | #ifdef CONFIG_BRCMFMAC_SDIO |
@@ -241,4 +240,4 @@ void brcmf_usb_exit(void); | |||
241 | void brcmf_usb_register(void); | 240 | void brcmf_usb_register(void); |
242 | #endif | 241 | #endif |
243 | 242 | ||
244 | #endif /* _BRCMF_BUS_H_ */ | 243 | #endif /* BRCMFMAC_BUS_H */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c index 28fa25b509db..f8a9dfa657ba 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.c | |||
@@ -26,18 +26,18 @@ | |||
26 | #include <brcmu_utils.h> | 26 | #include <brcmu_utils.h> |
27 | #include <defs.h> | 27 | #include <defs.h> |
28 | #include <brcmu_wifi.h> | 28 | #include <brcmu_wifi.h> |
29 | #include "dhd.h" | 29 | #include "core.h" |
30 | #include "dhd_dbg.h" | 30 | #include "debug.h" |
31 | #include "tracepoint.h" | 31 | #include "tracepoint.h" |
32 | #include "fwil_types.h" | 32 | #include "fwil_types.h" |
33 | #include "p2p.h" | 33 | #include "p2p.h" |
34 | #include "btcoex.h" | 34 | #include "btcoex.h" |
35 | #include "wl_cfg80211.h" | 35 | #include "cfg80211.h" |
36 | #include "feature.h" | 36 | #include "feature.h" |
37 | #include "fwil.h" | 37 | #include "fwil.h" |
38 | #include "proto.h" | 38 | #include "proto.h" |
39 | #include "vendor.h" | 39 | #include "vendor.h" |
40 | #include "dhd_bus.h" | 40 | #include "bus.h" |
41 | 41 | ||
42 | #define BRCMF_SCAN_IE_LEN_MAX 2048 | 42 | #define BRCMF_SCAN_IE_LEN_MAX 2048 |
43 | #define BRCMF_PNO_VERSION 2 | 43 | #define BRCMF_PNO_VERSION 2 |
@@ -299,6 +299,7 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, | |||
299 | primary_offset = ch->center_freq1 - ch->chan->center_freq; | 299 | primary_offset = ch->center_freq1 - ch->chan->center_freq; |
300 | switch (ch->width) { | 300 | switch (ch->width) { |
301 | case NL80211_CHAN_WIDTH_20: | 301 | case NL80211_CHAN_WIDTH_20: |
302 | case NL80211_CHAN_WIDTH_20_NOHT: | ||
302 | ch_inf.bw = BRCMU_CHAN_BW_20; | 303 | ch_inf.bw = BRCMU_CHAN_BW_20; |
303 | WARN_ON(primary_offset != 0); | 304 | WARN_ON(primary_offset != 0); |
304 | break; | 305 | break; |
@@ -323,6 +324,10 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, | |||
323 | ch_inf.sb = BRCMU_CHAN_SB_LU; | 324 | ch_inf.sb = BRCMU_CHAN_SB_LU; |
324 | } | 325 | } |
325 | break; | 326 | break; |
327 | case NL80211_CHAN_WIDTH_80P80: | ||
328 | case NL80211_CHAN_WIDTH_160: | ||
329 | case NL80211_CHAN_WIDTH_5: | ||
330 | case NL80211_CHAN_WIDTH_10: | ||
326 | default: | 331 | default: |
327 | WARN_ON_ONCE(1); | 332 | WARN_ON_ONCE(1); |
328 | } | 333 | } |
@@ -333,6 +338,7 @@ static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf, | |||
333 | case IEEE80211_BAND_5GHZ: | 338 | case IEEE80211_BAND_5GHZ: |
334 | ch_inf.band = BRCMU_CHAN_BAND_5G; | 339 | ch_inf.band = BRCMU_CHAN_BAND_5G; |
335 | break; | 340 | break; |
341 | case IEEE80211_BAND_60GHZ: | ||
336 | default: | 342 | default: |
337 | WARN_ON_ONCE(1); | 343 | WARN_ON_ONCE(1); |
338 | } | 344 | } |
@@ -2779,6 +2785,44 @@ static __always_inline void brcmf_delay(u32 ms) | |||
2779 | } | 2785 | } |
2780 | } | 2786 | } |
2781 | 2787 | ||
2788 | static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4], | ||
2789 | u8 *pattern, u32 patternsize, u8 *mask, | ||
2790 | u32 packet_offset) | ||
2791 | { | ||
2792 | struct brcmf_fil_wowl_pattern_le *filter; | ||
2793 | u32 masksize; | ||
2794 | u32 patternoffset; | ||
2795 | u8 *buf; | ||
2796 | u32 bufsize; | ||
2797 | s32 ret; | ||
2798 | |||
2799 | masksize = (patternsize + 7) / 8; | ||
2800 | patternoffset = sizeof(*filter) - sizeof(filter->cmd) + masksize; | ||
2801 | |||
2802 | bufsize = sizeof(*filter) + patternsize + masksize; | ||
2803 | buf = kzalloc(bufsize, GFP_KERNEL); | ||
2804 | if (!buf) | ||
2805 | return -ENOMEM; | ||
2806 | filter = (struct brcmf_fil_wowl_pattern_le *)buf; | ||
2807 | |||
2808 | memcpy(filter->cmd, cmd, 4); | ||
2809 | filter->masksize = cpu_to_le32(masksize); | ||
2810 | filter->offset = cpu_to_le32(packet_offset); | ||
2811 | filter->patternoffset = cpu_to_le32(patternoffset); | ||
2812 | filter->patternsize = cpu_to_le32(patternsize); | ||
2813 | filter->type = cpu_to_le32(BRCMF_WOWL_PATTERN_TYPE_BITMAP); | ||
2814 | |||
2815 | if ((mask) && (masksize)) | ||
2816 | memcpy(buf + sizeof(*filter), mask, masksize); | ||
2817 | if ((pattern) && (patternsize)) | ||
2818 | memcpy(buf + sizeof(*filter) + masksize, pattern, patternsize); | ||
2819 | |||
2820 | ret = brcmf_fil_iovar_data_set(ifp, "wowl_pattern", buf, bufsize); | ||
2821 | |||
2822 | kfree(buf); | ||
2823 | return ret; | ||
2824 | } | ||
2825 | |||
2782 | static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) | 2826 | static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) |
2783 | { | 2827 | { |
2784 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 2828 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
@@ -2788,10 +2832,11 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) | |||
2788 | brcmf_dbg(TRACE, "Enter\n"); | 2832 | brcmf_dbg(TRACE, "Enter\n"); |
2789 | 2833 | ||
2790 | if (cfg->wowl_enabled) { | 2834 | if (cfg->wowl_enabled) { |
2835 | brcmf_configure_arp_offload(ifp, true); | ||
2791 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, | 2836 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, |
2792 | cfg->pre_wowl_pmmode); | 2837 | cfg->pre_wowl_pmmode); |
2793 | brcmf_fil_iovar_data_set(ifp, "wowl_pattern", "clr", 4); | ||
2794 | brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0); | 2838 | brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0); |
2839 | brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0); | ||
2795 | cfg->wowl_enabled = false; | 2840 | cfg->wowl_enabled = false; |
2796 | } | 2841 | } |
2797 | return 0; | 2842 | return 0; |
@@ -2802,21 +2847,29 @@ static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg, | |||
2802 | struct cfg80211_wowlan *wowl) | 2847 | struct cfg80211_wowlan *wowl) |
2803 | { | 2848 | { |
2804 | u32 wowl_config; | 2849 | u32 wowl_config; |
2850 | u32 i; | ||
2805 | 2851 | ||
2806 | brcmf_dbg(TRACE, "Suspend, wowl config.\n"); | 2852 | brcmf_dbg(TRACE, "Suspend, wowl config.\n"); |
2807 | 2853 | ||
2854 | brcmf_configure_arp_offload(ifp, false); | ||
2808 | brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PM, &cfg->pre_wowl_pmmode); | 2855 | brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PM, &cfg->pre_wowl_pmmode); |
2809 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, PM_MAX); | 2856 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, PM_MAX); |
2810 | 2857 | ||
2811 | wowl_config = 0; | 2858 | wowl_config = 0; |
2812 | if (wowl->disconnect) | 2859 | if (wowl->disconnect) |
2813 | wowl_config |= WL_WOWL_DIS | WL_WOWL_BCN | WL_WOWL_RETR; | 2860 | wowl_config = BRCMF_WOWL_DIS | BRCMF_WOWL_BCN | BRCMF_WOWL_RETR; |
2814 | /* Note: if "wowl" target and not "wowlpf" then wowl_bcn_loss | ||
2815 | * should be configured. This paramater is not supported by | ||
2816 | * wowlpf. | ||
2817 | */ | ||
2818 | if (wowl->magic_pkt) | 2861 | if (wowl->magic_pkt) |
2819 | wowl_config |= WL_WOWL_MAGIC; | 2862 | wowl_config |= BRCMF_WOWL_MAGIC; |
2863 | if ((wowl->patterns) && (wowl->n_patterns)) { | ||
2864 | wowl_config |= BRCMF_WOWL_NET; | ||
2865 | for (i = 0; i < wowl->n_patterns; i++) { | ||
2866 | brcmf_config_wowl_pattern(ifp, "add", | ||
2867 | (u8 *)wowl->patterns[i].pattern, | ||
2868 | wowl->patterns[i].pattern_len, | ||
2869 | (u8 *)wowl->patterns[i].mask, | ||
2870 | wowl->patterns[i].pkt_offset); | ||
2871 | } | ||
2872 | } | ||
2820 | brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config); | 2873 | brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config); |
2821 | brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1); | 2874 | brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1); |
2822 | brcmf_bus_wowl_config(cfg->pub->bus_if, true); | 2875 | brcmf_bus_wowl_config(cfg->pub->bus_if, true); |
@@ -3998,24 +4051,24 @@ brcmf_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev, | |||
3998 | 4051 | ||
3999 | static int | 4052 | static int |
4000 | brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, | 4053 | brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, |
4001 | const u8 *mac) | 4054 | struct station_del_parameters *params) |
4002 | { | 4055 | { |
4003 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 4056 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
4004 | struct brcmf_scb_val_le scbval; | 4057 | struct brcmf_scb_val_le scbval; |
4005 | struct brcmf_if *ifp = netdev_priv(ndev); | 4058 | struct brcmf_if *ifp = netdev_priv(ndev); |
4006 | s32 err; | 4059 | s32 err; |
4007 | 4060 | ||
4008 | if (!mac) | 4061 | if (!params->mac) |
4009 | return -EFAULT; | 4062 | return -EFAULT; |
4010 | 4063 | ||
4011 | brcmf_dbg(TRACE, "Enter %pM\n", mac); | 4064 | brcmf_dbg(TRACE, "Enter %pM\n", params->mac); |
4012 | 4065 | ||
4013 | if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) | 4066 | if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) |
4014 | ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | 4067 | ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; |
4015 | if (!check_vif_up(ifp->vif)) | 4068 | if (!check_vif_up(ifp->vif)) |
4016 | return -EIO; | 4069 | return -EIO; |
4017 | 4070 | ||
4018 | memcpy(&scbval.ea, mac, ETH_ALEN); | 4071 | memcpy(&scbval.ea, params->mac, ETH_ALEN); |
4019 | scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING); | 4072 | scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING); |
4020 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON, | 4073 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON, |
4021 | &scbval, sizeof(scbval)); | 4074 | &scbval, sizeof(scbval)); |
@@ -5440,10 +5493,13 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy) | |||
5440 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | 5493 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; |
5441 | } | 5494 | } |
5442 | 5495 | ||
5443 | |||
5444 | #ifdef CONFIG_PM | 5496 | #ifdef CONFIG_PM |
5445 | static const struct wiphy_wowlan_support brcmf_wowlan_support = { | 5497 | static const struct wiphy_wowlan_support brcmf_wowlan_support = { |
5446 | .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, | 5498 | .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, |
5499 | .n_patterns = BRCMF_WOWL_MAXPATTERNS, | ||
5500 | .pattern_max_len = BRCMF_WOWL_MAXPATTERNSIZE, | ||
5501 | .pattern_min_len = 1, | ||
5502 | .max_pkt_offset = 1500, | ||
5447 | }; | 5503 | }; |
5448 | #endif | 5504 | #endif |
5449 | 5505 | ||
@@ -5607,7 +5663,8 @@ enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp) | |||
5607 | return wdev->iftype; | 5663 | return wdev->iftype; |
5608 | } | 5664 | } |
5609 | 5665 | ||
5610 | bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, unsigned long state) | 5666 | bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, |
5667 | unsigned long state) | ||
5611 | { | 5668 | { |
5612 | struct brcmf_cfg80211_vif *vif; | 5669 | struct brcmf_cfg80211_vif *vif; |
5613 | 5670 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h index 6abf94e41d3d..2a5b22cb3fef 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/cfg80211.h | |||
@@ -14,8 +14,8 @@ | |||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef _wl_cfg80211_h_ | 17 | #ifndef BRCMFMAC_CFG80211_H |
18 | #define _wl_cfg80211_h_ | 18 | #define BRCMFMAC_CFG80211_H |
19 | 19 | ||
20 | /* for brcmu_d11inf */ | 20 | /* for brcmu_d11inf */ |
21 | #include <brcmu_d11.h> | 21 | #include <brcmu_d11.h> |
@@ -480,7 +480,8 @@ const struct brcmf_tlv * | |||
480 | brcmf_parse_tlvs(const void *buf, int buflen, uint key); | 480 | brcmf_parse_tlvs(const void *buf, int buflen, uint key); |
481 | u16 channel_to_chanspec(struct brcmu_d11inf *d11inf, | 481 | u16 channel_to_chanspec(struct brcmu_d11inf *d11inf, |
482 | struct ieee80211_channel *ch); | 482 | struct ieee80211_channel *ch); |
483 | bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, unsigned long state); | 483 | bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, |
484 | unsigned long state); | ||
484 | void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg, | 485 | void brcmf_cfg80211_arm_vif_event(struct brcmf_cfg80211_info *cfg, |
485 | struct brcmf_cfg80211_vif *vif); | 486 | struct brcmf_cfg80211_vif *vif); |
486 | bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg); | 487 | bool brcmf_cfg80211_vif_event_armed(struct brcmf_cfg80211_info *cfg); |
@@ -493,4 +494,4 @@ void brcmf_set_mpc(struct brcmf_if *ndev, int mpc); | |||
493 | void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg); | 494 | void brcmf_abort_scanning(struct brcmf_cfg80211_info *cfg); |
494 | void brcmf_cfg80211_free_netdev(struct net_device *ndev); | 495 | void brcmf_cfg80211_free_netdev(struct net_device *ndev); |
495 | 496 | ||
496 | #endif /* _wl_cfg80211_h_ */ | 497 | #endif /* BRCMFMAC_CFG80211_H */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c index 95efde868db8..ddae0b5e56ec 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c | |||
@@ -25,7 +25,7 @@ | |||
25 | #include <brcm_hw_ids.h> | 25 | #include <brcm_hw_ids.h> |
26 | #include <brcmu_utils.h> | 26 | #include <brcmu_utils.h> |
27 | #include <chipcommon.h> | 27 | #include <chipcommon.h> |
28 | #include "dhd_dbg.h" | 28 | #include "debug.h" |
29 | #include "chip.h" | 29 | #include "chip.h" |
30 | 30 | ||
31 | /* SOC Interconnect types (aka chip types) */ | 31 | /* SOC Interconnect types (aka chip types) */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/common.c b/drivers/net/wireless/brcm80211/brcmfmac/common.c new file mode 100644 index 000000000000..1861a13e8d03 --- /dev/null +++ b/drivers/net/wireless/brcm80211/brcmfmac/common.c | |||
@@ -0,0 +1,168 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Broadcom Corporation | ||
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 ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/netdevice.h> | ||
20 | #include <brcmu_wifi.h> | ||
21 | #include <brcmu_utils.h> | ||
22 | #include "core.h" | ||
23 | #include "bus.h" | ||
24 | #include "debug.h" | ||
25 | #include "fwil.h" | ||
26 | #include "fwil_types.h" | ||
27 | #include "tracepoint.h" | ||
28 | |||
29 | #define BRCMF_DEFAULT_BCN_TIMEOUT 3 | ||
30 | #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40 | ||
31 | #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40 | ||
32 | |||
33 | /* boost value for RSSI_DELTA in preferred join selection */ | ||
34 | #define BRCMF_JOIN_PREF_RSSI_BOOST 8 | ||
35 | |||
36 | int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | ||
37 | { | ||
38 | s8 eventmask[BRCMF_EVENTING_MASK_LEN]; | ||
39 | u8 buf[BRCMF_DCMD_SMLEN]; | ||
40 | struct brcmf_join_pref_params join_pref_params[2]; | ||
41 | char *ptr; | ||
42 | s32 err; | ||
43 | |||
44 | /* retreive mac address */ | ||
45 | err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, | ||
46 | sizeof(ifp->mac_addr)); | ||
47 | if (err < 0) { | ||
48 | brcmf_err("Retreiving cur_etheraddr failed, %d\n", | ||
49 | err); | ||
50 | goto done; | ||
51 | } | ||
52 | memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); | ||
53 | |||
54 | /* query for 'ver' to get version info from firmware */ | ||
55 | memset(buf, 0, sizeof(buf)); | ||
56 | strcpy(buf, "ver"); | ||
57 | err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); | ||
58 | if (err < 0) { | ||
59 | brcmf_err("Retreiving version information failed, %d\n", | ||
60 | err); | ||
61 | goto done; | ||
62 | } | ||
63 | ptr = (char *)buf; | ||
64 | strsep(&ptr, "\n"); | ||
65 | |||
66 | /* Print fw version info */ | ||
67 | brcmf_err("Firmware version = %s\n", buf); | ||
68 | |||
69 | /* locate firmware version number for ethtool */ | ||
70 | ptr = strrchr(buf, ' ') + 1; | ||
71 | strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); | ||
72 | |||
73 | /* set mpc */ | ||
74 | err = brcmf_fil_iovar_int_set(ifp, "mpc", 1); | ||
75 | if (err) { | ||
76 | brcmf_err("failed setting mpc\n"); | ||
77 | goto done; | ||
78 | } | ||
79 | |||
80 | /* | ||
81 | * Setup timeout if Beacons are lost and roam is off to report | ||
82 | * link down | ||
83 | */ | ||
84 | err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", | ||
85 | BRCMF_DEFAULT_BCN_TIMEOUT); | ||
86 | if (err) { | ||
87 | brcmf_err("bcn_timeout error (%d)\n", err); | ||
88 | goto done; | ||
89 | } | ||
90 | |||
91 | /* Enable/Disable build-in roaming to allowed ext supplicant to take | ||
92 | * of romaing | ||
93 | */ | ||
94 | err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1); | ||
95 | if (err) { | ||
96 | brcmf_err("roam_off error (%d)\n", err); | ||
97 | goto done; | ||
98 | } | ||
99 | |||
100 | /* Setup join_pref to select target by RSSI(with boost on 5GHz) */ | ||
101 | join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA; | ||
102 | join_pref_params[0].len = 2; | ||
103 | join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST; | ||
104 | join_pref_params[0].band = WLC_BAND_5G; | ||
105 | join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI; | ||
106 | join_pref_params[1].len = 2; | ||
107 | join_pref_params[1].rssi_gain = 0; | ||
108 | join_pref_params[1].band = 0; | ||
109 | err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, | ||
110 | sizeof(join_pref_params)); | ||
111 | if (err) | ||
112 | brcmf_err("Set join_pref error (%d)\n", err); | ||
113 | |||
114 | /* Setup event_msgs, enable E_IF */ | ||
115 | err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask, | ||
116 | BRCMF_EVENTING_MASK_LEN); | ||
117 | if (err) { | ||
118 | brcmf_err("Get event_msgs error (%d)\n", err); | ||
119 | goto done; | ||
120 | } | ||
121 | setbit(eventmask, BRCMF_E_IF); | ||
122 | err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask, | ||
123 | BRCMF_EVENTING_MASK_LEN); | ||
124 | if (err) { | ||
125 | brcmf_err("Set event_msgs error (%d)\n", err); | ||
126 | goto done; | ||
127 | } | ||
128 | |||
129 | /* Setup default scan channel time */ | ||
130 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, | ||
131 | BRCMF_DEFAULT_SCAN_CHANNEL_TIME); | ||
132 | if (err) { | ||
133 | brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n", | ||
134 | err); | ||
135 | goto done; | ||
136 | } | ||
137 | |||
138 | /* Setup default scan unassoc time */ | ||
139 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME, | ||
140 | BRCMF_DEFAULT_SCAN_UNASSOC_TIME); | ||
141 | if (err) { | ||
142 | brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n", | ||
143 | err); | ||
144 | goto done; | ||
145 | } | ||
146 | |||
147 | /* do bus specific preinit here */ | ||
148 | err = brcmf_bus_preinit(ifp->drvr->bus_if); | ||
149 | done: | ||
150 | return err; | ||
151 | } | ||
152 | |||
153 | #if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG) | ||
154 | void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...) | ||
155 | { | ||
156 | struct va_format vaf = { | ||
157 | .fmt = fmt, | ||
158 | }; | ||
159 | va_list args; | ||
160 | |||
161 | va_start(args, fmt); | ||
162 | vaf.va = &args; | ||
163 | if (brcmf_msg_level & level) | ||
164 | pr_debug("%s %pV", func, &vaf); | ||
165 | trace_brcmf_dbg(level, func, &vaf); | ||
166 | va_end(args); | ||
167 | } | ||
168 | #endif | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c index c6d65b8e1e15..77656c711bed 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/commonring.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/commonring.c | |||
@@ -19,7 +19,7 @@ | |||
19 | #include <brcmu_utils.h> | 19 | #include <brcmu_utils.h> |
20 | #include <brcmu_wifi.h> | 20 | #include <brcmu_wifi.h> |
21 | 21 | ||
22 | #include "dhd.h" | 22 | #include "core.h" |
23 | #include "commonring.h" | 23 | #include "commonring.h" |
24 | 24 | ||
25 | 25 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/core.c index fb1043908a23..f407665cb1ea 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.c | |||
@@ -22,12 +22,12 @@ | |||
22 | #include <brcmu_utils.h> | 22 | #include <brcmu_utils.h> |
23 | #include <brcmu_wifi.h> | 23 | #include <brcmu_wifi.h> |
24 | 24 | ||
25 | #include "dhd.h" | 25 | #include "core.h" |
26 | #include "dhd_bus.h" | 26 | #include "bus.h" |
27 | #include "dhd_dbg.h" | 27 | #include "debug.h" |
28 | #include "fwil_types.h" | 28 | #include "fwil_types.h" |
29 | #include "p2p.h" | 29 | #include "p2p.h" |
30 | #include "wl_cfg80211.h" | 30 | #include "cfg80211.h" |
31 | #include "fwil.h" | 31 | #include "fwil.h" |
32 | #include "fwsignal.h" | 32 | #include "fwsignal.h" |
33 | #include "feature.h" | 33 | #include "feature.h" |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/core.h index 5e4317dbc2b0..98228e922d3a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/core.h | |||
@@ -18,8 +18,8 @@ | |||
18 | * Common types * | 18 | * Common types * |
19 | */ | 19 | */ |
20 | 20 | ||
21 | #ifndef _BRCMF_H_ | 21 | #ifndef BRCMFMAC_CORE_H |
22 | #define _BRCMF_H_ | 22 | #define BRCMFMAC_CORE_H |
23 | 23 | ||
24 | #include "fweh.h" | 24 | #include "fweh.h" |
25 | 25 | ||
@@ -83,7 +83,6 @@ struct brcmf_pub { | |||
83 | /* Internal brcmf items */ | 83 | /* Internal brcmf items */ |
84 | uint hdrlen; /* Total BRCMF header length (proto + bus) */ | 84 | uint hdrlen; /* Total BRCMF header length (proto + bus) */ |
85 | uint rxsz; /* Rx buffer size bus module should use */ | 85 | uint rxsz; /* Rx buffer size bus module should use */ |
86 | u8 wme_dp; /* wme discard priority */ | ||
87 | 86 | ||
88 | /* Dongle media info */ | 87 | /* Dongle media info */ |
89 | char fwver[BRCMF_DRIVER_FIRMWARE_VERSION_LEN]; | 88 | char fwver[BRCMF_DRIVER_FIRMWARE_VERSION_LEN]; |
@@ -186,4 +185,4 @@ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb); | |||
186 | /* Sets dongle media info (drv_version, mac address). */ | 185 | /* Sets dongle media info (drv_version, mac address). */ |
187 | int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); | 186 | int brcmf_c_preinit_dcmds(struct brcmf_if *ifp); |
188 | 187 | ||
189 | #endif /* _BRCMF_H_ */ | 188 | #endif /* BRCMFMAC_CORE_H */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c b/drivers/net/wireless/brcm80211/brcmfmac/debug.c index be9f4f829192..9b473d50b005 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.c | |||
@@ -19,9 +19,9 @@ | |||
19 | 19 | ||
20 | #include <brcmu_wifi.h> | 20 | #include <brcmu_wifi.h> |
21 | #include <brcmu_utils.h> | 21 | #include <brcmu_utils.h> |
22 | #include "dhd.h" | 22 | #include "core.h" |
23 | #include "dhd_bus.h" | 23 | #include "bus.h" |
24 | #include "dhd_dbg.h" | 24 | #include "debug.h" |
25 | 25 | ||
26 | static struct dentry *root_folder; | 26 | static struct dentry *root_folder; |
27 | 27 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h b/drivers/net/wireless/brcm80211/brcmfmac/debug.h index dec40d316c82..eb0b8c47479d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_dbg.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/debug.h | |||
@@ -14,8 +14,8 @@ | |||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef _BRCMF_DBG_H_ | 17 | #ifndef BRCMFMAC_DEBUG_H |
18 | #define _BRCMF_DBG_H_ | 18 | #define BRCMFMAC_DEBUG_H |
19 | 19 | ||
20 | /* message levels */ | 20 | /* message levels */ |
21 | #define BRCMF_TRACE_VAL 0x00000002 | 21 | #define BRCMF_TRACE_VAL 0x00000002 |
@@ -133,4 +133,4 @@ int brcmf_debugfs_add_entry(struct brcmf_pub *drvr, const char *fn, | |||
133 | } | 133 | } |
134 | #endif | 134 | #endif |
135 | 135 | ||
136 | #endif /* _BRCMF_DBG_H_ */ | 136 | #endif /* BRCMFMAC_DEBUG_H */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c deleted file mode 100644 index d991f8e3d9ec..000000000000 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c +++ /dev/null | |||
@@ -1,400 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2010 Broadcom Corporation | ||
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 ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #include <linux/kernel.h> | ||
18 | #include <linux/string.h> | ||
19 | #include <linux/netdevice.h> | ||
20 | #include <brcmu_wifi.h> | ||
21 | #include <brcmu_utils.h> | ||
22 | #include "dhd.h" | ||
23 | #include "dhd_bus.h" | ||
24 | #include "dhd_dbg.h" | ||
25 | #include "fwil.h" | ||
26 | #include "fwil_types.h" | ||
27 | #include "tracepoint.h" | ||
28 | |||
29 | #define PKTFILTER_BUF_SIZE 128 | ||
30 | #define BRCMF_DEFAULT_BCN_TIMEOUT 3 | ||
31 | #define BRCMF_DEFAULT_SCAN_CHANNEL_TIME 40 | ||
32 | #define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40 | ||
33 | #define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00" | ||
34 | |||
35 | /* boost value for RSSI_DELTA in preferred join selection */ | ||
36 | #define BRCMF_JOIN_PREF_RSSI_BOOST 8 | ||
37 | |||
38 | |||
39 | bool brcmf_c_prec_enq(struct device *dev, struct pktq *q, | ||
40 | struct sk_buff *pkt, int prec) | ||
41 | { | ||
42 | struct sk_buff *p; | ||
43 | int eprec = -1; /* precedence to evict from */ | ||
44 | bool discard_oldest; | ||
45 | struct brcmf_bus *bus_if = dev_get_drvdata(dev); | ||
46 | struct brcmf_pub *drvr = bus_if->drvr; | ||
47 | |||
48 | /* Fast case, precedence queue is not full and we are also not | ||
49 | * exceeding total queue length | ||
50 | */ | ||
51 | if (!pktq_pfull(q, prec) && !pktq_full(q)) { | ||
52 | brcmu_pktq_penq(q, prec, pkt); | ||
53 | return true; | ||
54 | } | ||
55 | |||
56 | /* Determine precedence from which to evict packet, if any */ | ||
57 | if (pktq_pfull(q, prec)) | ||
58 | eprec = prec; | ||
59 | else if (pktq_full(q)) { | ||
60 | p = brcmu_pktq_peek_tail(q, &eprec); | ||
61 | if (eprec > prec) | ||
62 | return false; | ||
63 | } | ||
64 | |||
65 | /* Evict if needed */ | ||
66 | if (eprec >= 0) { | ||
67 | /* Detect queueing to unconfigured precedence */ | ||
68 | discard_oldest = ac_bitmap_tst(drvr->wme_dp, eprec); | ||
69 | if (eprec == prec && !discard_oldest) | ||
70 | return false; /* refuse newer (incoming) packet */ | ||
71 | /* Evict packet according to discard policy */ | ||
72 | p = discard_oldest ? brcmu_pktq_pdeq(q, eprec) : | ||
73 | brcmu_pktq_pdeq_tail(q, eprec); | ||
74 | if (p == NULL) | ||
75 | brcmf_err("brcmu_pktq_penq() failed, oldest %d\n", | ||
76 | discard_oldest); | ||
77 | |||
78 | brcmu_pkt_buf_free_skb(p); | ||
79 | } | ||
80 | |||
81 | /* Enqueue */ | ||
82 | p = brcmu_pktq_penq(q, prec, pkt); | ||
83 | if (p == NULL) | ||
84 | brcmf_err("brcmu_pktq_penq() failed\n"); | ||
85 | |||
86 | return p != NULL; | ||
87 | } | ||
88 | |||
89 | /* Convert user's input in hex pattern to byte-size mask */ | ||
90 | static int brcmf_c_pattern_atoh(char *src, char *dst) | ||
91 | { | ||
92 | int i; | ||
93 | if (strncmp(src, "0x", 2) != 0 && strncmp(src, "0X", 2) != 0) { | ||
94 | brcmf_err("Mask invalid format. Needs to start with 0x\n"); | ||
95 | return -EINVAL; | ||
96 | } | ||
97 | src = src + 2; /* Skip past 0x */ | ||
98 | if (strlen(src) % 2 != 0) { | ||
99 | brcmf_err("Mask invalid format. Length must be even.\n"); | ||
100 | return -EINVAL; | ||
101 | } | ||
102 | for (i = 0; *src != '\0'; i++) { | ||
103 | unsigned long res; | ||
104 | char num[3]; | ||
105 | strncpy(num, src, 2); | ||
106 | num[2] = '\0'; | ||
107 | if (kstrtoul(num, 16, &res)) | ||
108 | return -EINVAL; | ||
109 | dst[i] = (u8)res; | ||
110 | src += 2; | ||
111 | } | ||
112 | return i; | ||
113 | } | ||
114 | |||
115 | static void | ||
116 | brcmf_c_pktfilter_offload_enable(struct brcmf_if *ifp, char *arg, int enable, | ||
117 | int master_mode) | ||
118 | { | ||
119 | unsigned long res; | ||
120 | char *argv; | ||
121 | char *arg_save = NULL, *arg_org = NULL; | ||
122 | s32 err; | ||
123 | struct brcmf_pkt_filter_enable_le enable_parm; | ||
124 | |||
125 | arg_save = kstrdup(arg, GFP_ATOMIC); | ||
126 | if (!arg_save) | ||
127 | goto fail; | ||
128 | |||
129 | arg_org = arg_save; | ||
130 | |||
131 | argv = strsep(&arg_save, " "); | ||
132 | |||
133 | if (argv == NULL) { | ||
134 | brcmf_err("No args provided\n"); | ||
135 | goto fail; | ||
136 | } | ||
137 | |||
138 | /* Parse packet filter id. */ | ||
139 | enable_parm.id = 0; | ||
140 | if (!kstrtoul(argv, 0, &res)) | ||
141 | enable_parm.id = cpu_to_le32((u32)res); | ||
142 | |||
143 | /* Enable/disable the specified filter. */ | ||
144 | enable_parm.enable = cpu_to_le32(enable); | ||
145 | |||
146 | err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_enable", &enable_parm, | ||
147 | sizeof(enable_parm)); | ||
148 | if (err) | ||
149 | brcmf_err("Set pkt_filter_enable error (%d)\n", err); | ||
150 | |||
151 | /* Control the master mode */ | ||
152 | err = brcmf_fil_iovar_int_set(ifp, "pkt_filter_mode", master_mode); | ||
153 | if (err) | ||
154 | brcmf_err("Set pkt_filter_mode error (%d)\n", err); | ||
155 | |||
156 | fail: | ||
157 | kfree(arg_org); | ||
158 | } | ||
159 | |||
160 | static void brcmf_c_pktfilter_offload_set(struct brcmf_if *ifp, char *arg) | ||
161 | { | ||
162 | struct brcmf_pkt_filter_le *pkt_filter; | ||
163 | unsigned long res; | ||
164 | int buf_len; | ||
165 | s32 err; | ||
166 | u32 mask_size; | ||
167 | u32 pattern_size; | ||
168 | char *argv[8], *buf = NULL; | ||
169 | int i = 0; | ||
170 | char *arg_save = NULL, *arg_org = NULL; | ||
171 | |||
172 | arg_save = kstrdup(arg, GFP_ATOMIC); | ||
173 | if (!arg_save) | ||
174 | goto fail; | ||
175 | |||
176 | arg_org = arg_save; | ||
177 | |||
178 | buf = kmalloc(PKTFILTER_BUF_SIZE, GFP_ATOMIC); | ||
179 | if (!buf) | ||
180 | goto fail; | ||
181 | |||
182 | argv[i] = strsep(&arg_save, " "); | ||
183 | while (argv[i]) { | ||
184 | i++; | ||
185 | if (i >= 8) { | ||
186 | brcmf_err("Too many parameters\n"); | ||
187 | goto fail; | ||
188 | } | ||
189 | argv[i] = strsep(&arg_save, " "); | ||
190 | } | ||
191 | |||
192 | if (i != 6) { | ||
193 | brcmf_err("Not enough args provided %d\n", i); | ||
194 | goto fail; | ||
195 | } | ||
196 | |||
197 | pkt_filter = (struct brcmf_pkt_filter_le *)buf; | ||
198 | |||
199 | /* Parse packet filter id. */ | ||
200 | pkt_filter->id = 0; | ||
201 | if (!kstrtoul(argv[0], 0, &res)) | ||
202 | pkt_filter->id = cpu_to_le32((u32)res); | ||
203 | |||
204 | /* Parse filter polarity. */ | ||
205 | pkt_filter->negate_match = 0; | ||
206 | if (!kstrtoul(argv[1], 0, &res)) | ||
207 | pkt_filter->negate_match = cpu_to_le32((u32)res); | ||
208 | |||
209 | /* Parse filter type. */ | ||
210 | pkt_filter->type = 0; | ||
211 | if (!kstrtoul(argv[2], 0, &res)) | ||
212 | pkt_filter->type = cpu_to_le32((u32)res); | ||
213 | |||
214 | /* Parse pattern filter offset. */ | ||
215 | pkt_filter->u.pattern.offset = 0; | ||
216 | if (!kstrtoul(argv[3], 0, &res)) | ||
217 | pkt_filter->u.pattern.offset = cpu_to_le32((u32)res); | ||
218 | |||
219 | /* Parse pattern filter mask. */ | ||
220 | mask_size = brcmf_c_pattern_atoh(argv[4], | ||
221 | (char *)pkt_filter->u.pattern.mask_and_pattern); | ||
222 | |||
223 | /* Parse pattern filter pattern. */ | ||
224 | pattern_size = brcmf_c_pattern_atoh(argv[5], | ||
225 | (char *)&pkt_filter->u.pattern.mask_and_pattern[mask_size]); | ||
226 | |||
227 | if (mask_size != pattern_size) { | ||
228 | brcmf_err("Mask and pattern not the same size\n"); | ||
229 | goto fail; | ||
230 | } | ||
231 | |||
232 | pkt_filter->u.pattern.size_bytes = cpu_to_le32(mask_size); | ||
233 | buf_len = offsetof(struct brcmf_pkt_filter_le, | ||
234 | u.pattern.mask_and_pattern); | ||
235 | buf_len += mask_size + pattern_size; | ||
236 | |||
237 | err = brcmf_fil_iovar_data_set(ifp, "pkt_filter_add", pkt_filter, | ||
238 | buf_len); | ||
239 | if (err) | ||
240 | brcmf_err("Set pkt_filter_add error (%d)\n", err); | ||
241 | |||
242 | fail: | ||
243 | kfree(arg_org); | ||
244 | |||
245 | kfree(buf); | ||
246 | } | ||
247 | |||
248 | int brcmf_c_preinit_dcmds(struct brcmf_if *ifp) | ||
249 | { | ||
250 | s8 eventmask[BRCMF_EVENTING_MASK_LEN]; | ||
251 | u8 buf[BRCMF_DCMD_SMLEN]; | ||
252 | struct brcmf_join_pref_params join_pref_params[2]; | ||
253 | char *ptr; | ||
254 | s32 err; | ||
255 | |||
256 | /* retreive mac address */ | ||
257 | err = brcmf_fil_iovar_data_get(ifp, "cur_etheraddr", ifp->mac_addr, | ||
258 | sizeof(ifp->mac_addr)); | ||
259 | if (err < 0) { | ||
260 | brcmf_err("Retreiving cur_etheraddr failed, %d\n", | ||
261 | err); | ||
262 | goto done; | ||
263 | } | ||
264 | memcpy(ifp->drvr->mac, ifp->mac_addr, sizeof(ifp->drvr->mac)); | ||
265 | |||
266 | /* query for 'ver' to get version info from firmware */ | ||
267 | memset(buf, 0, sizeof(buf)); | ||
268 | strcpy(buf, "ver"); | ||
269 | err = brcmf_fil_iovar_data_get(ifp, "ver", buf, sizeof(buf)); | ||
270 | if (err < 0) { | ||
271 | brcmf_err("Retreiving version information failed, %d\n", | ||
272 | err); | ||
273 | goto done; | ||
274 | } | ||
275 | ptr = (char *)buf; | ||
276 | strsep(&ptr, "\n"); | ||
277 | |||
278 | /* Print fw version info */ | ||
279 | brcmf_err("Firmware version = %s\n", buf); | ||
280 | |||
281 | /* locate firmware version number for ethtool */ | ||
282 | ptr = strrchr(buf, ' ') + 1; | ||
283 | strlcpy(ifp->drvr->fwver, ptr, sizeof(ifp->drvr->fwver)); | ||
284 | |||
285 | /* set mpc */ | ||
286 | err = brcmf_fil_iovar_int_set(ifp, "mpc", 1); | ||
287 | if (err) { | ||
288 | brcmf_err("failed setting mpc\n"); | ||
289 | goto done; | ||
290 | } | ||
291 | |||
292 | /* | ||
293 | * Setup timeout if Beacons are lost and roam is off to report | ||
294 | * link down | ||
295 | */ | ||
296 | err = brcmf_fil_iovar_int_set(ifp, "bcn_timeout", | ||
297 | BRCMF_DEFAULT_BCN_TIMEOUT); | ||
298 | if (err) { | ||
299 | brcmf_err("bcn_timeout error (%d)\n", err); | ||
300 | goto done; | ||
301 | } | ||
302 | |||
303 | /* Enable/Disable build-in roaming to allowed ext supplicant to take | ||
304 | * of romaing | ||
305 | */ | ||
306 | err = brcmf_fil_iovar_int_set(ifp, "roam_off", 1); | ||
307 | if (err) { | ||
308 | brcmf_err("roam_off error (%d)\n", err); | ||
309 | goto done; | ||
310 | } | ||
311 | |||
312 | /* Setup join_pref to select target by RSSI(with boost on 5GHz) */ | ||
313 | join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA; | ||
314 | join_pref_params[0].len = 2; | ||
315 | join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST; | ||
316 | join_pref_params[0].band = WLC_BAND_5G; | ||
317 | join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI; | ||
318 | join_pref_params[1].len = 2; | ||
319 | join_pref_params[1].rssi_gain = 0; | ||
320 | join_pref_params[1].band = 0; | ||
321 | err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params, | ||
322 | sizeof(join_pref_params)); | ||
323 | if (err) | ||
324 | brcmf_err("Set join_pref error (%d)\n", err); | ||
325 | |||
326 | /* Setup event_msgs, enable E_IF */ | ||
327 | err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask, | ||
328 | BRCMF_EVENTING_MASK_LEN); | ||
329 | if (err) { | ||
330 | brcmf_err("Get event_msgs error (%d)\n", err); | ||
331 | goto done; | ||
332 | } | ||
333 | setbit(eventmask, BRCMF_E_IF); | ||
334 | err = brcmf_fil_iovar_data_set(ifp, "event_msgs", eventmask, | ||
335 | BRCMF_EVENTING_MASK_LEN); | ||
336 | if (err) { | ||
337 | brcmf_err("Set event_msgs error (%d)\n", err); | ||
338 | goto done; | ||
339 | } | ||
340 | |||
341 | /* Setup default scan channel time */ | ||
342 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_CHANNEL_TIME, | ||
343 | BRCMF_DEFAULT_SCAN_CHANNEL_TIME); | ||
344 | if (err) { | ||
345 | brcmf_err("BRCMF_C_SET_SCAN_CHANNEL_TIME error (%d)\n", | ||
346 | err); | ||
347 | goto done; | ||
348 | } | ||
349 | |||
350 | /* Setup default scan unassoc time */ | ||
351 | err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_SCAN_UNASSOC_TIME, | ||
352 | BRCMF_DEFAULT_SCAN_UNASSOC_TIME); | ||
353 | if (err) { | ||
354 | brcmf_err("BRCMF_C_SET_SCAN_UNASSOC_TIME error (%d)\n", | ||
355 | err); | ||
356 | goto done; | ||
357 | } | ||
358 | |||
359 | /* Setup packet filter */ | ||
360 | brcmf_c_pktfilter_offload_set(ifp, BRCMF_DEFAULT_PACKET_FILTER); | ||
361 | brcmf_c_pktfilter_offload_enable(ifp, BRCMF_DEFAULT_PACKET_FILTER, | ||
362 | 0, true); | ||
363 | |||
364 | /* do bus specific preinit here */ | ||
365 | err = brcmf_bus_preinit(ifp->drvr->bus_if); | ||
366 | done: | ||
367 | return err; | ||
368 | } | ||
369 | |||
370 | #ifdef CONFIG_BRCM_TRACING | ||
371 | void __brcmf_err(const char *func, const char *fmt, ...) | ||
372 | { | ||
373 | struct va_format vaf = { | ||
374 | .fmt = fmt, | ||
375 | }; | ||
376 | va_list args; | ||
377 | |||
378 | va_start(args, fmt); | ||
379 | vaf.va = &args; | ||
380 | pr_err("%s: %pV", func, &vaf); | ||
381 | trace_brcmf_err(func, &vaf); | ||
382 | va_end(args); | ||
383 | } | ||
384 | #endif | ||
385 | #if defined(CONFIG_BRCM_TRACING) || defined(CONFIG_BRCMDBG) | ||
386 | void __brcmf_dbg(u32 level, const char *func, const char *fmt, ...) | ||
387 | { | ||
388 | struct va_format vaf = { | ||
389 | .fmt = fmt, | ||
390 | }; | ||
391 | va_list args; | ||
392 | |||
393 | va_start(args, fmt); | ||
394 | vaf.va = &args; | ||
395 | if (brcmf_msg_level & level) | ||
396 | pr_debug("%s %pV", func, &vaf); | ||
397 | trace_brcmf_dbg(level, func, &vaf); | ||
398 | va_end(args); | ||
399 | } | ||
400 | #endif | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/feature.c b/drivers/net/wireless/brcm80211/brcmfmac/feature.c index aed53acef456..931f68aefaa4 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/feature.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/feature.c | |||
@@ -17,18 +17,13 @@ | |||
17 | #include <linux/netdevice.h> | 17 | #include <linux/netdevice.h> |
18 | 18 | ||
19 | #include <brcm_hw_ids.h> | 19 | #include <brcm_hw_ids.h> |
20 | #include "dhd.h" | 20 | #include "core.h" |
21 | #include "dhd_bus.h" | 21 | #include "bus.h" |
22 | #include "dhd_dbg.h" | 22 | #include "debug.h" |
23 | #include "fwil.h" | 23 | #include "fwil.h" |
24 | #include "feature.h" | 24 | #include "feature.h" |
25 | 25 | ||
26 | /* | 26 | /* |
27 | * firmware error code received if iovar is unsupported. | ||
28 | */ | ||
29 | #define EBRCMF_FEAT_UNSUPPORTED 23 | ||
30 | |||
31 | /* | ||
32 | * expand feature list to array of feature strings. | 27 | * expand feature list to array of feature strings. |
33 | */ | 28 | */ |
34 | #define BRCMF_FEAT_DEF(_f) \ | 29 | #define BRCMF_FEAT_DEF(_f) \ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c index 8ea9f283d2b8..1ff787d1a36b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c | |||
@@ -20,7 +20,7 @@ | |||
20 | #include <linux/firmware.h> | 20 | #include <linux/firmware.h> |
21 | #include <linux/module.h> | 21 | #include <linux/module.h> |
22 | 22 | ||
23 | #include "dhd_dbg.h" | 23 | #include "debug.h" |
24 | #include "firmware.h" | 24 | #include "firmware.h" |
25 | 25 | ||
26 | char brcmf_firmware_path[BRCMF_FW_PATH_LEN]; | 26 | char brcmf_firmware_path[BRCMF_FW_PATH_LEN]; |
@@ -262,8 +262,7 @@ static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx) | |||
262 | 262 | ||
263 | fail: | 263 | fail: |
264 | brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); | 264 | brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev)); |
265 | if (fwctx->code) | 265 | release_firmware(fwctx->code); |
266 | release_firmware(fwctx->code); | ||
267 | device_release_driver(fwctx->dev); | 266 | device_release_driver(fwctx->dev); |
268 | kfree(fwctx); | 267 | kfree(fwctx); |
269 | } | 268 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c index 1faa929f5fff..44f3a84d1999 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/flowring.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/flowring.c | |||
@@ -19,9 +19,9 @@ | |||
19 | #include <linux/etherdevice.h> | 19 | #include <linux/etherdevice.h> |
20 | #include <brcmu_utils.h> | 20 | #include <brcmu_utils.h> |
21 | 21 | ||
22 | #include "dhd.h" | 22 | #include "core.h" |
23 | #include "dhd_dbg.h" | 23 | #include "debug.h" |
24 | #include "dhd_bus.h" | 24 | #include "bus.h" |
25 | #include "proto.h" | 25 | #include "proto.h" |
26 | #include "flowring.h" | 26 | #include "flowring.h" |
27 | #include "msgbuf.h" | 27 | #include "msgbuf.h" |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index 44fc85f68f7a..7338b335e153 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c | |||
@@ -18,8 +18,8 @@ | |||
18 | #include "brcmu_wifi.h" | 18 | #include "brcmu_wifi.h" |
19 | #include "brcmu_utils.h" | 19 | #include "brcmu_utils.h" |
20 | 20 | ||
21 | #include "dhd.h" | 21 | #include "core.h" |
22 | #include "dhd_dbg.h" | 22 | #include "debug.h" |
23 | #include "tracepoint.h" | 23 | #include "tracepoint.h" |
24 | #include "fwsignal.h" | 24 | #include "fwsignal.h" |
25 | #include "fweh.h" | 25 | #include "fweh.h" |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c index ded328f80cd1..51f88c11e642 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil.c | |||
@@ -22,9 +22,9 @@ | |||
22 | #include <linux/netdevice.h> | 22 | #include <linux/netdevice.h> |
23 | #include <brcmu_utils.h> | 23 | #include <brcmu_utils.h> |
24 | #include <brcmu_wifi.h> | 24 | #include <brcmu_wifi.h> |
25 | #include "dhd.h" | 25 | #include "core.h" |
26 | #include "dhd_bus.h" | 26 | #include "bus.h" |
27 | #include "dhd_dbg.h" | 27 | #include "debug.h" |
28 | #include "tracepoint.h" | 28 | #include "tracepoint.h" |
29 | #include "fwil.h" | 29 | #include "fwil.h" |
30 | #include "proto.h" | 30 | #include "proto.h" |
@@ -32,6 +32,76 @@ | |||
32 | 32 | ||
33 | #define MAX_HEX_DUMP_LEN 64 | 33 | #define MAX_HEX_DUMP_LEN 64 |
34 | 34 | ||
35 | #ifdef DEBUG | ||
36 | static const char * const brcmf_fil_errstr[] = { | ||
37 | "BCME_OK", | ||
38 | "BCME_ERROR", | ||
39 | "BCME_BADARG", | ||
40 | "BCME_BADOPTION", | ||
41 | "BCME_NOTUP", | ||
42 | "BCME_NOTDOWN", | ||
43 | "BCME_NOTAP", | ||
44 | "BCME_NOTSTA", | ||
45 | "BCME_BADKEYIDX", | ||
46 | "BCME_RADIOOFF", | ||
47 | "BCME_NOTBANDLOCKED", | ||
48 | "BCME_NOCLK", | ||
49 | "BCME_BADRATESET", | ||
50 | "BCME_BADBAND", | ||
51 | "BCME_BUFTOOSHORT", | ||
52 | "BCME_BUFTOOLONG", | ||
53 | "BCME_BUSY", | ||
54 | "BCME_NOTASSOCIATED", | ||
55 | "BCME_BADSSIDLEN", | ||
56 | "BCME_OUTOFRANGECHAN", | ||
57 | "BCME_BADCHAN", | ||
58 | "BCME_BADADDR", | ||
59 | "BCME_NORESOURCE", | ||
60 | "BCME_UNSUPPORTED", | ||
61 | "BCME_BADLEN", | ||
62 | "BCME_NOTREADY", | ||
63 | "BCME_EPERM", | ||
64 | "BCME_NOMEM", | ||
65 | "BCME_ASSOCIATED", | ||
66 | "BCME_RANGE", | ||
67 | "BCME_NOTFOUND", | ||
68 | "BCME_WME_NOT_ENABLED", | ||
69 | "BCME_TSPEC_NOTFOUND", | ||
70 | "BCME_ACM_NOTSUPPORTED", | ||
71 | "BCME_NOT_WME_ASSOCIATION", | ||
72 | "BCME_SDIO_ERROR", | ||
73 | "BCME_DONGLE_DOWN", | ||
74 | "BCME_VERSION", | ||
75 | "BCME_TXFAIL", | ||
76 | "BCME_RXFAIL", | ||
77 | "BCME_NODEVICE", | ||
78 | "BCME_NMODE_DISABLED", | ||
79 | "BCME_NONRESIDENT", | ||
80 | "BCME_SCANREJECT", | ||
81 | "BCME_USAGE_ERROR", | ||
82 | "BCME_IOCTL_ERROR", | ||
83 | "BCME_SERIAL_PORT_ERR", | ||
84 | "BCME_DISABLED", | ||
85 | "BCME_DECERR", | ||
86 | "BCME_ENCERR", | ||
87 | "BCME_MICERR", | ||
88 | "BCME_REPLAY", | ||
89 | "BCME_IE_NOTFOUND", | ||
90 | }; | ||
91 | |||
92 | static const char *brcmf_fil_get_errstr(u32 err) | ||
93 | { | ||
94 | if (err >= ARRAY_SIZE(brcmf_fil_errstr)) | ||
95 | return "(unknown)"; | ||
96 | |||
97 | return brcmf_fil_errstr[err]; | ||
98 | } | ||
99 | #else | ||
100 | static const char *brcmf_fil_get_errstr(u32 err) | ||
101 | { | ||
102 | return ""; | ||
103 | } | ||
104 | #endif /* DEBUG */ | ||
35 | 105 | ||
36 | static s32 | 106 | static s32 |
37 | brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) | 107 | brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) |
@@ -52,11 +122,11 @@ brcmf_fil_cmd_data(struct brcmf_if *ifp, u32 cmd, void *data, u32 len, bool set) | |||
52 | err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len); | 122 | err = brcmf_proto_query_dcmd(drvr, ifp->ifidx, cmd, data, len); |
53 | 123 | ||
54 | if (err >= 0) | 124 | if (err >= 0) |
55 | err = 0; | 125 | return 0; |
56 | else | ||
57 | brcmf_dbg(FIL, "Failed err=%d\n", err); | ||
58 | 126 | ||
59 | return err; | 127 | brcmf_dbg(FIL, "Failed: %s (%d)\n", |
128 | brcmf_fil_get_errstr((u32)(-err)), err); | ||
129 | return -EBADE; | ||
60 | } | 130 | } |
61 | 131 | ||
62 | s32 | 132 | s32 |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h index 5ff5cd0bb032..ba64b292f7a5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h | |||
@@ -55,59 +55,63 @@ | |||
55 | 55 | ||
56 | /* WOWL bits */ | 56 | /* WOWL bits */ |
57 | /* Wakeup on Magic packet: */ | 57 | /* Wakeup on Magic packet: */ |
58 | #define WL_WOWL_MAGIC (1 << 0) | 58 | #define BRCMF_WOWL_MAGIC (1 << 0) |
59 | /* Wakeup on Netpattern */ | 59 | /* Wakeup on Netpattern */ |
60 | #define WL_WOWL_NET (1 << 1) | 60 | #define BRCMF_WOWL_NET (1 << 1) |
61 | /* Wakeup on loss-of-link due to Disassoc/Deauth: */ | 61 | /* Wakeup on loss-of-link due to Disassoc/Deauth: */ |
62 | #define WL_WOWL_DIS (1 << 2) | 62 | #define BRCMF_WOWL_DIS (1 << 2) |
63 | /* Wakeup on retrograde TSF: */ | 63 | /* Wakeup on retrograde TSF: */ |
64 | #define WL_WOWL_RETR (1 << 3) | 64 | #define BRCMF_WOWL_RETR (1 << 3) |
65 | /* Wakeup on loss of beacon: */ | 65 | /* Wakeup on loss of beacon: */ |
66 | #define WL_WOWL_BCN (1 << 4) | 66 | #define BRCMF_WOWL_BCN (1 << 4) |
67 | /* Wakeup after test: */ | 67 | /* Wakeup after test: */ |
68 | #define WL_WOWL_TST (1 << 5) | 68 | #define BRCMF_WOWL_TST (1 << 5) |
69 | /* Wakeup after PTK refresh: */ | 69 | /* Wakeup after PTK refresh: */ |
70 | #define WL_WOWL_M1 (1 << 6) | 70 | #define BRCMF_WOWL_M1 (1 << 6) |
71 | /* Wakeup after receipt of EAP-Identity Req: */ | 71 | /* Wakeup after receipt of EAP-Identity Req: */ |
72 | #define WL_WOWL_EAPID (1 << 7) | 72 | #define BRCMF_WOWL_EAPID (1 << 7) |
73 | /* Wakeind via PME(0) or GPIO(1): */ | 73 | /* Wakeind via PME(0) or GPIO(1): */ |
74 | #define WL_WOWL_PME_GPIO (1 << 8) | 74 | #define BRCMF_WOWL_PME_GPIO (1 << 8) |
75 | /* need tkip phase 1 key to be updated by the driver: */ | 75 | /* need tkip phase 1 key to be updated by the driver: */ |
76 | #define WL_WOWL_NEEDTKIP1 (1 << 9) | 76 | #define BRCMF_WOWL_NEEDTKIP1 (1 << 9) |
77 | /* enable wakeup if GTK fails: */ | 77 | /* enable wakeup if GTK fails: */ |
78 | #define WL_WOWL_GTK_FAILURE (1 << 10) | 78 | #define BRCMF_WOWL_GTK_FAILURE (1 << 10) |
79 | /* support extended magic packets: */ | 79 | /* support extended magic packets: */ |
80 | #define WL_WOWL_EXTMAGPAT (1 << 11) | 80 | #define BRCMF_WOWL_EXTMAGPAT (1 << 11) |
81 | /* support ARP/NS/keepalive offloading: */ | 81 | /* support ARP/NS/keepalive offloading: */ |
82 | #define WL_WOWL_ARPOFFLOAD (1 << 12) | 82 | #define BRCMF_WOWL_ARPOFFLOAD (1 << 12) |
83 | /* read protocol version for EAPOL frames: */ | 83 | /* read protocol version for EAPOL frames: */ |
84 | #define WL_WOWL_WPA2 (1 << 13) | 84 | #define BRCMF_WOWL_WPA2 (1 << 13) |
85 | /* If the bit is set, use key rotaton: */ | 85 | /* If the bit is set, use key rotaton: */ |
86 | #define WL_WOWL_KEYROT (1 << 14) | 86 | #define BRCMF_WOWL_KEYROT (1 << 14) |
87 | /* If the bit is set, frm received was bcast frame: */ | 87 | /* If the bit is set, frm received was bcast frame: */ |
88 | #define WL_WOWL_BCAST (1 << 15) | 88 | #define BRCMF_WOWL_BCAST (1 << 15) |
89 | /* If the bit is set, scan offload is enabled: */ | 89 | /* If the bit is set, scan offload is enabled: */ |
90 | #define WL_WOWL_SCANOL (1 << 16) | 90 | #define BRCMF_WOWL_SCANOL (1 << 16) |
91 | /* Wakeup on tcpkeep alive timeout: */ | 91 | /* Wakeup on tcpkeep alive timeout: */ |
92 | #define WL_WOWL_TCPKEEP_TIME (1 << 17) | 92 | #define BRCMF_WOWL_TCPKEEP_TIME (1 << 17) |
93 | /* Wakeup on mDNS Conflict Resolution: */ | 93 | /* Wakeup on mDNS Conflict Resolution: */ |
94 | #define WL_WOWL_MDNS_CONFLICT (1 << 18) | 94 | #define BRCMF_WOWL_MDNS_CONFLICT (1 << 18) |
95 | /* Wakeup on mDNS Service Connect: */ | 95 | /* Wakeup on mDNS Service Connect: */ |
96 | #define WL_WOWL_MDNS_SERVICE (1 << 19) | 96 | #define BRCMF_WOWL_MDNS_SERVICE (1 << 19) |
97 | /* tcp keepalive got data: */ | 97 | /* tcp keepalive got data: */ |
98 | #define WL_WOWL_TCPKEEP_DATA (1 << 20) | 98 | #define BRCMF_WOWL_TCPKEEP_DATA (1 << 20) |
99 | /* Firmware died in wowl mode: */ | 99 | /* Firmware died in wowl mode: */ |
100 | #define WL_WOWL_FW_HALT (1 << 21) | 100 | #define BRCMF_WOWL_FW_HALT (1 << 21) |
101 | /* Enable detection of radio button changes: */ | 101 | /* Enable detection of radio button changes: */ |
102 | #define WL_WOWL_ENAB_HWRADIO (1 << 22) | 102 | #define BRCMF_WOWL_ENAB_HWRADIO (1 << 22) |
103 | /* Offloads detected MIC failure(s): */ | 103 | /* Offloads detected MIC failure(s): */ |
104 | #define WL_WOWL_MIC_FAIL (1 << 23) | 104 | #define BRCMF_WOWL_MIC_FAIL (1 << 23) |
105 | /* Wakeup in Unassociated state (Net/Magic Pattern): */ | 105 | /* Wakeup in Unassociated state (Net/Magic Pattern): */ |
106 | #define WL_WOWL_UNASSOC (1 << 24) | 106 | #define BRCMF_WOWL_UNASSOC (1 << 24) |
107 | /* Wakeup if received matched secured pattern: */ | 107 | /* Wakeup if received matched secured pattern: */ |
108 | #define WL_WOWL_SECURE (1 << 25) | 108 | #define BRCMF_WOWL_SECURE (1 << 25) |
109 | /* Link Down indication in WoWL mode: */ | 109 | /* Link Down indication in WoWL mode: */ |
110 | #define WL_WOWL_LINKDOWN (1 << 31) | 110 | #define BRCMF_WOWL_LINKDOWN (1 << 31) |
111 | |||
112 | #define BRCMF_WOWL_MAXPATTERNS 8 | ||
113 | #define BRCMF_WOWL_MAXPATTERNSIZE 128 | ||
114 | |||
111 | 115 | ||
112 | /* join preference types for join_pref iovar */ | 116 | /* join preference types for join_pref iovar */ |
113 | enum brcmf_join_pref_types { | 117 | enum brcmf_join_pref_types { |
@@ -124,6 +128,12 @@ enum brcmf_fil_p2p_if_types { | |||
124 | BRCMF_FIL_P2P_IF_DEV, | 128 | BRCMF_FIL_P2P_IF_DEV, |
125 | }; | 129 | }; |
126 | 130 | ||
131 | enum brcmf_wowl_pattern_type { | ||
132 | BRCMF_WOWL_PATTERN_TYPE_BITMAP = 0, | ||
133 | BRCMF_WOWL_PATTERN_TYPE_ARP, | ||
134 | BRCMF_WOWL_PATTERN_TYPE_NA | ||
135 | }; | ||
136 | |||
127 | struct brcmf_fil_p2p_if_le { | 137 | struct brcmf_fil_p2p_if_le { |
128 | u8 addr[ETH_ALEN]; | 138 | u8 addr[ETH_ALEN]; |
129 | __le16 type; | 139 | __le16 type; |
@@ -484,4 +494,29 @@ struct brcmf_rx_mgmt_data { | |||
484 | __be32 rate; | 494 | __be32 rate; |
485 | }; | 495 | }; |
486 | 496 | ||
497 | /** | ||
498 | * struct brcmf_fil_wowl_pattern_le - wowl pattern configuration struct. | ||
499 | * | ||
500 | * @cmd: "add", "del" or "clr". | ||
501 | * @masksize: Size of the mask in #of bytes | ||
502 | * @offset: Pattern byte offset in packet | ||
503 | * @patternoffset: Offset of start of pattern. Starting from field masksize. | ||
504 | * @patternsize: Size of the pattern itself in #of bytes | ||
505 | * @id: id | ||
506 | * @reasonsize: Size of the wakeup reason code | ||
507 | * @type: Type of pattern (enum brcmf_wowl_pattern_type) | ||
508 | */ | ||
509 | struct brcmf_fil_wowl_pattern_le { | ||
510 | u8 cmd[4]; | ||
511 | __le32 masksize; | ||
512 | __le32 offset; | ||
513 | __le32 patternoffset; | ||
514 | __le32 patternsize; | ||
515 | __le32 id; | ||
516 | __le32 reasonsize; | ||
517 | __le32 type; | ||
518 | /* u8 mask[] - Mask follows the structure above */ | ||
519 | /* u8 pattern[] - Pattern follows the mask is at 'patternoffset' */ | ||
520 | }; | ||
521 | |||
487 | #endif /* FWIL_TYPES_H_ */ | 522 | #endif /* FWIL_TYPES_H_ */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c index 183f08d7fc8c..f0dda0ecd23b 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c | |||
@@ -26,15 +26,15 @@ | |||
26 | 26 | ||
27 | #include <brcmu_utils.h> | 27 | #include <brcmu_utils.h> |
28 | #include <brcmu_wifi.h> | 28 | #include <brcmu_wifi.h> |
29 | #include "dhd.h" | 29 | #include "core.h" |
30 | #include "dhd_dbg.h" | 30 | #include "debug.h" |
31 | #include "dhd_bus.h" | 31 | #include "bus.h" |
32 | #include "fwil.h" | 32 | #include "fwil.h" |
33 | #include "fwil_types.h" | 33 | #include "fwil_types.h" |
34 | #include "fweh.h" | 34 | #include "fweh.h" |
35 | #include "fwsignal.h" | 35 | #include "fwsignal.h" |
36 | #include "p2p.h" | 36 | #include "p2p.h" |
37 | #include "wl_cfg80211.h" | 37 | #include "cfg80211.h" |
38 | #include "proto.h" | 38 | #include "proto.h" |
39 | 39 | ||
40 | /** | 40 | /** |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c index 11cc051f97cd..9f783db34ae5 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.c | |||
@@ -24,13 +24,13 @@ | |||
24 | #include <brcmu_utils.h> | 24 | #include <brcmu_utils.h> |
25 | #include <brcmu_wifi.h> | 25 | #include <brcmu_wifi.h> |
26 | 26 | ||
27 | #include "dhd.h" | 27 | #include "core.h" |
28 | #include "dhd_dbg.h" | 28 | #include "debug.h" |
29 | #include "proto.h" | 29 | #include "proto.h" |
30 | #include "msgbuf.h" | 30 | #include "msgbuf.h" |
31 | #include "commonring.h" | 31 | #include "commonring.h" |
32 | #include "flowring.h" | 32 | #include "flowring.h" |
33 | #include "dhd_bus.h" | 33 | #include "bus.h" |
34 | #include "tracepoint.h" | 34 | #include "tracepoint.h" |
35 | 35 | ||
36 | 36 | ||
@@ -518,8 +518,7 @@ static int brcmf_msgbuf_query_dcmd(struct brcmf_pub *drvr, int ifidx, | |||
518 | memcpy(buf, skb->data, (len < msgbuf->ioctl_resp_ret_len) ? | 518 | memcpy(buf, skb->data, (len < msgbuf->ioctl_resp_ret_len) ? |
519 | len : msgbuf->ioctl_resp_ret_len); | 519 | len : msgbuf->ioctl_resp_ret_len); |
520 | } | 520 | } |
521 | if (skb) | 521 | brcmu_pkt_buf_free_skb(skb); |
522 | brcmu_pkt_buf_free_skb(skb); | ||
523 | 522 | ||
524 | return msgbuf->ioctl_resp_status; | 523 | return msgbuf->ioctl_resp_status; |
525 | } | 524 | } |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/of.c b/drivers/net/wireless/brcm80211/brcmfmac/of.c index f05f5270fec1..eb3fce82a223 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/of.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/of.c | |||
@@ -21,8 +21,8 @@ | |||
21 | #include <linux/mmc/sdio_func.h> | 21 | #include <linux/mmc/sdio_func.h> |
22 | 22 | ||
23 | #include <defs.h> | 23 | #include <defs.h> |
24 | #include "dhd_dbg.h" | 24 | #include "debug.h" |
25 | #include "sdio_host.h" | 25 | #include "sdio.h" |
26 | 26 | ||
27 | void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev) | 27 | void brcmf_of_probe(struct brcmf_sdio_dev *sdiodev) |
28 | { | 28 | { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c index d54c58a32faa..effb48ebd864 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/p2p.c | |||
@@ -21,12 +21,12 @@ | |||
21 | #include <brcmu_wifi.h> | 21 | #include <brcmu_wifi.h> |
22 | #include <brcmu_utils.h> | 22 | #include <brcmu_utils.h> |
23 | #include <defs.h> | 23 | #include <defs.h> |
24 | #include <dhd.h> | 24 | #include "core.h" |
25 | #include <dhd_dbg.h> | 25 | #include "debug.h" |
26 | #include "fwil.h" | 26 | #include "fwil.h" |
27 | #include "fwil_types.h" | 27 | #include "fwil_types.h" |
28 | #include "p2p.h" | 28 | #include "p2p.h" |
29 | #include "wl_cfg80211.h" | 29 | #include "cfg80211.h" |
30 | 30 | ||
31 | /* parameters used for p2p escan */ | 31 | /* parameters used for p2p escan */ |
32 | #define P2PAPI_SCAN_NPROBES 1 | 32 | #define P2PAPI_SCAN_NPROBES 1 |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c index 8c0632ec9f7a..b0ae7993e2e8 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/pcie.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/pcie.c | |||
@@ -30,8 +30,8 @@ | |||
30 | #include <brcmu_wifi.h> | 30 | #include <brcmu_wifi.h> |
31 | #include <brcm_hw_ids.h> | 31 | #include <brcm_hw_ids.h> |
32 | 32 | ||
33 | #include "dhd_dbg.h" | 33 | #include "debug.h" |
34 | #include "dhd_bus.h" | 34 | #include "bus.h" |
35 | #include "commonring.h" | 35 | #include "commonring.h" |
36 | #include "msgbuf.h" | 36 | #include "msgbuf.h" |
37 | #include "pcie.h" | 37 | #include "pcie.h" |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/proto.c b/drivers/net/wireless/brcm80211/brcmfmac/proto.c index 62b940723339..26b68c367f57 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/proto.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/proto.c | |||
@@ -20,9 +20,9 @@ | |||
20 | #include <linux/netdevice.h> | 20 | #include <linux/netdevice.h> |
21 | 21 | ||
22 | #include <brcmu_wifi.h> | 22 | #include <brcmu_wifi.h> |
23 | #include "dhd.h" | 23 | #include "core.h" |
24 | #include "dhd_bus.h" | 24 | #include "bus.h" |
25 | #include "dhd_dbg.h" | 25 | #include "debug.h" |
26 | #include "proto.h" | 26 | #include "proto.h" |
27 | #include "bcdc.h" | 27 | #include "bcdc.h" |
28 | #include "msgbuf.h" | 28 | #include "msgbuf.h" |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c index f55f625fd06b..0b0d51a61060 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.c | |||
@@ -40,7 +40,7 @@ | |||
40 | #include <brcmu_utils.h> | 40 | #include <brcmu_utils.h> |
41 | #include <brcm_hw_ids.h> | 41 | #include <brcm_hw_ids.h> |
42 | #include <soc.h> | 42 | #include <soc.h> |
43 | #include "sdio_host.h" | 43 | #include "sdio.h" |
44 | #include "chip.h" | 44 | #include "chip.h" |
45 | #include "firmware.h" | 45 | #include "firmware.h" |
46 | 46 | ||
@@ -96,8 +96,8 @@ struct rte_console { | |||
96 | #endif /* DEBUG */ | 96 | #endif /* DEBUG */ |
97 | #include <chipcommon.h> | 97 | #include <chipcommon.h> |
98 | 98 | ||
99 | #include "dhd_bus.h" | 99 | #include "bus.h" |
100 | #include "dhd_dbg.h" | 100 | #include "debug.h" |
101 | #include "tracepoint.h" | 101 | #include "tracepoint.h" |
102 | 102 | ||
103 | #define TXQLEN 2048 /* bulk tx queue length */ | 103 | #define TXQLEN 2048 /* bulk tx queue length */ |
@@ -670,7 +670,6 @@ static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci, | |||
670 | struct brcmf_sdio_dev *sdiodev) | 670 | struct brcmf_sdio_dev *sdiodev) |
671 | { | 671 | { |
672 | int i; | 672 | int i; |
673 | uint fw_len, nv_len; | ||
674 | char end; | 673 | char end; |
675 | 674 | ||
676 | for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) { | 675 | for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) { |
@@ -684,25 +683,25 @@ static int brcmf_sdio_get_fwnames(struct brcmf_chip *ci, | |||
684 | return -ENODEV; | 683 | return -ENODEV; |
685 | } | 684 | } |
686 | 685 | ||
687 | fw_len = sizeof(sdiodev->fw_name) - 1; | ||
688 | nv_len = sizeof(sdiodev->nvram_name) - 1; | ||
689 | /* check if firmware path is provided by module parameter */ | 686 | /* check if firmware path is provided by module parameter */ |
690 | if (brcmf_firmware_path[0] != '\0') { | 687 | if (brcmf_firmware_path[0] != '\0') { |
691 | strncpy(sdiodev->fw_name, brcmf_firmware_path, fw_len); | 688 | strlcpy(sdiodev->fw_name, brcmf_firmware_path, |
692 | strncpy(sdiodev->nvram_name, brcmf_firmware_path, nv_len); | 689 | sizeof(sdiodev->fw_name)); |
693 | fw_len -= strlen(sdiodev->fw_name); | 690 | strlcpy(sdiodev->nvram_name, brcmf_firmware_path, |
694 | nv_len -= strlen(sdiodev->nvram_name); | 691 | sizeof(sdiodev->nvram_name)); |
695 | 692 | ||
696 | end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1]; | 693 | end = brcmf_firmware_path[strlen(brcmf_firmware_path) - 1]; |
697 | if (end != '/') { | 694 | if (end != '/') { |
698 | strncat(sdiodev->fw_name, "/", fw_len); | 695 | strlcat(sdiodev->fw_name, "/", |
699 | strncat(sdiodev->nvram_name, "/", nv_len); | 696 | sizeof(sdiodev->fw_name)); |
700 | fw_len--; | 697 | strlcat(sdiodev->nvram_name, "/", |
701 | nv_len--; | 698 | sizeof(sdiodev->nvram_name)); |
702 | } | 699 | } |
703 | } | 700 | } |
704 | strncat(sdiodev->fw_name, brcmf_fwname_data[i].bin, fw_len); | 701 | strlcat(sdiodev->fw_name, brcmf_fwname_data[i].bin, |
705 | strncat(sdiodev->nvram_name, brcmf_fwname_data[i].nv, nv_len); | 702 | sizeof(sdiodev->fw_name)); |
703 | strlcat(sdiodev->nvram_name, brcmf_fwname_data[i].nv, | ||
704 | sizeof(sdiodev->nvram_name)); | ||
706 | 705 | ||
707 | return 0; | 706 | return 0; |
708 | } | 707 | } |
@@ -2763,6 +2762,48 @@ static struct pktq *brcmf_sdio_bus_gettxq(struct device *dev) | |||
2763 | return &bus->txq; | 2762 | return &bus->txq; |
2764 | } | 2763 | } |
2765 | 2764 | ||
2765 | static bool brcmf_sdio_prec_enq(struct pktq *q, struct sk_buff *pkt, int prec) | ||
2766 | { | ||
2767 | struct sk_buff *p; | ||
2768 | int eprec = -1; /* precedence to evict from */ | ||
2769 | |||
2770 | /* Fast case, precedence queue is not full and we are also not | ||
2771 | * exceeding total queue length | ||
2772 | */ | ||
2773 | if (!pktq_pfull(q, prec) && !pktq_full(q)) { | ||
2774 | brcmu_pktq_penq(q, prec, pkt); | ||
2775 | return true; | ||
2776 | } | ||
2777 | |||
2778 | /* Determine precedence from which to evict packet, if any */ | ||
2779 | if (pktq_pfull(q, prec)) { | ||
2780 | eprec = prec; | ||
2781 | } else if (pktq_full(q)) { | ||
2782 | p = brcmu_pktq_peek_tail(q, &eprec); | ||
2783 | if (eprec > prec) | ||
2784 | return false; | ||
2785 | } | ||
2786 | |||
2787 | /* Evict if needed */ | ||
2788 | if (eprec >= 0) { | ||
2789 | /* Detect queueing to unconfigured precedence */ | ||
2790 | if (eprec == prec) | ||
2791 | return false; /* refuse newer (incoming) packet */ | ||
2792 | /* Evict packet according to discard policy */ | ||
2793 | p = brcmu_pktq_pdeq_tail(q, eprec); | ||
2794 | if (p == NULL) | ||
2795 | brcmf_err("brcmu_pktq_pdeq_tail() failed\n"); | ||
2796 | brcmu_pkt_buf_free_skb(p); | ||
2797 | } | ||
2798 | |||
2799 | /* Enqueue */ | ||
2800 | p = brcmu_pktq_penq(q, prec, pkt); | ||
2801 | if (p == NULL) | ||
2802 | brcmf_err("brcmu_pktq_penq() failed\n"); | ||
2803 | |||
2804 | return p != NULL; | ||
2805 | } | ||
2806 | |||
2766 | static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) | 2807 | static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) |
2767 | { | 2808 | { |
2768 | int ret = -EBADE; | 2809 | int ret = -EBADE; |
@@ -2788,7 +2829,7 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2788 | spin_lock_bh(&bus->txq_lock); | 2829 | spin_lock_bh(&bus->txq_lock); |
2789 | /* reset bus_flags in packet cb */ | 2830 | /* reset bus_flags in packet cb */ |
2790 | *(u16 *)(pkt->cb) = 0; | 2831 | *(u16 *)(pkt->cb) = 0; |
2791 | if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) { | 2832 | if (!brcmf_sdio_prec_enq(&bus->txq, pkt, prec)) { |
2792 | skb_pull(pkt, bus->tx_hdrlen); | 2833 | skb_pull(pkt, bus->tx_hdrlen); |
2793 | brcmf_err("out of bus->txq !!!\n"); | 2834 | brcmf_err("out of bus->txq !!!\n"); |
2794 | ret = -ENOSR; | 2835 | ret = -ENOSR; |
@@ -2798,7 +2839,7 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2798 | 2839 | ||
2799 | if (pktq_len(&bus->txq) >= TXHI) { | 2840 | if (pktq_len(&bus->txq) >= TXHI) { |
2800 | bus->txoff = true; | 2841 | bus->txoff = true; |
2801 | brcmf_txflowblock(bus->sdiodev->dev, true); | 2842 | brcmf_txflowblock(dev, true); |
2802 | } | 2843 | } |
2803 | spin_unlock_bh(&bus->txq_lock); | 2844 | spin_unlock_bh(&bus->txq_lock); |
2804 | 2845 | ||
@@ -3949,6 +3990,7 @@ static struct brcmf_bus_ops brcmf_sdio_bus_ops = { | |||
3949 | .txctl = brcmf_sdio_bus_txctl, | 3990 | .txctl = brcmf_sdio_bus_txctl, |
3950 | .rxctl = brcmf_sdio_bus_rxctl, | 3991 | .rxctl = brcmf_sdio_bus_rxctl, |
3951 | .gettxq = brcmf_sdio_bus_gettxq, | 3992 | .gettxq = brcmf_sdio_bus_gettxq, |
3993 | .wowl_config = brcmf_sdio_wowl_config | ||
3952 | }; | 3994 | }; |
3953 | 3995 | ||
3954 | static void brcmf_sdio_firmware_callback(struct device *dev, | 3996 | static void brcmf_sdio_firmware_callback(struct device *dev, |
@@ -4075,7 +4117,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
4075 | 4117 | ||
4076 | /* platform specific configuration: | 4118 | /* platform specific configuration: |
4077 | * alignments must be at least 4 bytes for ADMA | 4119 | * alignments must be at least 4 bytes for ADMA |
4078 | */ | 4120 | */ |
4079 | bus->head_align = ALIGNMENT; | 4121 | bus->head_align = ALIGNMENT; |
4080 | bus->sgentry_align = ALIGNMENT; | 4122 | bus->sgentry_align = ALIGNMENT; |
4081 | if (sdiodev->pdata) { | 4123 | if (sdiodev->pdata) { |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h index f2d06cae366a..8eb42620129c 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/sdio_host.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/sdio.h | |||
@@ -14,8 +14,8 @@ | |||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | 14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
15 | */ | 15 | */ |
16 | 16 | ||
17 | #ifndef _BRCM_SDH_H_ | 17 | #ifndef BRCMFMAC_SDIO_H |
18 | #define _BRCM_SDH_H_ | 18 | #define BRCMFMAC_SDIO_H |
19 | 19 | ||
20 | #include <linux/skbuff.h> | 20 | #include <linux/skbuff.h> |
21 | #include <linux/firmware.h> | 21 | #include <linux/firmware.h> |
@@ -186,6 +186,7 @@ struct brcmf_sdio_dev { | |||
186 | struct sg_table sgtable; | 186 | struct sg_table sgtable; |
187 | char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; | 187 | char fw_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; |
188 | char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; | 188 | char nvram_name[BRCMF_FW_PATH_LEN + BRCMF_FW_NAME_LEN]; |
189 | bool wowl_enabled; | ||
189 | }; | 190 | }; |
190 | 191 | ||
191 | /* sdio core registers */ | 192 | /* sdio core registers */ |
@@ -334,5 +335,6 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus); | |||
334 | void brcmf_sdio_isr(struct brcmf_sdio *bus); | 335 | void brcmf_sdio_isr(struct brcmf_sdio *bus); |
335 | 336 | ||
336 | void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick); | 337 | void brcmf_sdio_wd_timer(struct brcmf_sdio *bus, uint wdtick); |
338 | void brcmf_sdio_wowl_config(struct device *dev, bool enabled); | ||
337 | 339 | ||
338 | #endif /* _BRCM_SDH_H_ */ | 340 | #endif /* BRCMFMAC_SDIO_H */ |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c index b505db48c60d..a10f35c5eb3d 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/tracepoint.c | |||
@@ -19,4 +19,19 @@ | |||
19 | #ifndef __CHECKER__ | 19 | #ifndef __CHECKER__ |
20 | #define CREATE_TRACE_POINTS | 20 | #define CREATE_TRACE_POINTS |
21 | #include "tracepoint.h" | 21 | #include "tracepoint.h" |
22 | |||
23 | void __brcmf_err(const char *func, const char *fmt, ...) | ||
24 | { | ||
25 | struct va_format vaf = { | ||
26 | .fmt = fmt, | ||
27 | }; | ||
28 | va_list args; | ||
29 | |||
30 | va_start(args, fmt); | ||
31 | vaf.va = &args; | ||
32 | pr_err("%s: %pV", func, &vaf); | ||
33 | trace_brcmf_err(func, &vaf); | ||
34 | va_end(args); | ||
35 | } | ||
36 | |||
22 | #endif | 37 | #endif |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c index dc135915470d..5265aa70b094 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c | |||
@@ -23,13 +23,12 @@ | |||
23 | #include <brcmu_utils.h> | 23 | #include <brcmu_utils.h> |
24 | #include <brcm_hw_ids.h> | 24 | #include <brcm_hw_ids.h> |
25 | #include <brcmu_wifi.h> | 25 | #include <brcmu_wifi.h> |
26 | #include <dhd_bus.h> | 26 | #include "bus.h" |
27 | #include <dhd_dbg.h> | 27 | #include "debug.h" |
28 | |||
29 | #include "firmware.h" | 28 | #include "firmware.h" |
30 | #include "usb_rdl.h" | ||
31 | #include "usb.h" | 29 | #include "usb.h" |
32 | 30 | ||
31 | |||
33 | #define IOCTL_RESP_TIMEOUT 2000 | 32 | #define IOCTL_RESP_TIMEOUT 2000 |
34 | 33 | ||
35 | #define BRCMF_USB_RESET_GETVER_SPINWAIT 100 /* in unit of ms */ | 34 | #define BRCMF_USB_RESET_GETVER_SPINWAIT 100 /* in unit of ms */ |
@@ -49,6 +48,71 @@ | |||
49 | #define BRCMF_USB_43242_FW_NAME "brcm/brcmfmac43242a.bin" | 48 | #define BRCMF_USB_43242_FW_NAME "brcm/brcmfmac43242a.bin" |
50 | #define BRCMF_USB_43569_FW_NAME "brcm/brcmfmac43569.bin" | 49 | #define BRCMF_USB_43569_FW_NAME "brcm/brcmfmac43569.bin" |
51 | 50 | ||
51 | #define TRX_MAGIC 0x30524448 /* "HDR0" */ | ||
52 | #define TRX_MAX_OFFSET 3 /* Max number of file offsets */ | ||
53 | #define TRX_UNCOMP_IMAGE 0x20 /* Trx holds uncompressed img */ | ||
54 | #define TRX_RDL_CHUNK 1500 /* size of each dl transfer */ | ||
55 | #define TRX_OFFSETS_DLFWLEN_IDX 0 | ||
56 | |||
57 | /* Control messages: bRequest values */ | ||
58 | #define DL_GETSTATE 0 /* returns the rdl_state_t struct */ | ||
59 | #define DL_CHECK_CRC 1 /* currently unused */ | ||
60 | #define DL_GO 2 /* execute downloaded image */ | ||
61 | #define DL_START 3 /* initialize dl state */ | ||
62 | #define DL_REBOOT 4 /* reboot the device in 2 seconds */ | ||
63 | #define DL_GETVER 5 /* returns the bootrom_id_t struct */ | ||
64 | #define DL_GO_PROTECTED 6 /* execute the downloaded code and set reset | ||
65 | * event to occur in 2 seconds. It is the | ||
66 | * responsibility of the downloaded code to | ||
67 | * clear this event | ||
68 | */ | ||
69 | #define DL_EXEC 7 /* jump to a supplied address */ | ||
70 | #define DL_RESETCFG 8 /* To support single enum on dongle | ||
71 | * - Not used by bootloader | ||
72 | */ | ||
73 | #define DL_DEFER_RESP_OK 9 /* Potentially defer the response to setup | ||
74 | * if resp unavailable | ||
75 | */ | ||
76 | |||
77 | /* states */ | ||
78 | #define DL_WAITING 0 /* waiting to rx first pkt */ | ||
79 | #define DL_READY 1 /* hdr was good, waiting for more of the | ||
80 | * compressed image | ||
81 | */ | ||
82 | #define DL_BAD_HDR 2 /* hdr was corrupted */ | ||
83 | #define DL_BAD_CRC 3 /* compressed image was corrupted */ | ||
84 | #define DL_RUNNABLE 4 /* download was successful,waiting for go cmd */ | ||
85 | #define DL_START_FAIL 5 /* failed to initialize correctly */ | ||
86 | #define DL_NVRAM_TOOBIG 6 /* host specified nvram data exceeds DL_NVRAM | ||
87 | * value | ||
88 | */ | ||
89 | #define DL_IMAGE_TOOBIG 7 /* firmware image too big */ | ||
90 | |||
91 | |||
92 | struct trx_header_le { | ||
93 | __le32 magic; /* "HDR0" */ | ||
94 | __le32 len; /* Length of file including header */ | ||
95 | __le32 crc32; /* CRC from flag_version to end of file */ | ||
96 | __le32 flag_version; /* 0:15 flags, 16:31 version */ | ||
97 | __le32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of | ||
98 | * header | ||
99 | */ | ||
100 | }; | ||
101 | |||
102 | struct rdl_state_le { | ||
103 | __le32 state; | ||
104 | __le32 bytes; | ||
105 | }; | ||
106 | |||
107 | struct bootrom_id_le { | ||
108 | __le32 chip; /* Chip id */ | ||
109 | __le32 chiprev; /* Chip rev */ | ||
110 | __le32 ramsize; /* Size of RAM */ | ||
111 | __le32 remapbase; /* Current remap base address */ | ||
112 | __le32 boardtype; /* Type of board */ | ||
113 | __le32 boardrev; /* Board revision */ | ||
114 | }; | ||
115 | |||
52 | struct brcmf_usb_image { | 116 | struct brcmf_usb_image { |
53 | struct list_head list; | 117 | struct list_head list; |
54 | s8 *fwname; | 118 | s8 *fwname; |
@@ -93,6 +157,8 @@ struct brcmf_usbdev_info { | |||
93 | u8 ifnum; | 157 | u8 ifnum; |
94 | 158 | ||
95 | struct urb *bulk_urb; /* used for FW download */ | 159 | struct urb *bulk_urb; /* used for FW download */ |
160 | |||
161 | bool wowl_enabled; | ||
96 | }; | 162 | }; |
97 | 163 | ||
98 | static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, | 164 | static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo, |
@@ -600,6 +666,16 @@ static int brcmf_usb_up(struct device *dev) | |||
600 | return 0; | 666 | return 0; |
601 | } | 667 | } |
602 | 668 | ||
669 | static void brcmf_cancel_all_urbs(struct brcmf_usbdev_info *devinfo) | ||
670 | { | ||
671 | if (devinfo->ctl_urb) | ||
672 | usb_kill_urb(devinfo->ctl_urb); | ||
673 | if (devinfo->bulk_urb) | ||
674 | usb_kill_urb(devinfo->bulk_urb); | ||
675 | brcmf_usb_free_q(&devinfo->tx_postq, true); | ||
676 | brcmf_usb_free_q(&devinfo->rx_postq, true); | ||
677 | } | ||
678 | |||
603 | static void brcmf_usb_down(struct device *dev) | 679 | static void brcmf_usb_down(struct device *dev) |
604 | { | 680 | { |
605 | struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); | 681 | struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); |
@@ -613,14 +689,7 @@ static void brcmf_usb_down(struct device *dev) | |||
613 | 689 | ||
614 | brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_DOWN); | 690 | brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_DOWN); |
615 | 691 | ||
616 | if (devinfo->ctl_urb) | 692 | brcmf_cancel_all_urbs(devinfo); |
617 | usb_kill_urb(devinfo->ctl_urb); | ||
618 | |||
619 | if (devinfo->bulk_urb) | ||
620 | usb_kill_urb(devinfo->bulk_urb); | ||
621 | brcmf_usb_free_q(&devinfo->tx_postq, true); | ||
622 | |||
623 | brcmf_usb_free_q(&devinfo->rx_postq, true); | ||
624 | } | 693 | } |
625 | 694 | ||
626 | static void | 695 | static void |
@@ -783,7 +852,7 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen) | |||
783 | 852 | ||
784 | brcmf_dbg(USB, "Enter, fw %p, len %d\n", fw, fwlen); | 853 | brcmf_dbg(USB, "Enter, fw %p, len %d\n", fw, fwlen); |
785 | 854 | ||
786 | bulkchunk = kmalloc(RDL_CHUNK, GFP_ATOMIC); | 855 | bulkchunk = kmalloc(TRX_RDL_CHUNK, GFP_ATOMIC); |
787 | if (bulkchunk == NULL) { | 856 | if (bulkchunk == NULL) { |
788 | err = -ENOMEM; | 857 | err = -ENOMEM; |
789 | goto fail; | 858 | goto fail; |
@@ -810,10 +879,10 @@ brcmf_usb_dl_writeimage(struct brcmf_usbdev_info *devinfo, u8 *fw, int fwlen) | |||
810 | /* Wait until the usb device reports it received all | 879 | /* Wait until the usb device reports it received all |
811 | * the bytes we sent */ | 880 | * the bytes we sent */ |
812 | if ((rdlbytes == sent) && (rdlbytes != dllen)) { | 881 | if ((rdlbytes == sent) && (rdlbytes != dllen)) { |
813 | if ((dllen-sent) < RDL_CHUNK) | 882 | if ((dllen-sent) < TRX_RDL_CHUNK) |
814 | sendlen = dllen-sent; | 883 | sendlen = dllen-sent; |
815 | else | 884 | else |
816 | sendlen = RDL_CHUNK; | 885 | sendlen = TRX_RDL_CHUNK; |
817 | 886 | ||
818 | /* simply avoid having to send a ZLP by ensuring we | 887 | /* simply avoid having to send a ZLP by ensuring we |
819 | * never have an even | 888 | * never have an even |
@@ -978,21 +1047,6 @@ static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo) | |||
978 | kfree(devinfo->rx_reqs); | 1047 | kfree(devinfo->rx_reqs); |
979 | } | 1048 | } |
980 | 1049 | ||
981 | #define TRX_MAGIC 0x30524448 /* "HDR0" */ | ||
982 | #define TRX_VERSION 1 /* Version 1 */ | ||
983 | #define TRX_MAX_LEN 0x3B0000 /* Max length */ | ||
984 | #define TRX_NO_HEADER 1 /* Do not write TRX header */ | ||
985 | #define TRX_MAX_OFFSET 3 /* Max number of individual files */ | ||
986 | #define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed image */ | ||
987 | |||
988 | struct trx_header_le { | ||
989 | __le32 magic; /* "HDR0" */ | ||
990 | __le32 len; /* Length of file including header */ | ||
991 | __le32 crc32; /* CRC from flag_version to end of file */ | ||
992 | __le32 flag_version; /* 0:15 flags, 16:31 version */ | ||
993 | __le32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of | ||
994 | * header */ | ||
995 | }; | ||
996 | 1050 | ||
997 | static int check_file(const u8 *headers) | 1051 | static int check_file(const u8 *headers) |
998 | { | 1052 | { |
@@ -1094,11 +1148,24 @@ error: | |||
1094 | return NULL; | 1148 | return NULL; |
1095 | } | 1149 | } |
1096 | 1150 | ||
1151 | static void brcmf_usb_wowl_config(struct device *dev, bool enabled) | ||
1152 | { | ||
1153 | struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev); | ||
1154 | |||
1155 | brcmf_dbg(USB, "Configuring WOWL, enabled=%d\n", enabled); | ||
1156 | devinfo->wowl_enabled = enabled; | ||
1157 | if (enabled) | ||
1158 | device_set_wakeup_enable(devinfo->dev, true); | ||
1159 | else | ||
1160 | device_set_wakeup_enable(devinfo->dev, false); | ||
1161 | } | ||
1162 | |||
1097 | static struct brcmf_bus_ops brcmf_usb_bus_ops = { | 1163 | static struct brcmf_bus_ops brcmf_usb_bus_ops = { |
1098 | .txdata = brcmf_usb_tx, | 1164 | .txdata = brcmf_usb_tx, |
1099 | .stop = brcmf_usb_down, | 1165 | .stop = brcmf_usb_down, |
1100 | .txctl = brcmf_usb_tx_ctlpkt, | 1166 | .txctl = brcmf_usb_tx_ctlpkt, |
1101 | .rxctl = brcmf_usb_rx_ctlpkt, | 1167 | .rxctl = brcmf_usb_rx_ctlpkt, |
1168 | .wowl_config = brcmf_usb_wowl_config, | ||
1102 | }; | 1169 | }; |
1103 | 1170 | ||
1104 | static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo) | 1171 | static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo) |
@@ -1186,6 +1253,9 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo) | |||
1186 | bus->ops = &brcmf_usb_bus_ops; | 1253 | bus->ops = &brcmf_usb_bus_ops; |
1187 | bus->proto_type = BRCMF_PROTO_BCDC; | 1254 | bus->proto_type = BRCMF_PROTO_BCDC; |
1188 | bus->always_use_fws_queue = true; | 1255 | bus->always_use_fws_queue = true; |
1256 | #ifdef CONFIG_PM | ||
1257 | bus->wowl_supported = true; | ||
1258 | #endif | ||
1189 | 1259 | ||
1190 | if (!brcmf_usb_dlneeded(devinfo)) { | 1260 | if (!brcmf_usb_dlneeded(devinfo)) { |
1191 | ret = brcmf_usb_bus_setup(devinfo); | 1261 | ret = brcmf_usb_bus_setup(devinfo); |
@@ -1339,7 +1409,10 @@ static int brcmf_usb_suspend(struct usb_interface *intf, pm_message_t state) | |||
1339 | 1409 | ||
1340 | brcmf_dbg(USB, "Enter\n"); | 1410 | brcmf_dbg(USB, "Enter\n"); |
1341 | devinfo->bus_pub.state = BRCMFMAC_USB_STATE_SLEEP; | 1411 | devinfo->bus_pub.state = BRCMFMAC_USB_STATE_SLEEP; |
1342 | brcmf_detach(&usb->dev); | 1412 | if (devinfo->wowl_enabled) |
1413 | brcmf_cancel_all_urbs(devinfo); | ||
1414 | else | ||
1415 | brcmf_detach(&usb->dev); | ||
1343 | return 0; | 1416 | return 0; |
1344 | } | 1417 | } |
1345 | 1418 | ||
@@ -1352,7 +1425,12 @@ static int brcmf_usb_resume(struct usb_interface *intf) | |||
1352 | struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); | 1425 | struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev); |
1353 | 1426 | ||
1354 | brcmf_dbg(USB, "Enter\n"); | 1427 | brcmf_dbg(USB, "Enter\n"); |
1355 | return brcmf_usb_bus_setup(devinfo); | 1428 | if (!devinfo->wowl_enabled) |
1429 | return brcmf_usb_bus_setup(devinfo); | ||
1430 | |||
1431 | devinfo->bus_pub.state = BRCMFMAC_USB_STATE_UP; | ||
1432 | brcmf_usb_rx_fill_all(devinfo); | ||
1433 | return 0; | ||
1356 | } | 1434 | } |
1357 | 1435 | ||
1358 | static int brcmf_usb_reset_resume(struct usb_interface *intf) | 1436 | static int brcmf_usb_reset_resume(struct usb_interface *intf) |
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h b/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h deleted file mode 100644 index 0a35c51c3da2..000000000000 --- a/drivers/net/wireless/brcm80211/brcmfmac/usb_rdl.h +++ /dev/null | |||
@@ -1,75 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2011 Broadcom Corporation | ||
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 ANY | ||
11 | * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES | ||
12 | * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION | ||
13 | * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | ||
14 | * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | ||
15 | */ | ||
16 | |||
17 | #ifndef _USB_RDL_H | ||
18 | #define _USB_RDL_H | ||
19 | |||
20 | /* Control messages: bRequest values */ | ||
21 | #define DL_GETSTATE 0 /* returns the rdl_state_t struct */ | ||
22 | #define DL_CHECK_CRC 1 /* currently unused */ | ||
23 | #define DL_GO 2 /* execute downloaded image */ | ||
24 | #define DL_START 3 /* initialize dl state */ | ||
25 | #define DL_REBOOT 4 /* reboot the device in 2 seconds */ | ||
26 | #define DL_GETVER 5 /* returns the bootrom_id_t struct */ | ||
27 | #define DL_GO_PROTECTED 6 /* execute the downloaded code and set reset | ||
28 | * event to occur in 2 seconds. It is the | ||
29 | * responsibility of the downloaded code to | ||
30 | * clear this event | ||
31 | */ | ||
32 | #define DL_EXEC 7 /* jump to a supplied address */ | ||
33 | #define DL_RESETCFG 8 /* To support single enum on dongle | ||
34 | * - Not used by bootloader | ||
35 | */ | ||
36 | #define DL_DEFER_RESP_OK 9 /* Potentially defer the response to setup | ||
37 | * if resp unavailable | ||
38 | */ | ||
39 | |||
40 | /* states */ | ||
41 | #define DL_WAITING 0 /* waiting to rx first pkt */ | ||
42 | #define DL_READY 1 /* hdr was good, waiting for more of the | ||
43 | * compressed image */ | ||
44 | #define DL_BAD_HDR 2 /* hdr was corrupted */ | ||
45 | #define DL_BAD_CRC 3 /* compressed image was corrupted */ | ||
46 | #define DL_RUNNABLE 4 /* download was successful,waiting for go cmd */ | ||
47 | #define DL_START_FAIL 5 /* failed to initialize correctly */ | ||
48 | #define DL_NVRAM_TOOBIG 6 /* host specified nvram data exceeds DL_NVRAM | ||
49 | * value */ | ||
50 | #define DL_IMAGE_TOOBIG 7 /* download image too big (exceeds DATA_START | ||
51 | * for rdl) */ | ||
52 | |||
53 | struct rdl_state_le { | ||
54 | __le32 state; | ||
55 | __le32 bytes; | ||
56 | }; | ||
57 | |||
58 | struct bootrom_id_le { | ||
59 | __le32 chip; /* Chip id */ | ||
60 | __le32 chiprev; /* Chip rev */ | ||
61 | __le32 ramsize; /* Size of RAM */ | ||
62 | __le32 remapbase; /* Current remap base address */ | ||
63 | __le32 boardtype; /* Type of board */ | ||
64 | __le32 boardrev; /* Board revision */ | ||
65 | }; | ||
66 | |||
67 | #define RDL_CHUNK 1500 /* size of each dl transfer */ | ||
68 | |||
69 | #define TRX_OFFSETS_DLFWLEN_IDX 0 | ||
70 | #define TRX_OFFSETS_JUMPTO_IDX 1 | ||
71 | #define TRX_OFFSETS_NVM_LEN_IDX 2 | ||
72 | |||
73 | #define TRX_OFFSETS_DLBASE_IDX 0 | ||
74 | |||
75 | #endif /* _USB_RDL_H */ | ||
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/vendor.c b/drivers/net/wireless/brcm80211/brcmfmac/vendor.c index 5960d827508c..222f26a39642 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/vendor.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/vendor.c | |||
@@ -20,10 +20,10 @@ | |||
20 | 20 | ||
21 | #include <brcmu_wifi.h> | 21 | #include <brcmu_wifi.h> |
22 | #include "fwil_types.h" | 22 | #include "fwil_types.h" |
23 | #include "dhd.h" | 23 | #include "core.h" |
24 | #include "p2p.h" | 24 | #include "p2p.h" |
25 | #include "dhd_dbg.h" | 25 | #include "debug.h" |
26 | #include "wl_cfg80211.h" | 26 | #include "cfg80211.h" |
27 | #include "vendor.h" | 27 | #include "vendor.h" |
28 | #include "fwil.h" | 28 | #include "fwil.h" |
29 | 29 | ||
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/debug.c b/drivers/net/wireless/brcm80211/brcmsmac/debug.c index a5d4add26f41..19740c1b1566 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/debug.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/debug.c | |||
@@ -71,48 +71,148 @@ struct dentry *brcms_debugfs_get_devdir(struct brcms_pub *drvr) | |||
71 | } | 71 | } |
72 | 72 | ||
73 | static | 73 | static |
74 | ssize_t brcms_debugfs_hardware_read(struct file *f, char __user *data, | 74 | int brcms_debugfs_hardware_read(struct seq_file *s, void *data) |
75 | size_t count, loff_t *ppos) | ||
76 | { | 75 | { |
77 | char buf[128]; | 76 | struct brcms_pub *drvr = s->private; |
78 | int res; | 77 | |
79 | struct brcms_pub *drvr = f->private_data; | 78 | seq_printf(s, "board vendor: %x\n" |
80 | 79 | "board type: %x\n" | |
81 | /* only allow read from start */ | 80 | "board revision: %x\n" |
82 | if (*ppos > 0) | 81 | "board flags: %x\n" |
83 | return 0; | 82 | "board flags2: %x\n" |
84 | 83 | "firmware revision: %x\n", | |
85 | res = scnprintf(buf, sizeof(buf), | 84 | drvr->wlc->hw->d11core->bus->boardinfo.vendor, |
86 | "board vendor: %x\n" | 85 | drvr->wlc->hw->d11core->bus->boardinfo.type, |
87 | "board type: %x\n" | 86 | drvr->wlc->hw->boardrev, |
88 | "board revision: %x\n" | 87 | drvr->wlc->hw->boardflags, |
89 | "board flags: %x\n" | 88 | drvr->wlc->hw->boardflags2, |
90 | "board flags2: %x\n" | 89 | drvr->wlc->ucode_rev); |
91 | "firmware revision: %x\n", | 90 | |
92 | drvr->wlc->hw->d11core->bus->boardinfo.vendor, | 91 | return 0; |
93 | drvr->wlc->hw->d11core->bus->boardinfo.type, | 92 | } |
94 | drvr->wlc->hw->boardrev, | 93 | |
95 | drvr->wlc->hw->boardflags, | 94 | static int brcms_debugfs_macstat_read(struct seq_file *s, void *data) |
96 | drvr->wlc->hw->boardflags2, | 95 | { |
97 | drvr->wlc->ucode_rev | 96 | struct brcms_pub *drvr = s->private; |
98 | ); | 97 | struct brcms_info *wl = drvr->ieee_hw->priv; |
99 | 98 | struct macstat stats; | |
100 | return simple_read_from_buffer(data, count, ppos, buf, res); | 99 | int i; |
100 | |||
101 | spin_lock_bh(&wl->lock); | ||
102 | stats = *(drvr->wlc->core->macstat_snapshot); | ||
103 | spin_unlock_bh(&wl->lock); | ||
104 | |||
105 | seq_printf(s, "txallfrm: %d\n", stats.txallfrm); | ||
106 | seq_printf(s, "txrtsfrm: %d\n", stats.txrtsfrm); | ||
107 | seq_printf(s, "txctsfrm: %d\n", stats.txctsfrm); | ||
108 | seq_printf(s, "txackfrm: %d\n", stats.txackfrm); | ||
109 | seq_printf(s, "txdnlfrm: %d\n", stats.txdnlfrm); | ||
110 | seq_printf(s, "txbcnfrm: %d\n", stats.txbcnfrm); | ||
111 | seq_printf(s, "txfunfl[8]:"); | ||
112 | for (i = 0; i < ARRAY_SIZE(stats.txfunfl); i++) | ||
113 | seq_printf(s, " %d", stats.txfunfl[i]); | ||
114 | seq_printf(s, "\ntxtplunfl: %d\n", stats.txtplunfl); | ||
115 | seq_printf(s, "txphyerr: %d\n", stats.txphyerr); | ||
116 | seq_printf(s, "pktengrxducast: %d\n", stats.pktengrxducast); | ||
117 | seq_printf(s, "pktengrxdmcast: %d\n", stats.pktengrxdmcast); | ||
118 | seq_printf(s, "rxfrmtoolong: %d\n", stats.rxfrmtoolong); | ||
119 | seq_printf(s, "rxfrmtooshrt: %d\n", stats.rxfrmtooshrt); | ||
120 | seq_printf(s, "rxinvmachdr: %d\n", stats.rxinvmachdr); | ||
121 | seq_printf(s, "rxbadfcs: %d\n", stats.rxbadfcs); | ||
122 | seq_printf(s, "rxbadplcp: %d\n", stats.rxbadplcp); | ||
123 | seq_printf(s, "rxcrsglitch: %d\n", stats.rxcrsglitch); | ||
124 | seq_printf(s, "rxstrt: %d\n", stats.rxstrt); | ||
125 | seq_printf(s, "rxdfrmucastmbss: %d\n", stats.rxdfrmucastmbss); | ||
126 | seq_printf(s, "rxmfrmucastmbss: %d\n", stats.rxmfrmucastmbss); | ||
127 | seq_printf(s, "rxcfrmucast: %d\n", stats.rxcfrmucast); | ||
128 | seq_printf(s, "rxrtsucast: %d\n", stats.rxrtsucast); | ||
129 | seq_printf(s, "rxctsucast: %d\n", stats.rxctsucast); | ||
130 | seq_printf(s, "rxackucast: %d\n", stats.rxackucast); | ||
131 | seq_printf(s, "rxdfrmocast: %d\n", stats.rxdfrmocast); | ||
132 | seq_printf(s, "rxmfrmocast: %d\n", stats.rxmfrmocast); | ||
133 | seq_printf(s, "rxcfrmocast: %d\n", stats.rxcfrmocast); | ||
134 | seq_printf(s, "rxrtsocast: %d\n", stats.rxrtsocast); | ||
135 | seq_printf(s, "rxctsocast: %d\n", stats.rxctsocast); | ||
136 | seq_printf(s, "rxdfrmmcast: %d\n", stats.rxdfrmmcast); | ||
137 | seq_printf(s, "rxmfrmmcast: %d\n", stats.rxmfrmmcast); | ||
138 | seq_printf(s, "rxcfrmmcast: %d\n", stats.rxcfrmmcast); | ||
139 | seq_printf(s, "rxbeaconmbss: %d\n", stats.rxbeaconmbss); | ||
140 | seq_printf(s, "rxdfrmucastobss: %d\n", stats.rxdfrmucastobss); | ||
141 | seq_printf(s, "rxbeaconobss: %d\n", stats.rxbeaconobss); | ||
142 | seq_printf(s, "rxrsptmout: %d\n", stats.rxrsptmout); | ||
143 | seq_printf(s, "bcntxcancl: %d\n", stats.bcntxcancl); | ||
144 | seq_printf(s, "rxf0ovfl: %d\n", stats.rxf0ovfl); | ||
145 | seq_printf(s, "rxf1ovfl: %d\n", stats.rxf1ovfl); | ||
146 | seq_printf(s, "rxf2ovfl: %d\n", stats.rxf2ovfl); | ||
147 | seq_printf(s, "txsfovfl: %d\n", stats.txsfovfl); | ||
148 | seq_printf(s, "pmqovfl: %d\n", stats.pmqovfl); | ||
149 | seq_printf(s, "rxcgprqfrm: %d\n", stats.rxcgprqfrm); | ||
150 | seq_printf(s, "rxcgprsqovfl: %d\n", stats.rxcgprsqovfl); | ||
151 | seq_printf(s, "txcgprsfail: %d\n", stats.txcgprsfail); | ||
152 | seq_printf(s, "txcgprssuc: %d\n", stats.txcgprssuc); | ||
153 | seq_printf(s, "prs_timeout: %d\n", stats.prs_timeout); | ||
154 | seq_printf(s, "rxnack: %d\n", stats.rxnack); | ||
155 | seq_printf(s, "frmscons: %d\n", stats.frmscons); | ||
156 | seq_printf(s, "txnack: %d\n", stats.txnack); | ||
157 | seq_printf(s, "txglitch_nack: %d\n", stats.txglitch_nack); | ||
158 | seq_printf(s, "txburst: %d\n", stats.txburst); | ||
159 | seq_printf(s, "bphy_rxcrsglitch: %d\n", stats.bphy_rxcrsglitch); | ||
160 | seq_printf(s, "phywatchdog: %d\n", stats.phywatchdog); | ||
161 | seq_printf(s, "bphy_badplcp: %d\n", stats.bphy_badplcp); | ||
162 | return 0; | ||
163 | } | ||
164 | |||
165 | struct brcms_debugfs_entry { | ||
166 | int (*read)(struct seq_file *seq, void *data); | ||
167 | struct brcms_pub *drvr; | ||
168 | }; | ||
169 | |||
170 | static int brcms_debugfs_entry_open(struct inode *inode, struct file *f) | ||
171 | { | ||
172 | struct brcms_debugfs_entry *entry = inode->i_private; | ||
173 | |||
174 | return single_open(f, entry->read, entry->drvr); | ||
101 | } | 175 | } |
102 | 176 | ||
103 | static const struct file_operations brcms_debugfs_hardware_ops = { | 177 | static const struct file_operations brcms_debugfs_def_ops = { |
104 | .owner = THIS_MODULE, | 178 | .owner = THIS_MODULE, |
105 | .open = simple_open, | 179 | .open = brcms_debugfs_entry_open, |
106 | .read = brcms_debugfs_hardware_read | 180 | .release = single_release, |
181 | .read = seq_read, | ||
182 | .llseek = seq_lseek | ||
107 | }; | 183 | }; |
108 | 184 | ||
185 | static int | ||
186 | brcms_debugfs_add_entry(struct brcms_pub *drvr, const char *fn, | ||
187 | int (*read_fn)(struct seq_file *seq, void *data)) | ||
188 | { | ||
189 | struct device *dev = &drvr->wlc->hw->d11core->dev; | ||
190 | struct dentry *dentry = drvr->dbgfs_dir; | ||
191 | struct brcms_debugfs_entry *entry; | ||
192 | |||
193 | if (IS_ERR_OR_NULL(dentry)) | ||
194 | return -ENOENT; | ||
195 | |||
196 | entry = devm_kzalloc(dev, sizeof(*entry), GFP_KERNEL); | ||
197 | if (!entry) | ||
198 | return -ENOMEM; | ||
199 | |||
200 | entry->read = read_fn; | ||
201 | entry->drvr = drvr; | ||
202 | |||
203 | dentry = debugfs_create_file(fn, S_IRUGO, dentry, entry, | ||
204 | &brcms_debugfs_def_ops); | ||
205 | |||
206 | return PTR_ERR_OR_ZERO(dentry); | ||
207 | } | ||
208 | |||
109 | void brcms_debugfs_create_files(struct brcms_pub *drvr) | 209 | void brcms_debugfs_create_files(struct brcms_pub *drvr) |
110 | { | 210 | { |
111 | struct dentry *dentry = drvr->dbgfs_dir; | 211 | if (IS_ERR_OR_NULL(drvr->dbgfs_dir)) |
212 | return; | ||
112 | 213 | ||
113 | if (!IS_ERR_OR_NULL(dentry)) | 214 | brcms_debugfs_add_entry(drvr, "hardware", brcms_debugfs_hardware_read); |
114 | debugfs_create_file("hardware", S_IRUGO, dentry, | 215 | brcms_debugfs_add_entry(drvr, "macstat", brcms_debugfs_macstat_read); |
115 | drvr, &brcms_debugfs_hardware_ops); | ||
116 | } | 216 | } |
117 | 217 | ||
118 | #define __brcms_fn(fn) \ | 218 | #define __brcms_fn(fn) \ |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c index 43c71bfaa474..f95b52442281 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c | |||
@@ -764,7 +764,9 @@ brcms_ops_configure_filter(struct ieee80211_hw *hw, | |||
764 | return; | 764 | return; |
765 | } | 765 | } |
766 | 766 | ||
767 | static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw) | 767 | static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw, |
768 | struct ieee80211_vif *vif, | ||
769 | const u8 *mac_addr) | ||
768 | { | 770 | { |
769 | struct brcms_info *wl = hw->priv; | 771 | struct brcms_info *wl = hw->priv; |
770 | spin_lock_bh(&wl->lock); | 772 | spin_lock_bh(&wl->lock); |
@@ -773,7 +775,8 @@ static void brcms_ops_sw_scan_start(struct ieee80211_hw *hw) | |||
773 | return; | 775 | return; |
774 | } | 776 | } |
775 | 777 | ||
776 | static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw) | 778 | static void brcms_ops_sw_scan_complete(struct ieee80211_hw *hw, |
779 | struct ieee80211_vif *vif) | ||
777 | { | 780 | { |
778 | struct brcms_info *wl = hw->priv; | 781 | struct brcms_info *wl = hw->priv; |
779 | spin_lock_bh(&wl->lock); | 782 | spin_lock_bh(&wl->lock); |
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 1b474828d5b8..738cfaca1e0f 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -1009,8 +1009,7 @@ brcms_c_dotxstatus(struct brcms_c_info *wlc, struct tx_status *txs) | |||
1009 | if (txh) | 1009 | if (txh) |
1010 | trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, | 1010 | trace_brcms_txdesc(&wlc->hw->d11core->dev, txh, |
1011 | sizeof(*txh)); | 1011 | sizeof(*txh)); |
1012 | if (p) | 1012 | brcmu_pkt_buf_free_skb(p); |
1013 | brcmu_pkt_buf_free_skb(p); | ||
1014 | } | 1013 | } |
1015 | 1014 | ||
1016 | if (dma && queue < NFIFO) { | 1015 | if (dma && queue < NFIFO) { |
@@ -3081,7 +3080,7 @@ static bool brcms_c_ps_allowed(struct brcms_c_info *wlc) | |||
3081 | static void brcms_c_statsupd(struct brcms_c_info *wlc) | 3080 | static void brcms_c_statsupd(struct brcms_c_info *wlc) |
3082 | { | 3081 | { |
3083 | int i; | 3082 | int i; |
3084 | struct macstat macstats; | 3083 | struct macstat *macstats; |
3085 | #ifdef DEBUG | 3084 | #ifdef DEBUG |
3086 | u16 delta; | 3085 | u16 delta; |
3087 | u16 rxf0ovfl; | 3086 | u16 rxf0ovfl; |
@@ -3092,31 +3091,31 @@ static void brcms_c_statsupd(struct brcms_c_info *wlc) | |||
3092 | if (!wlc->pub->up) | 3091 | if (!wlc->pub->up) |
3093 | return; | 3092 | return; |
3094 | 3093 | ||
3094 | macstats = wlc->core->macstat_snapshot; | ||
3095 | |||
3095 | #ifdef DEBUG | 3096 | #ifdef DEBUG |
3096 | /* save last rx fifo 0 overflow count */ | 3097 | /* save last rx fifo 0 overflow count */ |
3097 | rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl; | 3098 | rxf0ovfl = macstats->rxf0ovfl; |
3098 | 3099 | ||
3099 | /* save last tx fifo underflow count */ | 3100 | /* save last tx fifo underflow count */ |
3100 | for (i = 0; i < NFIFO; i++) | 3101 | for (i = 0; i < NFIFO; i++) |
3101 | txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i]; | 3102 | txfunfl[i] = macstats->txfunfl[i]; |
3102 | #endif /* DEBUG */ | 3103 | #endif /* DEBUG */ |
3103 | 3104 | ||
3104 | /* Read mac stats from contiguous shared memory */ | 3105 | /* Read mac stats from contiguous shared memory */ |
3105 | brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, &macstats, | 3106 | brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, macstats, |
3106 | sizeof(struct macstat), OBJADDR_SHM_SEL); | 3107 | sizeof(*macstats), OBJADDR_SHM_SEL); |
3107 | 3108 | ||
3108 | #ifdef DEBUG | 3109 | #ifdef DEBUG |
3109 | /* check for rx fifo 0 overflow */ | 3110 | /* check for rx fifo 0 overflow */ |
3110 | delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl); | 3111 | delta = (u16)(macstats->rxf0ovfl - rxf0ovfl); |
3111 | if (delta) | 3112 | if (delta) |
3112 | brcms_err(wlc->hw->d11core, "wl%d: %u rx fifo 0 overflows!\n", | 3113 | brcms_err(wlc->hw->d11core, "wl%d: %u rx fifo 0 overflows!\n", |
3113 | wlc->pub->unit, delta); | 3114 | wlc->pub->unit, delta); |
3114 | 3115 | ||
3115 | /* check for tx fifo underflows */ | 3116 | /* check for tx fifo underflows */ |
3116 | for (i = 0; i < NFIFO; i++) { | 3117 | for (i = 0; i < NFIFO; i++) { |
3117 | delta = | 3118 | delta = macstats->txfunfl[i] - txfunfl[i]; |
3118 | (u16) (wlc->core->macstat_snapshot->txfunfl[i] - | ||
3119 | txfunfl[i]); | ||
3120 | if (delta) | 3119 | if (delta) |
3121 | brcms_err(wlc->hw->d11core, | 3120 | brcms_err(wlc->hw->d11core, |
3122 | "wl%d: %u tx fifo %d underflows!\n", | 3121 | "wl%d: %u tx fifo %d underflows!\n", |
diff --git a/drivers/net/wireless/cw1200/scan.c b/drivers/net/wireless/cw1200/scan.c index b2fb6c632092..f2e276faca70 100644 --- a/drivers/net/wireless/cw1200/scan.c +++ b/drivers/net/wireless/cw1200/scan.c | |||
@@ -78,7 +78,7 @@ int cw1200_hw_scan(struct ieee80211_hw *hw, | |||
78 | if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS) | 78 | if (req->n_ssids > WSM_SCAN_MAX_NUM_OF_SSIDS) |
79 | return -EINVAL; | 79 | return -EINVAL; |
80 | 80 | ||
81 | frame.skb = ieee80211_probereq_get(hw, priv->vif, NULL, 0, | 81 | frame.skb = ieee80211_probereq_get(hw, priv->vif->addr, NULL, 0, |
82 | req->ie_len); | 82 | req->ie_len); |
83 | if (!frame.skb) | 83 | if (!frame.skb) |
84 | return -ENOMEM; | 84 | return -ENOMEM; |
diff --git a/drivers/net/wireless/hostap/hostap_proc.c b/drivers/net/wireless/hostap/hostap_proc.c index 8efd17c52f65..dd84557cf957 100644 --- a/drivers/net/wireless/hostap/hostap_proc.c +++ b/drivers/net/wireless/hostap/hostap_proc.c | |||
@@ -168,7 +168,6 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v) | |||
168 | local_info_t *local = m->private; | 168 | local_info_t *local = m->private; |
169 | struct list_head *ptr = v; | 169 | struct list_head *ptr = v; |
170 | struct hostap_bss_info *bss; | 170 | struct hostap_bss_info *bss; |
171 | int i; | ||
172 | 171 | ||
173 | if (ptr == &local->bss_list) { | 172 | if (ptr == &local->bss_list) { |
174 | seq_printf(m, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t" | 173 | seq_printf(m, "#BSSID\tlast_update\tcount\tcapab_info\tSSID(txt)\t" |
@@ -181,9 +180,7 @@ static int prism2_bss_list_proc_show(struct seq_file *m, void *v) | |||
181 | bss->bssid, bss->last_update, | 180 | bss->bssid, bss->last_update, |
182 | bss->count, bss->capab_info); | 181 | bss->count, bss->capab_info); |
183 | 182 | ||
184 | for (i = 0; i < bss->ssid_len; i++) | 183 | seq_printf(m, "%*pE", (int)bss->ssid_len, bss->ssid); |
185 | seq_putc(m,bss->ssid[i] >= 32 && bss->ssid[i] < 127 ? | ||
186 | bss->ssid[i] : '_'); | ||
187 | 184 | ||
188 | seq_putc(m, '\t'); | 185 | seq_putc(m, '\t'); |
189 | seq_printf(m, "%*phN", (int)bss->ssid_len, bss->ssid); | 186 | seq_printf(m, "%*phN", (int)bss->ssid_len, bss->ssid); |
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c index c3d726f334e3..6fabea0309dd 100644 --- a/drivers/net/wireless/ipw2x00/ipw2100.c +++ b/drivers/net/wireless/ipw2x00/ipw2100.c | |||
@@ -2005,7 +2005,6 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) | |||
2005 | u32 chan; | 2005 | u32 chan; |
2006 | char *txratename; | 2006 | char *txratename; |
2007 | u8 bssid[ETH_ALEN]; | 2007 | u8 bssid[ETH_ALEN]; |
2008 | DECLARE_SSID_BUF(ssid); | ||
2009 | 2008 | ||
2010 | /* | 2009 | /* |
2011 | * TBD: BSSID is usually 00:00:00:00:00:00 here and not | 2010 | * TBD: BSSID is usually 00:00:00:00:00:00 here and not |
@@ -2067,8 +2066,8 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status) | |||
2067 | break; | 2066 | break; |
2068 | } | 2067 | } |
2069 | 2068 | ||
2070 | IPW_DEBUG_INFO("%s: Associated with '%s' at %s, channel %d (BSSID=%pM)\n", | 2069 | IPW_DEBUG_INFO("%s: Associated with '%*pE' at %s, channel %d (BSSID=%pM)\n", |
2071 | priv->net_dev->name, print_ssid(ssid, essid, essid_len), | 2070 | priv->net_dev->name, essid_len, essid, |
2072 | txratename, chan, bssid); | 2071 | txratename, chan, bssid); |
2073 | 2072 | ||
2074 | /* now we copy read ssid into dev */ | 2073 | /* now we copy read ssid into dev */ |
@@ -2095,9 +2094,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid, | |||
2095 | .host_command_length = ssid_len | 2094 | .host_command_length = ssid_len |
2096 | }; | 2095 | }; |
2097 | int err; | 2096 | int err; |
2098 | DECLARE_SSID_BUF(ssid); | ||
2099 | 2097 | ||
2100 | IPW_DEBUG_HC("SSID: '%s'\n", print_ssid(ssid, essid, ssid_len)); | 2098 | IPW_DEBUG_HC("SSID: '%*pE'\n", ssid_len, essid); |
2101 | 2099 | ||
2102 | if (ssid_len) | 2100 | if (ssid_len) |
2103 | memcpy(cmd.host_command_parameters, essid, ssid_len); | 2101 | memcpy(cmd.host_command_parameters, essid, ssid_len); |
@@ -2138,11 +2136,8 @@ static int ipw2100_set_essid(struct ipw2100_priv *priv, char *essid, | |||
2138 | 2136 | ||
2139 | static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status) | 2137 | static void isr_indicate_association_lost(struct ipw2100_priv *priv, u32 status) |
2140 | { | 2138 | { |
2141 | DECLARE_SSID_BUF(ssid); | ||
2142 | |||
2143 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, | 2139 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | IPW_DL_ASSOC, |
2144 | "disassociated: '%s' %pM\n", | 2140 | "disassociated: '%*pE' %pM\n", priv->essid_len, priv->essid, |
2145 | print_ssid(ssid, priv->essid, priv->essid_len), | ||
2146 | priv->bssid); | 2141 | priv->bssid); |
2147 | 2142 | ||
2148 | priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); | 2143 | priv->status &= ~(STATUS_ASSOCIATED | STATUS_ASSOCIATING); |
@@ -6975,7 +6970,6 @@ static int ipw2100_wx_set_essid(struct net_device *dev, | |||
6975 | char *essid = ""; /* ANY */ | 6970 | char *essid = ""; /* ANY */ |
6976 | int length = 0; | 6971 | int length = 0; |
6977 | int err = 0; | 6972 | int err = 0; |
6978 | DECLARE_SSID_BUF(ssid); | ||
6979 | 6973 | ||
6980 | mutex_lock(&priv->action_mutex); | 6974 | mutex_lock(&priv->action_mutex); |
6981 | if (!(priv->status & STATUS_INITIALIZED)) { | 6975 | if (!(priv->status & STATUS_INITIALIZED)) { |
@@ -7005,8 +6999,7 @@ static int ipw2100_wx_set_essid(struct net_device *dev, | |||
7005 | goto done; | 6999 | goto done; |
7006 | } | 7000 | } |
7007 | 7001 | ||
7008 | IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", | 7002 | IPW_DEBUG_WX("Setting ESSID: '%*pE' (%d)\n", length, essid, length); |
7009 | print_ssid(ssid, essid, length), length); | ||
7010 | 7003 | ||
7011 | priv->essid_len = length; | 7004 | priv->essid_len = length; |
7012 | memcpy(priv->essid, essid, priv->essid_len); | 7005 | memcpy(priv->essid, essid, priv->essid_len); |
@@ -7027,13 +7020,12 @@ static int ipw2100_wx_get_essid(struct net_device *dev, | |||
7027 | */ | 7020 | */ |
7028 | 7021 | ||
7029 | struct ipw2100_priv *priv = libipw_priv(dev); | 7022 | struct ipw2100_priv *priv = libipw_priv(dev); |
7030 | DECLARE_SSID_BUF(ssid); | ||
7031 | 7023 | ||
7032 | /* If we are associated, trying to associate, or have a statically | 7024 | /* If we are associated, trying to associate, or have a statically |
7033 | * configured ESSID then return that; otherwise return ANY */ | 7025 | * configured ESSID then return that; otherwise return ANY */ |
7034 | if (priv->config & CFG_STATIC_ESSID || priv->status & STATUS_ASSOCIATED) { | 7026 | if (priv->config & CFG_STATIC_ESSID || priv->status & STATUS_ASSOCIATED) { |
7035 | IPW_DEBUG_WX("Getting essid: '%s'\n", | 7027 | IPW_DEBUG_WX("Getting essid: '%*pE'\n", |
7036 | print_ssid(ssid, priv->essid, priv->essid_len)); | 7028 | priv->essid_len, priv->essid); |
7037 | memcpy(extra, priv->essid, priv->essid_len); | 7029 | memcpy(extra, priv->essid, priv->essid_len); |
7038 | wrqu->essid.length = priv->essid_len; | 7030 | wrqu->essid.length = priv->essid_len; |
7039 | wrqu->essid.flags = 1; /* active */ | 7031 | wrqu->essid.flags = 1; /* active */ |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index f0c3c77a48d3..67cad9b05ad8 100644 --- a/drivers/net/wireless/ipw2x00/ipw2200.c +++ b/drivers/net/wireless/ipw2x00/ipw2200.c | |||
@@ -1363,7 +1363,7 @@ static ssize_t show_cmd_log(struct device *d, | |||
1363 | if (!priv->cmdlog) | 1363 | if (!priv->cmdlog) |
1364 | return 0; | 1364 | return 0; |
1365 | for (i = (priv->cmdlog_pos + 1) % priv->cmdlog_len; | 1365 | for (i = (priv->cmdlog_pos + 1) % priv->cmdlog_len; |
1366 | (i != priv->cmdlog_pos) && (PAGE_SIZE - len); | 1366 | (i != priv->cmdlog_pos) && (len < PAGE_SIZE); |
1367 | i = (i + 1) % priv->cmdlog_len) { | 1367 | i = (i + 1) % priv->cmdlog_len) { |
1368 | len += | 1368 | len += |
1369 | snprintf(buf + len, PAGE_SIZE - len, | 1369 | snprintf(buf + len, PAGE_SIZE - len, |
@@ -4496,7 +4496,6 @@ static void handle_scan_event(struct ipw_priv *priv) | |||
4496 | static void ipw_rx_notification(struct ipw_priv *priv, | 4496 | static void ipw_rx_notification(struct ipw_priv *priv, |
4497 | struct ipw_rx_notification *notif) | 4497 | struct ipw_rx_notification *notif) |
4498 | { | 4498 | { |
4499 | DECLARE_SSID_BUF(ssid); | ||
4500 | u16 size = le16_to_cpu(notif->size); | 4499 | u16 size = le16_to_cpu(notif->size); |
4501 | 4500 | ||
4502 | IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, size); | 4501 | IPW_DEBUG_NOTIF("type = %i (%d bytes)\n", notif->subtype, size); |
@@ -4509,9 +4508,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4509 | case CMAS_ASSOCIATED:{ | 4508 | case CMAS_ASSOCIATED:{ |
4510 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | | 4509 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | |
4511 | IPW_DL_ASSOC, | 4510 | IPW_DL_ASSOC, |
4512 | "associated: '%s' %pM\n", | 4511 | "associated: '%*pE' %pM\n", |
4513 | print_ssid(ssid, priv->essid, | 4512 | priv->essid_len, priv->essid, |
4514 | priv->essid_len), | ||
4515 | priv->bssid); | 4513 | priv->bssid); |
4516 | 4514 | ||
4517 | switch (priv->ieee->iw_mode) { | 4515 | switch (priv->ieee->iw_mode) { |
@@ -4585,14 +4583,9 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4585 | IPW_DEBUG(IPW_DL_NOTIF | | 4583 | IPW_DEBUG(IPW_DL_NOTIF | |
4586 | IPW_DL_STATE | | 4584 | IPW_DL_STATE | |
4587 | IPW_DL_ASSOC, | 4585 | IPW_DL_ASSOC, |
4588 | "deauthenticated: '%s' " | 4586 | "deauthenticated: '%*pE' %pM: (0x%04X) - %s\n", |
4589 | "%pM" | 4587 | priv->essid_len, |
4590 | ": (0x%04X) - %s\n", | 4588 | priv->essid, |
4591 | print_ssid(ssid, | ||
4592 | priv-> | ||
4593 | essid, | ||
4594 | priv-> | ||
4595 | essid_len), | ||
4596 | priv->bssid, | 4589 | priv->bssid, |
4597 | le16_to_cpu(auth->status), | 4590 | le16_to_cpu(auth->status), |
4598 | ipw_get_status_code | 4591 | ipw_get_status_code |
@@ -4610,9 +4603,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4610 | 4603 | ||
4611 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | | 4604 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | |
4612 | IPW_DL_ASSOC, | 4605 | IPW_DL_ASSOC, |
4613 | "authenticated: '%s' %pM\n", | 4606 | "authenticated: '%*pE' %pM\n", |
4614 | print_ssid(ssid, priv->essid, | 4607 | priv->essid_len, priv->essid, |
4615 | priv->essid_len), | ||
4616 | priv->bssid); | 4608 | priv->bssid); |
4617 | break; | 4609 | break; |
4618 | } | 4610 | } |
@@ -4638,9 +4630,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4638 | 4630 | ||
4639 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | | 4631 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | |
4640 | IPW_DL_ASSOC, | 4632 | IPW_DL_ASSOC, |
4641 | "disassociated: '%s' %pM\n", | 4633 | "disassociated: '%*pE' %pM\n", |
4642 | print_ssid(ssid, priv->essid, | 4634 | priv->essid_len, priv->essid, |
4643 | priv->essid_len), | ||
4644 | priv->bssid); | 4635 | priv->bssid); |
4645 | 4636 | ||
4646 | priv->status &= | 4637 | priv->status &= |
@@ -4676,9 +4667,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4676 | switch (auth->state) { | 4667 | switch (auth->state) { |
4677 | case CMAS_AUTHENTICATED: | 4668 | case CMAS_AUTHENTICATED: |
4678 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, | 4669 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE, |
4679 | "authenticated: '%s' %pM\n", | 4670 | "authenticated: '%*pE' %pM\n", |
4680 | print_ssid(ssid, priv->essid, | 4671 | priv->essid_len, priv->essid, |
4681 | priv->essid_len), | ||
4682 | priv->bssid); | 4672 | priv->bssid); |
4683 | priv->status |= STATUS_AUTH; | 4673 | priv->status |= STATUS_AUTH; |
4684 | break; | 4674 | break; |
@@ -4695,9 +4685,8 @@ static void ipw_rx_notification(struct ipw_priv *priv, | |||
4695 | } | 4685 | } |
4696 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | | 4686 | IPW_DEBUG(IPW_DL_NOTIF | IPW_DL_STATE | |
4697 | IPW_DL_ASSOC, | 4687 | IPW_DL_ASSOC, |
4698 | "deauthenticated: '%s' %pM\n", | 4688 | "deauthenticated: '%*pE' %pM\n", |
4699 | print_ssid(ssid, priv->essid, | 4689 | priv->essid_len, priv->essid, |
4700 | priv->essid_len), | ||
4701 | priv->bssid); | 4690 | priv->bssid); |
4702 | 4691 | ||
4703 | priv->status &= ~(STATUS_ASSOCIATING | | 4692 | priv->status &= ~(STATUS_ASSOCIATING | |
@@ -5516,16 +5505,13 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, | |||
5516 | int roaming) | 5505 | int roaming) |
5517 | { | 5506 | { |
5518 | struct ipw_supported_rates rates; | 5507 | struct ipw_supported_rates rates; |
5519 | DECLARE_SSID_BUF(ssid); | ||
5520 | 5508 | ||
5521 | /* Verify that this network's capability is compatible with the | 5509 | /* Verify that this network's capability is compatible with the |
5522 | * current mode (AdHoc or Infrastructure) */ | 5510 | * current mode (AdHoc or Infrastructure) */ |
5523 | if ((priv->ieee->iw_mode == IW_MODE_ADHOC && | 5511 | if ((priv->ieee->iw_mode == IW_MODE_ADHOC && |
5524 | !(network->capability & WLAN_CAPABILITY_IBSS))) { | 5512 | !(network->capability & WLAN_CAPABILITY_IBSS))) { |
5525 | IPW_DEBUG_MERGE("Network '%s (%pM)' excluded due to " | 5513 | IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded due to capability mismatch.\n", |
5526 | "capability mismatch.\n", | 5514 | network->ssid_len, network->ssid, |
5527 | print_ssid(ssid, network->ssid, | ||
5528 | network->ssid_len), | ||
5529 | network->bssid); | 5515 | network->bssid); |
5530 | return 0; | 5516 | return 0; |
5531 | } | 5517 | } |
@@ -5536,10 +5522,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, | |||
5536 | if ((network->ssid_len != match->network->ssid_len) || | 5522 | if ((network->ssid_len != match->network->ssid_len) || |
5537 | memcmp(network->ssid, match->network->ssid, | 5523 | memcmp(network->ssid, match->network->ssid, |
5538 | network->ssid_len)) { | 5524 | network->ssid_len)) { |
5539 | IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " | 5525 | IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of non-network ESSID.\n", |
5540 | "because of non-network ESSID.\n", | 5526 | network->ssid_len, network->ssid, |
5541 | print_ssid(ssid, network->ssid, | ||
5542 | network->ssid_len), | ||
5543 | network->bssid); | 5527 | network->bssid); |
5544 | return 0; | 5528 | return 0; |
5545 | } | 5529 | } |
@@ -5550,17 +5534,10 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, | |||
5550 | ((network->ssid_len != priv->essid_len) || | 5534 | ((network->ssid_len != priv->essid_len) || |
5551 | memcmp(network->ssid, priv->essid, | 5535 | memcmp(network->ssid, priv->essid, |
5552 | min(network->ssid_len, priv->essid_len)))) { | 5536 | min(network->ssid_len, priv->essid_len)))) { |
5553 | char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; | 5537 | IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of ESSID mismatch: '%*pE'.\n", |
5554 | 5538 | network->ssid_len, network->ssid, | |
5555 | strlcpy(escaped, | 5539 | network->bssid, priv->essid_len, |
5556 | print_ssid(ssid, network->ssid, | 5540 | priv->essid); |
5557 | network->ssid_len), | ||
5558 | sizeof(escaped)); | ||
5559 | IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " | ||
5560 | "because of ESSID mismatch: '%s'.\n", | ||
5561 | escaped, network->bssid, | ||
5562 | print_ssid(ssid, priv->essid, | ||
5563 | priv->essid_len)); | ||
5564 | return 0; | 5541 | return 0; |
5565 | } | 5542 | } |
5566 | } | 5543 | } |
@@ -5569,26 +5546,20 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, | |||
5569 | * testing everything else. */ | 5546 | * testing everything else. */ |
5570 | 5547 | ||
5571 | if (network->time_stamp[0] < match->network->time_stamp[0]) { | 5548 | if (network->time_stamp[0] < match->network->time_stamp[0]) { |
5572 | IPW_DEBUG_MERGE("Network '%s excluded because newer than " | 5549 | IPW_DEBUG_MERGE("Network '%*pE excluded because newer than current network.\n", |
5573 | "current network.\n", | 5550 | match->network->ssid_len, match->network->ssid); |
5574 | print_ssid(ssid, match->network->ssid, | ||
5575 | match->network->ssid_len)); | ||
5576 | return 0; | 5551 | return 0; |
5577 | } else if (network->time_stamp[1] < match->network->time_stamp[1]) { | 5552 | } else if (network->time_stamp[1] < match->network->time_stamp[1]) { |
5578 | IPW_DEBUG_MERGE("Network '%s excluded because newer than " | 5553 | IPW_DEBUG_MERGE("Network '%*pE excluded because newer than current network.\n", |
5579 | "current network.\n", | 5554 | match->network->ssid_len, match->network->ssid); |
5580 | print_ssid(ssid, match->network->ssid, | ||
5581 | match->network->ssid_len)); | ||
5582 | return 0; | 5555 | return 0; |
5583 | } | 5556 | } |
5584 | 5557 | ||
5585 | /* Now go through and see if the requested network is valid... */ | 5558 | /* Now go through and see if the requested network is valid... */ |
5586 | if (priv->ieee->scan_age != 0 && | 5559 | if (priv->ieee->scan_age != 0 && |
5587 | time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { | 5560 | time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { |
5588 | IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " | 5561 | IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of age: %ums.\n", |
5589 | "because of age: %ums.\n", | 5562 | network->ssid_len, network->ssid, |
5590 | print_ssid(ssid, network->ssid, | ||
5591 | network->ssid_len), | ||
5592 | network->bssid, | 5563 | network->bssid, |
5593 | jiffies_to_msecs(jiffies - | 5564 | jiffies_to_msecs(jiffies - |
5594 | network->last_scanned)); | 5565 | network->last_scanned)); |
@@ -5597,10 +5568,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, | |||
5597 | 5568 | ||
5598 | if ((priv->config & CFG_STATIC_CHANNEL) && | 5569 | if ((priv->config & CFG_STATIC_CHANNEL) && |
5599 | (network->channel != priv->channel)) { | 5570 | (network->channel != priv->channel)) { |
5600 | IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " | 5571 | IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of channel mismatch: %d != %d.\n", |
5601 | "because of channel mismatch: %d != %d.\n", | 5572 | network->ssid_len, network->ssid, |
5602 | print_ssid(ssid, network->ssid, | ||
5603 | network->ssid_len), | ||
5604 | network->bssid, | 5573 | network->bssid, |
5605 | network->channel, priv->channel); | 5574 | network->channel, priv->channel); |
5606 | return 0; | 5575 | return 0; |
@@ -5609,10 +5578,8 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, | |||
5609 | /* Verify privacy compatibility */ | 5578 | /* Verify privacy compatibility */ |
5610 | if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) != | 5579 | if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) != |
5611 | ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) { | 5580 | ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) { |
5612 | IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " | 5581 | IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of privacy mismatch: %s != %s.\n", |
5613 | "because of privacy mismatch: %s != %s.\n", | 5582 | network->ssid_len, network->ssid, |
5614 | print_ssid(ssid, network->ssid, | ||
5615 | network->ssid_len), | ||
5616 | network->bssid, | 5583 | network->bssid, |
5617 | priv-> | 5584 | priv-> |
5618 | capability & CAP_PRIVACY_ON ? "on" : "off", | 5585 | capability & CAP_PRIVACY_ON ? "on" : "off", |
@@ -5623,22 +5590,16 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, | |||
5623 | } | 5590 | } |
5624 | 5591 | ||
5625 | if (ether_addr_equal(network->bssid, priv->bssid)) { | 5592 | if (ether_addr_equal(network->bssid, priv->bssid)) { |
5626 | IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " | 5593 | IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of the same BSSID match: %pM.\n", |
5627 | "because of the same BSSID match: %pM" | 5594 | network->ssid_len, network->ssid, |
5628 | ".\n", print_ssid(ssid, network->ssid, | 5595 | network->bssid, priv->bssid); |
5629 | network->ssid_len), | ||
5630 | network->bssid, | ||
5631 | priv->bssid); | ||
5632 | return 0; | 5596 | return 0; |
5633 | } | 5597 | } |
5634 | 5598 | ||
5635 | /* Filter out any incompatible freq / mode combinations */ | 5599 | /* Filter out any incompatible freq / mode combinations */ |
5636 | if (!libipw_is_valid_mode(priv->ieee, network->mode)) { | 5600 | if (!libipw_is_valid_mode(priv->ieee, network->mode)) { |
5637 | IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " | 5601 | IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of invalid frequency/mode combination.\n", |
5638 | "because of invalid frequency/mode " | 5602 | network->ssid_len, network->ssid, |
5639 | "combination.\n", | ||
5640 | print_ssid(ssid, network->ssid, | ||
5641 | network->ssid_len), | ||
5642 | network->bssid); | 5603 | network->bssid); |
5643 | return 0; | 5604 | return 0; |
5644 | } | 5605 | } |
@@ -5646,20 +5607,15 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, | |||
5646 | /* Ensure that the rates supported by the driver are compatible with | 5607 | /* Ensure that the rates supported by the driver are compatible with |
5647 | * this AP, including verification of basic rates (mandatory) */ | 5608 | * this AP, including verification of basic rates (mandatory) */ |
5648 | if (!ipw_compatible_rates(priv, network, &rates)) { | 5609 | if (!ipw_compatible_rates(priv, network, &rates)) { |
5649 | IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " | 5610 | IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because configured rate mask excludes AP mandatory rate.\n", |
5650 | "because configured rate mask excludes " | 5611 | network->ssid_len, network->ssid, |
5651 | "AP mandatory rate.\n", | ||
5652 | print_ssid(ssid, network->ssid, | ||
5653 | network->ssid_len), | ||
5654 | network->bssid); | 5612 | network->bssid); |
5655 | return 0; | 5613 | return 0; |
5656 | } | 5614 | } |
5657 | 5615 | ||
5658 | if (rates.num_rates == 0) { | 5616 | if (rates.num_rates == 0) { |
5659 | IPW_DEBUG_MERGE("Network '%s (%pM)' excluded " | 5617 | IPW_DEBUG_MERGE("Network '%*pE (%pM)' excluded because of no compatible rates.\n", |
5660 | "because of no compatible rates.\n", | 5618 | network->ssid_len, network->ssid, |
5661 | print_ssid(ssid, network->ssid, | ||
5662 | network->ssid_len), | ||
5663 | network->bssid); | 5619 | network->bssid); |
5664 | return 0; | 5620 | return 0; |
5665 | } | 5621 | } |
@@ -5671,16 +5627,14 @@ static int ipw_find_adhoc_network(struct ipw_priv *priv, | |||
5671 | /* Set up 'new' AP to this network */ | 5627 | /* Set up 'new' AP to this network */ |
5672 | ipw_copy_rates(&match->rates, &rates); | 5628 | ipw_copy_rates(&match->rates, &rates); |
5673 | match->network = network; | 5629 | match->network = network; |
5674 | IPW_DEBUG_MERGE("Network '%s (%pM)' is a viable match.\n", | 5630 | IPW_DEBUG_MERGE("Network '%*pE (%pM)' is a viable match.\n", |
5675 | print_ssid(ssid, network->ssid, network->ssid_len), | 5631 | network->ssid_len, network->ssid, network->bssid); |
5676 | network->bssid); | ||
5677 | 5632 | ||
5678 | return 1; | 5633 | return 1; |
5679 | } | 5634 | } |
5680 | 5635 | ||
5681 | static void ipw_merge_adhoc_network(struct work_struct *work) | 5636 | static void ipw_merge_adhoc_network(struct work_struct *work) |
5682 | { | 5637 | { |
5683 | DECLARE_SSID_BUF(ssid); | ||
5684 | struct ipw_priv *priv = | 5638 | struct ipw_priv *priv = |
5685 | container_of(work, struct ipw_priv, merge_networks); | 5639 | container_of(work, struct ipw_priv, merge_networks); |
5686 | struct libipw_network *network = NULL; | 5640 | struct libipw_network *network = NULL; |
@@ -5710,9 +5664,8 @@ static void ipw_merge_adhoc_network(struct work_struct *work) | |||
5710 | 5664 | ||
5711 | mutex_lock(&priv->mutex); | 5665 | mutex_lock(&priv->mutex); |
5712 | if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) { | 5666 | if ((priv->ieee->iw_mode == IW_MODE_ADHOC)) { |
5713 | IPW_DEBUG_MERGE("remove network %s\n", | 5667 | IPW_DEBUG_MERGE("remove network %*pE\n", |
5714 | print_ssid(ssid, priv->essid, | 5668 | priv->essid_len, priv->essid); |
5715 | priv->essid_len)); | ||
5716 | ipw_remove_current_network(priv); | 5669 | ipw_remove_current_network(priv); |
5717 | } | 5670 | } |
5718 | 5671 | ||
@@ -5728,7 +5681,6 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5728 | struct libipw_network *network, int roaming) | 5681 | struct libipw_network *network, int roaming) |
5729 | { | 5682 | { |
5730 | struct ipw_supported_rates rates; | 5683 | struct ipw_supported_rates rates; |
5731 | DECLARE_SSID_BUF(ssid); | ||
5732 | 5684 | ||
5733 | /* Verify that this network's capability is compatible with the | 5685 | /* Verify that this network's capability is compatible with the |
5734 | * current mode (AdHoc or Infrastructure) */ | 5686 | * current mode (AdHoc or Infrastructure) */ |
@@ -5736,10 +5688,8 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5736 | !(network->capability & WLAN_CAPABILITY_ESS)) || | 5688 | !(network->capability & WLAN_CAPABILITY_ESS)) || |
5737 | (priv->ieee->iw_mode == IW_MODE_ADHOC && | 5689 | (priv->ieee->iw_mode == IW_MODE_ADHOC && |
5738 | !(network->capability & WLAN_CAPABILITY_IBSS))) { | 5690 | !(network->capability & WLAN_CAPABILITY_IBSS))) { |
5739 | IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded due to " | 5691 | IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded due to capability mismatch.\n", |
5740 | "capability mismatch.\n", | 5692 | network->ssid_len, network->ssid, |
5741 | print_ssid(ssid, network->ssid, | ||
5742 | network->ssid_len), | ||
5743 | network->bssid); | 5693 | network->bssid); |
5744 | return 0; | 5694 | return 0; |
5745 | } | 5695 | } |
@@ -5750,10 +5700,8 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5750 | if ((network->ssid_len != match->network->ssid_len) || | 5700 | if ((network->ssid_len != match->network->ssid_len) || |
5751 | memcmp(network->ssid, match->network->ssid, | 5701 | memcmp(network->ssid, match->network->ssid, |
5752 | network->ssid_len)) { | 5702 | network->ssid_len)) { |
5753 | IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " | 5703 | IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of non-network ESSID.\n", |
5754 | "because of non-network ESSID.\n", | 5704 | network->ssid_len, network->ssid, |
5755 | print_ssid(ssid, network->ssid, | ||
5756 | network->ssid_len), | ||
5757 | network->bssid); | 5705 | network->bssid); |
5758 | return 0; | 5706 | return 0; |
5759 | } | 5707 | } |
@@ -5764,16 +5712,10 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5764 | ((network->ssid_len != priv->essid_len) || | 5712 | ((network->ssid_len != priv->essid_len) || |
5765 | memcmp(network->ssid, priv->essid, | 5713 | memcmp(network->ssid, priv->essid, |
5766 | min(network->ssid_len, priv->essid_len)))) { | 5714 | min(network->ssid_len, priv->essid_len)))) { |
5767 | char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; | 5715 | IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of ESSID mismatch: '%*pE'.\n", |
5768 | strlcpy(escaped, | 5716 | network->ssid_len, network->ssid, |
5769 | print_ssid(ssid, network->ssid, | 5717 | network->bssid, priv->essid_len, |
5770 | network->ssid_len), | 5718 | priv->essid); |
5771 | sizeof(escaped)); | ||
5772 | IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " | ||
5773 | "because of ESSID mismatch: '%s'.\n", | ||
5774 | escaped, network->bssid, | ||
5775 | print_ssid(ssid, priv->essid, | ||
5776 | priv->essid_len)); | ||
5777 | return 0; | 5719 | return 0; |
5778 | } | 5720 | } |
5779 | } | 5721 | } |
@@ -5781,16 +5723,10 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5781 | /* If the old network rate is better than this one, don't bother | 5723 | /* If the old network rate is better than this one, don't bother |
5782 | * testing everything else. */ | 5724 | * testing everything else. */ |
5783 | if (match->network && match->network->stats.rssi > network->stats.rssi) { | 5725 | if (match->network && match->network->stats.rssi > network->stats.rssi) { |
5784 | char escaped[IW_ESSID_MAX_SIZE * 2 + 1]; | 5726 | IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because '%*pE (%pM)' has a stronger signal.\n", |
5785 | strlcpy(escaped, | 5727 | network->ssid_len, network->ssid, |
5786 | print_ssid(ssid, network->ssid, network->ssid_len), | 5728 | network->bssid, match->network->ssid_len, |
5787 | sizeof(escaped)); | 5729 | match->network->ssid, match->network->bssid); |
5788 | IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded because " | ||
5789 | "'%s (%pM)' has a stronger signal.\n", | ||
5790 | escaped, network->bssid, | ||
5791 | print_ssid(ssid, match->network->ssid, | ||
5792 | match->network->ssid_len), | ||
5793 | match->network->bssid); | ||
5794 | return 0; | 5730 | return 0; |
5795 | } | 5731 | } |
5796 | 5732 | ||
@@ -5798,11 +5734,8 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5798 | * last 3 seconds, do not try and associate again... */ | 5734 | * last 3 seconds, do not try and associate again... */ |
5799 | if (network->last_associate && | 5735 | if (network->last_associate && |
5800 | time_after(network->last_associate + (HZ * 3UL), jiffies)) { | 5736 | time_after(network->last_associate + (HZ * 3UL), jiffies)) { |
5801 | IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " | 5737 | IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of storming (%ums since last assoc attempt).\n", |
5802 | "because of storming (%ums since last " | 5738 | network->ssid_len, network->ssid, |
5803 | "assoc attempt).\n", | ||
5804 | print_ssid(ssid, network->ssid, | ||
5805 | network->ssid_len), | ||
5806 | network->bssid, | 5739 | network->bssid, |
5807 | jiffies_to_msecs(jiffies - | 5740 | jiffies_to_msecs(jiffies - |
5808 | network->last_associate)); | 5741 | network->last_associate)); |
@@ -5812,10 +5745,8 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5812 | /* Now go through and see if the requested network is valid... */ | 5745 | /* Now go through and see if the requested network is valid... */ |
5813 | if (priv->ieee->scan_age != 0 && | 5746 | if (priv->ieee->scan_age != 0 && |
5814 | time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { | 5747 | time_after(jiffies, network->last_scanned + priv->ieee->scan_age)) { |
5815 | IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " | 5748 | IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of age: %ums.\n", |
5816 | "because of age: %ums.\n", | 5749 | network->ssid_len, network->ssid, |
5817 | print_ssid(ssid, network->ssid, | ||
5818 | network->ssid_len), | ||
5819 | network->bssid, | 5750 | network->bssid, |
5820 | jiffies_to_msecs(jiffies - | 5751 | jiffies_to_msecs(jiffies - |
5821 | network->last_scanned)); | 5752 | network->last_scanned)); |
@@ -5824,10 +5755,8 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5824 | 5755 | ||
5825 | if ((priv->config & CFG_STATIC_CHANNEL) && | 5756 | if ((priv->config & CFG_STATIC_CHANNEL) && |
5826 | (network->channel != priv->channel)) { | 5757 | (network->channel != priv->channel)) { |
5827 | IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " | 5758 | IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of channel mismatch: %d != %d.\n", |
5828 | "because of channel mismatch: %d != %d.\n", | 5759 | network->ssid_len, network->ssid, |
5829 | print_ssid(ssid, network->ssid, | ||
5830 | network->ssid_len), | ||
5831 | network->bssid, | 5760 | network->bssid, |
5832 | network->channel, priv->channel); | 5761 | network->channel, priv->channel); |
5833 | return 0; | 5762 | return 0; |
@@ -5836,10 +5765,8 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5836 | /* Verify privacy compatibility */ | 5765 | /* Verify privacy compatibility */ |
5837 | if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) != | 5766 | if (((priv->capability & CAP_PRIVACY_ON) ? 1 : 0) != |
5838 | ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) { | 5767 | ((network->capability & WLAN_CAPABILITY_PRIVACY) ? 1 : 0)) { |
5839 | IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " | 5768 | IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of privacy mismatch: %s != %s.\n", |
5840 | "because of privacy mismatch: %s != %s.\n", | 5769 | network->ssid_len, network->ssid, |
5841 | print_ssid(ssid, network->ssid, | ||
5842 | network->ssid_len), | ||
5843 | network->bssid, | 5770 | network->bssid, |
5844 | priv->capability & CAP_PRIVACY_ON ? "on" : | 5771 | priv->capability & CAP_PRIVACY_ON ? "on" : |
5845 | "off", | 5772 | "off", |
@@ -5850,31 +5777,24 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5850 | 5777 | ||
5851 | if ((priv->config & CFG_STATIC_BSSID) && | 5778 | if ((priv->config & CFG_STATIC_BSSID) && |
5852 | !ether_addr_equal(network->bssid, priv->bssid)) { | 5779 | !ether_addr_equal(network->bssid, priv->bssid)) { |
5853 | IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " | 5780 | IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of BSSID mismatch: %pM.\n", |
5854 | "because of BSSID mismatch: %pM.\n", | 5781 | network->ssid_len, network->ssid, |
5855 | print_ssid(ssid, network->ssid, | ||
5856 | network->ssid_len), | ||
5857 | network->bssid, priv->bssid); | 5782 | network->bssid, priv->bssid); |
5858 | return 0; | 5783 | return 0; |
5859 | } | 5784 | } |
5860 | 5785 | ||
5861 | /* Filter out any incompatible freq / mode combinations */ | 5786 | /* Filter out any incompatible freq / mode combinations */ |
5862 | if (!libipw_is_valid_mode(priv->ieee, network->mode)) { | 5787 | if (!libipw_is_valid_mode(priv->ieee, network->mode)) { |
5863 | IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " | 5788 | IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of invalid frequency/mode combination.\n", |
5864 | "because of invalid frequency/mode " | 5789 | network->ssid_len, network->ssid, |
5865 | "combination.\n", | ||
5866 | print_ssid(ssid, network->ssid, | ||
5867 | network->ssid_len), | ||
5868 | network->bssid); | 5790 | network->bssid); |
5869 | return 0; | 5791 | return 0; |
5870 | } | 5792 | } |
5871 | 5793 | ||
5872 | /* Filter out invalid channel in current GEO */ | 5794 | /* Filter out invalid channel in current GEO */ |
5873 | if (!libipw_is_valid_channel(priv->ieee, network->channel)) { | 5795 | if (!libipw_is_valid_channel(priv->ieee, network->channel)) { |
5874 | IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " | 5796 | IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of invalid channel in current GEO\n", |
5875 | "because of invalid channel in current GEO\n", | 5797 | network->ssid_len, network->ssid, |
5876 | print_ssid(ssid, network->ssid, | ||
5877 | network->ssid_len), | ||
5878 | network->bssid); | 5798 | network->bssid); |
5879 | return 0; | 5799 | return 0; |
5880 | } | 5800 | } |
@@ -5882,20 +5802,15 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5882 | /* Ensure that the rates supported by the driver are compatible with | 5802 | /* Ensure that the rates supported by the driver are compatible with |
5883 | * this AP, including verification of basic rates (mandatory) */ | 5803 | * this AP, including verification of basic rates (mandatory) */ |
5884 | if (!ipw_compatible_rates(priv, network, &rates)) { | 5804 | if (!ipw_compatible_rates(priv, network, &rates)) { |
5885 | IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " | 5805 | IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because configured rate mask excludes AP mandatory rate.\n", |
5886 | "because configured rate mask excludes " | 5806 | network->ssid_len, network->ssid, |
5887 | "AP mandatory rate.\n", | ||
5888 | print_ssid(ssid, network->ssid, | ||
5889 | network->ssid_len), | ||
5890 | network->bssid); | 5807 | network->bssid); |
5891 | return 0; | 5808 | return 0; |
5892 | } | 5809 | } |
5893 | 5810 | ||
5894 | if (rates.num_rates == 0) { | 5811 | if (rates.num_rates == 0) { |
5895 | IPW_DEBUG_ASSOC("Network '%s (%pM)' excluded " | 5812 | IPW_DEBUG_ASSOC("Network '%*pE (%pM)' excluded because of no compatible rates.\n", |
5896 | "because of no compatible rates.\n", | 5813 | network->ssid_len, network->ssid, |
5897 | print_ssid(ssid, network->ssid, | ||
5898 | network->ssid_len), | ||
5899 | network->bssid); | 5814 | network->bssid); |
5900 | return 0; | 5815 | return 0; |
5901 | } | 5816 | } |
@@ -5908,9 +5823,8 @@ static int ipw_best_network(struct ipw_priv *priv, | |||
5908 | ipw_copy_rates(&match->rates, &rates); | 5823 | ipw_copy_rates(&match->rates, &rates); |
5909 | match->network = network; | 5824 | match->network = network; |
5910 | 5825 | ||
5911 | IPW_DEBUG_ASSOC("Network '%s (%pM)' is a viable match.\n", | 5826 | IPW_DEBUG_ASSOC("Network '%*pE (%pM)' is a viable match.\n", |
5912 | print_ssid(ssid, network->ssid, network->ssid_len), | 5827 | network->ssid_len, network->ssid, network->bssid); |
5913 | network->bssid); | ||
5914 | 5828 | ||
5915 | return 1; | 5829 | return 1; |
5916 | } | 5830 | } |
@@ -6152,7 +6066,6 @@ static void ipw_bg_adhoc_check(struct work_struct *work) | |||
6152 | 6066 | ||
6153 | static void ipw_debug_config(struct ipw_priv *priv) | 6067 | static void ipw_debug_config(struct ipw_priv *priv) |
6154 | { | 6068 | { |
6155 | DECLARE_SSID_BUF(ssid); | ||
6156 | IPW_DEBUG_INFO("Scan completed, no valid APs matched " | 6069 | IPW_DEBUG_INFO("Scan completed, no valid APs matched " |
6157 | "[CFG 0x%08X]\n", priv->config); | 6070 | "[CFG 0x%08X]\n", priv->config); |
6158 | if (priv->config & CFG_STATIC_CHANNEL) | 6071 | if (priv->config & CFG_STATIC_CHANNEL) |
@@ -6160,8 +6073,8 @@ static void ipw_debug_config(struct ipw_priv *priv) | |||
6160 | else | 6073 | else |
6161 | IPW_DEBUG_INFO("Channel unlocked.\n"); | 6074 | IPW_DEBUG_INFO("Channel unlocked.\n"); |
6162 | if (priv->config & CFG_STATIC_ESSID) | 6075 | if (priv->config & CFG_STATIC_ESSID) |
6163 | IPW_DEBUG_INFO("ESSID locked to '%s'\n", | 6076 | IPW_DEBUG_INFO("ESSID locked to '%*pE'\n", |
6164 | print_ssid(ssid, priv->essid, priv->essid_len)); | 6077 | priv->essid_len, priv->essid); |
6165 | else | 6078 | else |
6166 | IPW_DEBUG_INFO("ESSID unlocked.\n"); | 6079 | IPW_DEBUG_INFO("ESSID unlocked.\n"); |
6167 | if (priv->config & CFG_STATIC_BSSID) | 6080 | if (priv->config & CFG_STATIC_BSSID) |
@@ -7385,7 +7298,6 @@ static int ipw_associate_network(struct ipw_priv *priv, | |||
7385 | struct ipw_supported_rates *rates, int roaming) | 7298 | struct ipw_supported_rates *rates, int roaming) |
7386 | { | 7299 | { |
7387 | int err; | 7300 | int err; |
7388 | DECLARE_SSID_BUF(ssid); | ||
7389 | 7301 | ||
7390 | if (priv->config & CFG_FIXED_RATE) | 7302 | if (priv->config & CFG_FIXED_RATE) |
7391 | ipw_set_fixed_rate(priv, network->mode); | 7303 | ipw_set_fixed_rate(priv, network->mode); |
@@ -7451,10 +7363,9 @@ static int ipw_associate_network(struct ipw_priv *priv, | |||
7451 | priv->assoc_request.capability &= | 7363 | priv->assoc_request.capability &= |
7452 | ~cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME); | 7364 | ~cpu_to_le16(WLAN_CAPABILITY_SHORT_SLOT_TIME); |
7453 | 7365 | ||
7454 | IPW_DEBUG_ASSOC("%ssociation attempt: '%s', channel %d, " | 7366 | IPW_DEBUG_ASSOC("%ssociation attempt: '%*pE', channel %d, 802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n", |
7455 | "802.11%c [%d], %s[:%s], enc=%s%s%s%c%c\n", | ||
7456 | roaming ? "Rea" : "A", | 7367 | roaming ? "Rea" : "A", |
7457 | print_ssid(ssid, priv->essid, priv->essid_len), | 7368 | priv->essid_len, priv->essid, |
7458 | network->channel, | 7369 | network->channel, |
7459 | ipw_modes[priv->assoc_request.ieee_mode], | 7370 | ipw_modes[priv->assoc_request.ieee_mode], |
7460 | rates->num_rates, | 7371 | rates->num_rates, |
@@ -7553,9 +7464,8 @@ static int ipw_associate_network(struct ipw_priv *priv, | |||
7553 | return err; | 7464 | return err; |
7554 | } | 7465 | } |
7555 | 7466 | ||
7556 | IPW_DEBUG(IPW_DL_STATE, "associating: '%s' %pM\n", | 7467 | IPW_DEBUG(IPW_DL_STATE, "associating: '%*pE' %pM\n", |
7557 | print_ssid(ssid, priv->essid, priv->essid_len), | 7468 | priv->essid_len, priv->essid, priv->bssid); |
7558 | priv->bssid); | ||
7559 | 7469 | ||
7560 | return 0; | 7470 | return 0; |
7561 | } | 7471 | } |
@@ -7645,7 +7555,6 @@ static int ipw_associate(void *data) | |||
7645 | struct ipw_supported_rates *rates; | 7555 | struct ipw_supported_rates *rates; |
7646 | struct list_head *element; | 7556 | struct list_head *element; |
7647 | unsigned long flags; | 7557 | unsigned long flags; |
7648 | DECLARE_SSID_BUF(ssid); | ||
7649 | 7558 | ||
7650 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) { | 7559 | if (priv->ieee->iw_mode == IW_MODE_MONITOR) { |
7651 | IPW_DEBUG_ASSOC("Not attempting association (monitor mode)\n"); | 7560 | IPW_DEBUG_ASSOC("Not attempting association (monitor mode)\n"); |
@@ -7704,10 +7613,8 @@ static int ipw_associate(void *data) | |||
7704 | /* If there are no more slots, expire the oldest */ | 7613 | /* If there are no more slots, expire the oldest */ |
7705 | list_del(&oldest->list); | 7614 | list_del(&oldest->list); |
7706 | target = oldest; | 7615 | target = oldest; |
7707 | IPW_DEBUG_ASSOC("Expired '%s' (%pM) from " | 7616 | IPW_DEBUG_ASSOC("Expired '%*pE' (%pM) from network list.\n", |
7708 | "network list.\n", | 7617 | target->ssid_len, target->ssid, |
7709 | print_ssid(ssid, target->ssid, | ||
7710 | target->ssid_len), | ||
7711 | target->bssid); | 7618 | target->bssid); |
7712 | list_add_tail(&target->list, | 7619 | list_add_tail(&target->list, |
7713 | &priv->ieee->network_free_list); | 7620 | &priv->ieee->network_free_list); |
@@ -9093,7 +9000,6 @@ static int ipw_wx_set_essid(struct net_device *dev, | |||
9093 | { | 9000 | { |
9094 | struct ipw_priv *priv = libipw_priv(dev); | 9001 | struct ipw_priv *priv = libipw_priv(dev); |
9095 | int length; | 9002 | int length; |
9096 | DECLARE_SSID_BUF(ssid); | ||
9097 | 9003 | ||
9098 | mutex_lock(&priv->mutex); | 9004 | mutex_lock(&priv->mutex); |
9099 | 9005 | ||
@@ -9118,8 +9024,7 @@ static int ipw_wx_set_essid(struct net_device *dev, | |||
9118 | return 0; | 9024 | return 0; |
9119 | } | 9025 | } |
9120 | 9026 | ||
9121 | IPW_DEBUG_WX("Setting ESSID: '%s' (%d)\n", | 9027 | IPW_DEBUG_WX("Setting ESSID: '%*pE' (%d)\n", length, extra, length); |
9122 | print_ssid(ssid, extra, length), length); | ||
9123 | 9028 | ||
9124 | priv->essid_len = length; | 9029 | priv->essid_len = length; |
9125 | memcpy(priv->essid, extra, priv->essid_len); | 9030 | memcpy(priv->essid, extra, priv->essid_len); |
@@ -9138,15 +9043,14 @@ static int ipw_wx_get_essid(struct net_device *dev, | |||
9138 | union iwreq_data *wrqu, char *extra) | 9043 | union iwreq_data *wrqu, char *extra) |
9139 | { | 9044 | { |
9140 | struct ipw_priv *priv = libipw_priv(dev); | 9045 | struct ipw_priv *priv = libipw_priv(dev); |
9141 | DECLARE_SSID_BUF(ssid); | ||
9142 | 9046 | ||
9143 | /* If we are associated, trying to associate, or have a statically | 9047 | /* If we are associated, trying to associate, or have a statically |
9144 | * configured ESSID then return that; otherwise return ANY */ | 9048 | * configured ESSID then return that; otherwise return ANY */ |
9145 | mutex_lock(&priv->mutex); | 9049 | mutex_lock(&priv->mutex); |
9146 | if (priv->config & CFG_STATIC_ESSID || | 9050 | if (priv->config & CFG_STATIC_ESSID || |
9147 | priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { | 9051 | priv->status & (STATUS_ASSOCIATED | STATUS_ASSOCIATING)) { |
9148 | IPW_DEBUG_WX("Getting essid: '%s'\n", | 9052 | IPW_DEBUG_WX("Getting essid: '%*pE'\n", |
9149 | print_ssid(ssid, priv->essid, priv->essid_len)); | 9053 | priv->essid_len, priv->essid); |
9150 | memcpy(extra, priv->essid, priv->essid_len); | 9054 | memcpy(extra, priv->essid, priv->essid_len); |
9151 | wrqu->essid.length = priv->essid_len; | 9055 | wrqu->essid.length = priv->essid_len; |
9152 | wrqu->essid.flags = 1; /* active */ | 9056 | wrqu->essid.flags = 1; /* active */ |
diff --git a/drivers/net/wireless/ipw2x00/libipw.h b/drivers/net/wireless/ipw2x00/libipw.h index 5ce2f59d3378..b0571618c2ed 100644 --- a/drivers/net/wireless/ipw2x00/libipw.h +++ b/drivers/net/wireless/ipw2x00/libipw.h | |||
@@ -654,10 +654,6 @@ struct libipw_network { | |||
654 | /* TPC Report - mandatory if spctrm mgmt required */ | 654 | /* TPC Report - mandatory if spctrm mgmt required */ |
655 | struct libipw_tpc_report tpc_report; | 655 | struct libipw_tpc_report tpc_report; |
656 | 656 | ||
657 | /* IBSS DFS - mandatory if spctrm mgmt required and IBSS | ||
658 | * NOTE: This is variable length and so must be allocated dynamically */ | ||
659 | struct libipw_ibss_dfs *ibss_dfs; | ||
660 | |||
661 | /* Channel Switch Announcement - optional if spctrm mgmt required */ | 657 | /* Channel Switch Announcement - optional if spctrm mgmt required */ |
662 | struct libipw_csa csa; | 658 | struct libipw_csa csa; |
663 | 659 | ||
@@ -970,7 +966,6 @@ int libipw_rx(struct libipw_device *ieee, struct sk_buff *skb, | |||
970 | /* make sure to set stats->len */ | 966 | /* make sure to set stats->len */ |
971 | void libipw_rx_mgt(struct libipw_device *ieee, struct libipw_hdr_4addr *header, | 967 | void libipw_rx_mgt(struct libipw_device *ieee, struct libipw_hdr_4addr *header, |
972 | struct libipw_rx_stats *stats); | 968 | struct libipw_rx_stats *stats); |
973 | void libipw_network_reset(struct libipw_network *network); | ||
974 | 969 | ||
975 | /* libipw_geo.c */ | 970 | /* libipw_geo.c */ |
976 | const struct libipw_geo *libipw_get_geo(struct libipw_device *ieee); | 971 | const struct libipw_geo *libipw_get_geo(struct libipw_device *ieee); |
diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c index 5f31b72a4921..60f28740f6af 100644 --- a/drivers/net/wireless/ipw2x00/libipw_module.c +++ b/drivers/net/wireless/ipw2x00/libipw_module.c | |||
@@ -84,25 +84,12 @@ static int libipw_networks_allocate(struct libipw_device *ieee) | |||
84 | return 0; | 84 | return 0; |
85 | } | 85 | } |
86 | 86 | ||
87 | void libipw_network_reset(struct libipw_network *network) | ||
88 | { | ||
89 | if (!network) | ||
90 | return; | ||
91 | |||
92 | if (network->ibss_dfs) { | ||
93 | kfree(network->ibss_dfs); | ||
94 | network->ibss_dfs = NULL; | ||
95 | } | ||
96 | } | ||
97 | |||
98 | static inline void libipw_networks_free(struct libipw_device *ieee) | 87 | static inline void libipw_networks_free(struct libipw_device *ieee) |
99 | { | 88 | { |
100 | int i; | 89 | int i; |
101 | 90 | ||
102 | for (i = 0; i < MAX_NETWORK_COUNT; i++) { | 91 | for (i = 0; i < MAX_NETWORK_COUNT; i++) |
103 | kfree(ieee->networks[i]->ibss_dfs); | ||
104 | kfree(ieee->networks[i]); | 92 | kfree(ieee->networks[i]); |
105 | } | ||
106 | } | 93 | } |
107 | 94 | ||
108 | void libipw_networks_age(struct libipw_device *ieee, | 95 | void libipw_networks_age(struct libipw_device *ieee, |
diff --git a/drivers/net/wireless/ipw2x00/libipw_rx.c b/drivers/net/wireless/ipw2x00/libipw_rx.c index a586a85bfcfe..a6877dd6ba73 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c | |||
@@ -1120,7 +1120,6 @@ static int libipw_parse_info_param(struct libipw_info_element | |||
1120 | *info_element, u16 length, | 1120 | *info_element, u16 length, |
1121 | struct libipw_network *network) | 1121 | struct libipw_network *network) |
1122 | { | 1122 | { |
1123 | DECLARE_SSID_BUF(ssid); | ||
1124 | u8 i; | 1123 | u8 i; |
1125 | #ifdef CONFIG_LIBIPW_DEBUG | 1124 | #ifdef CONFIG_LIBIPW_DEBUG |
1126 | char rates_str[64]; | 1125 | char rates_str[64]; |
@@ -1151,10 +1150,9 @@ static int libipw_parse_info_param(struct libipw_info_element | |||
1151 | memset(network->ssid + network->ssid_len, 0, | 1150 | memset(network->ssid + network->ssid_len, 0, |
1152 | IW_ESSID_MAX_SIZE - network->ssid_len); | 1151 | IW_ESSID_MAX_SIZE - network->ssid_len); |
1153 | 1152 | ||
1154 | LIBIPW_DEBUG_MGMT("WLAN_EID_SSID: '%s' len=%d.\n", | 1153 | LIBIPW_DEBUG_MGMT("WLAN_EID_SSID: '%*pE' len=%d.\n", |
1155 | print_ssid(ssid, network->ssid, | 1154 | network->ssid_len, network->ssid, |
1156 | network->ssid_len), | 1155 | network->ssid_len); |
1157 | network->ssid_len); | ||
1158 | break; | 1156 | break; |
1159 | 1157 | ||
1160 | case WLAN_EID_SUPP_RATES: | 1158 | case WLAN_EID_SUPP_RATES: |
@@ -1300,13 +1298,6 @@ static int libipw_parse_info_param(struct libipw_info_element | |||
1300 | break; | 1298 | break; |
1301 | 1299 | ||
1302 | case WLAN_EID_IBSS_DFS: | 1300 | case WLAN_EID_IBSS_DFS: |
1303 | if (network->ibss_dfs) | ||
1304 | break; | ||
1305 | network->ibss_dfs = kmemdup(info_element->data, | ||
1306 | info_element->len, | ||
1307 | GFP_ATOMIC); | ||
1308 | if (!network->ibss_dfs) | ||
1309 | return 1; | ||
1310 | network->flags |= NETWORK_HAS_IBSS_DFS; | 1301 | network->flags |= NETWORK_HAS_IBSS_DFS; |
1311 | break; | 1302 | break; |
1312 | 1303 | ||
@@ -1337,9 +1328,7 @@ static int libipw_parse_info_param(struct libipw_info_element | |||
1337 | static int libipw_handle_assoc_resp(struct libipw_device *ieee, struct libipw_assoc_response | 1328 | static int libipw_handle_assoc_resp(struct libipw_device *ieee, struct libipw_assoc_response |
1338 | *frame, struct libipw_rx_stats *stats) | 1329 | *frame, struct libipw_rx_stats *stats) |
1339 | { | 1330 | { |
1340 | struct libipw_network network_resp = { | 1331 | struct libipw_network network_resp = { }; |
1341 | .ibss_dfs = NULL, | ||
1342 | }; | ||
1343 | struct libipw_network *network = &network_resp; | 1332 | struct libipw_network *network = &network_resp; |
1344 | struct net_device *dev = ieee->dev; | 1333 | struct net_device *dev = ieee->dev; |
1345 | 1334 | ||
@@ -1399,8 +1388,6 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r | |||
1399 | struct libipw_network *network, | 1388 | struct libipw_network *network, |
1400 | struct libipw_rx_stats *stats) | 1389 | struct libipw_rx_stats *stats) |
1401 | { | 1390 | { |
1402 | DECLARE_SSID_BUF(ssid); | ||
1403 | |||
1404 | network->qos_data.active = 0; | 1391 | network->qos_data.active = 0; |
1405 | network->qos_data.supported = 0; | 1392 | network->qos_data.supported = 0; |
1406 | network->qos_data.param_count = 0; | 1393 | network->qos_data.param_count = 0; |
@@ -1447,11 +1434,9 @@ static int libipw_network_init(struct libipw_device *ieee, struct libipw_probe_r | |||
1447 | } | 1434 | } |
1448 | 1435 | ||
1449 | if (network->mode == 0) { | 1436 | if (network->mode == 0) { |
1450 | LIBIPW_DEBUG_SCAN("Filtered out '%s (%pM)' " | 1437 | LIBIPW_DEBUG_SCAN("Filtered out '%*pE (%pM)' network.\n", |
1451 | "network.\n", | 1438 | network->ssid_len, network->ssid, |
1452 | print_ssid(ssid, network->ssid, | 1439 | network->bssid); |
1453 | network->ssid_len), | ||
1454 | network->bssid); | ||
1455 | return 1; | 1440 | return 1; |
1456 | } | 1441 | } |
1457 | 1442 | ||
@@ -1478,9 +1463,6 @@ static void update_network(struct libipw_network *dst, | |||
1478 | int qos_active; | 1463 | int qos_active; |
1479 | u8 old_param; | 1464 | u8 old_param; |
1480 | 1465 | ||
1481 | libipw_network_reset(dst); | ||
1482 | dst->ibss_dfs = src->ibss_dfs; | ||
1483 | |||
1484 | /* We only update the statistics if they were created by receiving | 1466 | /* We only update the statistics if they were created by receiving |
1485 | * the network information on the actual channel the network is on. | 1467 | * the network information on the actual channel the network is on. |
1486 | * | 1468 | * |
@@ -1554,20 +1536,16 @@ static void libipw_process_probe_response(struct libipw_device | |||
1554 | *stats) | 1536 | *stats) |
1555 | { | 1537 | { |
1556 | struct net_device *dev = ieee->dev; | 1538 | struct net_device *dev = ieee->dev; |
1557 | struct libipw_network network = { | 1539 | struct libipw_network network = { }; |
1558 | .ibss_dfs = NULL, | ||
1559 | }; | ||
1560 | struct libipw_network *target; | 1540 | struct libipw_network *target; |
1561 | struct libipw_network *oldest = NULL; | 1541 | struct libipw_network *oldest = NULL; |
1562 | #ifdef CONFIG_LIBIPW_DEBUG | 1542 | #ifdef CONFIG_LIBIPW_DEBUG |
1563 | struct libipw_info_element *info_element = beacon->info_element; | 1543 | struct libipw_info_element *info_element = beacon->info_element; |
1564 | #endif | 1544 | #endif |
1565 | unsigned long flags; | 1545 | unsigned long flags; |
1566 | DECLARE_SSID_BUF(ssid); | ||
1567 | 1546 | ||
1568 | LIBIPW_DEBUG_SCAN("'%s' (%pM" | 1547 | LIBIPW_DEBUG_SCAN("'%*pE' (%pM): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", |
1569 | "): %c%c%c%c %c%c%c%c-%c%c%c%c %c%c%c%c\n", | 1548 | info_element->len, info_element->data, |
1570 | print_ssid(ssid, info_element->data, info_element->len), | ||
1571 | beacon->header.addr3, | 1549 | beacon->header.addr3, |
1572 | (beacon->capability & cpu_to_le16(1 << 0xf)) ? '1' : '0', | 1550 | (beacon->capability & cpu_to_le16(1 << 0xf)) ? '1' : '0', |
1573 | (beacon->capability & cpu_to_le16(1 << 0xe)) ? '1' : '0', | 1551 | (beacon->capability & cpu_to_le16(1 << 0xe)) ? '1' : '0', |
@@ -1587,12 +1565,11 @@ static void libipw_process_probe_response(struct libipw_device | |||
1587 | (beacon->capability & cpu_to_le16(1 << 0x0)) ? '1' : '0'); | 1565 | (beacon->capability & cpu_to_le16(1 << 0x0)) ? '1' : '0'); |
1588 | 1566 | ||
1589 | if (libipw_network_init(ieee, beacon, &network, stats)) { | 1567 | if (libipw_network_init(ieee, beacon, &network, stats)) { |
1590 | LIBIPW_DEBUG_SCAN("Dropped '%s' (%pM) via %s.\n", | 1568 | LIBIPW_DEBUG_SCAN("Dropped '%*pE' (%pM) via %s.\n", |
1591 | print_ssid(ssid, info_element->data, | 1569 | info_element->len, info_element->data, |
1592 | info_element->len), | 1570 | beacon->header.addr3, |
1593 | beacon->header.addr3, | 1571 | is_beacon(beacon->header.frame_ctl) ? |
1594 | is_beacon(beacon->header.frame_ctl) ? | 1572 | "BEACON" : "PROBE RESPONSE"); |
1595 | "BEACON" : "PROBE RESPONSE"); | ||
1596 | return; | 1573 | return; |
1597 | } | 1574 | } |
1598 | 1575 | ||
@@ -1624,12 +1601,9 @@ static void libipw_process_probe_response(struct libipw_device | |||
1624 | /* If there are no more slots, expire the oldest */ | 1601 | /* If there are no more slots, expire the oldest */ |
1625 | list_del(&oldest->list); | 1602 | list_del(&oldest->list); |
1626 | target = oldest; | 1603 | target = oldest; |
1627 | LIBIPW_DEBUG_SCAN("Expired '%s' (%pM) from " | 1604 | LIBIPW_DEBUG_SCAN("Expired '%*pE' (%pM) from network list.\n", |
1628 | "network list.\n", | 1605 | target->ssid_len, target->ssid, |
1629 | print_ssid(ssid, target->ssid, | 1606 | target->bssid); |
1630 | target->ssid_len), | ||
1631 | target->bssid); | ||
1632 | libipw_network_reset(target); | ||
1633 | } else { | 1607 | } else { |
1634 | /* Otherwise just pull from the free list */ | 1608 | /* Otherwise just pull from the free list */ |
1635 | target = list_entry(ieee->network_free_list.next, | 1609 | target = list_entry(ieee->network_free_list.next, |
@@ -1638,25 +1612,21 @@ static void libipw_process_probe_response(struct libipw_device | |||
1638 | } | 1612 | } |
1639 | 1613 | ||
1640 | #ifdef CONFIG_LIBIPW_DEBUG | 1614 | #ifdef CONFIG_LIBIPW_DEBUG |
1641 | LIBIPW_DEBUG_SCAN("Adding '%s' (%pM) via %s.\n", | 1615 | LIBIPW_DEBUG_SCAN("Adding '%*pE' (%pM) via %s.\n", |
1642 | print_ssid(ssid, network.ssid, | 1616 | network.ssid_len, network.ssid, |
1643 | network.ssid_len), | 1617 | network.bssid, |
1644 | network.bssid, | 1618 | is_beacon(beacon->header.frame_ctl) ? |
1645 | is_beacon(beacon->header.frame_ctl) ? | 1619 | "BEACON" : "PROBE RESPONSE"); |
1646 | "BEACON" : "PROBE RESPONSE"); | ||
1647 | #endif | 1620 | #endif |
1648 | memcpy(target, &network, sizeof(*target)); | 1621 | memcpy(target, &network, sizeof(*target)); |
1649 | network.ibss_dfs = NULL; | ||
1650 | list_add_tail(&target->list, &ieee->network_list); | 1622 | list_add_tail(&target->list, &ieee->network_list); |
1651 | } else { | 1623 | } else { |
1652 | LIBIPW_DEBUG_SCAN("Updating '%s' (%pM) via %s.\n", | 1624 | LIBIPW_DEBUG_SCAN("Updating '%*pE' (%pM) via %s.\n", |
1653 | print_ssid(ssid, target->ssid, | 1625 | target->ssid_len, target->ssid, |
1654 | target->ssid_len), | 1626 | target->bssid, |
1655 | target->bssid, | 1627 | is_beacon(beacon->header.frame_ctl) ? |
1656 | is_beacon(beacon->header.frame_ctl) ? | 1628 | "BEACON" : "PROBE RESPONSE"); |
1657 | "BEACON" : "PROBE RESPONSE"); | ||
1658 | update_network(target, &network); | 1629 | update_network(target, &network); |
1659 | network.ibss_dfs = NULL; | ||
1660 | } | 1630 | } |
1661 | 1631 | ||
1662 | spin_unlock_irqrestore(&ieee->lock, flags); | 1632 | spin_unlock_irqrestore(&ieee->lock, flags); |
diff --git a/drivers/net/wireless/ipw2x00/libipw_wx.c b/drivers/net/wireless/ipw2x00/libipw_wx.c index 54aba4744438..dd29f46d086b 100644 --- a/drivers/net/wireless/ipw2x00/libipw_wx.c +++ b/drivers/net/wireless/ipw2x00/libipw_wx.c | |||
@@ -272,7 +272,6 @@ int libipw_wx_get_scan(struct libipw_device *ieee, | |||
272 | char *ev = extra; | 272 | char *ev = extra; |
273 | char *stop = ev + wrqu->data.length; | 273 | char *stop = ev + wrqu->data.length; |
274 | int i = 0; | 274 | int i = 0; |
275 | DECLARE_SSID_BUF(ssid); | ||
276 | 275 | ||
277 | LIBIPW_DEBUG_WX("Getting scan\n"); | 276 | LIBIPW_DEBUG_WX("Getting scan\n"); |
278 | 277 | ||
@@ -290,12 +289,10 @@ int libipw_wx_get_scan(struct libipw_device *ieee, | |||
290 | ev = libipw_translate_scan(ieee, ev, stop, network, | 289 | ev = libipw_translate_scan(ieee, ev, stop, network, |
291 | info); | 290 | info); |
292 | else { | 291 | else { |
293 | LIBIPW_DEBUG_SCAN("Not showing network '%s (" | 292 | LIBIPW_DEBUG_SCAN("Not showing network '%*pE (%pM)' due to age (%ums).\n", |
294 | "%pM)' due to age (%ums).\n", | 293 | network->ssid_len, network->ssid, |
295 | print_ssid(ssid, network->ssid, | 294 | network->bssid, |
296 | network->ssid_len), | 295 | elapsed_jiffies_msecs( |
297 | network->bssid, | ||
298 | elapsed_jiffies_msecs( | ||
299 | network->last_scanned)); | 296 | network->last_scanned)); |
300 | } | 297 | } |
301 | } | 298 | } |
@@ -322,7 +319,6 @@ int libipw_wx_set_encode(struct libipw_device *ieee, | |||
322 | int i, key, key_provided, len; | 319 | int i, key, key_provided, len; |
323 | struct lib80211_crypt_data **crypt; | 320 | struct lib80211_crypt_data **crypt; |
324 | int host_crypto = ieee->host_encrypt || ieee->host_decrypt; | 321 | int host_crypto = ieee->host_encrypt || ieee->host_decrypt; |
325 | DECLARE_SSID_BUF(ssid); | ||
326 | 322 | ||
327 | LIBIPW_DEBUG_WX("SET_ENCODE\n"); | 323 | LIBIPW_DEBUG_WX("SET_ENCODE\n"); |
328 | 324 | ||
@@ -417,8 +413,8 @@ int libipw_wx_set_encode(struct libipw_device *ieee, | |||
417 | if (len > erq->length) | 413 | if (len > erq->length) |
418 | memset(sec.keys[key] + erq->length, 0, | 414 | memset(sec.keys[key] + erq->length, 0, |
419 | len - erq->length); | 415 | len - erq->length); |
420 | LIBIPW_DEBUG_WX("Setting key %d to '%s' (%d:%d bytes)\n", | 416 | LIBIPW_DEBUG_WX("Setting key %d to '%*pE' (%d:%d bytes)\n", |
421 | key, print_ssid(ssid, sec.keys[key], len), | 417 | key, len, sec.keys[key], |
422 | erq->length, len); | 418 | erq->length, len); |
423 | sec.key_sizes[key] = len; | 419 | sec.key_sizes[key] = len; |
424 | if (*crypt) | 420 | if (*crypt) |
diff --git a/drivers/net/wireless/iwlegacy/4965-mac.c b/drivers/net/wireless/iwlegacy/4965-mac.c index 26fec54dcd03..2748fde4b90c 100644 --- a/drivers/net/wireless/iwlegacy/4965-mac.c +++ b/drivers/net/wireless/iwlegacy/4965-mac.c | |||
@@ -6063,7 +6063,7 @@ il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
6063 | } | 6063 | } |
6064 | 6064 | ||
6065 | void | 6065 | void |
6066 | il4965_mac_channel_switch(struct ieee80211_hw *hw, | 6066 | il4965_mac_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
6067 | struct ieee80211_channel_switch *ch_switch) | 6067 | struct ieee80211_channel_switch *ch_switch) |
6068 | { | 6068 | { |
6069 | struct il_priv *il = hw->priv; | 6069 | struct il_priv *il = hw->priv; |
diff --git a/drivers/net/wireless/iwlegacy/4965.h b/drivers/net/wireless/iwlegacy/4965.h index 337dfcf3bbde..3a57f71b8ed5 100644 --- a/drivers/net/wireless/iwlegacy/4965.h +++ b/drivers/net/wireless/iwlegacy/4965.h | |||
@@ -187,8 +187,9 @@ int il4965_mac_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
187 | u8 buf_size); | 187 | u8 buf_size); |
188 | int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 188 | int il4965_mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
189 | struct ieee80211_sta *sta); | 189 | struct ieee80211_sta *sta); |
190 | void il4965_mac_channel_switch(struct ieee80211_hw *hw, | 190 | void |
191 | struct ieee80211_channel_switch *ch_switch); | 191 | il4965_mac_channel_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
192 | struct ieee80211_channel_switch *ch_switch); | ||
192 | 193 | ||
193 | void il4965_led_enable(struct il_priv *il); | 194 | void il4965_led_enable(struct il_priv *il); |
194 | 195 | ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/mac80211.c b/drivers/net/wireless/iwlwifi/dvm/mac80211.c index cae692ff1013..47e64e8b9517 100644 --- a/drivers/net/wireless/iwlwifi/dvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/dvm/mac80211.c | |||
@@ -941,6 +941,7 @@ static int iwlagn_mac_sta_state(struct ieee80211_hw *hw, | |||
941 | } | 941 | } |
942 | 942 | ||
943 | static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, | 943 | static void iwlagn_mac_channel_switch(struct ieee80211_hw *hw, |
944 | struct ieee80211_vif *vif, | ||
944 | struct ieee80211_channel_switch *ch_switch) | 945 | struct ieee80211_channel_switch *ch_switch) |
945 | { | 946 | { |
946 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); | 947 | struct iwl_priv *priv = IWL_MAC80211_GET_DVM(hw); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c index 8c96e5af75f7..f12b43d65f66 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/iwlwifi/mvm/fw.c | |||
@@ -288,7 +288,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
288 | 288 | ||
289 | lockdep_assert_held(&mvm->mutex); | 289 | lockdep_assert_held(&mvm->mutex); |
290 | 290 | ||
291 | if (WARN_ON_ONCE(mvm->init_ucode_complete)) | 291 | if (WARN_ON_ONCE(mvm->init_ucode_complete || mvm->calibrating)) |
292 | return 0; | 292 | return 0; |
293 | 293 | ||
294 | iwl_init_notification_wait(&mvm->notif_wait, | 294 | iwl_init_notification_wait(&mvm->notif_wait, |
@@ -338,6 +338,8 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
338 | goto out; | 338 | goto out; |
339 | } | 339 | } |
340 | 340 | ||
341 | mvm->calibrating = true; | ||
342 | |||
341 | /* Send TX valid antennas before triggering calibrations */ | 343 | /* Send TX valid antennas before triggering calibrations */ |
342 | ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant); | 344 | ret = iwl_send_tx_ant_cfg(mvm, mvm->fw->valid_tx_ant); |
343 | if (ret) | 345 | if (ret) |
@@ -362,11 +364,17 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm) | |||
362 | MVM_UCODE_CALIB_TIMEOUT); | 364 | MVM_UCODE_CALIB_TIMEOUT); |
363 | if (!ret) | 365 | if (!ret) |
364 | mvm->init_ucode_complete = true; | 366 | mvm->init_ucode_complete = true; |
367 | |||
368 | if (ret && iwl_mvm_is_radio_killed(mvm)) { | ||
369 | IWL_DEBUG_RF_KILL(mvm, "RFKILL while calibrating.\n"); | ||
370 | ret = 1; | ||
371 | } | ||
365 | goto out; | 372 | goto out; |
366 | 373 | ||
367 | error: | 374 | error: |
368 | iwl_remove_notification(&mvm->notif_wait, &calib_wait); | 375 | iwl_remove_notification(&mvm->notif_wait, &calib_wait); |
369 | out: | 376 | out: |
377 | mvm->calibrating = false; | ||
370 | if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) { | 378 | if (iwlmvm_mod_params.init_dbg && !mvm->nvm_data) { |
371 | /* we want to debug INIT and we have no NVM - fake */ | 379 | /* we want to debug INIT and we have no NVM - fake */ |
372 | mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) + | 380 | mvm->nvm_data = kzalloc(sizeof(struct iwl_nvm_data) + |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index ed2c219cf543..92e1810864b1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -850,6 +850,7 @@ static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) | |||
850 | 850 | ||
851 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 851 | mvm->scan_status = IWL_MVM_SCAN_NONE; |
852 | mvm->ps_disabled = false; | 852 | mvm->ps_disabled = false; |
853 | mvm->calibrating = false; | ||
853 | 854 | ||
854 | /* just in case one was running */ | 855 | /* just in case one was running */ |
855 | ieee80211_remain_on_channel_expired(mvm->hw); | 856 | ieee80211_remain_on_channel_expired(mvm->hw); |
@@ -920,9 +921,8 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw) | |||
920 | return ret; | 921 | return ret; |
921 | } | 922 | } |
922 | 923 | ||
923 | static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw) | 924 | static void iwl_mvm_restart_complete(struct iwl_mvm *mvm) |
924 | { | 925 | { |
925 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
926 | int ret; | 926 | int ret; |
927 | 927 | ||
928 | mutex_lock(&mvm->mutex); | 928 | mutex_lock(&mvm->mutex); |
@@ -940,6 +940,21 @@ static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw) | |||
940 | mutex_unlock(&mvm->mutex); | 940 | mutex_unlock(&mvm->mutex); |
941 | } | 941 | } |
942 | 942 | ||
943 | static void | ||
944 | iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw, | ||
945 | enum ieee80211_reconfig_type reconfig_type) | ||
946 | { | ||
947 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
948 | |||
949 | switch (reconfig_type) { | ||
950 | case IEEE80211_RECONFIG_TYPE_RESTART: | ||
951 | iwl_mvm_restart_complete(mvm); | ||
952 | break; | ||
953 | case IEEE80211_RECONFIG_TYPE_SUSPEND: | ||
954 | break; | ||
955 | } | ||
956 | } | ||
957 | |||
943 | void __iwl_mvm_mac_stop(struct iwl_mvm *mvm) | 958 | void __iwl_mvm_mac_stop(struct iwl_mvm *mvm) |
944 | { | 959 | { |
945 | lockdep_assert_held(&mvm->mutex); | 960 | lockdep_assert_held(&mvm->mutex); |
@@ -3083,7 +3098,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = { | |||
3083 | .tx = iwl_mvm_mac_tx, | 3098 | .tx = iwl_mvm_mac_tx, |
3084 | .ampdu_action = iwl_mvm_mac_ampdu_action, | 3099 | .ampdu_action = iwl_mvm_mac_ampdu_action, |
3085 | .start = iwl_mvm_mac_start, | 3100 | .start = iwl_mvm_mac_start, |
3086 | .restart_complete = iwl_mvm_mac_restart_complete, | 3101 | .reconfig_complete = iwl_mvm_mac_reconfig_complete, |
3087 | .stop = iwl_mvm_mac_stop, | 3102 | .stop = iwl_mvm_mac_stop, |
3088 | .add_interface = iwl_mvm_mac_add_interface, | 3103 | .add_interface = iwl_mvm_mac_add_interface, |
3089 | .remove_interface = iwl_mvm_mac_remove_interface, | 3104 | .remove_interface = iwl_mvm_mac_remove_interface, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h index 7d2c5289464b..09b49b407a5b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -548,6 +548,7 @@ struct iwl_mvm { | |||
548 | enum iwl_ucode_type cur_ucode; | 548 | enum iwl_ucode_type cur_ucode; |
549 | bool ucode_loaded; | 549 | bool ucode_loaded; |
550 | bool init_ucode_complete; | 550 | bool init_ucode_complete; |
551 | bool calibrating; | ||
551 | u32 error_event_table; | 552 | u32 error_event_table; |
552 | u32 log_event_table; | 553 | u32 log_event_table; |
553 | u32 umac_error_event_table; | 554 | u32 umac_error_event_table; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 8664f617f6e7..53a5a29897b4 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -429,6 +429,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
429 | } | 429 | } |
430 | mvm->sf_state = SF_UNINIT; | 430 | mvm->sf_state = SF_UNINIT; |
431 | mvm->low_latency_agg_frame_limit = 6; | 431 | mvm->low_latency_agg_frame_limit = 6; |
432 | mvm->cur_ucode = IWL_UCODE_INIT; | ||
432 | 433 | ||
433 | mutex_init(&mvm->mutex); | 434 | mutex_init(&mvm->mutex); |
434 | mutex_init(&mvm->d0i3_suspend_mutex); | 435 | mutex_init(&mvm->d0i3_suspend_mutex); |
@@ -760,6 +761,7 @@ void iwl_mvm_set_hw_ctkill_state(struct iwl_mvm *mvm, bool state) | |||
760 | static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | 761 | static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) |
761 | { | 762 | { |
762 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); | 763 | struct iwl_mvm *mvm = IWL_OP_MODE_GET_MVM(op_mode); |
764 | bool calibrating = ACCESS_ONCE(mvm->calibrating); | ||
763 | 765 | ||
764 | if (state) | 766 | if (state) |
765 | set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); | 767 | set_bit(IWL_MVM_STATUS_HW_RFKILL, &mvm->status); |
@@ -768,7 +770,15 @@ static bool iwl_mvm_set_hw_rfkill_state(struct iwl_op_mode *op_mode, bool state) | |||
768 | 770 | ||
769 | wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm)); | 771 | wiphy_rfkill_set_hw_state(mvm->hw->wiphy, iwl_mvm_is_radio_killed(mvm)); |
770 | 772 | ||
771 | return state && mvm->cur_ucode != IWL_UCODE_INIT; | 773 | /* iwl_run_init_mvm_ucode is waiting for results, abort it */ |
774 | if (calibrating) | ||
775 | iwl_abort_notification_waits(&mvm->notif_wait); | ||
776 | |||
777 | /* | ||
778 | * Stop the device if we run OPERATIONAL firmware or if we are in the | ||
779 | * middle of the calibrations. | ||
780 | */ | ||
781 | return state && (mvm->cur_ucode != IWL_UCODE_INIT || calibrating); | ||
772 | } | 782 | } |
773 | 783 | ||
774 | static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) | 784 | static void iwl_mvm_free_skb(struct iwl_op_mode *op_mode, struct sk_buff *skb) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index 5cd59a43e1da..fb2a8628b8fc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -603,16 +603,6 @@ static int iwl_mvm_cancel_regular_scan(struct iwl_mvm *mvm) | |||
603 | SCAN_COMPLETE_NOTIFICATION }; | 603 | SCAN_COMPLETE_NOTIFICATION }; |
604 | int ret; | 604 | int ret; |
605 | 605 | ||
606 | if (mvm->scan_status == IWL_MVM_SCAN_NONE) | ||
607 | return 0; | ||
608 | |||
609 | if (iwl_mvm_is_radio_killed(mvm)) { | ||
610 | ieee80211_scan_completed(mvm->hw, true); | ||
611 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | ||
612 | mvm->scan_status = IWL_MVM_SCAN_NONE; | ||
613 | return 0; | ||
614 | } | ||
615 | |||
616 | iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort, | 606 | iwl_init_notification_wait(&mvm->notif_wait, &wait_scan_abort, |
617 | scan_abort_notif, | 607 | scan_abort_notif, |
618 | ARRAY_SIZE(scan_abort_notif), | 608 | ARRAY_SIZE(scan_abort_notif), |
@@ -1431,6 +1421,16 @@ int iwl_mvm_unified_sched_scan_lmac(struct iwl_mvm *mvm, | |||
1431 | 1421 | ||
1432 | int iwl_mvm_cancel_scan(struct iwl_mvm *mvm) | 1422 | int iwl_mvm_cancel_scan(struct iwl_mvm *mvm) |
1433 | { | 1423 | { |
1424 | if (mvm->scan_status == IWL_MVM_SCAN_NONE) | ||
1425 | return 0; | ||
1426 | |||
1427 | if (iwl_mvm_is_radio_killed(mvm)) { | ||
1428 | ieee80211_scan_completed(mvm->hw, true); | ||
1429 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | ||
1430 | mvm->scan_status = IWL_MVM_SCAN_NONE; | ||
1431 | return 0; | ||
1432 | } | ||
1433 | |||
1434 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) | 1434 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) |
1435 | return iwl_mvm_scan_offload_stop(mvm, true); | 1435 | return iwl_mvm_scan_offload_stop(mvm, true); |
1436 | return iwl_mvm_cancel_regular_scan(mvm); | 1436 | return iwl_mvm_cancel_regular_scan(mvm); |
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 12cb427b742a..ee2ec516e30c 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -916,7 +916,8 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
916 | * restart. So don't process again if the device is | 916 | * restart. So don't process again if the device is |
917 | * already dead. | 917 | * already dead. |
918 | */ | 918 | */ |
919 | if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) { | 919 | if (test_and_clear_bit(STATUS_DEVICE_ENABLED, &trans->status)) { |
920 | IWL_DEBUG_INFO(trans, "DEVICE_ENABLED bit was set and is now cleared\n"); | ||
920 | iwl_pcie_tx_stop(trans); | 921 | iwl_pcie_tx_stop(trans); |
921 | iwl_pcie_rx_stop(trans); | 922 | iwl_pcie_rx_stop(trans); |
922 | 923 | ||
@@ -946,7 +947,6 @@ static void iwl_trans_pcie_stop_device(struct iwl_trans *trans) | |||
946 | /* clear all status bits */ | 947 | /* clear all status bits */ |
947 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); | 948 | clear_bit(STATUS_SYNC_HCMD_ACTIVE, &trans->status); |
948 | clear_bit(STATUS_INT_ENABLED, &trans->status); | 949 | clear_bit(STATUS_INT_ENABLED, &trans->status); |
949 | clear_bit(STATUS_DEVICE_ENABLED, &trans->status); | ||
950 | clear_bit(STATUS_TPOWER_PMI, &trans->status); | 950 | clear_bit(STATUS_TPOWER_PMI, &trans->status); |
951 | clear_bit(STATUS_RFKILL, &trans->status); | 951 | clear_bit(STATUS_RFKILL, &trans->status); |
952 | 952 | ||
@@ -1906,8 +1906,7 @@ static u32 iwl_trans_pcie_dump_prph(struct iwl_trans *trans, | |||
1906 | int reg; | 1906 | int reg; |
1907 | __le32 *val; | 1907 | __le32 *val; |
1908 | 1908 | ||
1909 | prph_len += sizeof(*data) + sizeof(*prph) + | 1909 | prph_len += sizeof(**data) + sizeof(*prph) + num_bytes_in_chunk; |
1910 | num_bytes_in_chunk; | ||
1911 | 1910 | ||
1912 | (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH); | 1911 | (*data)->type = cpu_to_le32(IWL_FW_ERROR_DUMP_PRPH); |
1913 | (*data)->len = cpu_to_le32(sizeof(*prph) + | 1912 | (*data)->len = cpu_to_le32(sizeof(*prph) + |
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c index 818b1edaaa9a..34f09ef90bb3 100644 --- a/drivers/net/wireless/libertas/cfg.c +++ b/drivers/net/wireless/libertas/cfg.c | |||
@@ -590,7 +590,6 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, | |||
590 | int chan_no = -1; | 590 | int chan_no = -1; |
591 | const u8 *ssid = NULL; | 591 | const u8 *ssid = NULL; |
592 | u8 ssid_len = 0; | 592 | u8 ssid_len = 0; |
593 | DECLARE_SSID_BUF(ssid_buf); | ||
594 | 593 | ||
595 | int len = get_unaligned_le16(pos); | 594 | int len = get_unaligned_le16(pos); |
596 | pos += 2; | 595 | pos += 2; |
@@ -644,10 +643,8 @@ static int lbs_ret_scan(struct lbs_private *priv, unsigned long dummy, | |||
644 | struct ieee80211_channel *channel = | 643 | struct ieee80211_channel *channel = |
645 | ieee80211_get_channel(wiphy, freq); | 644 | ieee80211_get_channel(wiphy, freq); |
646 | 645 | ||
647 | lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %s, " | 646 | lbs_deb_scan("scan: %pM, capa %04x, chan %2d, %*pE, %d dBm\n", |
648 | "%d dBm\n", | 647 | bssid, capa, chan_no, ssid_len, ssid, |
649 | bssid, capa, chan_no, | ||
650 | print_ssid(ssid_buf, ssid, ssid_len), | ||
651 | LBS_SCAN_RSSI_TO_MBM(rssi)/100); | 648 | LBS_SCAN_RSSI_TO_MBM(rssi)/100); |
652 | 649 | ||
653 | if (channel && | 650 | if (channel && |
@@ -1984,7 +1981,6 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev, | |||
1984 | struct lbs_private *priv = wiphy_priv(wiphy); | 1981 | struct lbs_private *priv = wiphy_priv(wiphy); |
1985 | int ret = 0; | 1982 | int ret = 0; |
1986 | struct cfg80211_bss *bss; | 1983 | struct cfg80211_bss *bss; |
1987 | DECLARE_SSID_BUF(ssid_buf); | ||
1988 | 1984 | ||
1989 | if (dev == priv->mesh_dev) | 1985 | if (dev == priv->mesh_dev) |
1990 | return -EOPNOTSUPP; | 1986 | return -EOPNOTSUPP; |
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c index 01a67f62696f..d0c881dd5846 100644 --- a/drivers/net/wireless/libertas/mesh.c +++ b/drivers/net/wireless/libertas/mesh.c | |||
@@ -93,7 +93,6 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action, | |||
93 | { | 93 | { |
94 | struct cmd_ds_mesh_config cmd; | 94 | struct cmd_ds_mesh_config cmd; |
95 | struct mrvl_meshie *ie; | 95 | struct mrvl_meshie *ie; |
96 | DECLARE_SSID_BUF(ssid); | ||
97 | 96 | ||
98 | memset(&cmd, 0, sizeof(cmd)); | 97 | memset(&cmd, 0, sizeof(cmd)); |
99 | cmd.channel = cpu_to_le16(chan); | 98 | cmd.channel = cpu_to_le16(chan); |
@@ -122,9 +121,9 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action, | |||
122 | default: | 121 | default: |
123 | return -1; | 122 | return -1; |
124 | } | 123 | } |
125 | lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n", | 124 | lbs_deb_cmd("mesh config action %d type %x channel %d SSID %*pE\n", |
126 | action, priv->mesh_tlv, chan, | 125 | action, priv->mesh_tlv, chan, priv->mesh_ssid_len, |
127 | print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len)); | 126 | priv->mesh_ssid); |
128 | 127 | ||
129 | return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); | 128 | return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); |
130 | } | 129 | } |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index babbdc1ce741..2371d11e4190 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -412,6 +412,11 @@ struct mac80211_hwsim_data { | |||
412 | struct mac_address addresses[2]; | 412 | struct mac_address addresses[2]; |
413 | int channels, idx; | 413 | int channels, idx; |
414 | bool use_chanctx; | 414 | bool use_chanctx; |
415 | bool destroy_on_close; | ||
416 | struct work_struct destroy_work; | ||
417 | u32 portid; | ||
418 | char alpha2[2]; | ||
419 | const struct ieee80211_regdomain *regd; | ||
415 | 420 | ||
416 | struct ieee80211_channel *tmp_chan; | 421 | struct ieee80211_channel *tmp_chan; |
417 | struct delayed_work roc_done; | 422 | struct delayed_work roc_done; |
@@ -419,6 +424,7 @@ struct mac80211_hwsim_data { | |||
419 | struct cfg80211_scan_request *hw_scan_request; | 424 | struct cfg80211_scan_request *hw_scan_request; |
420 | struct ieee80211_vif *hw_scan_vif; | 425 | struct ieee80211_vif *hw_scan_vif; |
421 | int scan_chan_idx; | 426 | int scan_chan_idx; |
427 | u8 scan_addr[ETH_ALEN]; | ||
422 | 428 | ||
423 | struct ieee80211_channel *channel; | 429 | struct ieee80211_channel *channel; |
424 | u64 beacon_int /* beacon interval in us */; | 430 | u64 beacon_int /* beacon interval in us */; |
@@ -436,7 +442,7 @@ struct mac80211_hwsim_data { | |||
436 | /* | 442 | /* |
437 | * Only radios in the same group can communicate together (the | 443 | * Only radios in the same group can communicate together (the |
438 | * channel has to match too). Each bit represents a group. A | 444 | * channel has to match too). Each bit represents a group. A |
439 | * radio can be in more then one group. | 445 | * radio can be in more than one group. |
440 | */ | 446 | */ |
441 | u64 group; | 447 | u64 group; |
442 | 448 | ||
@@ -447,6 +453,14 @@ struct mac80211_hwsim_data { | |||
447 | s64 bcn_delta; | 453 | s64 bcn_delta; |
448 | /* absolute beacon transmission time. Used to cover up "tx" delay. */ | 454 | /* absolute beacon transmission time. Used to cover up "tx" delay. */ |
449 | u64 abs_bcn_ts; | 455 | u64 abs_bcn_ts; |
456 | |||
457 | /* Stats */ | ||
458 | u64 tx_pkts; | ||
459 | u64 rx_pkts; | ||
460 | u64 tx_bytes; | ||
461 | u64 rx_bytes; | ||
462 | u64 tx_dropped; | ||
463 | u64 tx_failed; | ||
450 | }; | 464 | }; |
451 | 465 | ||
452 | 466 | ||
@@ -476,6 +490,14 @@ static struct genl_family hwsim_genl_family = { | |||
476 | .maxattr = HWSIM_ATTR_MAX, | 490 | .maxattr = HWSIM_ATTR_MAX, |
477 | }; | 491 | }; |
478 | 492 | ||
493 | enum hwsim_multicast_groups { | ||
494 | HWSIM_MCGRP_CONFIG, | ||
495 | }; | ||
496 | |||
497 | static const struct genl_multicast_group hwsim_mcgrps[] = { | ||
498 | [HWSIM_MCGRP_CONFIG] = { .name = "config", }, | ||
499 | }; | ||
500 | |||
479 | /* MAC80211_HWSIM netlink policy */ | 501 | /* MAC80211_HWSIM netlink policy */ |
480 | 502 | ||
481 | static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { | 503 | static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { |
@@ -496,6 +518,10 @@ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { | |||
496 | [HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 }, | 518 | [HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 }, |
497 | [HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG }, | 519 | [HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG }, |
498 | [HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG }, | 520 | [HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG }, |
521 | [HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE] = { .type = NLA_FLAG }, | ||
522 | [HWSIM_ATTR_RADIO_NAME] = { .type = NLA_STRING }, | ||
523 | [HWSIM_ATTR_NO_VIF] = { .type = NLA_FLAG }, | ||
524 | [HWSIM_ATTR_FREQ] = { .type = NLA_U32 }, | ||
499 | }; | 525 | }; |
500 | 526 | ||
501 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | 527 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, |
@@ -807,6 +833,9 @@ static bool mac80211_hwsim_addr_match(struct mac80211_hwsim_data *data, | |||
807 | .ret = false, | 833 | .ret = false, |
808 | }; | 834 | }; |
809 | 835 | ||
836 | if (data->scanning && memcmp(addr, data->scan_addr, ETH_ALEN) == 0) | ||
837 | return true; | ||
838 | |||
810 | memcpy(md.addr, addr, ETH_ALEN); | 839 | memcpy(md.addr, addr, ETH_ALEN); |
811 | 840 | ||
812 | ieee80211_iterate_active_interfaces_atomic(data->hw, | 841 | ieee80211_iterate_active_interfaces_atomic(data->hw, |
@@ -861,8 +890,10 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, | |||
861 | /* If the queue contains MAX_QUEUE skb's drop some */ | 890 | /* If the queue contains MAX_QUEUE skb's drop some */ |
862 | if (skb_queue_len(&data->pending) >= MAX_QUEUE) { | 891 | if (skb_queue_len(&data->pending) >= MAX_QUEUE) { |
863 | /* Droping until WARN_QUEUE level */ | 892 | /* Droping until WARN_QUEUE level */ |
864 | while (skb_queue_len(&data->pending) >= WARN_QUEUE) | 893 | while (skb_queue_len(&data->pending) >= WARN_QUEUE) { |
865 | skb_dequeue(&data->pending); | 894 | ieee80211_free_txskb(hw, skb_dequeue(&data->pending)); |
895 | data->tx_dropped++; | ||
896 | } | ||
866 | } | 897 | } |
867 | 898 | ||
868 | skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC); | 899 | skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC); |
@@ -896,6 +927,9 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, | |||
896 | if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags)) | 927 | if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags)) |
897 | goto nla_put_failure; | 928 | goto nla_put_failure; |
898 | 929 | ||
930 | if (nla_put_u32(skb, HWSIM_ATTR_FREQ, data->channel->center_freq)) | ||
931 | goto nla_put_failure; | ||
932 | |||
899 | /* We get the tx control (rate and retries) info*/ | 933 | /* We get the tx control (rate and retries) info*/ |
900 | 934 | ||
901 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 935 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
@@ -917,10 +951,14 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, | |||
917 | 951 | ||
918 | /* Enqueue the packet */ | 952 | /* Enqueue the packet */ |
919 | skb_queue_tail(&data->pending, my_skb); | 953 | skb_queue_tail(&data->pending, my_skb); |
954 | data->tx_pkts++; | ||
955 | data->tx_bytes += my_skb->len; | ||
920 | return; | 956 | return; |
921 | 957 | ||
922 | nla_put_failure: | 958 | nla_put_failure: |
923 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); | 959 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); |
960 | ieee80211_free_txskb(hw, my_skb); | ||
961 | data->tx_failed++; | ||
924 | } | 962 | } |
925 | 963 | ||
926 | static bool hwsim_chans_compat(struct ieee80211_channel *c1, | 964 | static bool hwsim_chans_compat(struct ieee80211_channel *c1, |
@@ -952,6 +990,53 @@ static void mac80211_hwsim_tx_iter(void *_data, u8 *addr, | |||
952 | data->receive = true; | 990 | data->receive = true; |
953 | } | 991 | } |
954 | 992 | ||
993 | static void mac80211_hwsim_add_vendor_rtap(struct sk_buff *skb) | ||
994 | { | ||
995 | /* | ||
996 | * To enable this code, #define the HWSIM_RADIOTAP_OUI, | ||
997 | * e.g. like this: | ||
998 | * #define HWSIM_RADIOTAP_OUI "\x02\x00\x00" | ||
999 | * (but you should use a valid OUI, not that) | ||
1000 | * | ||
1001 | * If anyone wants to 'donate' a radiotap OUI/subns code | ||
1002 | * please send a patch removing this #ifdef and changing | ||
1003 | * the values accordingly. | ||
1004 | */ | ||
1005 | #ifdef HWSIM_RADIOTAP_OUI | ||
1006 | struct ieee80211_vendor_radiotap *rtap; | ||
1007 | |||
1008 | /* | ||
1009 | * Note that this code requires the headroom in the SKB | ||
1010 | * that was allocated earlier. | ||
1011 | */ | ||
1012 | rtap = (void *)skb_push(skb, sizeof(*rtap) + 8 + 4); | ||
1013 | rtap->oui[0] = HWSIM_RADIOTAP_OUI[0]; | ||
1014 | rtap->oui[1] = HWSIM_RADIOTAP_OUI[1]; | ||
1015 | rtap->oui[2] = HWSIM_RADIOTAP_OUI[2]; | ||
1016 | rtap->subns = 127; | ||
1017 | |||
1018 | /* | ||
1019 | * Radiotap vendor namespaces can (and should) also be | ||
1020 | * split into fields by using the standard radiotap | ||
1021 | * presence bitmap mechanism. Use just BIT(0) here for | ||
1022 | * the presence bitmap. | ||
1023 | */ | ||
1024 | rtap->present = BIT(0); | ||
1025 | /* We have 8 bytes of (dummy) data */ | ||
1026 | rtap->len = 8; | ||
1027 | /* For testing, also require it to be aligned */ | ||
1028 | rtap->align = 8; | ||
1029 | /* And also test that padding works, 4 bytes */ | ||
1030 | rtap->pad = 4; | ||
1031 | /* push the data */ | ||
1032 | memcpy(rtap->data, "ABCDEFGH", 8); | ||
1033 | /* make sure to clear padding, mac80211 doesn't */ | ||
1034 | memset(rtap->data + 8, 0, 4); | ||
1035 | |||
1036 | IEEE80211_SKB_RXCB(skb)->flag |= RX_FLAG_RADIOTAP_VENDOR_DATA; | ||
1037 | #endif | ||
1038 | } | ||
1039 | |||
955 | static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | 1040 | static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, |
956 | struct sk_buff *skb, | 1041 | struct sk_buff *skb, |
957 | struct ieee80211_channel *chan) | 1042 | struct ieee80211_channel *chan) |
@@ -1066,6 +1151,11 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
1066 | rx_status.mactime = now + data2->tsf_offset; | 1151 | rx_status.mactime = now + data2->tsf_offset; |
1067 | 1152 | ||
1068 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); | 1153 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); |
1154 | |||
1155 | mac80211_hwsim_add_vendor_rtap(nskb); | ||
1156 | |||
1157 | data2->rx_pkts++; | ||
1158 | data2->rx_bytes += nskb->len; | ||
1069 | ieee80211_rx_irqsafe(data2->hw, nskb); | 1159 | ieee80211_rx_irqsafe(data2->hw, nskb); |
1070 | } | 1160 | } |
1071 | spin_unlock(&hwsim_radio_lock); | 1161 | spin_unlock(&hwsim_radio_lock); |
@@ -1133,6 +1223,8 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, | |||
1133 | return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); | 1223 | return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); |
1134 | 1224 | ||
1135 | /* NO wmediumd detected, perfect medium simulation */ | 1225 | /* NO wmediumd detected, perfect medium simulation */ |
1226 | data->tx_pkts++; | ||
1227 | data->tx_bytes += skb->len; | ||
1136 | ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel); | 1228 | ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel); |
1137 | 1229 | ||
1138 | if (ack && skb->len >= 16) { | 1230 | if (ack && skb->len >= 16) { |
@@ -1716,7 +1808,7 @@ static void hw_scan_work(struct work_struct *work) | |||
1716 | struct sk_buff *probe; | 1808 | struct sk_buff *probe; |
1717 | 1809 | ||
1718 | probe = ieee80211_probereq_get(hwsim->hw, | 1810 | probe = ieee80211_probereq_get(hwsim->hw, |
1719 | hwsim->hw_scan_vif, | 1811 | hwsim->scan_addr, |
1720 | req->ssids[i].ssid, | 1812 | req->ssids[i].ssid, |
1721 | req->ssids[i].ssid_len, | 1813 | req->ssids[i].ssid_len, |
1722 | req->ie_len); | 1814 | req->ie_len); |
@@ -1754,6 +1846,12 @@ static int mac80211_hwsim_hw_scan(struct ieee80211_hw *hw, | |||
1754 | hwsim->hw_scan_request = req; | 1846 | hwsim->hw_scan_request = req; |
1755 | hwsim->hw_scan_vif = vif; | 1847 | hwsim->hw_scan_vif = vif; |
1756 | hwsim->scan_chan_idx = 0; | 1848 | hwsim->scan_chan_idx = 0; |
1849 | if (req->flags & NL80211_SCAN_FLAG_RANDOM_ADDR) | ||
1850 | get_random_mask_addr(hwsim->scan_addr, | ||
1851 | hw_req->req.mac_addr, | ||
1852 | hw_req->req.mac_addr_mask); | ||
1853 | else | ||
1854 | memcpy(hwsim->scan_addr, vif->addr, ETH_ALEN); | ||
1757 | mutex_unlock(&hwsim->mutex); | 1855 | mutex_unlock(&hwsim->mutex); |
1758 | 1856 | ||
1759 | wiphy_debug(hw->wiphy, "hwsim hw_scan request\n"); | 1857 | wiphy_debug(hw->wiphy, "hwsim hw_scan request\n"); |
@@ -1780,7 +1878,9 @@ static void mac80211_hwsim_cancel_hw_scan(struct ieee80211_hw *hw, | |||
1780 | mutex_unlock(&hwsim->mutex); | 1878 | mutex_unlock(&hwsim->mutex); |
1781 | } | 1879 | } |
1782 | 1880 | ||
1783 | static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw) | 1881 | static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw, |
1882 | struct ieee80211_vif *vif, | ||
1883 | const u8 *mac_addr) | ||
1784 | { | 1884 | { |
1785 | struct mac80211_hwsim_data *hwsim = hw->priv; | 1885 | struct mac80211_hwsim_data *hwsim = hw->priv; |
1786 | 1886 | ||
@@ -1792,13 +1892,16 @@ static void mac80211_hwsim_sw_scan(struct ieee80211_hw *hw) | |||
1792 | } | 1892 | } |
1793 | 1893 | ||
1794 | printk(KERN_DEBUG "hwsim sw_scan request, prepping stuff\n"); | 1894 | printk(KERN_DEBUG "hwsim sw_scan request, prepping stuff\n"); |
1895 | |||
1896 | memcpy(hwsim->scan_addr, mac_addr, ETH_ALEN); | ||
1795 | hwsim->scanning = true; | 1897 | hwsim->scanning = true; |
1796 | 1898 | ||
1797 | out: | 1899 | out: |
1798 | mutex_unlock(&hwsim->mutex); | 1900 | mutex_unlock(&hwsim->mutex); |
1799 | } | 1901 | } |
1800 | 1902 | ||
1801 | static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw) | 1903 | static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw, |
1904 | struct ieee80211_vif *vif) | ||
1802 | { | 1905 | { |
1803 | struct mac80211_hwsim_data *hwsim = hw->priv; | 1906 | struct mac80211_hwsim_data *hwsim = hw->priv; |
1804 | 1907 | ||
@@ -1806,6 +1909,7 @@ static void mac80211_hwsim_sw_scan_complete(struct ieee80211_hw *hw) | |||
1806 | 1909 | ||
1807 | printk(KERN_DEBUG "hwsim sw_scan_complete\n"); | 1910 | printk(KERN_DEBUG "hwsim sw_scan_complete\n"); |
1808 | hwsim->scanning = false; | 1911 | hwsim->scanning = false; |
1912 | memset(hwsim->scan_addr, 0, ETH_ALEN); | ||
1809 | 1913 | ||
1810 | mutex_unlock(&hwsim->mutex); | 1914 | mutex_unlock(&hwsim->mutex); |
1811 | } | 1915 | } |
@@ -1916,6 +2020,57 @@ static void mac80211_hwsim_unassign_vif_chanctx(struct ieee80211_hw *hw, | |||
1916 | hwsim_check_chanctx_magic(ctx); | 2020 | hwsim_check_chanctx_magic(ctx); |
1917 | } | 2021 | } |
1918 | 2022 | ||
2023 | static const char mac80211_hwsim_gstrings_stats[][ETH_GSTRING_LEN] = { | ||
2024 | "tx_pkts_nic", | ||
2025 | "tx_bytes_nic", | ||
2026 | "rx_pkts_nic", | ||
2027 | "rx_bytes_nic", | ||
2028 | "d_tx_dropped", | ||
2029 | "d_tx_failed", | ||
2030 | "d_ps_mode", | ||
2031 | "d_group", | ||
2032 | "d_tx_power", | ||
2033 | }; | ||
2034 | |||
2035 | #define MAC80211_HWSIM_SSTATS_LEN ARRAY_SIZE(mac80211_hwsim_gstrings_stats) | ||
2036 | |||
2037 | static void mac80211_hwsim_get_et_strings(struct ieee80211_hw *hw, | ||
2038 | struct ieee80211_vif *vif, | ||
2039 | u32 sset, u8 *data) | ||
2040 | { | ||
2041 | if (sset == ETH_SS_STATS) | ||
2042 | memcpy(data, *mac80211_hwsim_gstrings_stats, | ||
2043 | sizeof(mac80211_hwsim_gstrings_stats)); | ||
2044 | } | ||
2045 | |||
2046 | static int mac80211_hwsim_get_et_sset_count(struct ieee80211_hw *hw, | ||
2047 | struct ieee80211_vif *vif, int sset) | ||
2048 | { | ||
2049 | if (sset == ETH_SS_STATS) | ||
2050 | return MAC80211_HWSIM_SSTATS_LEN; | ||
2051 | return 0; | ||
2052 | } | ||
2053 | |||
2054 | static void mac80211_hwsim_get_et_stats(struct ieee80211_hw *hw, | ||
2055 | struct ieee80211_vif *vif, | ||
2056 | struct ethtool_stats *stats, u64 *data) | ||
2057 | { | ||
2058 | struct mac80211_hwsim_data *ar = hw->priv; | ||
2059 | int i = 0; | ||
2060 | |||
2061 | data[i++] = ar->tx_pkts; | ||
2062 | data[i++] = ar->tx_bytes; | ||
2063 | data[i++] = ar->rx_pkts; | ||
2064 | data[i++] = ar->rx_bytes; | ||
2065 | data[i++] = ar->tx_dropped; | ||
2066 | data[i++] = ar->tx_failed; | ||
2067 | data[i++] = ar->ps; | ||
2068 | data[i++] = ar->group; | ||
2069 | data[i++] = ar->power_level; | ||
2070 | |||
2071 | WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN); | ||
2072 | } | ||
2073 | |||
1919 | static const struct ieee80211_ops mac80211_hwsim_ops = { | 2074 | static const struct ieee80211_ops mac80211_hwsim_ops = { |
1920 | .tx = mac80211_hwsim_tx, | 2075 | .tx = mac80211_hwsim_tx, |
1921 | .start = mac80211_hwsim_start, | 2076 | .start = mac80211_hwsim_start, |
@@ -1939,14 +2094,131 @@ static const struct ieee80211_ops mac80211_hwsim_ops = { | |||
1939 | .flush = mac80211_hwsim_flush, | 2094 | .flush = mac80211_hwsim_flush, |
1940 | .get_tsf = mac80211_hwsim_get_tsf, | 2095 | .get_tsf = mac80211_hwsim_get_tsf, |
1941 | .set_tsf = mac80211_hwsim_set_tsf, | 2096 | .set_tsf = mac80211_hwsim_set_tsf, |
2097 | .get_et_sset_count = mac80211_hwsim_get_et_sset_count, | ||
2098 | .get_et_stats = mac80211_hwsim_get_et_stats, | ||
2099 | .get_et_strings = mac80211_hwsim_get_et_strings, | ||
1942 | }; | 2100 | }; |
1943 | 2101 | ||
1944 | static struct ieee80211_ops mac80211_hwsim_mchan_ops; | 2102 | static struct ieee80211_ops mac80211_hwsim_mchan_ops; |
1945 | 2103 | ||
1946 | static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | 2104 | struct hwsim_new_radio_params { |
1947 | const struct ieee80211_regdomain *regd, | 2105 | unsigned int channels; |
1948 | bool reg_strict, bool p2p_device, | 2106 | const char *reg_alpha2; |
1949 | bool use_chanctx) | 2107 | const struct ieee80211_regdomain *regd; |
2108 | bool reg_strict; | ||
2109 | bool p2p_device; | ||
2110 | bool use_chanctx; | ||
2111 | bool destroy_on_close; | ||
2112 | const char *hwname; | ||
2113 | bool no_vif; | ||
2114 | }; | ||
2115 | |||
2116 | static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb, | ||
2117 | struct genl_info *info) | ||
2118 | { | ||
2119 | if (info) | ||
2120 | genl_notify(&hwsim_genl_family, mcast_skb, | ||
2121 | genl_info_net(info), info->snd_portid, | ||
2122 | HWSIM_MCGRP_CONFIG, info->nlhdr, GFP_KERNEL); | ||
2123 | else | ||
2124 | genlmsg_multicast(&hwsim_genl_family, mcast_skb, 0, | ||
2125 | HWSIM_MCGRP_CONFIG, GFP_KERNEL); | ||
2126 | } | ||
2127 | |||
2128 | static int append_radio_msg(struct sk_buff *skb, int id, | ||
2129 | struct hwsim_new_radio_params *param) | ||
2130 | { | ||
2131 | int ret; | ||
2132 | |||
2133 | ret = nla_put_u32(skb, HWSIM_ATTR_RADIO_ID, id); | ||
2134 | if (ret < 0) | ||
2135 | return ret; | ||
2136 | |||
2137 | if (param->channels) { | ||
2138 | ret = nla_put_u32(skb, HWSIM_ATTR_CHANNELS, param->channels); | ||
2139 | if (ret < 0) | ||
2140 | return ret; | ||
2141 | } | ||
2142 | |||
2143 | if (param->reg_alpha2) { | ||
2144 | ret = nla_put(skb, HWSIM_ATTR_REG_HINT_ALPHA2, 2, | ||
2145 | param->reg_alpha2); | ||
2146 | if (ret < 0) | ||
2147 | return ret; | ||
2148 | } | ||
2149 | |||
2150 | if (param->regd) { | ||
2151 | int i; | ||
2152 | |||
2153 | for (i = 0; hwsim_world_regdom_custom[i] != param->regd && | ||
2154 | i < ARRAY_SIZE(hwsim_world_regdom_custom); i++) | ||
2155 | ; | ||
2156 | |||
2157 | if (i < ARRAY_SIZE(hwsim_world_regdom_custom)) { | ||
2158 | ret = nla_put_u32(skb, HWSIM_ATTR_REG_CUSTOM_REG, i); | ||
2159 | if (ret < 0) | ||
2160 | return ret; | ||
2161 | } | ||
2162 | } | ||
2163 | |||
2164 | if (param->reg_strict) { | ||
2165 | ret = nla_put_flag(skb, HWSIM_ATTR_REG_STRICT_REG); | ||
2166 | if (ret < 0) | ||
2167 | return ret; | ||
2168 | } | ||
2169 | |||
2170 | if (param->p2p_device) { | ||
2171 | ret = nla_put_flag(skb, HWSIM_ATTR_SUPPORT_P2P_DEVICE); | ||
2172 | if (ret < 0) | ||
2173 | return ret; | ||
2174 | } | ||
2175 | |||
2176 | if (param->use_chanctx) { | ||
2177 | ret = nla_put_flag(skb, HWSIM_ATTR_USE_CHANCTX); | ||
2178 | if (ret < 0) | ||
2179 | return ret; | ||
2180 | } | ||
2181 | |||
2182 | if (param->hwname) { | ||
2183 | ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME, | ||
2184 | strlen(param->hwname), param->hwname); | ||
2185 | if (ret < 0) | ||
2186 | return ret; | ||
2187 | } | ||
2188 | |||
2189 | return 0; | ||
2190 | } | ||
2191 | |||
2192 | static void hwsim_mcast_new_radio(int id, struct genl_info *info, | ||
2193 | struct hwsim_new_radio_params *param) | ||
2194 | { | ||
2195 | struct sk_buff *mcast_skb; | ||
2196 | void *data; | ||
2197 | |||
2198 | mcast_skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
2199 | if (!mcast_skb) | ||
2200 | return; | ||
2201 | |||
2202 | data = genlmsg_put(mcast_skb, 0, 0, &hwsim_genl_family, 0, | ||
2203 | HWSIM_CMD_NEW_RADIO); | ||
2204 | if (!data) | ||
2205 | goto out_err; | ||
2206 | |||
2207 | if (append_radio_msg(mcast_skb, id, param) < 0) | ||
2208 | goto out_err; | ||
2209 | |||
2210 | genlmsg_end(mcast_skb, data); | ||
2211 | |||
2212 | hwsim_mcast_config_msg(mcast_skb, info); | ||
2213 | return; | ||
2214 | |||
2215 | out_err: | ||
2216 | genlmsg_cancel(mcast_skb, data); | ||
2217 | nlmsg_free(mcast_skb); | ||
2218 | } | ||
2219 | |||
2220 | static int mac80211_hwsim_new_radio(struct genl_info *info, | ||
2221 | struct hwsim_new_radio_params *param) | ||
1950 | { | 2222 | { |
1951 | int err; | 2223 | int err; |
1952 | u8 addr[ETH_ALEN]; | 2224 | u8 addr[ETH_ALEN]; |
@@ -1956,16 +2228,16 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
1956 | const struct ieee80211_ops *ops = &mac80211_hwsim_ops; | 2228 | const struct ieee80211_ops *ops = &mac80211_hwsim_ops; |
1957 | int idx; | 2229 | int idx; |
1958 | 2230 | ||
1959 | if (WARN_ON(channels > 1 && !use_chanctx)) | 2231 | if (WARN_ON(param->channels > 1 && !param->use_chanctx)) |
1960 | return -EINVAL; | 2232 | return -EINVAL; |
1961 | 2233 | ||
1962 | spin_lock_bh(&hwsim_radio_lock); | 2234 | spin_lock_bh(&hwsim_radio_lock); |
1963 | idx = hwsim_radio_idx++; | 2235 | idx = hwsim_radio_idx++; |
1964 | spin_unlock_bh(&hwsim_radio_lock); | 2236 | spin_unlock_bh(&hwsim_radio_lock); |
1965 | 2237 | ||
1966 | if (use_chanctx) | 2238 | if (param->use_chanctx) |
1967 | ops = &mac80211_hwsim_mchan_ops; | 2239 | ops = &mac80211_hwsim_mchan_ops; |
1968 | hw = ieee80211_alloc_hw(sizeof(*data), ops); | 2240 | hw = ieee80211_alloc_hw_nm(sizeof(*data), ops, param->hwname); |
1969 | if (!hw) { | 2241 | if (!hw) { |
1970 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw failed\n"); | 2242 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw failed\n"); |
1971 | err = -ENOMEM; | 2243 | err = -ENOMEM; |
@@ -1987,7 +2259,7 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
1987 | if (err != 0) { | 2259 | if (err != 0) { |
1988 | printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n", | 2260 | printk(KERN_DEBUG "mac80211_hwsim: device_bind_driver failed (%d)\n", |
1989 | err); | 2261 | err); |
1990 | goto failed_hw; | 2262 | goto failed_bind; |
1991 | } | 2263 | } |
1992 | 2264 | ||
1993 | skb_queue_head_init(&data->pending); | 2265 | skb_queue_head_init(&data->pending); |
@@ -2003,9 +2275,12 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2003 | hw->wiphy->n_addresses = 2; | 2275 | hw->wiphy->n_addresses = 2; |
2004 | hw->wiphy->addresses = data->addresses; | 2276 | hw->wiphy->addresses = data->addresses; |
2005 | 2277 | ||
2006 | data->channels = channels; | 2278 | data->channels = param->channels; |
2007 | data->use_chanctx = use_chanctx; | 2279 | data->use_chanctx = param->use_chanctx; |
2008 | data->idx = idx; | 2280 | data->idx = idx; |
2281 | data->destroy_on_close = param->destroy_on_close; | ||
2282 | if (info) | ||
2283 | data->portid = info->snd_portid; | ||
2009 | 2284 | ||
2010 | if (data->use_chanctx) { | 2285 | if (data->use_chanctx) { |
2011 | hw->wiphy->max_scan_ssids = 255; | 2286 | hw->wiphy->max_scan_ssids = 255; |
@@ -2014,12 +2289,12 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2014 | /* For channels > 1 DFS is not allowed */ | 2289 | /* For channels > 1 DFS is not allowed */ |
2015 | hw->wiphy->n_iface_combinations = 1; | 2290 | hw->wiphy->n_iface_combinations = 1; |
2016 | hw->wiphy->iface_combinations = &data->if_combination; | 2291 | hw->wiphy->iface_combinations = &data->if_combination; |
2017 | if (p2p_device) | 2292 | if (param->p2p_device) |
2018 | data->if_combination = hwsim_if_comb_p2p_dev[0]; | 2293 | data->if_combination = hwsim_if_comb_p2p_dev[0]; |
2019 | else | 2294 | else |
2020 | data->if_combination = hwsim_if_comb[0]; | 2295 | data->if_combination = hwsim_if_comb[0]; |
2021 | data->if_combination.num_different_channels = data->channels; | 2296 | data->if_combination.num_different_channels = data->channels; |
2022 | } else if (p2p_device) { | 2297 | } else if (param->p2p_device) { |
2023 | hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev; | 2298 | hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev; |
2024 | hw->wiphy->n_iface_combinations = | 2299 | hw->wiphy->n_iface_combinations = |
2025 | ARRAY_SIZE(hwsim_if_comb_p2p_dev); | 2300 | ARRAY_SIZE(hwsim_if_comb_p2p_dev); |
@@ -2040,7 +2315,7 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2040 | BIT(NL80211_IFTYPE_ADHOC) | | 2315 | BIT(NL80211_IFTYPE_ADHOC) | |
2041 | BIT(NL80211_IFTYPE_MESH_POINT); | 2316 | BIT(NL80211_IFTYPE_MESH_POINT); |
2042 | 2317 | ||
2043 | if (p2p_device) | 2318 | if (param->p2p_device) |
2044 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE); | 2319 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE); |
2045 | 2320 | ||
2046 | hw->flags = IEEE80211_HW_MFP_CAPABLE | | 2321 | hw->flags = IEEE80211_HW_MFP_CAPABLE | |
@@ -2060,7 +2335,8 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2060 | hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR | | 2335 | hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR | |
2061 | NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | | 2336 | NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE | |
2062 | NL80211_FEATURE_STATIC_SMPS | | 2337 | NL80211_FEATURE_STATIC_SMPS | |
2063 | NL80211_FEATURE_DYNAMIC_SMPS; | 2338 | NL80211_FEATURE_DYNAMIC_SMPS | |
2339 | NL80211_FEATURE_SCAN_RANDOM_MAC_ADDR; | ||
2064 | 2340 | ||
2065 | /* ask mac80211 to reserve space for magic */ | 2341 | /* ask mac80211 to reserve space for magic */ |
2066 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); | 2342 | hw->vif_data_size = sizeof(struct hwsim_vif_priv); |
@@ -2095,6 +2371,7 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2095 | sband->ht_cap.ht_supported = true; | 2371 | sband->ht_cap.ht_supported = true; |
2096 | sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | 2372 | sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | |
2097 | IEEE80211_HT_CAP_GRN_FLD | | 2373 | IEEE80211_HT_CAP_GRN_FLD | |
2374 | IEEE80211_HT_CAP_SGI_20 | | ||
2098 | IEEE80211_HT_CAP_SGI_40 | | 2375 | IEEE80211_HT_CAP_SGI_40 | |
2099 | IEEE80211_HT_CAP_DSSSCCK40; | 2376 | IEEE80211_HT_CAP_DSSSCCK40; |
2100 | sband->ht_cap.ampdu_factor = 0x3; | 2377 | sband->ht_cap.ampdu_factor = 0x3; |
@@ -2142,15 +2419,19 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2142 | hw->max_rates = 4; | 2419 | hw->max_rates = 4; |
2143 | hw->max_rate_tries = 11; | 2420 | hw->max_rate_tries = 11; |
2144 | 2421 | ||
2145 | if (reg_strict) | 2422 | if (param->reg_strict) |
2146 | hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG; | 2423 | hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG; |
2147 | if (regd) { | 2424 | if (param->regd) { |
2425 | data->regd = param->regd; | ||
2148 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; | 2426 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; |
2149 | wiphy_apply_custom_regulatory(hw->wiphy, regd); | 2427 | wiphy_apply_custom_regulatory(hw->wiphy, param->regd); |
2150 | /* give the regulatory workqueue a chance to run */ | 2428 | /* give the regulatory workqueue a chance to run */ |
2151 | schedule_timeout_interruptible(1); | 2429 | schedule_timeout_interruptible(1); |
2152 | } | 2430 | } |
2153 | 2431 | ||
2432 | if (param->no_vif) | ||
2433 | hw->flags |= IEEE80211_HW_NO_AUTO_VIF; | ||
2434 | |||
2154 | err = ieee80211_register_hw(hw); | 2435 | err = ieee80211_register_hw(hw); |
2155 | if (err < 0) { | 2436 | if (err < 0) { |
2156 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n", | 2437 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n", |
@@ -2160,8 +2441,11 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2160 | 2441 | ||
2161 | wiphy_debug(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr); | 2442 | wiphy_debug(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr); |
2162 | 2443 | ||
2163 | if (reg_alpha2) | 2444 | if (param->reg_alpha2) { |
2164 | regulatory_hint(hw->wiphy, reg_alpha2); | 2445 | data->alpha2[0] = param->reg_alpha2[0]; |
2446 | data->alpha2[1] = param->reg_alpha2[1]; | ||
2447 | regulatory_hint(hw->wiphy, param->reg_alpha2); | ||
2448 | } | ||
2165 | 2449 | ||
2166 | data->debugfs = debugfs_create_dir("hwsim", hw->wiphy->debugfsdir); | 2450 | data->debugfs = debugfs_create_dir("hwsim", hw->wiphy->debugfsdir); |
2167 | debugfs_create_file("ps", 0666, data->debugfs, data, &hwsim_fops_ps); | 2451 | debugfs_create_file("ps", 0666, data->debugfs, data, &hwsim_fops_ps); |
@@ -2180,9 +2464,14 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2180 | list_add_tail(&data->list, &hwsim_radios); | 2464 | list_add_tail(&data->list, &hwsim_radios); |
2181 | spin_unlock_bh(&hwsim_radio_lock); | 2465 | spin_unlock_bh(&hwsim_radio_lock); |
2182 | 2466 | ||
2467 | if (idx > 0) | ||
2468 | hwsim_mcast_new_radio(idx, info, param); | ||
2469 | |||
2183 | return idx; | 2470 | return idx; |
2184 | 2471 | ||
2185 | failed_hw: | 2472 | failed_hw: |
2473 | device_release_driver(data->dev); | ||
2474 | failed_bind: | ||
2186 | device_unregister(data->dev); | 2475 | device_unregister(data->dev); |
2187 | failed_drvdata: | 2476 | failed_drvdata: |
2188 | ieee80211_free_hw(hw); | 2477 | ieee80211_free_hw(hw); |
@@ -2190,8 +2479,46 @@ failed: | |||
2190 | return err; | 2479 | return err; |
2191 | } | 2480 | } |
2192 | 2481 | ||
2193 | static void mac80211_hwsim_destroy_radio(struct mac80211_hwsim_data *data) | 2482 | static void hwsim_mcast_del_radio(int id, const char *hwname, |
2483 | struct genl_info *info) | ||
2484 | { | ||
2485 | struct sk_buff *skb; | ||
2486 | void *data; | ||
2487 | int ret; | ||
2488 | |||
2489 | skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
2490 | if (!skb) | ||
2491 | return; | ||
2492 | |||
2493 | data = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0, | ||
2494 | HWSIM_CMD_DEL_RADIO); | ||
2495 | if (!data) | ||
2496 | goto error; | ||
2497 | |||
2498 | ret = nla_put_u32(skb, HWSIM_ATTR_RADIO_ID, id); | ||
2499 | if (ret < 0) | ||
2500 | goto error; | ||
2501 | |||
2502 | ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME, strlen(hwname), | ||
2503 | hwname); | ||
2504 | if (ret < 0) | ||
2505 | goto error; | ||
2506 | |||
2507 | genlmsg_end(skb, data); | ||
2508 | |||
2509 | hwsim_mcast_config_msg(skb, info); | ||
2510 | |||
2511 | return; | ||
2512 | |||
2513 | error: | ||
2514 | nlmsg_free(skb); | ||
2515 | } | ||
2516 | |||
2517 | static void mac80211_hwsim_del_radio(struct mac80211_hwsim_data *data, | ||
2518 | const char *hwname, | ||
2519 | struct genl_info *info) | ||
2194 | { | 2520 | { |
2521 | hwsim_mcast_del_radio(data->idx, hwname, info); | ||
2195 | debugfs_remove_recursive(data->debugfs); | 2522 | debugfs_remove_recursive(data->debugfs); |
2196 | ieee80211_unregister_hw(data->hw); | 2523 | ieee80211_unregister_hw(data->hw); |
2197 | device_release_driver(data->dev); | 2524 | device_release_driver(data->dev); |
@@ -2199,6 +2526,44 @@ static void mac80211_hwsim_destroy_radio(struct mac80211_hwsim_data *data) | |||
2199 | ieee80211_free_hw(data->hw); | 2526 | ieee80211_free_hw(data->hw); |
2200 | } | 2527 | } |
2201 | 2528 | ||
2529 | static int mac80211_hwsim_get_radio(struct sk_buff *skb, | ||
2530 | struct mac80211_hwsim_data *data, | ||
2531 | u32 portid, u32 seq, | ||
2532 | struct netlink_callback *cb, int flags) | ||
2533 | { | ||
2534 | void *hdr; | ||
2535 | struct hwsim_new_radio_params param = { }; | ||
2536 | int res = -EMSGSIZE; | ||
2537 | |||
2538 | hdr = genlmsg_put(skb, portid, seq, &hwsim_genl_family, flags, | ||
2539 | HWSIM_CMD_GET_RADIO); | ||
2540 | if (!hdr) | ||
2541 | return -EMSGSIZE; | ||
2542 | |||
2543 | if (cb) | ||
2544 | genl_dump_check_consistent(cb, hdr, &hwsim_genl_family); | ||
2545 | |||
2546 | param.reg_alpha2 = data->alpha2; | ||
2547 | param.reg_strict = !!(data->hw->wiphy->regulatory_flags & | ||
2548 | REGULATORY_STRICT_REG); | ||
2549 | param.p2p_device = !!(data->hw->wiphy->interface_modes & | ||
2550 | BIT(NL80211_IFTYPE_P2P_DEVICE)); | ||
2551 | param.use_chanctx = data->use_chanctx; | ||
2552 | param.regd = data->regd; | ||
2553 | param.channels = data->channels; | ||
2554 | param.hwname = wiphy_name(data->hw->wiphy); | ||
2555 | |||
2556 | res = append_radio_msg(skb, data->idx, ¶m); | ||
2557 | if (res < 0) | ||
2558 | goto out_err; | ||
2559 | |||
2560 | return genlmsg_end(skb, hdr); | ||
2561 | |||
2562 | out_err: | ||
2563 | genlmsg_cancel(skb, hdr); | ||
2564 | return res; | ||
2565 | } | ||
2566 | |||
2202 | static void mac80211_hwsim_free(void) | 2567 | static void mac80211_hwsim_free(void) |
2203 | { | 2568 | { |
2204 | struct mac80211_hwsim_data *data; | 2569 | struct mac80211_hwsim_data *data; |
@@ -2209,7 +2574,8 @@ static void mac80211_hwsim_free(void) | |||
2209 | list))) { | 2574 | list))) { |
2210 | list_del(&data->list); | 2575 | list_del(&data->list); |
2211 | spin_unlock_bh(&hwsim_radio_lock); | 2576 | spin_unlock_bh(&hwsim_radio_lock); |
2212 | mac80211_hwsim_destroy_radio(data); | 2577 | mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), |
2578 | NULL); | ||
2213 | spin_lock_bh(&hwsim_radio_lock); | 2579 | spin_lock_bh(&hwsim_radio_lock); |
2214 | } | 2580 | } |
2215 | spin_unlock_bh(&hwsim_radio_lock); | 2581 | spin_unlock_bh(&hwsim_radio_lock); |
@@ -2337,7 +2703,6 @@ out: | |||
2337 | static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, | 2703 | static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, |
2338 | struct genl_info *info) | 2704 | struct genl_info *info) |
2339 | { | 2705 | { |
2340 | |||
2341 | struct mac80211_hwsim_data *data2; | 2706 | struct mac80211_hwsim_data *data2; |
2342 | struct ieee80211_rx_status rx_status; | 2707 | struct ieee80211_rx_status rx_status; |
2343 | const u8 *dst; | 2708 | const u8 *dst; |
@@ -2380,18 +2745,22 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, | |||
2380 | 2745 | ||
2381 | /* A frame is received from user space */ | 2746 | /* A frame is received from user space */ |
2382 | memset(&rx_status, 0, sizeof(rx_status)); | 2747 | memset(&rx_status, 0, sizeof(rx_status)); |
2748 | /* TODO: Check ATTR_FREQ if it exists, and maybe throw away off-channel | ||
2749 | * packets? | ||
2750 | */ | ||
2383 | rx_status.freq = data2->channel->center_freq; | 2751 | rx_status.freq = data2->channel->center_freq; |
2384 | rx_status.band = data2->channel->band; | 2752 | rx_status.band = data2->channel->band; |
2385 | rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]); | 2753 | rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]); |
2386 | rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); | 2754 | rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); |
2387 | 2755 | ||
2388 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); | 2756 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); |
2757 | data2->rx_pkts++; | ||
2758 | data2->rx_bytes += skb->len; | ||
2389 | ieee80211_rx_irqsafe(data2->hw, skb); | 2759 | ieee80211_rx_irqsafe(data2->hw, skb); |
2390 | 2760 | ||
2391 | return 0; | 2761 | return 0; |
2392 | err: | 2762 | err: |
2393 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); | 2763 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); |
2394 | goto out; | ||
2395 | out: | 2764 | out: |
2396 | dev_kfree_skb(skb); | 2765 | dev_kfree_skb(skb); |
2397 | return -EINVAL; | 2766 | return -EINVAL; |
@@ -2427,54 +2796,72 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2, | |||
2427 | return 0; | 2796 | return 0; |
2428 | } | 2797 | } |
2429 | 2798 | ||
2430 | static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info) | 2799 | static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) |
2431 | { | 2800 | { |
2432 | unsigned int chans = channels; | 2801 | struct hwsim_new_radio_params param = { 0 }; |
2433 | const char *alpha2 = NULL; | 2802 | |
2434 | const struct ieee80211_regdomain *regd = NULL; | 2803 | param.reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; |
2435 | bool reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; | 2804 | param.p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE]; |
2436 | bool p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE]; | 2805 | param.channels = channels; |
2437 | bool use_chanctx; | 2806 | param.destroy_on_close = |
2807 | info->attrs[HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE]; | ||
2438 | 2808 | ||
2439 | if (info->attrs[HWSIM_ATTR_CHANNELS]) | 2809 | if (info->attrs[HWSIM_ATTR_CHANNELS]) |
2440 | chans = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]); | 2810 | param.channels = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]); |
2811 | |||
2812 | if (info->attrs[HWSIM_ATTR_NO_VIF]) | ||
2813 | param.no_vif = true; | ||
2814 | |||
2815 | if (info->attrs[HWSIM_ATTR_RADIO_NAME]) | ||
2816 | param.hwname = nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]); | ||
2441 | 2817 | ||
2442 | if (info->attrs[HWSIM_ATTR_USE_CHANCTX]) | 2818 | if (info->attrs[HWSIM_ATTR_USE_CHANCTX]) |
2443 | use_chanctx = true; | 2819 | param.use_chanctx = true; |
2444 | else | 2820 | else |
2445 | use_chanctx = (chans > 1); | 2821 | param.use_chanctx = (param.channels > 1); |
2446 | 2822 | ||
2447 | if (info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]) | 2823 | if (info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]) |
2448 | alpha2 = nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]); | 2824 | param.reg_alpha2 = |
2825 | nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]); | ||
2449 | 2826 | ||
2450 | if (info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]) { | 2827 | if (info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]) { |
2451 | u32 idx = nla_get_u32(info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]); | 2828 | u32 idx = nla_get_u32(info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]); |
2452 | 2829 | ||
2453 | if (idx >= ARRAY_SIZE(hwsim_world_regdom_custom)) | 2830 | if (idx >= ARRAY_SIZE(hwsim_world_regdom_custom)) |
2454 | return -EINVAL; | 2831 | return -EINVAL; |
2455 | regd = hwsim_world_regdom_custom[idx]; | 2832 | param.regd = hwsim_world_regdom_custom[idx]; |
2456 | } | 2833 | } |
2457 | 2834 | ||
2458 | return mac80211_hwsim_create_radio(chans, alpha2, regd, reg_strict, | 2835 | return mac80211_hwsim_new_radio(info, ¶m); |
2459 | p2p_device, use_chanctx); | ||
2460 | } | 2836 | } |
2461 | 2837 | ||
2462 | static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info) | 2838 | static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) |
2463 | { | 2839 | { |
2464 | struct mac80211_hwsim_data *data; | 2840 | struct mac80211_hwsim_data *data; |
2465 | int idx; | 2841 | s64 idx = -1; |
2842 | const char *hwname = NULL; | ||
2466 | 2843 | ||
2467 | if (!info->attrs[HWSIM_ATTR_RADIO_ID]) | 2844 | if (info->attrs[HWSIM_ATTR_RADIO_ID]) |
2845 | idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); | ||
2846 | else if (info->attrs[HWSIM_ATTR_RADIO_NAME]) | ||
2847 | hwname = (void *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]); | ||
2848 | else | ||
2468 | return -EINVAL; | 2849 | return -EINVAL; |
2469 | idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); | ||
2470 | 2850 | ||
2471 | spin_lock_bh(&hwsim_radio_lock); | 2851 | spin_lock_bh(&hwsim_radio_lock); |
2472 | list_for_each_entry(data, &hwsim_radios, list) { | 2852 | list_for_each_entry(data, &hwsim_radios, list) { |
2473 | if (data->idx != idx) | 2853 | if (idx >= 0) { |
2474 | continue; | 2854 | if (data->idx != idx) |
2855 | continue; | ||
2856 | } else { | ||
2857 | if (strcmp(hwname, wiphy_name(data->hw->wiphy))) | ||
2858 | continue; | ||
2859 | } | ||
2860 | |||
2475 | list_del(&data->list); | 2861 | list_del(&data->list); |
2476 | spin_unlock_bh(&hwsim_radio_lock); | 2862 | spin_unlock_bh(&hwsim_radio_lock); |
2477 | mac80211_hwsim_destroy_radio(data); | 2863 | mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), |
2864 | info); | ||
2478 | return 0; | 2865 | return 0; |
2479 | } | 2866 | } |
2480 | spin_unlock_bh(&hwsim_radio_lock); | 2867 | spin_unlock_bh(&hwsim_radio_lock); |
@@ -2482,6 +2869,77 @@ static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info) | |||
2482 | return -ENODEV; | 2869 | return -ENODEV; |
2483 | } | 2870 | } |
2484 | 2871 | ||
2872 | static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info) | ||
2873 | { | ||
2874 | struct mac80211_hwsim_data *data; | ||
2875 | struct sk_buff *skb; | ||
2876 | int idx, res = -ENODEV; | ||
2877 | |||
2878 | if (!info->attrs[HWSIM_ATTR_RADIO_ID]) | ||
2879 | return -EINVAL; | ||
2880 | idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); | ||
2881 | |||
2882 | spin_lock_bh(&hwsim_radio_lock); | ||
2883 | list_for_each_entry(data, &hwsim_radios, list) { | ||
2884 | if (data->idx != idx) | ||
2885 | continue; | ||
2886 | |||
2887 | skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
2888 | if (!skb) { | ||
2889 | res = -ENOMEM; | ||
2890 | goto out_err; | ||
2891 | } | ||
2892 | |||
2893 | res = mac80211_hwsim_get_radio(skb, data, info->snd_portid, | ||
2894 | info->snd_seq, NULL, 0); | ||
2895 | if (res < 0) { | ||
2896 | nlmsg_free(skb); | ||
2897 | goto out_err; | ||
2898 | } | ||
2899 | |||
2900 | genlmsg_reply(skb, info); | ||
2901 | break; | ||
2902 | } | ||
2903 | |||
2904 | out_err: | ||
2905 | spin_unlock_bh(&hwsim_radio_lock); | ||
2906 | |||
2907 | return res; | ||
2908 | } | ||
2909 | |||
2910 | static int hwsim_dump_radio_nl(struct sk_buff *skb, | ||
2911 | struct netlink_callback *cb) | ||
2912 | { | ||
2913 | int idx = cb->args[0]; | ||
2914 | struct mac80211_hwsim_data *data = NULL; | ||
2915 | int res; | ||
2916 | |||
2917 | spin_lock_bh(&hwsim_radio_lock); | ||
2918 | |||
2919 | if (idx == hwsim_radio_idx) | ||
2920 | goto done; | ||
2921 | |||
2922 | list_for_each_entry(data, &hwsim_radios, list) { | ||
2923 | if (data->idx < idx) | ||
2924 | continue; | ||
2925 | |||
2926 | res = mac80211_hwsim_get_radio(skb, data, | ||
2927 | NETLINK_CB(cb->skb).portid, | ||
2928 | cb->nlh->nlmsg_seq, cb, | ||
2929 | NLM_F_MULTI); | ||
2930 | if (res < 0) | ||
2931 | break; | ||
2932 | |||
2933 | idx = data->idx + 1; | ||
2934 | } | ||
2935 | |||
2936 | cb->args[0] = idx; | ||
2937 | |||
2938 | done: | ||
2939 | spin_unlock_bh(&hwsim_radio_lock); | ||
2940 | return skb->len; | ||
2941 | } | ||
2942 | |||
2485 | /* Generic Netlink operations array */ | 2943 | /* Generic Netlink operations array */ |
2486 | static const struct genl_ops hwsim_ops[] = { | 2944 | static const struct genl_ops hwsim_ops[] = { |
2487 | { | 2945 | { |
@@ -2501,19 +2959,48 @@ static const struct genl_ops hwsim_ops[] = { | |||
2501 | .doit = hwsim_tx_info_frame_received_nl, | 2959 | .doit = hwsim_tx_info_frame_received_nl, |
2502 | }, | 2960 | }, |
2503 | { | 2961 | { |
2504 | .cmd = HWSIM_CMD_CREATE_RADIO, | 2962 | .cmd = HWSIM_CMD_NEW_RADIO, |
2505 | .policy = hwsim_genl_policy, | 2963 | .policy = hwsim_genl_policy, |
2506 | .doit = hwsim_create_radio_nl, | 2964 | .doit = hwsim_new_radio_nl, |
2507 | .flags = GENL_ADMIN_PERM, | 2965 | .flags = GENL_ADMIN_PERM, |
2508 | }, | 2966 | }, |
2509 | { | 2967 | { |
2510 | .cmd = HWSIM_CMD_DESTROY_RADIO, | 2968 | .cmd = HWSIM_CMD_DEL_RADIO, |
2511 | .policy = hwsim_genl_policy, | 2969 | .policy = hwsim_genl_policy, |
2512 | .doit = hwsim_destroy_radio_nl, | 2970 | .doit = hwsim_del_radio_nl, |
2513 | .flags = GENL_ADMIN_PERM, | 2971 | .flags = GENL_ADMIN_PERM, |
2514 | }, | 2972 | }, |
2973 | { | ||
2974 | .cmd = HWSIM_CMD_GET_RADIO, | ||
2975 | .policy = hwsim_genl_policy, | ||
2976 | .doit = hwsim_get_radio_nl, | ||
2977 | .dumpit = hwsim_dump_radio_nl, | ||
2978 | }, | ||
2515 | }; | 2979 | }; |
2516 | 2980 | ||
2981 | static void destroy_radio(struct work_struct *work) | ||
2982 | { | ||
2983 | struct mac80211_hwsim_data *data = | ||
2984 | container_of(work, struct mac80211_hwsim_data, destroy_work); | ||
2985 | |||
2986 | mac80211_hwsim_del_radio(data, wiphy_name(data->hw->wiphy), NULL); | ||
2987 | } | ||
2988 | |||
2989 | static void remove_user_radios(u32 portid) | ||
2990 | { | ||
2991 | struct mac80211_hwsim_data *entry, *tmp; | ||
2992 | |||
2993 | spin_lock_bh(&hwsim_radio_lock); | ||
2994 | list_for_each_entry_safe(entry, tmp, &hwsim_radios, list) { | ||
2995 | if (entry->destroy_on_close && entry->portid == portid) { | ||
2996 | list_del(&entry->list); | ||
2997 | INIT_WORK(&entry->destroy_work, destroy_radio); | ||
2998 | schedule_work(&entry->destroy_work); | ||
2999 | } | ||
3000 | } | ||
3001 | spin_unlock_bh(&hwsim_radio_lock); | ||
3002 | } | ||
3003 | |||
2517 | static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, | 3004 | static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, |
2518 | unsigned long state, | 3005 | unsigned long state, |
2519 | void *_notify) | 3006 | void *_notify) |
@@ -2523,6 +3010,8 @@ static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, | |||
2523 | if (state != NETLINK_URELEASE) | 3010 | if (state != NETLINK_URELEASE) |
2524 | return NOTIFY_DONE; | 3011 | return NOTIFY_DONE; |
2525 | 3012 | ||
3013 | remove_user_radios(notify->portid); | ||
3014 | |||
2526 | if (notify->portid == wmediumd_portid) { | 3015 | if (notify->portid == wmediumd_portid) { |
2527 | printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink" | 3016 | printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink" |
2528 | " socket, switching to perfect channel medium\n"); | 3017 | " socket, switching to perfect channel medium\n"); |
@@ -2542,7 +3031,9 @@ static int hwsim_init_netlink(void) | |||
2542 | 3031 | ||
2543 | printk(KERN_INFO "mac80211_hwsim: initializing netlink\n"); | 3032 | printk(KERN_INFO "mac80211_hwsim: initializing netlink\n"); |
2544 | 3033 | ||
2545 | rc = genl_register_family_with_ops(&hwsim_genl_family, hwsim_ops); | 3034 | rc = genl_register_family_with_ops_groups(&hwsim_genl_family, |
3035 | hwsim_ops, | ||
3036 | hwsim_mcgrps); | ||
2546 | if (rc) | 3037 | if (rc) |
2547 | goto failure; | 3038 | goto failure; |
2548 | 3039 | ||
@@ -2603,69 +3094,73 @@ static int __init init_mac80211_hwsim(void) | |||
2603 | goto out_unregister_driver; | 3094 | goto out_unregister_driver; |
2604 | } | 3095 | } |
2605 | 3096 | ||
3097 | err = hwsim_init_netlink(); | ||
3098 | if (err < 0) | ||
3099 | goto out_unregister_driver; | ||
3100 | |||
2606 | for (i = 0; i < radios; i++) { | 3101 | for (i = 0; i < radios; i++) { |
2607 | const char *reg_alpha2 = NULL; | 3102 | struct hwsim_new_radio_params param = { 0 }; |
2608 | const struct ieee80211_regdomain *regd = NULL; | 3103 | |
2609 | bool reg_strict = false; | 3104 | param.channels = channels; |
2610 | 3105 | ||
2611 | switch (regtest) { | 3106 | switch (regtest) { |
2612 | case HWSIM_REGTEST_DIFF_COUNTRY: | 3107 | case HWSIM_REGTEST_DIFF_COUNTRY: |
2613 | if (i < ARRAY_SIZE(hwsim_alpha2s)) | 3108 | if (i < ARRAY_SIZE(hwsim_alpha2s)) |
2614 | reg_alpha2 = hwsim_alpha2s[i]; | 3109 | param.reg_alpha2 = hwsim_alpha2s[i]; |
2615 | break; | 3110 | break; |
2616 | case HWSIM_REGTEST_DRIVER_REG_FOLLOW: | 3111 | case HWSIM_REGTEST_DRIVER_REG_FOLLOW: |
2617 | if (!i) | 3112 | if (!i) |
2618 | reg_alpha2 = hwsim_alpha2s[0]; | 3113 | param.reg_alpha2 = hwsim_alpha2s[0]; |
2619 | break; | 3114 | break; |
2620 | case HWSIM_REGTEST_STRICT_ALL: | 3115 | case HWSIM_REGTEST_STRICT_ALL: |
2621 | reg_strict = true; | 3116 | param.reg_strict = true; |
2622 | case HWSIM_REGTEST_DRIVER_REG_ALL: | 3117 | case HWSIM_REGTEST_DRIVER_REG_ALL: |
2623 | reg_alpha2 = hwsim_alpha2s[0]; | 3118 | param.reg_alpha2 = hwsim_alpha2s[0]; |
2624 | break; | 3119 | break; |
2625 | case HWSIM_REGTEST_WORLD_ROAM: | 3120 | case HWSIM_REGTEST_WORLD_ROAM: |
2626 | if (i == 0) | 3121 | if (i == 0) |
2627 | regd = &hwsim_world_regdom_custom_01; | 3122 | param.regd = &hwsim_world_regdom_custom_01; |
2628 | break; | 3123 | break; |
2629 | case HWSIM_REGTEST_CUSTOM_WORLD: | 3124 | case HWSIM_REGTEST_CUSTOM_WORLD: |
2630 | regd = &hwsim_world_regdom_custom_01; | 3125 | param.regd = &hwsim_world_regdom_custom_01; |
2631 | break; | 3126 | break; |
2632 | case HWSIM_REGTEST_CUSTOM_WORLD_2: | 3127 | case HWSIM_REGTEST_CUSTOM_WORLD_2: |
2633 | if (i == 0) | 3128 | if (i == 0) |
2634 | regd = &hwsim_world_regdom_custom_01; | 3129 | param.regd = &hwsim_world_regdom_custom_01; |
2635 | else if (i == 1) | 3130 | else if (i == 1) |
2636 | regd = &hwsim_world_regdom_custom_02; | 3131 | param.regd = &hwsim_world_regdom_custom_02; |
2637 | break; | 3132 | break; |
2638 | case HWSIM_REGTEST_STRICT_FOLLOW: | 3133 | case HWSIM_REGTEST_STRICT_FOLLOW: |
2639 | if (i == 0) { | 3134 | if (i == 0) { |
2640 | reg_strict = true; | 3135 | param.reg_strict = true; |
2641 | reg_alpha2 = hwsim_alpha2s[0]; | 3136 | param.reg_alpha2 = hwsim_alpha2s[0]; |
2642 | } | 3137 | } |
2643 | break; | 3138 | break; |
2644 | case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: | 3139 | case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: |
2645 | if (i == 0) { | 3140 | if (i == 0) { |
2646 | reg_strict = true; | 3141 | param.reg_strict = true; |
2647 | reg_alpha2 = hwsim_alpha2s[0]; | 3142 | param.reg_alpha2 = hwsim_alpha2s[0]; |
2648 | } else if (i == 1) { | 3143 | } else if (i == 1) { |
2649 | reg_alpha2 = hwsim_alpha2s[1]; | 3144 | param.reg_alpha2 = hwsim_alpha2s[1]; |
2650 | } | 3145 | } |
2651 | break; | 3146 | break; |
2652 | case HWSIM_REGTEST_ALL: | 3147 | case HWSIM_REGTEST_ALL: |
2653 | switch (i) { | 3148 | switch (i) { |
2654 | case 0: | 3149 | case 0: |
2655 | regd = &hwsim_world_regdom_custom_01; | 3150 | param.regd = &hwsim_world_regdom_custom_01; |
2656 | break; | 3151 | break; |
2657 | case 1: | 3152 | case 1: |
2658 | regd = &hwsim_world_regdom_custom_02; | 3153 | param.regd = &hwsim_world_regdom_custom_02; |
2659 | break; | 3154 | break; |
2660 | case 2: | 3155 | case 2: |
2661 | reg_alpha2 = hwsim_alpha2s[0]; | 3156 | param.reg_alpha2 = hwsim_alpha2s[0]; |
2662 | break; | 3157 | break; |
2663 | case 3: | 3158 | case 3: |
2664 | reg_alpha2 = hwsim_alpha2s[1]; | 3159 | param.reg_alpha2 = hwsim_alpha2s[1]; |
2665 | break; | 3160 | break; |
2666 | case 4: | 3161 | case 4: |
2667 | reg_strict = true; | 3162 | param.reg_strict = true; |
2668 | reg_alpha2 = hwsim_alpha2s[2]; | 3163 | param.reg_alpha2 = hwsim_alpha2s[2]; |
2669 | break; | 3164 | break; |
2670 | } | 3165 | } |
2671 | break; | 3166 | break; |
@@ -2673,10 +3168,10 @@ static int __init init_mac80211_hwsim(void) | |||
2673 | break; | 3168 | break; |
2674 | } | 3169 | } |
2675 | 3170 | ||
2676 | err = mac80211_hwsim_create_radio(channels, reg_alpha2, | 3171 | param.p2p_device = support_p2p_device; |
2677 | regd, reg_strict, | 3172 | param.use_chanctx = channels > 1; |
2678 | support_p2p_device, | 3173 | |
2679 | channels > 1); | 3174 | err = mac80211_hwsim_new_radio(NULL, ¶m); |
2680 | if (err < 0) | 3175 | if (err < 0) |
2681 | goto out_free_radios; | 3176 | goto out_free_radios; |
2682 | } | 3177 | } |
@@ -2702,10 +3197,6 @@ static int __init init_mac80211_hwsim(void) | |||
2702 | } | 3197 | } |
2703 | rtnl_unlock(); | 3198 | rtnl_unlock(); |
2704 | 3199 | ||
2705 | err = hwsim_init_netlink(); | ||
2706 | if (err < 0) | ||
2707 | goto out_free_mon; | ||
2708 | |||
2709 | return 0; | 3200 | return 0; |
2710 | 3201 | ||
2711 | out_free_mon: | 3202 | out_free_mon: |
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h index c9d0315575ba..66e1c73bd507 100644 --- a/drivers/net/wireless/mac80211_hwsim.h +++ b/drivers/net/wireless/mac80211_hwsim.h | |||
@@ -60,14 +60,17 @@ enum hwsim_tx_control_flags { | |||
60 | * space, uses: | 60 | * space, uses: |
61 | * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_ADDR_RECEIVER, | 61 | * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_ADDR_RECEIVER, |
62 | * %HWSIM_ATTR_FRAME, %HWSIM_ATTR_FLAGS, %HWSIM_ATTR_RX_RATE, | 62 | * %HWSIM_ATTR_FRAME, %HWSIM_ATTR_FLAGS, %HWSIM_ATTR_RX_RATE, |
63 | * %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE | 63 | * %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE, %HWSIM_ATTR_FREQ (optional) |
64 | * @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to | 64 | * @HWSIM_CMD_TX_INFO_FRAME: Transmission info report from user space to |
65 | * kernel, uses: | 65 | * kernel, uses: |
66 | * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS, | 66 | * %HWSIM_ATTR_ADDR_TRANSMITTER, %HWSIM_ATTR_FLAGS, |
67 | * %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE | 67 | * %HWSIM_ATTR_TX_INFO, %HWSIM_ATTR_SIGNAL, %HWSIM_ATTR_COOKIE |
68 | * @HWSIM_CMD_CREATE_RADIO: create a new radio with the given parameters, | 68 | * @HWSIM_CMD_NEW_RADIO: create a new radio with the given parameters, |
69 | * returns the radio ID (>= 0) or negative on errors | 69 | * returns the radio ID (>= 0) or negative on errors, if successful |
70 | * @HWSIM_CMD_DESTROY_RADIO: destroy a radio | 70 | * then multicast the result |
71 | * @HWSIM_CMD_DEL_RADIO: destroy a radio, reply is multicasted | ||
72 | * @HWSIM_CMD_GET_RADIO: fetch information about existing radios, uses: | ||
73 | * %HWSIM_ATTR_RADIO_ID | ||
71 | * @__HWSIM_CMD_MAX: enum limit | 74 | * @__HWSIM_CMD_MAX: enum limit |
72 | */ | 75 | */ |
73 | enum { | 76 | enum { |
@@ -75,12 +78,16 @@ enum { | |||
75 | HWSIM_CMD_REGISTER, | 78 | HWSIM_CMD_REGISTER, |
76 | HWSIM_CMD_FRAME, | 79 | HWSIM_CMD_FRAME, |
77 | HWSIM_CMD_TX_INFO_FRAME, | 80 | HWSIM_CMD_TX_INFO_FRAME, |
78 | HWSIM_CMD_CREATE_RADIO, | 81 | HWSIM_CMD_NEW_RADIO, |
79 | HWSIM_CMD_DESTROY_RADIO, | 82 | HWSIM_CMD_DEL_RADIO, |
83 | HWSIM_CMD_GET_RADIO, | ||
80 | __HWSIM_CMD_MAX, | 84 | __HWSIM_CMD_MAX, |
81 | }; | 85 | }; |
82 | #define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1) | 86 | #define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1) |
83 | 87 | ||
88 | #define HWSIM_CMD_CREATE_RADIO HWSIM_CMD_NEW_RADIO | ||
89 | #define HWSIM_CMD_DESTROY_RADIO HWSIM_CMD_DEL_RADIO | ||
90 | |||
84 | /** | 91 | /** |
85 | * enum hwsim_attrs - hwsim netlink attributes | 92 | * enum hwsim_attrs - hwsim netlink attributes |
86 | * | 93 | * |
@@ -111,6 +118,11 @@ enum { | |||
111 | * @HWSIM_ATTR_USE_CHANCTX: used with the %HWSIM_CMD_CREATE_RADIO | 118 | * @HWSIM_ATTR_USE_CHANCTX: used with the %HWSIM_CMD_CREATE_RADIO |
112 | * command to force use of channel contexts even when only a | 119 | * command to force use of channel contexts even when only a |
113 | * single channel is supported | 120 | * single channel is supported |
121 | * @HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE: used with the %HWSIM_CMD_CREATE_RADIO | ||
122 | * command to force radio removal when process that created the radio dies | ||
123 | * @HWSIM_ATTR_RADIO_NAME: Name of radio, e.g. phy666 | ||
124 | * @HWSIM_ATTR_NO_VIF: Do not create vif (wlanX) when creating radio. | ||
125 | * @HWSIM_ATTR_FREQ: Frequency at which packet is transmitted or received. | ||
114 | * @__HWSIM_ATTR_MAX: enum limit | 126 | * @__HWSIM_ATTR_MAX: enum limit |
115 | */ | 127 | */ |
116 | 128 | ||
@@ -132,6 +144,10 @@ enum { | |||
132 | HWSIM_ATTR_REG_STRICT_REG, | 144 | HWSIM_ATTR_REG_STRICT_REG, |
133 | HWSIM_ATTR_SUPPORT_P2P_DEVICE, | 145 | HWSIM_ATTR_SUPPORT_P2P_DEVICE, |
134 | HWSIM_ATTR_USE_CHANCTX, | 146 | HWSIM_ATTR_USE_CHANCTX, |
147 | HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE, | ||
148 | HWSIM_ATTR_RADIO_NAME, | ||
149 | HWSIM_ATTR_NO_VIF, | ||
150 | HWSIM_ATTR_FREQ, | ||
135 | __HWSIM_ATTR_MAX, | 151 | __HWSIM_ATTR_MAX, |
136 | }; | 152 | }; |
137 | #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) | 153 | #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) |
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h index 2ee268b632be..f275675cdbd3 100644 --- a/drivers/net/wireless/mwifiex/11n.h +++ b/drivers/net/wireless/mwifiex/11n.h | |||
@@ -84,6 +84,8 @@ mwifiex_is_amsdu_in_ampdu_allowed(struct mwifiex_private *priv, | |||
84 | { | 84 | { |
85 | struct mwifiex_tx_ba_stream_tbl *tx_tbl; | 85 | struct mwifiex_tx_ba_stream_tbl *tx_tbl; |
86 | 86 | ||
87 | if (is_broadcast_ether_addr(ptr->ra)) | ||
88 | return false; | ||
87 | tx_tbl = mwifiex_get_ba_tbl(priv, tid, ptr->ra); | 89 | tx_tbl = mwifiex_get_ba_tbl(priv, tid, ptr->ra); |
88 | if (tx_tbl) | 90 | if (tx_tbl) |
89 | return tx_tbl->amsdu; | 91 | return tx_tbl->amsdu; |
@@ -96,6 +98,8 @@ static inline u8 | |||
96 | mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, | 98 | mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, |
97 | struct mwifiex_ra_list_tbl *ptr, int tid) | 99 | struct mwifiex_ra_list_tbl *ptr, int tid) |
98 | { | 100 | { |
101 | if (is_broadcast_ether_addr(ptr->ra)) | ||
102 | return false; | ||
99 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { | 103 | if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { |
100 | return mwifiex_is_station_ampdu_allowed(priv, ptr, tid); | 104 | return mwifiex_is_station_ampdu_allowed(priv, ptr, tid); |
101 | } else { | 105 | } else { |
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c index 40057079ffb9..5ef5a0eeba50 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.c | |||
@@ -196,6 +196,7 @@ mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv, | |||
196 | mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); | 196 | mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); |
197 | 197 | ||
198 | del_timer_sync(&tbl->timer_context.timer); | 198 | del_timer_sync(&tbl->timer_context.timer); |
199 | tbl->timer_context.timer_is_set = false; | ||
199 | 200 | ||
200 | spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); | 201 | spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); |
201 | list_del(&tbl->list); | 202 | list_del(&tbl->list); |
@@ -297,6 +298,7 @@ mwifiex_flush_data(unsigned long context) | |||
297 | (struct reorder_tmr_cnxt *) context; | 298 | (struct reorder_tmr_cnxt *) context; |
298 | int start_win, seq_num; | 299 | int start_win, seq_num; |
299 | 300 | ||
301 | ctx->timer_is_set = false; | ||
300 | seq_num = mwifiex_11n_find_last_seq_num(ctx); | 302 | seq_num = mwifiex_11n_find_last_seq_num(ctx); |
301 | 303 | ||
302 | if (seq_num < 0) | 304 | if (seq_num < 0) |
@@ -385,6 +387,7 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, | |||
385 | 387 | ||
386 | new_node->timer_context.ptr = new_node; | 388 | new_node->timer_context.ptr = new_node; |
387 | new_node->timer_context.priv = priv; | 389 | new_node->timer_context.priv = priv; |
390 | new_node->timer_context.timer_is_set = false; | ||
388 | 391 | ||
389 | init_timer(&new_node->timer_context.timer); | 392 | init_timer(&new_node->timer_context.timer); |
390 | new_node->timer_context.timer.function = mwifiex_flush_data; | 393 | new_node->timer_context.timer.function = mwifiex_flush_data; |
@@ -399,6 +402,22 @@ mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, | |||
399 | spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); | 402 | spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); |
400 | } | 403 | } |
401 | 404 | ||
405 | static void | ||
406 | mwifiex_11n_rxreorder_timer_restart(struct mwifiex_rx_reorder_tbl *tbl) | ||
407 | { | ||
408 | u32 min_flush_time; | ||
409 | |||
410 | if (tbl->win_size >= MWIFIEX_BA_WIN_SIZE_32) | ||
411 | min_flush_time = MIN_FLUSH_TIMER_15_MS; | ||
412 | else | ||
413 | min_flush_time = MIN_FLUSH_TIMER_MS; | ||
414 | |||
415 | mod_timer(&tbl->timer_context.timer, | ||
416 | jiffies + msecs_to_jiffies(min_flush_time * tbl->win_size)); | ||
417 | |||
418 | tbl->timer_context.timer_is_set = true; | ||
419 | } | ||
420 | |||
402 | /* | 421 | /* |
403 | * This function prepares command for adding a BA request. | 422 | * This function prepares command for adding a BA request. |
404 | * | 423 | * |
@@ -523,31 +542,31 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, | |||
523 | u8 *ta, u8 pkt_type, void *payload) | 542 | u8 *ta, u8 pkt_type, void *payload) |
524 | { | 543 | { |
525 | struct mwifiex_rx_reorder_tbl *tbl; | 544 | struct mwifiex_rx_reorder_tbl *tbl; |
526 | int start_win, end_win, win_size; | 545 | int prev_start_win, start_win, end_win, win_size; |
527 | u16 pkt_index; | 546 | u16 pkt_index; |
528 | bool init_window_shift = false; | 547 | bool init_window_shift = false; |
548 | int ret = 0; | ||
529 | 549 | ||
530 | tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); | 550 | tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); |
531 | if (!tbl) { | 551 | if (!tbl) { |
532 | if (pkt_type != PKT_TYPE_BAR) | 552 | if (pkt_type != PKT_TYPE_BAR) |
533 | mwifiex_11n_dispatch_pkt(priv, payload); | 553 | mwifiex_11n_dispatch_pkt(priv, payload); |
534 | return 0; | 554 | return ret; |
535 | } | 555 | } |
536 | 556 | ||
537 | if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) { | 557 | if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) { |
538 | mwifiex_11n_dispatch_pkt(priv, payload); | 558 | mwifiex_11n_dispatch_pkt(priv, payload); |
539 | return 0; | 559 | return ret; |
540 | } | 560 | } |
541 | 561 | ||
542 | start_win = tbl->start_win; | 562 | start_win = tbl->start_win; |
563 | prev_start_win = start_win; | ||
543 | win_size = tbl->win_size; | 564 | win_size = tbl->win_size; |
544 | end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); | 565 | end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); |
545 | if (tbl->flags & RXREOR_INIT_WINDOW_SHIFT) { | 566 | if (tbl->flags & RXREOR_INIT_WINDOW_SHIFT) { |
546 | init_window_shift = true; | 567 | init_window_shift = true; |
547 | tbl->flags &= ~RXREOR_INIT_WINDOW_SHIFT; | 568 | tbl->flags &= ~RXREOR_INIT_WINDOW_SHIFT; |
548 | } | 569 | } |
549 | mod_timer(&tbl->timer_context.timer, | ||
550 | jiffies + msecs_to_jiffies(MIN_FLUSH_TIMER_MS * win_size)); | ||
551 | 570 | ||
552 | if (tbl->flags & RXREOR_FORCE_NO_DROP) { | 571 | if (tbl->flags & RXREOR_FORCE_NO_DROP) { |
553 | dev_dbg(priv->adapter->dev, | 572 | dev_dbg(priv->adapter->dev, |
@@ -568,11 +587,14 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, | |||
568 | if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) { | 587 | if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) { |
569 | if (seq_num >= ((start_win + TWOPOW11) & | 588 | if (seq_num >= ((start_win + TWOPOW11) & |
570 | (MAX_TID_VALUE - 1)) && | 589 | (MAX_TID_VALUE - 1)) && |
571 | seq_num < start_win) | 590 | seq_num < start_win) { |
572 | return -1; | 591 | ret = -1; |
592 | goto done; | ||
593 | } | ||
573 | } else if ((seq_num < start_win) || | 594 | } else if ((seq_num < start_win) || |
574 | (seq_num > (start_win + TWOPOW11))) { | 595 | (seq_num >= (start_win + TWOPOW11))) { |
575 | return -1; | 596 | ret = -1; |
597 | goto done; | ||
576 | } | 598 | } |
577 | } | 599 | } |
578 | 600 | ||
@@ -601,8 +623,10 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, | |||
601 | else | 623 | else |
602 | pkt_index = (seq_num+MAX_TID_VALUE) - start_win; | 624 | pkt_index = (seq_num+MAX_TID_VALUE) - start_win; |
603 | 625 | ||
604 | if (tbl->rx_reorder_ptr[pkt_index]) | 626 | if (tbl->rx_reorder_ptr[pkt_index]) { |
605 | return -1; | 627 | ret = -1; |
628 | goto done; | ||
629 | } | ||
606 | 630 | ||
607 | tbl->rx_reorder_ptr[pkt_index] = payload; | 631 | tbl->rx_reorder_ptr[pkt_index] = payload; |
608 | } | 632 | } |
@@ -613,7 +637,11 @@ int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, | |||
613 | */ | 637 | */ |
614 | mwifiex_11n_scan_and_dispatch(priv, tbl); | 638 | mwifiex_11n_scan_and_dispatch(priv, tbl); |
615 | 639 | ||
616 | return 0; | 640 | done: |
641 | if (!tbl->timer_context.timer_is_set || | ||
642 | prev_start_win != tbl->start_win) | ||
643 | mwifiex_11n_rxreorder_timer_restart(tbl); | ||
644 | return ret; | ||
617 | } | 645 | } |
618 | 646 | ||
619 | /* | 647 | /* |
diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h index 3a87bb0e3a62..63ecea89b4ab 100644 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.h +++ b/drivers/net/wireless/mwifiex/11n_rxreorder.h | |||
@@ -21,6 +21,8 @@ | |||
21 | #define _MWIFIEX_11N_RXREORDER_H_ | 21 | #define _MWIFIEX_11N_RXREORDER_H_ |
22 | 22 | ||
23 | #define MIN_FLUSH_TIMER_MS 50 | 23 | #define MIN_FLUSH_TIMER_MS 50 |
24 | #define MIN_FLUSH_TIMER_15_MS 15 | ||
25 | #define MWIFIEX_BA_WIN_SIZE_32 32 | ||
24 | 26 | ||
25 | #define PKT_TYPE_BAR 0xE7 | 27 | #define PKT_TYPE_BAR 0xE7 |
26 | #define MAX_TID_VALUE (2 << 11) | 28 | #define MAX_TID_VALUE (2 << 11) |
diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig index e70d0df9b0da..aa01c9bc77f9 100644 --- a/drivers/net/wireless/mwifiex/Kconfig +++ b/drivers/net/wireless/mwifiex/Kconfig | |||
@@ -31,7 +31,7 @@ config MWIFIEX_PCIE | |||
31 | mwifiex_pcie. | 31 | mwifiex_pcie. |
32 | 32 | ||
33 | config MWIFIEX_USB | 33 | config MWIFIEX_USB |
34 | tristate "Marvell WiFi-Ex Driver for USB8797/8897" | 34 | tristate "Marvell WiFi-Ex Driver for USB8766/8797/8897" |
35 | depends on MWIFIEX && USB | 35 | depends on MWIFIEX && USB |
36 | select FW_LOADER | 36 | select FW_LOADER |
37 | ---help--- | 37 | ---help--- |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 0dd672954ad1..17f0ee02d6e7 100644 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ b/drivers/net/wireless/mwifiex/cfg80211.c | |||
@@ -992,6 +992,52 @@ mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev, | |||
992 | return mwifiex_dump_station_info(priv, sinfo); | 992 | return mwifiex_dump_station_info(priv, sinfo); |
993 | } | 993 | } |
994 | 994 | ||
995 | static int | ||
996 | mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev, | ||
997 | int idx, struct survey_info *survey) | ||
998 | { | ||
999 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | ||
1000 | struct mwifiex_chan_stats *pchan_stats = priv->adapter->chan_stats; | ||
1001 | enum ieee80211_band band; | ||
1002 | |||
1003 | dev_dbg(priv->adapter->dev, "dump_survey idx=%d\n", idx); | ||
1004 | |||
1005 | memset(survey, 0, sizeof(struct survey_info)); | ||
1006 | |||
1007 | if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && | ||
1008 | priv->media_connected && idx == 0) { | ||
1009 | u8 curr_bss_band = priv->curr_bss_params.band; | ||
1010 | u32 chan = priv->curr_bss_params.bss_descriptor.channel; | ||
1011 | |||
1012 | band = mwifiex_band_to_radio_type(curr_bss_band); | ||
1013 | survey->channel = ieee80211_get_channel(wiphy, | ||
1014 | ieee80211_channel_to_frequency(chan, band)); | ||
1015 | |||
1016 | if (priv->bcn_nf_last) { | ||
1017 | survey->filled = SURVEY_INFO_NOISE_DBM; | ||
1018 | survey->noise = priv->bcn_nf_last; | ||
1019 | } | ||
1020 | return 0; | ||
1021 | } | ||
1022 | |||
1023 | if (idx >= priv->adapter->num_in_chan_stats) | ||
1024 | return -ENOENT; | ||
1025 | |||
1026 | if (!pchan_stats[idx].cca_scan_dur) | ||
1027 | return 0; | ||
1028 | |||
1029 | band = pchan_stats[idx].bandcfg; | ||
1030 | survey->channel = ieee80211_get_channel(wiphy, | ||
1031 | ieee80211_channel_to_frequency(pchan_stats[idx].chan_num, band)); | ||
1032 | survey->filled = SURVEY_INFO_NOISE_DBM | | ||
1033 | SURVEY_INFO_CHANNEL_TIME | SURVEY_INFO_CHANNEL_TIME_BUSY; | ||
1034 | survey->noise = pchan_stats[idx].noise; | ||
1035 | survey->channel_time = pchan_stats[idx].cca_scan_dur; | ||
1036 | survey->channel_time_busy = pchan_stats[idx].cca_busy_dur; | ||
1037 | |||
1038 | return 0; | ||
1039 | } | ||
1040 | |||
995 | /* Supported rates to be advertised to the cfg80211 */ | 1041 | /* Supported rates to be advertised to the cfg80211 */ |
996 | static struct ieee80211_rate mwifiex_rates[] = { | 1042 | static struct ieee80211_rate mwifiex_rates[] = { |
997 | {.bitrate = 10, .hw_value = 2, }, | 1043 | {.bitrate = 10, .hw_value = 2, }, |
@@ -1239,7 +1285,7 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy, | |||
1239 | */ | 1285 | */ |
1240 | static int | 1286 | static int |
1241 | mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, | 1287 | mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, |
1242 | const u8 *mac) | 1288 | struct station_del_parameters *params) |
1243 | { | 1289 | { |
1244 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); | 1290 | struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); |
1245 | struct mwifiex_sta_node *sta_node; | 1291 | struct mwifiex_sta_node *sta_node; |
@@ -1248,7 +1294,7 @@ mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
1248 | if (list_empty(&priv->sta_list) || !priv->bss_started) | 1294 | if (list_empty(&priv->sta_list) || !priv->bss_started) |
1249 | return 0; | 1295 | return 0; |
1250 | 1296 | ||
1251 | if (!mac || is_broadcast_ether_addr(mac)) { | 1297 | if (!params->mac || is_broadcast_ether_addr(params->mac)) { |
1252 | wiphy_dbg(wiphy, "%s: NULL/broadcast mac address\n", __func__); | 1298 | wiphy_dbg(wiphy, "%s: NULL/broadcast mac address\n", __func__); |
1253 | list_for_each_entry(sta_node, &priv->sta_list, list) { | 1299 | list_for_each_entry(sta_node, &priv->sta_list, list) { |
1254 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH, | 1300 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH, |
@@ -1258,9 +1304,10 @@ mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, | |||
1258 | mwifiex_uap_del_sta_data(priv, sta_node); | 1304 | mwifiex_uap_del_sta_data(priv, sta_node); |
1259 | } | 1305 | } |
1260 | } else { | 1306 | } else { |
1261 | wiphy_dbg(wiphy, "%s: mac address %pM\n", __func__, mac); | 1307 | wiphy_dbg(wiphy, "%s: mac address %pM\n", __func__, |
1308 | params->mac); | ||
1262 | spin_lock_irqsave(&priv->sta_list_spinlock, flags); | 1309 | spin_lock_irqsave(&priv->sta_list_spinlock, flags); |
1263 | sta_node = mwifiex_get_sta_entry(priv, mac); | 1310 | sta_node = mwifiex_get_sta_entry(priv, params->mac); |
1264 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); | 1311 | spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); |
1265 | if (sta_node) { | 1312 | if (sta_node) { |
1266 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH, | 1313 | if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH, |
@@ -1759,6 +1806,10 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, | |||
1759 | dev_dbg(priv->adapter->dev, | 1806 | dev_dbg(priv->adapter->dev, |
1760 | "info: associated to bssid %pM successfully\n", | 1807 | "info: associated to bssid %pM successfully\n", |
1761 | priv->cfg_bssid); | 1808 | priv->cfg_bssid); |
1809 | if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && | ||
1810 | priv->adapter->auto_tdls && | ||
1811 | priv->bss_type == MWIFIEX_BSS_TYPE_STA) | ||
1812 | mwifiex_setup_auto_tdls_timer(priv); | ||
1762 | } else { | 1813 | } else { |
1763 | dev_dbg(priv->adapter->dev, | 1814 | dev_dbg(priv->adapter->dev, |
1764 | "info: association to bssid %pM failed\n", | 1815 | "info: association to bssid %pM failed\n", |
@@ -2630,11 +2681,13 @@ mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, | |||
2630 | dev_dbg(priv->adapter->dev, | 2681 | dev_dbg(priv->adapter->dev, |
2631 | "Send TDLS Setup Request to %pM status_code=%d\n", peer, | 2682 | "Send TDLS Setup Request to %pM status_code=%d\n", peer, |
2632 | status_code); | 2683 | status_code); |
2684 | mwifiex_add_auto_tdls_peer(priv, peer); | ||
2633 | ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, | 2685 | ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, |
2634 | dialog_token, status_code, | 2686 | dialog_token, status_code, |
2635 | extra_ies, extra_ies_len); | 2687 | extra_ies, extra_ies_len); |
2636 | break; | 2688 | break; |
2637 | case WLAN_TDLS_SETUP_RESPONSE: | 2689 | case WLAN_TDLS_SETUP_RESPONSE: |
2690 | mwifiex_add_auto_tdls_peer(priv, peer); | ||
2638 | dev_dbg(priv->adapter->dev, | 2691 | dev_dbg(priv->adapter->dev, |
2639 | "Send TDLS Setup Response to %pM status_code=%d\n", | 2692 | "Send TDLS Setup Response to %pM status_code=%d\n", |
2640 | peer, status_code); | 2693 | peer, status_code); |
@@ -2779,6 +2832,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
2779 | .disconnect = mwifiex_cfg80211_disconnect, | 2832 | .disconnect = mwifiex_cfg80211_disconnect, |
2780 | .get_station = mwifiex_cfg80211_get_station, | 2833 | .get_station = mwifiex_cfg80211_get_station, |
2781 | .dump_station = mwifiex_cfg80211_dump_station, | 2834 | .dump_station = mwifiex_cfg80211_dump_station, |
2835 | .dump_survey = mwifiex_cfg80211_dump_survey, | ||
2782 | .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, | 2836 | .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, |
2783 | .join_ibss = mwifiex_cfg80211_join_ibss, | 2837 | .join_ibss = mwifiex_cfg80211_join_ibss, |
2784 | .leave_ibss = mwifiex_cfg80211_leave_ibss, | 2838 | .leave_ibss = mwifiex_cfg80211_leave_ibss, |
@@ -2840,6 +2894,25 @@ static const struct wiphy_coalesce_support mwifiex_coalesce_support = { | |||
2840 | .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN, | 2894 | .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN, |
2841 | }; | 2895 | }; |
2842 | 2896 | ||
2897 | int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter) | ||
2898 | { | ||
2899 | u32 n_channels_bg, n_channels_a = 0; | ||
2900 | |||
2901 | n_channels_bg = mwifiex_band_2ghz.n_channels; | ||
2902 | |||
2903 | if (adapter->config_bands & BAND_A) | ||
2904 | n_channels_a = mwifiex_band_5ghz.n_channels; | ||
2905 | |||
2906 | adapter->num_in_chan_stats = max_t(u32, n_channels_bg, n_channels_a); | ||
2907 | adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) * | ||
2908 | adapter->num_in_chan_stats); | ||
2909 | |||
2910 | if (!adapter->chan_stats) | ||
2911 | return -ENOMEM; | ||
2912 | |||
2913 | return 0; | ||
2914 | } | ||
2915 | |||
2843 | /* | 2916 | /* |
2844 | * This function registers the device with CFG802.11 subsystem. | 2917 | * This function registers the device with CFG802.11 subsystem. |
2845 | * | 2918 | * |
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index e0d00a7f0ec3..fc0b1ed80a6a 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h | |||
@@ -85,6 +85,11 @@ | |||
85 | #define MWIFIEX_TDLS_CREATE_LINK 0x02 | 85 | #define MWIFIEX_TDLS_CREATE_LINK 0x02 |
86 | #define MWIFIEX_TDLS_CONFIG_LINK 0x03 | 86 | #define MWIFIEX_TDLS_CONFIG_LINK 0x03 |
87 | 87 | ||
88 | #define MWIFIEX_TDLS_RSSI_HIGH 50 | ||
89 | #define MWIFIEX_TDLS_RSSI_LOW 55 | ||
90 | #define MWIFIEX_TDLS_MAX_FAIL_COUNT 4 | ||
91 | #define MWIFIEX_AUTO_TDLS_IDLE_TIME 10 | ||
92 | |||
88 | enum mwifiex_bss_type { | 93 | enum mwifiex_bss_type { |
89 | MWIFIEX_BSS_TYPE_STA = 0, | 94 | MWIFIEX_BSS_TYPE_STA = 0, |
90 | MWIFIEX_BSS_TYPE_UAP = 1, | 95 | MWIFIEX_BSS_TYPE_UAP = 1, |
@@ -185,4 +190,14 @@ struct mwifiex_arp_eth_header { | |||
185 | u8 ar_tha[ETH_ALEN]; | 190 | u8 ar_tha[ETH_ALEN]; |
186 | u8 ar_tip[4]; | 191 | u8 ar_tip[4]; |
187 | } __packed; | 192 | } __packed; |
193 | |||
194 | struct mwifiex_chan_stats { | ||
195 | u8 chan_num; | ||
196 | u8 bandcfg; | ||
197 | u8 flags; | ||
198 | s8 noise; | ||
199 | u16 total_bss; | ||
200 | u16 cca_scan_dur; | ||
201 | u16 cca_busy_dur; | ||
202 | } __packed; | ||
188 | #endif /* !_MWIFIEX_DECL_H_ */ | 203 | #endif /* !_MWIFIEX_DECL_H_ */ |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 1eb61739071f..e095f371545a 100644 --- a/drivers/net/wireless/mwifiex/fw.h +++ b/drivers/net/wireless/mwifiex/fw.h | |||
@@ -172,6 +172,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER { | |||
172 | #define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194) | 172 | #define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194) |
173 | #define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197) | 173 | #define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197) |
174 | #define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199) | 174 | #define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199) |
175 | #define TLV_TYPE_CHANNEL_STATS (PROPRIETARY_TLV_BASE_ID + 198) | ||
175 | 176 | ||
176 | #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 | 177 | #define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 |
177 | 178 | ||
@@ -583,6 +584,7 @@ struct rxpd { | |||
583 | * [Bit 7] Reserved | 584 | * [Bit 7] Reserved |
584 | */ | 585 | */ |
585 | u8 ht_info; | 586 | u8 ht_info; |
587 | u8 reserved[3]; | ||
586 | u8 flags; | 588 | u8 flags; |
587 | } __packed; | 589 | } __packed; |
588 | 590 | ||
@@ -611,6 +613,16 @@ struct uap_rxpd { | |||
611 | u8 reserved1; | 613 | u8 reserved1; |
612 | }; | 614 | }; |
613 | 615 | ||
616 | struct mwifiex_fw_chan_stats { | ||
617 | u8 chan_num; | ||
618 | u8 bandcfg; | ||
619 | u8 flags; | ||
620 | s8 noise; | ||
621 | __le16 total_bss; | ||
622 | __le16 cca_scan_dur; | ||
623 | __le16 cca_busy_dur; | ||
624 | } __packed; | ||
625 | |||
614 | enum mwifiex_chan_scan_mode_bitmasks { | 626 | enum mwifiex_chan_scan_mode_bitmasks { |
615 | MWIFIEX_PASSIVE_SCAN = BIT(0), | 627 | MWIFIEX_PASSIVE_SCAN = BIT(0), |
616 | MWIFIEX_DISABLE_CHAN_FILT = BIT(1), | 628 | MWIFIEX_DISABLE_CHAN_FILT = BIT(1), |
@@ -660,6 +672,11 @@ struct mwifiex_ie_types_scan_chan_gap { | |||
660 | __le16 chan_gap; | 672 | __le16 chan_gap; |
661 | } __packed; | 673 | } __packed; |
662 | 674 | ||
675 | struct mwifiex_ietypes_chanstats { | ||
676 | struct mwifiex_ie_types_header header; | ||
677 | struct mwifiex_fw_chan_stats chanstats[0]; | ||
678 | } __packed; | ||
679 | |||
663 | struct mwifiex_ie_types_wildcard_ssid_params { | 680 | struct mwifiex_ie_types_wildcard_ssid_params { |
664 | struct mwifiex_ie_types_header header; | 681 | struct mwifiex_ie_types_header header; |
665 | u8 max_ssid_length; | 682 | u8 max_ssid_length; |
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c index 580aa45ec4bc..cc15ab81aa66 100644 --- a/drivers/net/wireless/mwifiex/init.c +++ b/drivers/net/wireless/mwifiex/init.c | |||
@@ -137,6 +137,7 @@ int mwifiex_init_priv(struct mwifiex_private *priv) | |||
137 | priv->csa_expire_time = 0; | 137 | priv->csa_expire_time = 0; |
138 | priv->del_list_idx = 0; | 138 | priv->del_list_idx = 0; |
139 | priv->hs2_enabled = false; | 139 | priv->hs2_enabled = false; |
140 | priv->check_tdls_tx = false; | ||
140 | memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID); | 141 | memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID); |
141 | 142 | ||
142 | return mwifiex_add_bss_prio_tbl(priv); | 143 | return mwifiex_add_bss_prio_tbl(priv); |
@@ -366,6 +367,7 @@ static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) | |||
366 | list_del(&priv->tx_ba_stream_tbl_ptr); | 367 | list_del(&priv->tx_ba_stream_tbl_ptr); |
367 | list_del(&priv->rx_reorder_tbl_ptr); | 368 | list_del(&priv->rx_reorder_tbl_ptr); |
368 | list_del(&priv->sta_list); | 369 | list_del(&priv->sta_list); |
370 | list_del(&priv->auto_tdls_list); | ||
369 | } | 371 | } |
370 | } | 372 | } |
371 | } | 373 | } |
@@ -434,6 +436,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) | |||
434 | spin_lock_init(&priv->wmm.ra_list_spinlock); | 436 | spin_lock_init(&priv->wmm.ra_list_spinlock); |
435 | spin_lock_init(&priv->curr_bcn_buf_lock); | 437 | spin_lock_init(&priv->curr_bcn_buf_lock); |
436 | spin_lock_init(&priv->sta_list_spinlock); | 438 | spin_lock_init(&priv->sta_list_spinlock); |
439 | spin_lock_init(&priv->auto_tdls_lock); | ||
437 | } | 440 | } |
438 | } | 441 | } |
439 | 442 | ||
@@ -449,7 +452,6 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) | |||
449 | spin_lock_init(&adapter->scan_pending_q_lock); | 452 | spin_lock_init(&adapter->scan_pending_q_lock); |
450 | spin_lock_init(&adapter->rx_proc_lock); | 453 | spin_lock_init(&adapter->rx_proc_lock); |
451 | 454 | ||
452 | skb_queue_head_init(&adapter->usb_rx_data_q); | ||
453 | skb_queue_head_init(&adapter->rx_data_q); | 455 | skb_queue_head_init(&adapter->rx_data_q); |
454 | 456 | ||
455 | for (i = 0; i < adapter->priv_num; ++i) { | 457 | for (i = 0; i < adapter->priv_num; ++i) { |
@@ -466,6 +468,7 @@ int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) | |||
466 | INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); | 468 | INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); |
467 | INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); | 469 | INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); |
468 | INIT_LIST_HEAD(&priv->sta_list); | 470 | INIT_LIST_HEAD(&priv->sta_list); |
471 | INIT_LIST_HEAD(&priv->auto_tdls_list); | ||
469 | skb_queue_head_init(&priv->tdls_txq); | 472 | skb_queue_head_init(&priv->tdls_txq); |
470 | 473 | ||
471 | spin_lock_init(&priv->tx_ba_stream_tbl_lock); | 474 | spin_lock_init(&priv->tx_ba_stream_tbl_lock); |
@@ -646,6 +649,7 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) | |||
646 | if (adapter->priv[i]) { | 649 | if (adapter->priv[i]) { |
647 | priv = adapter->priv[i]; | 650 | priv = adapter->priv[i]; |
648 | 651 | ||
652 | mwifiex_clean_auto_tdls(priv); | ||
649 | mwifiex_clean_txrx(priv); | 653 | mwifiex_clean_txrx(priv); |
650 | mwifiex_delete_bss_prio_tbl(priv); | 654 | mwifiex_delete_bss_prio_tbl(priv); |
651 | } | 655 | } |
@@ -668,19 +672,6 @@ mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) | |||
668 | 672 | ||
669 | spin_lock(&adapter->mwifiex_lock); | 673 | spin_lock(&adapter->mwifiex_lock); |
670 | 674 | ||
671 | if (adapter->if_ops.data_complete) { | ||
672 | while ((skb = skb_dequeue(&adapter->usb_rx_data_q))) { | ||
673 | struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); | ||
674 | |||
675 | priv = adapter->priv[rx_info->bss_num]; | ||
676 | if (priv) | ||
677 | priv->stats.rx_dropped++; | ||
678 | |||
679 | dev_kfree_skb_any(skb); | ||
680 | adapter->if_ops.data_complete(adapter); | ||
681 | } | ||
682 | } | ||
683 | |||
684 | mwifiex_adapter_cleanup(adapter); | 675 | mwifiex_adapter_cleanup(adapter); |
685 | 676 | ||
686 | spin_unlock(&adapter->mwifiex_lock); | 677 | spin_unlock(&adapter->mwifiex_lock); |
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c index 8d6c25908b6d..411a6c2f4aca 100644 --- a/drivers/net/wireless/mwifiex/join.c +++ b/drivers/net/wireless/mwifiex/join.c | |||
@@ -880,9 +880,7 @@ mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, | |||
880 | 880 | ||
881 | /* Set Capability info */ | 881 | /* Set Capability info */ |
882 | bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_IBSS; | 882 | bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_IBSS; |
883 | tmp_cap = le16_to_cpu(adhoc_start->cap_info_bitmap); | 883 | tmp_cap = WLAN_CAPABILITY_IBSS; |
884 | tmp_cap &= ~WLAN_CAPABILITY_ESS; | ||
885 | tmp_cap |= WLAN_CAPABILITY_IBSS; | ||
886 | 884 | ||
887 | /* Set up privacy in bss_desc */ | 885 | /* Set up privacy in bss_desc */ |
888 | if (priv->sec_info.encryption_mode) { | 886 | if (priv->sec_info.encryption_mode) { |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index d5070c444fe1..0e50120eb807 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -28,6 +28,11 @@ const char driver_version[] = "mwifiex " VERSION " (%s) "; | |||
28 | static char *cal_data_cfg; | 28 | static char *cal_data_cfg; |
29 | module_param(cal_data_cfg, charp, 0); | 29 | module_param(cal_data_cfg, charp, 0); |
30 | 30 | ||
31 | static unsigned short driver_mode; | ||
32 | module_param(driver_mode, ushort, 0); | ||
33 | MODULE_PARM_DESC(driver_mode, | ||
34 | "station=0x1(default), ap-sta=0x3, station-p2p=0x5, ap-sta-p2p=0x7"); | ||
35 | |||
31 | /* | 36 | /* |
32 | * This function registers the device and performs all the necessary | 37 | * This function registers the device and performs all the necessary |
33 | * initializations. | 38 | * initializations. |
@@ -122,6 +127,7 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter) | |||
122 | } | 127 | } |
123 | } | 128 | } |
124 | 129 | ||
130 | vfree(adapter->chan_stats); | ||
125 | kfree(adapter); | 131 | kfree(adapter); |
126 | return 0; | 132 | return 0; |
127 | } | 133 | } |
@@ -145,6 +151,8 @@ static int mwifiex_process_rx(struct mwifiex_adapter *adapter) | |||
145 | atomic_dec(&adapter->rx_pending); | 151 | atomic_dec(&adapter->rx_pending); |
146 | if (adapter->delay_main_work && | 152 | if (adapter->delay_main_work && |
147 | (atomic_read(&adapter->rx_pending) < LOW_RX_PENDING)) { | 153 | (atomic_read(&adapter->rx_pending) < LOW_RX_PENDING)) { |
154 | if (adapter->if_ops.submit_rem_rx_urbs) | ||
155 | adapter->if_ops.submit_rem_rx_urbs(adapter); | ||
148 | adapter->delay_main_work = false; | 156 | adapter->delay_main_work = false; |
149 | queue_work(adapter->workqueue, &adapter->main_work); | 157 | queue_work(adapter->workqueue, &adapter->main_work); |
150 | } | 158 | } |
@@ -177,7 +185,6 @@ int mwifiex_main_process(struct mwifiex_adapter *adapter) | |||
177 | { | 185 | { |
178 | int ret = 0; | 186 | int ret = 0; |
179 | unsigned long flags; | 187 | unsigned long flags; |
180 | struct sk_buff *skb; | ||
181 | 188 | ||
182 | spin_lock_irqsave(&adapter->main_proc_lock, flags); | 189 | spin_lock_irqsave(&adapter->main_proc_lock, flags); |
183 | 190 | ||
@@ -252,11 +259,6 @@ process_start: | |||
252 | } | 259 | } |
253 | } | 260 | } |
254 | 261 | ||
255 | /* Check Rx data for USB */ | ||
256 | if (adapter->iface_type == MWIFIEX_USB) | ||
257 | while ((skb = skb_dequeue(&adapter->usb_rx_data_q))) | ||
258 | mwifiex_handle_rx_packet(adapter, skb); | ||
259 | |||
260 | /* Check for event */ | 262 | /* Check for event */ |
261 | if (adapter->event_received) { | 263 | if (adapter->event_received) { |
262 | adapter->event_received = false; | 264 | adapter->event_received = false; |
@@ -447,6 +449,16 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) | |||
447 | goto err_init_fw; | 449 | goto err_init_fw; |
448 | } | 450 | } |
449 | 451 | ||
452 | if (mwifiex_init_channel_scan_gap(adapter)) { | ||
453 | dev_err(adapter->dev, "could not init channel stats table\n"); | ||
454 | goto err_init_fw; | ||
455 | } | ||
456 | |||
457 | if (driver_mode) { | ||
458 | driver_mode &= MWIFIEX_DRIVER_MODE_BITMASK; | ||
459 | driver_mode |= MWIFIEX_DRIVER_MODE_STA; | ||
460 | } | ||
461 | |||
450 | rtnl_lock(); | 462 | rtnl_lock(); |
451 | /* Create station interface by default */ | 463 | /* Create station interface by default */ |
452 | wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", | 464 | wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", |
@@ -456,6 +468,28 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) | |||
456 | rtnl_unlock(); | 468 | rtnl_unlock(); |
457 | goto err_add_intf; | 469 | goto err_add_intf; |
458 | } | 470 | } |
471 | |||
472 | if (driver_mode & MWIFIEX_DRIVER_MODE_UAP) { | ||
473 | wdev = mwifiex_add_virtual_intf(adapter->wiphy, "uap%d", | ||
474 | NL80211_IFTYPE_AP, NULL, NULL); | ||
475 | if (IS_ERR(wdev)) { | ||
476 | dev_err(adapter->dev, "cannot create AP interface\n"); | ||
477 | rtnl_unlock(); | ||
478 | goto err_add_intf; | ||
479 | } | ||
480 | } | ||
481 | |||
482 | if (driver_mode & MWIFIEX_DRIVER_MODE_P2P) { | ||
483 | wdev = mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d", | ||
484 | NL80211_IFTYPE_P2P_CLIENT, NULL, | ||
485 | NULL); | ||
486 | if (IS_ERR(wdev)) { | ||
487 | dev_err(adapter->dev, | ||
488 | "cannot create p2p client interface\n"); | ||
489 | rtnl_unlock(); | ||
490 | goto err_add_intf; | ||
491 | } | ||
492 | } | ||
459 | rtnl_unlock(); | 493 | rtnl_unlock(); |
460 | 494 | ||
461 | mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); | 495 | mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); |
@@ -628,6 +662,13 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) | |||
628 | */ | 662 | */ |
629 | __net_timestamp(skb); | 663 | __net_timestamp(skb); |
630 | 664 | ||
665 | if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && | ||
666 | priv->bss_type == MWIFIEX_BSS_TYPE_STA && | ||
667 | !ether_addr_equal_unaligned(priv->cfg_bssid, skb->data)) { | ||
668 | if (priv->adapter->auto_tdls && priv->check_tdls_tx) | ||
669 | mwifiex_tdls_check_tx(priv, skb); | ||
670 | } | ||
671 | |||
631 | mwifiex_queue_tx_pkt(priv, skb); | 672 | mwifiex_queue_tx_pkt(priv, skb); |
632 | 673 | ||
633 | return 0; | 674 | return 0; |
@@ -858,7 +899,7 @@ mwifiex_add_card(void *card, struct semaphore *sem, | |||
858 | adapter->cmd_wait_q.status = 0; | 899 | adapter->cmd_wait_q.status = 0; |
859 | adapter->scan_wait_q_woken = false; | 900 | adapter->scan_wait_q_woken = false; |
860 | 901 | ||
861 | if (num_possible_cpus() > 1) { | 902 | if ((num_possible_cpus() > 1) || adapter->iface_type == MWIFIEX_USB) { |
862 | adapter->rx_work_enabled = true; | 903 | adapter->rx_work_enabled = true; |
863 | pr_notice("rx work enabled, cpus %d\n", num_possible_cpus()); | 904 | pr_notice("rx work enabled, cpus %d\n", num_possible_cpus()); |
864 | } | 905 | } |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index e2635747d966..5a690d5210f0 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -48,6 +48,11 @@ enum { | |||
48 | MWIFIEX_SYNC_CMD | 48 | MWIFIEX_SYNC_CMD |
49 | }; | 49 | }; |
50 | 50 | ||
51 | #define MWIFIEX_DRIVER_MODE_STA BIT(0) | ||
52 | #define MWIFIEX_DRIVER_MODE_UAP BIT(1) | ||
53 | #define MWIFIEX_DRIVER_MODE_P2P BIT(2) | ||
54 | #define MWIFIEX_DRIVER_MODE_BITMASK (BIT(0) | BIT(1) | BIT(2)) | ||
55 | |||
51 | #define MWIFIEX_MAX_AP 64 | 56 | #define MWIFIEX_MAX_AP 64 |
52 | 57 | ||
53 | #define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) | 58 | #define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) |
@@ -106,10 +111,7 @@ enum { | |||
106 | */ | 111 | */ |
107 | #define IS_CARD_RX_RCVD(adapter) (adapter->cmd_resp_received || \ | 112 | #define IS_CARD_RX_RCVD(adapter) (adapter->cmd_resp_received || \ |
108 | adapter->event_received || \ | 113 | adapter->event_received || \ |
109 | ((adapter->iface_type != MWIFIEX_USB) && \ | 114 | adapter->data_received) |
110 | adapter->data_received) || \ | ||
111 | ((adapter->iface_type == MWIFIEX_USB) && \ | ||
112 | !skb_queue_empty(&adapter->usb_rx_data_q))) | ||
113 | 115 | ||
114 | #define MWIFIEX_TYPE_CMD 1 | 116 | #define MWIFIEX_TYPE_CMD 1 |
115 | #define MWIFIEX_TYPE_DATA 0 | 117 | #define MWIFIEX_TYPE_DATA 0 |
@@ -504,8 +506,11 @@ struct mwifiex_private { | |||
504 | struct mwifiex_wmm_desc wmm; | 506 | struct mwifiex_wmm_desc wmm; |
505 | atomic_t wmm_tx_pending[IEEE80211_NUM_ACS]; | 507 | atomic_t wmm_tx_pending[IEEE80211_NUM_ACS]; |
506 | struct list_head sta_list; | 508 | struct list_head sta_list; |
507 | /* spin lock for associated station list */ | 509 | /* spin lock for associated station/TDLS peers list */ |
508 | spinlock_t sta_list_spinlock; | 510 | spinlock_t sta_list_spinlock; |
511 | struct list_head auto_tdls_list; | ||
512 | /* spin lock for auto TDLS peer list */ | ||
513 | spinlock_t auto_tdls_lock; | ||
509 | struct list_head tx_ba_stream_tbl_ptr; | 514 | struct list_head tx_ba_stream_tbl_ptr; |
510 | /* spin lock for tx_ba_stream_tbl_ptr queue */ | 515 | /* spin lock for tx_ba_stream_tbl_ptr queue */ |
511 | spinlock_t tx_ba_stream_tbl_lock; | 516 | spinlock_t tx_ba_stream_tbl_lock; |
@@ -570,6 +575,9 @@ struct mwifiex_private { | |||
570 | bool hs2_enabled; | 575 | bool hs2_enabled; |
571 | struct station_parameters *sta_params; | 576 | struct station_parameters *sta_params; |
572 | struct sk_buff_head tdls_txq; | 577 | struct sk_buff_head tdls_txq; |
578 | u8 check_tdls_tx; | ||
579 | struct timer_list auto_tdls_timer; | ||
580 | bool auto_tdls_timer_active; | ||
573 | }; | 581 | }; |
574 | 582 | ||
575 | enum mwifiex_ba_status { | 583 | enum mwifiex_ba_status { |
@@ -592,6 +600,7 @@ struct reorder_tmr_cnxt { | |||
592 | struct timer_list timer; | 600 | struct timer_list timer; |
593 | struct mwifiex_rx_reorder_tbl *ptr; | 601 | struct mwifiex_rx_reorder_tbl *ptr; |
594 | struct mwifiex_private *priv; | 602 | struct mwifiex_private *priv; |
603 | u8 timer_is_set; | ||
595 | }; | 604 | }; |
596 | 605 | ||
597 | struct mwifiex_rx_reorder_tbl { | 606 | struct mwifiex_rx_reorder_tbl { |
@@ -669,6 +678,17 @@ struct mwifiex_sta_node { | |||
669 | struct mwifiex_tdls_capab tdls_cap; | 678 | struct mwifiex_tdls_capab tdls_cap; |
670 | }; | 679 | }; |
671 | 680 | ||
681 | struct mwifiex_auto_tdls_peer { | ||
682 | struct list_head list; | ||
683 | u8 mac_addr[ETH_ALEN]; | ||
684 | u8 tdls_status; | ||
685 | int rssi; | ||
686 | long rssi_jiffies; | ||
687 | u8 failure_count; | ||
688 | u8 do_discover; | ||
689 | u8 do_setup; | ||
690 | }; | ||
691 | |||
672 | struct mwifiex_if_ops { | 692 | struct mwifiex_if_ops { |
673 | int (*init_if) (struct mwifiex_adapter *); | 693 | int (*init_if) (struct mwifiex_adapter *); |
674 | void (*cleanup_if) (struct mwifiex_adapter *); | 694 | void (*cleanup_if) (struct mwifiex_adapter *); |
@@ -689,13 +709,13 @@ struct mwifiex_if_ops { | |||
689 | void (*cleanup_mpa_buf) (struct mwifiex_adapter *); | 709 | void (*cleanup_mpa_buf) (struct mwifiex_adapter *); |
690 | int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *); | 710 | int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *); |
691 | int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *); | 711 | int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *); |
692 | int (*data_complete) (struct mwifiex_adapter *); | ||
693 | int (*init_fw_port) (struct mwifiex_adapter *); | 712 | int (*init_fw_port) (struct mwifiex_adapter *); |
694 | int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *); | 713 | int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *); |
695 | void (*card_reset) (struct mwifiex_adapter *); | 714 | void (*card_reset) (struct mwifiex_adapter *); |
696 | void (*fw_dump)(struct mwifiex_adapter *); | 715 | void (*fw_dump)(struct mwifiex_adapter *); |
697 | int (*clean_pcie_ring) (struct mwifiex_adapter *adapter); | 716 | int (*clean_pcie_ring) (struct mwifiex_adapter *adapter); |
698 | void (*iface_work)(struct work_struct *work); | 717 | void (*iface_work)(struct work_struct *work); |
718 | void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter); | ||
699 | }; | 719 | }; |
700 | 720 | ||
701 | struct mwifiex_adapter { | 721 | struct mwifiex_adapter { |
@@ -766,7 +786,6 @@ struct mwifiex_adapter { | |||
766 | spinlock_t scan_pending_q_lock; | 786 | spinlock_t scan_pending_q_lock; |
767 | /* spin lock for RX processing routine */ | 787 | /* spin lock for RX processing routine */ |
768 | spinlock_t rx_proc_lock; | 788 | spinlock_t rx_proc_lock; |
769 | struct sk_buff_head usb_rx_data_q; | ||
770 | u32 scan_processing; | 789 | u32 scan_processing; |
771 | u16 region_code; | 790 | u16 region_code; |
772 | struct mwifiex_802_11d_domain_reg domain_reg; | 791 | struct mwifiex_802_11d_domain_reg domain_reg; |
@@ -844,6 +863,10 @@ struct mwifiex_adapter { | |||
844 | u8 curr_mem_idx; | 863 | u8 curr_mem_idx; |
845 | bool scan_chan_gap_enabled; | 864 | bool scan_chan_gap_enabled; |
846 | struct sk_buff_head rx_data_q; | 865 | struct sk_buff_head rx_data_q; |
866 | struct mwifiex_chan_stats *chan_stats; | ||
867 | u32 num_in_chan_stats; | ||
868 | int survey_idx; | ||
869 | bool auto_tdls; | ||
847 | }; | 870 | }; |
848 | 871 | ||
849 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); | 872 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); |
@@ -1030,7 +1053,8 @@ void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv); | |||
1030 | int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, | 1053 | int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, |
1031 | struct host_cmd_ds_command *cmd, | 1054 | struct host_cmd_ds_command *cmd, |
1032 | void *data_buf); | 1055 | void *data_buf); |
1033 | int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv); | 1056 | int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv, |
1057 | struct host_cmd_ds_command *resp); | ||
1034 | int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv, | 1058 | int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv, |
1035 | void *buf); | 1059 | void *buf); |
1036 | 1060 | ||
@@ -1300,6 +1324,17 @@ u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band, | |||
1300 | u32 pri_chan, u8 chan_bw); | 1324 | u32 pri_chan, u8 chan_bw); |
1301 | int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter); | 1325 | int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter); |
1302 | 1326 | ||
1327 | int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb); | ||
1328 | void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv); | ||
1329 | void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv, | ||
1330 | const u8 *mac, u8 link_status); | ||
1331 | void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv, | ||
1332 | u8 *mac, s8 snr, s8 nflr); | ||
1333 | void mwifiex_check_auto_tdls(unsigned long context); | ||
1334 | void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac); | ||
1335 | void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv); | ||
1336 | void mwifiex_clean_auto_tdls(struct mwifiex_private *priv); | ||
1337 | |||
1303 | #ifdef CONFIG_DEBUG_FS | 1338 | #ifdef CONFIG_DEBUG_FS |
1304 | void mwifiex_debugfs_init(void); | 1339 | void mwifiex_debugfs_init(void); |
1305 | void mwifiex_debugfs_remove(void); | 1340 | void mwifiex_debugfs_remove(void); |
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c index ca64d4c94112..3a17821157d7 100644 --- a/drivers/net/wireless/mwifiex/scan.c +++ b/drivers/net/wireless/mwifiex/scan.c | |||
@@ -1755,6 +1755,7 @@ static void mwifiex_complete_scan(struct mwifiex_private *priv) | |||
1755 | { | 1755 | { |
1756 | struct mwifiex_adapter *adapter = priv->adapter; | 1756 | struct mwifiex_adapter *adapter = priv->adapter; |
1757 | 1757 | ||
1758 | adapter->survey_idx = 0; | ||
1758 | if (adapter->curr_cmd->wait_q_enabled) { | 1759 | if (adapter->curr_cmd->wait_q_enabled) { |
1759 | adapter->cmd_wait_q.status = 0; | 1760 | adapter->cmd_wait_q.status = 0; |
1760 | if (!priv->scan_request) { | 1761 | if (!priv->scan_request) { |
@@ -1976,10 +1977,53 @@ int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, | |||
1976 | return 0; | 1977 | return 0; |
1977 | } | 1978 | } |
1978 | 1979 | ||
1980 | static void | ||
1981 | mwifiex_update_chan_statistics(struct mwifiex_private *priv, | ||
1982 | struct mwifiex_ietypes_chanstats *tlv_stat) | ||
1983 | { | ||
1984 | struct mwifiex_adapter *adapter = priv->adapter; | ||
1985 | u8 i, num_chan; | ||
1986 | struct mwifiex_fw_chan_stats *fw_chan_stats; | ||
1987 | struct mwifiex_chan_stats chan_stats; | ||
1988 | |||
1989 | fw_chan_stats = (void *)((u8 *)tlv_stat + | ||
1990 | sizeof(struct mwifiex_ie_types_header)); | ||
1991 | num_chan = le16_to_cpu(tlv_stat->header.len) / | ||
1992 | sizeof(struct mwifiex_chan_stats); | ||
1993 | |||
1994 | for (i = 0 ; i < num_chan; i++) { | ||
1995 | chan_stats.chan_num = fw_chan_stats->chan_num; | ||
1996 | chan_stats.bandcfg = fw_chan_stats->bandcfg; | ||
1997 | chan_stats.flags = fw_chan_stats->flags; | ||
1998 | chan_stats.noise = fw_chan_stats->noise; | ||
1999 | chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss); | ||
2000 | chan_stats.cca_scan_dur = | ||
2001 | le16_to_cpu(fw_chan_stats->cca_scan_dur); | ||
2002 | chan_stats.cca_busy_dur = | ||
2003 | le16_to_cpu(fw_chan_stats->cca_busy_dur); | ||
2004 | dev_dbg(adapter->dev, | ||
2005 | "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n", | ||
2006 | chan_stats.chan_num, | ||
2007 | chan_stats.noise, | ||
2008 | chan_stats.total_bss, | ||
2009 | chan_stats.cca_scan_dur, | ||
2010 | chan_stats.cca_busy_dur); | ||
2011 | memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats, | ||
2012 | sizeof(struct mwifiex_chan_stats)); | ||
2013 | fw_chan_stats++; | ||
2014 | } | ||
2015 | } | ||
2016 | |||
1979 | /* This function handles the command response of extended scan */ | 2017 | /* This function handles the command response of extended scan */ |
1980 | int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv) | 2018 | int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv, |
2019 | struct host_cmd_ds_command *resp) | ||
1981 | { | 2020 | { |
1982 | struct mwifiex_adapter *adapter = priv->adapter; | 2021 | struct mwifiex_adapter *adapter = priv->adapter; |
2022 | struct host_cmd_ds_802_11_scan_ext *ext_scan_resp; | ||
2023 | struct mwifiex_ie_types_header *tlv; | ||
2024 | struct mwifiex_ietypes_chanstats *tlv_stat; | ||
2025 | u16 buf_left, type, len; | ||
2026 | |||
1983 | struct host_cmd_ds_command *cmd_ptr; | 2027 | struct host_cmd_ds_command *cmd_ptr; |
1984 | struct cmd_ctrl_node *cmd_node; | 2028 | struct cmd_ctrl_node *cmd_node; |
1985 | unsigned long cmd_flags, scan_flags; | 2029 | unsigned long cmd_flags, scan_flags; |
@@ -1987,6 +2031,36 @@ int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv) | |||
1987 | 2031 | ||
1988 | dev_dbg(priv->adapter->dev, "info: EXT scan returns successfully\n"); | 2032 | dev_dbg(priv->adapter->dev, "info: EXT scan returns successfully\n"); |
1989 | 2033 | ||
2034 | ext_scan_resp = &resp->params.ext_scan; | ||
2035 | |||
2036 | tlv = (void *)ext_scan_resp->tlv_buffer; | ||
2037 | buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN | ||
2038 | - 1); | ||
2039 | |||
2040 | while (buf_left >= sizeof(struct mwifiex_ie_types_header)) { | ||
2041 | type = le16_to_cpu(tlv->type); | ||
2042 | len = le16_to_cpu(tlv->len); | ||
2043 | |||
2044 | if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) { | ||
2045 | dev_err(adapter->dev, | ||
2046 | "error processing scan response TLVs"); | ||
2047 | break; | ||
2048 | } | ||
2049 | |||
2050 | switch (type) { | ||
2051 | case TLV_TYPE_CHANNEL_STATS: | ||
2052 | tlv_stat = (void *)tlv; | ||
2053 | mwifiex_update_chan_statistics(priv, tlv_stat); | ||
2054 | break; | ||
2055 | default: | ||
2056 | break; | ||
2057 | } | ||
2058 | |||
2059 | buf_left -= len + sizeof(struct mwifiex_ie_types_header); | ||
2060 | tlv = (void *)((u8 *)tlv + len + | ||
2061 | sizeof(struct mwifiex_ie_types_header)); | ||
2062 | } | ||
2063 | |||
1990 | spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags); | 2064 | spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags); |
1991 | spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags); | 2065 | spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags); |
1992 | if (list_empty(&adapter->scan_pending_q)) { | 2066 | if (list_empty(&adapter->scan_pending_q)) { |
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c index b25766b43b9f..933dae137850 100644 --- a/drivers/net/wireless/mwifiex/sdio.c +++ b/drivers/net/wireless/mwifiex/sdio.c | |||
@@ -106,6 +106,7 @@ mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) | |||
106 | card->mp_tx_agg_buf_size = data->mp_tx_agg_buf_size; | 106 | card->mp_tx_agg_buf_size = data->mp_tx_agg_buf_size; |
107 | card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size; | 107 | card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size; |
108 | card->supports_fw_dump = data->supports_fw_dump; | 108 | card->supports_fw_dump = data->supports_fw_dump; |
109 | card->auto_tdls = data->auto_tdls; | ||
109 | } | 110 | } |
110 | 111 | ||
111 | sdio_claim_host(func); | 112 | sdio_claim_host(func); |
@@ -1880,6 +1881,7 @@ static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) | |||
1880 | return -1; | 1881 | return -1; |
1881 | } | 1882 | } |
1882 | 1883 | ||
1884 | adapter->auto_tdls = card->auto_tdls; | ||
1883 | return ret; | 1885 | return ret; |
1884 | } | 1886 | } |
1885 | 1887 | ||
diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h index 20cd9adc98d3..54c07156dd78 100644 --- a/drivers/net/wireless/mwifiex/sdio.h +++ b/drivers/net/wireless/mwifiex/sdio.h | |||
@@ -246,6 +246,7 @@ struct sdio_mmc_card { | |||
246 | u8 curr_wr_port; | 246 | u8 curr_wr_port; |
247 | 247 | ||
248 | u8 *mp_regs; | 248 | u8 *mp_regs; |
249 | u8 auto_tdls; | ||
249 | 250 | ||
250 | struct mwifiex_sdio_mpa_tx mpa_tx; | 251 | struct mwifiex_sdio_mpa_tx mpa_tx; |
251 | struct mwifiex_sdio_mpa_rx mpa_rx; | 252 | struct mwifiex_sdio_mpa_rx mpa_rx; |
@@ -262,6 +263,7 @@ struct mwifiex_sdio_device { | |||
262 | u16 tx_buf_size; | 263 | u16 tx_buf_size; |
263 | u32 mp_tx_agg_buf_size; | 264 | u32 mp_tx_agg_buf_size; |
264 | u32 mp_rx_agg_buf_size; | 265 | u32 mp_rx_agg_buf_size; |
266 | u8 auto_tdls; | ||
265 | }; | 267 | }; |
266 | 268 | ||
267 | static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = { | 269 | static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = { |
@@ -387,6 +389,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = { | |||
387 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | 389 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, |
388 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | 390 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, |
389 | .supports_fw_dump = false, | 391 | .supports_fw_dump = false, |
392 | .auto_tdls = false, | ||
390 | }; | 393 | }; |
391 | 394 | ||
392 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { | 395 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { |
@@ -400,6 +403,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { | |||
400 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | 403 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, |
401 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | 404 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, |
402 | .supports_fw_dump = false, | 405 | .supports_fw_dump = false, |
406 | .auto_tdls = false, | ||
403 | }; | 407 | }; |
404 | 408 | ||
405 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { | 409 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { |
@@ -413,6 +417,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { | |||
413 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | 417 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, |
414 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, | 418 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, |
415 | .supports_fw_dump = false, | 419 | .supports_fw_dump = false, |
420 | .auto_tdls = false, | ||
416 | }; | 421 | }; |
417 | 422 | ||
418 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { | 423 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { |
@@ -426,6 +431,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { | |||
426 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, | 431 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, |
427 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, | 432 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, |
428 | .supports_fw_dump = true, | 433 | .supports_fw_dump = true, |
434 | .auto_tdls = false, | ||
429 | }; | 435 | }; |
430 | 436 | ||
431 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = { | 437 | static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = { |
@@ -439,6 +445,7 @@ static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = { | |||
439 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, | 445 | .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, |
440 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, | 446 | .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, |
441 | .supports_fw_dump = false, | 447 | .supports_fw_dump = false, |
448 | .auto_tdls = true, | ||
442 | }; | 449 | }; |
443 | 450 | ||
444 | /* | 451 | /* |
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c index 4aad44685f8d..b65e1014b0fc 100644 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c | |||
@@ -983,7 +983,7 @@ int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, | |||
983 | adapter->curr_cmd->wait_q_enabled = false; | 983 | adapter->curr_cmd->wait_q_enabled = false; |
984 | break; | 984 | break; |
985 | case HostCmd_CMD_802_11_SCAN_EXT: | 985 | case HostCmd_CMD_802_11_SCAN_EXT: |
986 | ret = mwifiex_ret_802_11_scan_ext(priv); | 986 | ret = mwifiex_ret_802_11_scan_ext(priv, resp); |
987 | adapter->curr_cmd->wait_q_enabled = false; | 987 | adapter->curr_cmd->wait_q_enabled = false; |
988 | break; | 988 | break; |
989 | case HostCmd_CMD_802_11_BG_SCAN_QUERY: | 989 | case HostCmd_CMD_802_11_BG_SCAN_QUERY: |
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c index f1c240eca0cd..204ecc8faa5b 100644 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ b/drivers/net/wireless/mwifiex/sta_event.c | |||
@@ -55,9 +55,13 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code) | |||
55 | priv->scan_block = false; | 55 | priv->scan_block = false; |
56 | 56 | ||
57 | if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && | 57 | if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && |
58 | ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) | 58 | ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) { |
59 | mwifiex_disable_all_tdls_links(priv); | 59 | mwifiex_disable_all_tdls_links(priv); |
60 | 60 | ||
61 | if (priv->adapter->auto_tdls) | ||
62 | mwifiex_clean_auto_tdls(priv); | ||
63 | } | ||
64 | |||
61 | /* Free Tx and Rx packets, report disconnect to upper layer */ | 65 | /* Free Tx and Rx packets, report disconnect to upper layer */ |
62 | mwifiex_clean_txrx(priv); | 66 | mwifiex_clean_txrx(priv); |
63 | 67 | ||
@@ -163,9 +167,6 @@ static int mwifiex_parse_tdls_event(struct mwifiex_private *priv, | |||
163 | NL80211_TDLS_TEARDOWN, | 167 | NL80211_TDLS_TEARDOWN, |
164 | le16_to_cpu(tdls_evt->u.reason_code), | 168 | le16_to_cpu(tdls_evt->u.reason_code), |
165 | GFP_KERNEL); | 169 | GFP_KERNEL); |
166 | ret = mwifiex_tdls_oper(priv, tdls_evt->peer_mac, | ||
167 | MWIFIEX_TDLS_DISABLE_LINK); | ||
168 | queue_work(adapter->workqueue, &adapter->main_work); | ||
169 | break; | 170 | break; |
170 | default: | 171 | default: |
171 | break; | 172 | break; |
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c index 92f3eb839866..1626868a4b5c 100644 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ b/drivers/net/wireless/mwifiex/sta_ioctl.c | |||
@@ -1026,12 +1026,12 @@ mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version, | |||
1026 | int max_len) | 1026 | int max_len) |
1027 | { | 1027 | { |
1028 | union { | 1028 | union { |
1029 | u32 l; | 1029 | __le32 l; |
1030 | u8 c[4]; | 1030 | u8 c[4]; |
1031 | } ver; | 1031 | } ver; |
1032 | char fw_ver[32]; | 1032 | char fw_ver[32]; |
1033 | 1033 | ||
1034 | ver.l = adapter->fw_release_number; | 1034 | ver.l = cpu_to_le32(adapter->fw_release_number); |
1035 | sprintf(fw_ver, "%u.%u.%u.p%u", ver.c[2], ver.c[1], ver.c[0], ver.c[3]); | 1035 | sprintf(fw_ver, "%u.%u.%u.p%u", ver.c[2], ver.c[1], ver.c[0], ver.c[3]); |
1036 | 1036 | ||
1037 | snprintf(version, max_len, driver_version, fw_ver); | 1037 | snprintf(version, max_len, driver_version, fw_ver); |
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c index 9ceb1dbe34c5..c2ad3b63ae70 100644 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ b/drivers/net/wireless/mwifiex/sta_rx.c | |||
@@ -232,6 +232,9 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, | |||
232 | if (sta_ptr) | 232 | if (sta_ptr) |
233 | sta_ptr->rx_seq[local_rx_pd->priority] = | 233 | sta_ptr->rx_seq[local_rx_pd->priority] = |
234 | le16_to_cpu(local_rx_pd->seq_num); | 234 | le16_to_cpu(local_rx_pd->seq_num); |
235 | mwifiex_auto_tdls_update_peer_signal(priv, ta, | ||
236 | local_rx_pd->snr, | ||
237 | local_rx_pd->nf); | ||
235 | } | 238 | } |
236 | } else { | 239 | } else { |
237 | if (rx_pkt_type != PKT_TYPE_BAR) | 240 | if (rx_pkt_type != PKT_TYPE_BAR) |
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c index e2949077f5b5..22884b429be7 100644 --- a/drivers/net/wireless/mwifiex/tdls.c +++ b/drivers/net/wireless/mwifiex/tdls.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #define TDLS_REQ_FIX_LEN 6 | 24 | #define TDLS_REQ_FIX_LEN 6 |
25 | #define TDLS_RESP_FIX_LEN 8 | 25 | #define TDLS_RESP_FIX_LEN 8 |
26 | #define TDLS_CONFIRM_FIX_LEN 6 | 26 | #define TDLS_CONFIRM_FIX_LEN 6 |
27 | #define MWIFIEX_TDLS_WMM_INFO_SIZE 7 | ||
27 | 28 | ||
28 | static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv, | 29 | static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv, |
29 | const u8 *mac, u8 status) | 30 | const u8 *mac, u8 status) |
@@ -367,6 +368,55 @@ static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb) | |||
367 | *pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB; | 368 | *pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB; |
368 | } | 369 | } |
369 | 370 | ||
371 | static void | ||
372 | mwifiex_tdls_add_wmm_param_ie(struct mwifiex_private *priv, struct sk_buff *skb) | ||
373 | { | ||
374 | struct ieee80211_wmm_param_ie *wmm; | ||
375 | u8 ac_vi[] = {0x42, 0x43, 0x5e, 0x00}; | ||
376 | u8 ac_vo[] = {0x62, 0x32, 0x2f, 0x00}; | ||
377 | u8 ac_be[] = {0x03, 0xa4, 0x00, 0x00}; | ||
378 | u8 ac_bk[] = {0x27, 0xa4, 0x00, 0x00}; | ||
379 | |||
380 | wmm = (void *)skb_put(skb, sizeof(*wmm)); | ||
381 | memset(wmm, 0, sizeof(*wmm)); | ||
382 | |||
383 | wmm->element_id = WLAN_EID_VENDOR_SPECIFIC; | ||
384 | wmm->len = sizeof(*wmm) - 2; | ||
385 | wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
386 | wmm->oui[1] = 0x50; | ||
387 | wmm->oui[2] = 0xf2; | ||
388 | wmm->oui_type = 2; /* WME */ | ||
389 | wmm->oui_subtype = 1; /* WME param */ | ||
390 | wmm->version = 1; /* WME ver */ | ||
391 | wmm->qos_info = 0; /* U-APSD not in use */ | ||
392 | |||
393 | /* use default WMM AC parameters for TDLS link*/ | ||
394 | memcpy(&wmm->ac[0], ac_be, sizeof(ac_be)); | ||
395 | memcpy(&wmm->ac[1], ac_bk, sizeof(ac_bk)); | ||
396 | memcpy(&wmm->ac[2], ac_vi, sizeof(ac_vi)); | ||
397 | memcpy(&wmm->ac[3], ac_vo, sizeof(ac_vo)); | ||
398 | } | ||
399 | |||
400 | static void | ||
401 | mwifiex_add_wmm_info_ie(struct mwifiex_private *priv, struct sk_buff *skb, | ||
402 | u8 qosinfo) | ||
403 | { | ||
404 | u8 *buf; | ||
405 | |||
406 | buf = (void *)skb_put(skb, MWIFIEX_TDLS_WMM_INFO_SIZE + | ||
407 | sizeof(struct ieee_types_header)); | ||
408 | |||
409 | *buf++ = WLAN_EID_VENDOR_SPECIFIC; | ||
410 | *buf++ = 7; /* len */ | ||
411 | *buf++ = 0x00; /* Microsoft OUI 00:50:F2 */ | ||
412 | *buf++ = 0x50; | ||
413 | *buf++ = 0xf2; | ||
414 | *buf++ = 2; /* WME */ | ||
415 | *buf++ = 0; /* WME info */ | ||
416 | *buf++ = 1; /* WME ver */ | ||
417 | *buf++ = qosinfo; /* U-APSD no in use */ | ||
418 | } | ||
419 | |||
370 | static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, | 420 | static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, |
371 | const u8 *peer, u8 action_code, | 421 | const u8 *peer, u8 action_code, |
372 | u8 dialog_token, | 422 | u8 dialog_token, |
@@ -421,6 +471,7 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, | |||
421 | 471 | ||
422 | mwifiex_tdls_add_ext_capab(priv, skb); | 472 | mwifiex_tdls_add_ext_capab(priv, skb); |
423 | mwifiex_tdls_add_qos_capab(skb); | 473 | mwifiex_tdls_add_qos_capab(skb); |
474 | mwifiex_add_wmm_info_ie(priv, skb, 0); | ||
424 | break; | 475 | break; |
425 | 476 | ||
426 | case WLAN_TDLS_SETUP_RESPONSE: | 477 | case WLAN_TDLS_SETUP_RESPONSE: |
@@ -458,6 +509,7 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, | |||
458 | 509 | ||
459 | mwifiex_tdls_add_ext_capab(priv, skb); | 510 | mwifiex_tdls_add_ext_capab(priv, skb); |
460 | mwifiex_tdls_add_qos_capab(skb); | 511 | mwifiex_tdls_add_qos_capab(skb); |
512 | mwifiex_add_wmm_info_ie(priv, skb, 0); | ||
461 | break; | 513 | break; |
462 | 514 | ||
463 | case WLAN_TDLS_SETUP_CONFIRM: | 515 | case WLAN_TDLS_SETUP_CONFIRM: |
@@ -466,6 +518,8 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, | |||
466 | skb_put(skb, sizeof(tf->u.setup_cfm)); | 518 | skb_put(skb, sizeof(tf->u.setup_cfm)); |
467 | tf->u.setup_cfm.status_code = cpu_to_le16(status_code); | 519 | tf->u.setup_cfm.status_code = cpu_to_le16(status_code); |
468 | tf->u.setup_cfm.dialog_token = dialog_token; | 520 | tf->u.setup_cfm.dialog_token = dialog_token; |
521 | |||
522 | mwifiex_tdls_add_wmm_param_ie(priv, skb); | ||
469 | if (priv->adapter->is_hw_11ac_capable) { | 523 | if (priv->adapter->is_hw_11ac_capable) { |
470 | ret = mwifiex_tdls_add_vht_oper(priv, peer, skb); | 524 | ret = mwifiex_tdls_add_vht_oper(priv, peer, skb); |
471 | if (ret) { | 525 | if (ret) { |
@@ -544,6 +598,7 @@ int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer, | |||
544 | sizeof(struct ieee_types_bss_co_2040) + | 598 | sizeof(struct ieee_types_bss_co_2040) + |
545 | sizeof(struct ieee80211_ht_operation) + | 599 | sizeof(struct ieee80211_ht_operation) + |
546 | sizeof(struct ieee80211_tdls_lnkie) + | 600 | sizeof(struct ieee80211_tdls_lnkie) + |
601 | sizeof(struct ieee80211_wmm_param_ie) + | ||
547 | extra_ies_len; | 602 | extra_ies_len; |
548 | 603 | ||
549 | if (priv->adapter->is_hw_11ac_capable) | 604 | if (priv->adapter->is_hw_11ac_capable) |
@@ -973,6 +1028,7 @@ mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer) | |||
973 | } | 1028 | } |
974 | 1029 | ||
975 | mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN); | 1030 | mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN); |
1031 | mwifiex_auto_tdls_update_peer_status(priv, peer, TDLS_NOT_SETUP); | ||
976 | memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN); | 1032 | memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN); |
977 | tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK; | 1033 | tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK; |
978 | return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER, | 1034 | return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER, |
@@ -1017,6 +1073,8 @@ mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer) | |||
1017 | 1073 | ||
1018 | memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq)); | 1074 | memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq)); |
1019 | mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE); | 1075 | mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE); |
1076 | mwifiex_auto_tdls_update_peer_status(priv, peer, | ||
1077 | TDLS_SETUP_COMPLETE); | ||
1020 | } else { | 1078 | } else { |
1021 | dev_dbg(priv->adapter->dev, | 1079 | dev_dbg(priv->adapter->dev, |
1022 | "tdls: enable link %pM failed\n", peer); | 1080 | "tdls: enable link %pM failed\n", peer); |
@@ -1030,6 +1088,8 @@ mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer) | |||
1030 | mwifiex_del_sta_entry(priv, peer); | 1088 | mwifiex_del_sta_entry(priv, peer); |
1031 | } | 1089 | } |
1032 | mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN); | 1090 | mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN); |
1091 | mwifiex_auto_tdls_update_peer_status(priv, peer, | ||
1092 | TDLS_NOT_SETUP); | ||
1033 | 1093 | ||
1034 | return -1; | 1094 | return -1; |
1035 | } | 1095 | } |
@@ -1097,3 +1157,231 @@ void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv) | |||
1097 | 1157 | ||
1098 | mwifiex_del_all_sta_list(priv); | 1158 | mwifiex_del_all_sta_list(priv); |
1099 | } | 1159 | } |
1160 | |||
1161 | int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb) | ||
1162 | { | ||
1163 | struct mwifiex_auto_tdls_peer *peer; | ||
1164 | unsigned long flags; | ||
1165 | u8 mac[ETH_ALEN]; | ||
1166 | |||
1167 | ether_addr_copy(mac, skb->data); | ||
1168 | |||
1169 | spin_lock_irqsave(&priv->auto_tdls_lock, flags); | ||
1170 | list_for_each_entry(peer, &priv->auto_tdls_list, list) { | ||
1171 | if (!memcmp(mac, peer->mac_addr, ETH_ALEN)) { | ||
1172 | if (peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH && | ||
1173 | peer->tdls_status == TDLS_NOT_SETUP && | ||
1174 | (peer->failure_count < | ||
1175 | MWIFIEX_TDLS_MAX_FAIL_COUNT)) { | ||
1176 | peer->tdls_status = TDLS_SETUP_INPROGRESS; | ||
1177 | dev_dbg(priv->adapter->dev, | ||
1178 | "setup TDLS link, peer=%pM rssi=%d\n", | ||
1179 | peer->mac_addr, peer->rssi); | ||
1180 | |||
1181 | cfg80211_tdls_oper_request(priv->netdev, | ||
1182 | peer->mac_addr, | ||
1183 | NL80211_TDLS_SETUP, | ||
1184 | 0, GFP_ATOMIC); | ||
1185 | peer->do_setup = false; | ||
1186 | priv->check_tdls_tx = false; | ||
1187 | } else if (peer->failure_count < | ||
1188 | MWIFIEX_TDLS_MAX_FAIL_COUNT && | ||
1189 | peer->do_discover) { | ||
1190 | mwifiex_send_tdls_data_frame(priv, | ||
1191 | peer->mac_addr, | ||
1192 | WLAN_TDLS_DISCOVERY_REQUEST, | ||
1193 | 1, 0, NULL, 0); | ||
1194 | peer->do_discover = false; | ||
1195 | } | ||
1196 | } | ||
1197 | } | ||
1198 | spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); | ||
1199 | |||
1200 | return 0; | ||
1201 | } | ||
1202 | |||
1203 | void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv) | ||
1204 | { | ||
1205 | struct mwifiex_auto_tdls_peer *peer, *tmp_node; | ||
1206 | unsigned long flags; | ||
1207 | |||
1208 | spin_lock_irqsave(&priv->auto_tdls_lock, flags); | ||
1209 | list_for_each_entry_safe(peer, tmp_node, &priv->auto_tdls_list, list) { | ||
1210 | list_del(&peer->list); | ||
1211 | kfree(peer); | ||
1212 | } | ||
1213 | |||
1214 | INIT_LIST_HEAD(&priv->auto_tdls_list); | ||
1215 | spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); | ||
1216 | priv->check_tdls_tx = false; | ||
1217 | } | ||
1218 | |||
1219 | void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac) | ||
1220 | { | ||
1221 | struct mwifiex_auto_tdls_peer *tdls_peer; | ||
1222 | unsigned long flags; | ||
1223 | |||
1224 | if (!priv->adapter->auto_tdls) | ||
1225 | return; | ||
1226 | |||
1227 | spin_lock_irqsave(&priv->auto_tdls_lock, flags); | ||
1228 | list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) { | ||
1229 | if (!memcmp(tdls_peer->mac_addr, mac, ETH_ALEN)) { | ||
1230 | tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS; | ||
1231 | tdls_peer->rssi_jiffies = jiffies; | ||
1232 | spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); | ||
1233 | return; | ||
1234 | } | ||
1235 | } | ||
1236 | |||
1237 | /* create new TDLS peer */ | ||
1238 | tdls_peer = kzalloc(sizeof(*tdls_peer), GFP_ATOMIC); | ||
1239 | if (tdls_peer) { | ||
1240 | ether_addr_copy(tdls_peer->mac_addr, mac); | ||
1241 | tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS; | ||
1242 | tdls_peer->rssi_jiffies = jiffies; | ||
1243 | INIT_LIST_HEAD(&tdls_peer->list); | ||
1244 | list_add_tail(&tdls_peer->list, &priv->auto_tdls_list); | ||
1245 | dev_dbg(priv->adapter->dev, "Add auto TDLS peer= %pM to list\n", | ||
1246 | mac); | ||
1247 | } | ||
1248 | |||
1249 | spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); | ||
1250 | } | ||
1251 | |||
1252 | void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv, | ||
1253 | const u8 *mac, u8 link_status) | ||
1254 | { | ||
1255 | struct mwifiex_auto_tdls_peer *peer; | ||
1256 | unsigned long flags; | ||
1257 | |||
1258 | if (!priv->adapter->auto_tdls) | ||
1259 | return; | ||
1260 | |||
1261 | spin_lock_irqsave(&priv->auto_tdls_lock, flags); | ||
1262 | list_for_each_entry(peer, &priv->auto_tdls_list, list) { | ||
1263 | if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) { | ||
1264 | if ((link_status == TDLS_NOT_SETUP) && | ||
1265 | (peer->tdls_status == TDLS_SETUP_INPROGRESS)) | ||
1266 | peer->failure_count++; | ||
1267 | else if (link_status == TDLS_SETUP_COMPLETE) | ||
1268 | peer->failure_count = 0; | ||
1269 | |||
1270 | peer->tdls_status = link_status; | ||
1271 | break; | ||
1272 | } | ||
1273 | } | ||
1274 | spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); | ||
1275 | } | ||
1276 | |||
1277 | void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv, | ||
1278 | u8 *mac, s8 snr, s8 nflr) | ||
1279 | { | ||
1280 | struct mwifiex_auto_tdls_peer *peer; | ||
1281 | unsigned long flags; | ||
1282 | |||
1283 | if (!priv->adapter->auto_tdls) | ||
1284 | return; | ||
1285 | |||
1286 | spin_lock_irqsave(&priv->auto_tdls_lock, flags); | ||
1287 | list_for_each_entry(peer, &priv->auto_tdls_list, list) { | ||
1288 | if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) { | ||
1289 | peer->rssi = nflr - snr; | ||
1290 | peer->rssi_jiffies = jiffies; | ||
1291 | break; | ||
1292 | } | ||
1293 | } | ||
1294 | spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); | ||
1295 | } | ||
1296 | |||
1297 | void mwifiex_check_auto_tdls(unsigned long context) | ||
1298 | { | ||
1299 | struct mwifiex_private *priv = (struct mwifiex_private *)context; | ||
1300 | struct mwifiex_auto_tdls_peer *tdls_peer; | ||
1301 | unsigned long flags; | ||
1302 | u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED; | ||
1303 | |||
1304 | if (WARN_ON_ONCE(!priv || !priv->adapter)) { | ||
1305 | pr_err("mwifiex: %s: adapter or private structure is NULL\n", | ||
1306 | __func__); | ||
1307 | return; | ||
1308 | } | ||
1309 | |||
1310 | if (unlikely(!priv->adapter->auto_tdls)) | ||
1311 | return; | ||
1312 | |||
1313 | if (!priv->auto_tdls_timer_active) { | ||
1314 | dev_dbg(priv->adapter->dev, | ||
1315 | "auto TDLS timer inactive; return"); | ||
1316 | return; | ||
1317 | } | ||
1318 | |||
1319 | priv->check_tdls_tx = false; | ||
1320 | |||
1321 | if (list_empty(&priv->auto_tdls_list)) { | ||
1322 | mod_timer(&priv->auto_tdls_timer, | ||
1323 | jiffies + | ||
1324 | msecs_to_jiffies(MWIFIEX_TIMER_10S)); | ||
1325 | return; | ||
1326 | } | ||
1327 | |||
1328 | spin_lock_irqsave(&priv->auto_tdls_lock, flags); | ||
1329 | list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) { | ||
1330 | if ((jiffies - tdls_peer->rssi_jiffies) > | ||
1331 | (MWIFIEX_AUTO_TDLS_IDLE_TIME * HZ)) { | ||
1332 | tdls_peer->rssi = 0; | ||
1333 | tdls_peer->do_discover = true; | ||
1334 | priv->check_tdls_tx = true; | ||
1335 | } | ||
1336 | |||
1337 | if (((tdls_peer->rssi >= MWIFIEX_TDLS_RSSI_LOW) || | ||
1338 | !tdls_peer->rssi) && | ||
1339 | tdls_peer->tdls_status == TDLS_SETUP_COMPLETE) { | ||
1340 | tdls_peer->tdls_status = TDLS_LINK_TEARDOWN; | ||
1341 | dev_dbg(priv->adapter->dev, | ||
1342 | "teardown TDLS link,peer=%pM rssi=%d\n", | ||
1343 | tdls_peer->mac_addr, -tdls_peer->rssi); | ||
1344 | tdls_peer->do_discover = true; | ||
1345 | priv->check_tdls_tx = true; | ||
1346 | cfg80211_tdls_oper_request(priv->netdev, | ||
1347 | tdls_peer->mac_addr, | ||
1348 | NL80211_TDLS_TEARDOWN, | ||
1349 | reason, GFP_ATOMIC); | ||
1350 | } else if (tdls_peer->rssi && | ||
1351 | tdls_peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH && | ||
1352 | tdls_peer->tdls_status == TDLS_NOT_SETUP && | ||
1353 | tdls_peer->failure_count < | ||
1354 | MWIFIEX_TDLS_MAX_FAIL_COUNT) { | ||
1355 | priv->check_tdls_tx = true; | ||
1356 | tdls_peer->do_setup = true; | ||
1357 | dev_dbg(priv->adapter->dev, | ||
1358 | "check TDLS with peer=%pM rssi=%d\n", | ||
1359 | tdls_peer->mac_addr, -tdls_peer->rssi); | ||
1360 | } | ||
1361 | } | ||
1362 | spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); | ||
1363 | |||
1364 | mod_timer(&priv->auto_tdls_timer, | ||
1365 | jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S)); | ||
1366 | } | ||
1367 | |||
1368 | void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv) | ||
1369 | { | ||
1370 | init_timer(&priv->auto_tdls_timer); | ||
1371 | priv->auto_tdls_timer.function = mwifiex_check_auto_tdls; | ||
1372 | priv->auto_tdls_timer.data = (unsigned long)priv; | ||
1373 | priv->auto_tdls_timer_active = true; | ||
1374 | mod_timer(&priv->auto_tdls_timer, | ||
1375 | jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S)); | ||
1376 | } | ||
1377 | |||
1378 | void mwifiex_clean_auto_tdls(struct mwifiex_private *priv) | ||
1379 | { | ||
1380 | if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && | ||
1381 | priv->adapter->auto_tdls && | ||
1382 | priv->bss_type == MWIFIEX_BSS_TYPE_STA) { | ||
1383 | priv->auto_tdls_timer_active = false; | ||
1384 | del_timer(&priv->auto_tdls_timer); | ||
1385 | mwifiex_flush_auto_tdls_list(priv); | ||
1386 | } | ||
1387 | } | ||
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c index 96a2126cc44b..a5983fc4e83a 100644 --- a/drivers/net/wireless/mwifiex/txrx.c +++ b/drivers/net/wireless/mwifiex/txrx.c | |||
@@ -64,10 +64,6 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, | |||
64 | else | 64 | else |
65 | ret = mwifiex_process_sta_rx_packet(priv, skb); | 65 | ret = mwifiex_process_sta_rx_packet(priv, skb); |
66 | 66 | ||
67 | /* Decrement RX pending counter for each packet */ | ||
68 | if (adapter->if_ops.data_complete) | ||
69 | adapter->if_ops.data_complete(adapter); | ||
70 | |||
71 | return ret; | 67 | return ret; |
72 | } | 68 | } |
73 | EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); | 69 | EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); |
diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c index 300bab438011..0f347fdefa0a 100644 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ b/drivers/net/wireless/mwifiex/uap_cmd.c | |||
@@ -167,7 +167,7 @@ mwifiex_set_ht_params(struct mwifiex_private *priv, | |||
167 | ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail, | 167 | ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail, |
168 | params->beacon.tail_len); | 168 | params->beacon.tail_len); |
169 | if (ht_ie) { | 169 | if (ht_ie) { |
170 | memcpy(&bss_cfg->ht_cap, ht_ie + 2, | 170 | memcpy(&bss_cfg->ht_cap, ht_ie, |
171 | sizeof(struct ieee80211_ht_cap)); | 171 | sizeof(struct ieee80211_ht_cap)); |
172 | cap_info = le16_to_cpu(bss_cfg->ht_cap.cap_info); | 172 | cap_info = le16_to_cpu(bss_cfg->ht_cap.cap_info); |
173 | memset(&bss_cfg->ht_cap.mcs, 0, | 173 | memset(&bss_cfg->ht_cap.mcs, 0, |
diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c index 4371e12b36f3..1b56495ec872 100644 --- a/drivers/net/wireless/mwifiex/usb.c +++ b/drivers/net/wireless/mwifiex/usb.c | |||
@@ -27,6 +27,11 @@ static struct mwifiex_if_ops usb_ops; | |||
27 | static struct semaphore add_remove_card_sem; | 27 | static struct semaphore add_remove_card_sem; |
28 | 28 | ||
29 | static struct usb_device_id mwifiex_usb_table[] = { | 29 | static struct usb_device_id mwifiex_usb_table[] = { |
30 | /* 8766 */ | ||
31 | {USB_DEVICE(USB8XXX_VID, USB8766_PID_1)}, | ||
32 | {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8766_PID_2, | ||
33 | USB_CLASS_VENDOR_SPEC, | ||
34 | USB_SUBCLASS_VENDOR_SPEC, 0xff)}, | ||
30 | /* 8797 */ | 35 | /* 8797 */ |
31 | {USB_DEVICE(USB8XXX_VID, USB8797_PID_1)}, | 36 | {USB_DEVICE(USB8XXX_VID, USB8797_PID_1)}, |
32 | {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8797_PID_2, | 37 | {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8797_PID_2, |
@@ -125,8 +130,10 @@ static int mwifiex_usb_recv(struct mwifiex_adapter *adapter, | |||
125 | dev_err(dev, "DATA: skb->len too large\n"); | 130 | dev_err(dev, "DATA: skb->len too large\n"); |
126 | return -1; | 131 | return -1; |
127 | } | 132 | } |
128 | skb_queue_tail(&adapter->usb_rx_data_q, skb); | 133 | |
134 | skb_queue_tail(&adapter->rx_data_q, skb); | ||
129 | adapter->data_received = true; | 135 | adapter->data_received = true; |
136 | atomic_inc(&adapter->rx_pending); | ||
130 | break; | 137 | break; |
131 | default: | 138 | default: |
132 | dev_err(dev, "%s: unknown endport %#x\n", __func__, ep); | 139 | dev_err(dev, "%s: unknown endport %#x\n", __func__, ep); |
@@ -176,7 +183,6 @@ static void mwifiex_usb_rx_complete(struct urb *urb) | |||
176 | else | 183 | else |
177 | skb_put(skb, recv_length - skb->len); | 184 | skb_put(skb, recv_length - skb->len); |
178 | 185 | ||
179 | atomic_inc(&adapter->rx_pending); | ||
180 | status = mwifiex_usb_recv(adapter, skb, context->ep); | 186 | status = mwifiex_usb_recv(adapter, skb, context->ep); |
181 | 187 | ||
182 | dev_dbg(adapter->dev, "info: recv_length=%d, status=%d\n", | 188 | dev_dbg(adapter->dev, "info: recv_length=%d, status=%d\n", |
@@ -191,7 +197,6 @@ static void mwifiex_usb_rx_complete(struct urb *urb) | |||
191 | if (card->rx_cmd_ep == context->ep) | 197 | if (card->rx_cmd_ep == context->ep) |
192 | return; | 198 | return; |
193 | } else { | 199 | } else { |
194 | atomic_dec(&adapter->rx_pending); | ||
195 | if (status == -1) | 200 | if (status == -1) |
196 | dev_err(adapter->dev, | 201 | dev_err(adapter->dev, |
197 | "received data processing failed!\n"); | 202 | "received data processing failed!\n"); |
@@ -222,7 +227,13 @@ setup_for_next: | |||
222 | else | 227 | else |
223 | size = MWIFIEX_RX_DATA_BUF_SIZE; | 228 | size = MWIFIEX_RX_DATA_BUF_SIZE; |
224 | 229 | ||
225 | mwifiex_usb_submit_rx_urb(context, size); | 230 | if (card->rx_cmd_ep == context->ep) { |
231 | mwifiex_usb_submit_rx_urb(context, size); | ||
232 | } else { | ||
233 | context->skb = NULL; | ||
234 | if (atomic_read(&adapter->rx_pending) <= HIGH_RX_PENDING) | ||
235 | mwifiex_usb_submit_rx_urb(context, size); | ||
236 | } | ||
226 | 237 | ||
227 | return; | 238 | return; |
228 | } | 239 | } |
@@ -348,10 +359,12 @@ static int mwifiex_usb_probe(struct usb_interface *intf, | |||
348 | 359 | ||
349 | /* PID_1 is used for firmware downloading only */ | 360 | /* PID_1 is used for firmware downloading only */ |
350 | switch (id_product) { | 361 | switch (id_product) { |
362 | case USB8766_PID_1: | ||
351 | case USB8797_PID_1: | 363 | case USB8797_PID_1: |
352 | case USB8897_PID_1: | 364 | case USB8897_PID_1: |
353 | card->usb_boot_state = USB8XXX_FW_DNLD; | 365 | card->usb_boot_state = USB8XXX_FW_DNLD; |
354 | break; | 366 | break; |
367 | case USB8766_PID_2: | ||
355 | case USB8797_PID_2: | 368 | case USB8797_PID_2: |
356 | case USB8897_PID_2: | 369 | case USB8897_PID_2: |
357 | card->usb_boot_state = USB8XXX_FW_READY; | 370 | card->usb_boot_state = USB8XXX_FW_READY; |
@@ -780,6 +793,11 @@ static int mwifiex_register_dev(struct mwifiex_adapter *adapter) | |||
780 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; | 793 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; |
781 | strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME); | 794 | strcpy(adapter->fw_name, USB8897_DEFAULT_FW_NAME); |
782 | break; | 795 | break; |
796 | case USB8766_PID_1: | ||
797 | case USB8766_PID_2: | ||
798 | adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; | ||
799 | strcpy(adapter->fw_name, USB8766_DEFAULT_FW_NAME); | ||
800 | break; | ||
783 | case USB8797_PID_1: | 801 | case USB8797_PID_1: |
784 | case USB8797_PID_2: | 802 | case USB8797_PID_2: |
785 | default: | 803 | default: |
@@ -962,19 +980,11 @@ static void mwifiex_submit_rx_urb(struct mwifiex_adapter *adapter, u8 ep) | |||
962 | static int mwifiex_usb_cmd_event_complete(struct mwifiex_adapter *adapter, | 980 | static int mwifiex_usb_cmd_event_complete(struct mwifiex_adapter *adapter, |
963 | struct sk_buff *skb) | 981 | struct sk_buff *skb) |
964 | { | 982 | { |
965 | atomic_dec(&adapter->rx_pending); | ||
966 | mwifiex_submit_rx_urb(adapter, MWIFIEX_USB_EP_CMD_EVENT); | 983 | mwifiex_submit_rx_urb(adapter, MWIFIEX_USB_EP_CMD_EVENT); |
967 | 984 | ||
968 | return 0; | 985 | return 0; |
969 | } | 986 | } |
970 | 987 | ||
971 | static int mwifiex_usb_data_complete(struct mwifiex_adapter *adapter) | ||
972 | { | ||
973 | atomic_dec(&adapter->rx_pending); | ||
974 | |||
975 | return 0; | ||
976 | } | ||
977 | |||
978 | /* This function wakes up the card. */ | 988 | /* This function wakes up the card. */ |
979 | static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | 989 | static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) |
980 | { | 990 | { |
@@ -986,6 +996,20 @@ static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) | |||
986 | return 0; | 996 | return 0; |
987 | } | 997 | } |
988 | 998 | ||
999 | static void mwifiex_usb_submit_rem_rx_urbs(struct mwifiex_adapter *adapter) | ||
1000 | { | ||
1001 | struct usb_card_rec *card = (struct usb_card_rec *)adapter->card; | ||
1002 | int i; | ||
1003 | struct urb_context *ctx; | ||
1004 | |||
1005 | for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) { | ||
1006 | if (card->rx_data_list[i].skb) | ||
1007 | continue; | ||
1008 | ctx = &card->rx_data_list[i]; | ||
1009 | mwifiex_usb_submit_rx_urb(ctx, MWIFIEX_RX_DATA_BUF_SIZE); | ||
1010 | } | ||
1011 | } | ||
1012 | |||
989 | static struct mwifiex_if_ops usb_ops = { | 1013 | static struct mwifiex_if_ops usb_ops = { |
990 | .register_dev = mwifiex_register_dev, | 1014 | .register_dev = mwifiex_register_dev, |
991 | .unregister_dev = mwifiex_unregister_dev, | 1015 | .unregister_dev = mwifiex_unregister_dev, |
@@ -996,8 +1020,8 @@ static struct mwifiex_if_ops usb_ops = { | |||
996 | .dnld_fw = mwifiex_usb_dnld_fw, | 1020 | .dnld_fw = mwifiex_usb_dnld_fw, |
997 | .cmdrsp_complete = mwifiex_usb_cmd_event_complete, | 1021 | .cmdrsp_complete = mwifiex_usb_cmd_event_complete, |
998 | .event_complete = mwifiex_usb_cmd_event_complete, | 1022 | .event_complete = mwifiex_usb_cmd_event_complete, |
999 | .data_complete = mwifiex_usb_data_complete, | ||
1000 | .host_to_card = mwifiex_usb_host_to_card, | 1023 | .host_to_card = mwifiex_usb_host_to_card, |
1024 | .submit_rem_rx_urbs = mwifiex_usb_submit_rem_rx_urbs, | ||
1001 | }; | 1025 | }; |
1002 | 1026 | ||
1003 | /* This function initializes the USB driver module. | 1027 | /* This function initializes the USB driver module. |
@@ -1048,5 +1072,6 @@ MODULE_AUTHOR("Marvell International Ltd."); | |||
1048 | MODULE_DESCRIPTION("Marvell WiFi-Ex USB Driver version" USB_VERSION); | 1072 | MODULE_DESCRIPTION("Marvell WiFi-Ex USB Driver version" USB_VERSION); |
1049 | MODULE_VERSION(USB_VERSION); | 1073 | MODULE_VERSION(USB_VERSION); |
1050 | MODULE_LICENSE("GPL v2"); | 1074 | MODULE_LICENSE("GPL v2"); |
1075 | MODULE_FIRMWARE(USB8766_DEFAULT_FW_NAME); | ||
1051 | MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME); | 1076 | MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME); |
1052 | MODULE_FIRMWARE(USB8897_DEFAULT_FW_NAME); | 1077 | MODULE_FIRMWARE(USB8897_DEFAULT_FW_NAME); |
diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h index 4c41c2a193c5..a7cbba1355af 100644 --- a/drivers/net/wireless/mwifiex/usb.h +++ b/drivers/net/wireless/mwifiex/usb.h | |||
@@ -24,6 +24,8 @@ | |||
24 | 24 | ||
25 | #define USB8XXX_VID 0x1286 | 25 | #define USB8XXX_VID 0x1286 |
26 | 26 | ||
27 | #define USB8766_PID_1 0x2041 | ||
28 | #define USB8766_PID_2 0x2042 | ||
27 | #define USB8797_PID_1 0x2043 | 29 | #define USB8797_PID_1 0x2043 |
28 | #define USB8797_PID_2 0x2044 | 30 | #define USB8797_PID_2 0x2044 |
29 | #define USB8897_PID_1 0x2045 | 31 | #define USB8897_PID_1 0x2045 |
@@ -37,6 +39,7 @@ | |||
37 | #define MWIFIEX_RX_DATA_URB 6 | 39 | #define MWIFIEX_RX_DATA_URB 6 |
38 | #define MWIFIEX_USB_TIMEOUT 100 | 40 | #define MWIFIEX_USB_TIMEOUT 100 |
39 | 41 | ||
42 | #define USB8766_DEFAULT_FW_NAME "mrvl/usb8766_uapsta.bin" | ||
40 | #define USB8797_DEFAULT_FW_NAME "mrvl/usb8797_uapsta.bin" | 43 | #define USB8797_DEFAULT_FW_NAME "mrvl/usb8797_uapsta.bin" |
41 | #define USB8897_DEFAULT_FW_NAME "mrvl/usb8897_uapsta.bin" | 44 | #define USB8897_DEFAULT_FW_NAME "mrvl/usb8897_uapsta.bin" |
42 | 45 | ||
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c index ec79c49de097..a113ef8f0b8b 100644 --- a/drivers/net/wireless/mwifiex/util.c +++ b/drivers/net/wireless/mwifiex/util.c | |||
@@ -141,6 +141,38 @@ int mwifiex_get_debug_info(struct mwifiex_private *priv, | |||
141 | return 0; | 141 | return 0; |
142 | } | 142 | } |
143 | 143 | ||
144 | static int | ||
145 | mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len, | ||
146 | struct rxpd *rx_pd) | ||
147 | { | ||
148 | u16 stype; | ||
149 | u8 category, action_code; | ||
150 | struct ieee80211_hdr *ieee_hdr = (void *)payload; | ||
151 | |||
152 | stype = (cpu_to_le16(ieee_hdr->frame_control) & IEEE80211_FCTL_STYPE); | ||
153 | |||
154 | switch (stype) { | ||
155 | case IEEE80211_STYPE_ACTION: | ||
156 | category = *(payload + sizeof(struct ieee80211_hdr)); | ||
157 | action_code = *(payload + sizeof(struct ieee80211_hdr) + 1); | ||
158 | if (category == WLAN_CATEGORY_PUBLIC && | ||
159 | action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) { | ||
160 | dev_dbg(priv->adapter->dev, | ||
161 | "TDLS discovery response %pM nf=%d, snr=%d\n", | ||
162 | ieee_hdr->addr2, rx_pd->nf, rx_pd->snr); | ||
163 | mwifiex_auto_tdls_update_peer_signal(priv, | ||
164 | ieee_hdr->addr2, | ||
165 | rx_pd->snr, | ||
166 | rx_pd->nf); | ||
167 | } | ||
168 | break; | ||
169 | default: | ||
170 | dev_dbg(priv->adapter->dev, | ||
171 | "unknown mgmt frame subytpe %#x\n", stype); | ||
172 | } | ||
173 | |||
174 | return 0; | ||
175 | } | ||
144 | /* | 176 | /* |
145 | * This function processes the received management packet and send it | 177 | * This function processes the received management packet and send it |
146 | * to the kernel. | 178 | * to the kernel. |
@@ -151,6 +183,7 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, | |||
151 | { | 183 | { |
152 | struct rxpd *rx_pd; | 184 | struct rxpd *rx_pd; |
153 | u16 pkt_len; | 185 | u16 pkt_len; |
186 | struct ieee80211_hdr *ieee_hdr; | ||
154 | 187 | ||
155 | if (!skb) | 188 | if (!skb) |
156 | return -1; | 189 | return -1; |
@@ -162,6 +195,11 @@ mwifiex_process_mgmt_packet(struct mwifiex_private *priv, | |||
162 | 195 | ||
163 | pkt_len = le16_to_cpu(rx_pd->rx_pkt_length); | 196 | pkt_len = le16_to_cpu(rx_pd->rx_pkt_length); |
164 | 197 | ||
198 | ieee_hdr = (void *)skb->data; | ||
199 | if (ieee80211_is_mgmt(ieee_hdr->frame_control)) { | ||
200 | mwifiex_parse_mgmt_packet(priv, (u8 *)ieee_hdr, | ||
201 | pkt_len, rx_pd); | ||
202 | } | ||
165 | /* Remove address4 */ | 203 | /* Remove address4 */ |
166 | memmove(skb->data + sizeof(struct ieee80211_hdr_3addr), | 204 | memmove(skb->data + sizeof(struct ieee80211_hdr_3addr), |
167 | skb->data + sizeof(struct ieee80211_hdr), | 205 | skb->data + sizeof(struct ieee80211_hdr), |
diff --git a/drivers/net/wireless/mwl8k.c b/drivers/net/wireless/mwl8k.c index ef1104476bd8..b8d1e04aa9b9 100644 --- a/drivers/net/wireless/mwl8k.c +++ b/drivers/net/wireless/mwl8k.c | |||
@@ -5548,7 +5548,9 @@ mwl8k_ampdu_action(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
5548 | return rc; | 5548 | return rc; |
5549 | } | 5549 | } |
5550 | 5550 | ||
5551 | static void mwl8k_sw_scan_start(struct ieee80211_hw *hw) | 5551 | static void mwl8k_sw_scan_start(struct ieee80211_hw *hw, |
5552 | struct ieee80211_vif *vif, | ||
5553 | const u8 *mac_addr) | ||
5552 | { | 5554 | { |
5553 | struct mwl8k_priv *priv = hw->priv; | 5555 | struct mwl8k_priv *priv = hw->priv; |
5554 | u8 tmp; | 5556 | u8 tmp; |
@@ -5565,7 +5567,8 @@ static void mwl8k_sw_scan_start(struct ieee80211_hw *hw) | |||
5565 | priv->sw_scan_start = true; | 5567 | priv->sw_scan_start = true; |
5566 | } | 5568 | } |
5567 | 5569 | ||
5568 | static void mwl8k_sw_scan_complete(struct ieee80211_hw *hw) | 5570 | static void mwl8k_sw_scan_complete(struct ieee80211_hw *hw, |
5571 | struct ieee80211_vif *vif) | ||
5569 | { | 5572 | { |
5570 | struct mwl8k_priv *priv = hw->priv; | 5573 | struct mwl8k_priv *priv = hw->priv; |
5571 | u8 tmp; | 5574 | u8 tmp; |
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c index d849d590de25..c878e3f3993c 100644 --- a/drivers/net/wireless/rt2x00/rt2500usb.c +++ b/drivers/net/wireless/rt2x00/rt2500usb.c | |||
@@ -62,7 +62,7 @@ static inline void rt2500usb_register_read(struct rt2x00_dev *rt2x00dev, | |||
62 | __le16 reg; | 62 | __le16 reg; |
63 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, | 63 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, |
64 | USB_VENDOR_REQUEST_IN, offset, | 64 | USB_VENDOR_REQUEST_IN, offset, |
65 | ®, sizeof(reg), REGISTER_TIMEOUT); | 65 | ®, sizeof(reg)); |
66 | *value = le16_to_cpu(reg); | 66 | *value = le16_to_cpu(reg); |
67 | } | 67 | } |
68 | 68 | ||
@@ -83,8 +83,7 @@ static inline void rt2500usb_register_multiread(struct rt2x00_dev *rt2x00dev, | |||
83 | { | 83 | { |
84 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, | 84 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, |
85 | USB_VENDOR_REQUEST_IN, offset, | 85 | USB_VENDOR_REQUEST_IN, offset, |
86 | value, length, | 86 | value, length); |
87 | REGISTER_TIMEOUT16(length)); | ||
88 | } | 87 | } |
89 | 88 | ||
90 | static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, | 89 | static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, |
@@ -94,7 +93,7 @@ static inline void rt2500usb_register_write(struct rt2x00_dev *rt2x00dev, | |||
94 | __le16 reg = cpu_to_le16(value); | 93 | __le16 reg = cpu_to_le16(value); |
95 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, | 94 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, |
96 | USB_VENDOR_REQUEST_OUT, offset, | 95 | USB_VENDOR_REQUEST_OUT, offset, |
97 | ®, sizeof(reg), REGISTER_TIMEOUT); | 96 | ®, sizeof(reg)); |
98 | } | 97 | } |
99 | 98 | ||
100 | static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, | 99 | static inline void rt2500usb_register_write_lock(struct rt2x00_dev *rt2x00dev, |
@@ -113,8 +112,7 @@ static inline void rt2500usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, | |||
113 | { | 112 | { |
114 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, | 113 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, |
115 | USB_VENDOR_REQUEST_OUT, offset, | 114 | USB_VENDOR_REQUEST_OUT, offset, |
116 | value, length, | 115 | value, length); |
117 | REGISTER_TIMEOUT16(length)); | ||
118 | } | 116 | } |
119 | 117 | ||
120 | static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev, | 118 | static int rt2500usb_regbusy_read(struct rt2x00_dev *rt2x00dev, |
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c index 573897b8e878..8444313eabe2 100644 --- a/drivers/net/wireless/rt2x00/rt2800usb.c +++ b/drivers/net/wireless/rt2x00/rt2800usb.c | |||
@@ -1111,6 +1111,7 @@ static struct usb_device_id rt2800usb_device_table[] = { | |||
1111 | /* Ovislink */ | 1111 | /* Ovislink */ |
1112 | { USB_DEVICE(0x1b75, 0x3071) }, | 1112 | { USB_DEVICE(0x1b75, 0x3071) }, |
1113 | { USB_DEVICE(0x1b75, 0x3072) }, | 1113 | { USB_DEVICE(0x1b75, 0x3072) }, |
1114 | { USB_DEVICE(0x1b75, 0xa200) }, | ||
1114 | /* Para */ | 1115 | /* Para */ |
1115 | { USB_DEVICE(0x20b8, 0x8888) }, | 1116 | { USB_DEVICE(0x20b8, 0x8888) }, |
1116 | /* Pegatron */ | 1117 | /* Pegatron */ |
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h index d13f25cd70d5..1ff81afb672c 100644 --- a/drivers/net/wireless/rt2x00/rt2x00.h +++ b/drivers/net/wireless/rt2x00/rt2x00.h | |||
@@ -1437,8 +1437,11 @@ int rt2x00mac_sta_add(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
1437 | struct ieee80211_sta *sta); | 1437 | struct ieee80211_sta *sta); |
1438 | int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | 1438 | int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, |
1439 | struct ieee80211_sta *sta); | 1439 | struct ieee80211_sta *sta); |
1440 | void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw); | 1440 | void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw, |
1441 | void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw); | 1441 | struct ieee80211_vif *vif, |
1442 | const u8 *mac_addr); | ||
1443 | void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw, | ||
1444 | struct ieee80211_vif *vif); | ||
1442 | int rt2x00mac_get_stats(struct ieee80211_hw *hw, | 1445 | int rt2x00mac_get_stats(struct ieee80211_hw *hw, |
1443 | struct ieee80211_low_level_stats *stats); | 1446 | struct ieee80211_low_level_stats *stats); |
1444 | void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, | 1447 | void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw, |
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c index ad6e5a8d1e10..cb40245a0695 100644 --- a/drivers/net/wireless/rt2x00/rt2x00mac.c +++ b/drivers/net/wireless/rt2x00/rt2x00mac.c | |||
@@ -568,7 +568,9 @@ int rt2x00mac_sta_remove(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
568 | } | 568 | } |
569 | EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove); | 569 | EXPORT_SYMBOL_GPL(rt2x00mac_sta_remove); |
570 | 570 | ||
571 | void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw) | 571 | void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw, |
572 | struct ieee80211_vif *vif, | ||
573 | const u8 *mac_addr) | ||
572 | { | 574 | { |
573 | struct rt2x00_dev *rt2x00dev = hw->priv; | 575 | struct rt2x00_dev *rt2x00dev = hw->priv; |
574 | set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); | 576 | set_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); |
@@ -576,7 +578,8 @@ void rt2x00mac_sw_scan_start(struct ieee80211_hw *hw) | |||
576 | } | 578 | } |
577 | EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start); | 579 | EXPORT_SYMBOL_GPL(rt2x00mac_sw_scan_start); |
578 | 580 | ||
579 | void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw) | 581 | void rt2x00mac_sw_scan_complete(struct ieee80211_hw *hw, |
582 | struct ieee80211_vif *vif) | ||
580 | { | 583 | { |
581 | struct rt2x00_dev *rt2x00dev = hw->priv; | 584 | struct rt2x00_dev *rt2x00dev = hw->priv; |
582 | clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); | 585 | clear_bit(DEVICE_STATE_SCANNING, &rt2x00dev->flags); |
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c index 8e68f87ab13c..66ff36447b94 100644 --- a/drivers/net/wireless/rt2x00/rt2x00queue.c +++ b/drivers/net/wireless/rt2x00/rt2x00queue.c | |||
@@ -158,55 +158,29 @@ void rt2x00queue_align_frame(struct sk_buff *skb) | |||
158 | skb_trim(skb, frame_length); | 158 | skb_trim(skb, frame_length); |
159 | } | 159 | } |
160 | 160 | ||
161 | void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length) | 161 | /* |
162 | * H/W needs L2 padding between the header and the paylod if header size | ||
163 | * is not 4 bytes aligned. | ||
164 | */ | ||
165 | void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int hdr_len) | ||
162 | { | 166 | { |
163 | unsigned int payload_length = skb->len - header_length; | 167 | unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0; |
164 | unsigned int header_align = ALIGN_SIZE(skb, 0); | ||
165 | unsigned int payload_align = ALIGN_SIZE(skb, header_length); | ||
166 | unsigned int l2pad = payload_length ? L2PAD_SIZE(header_length) : 0; | ||
167 | 168 | ||
168 | /* | 169 | if (!l2pad) |
169 | * Adjust the header alignment if the payload needs to be moved more | ||
170 | * than the header. | ||
171 | */ | ||
172 | if (payload_align > header_align) | ||
173 | header_align += 4; | ||
174 | |||
175 | /* There is nothing to do if no alignment is needed */ | ||
176 | if (!header_align) | ||
177 | return; | 170 | return; |
178 | 171 | ||
179 | /* Reserve the amount of space needed in front of the frame */ | 172 | skb_push(skb, l2pad); |
180 | skb_push(skb, header_align); | 173 | memmove(skb->data, skb->data + l2pad, hdr_len); |
181 | |||
182 | /* | ||
183 | * Move the header. | ||
184 | */ | ||
185 | memmove(skb->data, skb->data + header_align, header_length); | ||
186 | |||
187 | /* Move the payload, if present and if required */ | ||
188 | if (payload_length && payload_align) | ||
189 | memmove(skb->data + header_length + l2pad, | ||
190 | skb->data + header_length + l2pad + payload_align, | ||
191 | payload_length); | ||
192 | |||
193 | /* Trim the skb to the correct size */ | ||
194 | skb_trim(skb, header_length + l2pad + payload_length); | ||
195 | } | 174 | } |
196 | 175 | ||
197 | void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int header_length) | 176 | void rt2x00queue_remove_l2pad(struct sk_buff *skb, unsigned int hdr_len) |
198 | { | 177 | { |
199 | /* | 178 | unsigned int l2pad = (skb->len > hdr_len) ? L2PAD_SIZE(hdr_len) : 0; |
200 | * L2 padding is only present if the skb contains more than just the | ||
201 | * IEEE 802.11 header. | ||
202 | */ | ||
203 | unsigned int l2pad = (skb->len > header_length) ? | ||
204 | L2PAD_SIZE(header_length) : 0; | ||
205 | 179 | ||
206 | if (!l2pad) | 180 | if (!l2pad) |
207 | return; | 181 | return; |
208 | 182 | ||
209 | memmove(skb->data + l2pad, skb->data, header_length); | 183 | memmove(skb->data + l2pad, skb->data, hdr_len); |
210 | skb_pull(skb, l2pad); | 184 | skb_pull(skb, l2pad); |
211 | } | 185 | } |
212 | 186 | ||
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c index 86c43d112a4b..dc85d3e0ffe5 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.c +++ b/drivers/net/wireless/rt2x00/rt2x00usb.c | |||
@@ -116,7 +116,7 @@ EXPORT_SYMBOL_GPL(rt2x00usb_vendor_req_buff_lock); | |||
116 | int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, | 116 | int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, |
117 | const u8 request, const u8 requesttype, | 117 | const u8 request, const u8 requesttype, |
118 | const u16 offset, void *buffer, | 118 | const u16 offset, void *buffer, |
119 | const u16 buffer_length, const int timeout) | 119 | const u16 buffer_length) |
120 | { | 120 | { |
121 | int status = 0; | 121 | int status = 0; |
122 | unsigned char *tb; | 122 | unsigned char *tb; |
@@ -131,7 +131,7 @@ int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, | |||
131 | bsize = min_t(u16, CSR_CACHE_SIZE, len); | 131 | bsize = min_t(u16, CSR_CACHE_SIZE, len); |
132 | status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request, | 132 | status = rt2x00usb_vendor_req_buff_lock(rt2x00dev, request, |
133 | requesttype, off, tb, | 133 | requesttype, off, tb, |
134 | bsize, timeout); | 134 | bsize, REGISTER_TIMEOUT); |
135 | 135 | ||
136 | tb += bsize; | 136 | tb += bsize; |
137 | len -= bsize; | 137 | len -= bsize; |
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h index 831b65f93feb..819690e978c0 100644 --- a/drivers/net/wireless/rt2x00/rt2x00usb.h +++ b/drivers/net/wireless/rt2x00/rt2x00usb.h | |||
@@ -33,27 +33,14 @@ | |||
33 | }) | 33 | }) |
34 | 34 | ||
35 | /* | 35 | /* |
36 | * For USB vendor requests we need to pass a timeout | 36 | * For USB vendor requests we need to pass a timeout time in ms, for this we |
37 | * time in ms, for this we use the REGISTER_TIMEOUT, | 37 | * use the REGISTER_TIMEOUT, however when loading firmware or read EEPROM |
38 | * however when loading firmware a higher value is | 38 | * a higher value is required. In that case we use the REGISTER_TIMEOUT_FIRMWARE |
39 | * required. In that case we use the REGISTER_TIMEOUT_FIRMWARE. | 39 | * and EEPROM_TIMEOUT. |
40 | */ | 40 | */ |
41 | #define REGISTER_TIMEOUT 500 | 41 | #define REGISTER_TIMEOUT 500 |
42 | #define REGISTER_TIMEOUT_FIRMWARE 1000 | 42 | #define REGISTER_TIMEOUT_FIRMWARE 1000 |
43 | 43 | #define EEPROM_TIMEOUT 2000 | |
44 | /** | ||
45 | * REGISTER_TIMEOUT16 - Determine the timeout for 16bit register access | ||
46 | * @__datalen: Data length | ||
47 | */ | ||
48 | #define REGISTER_TIMEOUT16(__datalen) \ | ||
49 | ( REGISTER_TIMEOUT * ((__datalen) / sizeof(u16)) ) | ||
50 | |||
51 | /** | ||
52 | * REGISTER_TIMEOUT32 - Determine the timeout for 32bit register access | ||
53 | * @__datalen: Data length | ||
54 | */ | ||
55 | #define REGISTER_TIMEOUT32(__datalen) \ | ||
56 | ( REGISTER_TIMEOUT * ((__datalen) / sizeof(u32)) ) | ||
57 | 44 | ||
58 | /* | 45 | /* |
59 | * Cache size | 46 | * Cache size |
@@ -126,7 +113,6 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, | |||
126 | * @offset: Register offset to perform action on | 113 | * @offset: Register offset to perform action on |
127 | * @buffer: Buffer where information will be read/written to by device | 114 | * @buffer: Buffer where information will be read/written to by device |
128 | * @buffer_length: Size of &buffer | 115 | * @buffer_length: Size of &buffer |
129 | * @timeout: Operation timeout | ||
130 | * | 116 | * |
131 | * This function will use a previously with kmalloc allocated cache | 117 | * This function will use a previously with kmalloc allocated cache |
132 | * to communicate with the device. The contents of the buffer pointer | 118 | * to communicate with the device. The contents of the buffer pointer |
@@ -139,7 +125,7 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev, | |||
139 | int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, | 125 | int rt2x00usb_vendor_request_buff(struct rt2x00_dev *rt2x00dev, |
140 | const u8 request, const u8 requesttype, | 126 | const u8 request, const u8 requesttype, |
141 | const u16 offset, void *buffer, | 127 | const u16 offset, void *buffer, |
142 | const u16 buffer_length, const int timeout); | 128 | const u16 buffer_length); |
143 | 129 | ||
144 | /** | 130 | /** |
145 | * rt2x00usb_vendor_request_buff - Send register command to device (buffered) | 131 | * rt2x00usb_vendor_request_buff - Send register command to device (buffered) |
@@ -197,8 +183,7 @@ static inline int rt2x00usb_eeprom_read(struct rt2x00_dev *rt2x00dev, | |||
197 | { | 183 | { |
198 | return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ, | 184 | return rt2x00usb_vendor_request(rt2x00dev, USB_EEPROM_READ, |
199 | USB_VENDOR_REQUEST_IN, 0, 0, | 185 | USB_VENDOR_REQUEST_IN, 0, 0, |
200 | eeprom, length, | 186 | eeprom, length, EEPROM_TIMEOUT); |
201 | REGISTER_TIMEOUT16(length)); | ||
202 | } | 187 | } |
203 | 188 | ||
204 | /** | 189 | /** |
@@ -217,7 +202,7 @@ static inline void rt2x00usb_register_read(struct rt2x00_dev *rt2x00dev, | |||
217 | __le32 reg; | 202 | __le32 reg; |
218 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, | 203 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, |
219 | USB_VENDOR_REQUEST_IN, offset, | 204 | USB_VENDOR_REQUEST_IN, offset, |
220 | ®, sizeof(reg), REGISTER_TIMEOUT); | 205 | ®, sizeof(reg)); |
221 | *value = le32_to_cpu(reg); | 206 | *value = le32_to_cpu(reg); |
222 | } | 207 | } |
223 | 208 | ||
@@ -257,8 +242,7 @@ static inline void rt2x00usb_register_multiread(struct rt2x00_dev *rt2x00dev, | |||
257 | { | 242 | { |
258 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, | 243 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_READ, |
259 | USB_VENDOR_REQUEST_IN, offset, | 244 | USB_VENDOR_REQUEST_IN, offset, |
260 | value, length, | 245 | value, length); |
261 | REGISTER_TIMEOUT32(length)); | ||
262 | } | 246 | } |
263 | 247 | ||
264 | /** | 248 | /** |
@@ -277,7 +261,7 @@ static inline void rt2x00usb_register_write(struct rt2x00_dev *rt2x00dev, | |||
277 | __le32 reg = cpu_to_le32(value); | 261 | __le32 reg = cpu_to_le32(value); |
278 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, | 262 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, |
279 | USB_VENDOR_REQUEST_OUT, offset, | 263 | USB_VENDOR_REQUEST_OUT, offset, |
280 | ®, sizeof(reg), REGISTER_TIMEOUT); | 264 | ®, sizeof(reg)); |
281 | } | 265 | } |
282 | 266 | ||
283 | /** | 267 | /** |
@@ -316,8 +300,7 @@ static inline void rt2x00usb_register_multiwrite(struct rt2x00_dev *rt2x00dev, | |||
316 | { | 300 | { |
317 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, | 301 | rt2x00usb_vendor_request_buff(rt2x00dev, USB_MULTI_WRITE, |
318 | USB_VENDOR_REQUEST_OUT, offset, | 302 | USB_VENDOR_REQUEST_OUT, offset, |
319 | (void *)value, length, | 303 | (void *)value, length); |
320 | REGISTER_TIMEOUT32(length)); | ||
321 | } | 304 | } |
322 | 305 | ||
323 | /** | 306 | /** |
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c index ded967aa6ecb..706b844bce00 100644 --- a/drivers/net/wireless/rtl818x/rtl8180/dev.c +++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c | |||
@@ -742,35 +742,49 @@ static void rtl8180_int_disable(struct ieee80211_hw *dev) | |||
742 | } | 742 | } |
743 | 743 | ||
744 | static void rtl8180_conf_basic_rates(struct ieee80211_hw *dev, | 744 | static void rtl8180_conf_basic_rates(struct ieee80211_hw *dev, |
745 | u32 rates_mask) | 745 | u32 basic_mask) |
746 | { | 746 | { |
747 | struct rtl8180_priv *priv = dev->priv; | 747 | struct rtl8180_priv *priv = dev->priv; |
748 | |||
749 | u8 max, min; | ||
750 | u16 reg; | 748 | u16 reg; |
751 | 749 | u32 resp_mask; | |
752 | max = fls(rates_mask) - 1; | 750 | u8 basic_max; |
753 | min = ffs(rates_mask) - 1; | 751 | u8 resp_max, resp_min; |
752 | |||
753 | resp_mask = basic_mask; | ||
754 | /* IEEE80211 says the response rate should be equal to the highest basic | ||
755 | * rate that is not faster than received frame. But it says also that if | ||
756 | * the basic rate set does not contains any rate for the current | ||
757 | * modulation class then mandatory rate set must be used for that | ||
758 | * modulation class. Eventually add OFDM mandatory rates.. | ||
759 | */ | ||
760 | if ((resp_mask & 0xf) == resp_mask) | ||
761 | resp_mask |= 0x150; /* 6, 12, 24Mbps */ | ||
754 | 762 | ||
755 | switch (priv->chip_family) { | 763 | switch (priv->chip_family) { |
756 | 764 | ||
757 | case RTL818X_CHIP_FAMILY_RTL8180: | 765 | case RTL818X_CHIP_FAMILY_RTL8180: |
758 | /* in 8180 this is NOT a BITMAP */ | 766 | /* in 8180 this is NOT a BITMAP */ |
767 | basic_max = fls(basic_mask) - 1; | ||
759 | reg = rtl818x_ioread16(priv, &priv->map->BRSR); | 768 | reg = rtl818x_ioread16(priv, &priv->map->BRSR); |
760 | reg &= ~3; | 769 | reg &= ~3; |
761 | reg |= max; | 770 | reg |= basic_max; |
762 | rtl818x_iowrite16(priv, &priv->map->BRSR, reg); | 771 | rtl818x_iowrite16(priv, &priv->map->BRSR, reg); |
763 | break; | 772 | break; |
764 | 773 | ||
765 | case RTL818X_CHIP_FAMILY_RTL8185: | 774 | case RTL818X_CHIP_FAMILY_RTL8185: |
775 | resp_max = fls(resp_mask) - 1; | ||
776 | resp_min = ffs(resp_mask) - 1; | ||
766 | /* in 8185 this is a BITMAP */ | 777 | /* in 8185 this is a BITMAP */ |
767 | rtl818x_iowrite16(priv, &priv->map->BRSR, rates_mask); | 778 | rtl818x_iowrite16(priv, &priv->map->BRSR, basic_mask); |
768 | rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (max << 4) | min); | 779 | rtl818x_iowrite8(priv, &priv->map->RESP_RATE, (resp_max << 4) | |
780 | resp_min); | ||
769 | break; | 781 | break; |
770 | 782 | ||
771 | case RTL818X_CHIP_FAMILY_RTL8187SE: | 783 | case RTL818X_CHIP_FAMILY_RTL8187SE: |
772 | /* in 8187se this is a BITMAP */ | 784 | /* in 8187se this is a BITMAP. BRSR reg actually sets |
773 | rtl818x_iowrite16(priv, &priv->map->BRSR_8187SE, rates_mask); | 785 | * response rates. |
786 | */ | ||
787 | rtl818x_iowrite16(priv, &priv->map->BRSR_8187SE, resp_mask); | ||
774 | break; | 788 | break; |
775 | } | 789 | } |
776 | } | 790 | } |
diff --git a/drivers/net/wireless/rtlwifi/base.c b/drivers/net/wireless/rtlwifi/base.c index 58ba71830886..40b6d1d006d7 100644 --- a/drivers/net/wireless/rtlwifi/base.c +++ b/drivers/net/wireless/rtlwifi/base.c | |||
@@ -467,7 +467,7 @@ static void _rtl_init_deferred_work(struct ieee80211_hw *hw) | |||
467 | rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw); | 467 | rtl_easy_concurrent_retrytimer_callback, (unsigned long)hw); |
468 | /* <2> work queue */ | 468 | /* <2> work queue */ |
469 | rtlpriv->works.hw = hw; | 469 | rtlpriv->works.hw = hw; |
470 | rtlpriv->works.rtl_wq = alloc_workqueue(rtlpriv->cfg->name, 0, 0); | 470 | rtlpriv->works.rtl_wq = alloc_workqueue("%s", 0, 0, rtlpriv->cfg->name); |
471 | INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq, | 471 | INIT_DELAYED_WORK(&rtlpriv->works.watchdog_wq, |
472 | (void *)rtl_watchdog_wq_callback); | 472 | (void *)rtl_watchdog_wq_callback); |
473 | INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, | 473 | INIT_DELAYED_WORK(&rtlpriv->works.ips_nic_off_wq, |
diff --git a/drivers/net/wireless/rtlwifi/core.c b/drivers/net/wireless/rtlwifi/core.c index f6179bc06086..af52f0bdb71e 100644 --- a/drivers/net/wireless/rtlwifi/core.c +++ b/drivers/net/wireless/rtlwifi/core.c | |||
@@ -1361,7 +1361,9 @@ static int rtl_op_ampdu_action(struct ieee80211_hw *hw, | |||
1361 | return 0; | 1361 | return 0; |
1362 | } | 1362 | } |
1363 | 1363 | ||
1364 | static void rtl_op_sw_scan_start(struct ieee80211_hw *hw) | 1364 | static void rtl_op_sw_scan_start(struct ieee80211_hw *hw, |
1365 | struct ieee80211_vif *vif, | ||
1366 | const u8 *mac_addr) | ||
1365 | { | 1367 | { |
1366 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1368 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1367 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 1369 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
@@ -1396,7 +1398,8 @@ static void rtl_op_sw_scan_start(struct ieee80211_hw *hw) | |||
1396 | rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP_BAND0); | 1398 | rtlpriv->cfg->ops->scan_operation_backup(hw, SCAN_OPT_BACKUP_BAND0); |
1397 | } | 1399 | } |
1398 | 1400 | ||
1399 | static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw) | 1401 | static void rtl_op_sw_scan_complete(struct ieee80211_hw *hw, |
1402 | struct ieee80211_vif *vif) | ||
1400 | { | 1403 | { |
1401 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1404 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
1402 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 1405 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
@@ -1828,3 +1831,9 @@ const struct ieee80211_ops rtl_ops = { | |||
1828 | .flush = rtl_op_flush, | 1831 | .flush = rtl_op_flush, |
1829 | }; | 1832 | }; |
1830 | EXPORT_SYMBOL_GPL(rtl_ops); | 1833 | EXPORT_SYMBOL_GPL(rtl_ops); |
1834 | |||
1835 | bool rtl_btc_status_false(void) | ||
1836 | { | ||
1837 | return false; | ||
1838 | } | ||
1839 | EXPORT_SYMBOL_GPL(rtl_btc_status_false); | ||
diff --git a/drivers/net/wireless/rtlwifi/core.h b/drivers/net/wireless/rtlwifi/core.h index 59cd3b9dca25..624e1dc16d31 100644 --- a/drivers/net/wireless/rtlwifi/core.h +++ b/drivers/net/wireless/rtlwifi/core.h | |||
@@ -42,5 +42,6 @@ void rtl_rfreg_delay(struct ieee80211_hw *hw, enum radio_path rfpath, u32 addr, | |||
42 | u32 mask, u32 data); | 42 | u32 mask, u32 data); |
43 | void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data); | 43 | void rtl_bb_delay(struct ieee80211_hw *hw, u32 addr, u32 data); |
44 | bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb); | 44 | bool rtl_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb); |
45 | bool rtl_btc_status_false(void); | ||
45 | 46 | ||
46 | #endif | 47 | #endif |
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c index 667aba81246c..61f5d36eca6a 100644 --- a/drivers/net/wireless/rtlwifi/pci.c +++ b/drivers/net/wireless/rtlwifi/pci.c | |||
@@ -842,7 +842,8 @@ static void _rtl_pci_rx_interrupt(struct ieee80211_hw *hw) | |||
842 | break; | 842 | break; |
843 | } | 843 | } |
844 | /* handle command packet here */ | 844 | /* handle command packet here */ |
845 | if (rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) { | 845 | if (rtlpriv->cfg->ops->rx_command_packet && |
846 | rtlpriv->cfg->ops->rx_command_packet(hw, stats, skb)) { | ||
846 | dev_kfree_skb_any(skb); | 847 | dev_kfree_skb_any(skb); |
847 | goto end; | 848 | goto end; |
848 | } | 849 | } |
@@ -1127,9 +1128,14 @@ static void _rtl_pci_prepare_bcn_tasklet(struct ieee80211_hw *hw) | |||
1127 | 1128 | ||
1128 | __skb_queue_tail(&ring->queue, pskb); | 1129 | __skb_queue_tail(&ring->queue, pskb); |
1129 | 1130 | ||
1130 | rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN, | 1131 | if (rtlpriv->use_new_trx_flow) { |
1131 | &temp_one); | 1132 | temp_one = 4; |
1132 | 1133 | rtlpriv->cfg->ops->set_desc(hw, (u8 *)pbuffer_desc, true, | |
1134 | HW_DESC_OWN, (u8 *)&temp_one); | ||
1135 | } else { | ||
1136 | rtlpriv->cfg->ops->set_desc(hw, (u8 *)pdesc, true, HW_DESC_OWN, | ||
1137 | &temp_one); | ||
1138 | } | ||
1133 | return; | 1139 | return; |
1134 | } | 1140 | } |
1135 | 1141 | ||
@@ -1370,9 +1376,9 @@ static void _rtl_pci_free_tx_ring(struct ieee80211_hw *hw, | |||
1370 | ring->desc = NULL; | 1376 | ring->desc = NULL; |
1371 | if (rtlpriv->use_new_trx_flow) { | 1377 | if (rtlpriv->use_new_trx_flow) { |
1372 | pci_free_consistent(rtlpci->pdev, | 1378 | pci_free_consistent(rtlpci->pdev, |
1373 | sizeof(*ring->desc) * ring->entries, | 1379 | sizeof(*ring->buffer_desc) * ring->entries, |
1374 | ring->buffer_desc, ring->buffer_desc_dma); | 1380 | ring->buffer_desc, ring->buffer_desc_dma); |
1375 | ring->desc = NULL; | 1381 | ring->buffer_desc = NULL; |
1376 | } | 1382 | } |
1377 | } | 1383 | } |
1378 | 1384 | ||
@@ -1543,7 +1549,6 @@ int rtl_pci_reset_trx_ring(struct ieee80211_hw *hw) | |||
1543 | true, | 1549 | true, |
1544 | HW_DESC_TXBUFF_ADDR), | 1550 | HW_DESC_TXBUFF_ADDR), |
1545 | skb->len, PCI_DMA_TODEVICE); | 1551 | skb->len, PCI_DMA_TODEVICE); |
1546 | ring->idx = (ring->idx + 1) % ring->entries; | ||
1547 | kfree_skb(skb); | 1552 | kfree_skb(skb); |
1548 | ring->idx = (ring->idx + 1) % ring->entries; | 1553 | ring->idx = (ring->idx + 1) % ring->entries; |
1549 | } | 1554 | } |
@@ -1796,7 +1801,8 @@ static int rtl_pci_start(struct ieee80211_hw *hw) | |||
1796 | rtl_pci_reset_trx_ring(hw); | 1801 | rtl_pci_reset_trx_ring(hw); |
1797 | 1802 | ||
1798 | rtlpci->driver_is_goingto_unload = false; | 1803 | rtlpci->driver_is_goingto_unload = false; |
1799 | if (rtlpriv->cfg->ops->get_btc_status()) { | 1804 | if (rtlpriv->cfg->ops->get_btc_status && |
1805 | rtlpriv->cfg->ops->get_btc_status()) { | ||
1800 | rtlpriv->btcoexist.btc_ops->btc_init_variables(rtlpriv); | 1806 | rtlpriv->btcoexist.btc_ops->btc_init_variables(rtlpriv); |
1801 | rtlpriv->btcoexist.btc_ops->btc_init_hal_vars(rtlpriv); | 1807 | rtlpriv->btcoexist.btc_ops->btc_init_hal_vars(rtlpriv); |
1802 | } | 1808 | } |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c index a00861b26ece..29983bc96a89 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.c | |||
@@ -656,7 +656,8 @@ static u8 reserved_page_packet[TOTAL_RESERVED_PKT_LEN] = { | |||
656 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, | 656 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, |
657 | }; | 657 | }; |
658 | 658 | ||
659 | void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) | 659 | void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, |
660 | bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *)) | ||
660 | { | 661 | { |
661 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 662 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
662 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); | 663 | struct rtl_mac *mac = rtl_mac(rtl_priv(hw)); |
@@ -722,7 +723,10 @@ void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished) | |||
722 | memcpy((u8 *)skb_put(skb, totalpacketlen), | 723 | memcpy((u8 *)skb_put(skb, totalpacketlen), |
723 | &reserved_page_packet, totalpacketlen); | 724 | &reserved_page_packet, totalpacketlen); |
724 | 725 | ||
725 | rtstatus = rtl_cmd_send_packet(hw, skb); | 726 | if (cmd_send_packet) |
727 | rtstatus = cmd_send_packet(hw, skb); | ||
728 | else | ||
729 | rtstatus = rtl_cmd_send_packet(hw, skb); | ||
726 | 730 | ||
727 | if (rtstatus) | 731 | if (rtstatus) |
728 | b_dlok = true; | 732 | b_dlok = true; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h index a815bd6273da..b64ae45dc674 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h +++ b/drivers/net/wireless/rtlwifi/rtl8192c/fw_common.h | |||
@@ -109,7 +109,9 @@ void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, u8 element_id, | |||
109 | u32 cmd_len, u8 *p_cmdbuffer); | 109 | u32 cmd_len, u8 *p_cmdbuffer); |
110 | void rtl92c_firmware_selfreset(struct ieee80211_hw *hw); | 110 | void rtl92c_firmware_selfreset(struct ieee80211_hw *hw); |
111 | void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); | 111 | void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); |
112 | void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool b_dl_finished); | 112 | void rtl92c_set_fw_rsvdpagepkt |
113 | (struct ieee80211_hw *hw, | ||
114 | bool (*cmd_send_packet)(struct ieee80211_hw *, struct sk_buff *)); | ||
113 | void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); | 115 | void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); |
114 | void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len); | 116 | void usb_writeN_async(struct rtl_priv *rtlpriv, u32 addr, void *data, u16 len); |
115 | void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); | 117 | void rtl92c_set_p2p_ps_offload_cmd(struct ieee80211_hw *hw, u8 p2p_ps_state); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h index 831df101d7b7..9b660df6fd71 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/def.h | |||
@@ -114,6 +114,8 @@ | |||
114 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) | 114 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 16, 4) |
115 | #define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ | 115 | #define GET_C2H_CMD_FEEDBACK_CCX_SEQ(__pcmdfbhdr) \ |
116 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) | 116 | LE_BITS_TO_4BYTE(((__pcmdfbhdr) + 4), 20, 12) |
117 | #define GET_RX_STATUS_DESC_BUFF_ADDR(__pdesc) \ | ||
118 | SHIFT_AND_MASK_LE(__pdesc + 24, 0, 32) | ||
117 | 119 | ||
118 | #define CHIP_VER_B BIT(4) | 120 | #define CHIP_VER_B BIT(4) |
119 | #define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3) | 121 | #define CHIP_BONDING_IDENTIFIER(_value) (((_value) >> 22) & 0x3) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c index 8ec0f031f48a..55357d69397a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c | |||
@@ -459,7 +459,7 @@ void rtl92ce_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
459 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, | 459 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, |
460 | tmp_reg422 & (~BIT(6))); | 460 | tmp_reg422 & (~BIT(6))); |
461 | 461 | ||
462 | rtl92c_set_fw_rsvdpagepkt(hw, 0); | 462 | rtl92c_set_fw_rsvdpagepkt(hw, NULL); |
463 | 463 | ||
464 | _rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0); | 464 | _rtl92ce_set_bcn_ctrl_reg(hw, BIT(3), 0); |
465 | _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4)); | 465 | _rtl92ce_set_bcn_ctrl_reg(hw, 0, BIT(4)); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c index d86b5b566444..46ea07605eb4 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c | |||
@@ -244,6 +244,7 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = { | |||
244 | .phy_lc_calibrate = _rtl92ce_phy_lc_calibrate, | 244 | .phy_lc_calibrate = _rtl92ce_phy_lc_calibrate, |
245 | .phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback, | 245 | .phy_set_bw_mode_callback = rtl92ce_phy_set_bw_mode_callback, |
246 | .dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower, | 246 | .dm_dynamic_txpower = rtl92ce_dm_dynamic_txpower, |
247 | .get_btc_status = rtl_btc_status_false, | ||
247 | }; | 248 | }; |
248 | 249 | ||
249 | static struct rtl_mod_params rtl92ce_mod_params = { | 250 | static struct rtl_mod_params rtl92ce_mod_params = { |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c index 2fb9c7acb76a..dc3d20b17a26 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ce/trx.c | |||
@@ -728,6 +728,9 @@ u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name) | |||
728 | case HW_DESC_RXPKT_LEN: | 728 | case HW_DESC_RXPKT_LEN: |
729 | ret = GET_RX_DESC_PKT_LEN(pdesc); | 729 | ret = GET_RX_DESC_PKT_LEN(pdesc); |
730 | break; | 730 | break; |
731 | case HW_DESC_RXBUFF_ADDR: | ||
732 | ret = GET_RX_STATUS_DESC_BUFF_ADDR(pdesc); | ||
733 | break; | ||
731 | default: | 734 | default: |
732 | RT_ASSERT(false, "ERR rxdesc :%d not process\n", | 735 | RT_ASSERT(false, "ERR rxdesc :%d not process\n", |
733 | desc_name); | 736 | desc_name); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c index 04aa0b5f5b3d..873363acbacf 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c | |||
@@ -1592,6 +1592,20 @@ void rtl92cu_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
1592 | } | 1592 | } |
1593 | } | 1593 | } |
1594 | 1594 | ||
1595 | bool usb_cmd_send_packet(struct ieee80211_hw *hw, struct sk_buff *skb) | ||
1596 | { | ||
1597 | /* Currently nothing happens here. | ||
1598 | * Traffic stops after some seconds in WPA2 802.11n mode. | ||
1599 | * Maybe because rtl8192cu chip should be set from here? | ||
1600 | * If I understand correctly, the realtek vendor driver sends some urbs | ||
1601 | * if its "here". | ||
1602 | * | ||
1603 | * This is maybe necessary: | ||
1604 | * rtlpriv->cfg->ops->fill_tx_cmddesc(hw, buffer, 1, 1, skb); | ||
1605 | */ | ||
1606 | return true; | ||
1607 | } | ||
1608 | |||
1595 | void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | 1609 | void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) |
1596 | { | 1610 | { |
1597 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 1611 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
@@ -1939,7 +1953,8 @@ void rtl92cu_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
1939 | recover = true; | 1953 | recover = true; |
1940 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, | 1954 | rtl_write_byte(rtlpriv, REG_FWHW_TXQ_CTRL + 2, |
1941 | tmp_reg422 & (~BIT(6))); | 1955 | tmp_reg422 & (~BIT(6))); |
1942 | rtl92c_set_fw_rsvdpagepkt(hw, 0); | 1956 | rtl92c_set_fw_rsvdpagepkt(hw, |
1957 | &usb_cmd_send_packet); | ||
1943 | _rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0); | 1958 | _rtl92cu_set_bcn_ctrl_reg(hw, BIT(3), 0); |
1944 | _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4)); | 1959 | _rtl92cu_set_bcn_ctrl_reg(hw, 0, BIT(4)); |
1945 | if (recover) | 1960 | if (recover) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h index 0f7812e0c8aa..c1e33b0228c0 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.h | |||
@@ -104,7 +104,6 @@ bool rtl92cu_gpio_radio_on_off_checking(struct ieee80211_hw *hw, u8 * valid); | |||
104 | void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); | 104 | void rtl92cu_set_check_bssid(struct ieee80211_hw *hw, bool check_bssid); |
105 | int rtl92c_download_fw(struct ieee80211_hw *hw); | 105 | int rtl92c_download_fw(struct ieee80211_hw *hw); |
106 | void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); | 106 | void rtl92c_set_fw_pwrmode_cmd(struct ieee80211_hw *hw, u8 mode); |
107 | void rtl92c_set_fw_rsvdpagepkt(struct ieee80211_hw *hw, bool dl_finished); | ||
108 | void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); | 107 | void rtl92c_set_fw_joinbss_report_cmd(struct ieee80211_hw *hw, u8 mstatus); |
109 | void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, | 108 | void rtl92c_fill_h2c_cmd(struct ieee80211_hw *hw, |
110 | u8 element_id, u32 cmd_len, u8 *p_cmdbuffer); | 109 | u8 element_id, u32 cmd_len, u8 *p_cmdbuffer); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c index 7c5fbaf5fee0..e06bafee37f9 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c | |||
@@ -101,6 +101,12 @@ static void rtl92cu_deinit_sw_vars(struct ieee80211_hw *hw) | |||
101 | } | 101 | } |
102 | } | 102 | } |
103 | 103 | ||
104 | /* get bt coexist status */ | ||
105 | static bool rtl92cu_get_btc_status(void) | ||
106 | { | ||
107 | return false; | ||
108 | } | ||
109 | |||
104 | static struct rtl_hal_ops rtl8192cu_hal_ops = { | 110 | static struct rtl_hal_ops rtl8192cu_hal_ops = { |
105 | .init_sw_vars = rtl92cu_init_sw_vars, | 111 | .init_sw_vars = rtl92cu_init_sw_vars, |
106 | .deinit_sw_vars = rtl92cu_deinit_sw_vars, | 112 | .deinit_sw_vars = rtl92cu_deinit_sw_vars, |
@@ -148,6 +154,7 @@ static struct rtl_hal_ops rtl8192cu_hal_ops = { | |||
148 | .phy_set_bw_mode_callback = rtl92cu_phy_set_bw_mode_callback, | 154 | .phy_set_bw_mode_callback = rtl92cu_phy_set_bw_mode_callback, |
149 | .dm_dynamic_txpower = rtl92cu_dm_dynamic_txpower, | 155 | .dm_dynamic_txpower = rtl92cu_dm_dynamic_txpower, |
150 | .fill_h2c_cmd = rtl92c_fill_h2c_cmd, | 156 | .fill_h2c_cmd = rtl92c_fill_h2c_cmd, |
157 | .get_btc_status = rtl92cu_get_btc_status, | ||
151 | }; | 158 | }; |
152 | 159 | ||
153 | static struct rtl_mod_params rtl92cu_mod_params = { | 160 | static struct rtl_mod_params rtl92cu_mod_params = { |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c index edab5a5351b5..a0aba088259a 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192de/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192de/sw.c | |||
@@ -251,6 +251,7 @@ static struct rtl_hal_ops rtl8192de_hal_ops = { | |||
251 | .get_rfreg = rtl92d_phy_query_rf_reg, | 251 | .get_rfreg = rtl92d_phy_query_rf_reg, |
252 | .set_rfreg = rtl92d_phy_set_rf_reg, | 252 | .set_rfreg = rtl92d_phy_set_rf_reg, |
253 | .linked_set_reg = rtl92d_linked_set_reg, | 253 | .linked_set_reg = rtl92d_linked_set_reg, |
254 | .get_btc_status = rtl_btc_status_false, | ||
254 | }; | 255 | }; |
255 | 256 | ||
256 | static struct rtl_mod_params rtl92de_mod_params = { | 257 | static struct rtl_mod_params rtl92de_mod_params = { |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c index dfdc9b20e4ad..1a87edca2c3f 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192ee/hw.c | |||
@@ -362,7 +362,7 @@ void rtl92ee_get_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
362 | } | 362 | } |
363 | break; | 363 | break; |
364 | default: | 364 | default: |
365 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 365 | RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, |
366 | "switch case not process %x\n", variable); | 366 | "switch case not process %x\n", variable); |
367 | break; | 367 | break; |
368 | } | 368 | } |
@@ -591,7 +591,7 @@ void rtl92ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
591 | acm_ctrl &= (~ACMHW_BEQEN); | 591 | acm_ctrl &= (~ACMHW_BEQEN); |
592 | break; | 592 | break; |
593 | default: | 593 | default: |
594 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 594 | RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, |
595 | "switch case not process\n"); | 595 | "switch case not process\n"); |
596 | break; | 596 | break; |
597 | } | 597 | } |
@@ -710,7 +710,7 @@ void rtl92ee_set_hw_reg(struct ieee80211_hw *hw, u8 variable, u8 *val) | |||
710 | } | 710 | } |
711 | break; | 711 | break; |
712 | default: | 712 | default: |
713 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 713 | RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, |
714 | "switch case not process %x\n", variable); | 714 | "switch case not process %x\n", variable); |
715 | break; | 715 | break; |
716 | } | 716 | } |
@@ -2424,7 +2424,7 @@ void rtl92ee_set_key(struct ieee80211_hw *hw, u32 key_index, | |||
2424 | enc_algo = CAM_AES; | 2424 | enc_algo = CAM_AES; |
2425 | break; | 2425 | break; |
2426 | default: | 2426 | default: |
2427 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | 2427 | RT_TRACE(rtlpriv, COMP_ERR, DBG_DMESG, |
2428 | "switch case not process\n"); | 2428 | "switch case not process\n"); |
2429 | enc_algo = CAM_TKIP; | 2429 | enc_algo = CAM_TKIP; |
2430 | break; | 2430 | break; |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/def.h b/drivers/net/wireless/rtlwifi/rtl8192se/def.h index 83c98674bfd3..6e7a70b43949 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/def.h +++ b/drivers/net/wireless/rtlwifi/rtl8192se/def.h | |||
@@ -446,6 +446,8 @@ | |||
446 | /* DWORD 6 */ | 446 | /* DWORD 6 */ |
447 | #define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \ | 447 | #define SET_RX_STATUS__DESC_BUFF_ADDR(__pdesc, __val) \ |
448 | SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val) | 448 | SET_BITS_OFFSET_LE(__pdesc + 24, 0, 32, __val) |
449 | #define GET_RX_STATUS_DESC_BUFF_ADDR(__pdesc) \ | ||
450 | SHIFT_AND_MASK_LE(__pdesc + 24, 0, 32) | ||
449 | 451 | ||
450 | #define SE_RX_HAL_IS_CCK_RATE(_pdesc)\ | 452 | #define SE_RX_HAL_IS_CCK_RATE(_pdesc)\ |
451 | (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M || \ | 453 | (GET_RX_STATUS_DESC_RX_MCS(_pdesc) == DESC92_RATE1M || \ |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c index 00e067044c08..5761d5b49e39 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c | |||
@@ -1201,6 +1201,9 @@ static int _rtl92se_set_media_status(struct ieee80211_hw *hw, | |||
1201 | 1201 | ||
1202 | } | 1202 | } |
1203 | 1203 | ||
1204 | if (type != NL80211_IFTYPE_AP && | ||
1205 | rtlpriv->mac80211.link_state < MAC80211_LINKED) | ||
1206 | bt_msr = rtl_read_byte(rtlpriv, MSR) & ~MSR_LINK_MASK; | ||
1204 | rtl_write_byte(rtlpriv, (MSR), bt_msr); | 1207 | rtl_write_byte(rtlpriv, (MSR), bt_msr); |
1205 | 1208 | ||
1206 | temp = rtl_read_dword(rtlpriv, TCR); | 1209 | temp = rtl_read_dword(rtlpriv, TCR); |
@@ -1262,6 +1265,7 @@ void rtl92se_enable_interrupt(struct ieee80211_hw *hw) | |||
1262 | rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]); | 1265 | rtl_write_dword(rtlpriv, INTA_MASK, rtlpci->irq_mask[0]); |
1263 | /* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */ | 1266 | /* Support Bit 32-37(Assign as Bit 0-5) interrupt setting now */ |
1264 | rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F); | 1267 | rtl_write_dword(rtlpriv, INTA_MASK + 4, rtlpci->irq_mask[1] & 0x3F); |
1268 | rtlpci->irq_enabled = true; | ||
1265 | } | 1269 | } |
1266 | 1270 | ||
1267 | void rtl92se_disable_interrupt(struct ieee80211_hw *hw) | 1271 | void rtl92se_disable_interrupt(struct ieee80211_hw *hw) |
@@ -1276,8 +1280,7 @@ void rtl92se_disable_interrupt(struct ieee80211_hw *hw) | |||
1276 | rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | 1280 | rtlpci = rtl_pcidev(rtl_pcipriv(hw)); |
1277 | rtl_write_dword(rtlpriv, INTA_MASK, 0); | 1281 | rtl_write_dword(rtlpriv, INTA_MASK, 0); |
1278 | rtl_write_dword(rtlpriv, INTA_MASK + 4, 0); | 1282 | rtl_write_dword(rtlpriv, INTA_MASK + 4, 0); |
1279 | 1283 | rtlpci->irq_enabled = false; | |
1280 | synchronize_irq(rtlpci->pdev->irq); | ||
1281 | } | 1284 | } |
1282 | 1285 | ||
1283 | static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data) | 1286 | static u8 _rtl92s_set_sysclk(struct ieee80211_hw *hw, u8 data) |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c index 77c5b5f35244..4b4612fe2fdb 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/phy.c | |||
@@ -399,6 +399,8 @@ static bool _rtl92s_phy_sw_chnl_step_by_step(struct ieee80211_hw *hw, | |||
399 | case 2: | 399 | case 2: |
400 | currentcmd = &postcommoncmd[*step]; | 400 | currentcmd = &postcommoncmd[*step]; |
401 | break; | 401 | break; |
402 | default: | ||
403 | return true; | ||
402 | } | 404 | } |
403 | 405 | ||
404 | if (currentcmd->cmdid == CMDID_END) { | 406 | if (currentcmd->cmdid == CMDID_END) { |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c index 1bff2a0f7600..fb003868bdef 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c | |||
@@ -87,11 +87,8 @@ static void rtl92s_init_aspm_vars(struct ieee80211_hw *hw) | |||
87 | static void rtl92se_fw_cb(const struct firmware *firmware, void *context) | 87 | static void rtl92se_fw_cb(const struct firmware *firmware, void *context) |
88 | { | 88 | { |
89 | struct ieee80211_hw *hw = context; | 89 | struct ieee80211_hw *hw = context; |
90 | struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); | ||
91 | struct rtl_priv *rtlpriv = rtl_priv(hw); | 90 | struct rtl_priv *rtlpriv = rtl_priv(hw); |
92 | struct rtl_pci *rtlpci = rtl_pcidev(pcipriv); | ||
93 | struct rt_firmware *pfirmware = NULL; | 91 | struct rt_firmware *pfirmware = NULL; |
94 | int err; | ||
95 | 92 | ||
96 | RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, | 93 | RT_TRACE(rtlpriv, COMP_ERR, DBG_LOUD, |
97 | "Firmware callback routine entered!\n"); | 94 | "Firmware callback routine entered!\n"); |
@@ -112,20 +109,6 @@ static void rtl92se_fw_cb(const struct firmware *firmware, void *context) | |||
112 | memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size); | 109 | memcpy(pfirmware->sz_fw_tmpbuffer, firmware->data, firmware->size); |
113 | pfirmware->sz_fw_tmpbufferlen = firmware->size; | 110 | pfirmware->sz_fw_tmpbufferlen = firmware->size; |
114 | release_firmware(firmware); | 111 | release_firmware(firmware); |
115 | |||
116 | err = ieee80211_register_hw(hw); | ||
117 | if (err) { | ||
118 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
119 | "Can't register mac80211 hw\n"); | ||
120 | return; | ||
121 | } else { | ||
122 | rtlpriv->mac80211.mac80211_registered = 1; | ||
123 | } | ||
124 | rtlpci->irq_alloc = 1; | ||
125 | set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); | ||
126 | |||
127 | /*init rfkill */ | ||
128 | rtl_init_rfkill(hw); | ||
129 | } | 112 | } |
130 | 113 | ||
131 | static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) | 114 | static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) |
@@ -226,8 +209,8 @@ static int rtl92s_init_sw_vars(struct ieee80211_hw *hw) | |||
226 | if (!rtlpriv->rtlhal.pfirmware) | 209 | if (!rtlpriv->rtlhal.pfirmware) |
227 | return 1; | 210 | return 1; |
228 | 211 | ||
229 | rtlpriv->max_fw_size = RTL8190_MAX_RAW_FIRMWARE_CODE_SIZE; | 212 | rtlpriv->max_fw_size = RTL8190_MAX_FIRMWARE_CODE_SIZE*2 + |
230 | 213 | sizeof(struct fw_hdr); | |
231 | pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n" | 214 | pr_info("Driver for Realtek RTL8192SE/RTL8191SE\n" |
232 | "Loading firmware %s\n", rtlpriv->cfg->fw_name); | 215 | "Loading firmware %s\n", rtlpriv->cfg->fw_name); |
233 | /* request fw */ | 216 | /* request fw */ |
@@ -253,6 +236,19 @@ static void rtl92s_deinit_sw_vars(struct ieee80211_hw *hw) | |||
253 | } | 236 | } |
254 | } | 237 | } |
255 | 238 | ||
239 | static bool rtl92se_is_tx_desc_closed(struct ieee80211_hw *hw, u8 hw_queue, | ||
240 | u16 index) | ||
241 | { | ||
242 | struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); | ||
243 | struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue]; | ||
244 | u8 *entry = (u8 *)(&ring->desc[ring->idx]); | ||
245 | u8 own = (u8)rtl92se_get_desc(entry, true, HW_DESC_OWN); | ||
246 | |||
247 | if (own) | ||
248 | return false; | ||
249 | return true; | ||
250 | } | ||
251 | |||
256 | static struct rtl_hal_ops rtl8192se_hal_ops = { | 252 | static struct rtl_hal_ops rtl8192se_hal_ops = { |
257 | .init_sw_vars = rtl92s_init_sw_vars, | 253 | .init_sw_vars = rtl92s_init_sw_vars, |
258 | .deinit_sw_vars = rtl92s_deinit_sw_vars, | 254 | .deinit_sw_vars = rtl92s_deinit_sw_vars, |
@@ -286,6 +282,7 @@ static struct rtl_hal_ops rtl8192se_hal_ops = { | |||
286 | .led_control = rtl92se_led_control, | 282 | .led_control = rtl92se_led_control, |
287 | .set_desc = rtl92se_set_desc, | 283 | .set_desc = rtl92se_set_desc, |
288 | .get_desc = rtl92se_get_desc, | 284 | .get_desc = rtl92se_get_desc, |
285 | .is_tx_desc_closed = rtl92se_is_tx_desc_closed, | ||
289 | .tx_polling = rtl92se_tx_polling, | 286 | .tx_polling = rtl92se_tx_polling, |
290 | .enable_hw_sec = rtl92se_enable_hw_security_config, | 287 | .enable_hw_sec = rtl92se_enable_hw_security_config, |
291 | .set_key = rtl92se_set_key, | 288 | .set_key = rtl92se_set_key, |
@@ -294,6 +291,7 @@ static struct rtl_hal_ops rtl8192se_hal_ops = { | |||
294 | .set_bbreg = rtl92s_phy_set_bb_reg, | 291 | .set_bbreg = rtl92s_phy_set_bb_reg, |
295 | .get_rfreg = rtl92s_phy_query_rf_reg, | 292 | .get_rfreg = rtl92s_phy_query_rf_reg, |
296 | .set_rfreg = rtl92s_phy_set_rf_reg, | 293 | .set_rfreg = rtl92s_phy_set_rf_reg, |
294 | .get_btc_status = rtl_btc_status_false, | ||
297 | }; | 295 | }; |
298 | 296 | ||
299 | static struct rtl_mod_params rtl92se_mod_params = { | 297 | static struct rtl_mod_params rtl92se_mod_params = { |
@@ -322,6 +320,8 @@ static struct rtl_hal_cfg rtl92se_hal_cfg = { | |||
322 | .maps[MAC_RCR_ACRC32] = RCR_ACRC32, | 320 | .maps[MAC_RCR_ACRC32] = RCR_ACRC32, |
323 | .maps[MAC_RCR_ACF] = RCR_ACF, | 321 | .maps[MAC_RCR_ACF] = RCR_ACF, |
324 | .maps[MAC_RCR_AAP] = RCR_AAP, | 322 | .maps[MAC_RCR_AAP] = RCR_AAP, |
323 | .maps[MAC_HIMR] = INTA_MASK, | ||
324 | .maps[MAC_HIMRE] = INTA_MASK + 4, | ||
325 | 325 | ||
326 | .maps[EFUSE_TEST] = REG_EFUSE_TEST, | 326 | .maps[EFUSE_TEST] = REG_EFUSE_TEST, |
327 | .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, | 327 | .maps[EFUSE_CTRL] = REG_EFUSE_CTRL, |
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c index b358ebce8942..672fd3b02835 100644 --- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c +++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c | |||
@@ -640,6 +640,9 @@ u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name) | |||
640 | case HW_DESC_RXPKT_LEN: | 640 | case HW_DESC_RXPKT_LEN: |
641 | ret = GET_RX_STATUS_DESC_PKT_LEN(desc); | 641 | ret = GET_RX_STATUS_DESC_PKT_LEN(desc); |
642 | break; | 642 | break; |
643 | case HW_DESC_RXBUFF_ADDR: | ||
644 | ret = GET_RX_STATUS_DESC_BUFF_ADDR(desc); | ||
645 | break; | ||
643 | default: | 646 | default: |
644 | RT_ASSERT(false, "ERR rxdesc :%d not process\n", | 647 | RT_ASSERT(false, "ERR rxdesc :%d not process\n", |
645 | desc_name); | 648 | desc_name); |
diff --git a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c index 9786313dc62f..9b4d8a637915 100644 --- a/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c +++ b/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c | |||
@@ -800,7 +800,7 @@ static void _rtl8821ae_phy_set_txpower_by_rate_base(struct ieee80211_hw *hw, | |||
800 | "Invalid RateSection %d in Band 2.4G,Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n", | 800 | "Invalid RateSection %d in Band 2.4G,Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n", |
801 | rate_section, path, txnum); | 801 | rate_section, path, txnum); |
802 | break; | 802 | break; |
803 | }; | 803 | } |
804 | } else if (band == BAND_ON_5G) { | 804 | } else if (band == BAND_ON_5G) { |
805 | switch (rate_section) { | 805 | switch (rate_section) { |
806 | case OFDM: | 806 | case OFDM: |
@@ -823,7 +823,7 @@ static void _rtl8821ae_phy_set_txpower_by_rate_base(struct ieee80211_hw *hw, | |||
823 | "Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n", | 823 | "Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in PHY_SetTxPowerByRateBase()\n", |
824 | rate_section, path, txnum); | 824 | rate_section, path, txnum); |
825 | break; | 825 | break; |
826 | }; | 826 | } |
827 | } else { | 827 | } else { |
828 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | 828 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, |
829 | "Invalid Band %d in PHY_SetTxPowerByRateBase()\n", band); | 829 | "Invalid Band %d in PHY_SetTxPowerByRateBase()\n", band); |
@@ -870,7 +870,7 @@ static u8 _rtl8821ae_phy_get_txpower_by_rate_base(struct ieee80211_hw *hw, | |||
870 | "Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n", | 870 | "Invalid RateSection %d in Band 2.4G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n", |
871 | rate_section, path, txnum); | 871 | rate_section, path, txnum); |
872 | break; | 872 | break; |
873 | }; | 873 | } |
874 | } else if (band == BAND_ON_5G) { | 874 | } else if (band == BAND_ON_5G) { |
875 | switch (rate_section) { | 875 | switch (rate_section) { |
876 | case OFDM: | 876 | case OFDM: |
@@ -893,7 +893,7 @@ static u8 _rtl8821ae_phy_get_txpower_by_rate_base(struct ieee80211_hw *hw, | |||
893 | "Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n", | 893 | "Invalid RateSection %d in Band 5G, Rf Path %d, %dTx in PHY_GetTxPowerByRateBase()\n", |
894 | rate_section, path, txnum); | 894 | rate_section, path, txnum); |
895 | break; | 895 | break; |
896 | }; | 896 | } |
897 | } else { | 897 | } else { |
898 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | 898 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, |
899 | "Invalid Band %d in PHY_GetTxPowerByRateBase()\n", band); | 899 | "Invalid Band %d in PHY_GetTxPowerByRateBase()\n", band); |
@@ -1889,15 +1889,18 @@ static void _rtl8821ae_store_tx_power_by_rate(struct ieee80211_hw *hw, | |||
1889 | struct rtl_phy *rtlphy = &rtlpriv->phy; | 1889 | struct rtl_phy *rtlphy = &rtlpriv->phy; |
1890 | u8 rate_section = _rtl8821ae_get_rate_section_index(regaddr); | 1890 | u8 rate_section = _rtl8821ae_get_rate_section_index(regaddr); |
1891 | 1891 | ||
1892 | if (band != BAND_ON_2_4G && band != BAND_ON_5G) | 1892 | if (band != BAND_ON_2_4G && band != BAND_ON_5G) { |
1893 | RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid Band %d\n", band); | 1893 | RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid Band %d\n", band); |
1894 | 1894 | band = BAND_ON_2_4G; | |
1895 | if (rfpath >= MAX_RF_PATH) | 1895 | } |
1896 | if (rfpath >= MAX_RF_PATH) { | ||
1896 | RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid RfPath %d\n", rfpath); | 1897 | RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid RfPath %d\n", rfpath); |
1897 | 1898 | rfpath = MAX_RF_PATH - 1; | |
1898 | if (txnum >= MAX_RF_PATH) | 1899 | } |
1900 | if (txnum >= MAX_RF_PATH) { | ||
1899 | RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid TxNum %d\n", txnum); | 1901 | RT_TRACE(rtlpriv, COMP_INIT, DBG_WARNING, "Invalid TxNum %d\n", txnum); |
1900 | 1902 | txnum = MAX_RF_PATH - 1; | |
1903 | } | ||
1901 | rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section] = data; | 1904 | rtlphy->tx_power_by_rate_offset[band][rfpath][txnum][rate_section] = data; |
1902 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, | 1905 | RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, |
1903 | "TxPwrByRateOffset[Band %d][RfPath %d][TxNum %d][RateSection %d] = 0x%x\n", | 1906 | "TxPwrByRateOffset[Band %d][RfPath %d][TxNum %d][RateSection %d] = 0x%x\n", |
@@ -3743,7 +3746,7 @@ static void _rtl8821ae_iqk_tx_fill_iqc(struct ieee80211_hw *hw, | |||
3743 | break; | 3746 | break; |
3744 | default: | 3747 | default: |
3745 | break; | 3748 | break; |
3746 | }; | 3749 | } |
3747 | } | 3750 | } |
3748 | 3751 | ||
3749 | static void _rtl8821ae_iqk_rx_fill_iqc(struct ieee80211_hw *hw, | 3752 | static void _rtl8821ae_iqk_rx_fill_iqc(struct ieee80211_hw *hw, |
@@ -3764,7 +3767,7 @@ static void _rtl8821ae_iqk_rx_fill_iqc(struct ieee80211_hw *hw, | |||
3764 | break; | 3767 | break; |
3765 | default: | 3768 | default: |
3766 | break; | 3769 | break; |
3767 | }; | 3770 | } |
3768 | } | 3771 | } |
3769 | 3772 | ||
3770 | #define cal_num 10 | 3773 | #define cal_num 10 |
diff --git a/drivers/net/wireless/rtlwifi/usb.c b/drivers/net/wireless/rtlwifi/usb.c index 10cf69c4bc42..46ee956d0235 100644 --- a/drivers/net/wireless/rtlwifi/usb.c +++ b/drivers/net/wireless/rtlwifi/usb.c | |||
@@ -1117,7 +1117,18 @@ int rtl_usb_probe(struct usb_interface *intf, | |||
1117 | } | 1117 | } |
1118 | rtlpriv->cfg->ops->init_sw_leds(hw); | 1118 | rtlpriv->cfg->ops->init_sw_leds(hw); |
1119 | 1119 | ||
1120 | err = ieee80211_register_hw(hw); | ||
1121 | if (err) { | ||
1122 | RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, | ||
1123 | "Can't register mac80211 hw.\n"); | ||
1124 | err = -ENODEV; | ||
1125 | goto error_out; | ||
1126 | } | ||
1127 | rtlpriv->mac80211.mac80211_registered = 1; | ||
1128 | |||
1129 | set_bit(RTL_STATUS_INTERFACE_START, &rtlpriv->status); | ||
1120 | return 0; | 1130 | return 0; |
1131 | |||
1121 | error_out: | 1132 | error_out: |
1122 | rtl_deinit_core(hw); | 1133 | rtl_deinit_core(hw); |
1123 | _rtl_usb_io_handler_release(hw); | 1134 | _rtl_usb_io_handler_release(hw); |
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h index 976667ae8549..6866dcf24340 100644 --- a/drivers/net/wireless/rtlwifi/wifi.h +++ b/drivers/net/wireless/rtlwifi/wifi.h | |||
@@ -1370,7 +1370,7 @@ struct rtl_mac { | |||
1370 | bool rdg_en; | 1370 | bool rdg_en; |
1371 | 1371 | ||
1372 | /*AP*/ | 1372 | /*AP*/ |
1373 | u8 bssid[6]; | 1373 | u8 bssid[ETH_ALEN] __aligned(2); |
1374 | u32 vendor; | 1374 | u32 vendor; |
1375 | u8 mcs[16]; /* 16 bytes mcs for HT rates. */ | 1375 | u8 mcs[16]; /* 16 bytes mcs for HT rates. */ |
1376 | u32 basic_rates; /* b/g rates */ | 1376 | u32 basic_rates; /* b/g rates */ |
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c index 38234851457e..0b30a7b4d663 100644 --- a/drivers/net/wireless/ti/wl1251/main.c +++ b/drivers/net/wireless/ti/wl1251/main.c | |||
@@ -1029,7 +1029,7 @@ static int wl1251_op_hw_scan(struct ieee80211_hw *hw, | |||
1029 | goto out_sleep; | 1029 | goto out_sleep; |
1030 | } | 1030 | } |
1031 | 1031 | ||
1032 | skb = ieee80211_probereq_get(wl->hw, wl->vif, ssid, ssid_len, | 1032 | skb = ieee80211_probereq_get(wl->hw, wl->vif->addr, ssid, ssid_len, |
1033 | req->ie_len); | 1033 | req->ie_len); |
1034 | if (!skb) { | 1034 | if (!skb) { |
1035 | ret = -ENOMEM; | 1035 | ret = -ENOMEM; |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.c b/drivers/net/wireless/ti/wlcore/cmd.c index 05604ee31224..b82661962d33 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.c +++ b/drivers/net/wireless/ti/wlcore/cmd.c | |||
@@ -64,6 +64,9 @@ static int __wlcore_cmd_send(struct wl1271 *wl, u16 id, void *buf, | |||
64 | id != CMD_STOP_FWLOGGER)) | 64 | id != CMD_STOP_FWLOGGER)) |
65 | return -EIO; | 65 | return -EIO; |
66 | 66 | ||
67 | if (WARN_ON_ONCE(len < sizeof(*cmd))) | ||
68 | return -EIO; | ||
69 | |||
67 | cmd = buf; | 70 | cmd = buf; |
68 | cmd->id = cpu_to_le16(id); | 71 | cmd->id = cpu_to_le16(id); |
69 | cmd->status = 0; | 72 | cmd->status = 0; |
@@ -128,8 +131,9 @@ static int __wlcore_cmd_send(struct wl1271 *wl, u16 id, void *buf, | |||
128 | * send command to fw and return cmd status on success | 131 | * send command to fw and return cmd status on success |
129 | * valid_rets contains a bitmap of allowed error codes | 132 | * valid_rets contains a bitmap of allowed error codes |
130 | */ | 133 | */ |
131 | int wlcore_cmd_send_failsafe(struct wl1271 *wl, u16 id, void *buf, size_t len, | 134 | static int wlcore_cmd_send_failsafe(struct wl1271 *wl, u16 id, void *buf, |
132 | size_t res_len, unsigned long valid_rets) | 135 | size_t len, size_t res_len, |
136 | unsigned long valid_rets) | ||
133 | { | 137 | { |
134 | int ret = __wlcore_cmd_send(wl, id, buf, len, res_len); | 138 | int ret = __wlcore_cmd_send(wl, id, buf, len, res_len); |
135 | 139 | ||
@@ -150,7 +154,6 @@ fail: | |||
150 | wl12xx_queue_recovery_work(wl); | 154 | wl12xx_queue_recovery_work(wl); |
151 | return ret; | 155 | return ret; |
152 | } | 156 | } |
153 | EXPORT_SYMBOL_GPL(wl1271_cmd_send); | ||
154 | 157 | ||
155 | /* | 158 | /* |
156 | * wrapper for wlcore_cmd_send that accept only CMD_STATUS_SUCCESS | 159 | * wrapper for wlcore_cmd_send that accept only CMD_STATUS_SUCCESS |
@@ -165,6 +168,7 @@ int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | |||
165 | return ret; | 168 | return ret; |
166 | return 0; | 169 | return 0; |
167 | } | 170 | } |
171 | EXPORT_SYMBOL_GPL(wl1271_cmd_send); | ||
168 | 172 | ||
169 | /* | 173 | /* |
170 | * Poll the mailbox event field until any of the bits in the mask is set or a | 174 | * Poll the mailbox event field until any of the bits in the mask is set or a |
@@ -891,6 +895,9 @@ int wlcore_cmd_configure_failsafe(struct wl1271 *wl, u16 id, void *buf, | |||
891 | 895 | ||
892 | wl1271_debug(DEBUG_CMD, "cmd configure (%d)", id); | 896 | wl1271_debug(DEBUG_CMD, "cmd configure (%d)", id); |
893 | 897 | ||
898 | if (WARN_ON_ONCE(len < sizeof(*acx))) | ||
899 | return -EIO; | ||
900 | |||
894 | acx->id = cpu_to_le16(id); | 901 | acx->id = cpu_to_le16(id); |
895 | 902 | ||
896 | /* payload length, does not include any headers */ | 903 | /* payload length, does not include any headers */ |
@@ -1138,7 +1145,7 @@ int wl12xx_cmd_build_probe_req(struct wl1271 *wl, struct wl12xx_vif *wlvif, | |||
1138 | 1145 | ||
1139 | wl1271_debug(DEBUG_SCAN, "build probe request band %d", band); | 1146 | wl1271_debug(DEBUG_SCAN, "build probe request band %d", band); |
1140 | 1147 | ||
1141 | skb = ieee80211_probereq_get(wl->hw, vif, ssid, ssid_len, | 1148 | skb = ieee80211_probereq_get(wl->hw, vif->addr, ssid, ssid_len, |
1142 | ie0_len + ie1_len); | 1149 | ie0_len + ie1_len); |
1143 | if (!skb) { | 1150 | if (!skb) { |
1144 | ret = -ENOMEM; | 1151 | ret = -ENOMEM; |
diff --git a/drivers/net/wireless/ti/wlcore/cmd.h b/drivers/net/wireless/ti/wlcore/cmd.h index ca6a28b03f8f..453684a71d30 100644 --- a/drivers/net/wireless/ti/wlcore/cmd.h +++ b/drivers/net/wireless/ti/wlcore/cmd.h | |||
@@ -31,8 +31,6 @@ struct acx_header; | |||
31 | 31 | ||
32 | int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, | 32 | int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, |
33 | size_t res_len); | 33 | size_t res_len); |
34 | int wlcore_cmd_send_failsafe(struct wl1271 *wl, u16 id, void *buf, size_t len, | ||
35 | size_t res_len, unsigned long valid_rets); | ||
36 | int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, | 34 | int wl12xx_cmd_role_enable(struct wl1271 *wl, u8 *addr, u8 role_type, |
37 | u8 *role_id); | 35 | u8 *role_id); |
38 | int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); | 36 | int wl12xx_cmd_role_disable(struct wl1271 *wl, u8 *role_id); |
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c index 575c8f6d4009..6ad3fcedab9b 100644 --- a/drivers/net/wireless/ti/wlcore/main.c +++ b/drivers/net/wireless/ti/wlcore/main.c | |||
@@ -5177,10 +5177,11 @@ out: | |||
5177 | } | 5177 | } |
5178 | 5178 | ||
5179 | static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, | 5179 | static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, |
5180 | struct ieee80211_vif *vif, | ||
5180 | struct ieee80211_channel_switch *ch_switch) | 5181 | struct ieee80211_channel_switch *ch_switch) |
5181 | { | 5182 | { |
5182 | struct wl1271 *wl = hw->priv; | 5183 | struct wl1271 *wl = hw->priv; |
5183 | struct wl12xx_vif *wlvif; | 5184 | struct wl12xx_vif *wlvif = wl12xx_vif_to_data(vif); |
5184 | int ret; | 5185 | int ret; |
5185 | 5186 | ||
5186 | wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch"); | 5187 | wl1271_debug(DEBUG_MAC80211, "mac80211 channel switch"); |
@@ -5190,14 +5191,8 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, | |||
5190 | mutex_lock(&wl->mutex); | 5191 | mutex_lock(&wl->mutex); |
5191 | 5192 | ||
5192 | if (unlikely(wl->state == WLCORE_STATE_OFF)) { | 5193 | if (unlikely(wl->state == WLCORE_STATE_OFF)) { |
5193 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | 5194 | if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) |
5194 | struct ieee80211_vif *vif = wl12xx_wlvif_to_vif(wlvif); | ||
5195 | |||
5196 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | ||
5197 | continue; | ||
5198 | |||
5199 | ieee80211_chswitch_done(vif, false); | 5195 | ieee80211_chswitch_done(vif, false); |
5200 | } | ||
5201 | goto out; | 5196 | goto out; |
5202 | } else if (unlikely(wl->state != WLCORE_STATE_ON)) { | 5197 | } else if (unlikely(wl->state != WLCORE_STATE_ON)) { |
5203 | goto out; | 5198 | goto out; |
@@ -5208,11 +5203,9 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, | |||
5208 | goto out; | 5203 | goto out; |
5209 | 5204 | ||
5210 | /* TODO: change mac80211 to pass vif as param */ | 5205 | /* TODO: change mac80211 to pass vif as param */ |
5211 | wl12xx_for_each_wlvif_sta(wl, wlvif) { | ||
5212 | unsigned long delay_usec; | ||
5213 | 5206 | ||
5214 | if (!test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) | 5207 | if (test_bit(WLVIF_FLAG_STA_ASSOCIATED, &wlvif->flags)) { |
5215 | continue; | 5208 | unsigned long delay_usec; |
5216 | 5209 | ||
5217 | ret = wl->ops->channel_switch(wl, wlvif, ch_switch); | 5210 | ret = wl->ops->channel_switch(wl, wlvif, ch_switch); |
5218 | if (ret) | 5211 | if (ret) |
@@ -5222,10 +5215,10 @@ static void wl12xx_op_channel_switch(struct ieee80211_hw *hw, | |||
5222 | 5215 | ||
5223 | /* indicate failure 5 seconds after channel switch time */ | 5216 | /* indicate failure 5 seconds after channel switch time */ |
5224 | delay_usec = ieee80211_tu_to_usec(wlvif->beacon_int) * | 5217 | delay_usec = ieee80211_tu_to_usec(wlvif->beacon_int) * |
5225 | ch_switch->count; | 5218 | ch_switch->count; |
5226 | ieee80211_queue_delayed_work(hw, &wlvif->channel_switch_work, | 5219 | ieee80211_queue_delayed_work(hw, &wlvif->channel_switch_work, |
5227 | usecs_to_jiffies(delay_usec) + | 5220 | usecs_to_jiffies(delay_usec) + |
5228 | msecs_to_jiffies(5000)); | 5221 | msecs_to_jiffies(5000)); |
5229 | } | 5222 | } |
5230 | 5223 | ||
5231 | out_sleep: | 5224 | out_sleep: |