diff options
Diffstat (limited to 'drivers/net/wireless')
139 files changed, 5148 insertions, 2912 deletions
diff --git a/drivers/net/wireless/ath/ath.h b/drivers/net/wireless/ath/ath.h index 86907e5ba6ca..999d24ff242f 100644 --- a/drivers/net/wireless/ath/ath.h +++ b/drivers/net/wireless/ath/ath.h | |||
@@ -148,7 +148,7 @@ struct ath_common { | |||
148 | u16 cachelsz; | 148 | u16 cachelsz; |
149 | u16 curaid; | 149 | u16 curaid; |
150 | u8 macaddr[ETH_ALEN]; | 150 | u8 macaddr[ETH_ALEN]; |
151 | u8 curbssid[ETH_ALEN]; | 151 | u8 curbssid[ETH_ALEN] __aligned(2); |
152 | u8 bssidmask[ETH_ALEN]; | 152 | u8 bssidmask[ETH_ALEN]; |
153 | 153 | ||
154 | u32 rx_bufsize; | 154 | u32 rx_bufsize; |
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 101cadb6e4ba..9b89ac133946 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; |
@@ -576,11 +576,11 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, | |||
576 | * Guts of ath10k_ce_completed_send_next. | 576 | * Guts of ath10k_ce_completed_send_next. |
577 | * The caller takes responsibility for any necessary locking. | 577 | * The caller takes responsibility for any necessary locking. |
578 | */ | 578 | */ |
579 | static int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, | 579 | int ath10k_ce_completed_send_next_nolock(struct ath10k_ce_pipe *ce_state, |
580 | void **per_transfer_contextp, | 580 | void **per_transfer_contextp, |
581 | u32 *bufferp, | 581 | u32 *bufferp, |
582 | unsigned int *nbytesp, | 582 | unsigned int *nbytesp, |
583 | unsigned int *transfer_idp) | 583 | unsigned int *transfer_idp) |
584 | { | 584 | { |
585 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; | 585 | struct ath10k_ce_ring *src_ring = ce_state->src_ring; |
586 | u32 ctrl_addr = ce_state->ctrl_addr; | 586 | u32 ctrl_addr = ce_state->ctrl_addr; |
@@ -817,7 +817,10 @@ void ath10k_ce_enable_interrupts(struct ath10k *ar) | |||
817 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 817 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
818 | int ce_id; | 818 | int ce_id; |
819 | 819 | ||
820 | for (ce_id = 0; ce_id < CE_COUNT; ce_id++) | 820 | /* Skip the last copy engine, CE7 the diagnostic window, as that |
821 | * uses polling and isn't initialized for interrupts. | ||
822 | */ | ||
823 | for (ce_id = 0; ce_id < CE_COUNT - 1; ce_id++) | ||
821 | ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]); | 824 | ath10k_ce_per_engine_handler_adjust(&ar_pci->ce_states[ce_id]); |
822 | } | 825 | } |
823 | 826 | ||
@@ -1020,37 +1023,10 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id, | |||
1020 | * initialized by software/firmware. | 1023 | * initialized by software/firmware. |
1021 | */ | 1024 | */ |
1022 | int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, | 1025 | int ath10k_ce_init_pipe(struct ath10k *ar, unsigned int ce_id, |
1023 | const struct ce_attr *attr, | 1026 | const struct ce_attr *attr) |
1024 | void (*send_cb)(struct ath10k_ce_pipe *), | ||
1025 | void (*recv_cb)(struct ath10k_ce_pipe *)) | ||
1026 | { | 1027 | { |
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; | 1028 | int ret; |
1030 | 1029 | ||
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) { | 1030 | if (attr->src_nentries) { |
1055 | ret = ath10k_ce_init_src_ring(ar, ce_id, attr); | 1031 | ret = ath10k_ce_init_src_ring(ar, ce_id, attr); |
1056 | if (ret) { | 1032 | if (ret) { |
@@ -1098,12 +1074,37 @@ void ath10k_ce_deinit_pipe(struct ath10k *ar, unsigned int ce_id) | |||
1098 | } | 1074 | } |
1099 | 1075 | ||
1100 | int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, | 1076 | int ath10k_ce_alloc_pipe(struct ath10k *ar, int ce_id, |
1101 | const struct ce_attr *attr) | 1077 | const struct ce_attr *attr, |
1078 | void (*send_cb)(struct ath10k_ce_pipe *), | ||
1079 | void (*recv_cb)(struct ath10k_ce_pipe *)) | ||
1102 | { | 1080 | { |
1103 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1081 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); |
1104 | struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; | 1082 | struct ath10k_ce_pipe *ce_state = &ar_pci->ce_states[ce_id]; |
1105 | int ret; | 1083 | int ret; |
1106 | 1084 | ||
1085 | /* | ||
1086 | * Make sure there's enough CE ringbuffer entries for HTT TX to avoid | ||
1087 | * additional TX locking checks. | ||
1088 | * | ||
1089 | * For the lack of a better place do the check here. | ||
1090 | */ | ||
1091 | BUILD_BUG_ON(2*TARGET_NUM_MSDU_DESC > | ||
1092 | (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); | ||
1093 | BUILD_BUG_ON(2*TARGET_10X_NUM_MSDU_DESC > | ||
1094 | (CE_HTT_H2T_MSG_SRC_NENTRIES - 1)); | ||
1095 | |||
1096 | ce_state->ar = ar; | ||
1097 | ce_state->id = ce_id; | ||
1098 | ce_state->ctrl_addr = ath10k_ce_base_address(ce_id); | ||
1099 | ce_state->attr_flags = attr->flags; | ||
1100 | ce_state->src_sz_max = attr->src_sz_max; | ||
1101 | |||
1102 | if (attr->src_nentries) | ||
1103 | ce_state->send_cb = send_cb; | ||
1104 | |||
1105 | if (attr->dest_nentries) | ||
1106 | ce_state->recv_cb = recv_cb; | ||
1107 | |||
1107 | if (attr->src_nentries) { | 1108 | if (attr->src_nentries) { |
1108 | ce_state->src_ring = ath10k_ce_alloc_src_ring(ar, ce_id, attr); | 1109 | ce_state->src_ring = ath10k_ce_alloc_src_ring(ar, ce_id, attr); |
1109 | if (IS_ERR(ce_state->src_ring)) { | 1110 | 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..5c23d00f7d60 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c | |||
@@ -138,7 +138,8 @@ static const struct firmware *ath10k_fetch_fw_file(struct ath10k *ar, | |||
138 | return fw; | 138 | return fw; |
139 | } | 139 | } |
140 | 140 | ||
141 | static int ath10k_push_board_ext_data(struct ath10k *ar) | 141 | static int ath10k_push_board_ext_data(struct ath10k *ar, const void *data, |
142 | size_t data_len) | ||
142 | { | 143 | { |
143 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; | 144 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; |
144 | u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ; | 145 | u32 board_ext_data_size = QCA988X_BOARD_EXT_DATA_SZ; |
@@ -159,14 +160,14 @@ static int ath10k_push_board_ext_data(struct ath10k *ar) | |||
159 | if (board_ext_data_addr == 0) | 160 | if (board_ext_data_addr == 0) |
160 | return 0; | 161 | return 0; |
161 | 162 | ||
162 | if (ar->board_len != (board_data_size + board_ext_data_size)) { | 163 | if (data_len != (board_data_size + board_ext_data_size)) { |
163 | ath10k_err(ar, "invalid board (ext) data sizes %zu != %d+%d\n", | 164 | ath10k_err(ar, "invalid board (ext) data sizes %zu != %d+%d\n", |
164 | ar->board_len, board_data_size, board_ext_data_size); | 165 | data_len, board_data_size, board_ext_data_size); |
165 | return -EINVAL; | 166 | return -EINVAL; |
166 | } | 167 | } |
167 | 168 | ||
168 | ret = ath10k_bmi_write_memory(ar, board_ext_data_addr, | 169 | ret = ath10k_bmi_write_memory(ar, board_ext_data_addr, |
169 | ar->board_data + board_data_size, | 170 | data + board_data_size, |
170 | board_ext_data_size); | 171 | board_ext_data_size); |
171 | if (ret) { | 172 | if (ret) { |
172 | ath10k_err(ar, "could not write board ext data (%d)\n", ret); | 173 | ath10k_err(ar, "could not write board ext data (%d)\n", ret); |
@@ -184,13 +185,14 @@ static int ath10k_push_board_ext_data(struct ath10k *ar) | |||
184 | return 0; | 185 | return 0; |
185 | } | 186 | } |
186 | 187 | ||
187 | static int ath10k_download_board_data(struct ath10k *ar) | 188 | static int ath10k_download_board_data(struct ath10k *ar, const void *data, |
189 | size_t data_len) | ||
188 | { | 190 | { |
189 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; | 191 | u32 board_data_size = QCA988X_BOARD_DATA_SZ; |
190 | u32 address; | 192 | u32 address; |
191 | int ret; | 193 | int ret; |
192 | 194 | ||
193 | ret = ath10k_push_board_ext_data(ar); | 195 | ret = ath10k_push_board_ext_data(ar, data, data_len); |
194 | if (ret) { | 196 | if (ret) { |
195 | ath10k_err(ar, "could not push board ext data (%d)\n", ret); | 197 | ath10k_err(ar, "could not push board ext data (%d)\n", ret); |
196 | goto exit; | 198 | goto exit; |
@@ -202,9 +204,9 @@ static int ath10k_download_board_data(struct ath10k *ar) | |||
202 | goto exit; | 204 | goto exit; |
203 | } | 205 | } |
204 | 206 | ||
205 | ret = ath10k_bmi_write_memory(ar, address, ar->board_data, | 207 | ret = ath10k_bmi_write_memory(ar, address, data, |
206 | min_t(u32, board_data_size, | 208 | min_t(u32, board_data_size, |
207 | ar->board_len)); | 209 | data_len)); |
208 | if (ret) { | 210 | if (ret) { |
209 | ath10k_err(ar, "could not write board data (%d)\n", ret); | 211 | ath10k_err(ar, "could not write board data (%d)\n", ret); |
210 | goto exit; | 212 | goto exit; |
@@ -220,11 +222,39 @@ exit: | |||
220 | return ret; | 222 | return ret; |
221 | } | 223 | } |
222 | 224 | ||
225 | static int ath10k_download_cal_file(struct ath10k *ar) | ||
226 | { | ||
227 | int ret; | ||
228 | |||
229 | if (!ar->cal_file) | ||
230 | return -ENOENT; | ||
231 | |||
232 | if (IS_ERR(ar->cal_file)) | ||
233 | return PTR_ERR(ar->cal_file); | ||
234 | |||
235 | ret = ath10k_download_board_data(ar, ar->cal_file->data, | ||
236 | ar->cal_file->size); | ||
237 | if (ret) { | ||
238 | ath10k_err(ar, "failed to download cal_file data: %d\n", ret); | ||
239 | return ret; | ||
240 | } | ||
241 | |||
242 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cal file downloaded\n"); | ||
243 | |||
244 | return 0; | ||
245 | } | ||
246 | |||
223 | static int ath10k_download_and_run_otp(struct ath10k *ar) | 247 | static int ath10k_download_and_run_otp(struct ath10k *ar) |
224 | { | 248 | { |
225 | u32 result, address = ar->hw_params.patch_load_addr; | 249 | u32 result, address = ar->hw_params.patch_load_addr; |
226 | int ret; | 250 | int ret; |
227 | 251 | ||
252 | ret = ath10k_download_board_data(ar, ar->board_data, ar->board_len); | ||
253 | if (ret) { | ||
254 | ath10k_err(ar, "failed to download board data: %d\n", ret); | ||
255 | return ret; | ||
256 | } | ||
257 | |||
228 | /* OTP is optional */ | 258 | /* OTP is optional */ |
229 | 259 | ||
230 | if (!ar->otp_data || !ar->otp_len) { | 260 | if (!ar->otp_data || !ar->otp_len) { |
@@ -308,6 +338,9 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) | |||
308 | if (ar->firmware && !IS_ERR(ar->firmware)) | 338 | if (ar->firmware && !IS_ERR(ar->firmware)) |
309 | release_firmware(ar->firmware); | 339 | release_firmware(ar->firmware); |
310 | 340 | ||
341 | if (ar->cal_file && !IS_ERR(ar->cal_file)) | ||
342 | release_firmware(ar->cal_file); | ||
343 | |||
311 | ar->board = NULL; | 344 | ar->board = NULL; |
312 | ar->board_data = NULL; | 345 | ar->board_data = NULL; |
313 | ar->board_len = 0; | 346 | ar->board_len = 0; |
@@ -319,6 +352,27 @@ static void ath10k_core_free_firmware_files(struct ath10k *ar) | |||
319 | ar->firmware = NULL; | 352 | ar->firmware = NULL; |
320 | ar->firmware_data = NULL; | 353 | ar->firmware_data = NULL; |
321 | ar->firmware_len = 0; | 354 | ar->firmware_len = 0; |
355 | |||
356 | ar->cal_file = NULL; | ||
357 | } | ||
358 | |||
359 | static int ath10k_fetch_cal_file(struct ath10k *ar) | ||
360 | { | ||
361 | char filename[100]; | ||
362 | |||
363 | /* cal-<bus>-<id>.bin */ | ||
364 | scnprintf(filename, sizeof(filename), "cal-%s-%s.bin", | ||
365 | ath10k_bus_str(ar->hif.bus), dev_name(ar->dev)); | ||
366 | |||
367 | ar->cal_file = ath10k_fetch_fw_file(ar, ATH10K_FW_DIR, filename); | ||
368 | if (IS_ERR(ar->cal_file)) | ||
369 | /* calibration file is optional, don't print any warnings */ | ||
370 | return PTR_ERR(ar->cal_file); | ||
371 | |||
372 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "found calibration file %s/%s\n", | ||
373 | ATH10K_FW_DIR, filename); | ||
374 | |||
375 | return 0; | ||
322 | } | 376 | } |
323 | 377 | ||
324 | static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar) | 378 | static int ath10k_core_fetch_firmware_api_1(struct ath10k *ar) |
@@ -562,6 +616,9 @@ static int ath10k_core_fetch_firmware_files(struct ath10k *ar) | |||
562 | { | 616 | { |
563 | int ret; | 617 | int ret; |
564 | 618 | ||
619 | /* calibration file is optional, don't check for any errors */ | ||
620 | ath10k_fetch_cal_file(ar); | ||
621 | |||
565 | ar->fw_api = 3; | 622 | ar->fw_api = 3; |
566 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); | 623 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "trying fw api %d\n", ar->fw_api); |
567 | 624 | ||
@@ -589,30 +646,32 @@ success: | |||
589 | return 0; | 646 | return 0; |
590 | } | 647 | } |
591 | 648 | ||
592 | static int ath10k_init_download_firmware(struct ath10k *ar, | 649 | static int ath10k_download_cal_data(struct ath10k *ar) |
593 | enum ath10k_firmware_mode mode) | ||
594 | { | 650 | { |
595 | int ret; | 651 | int ret; |
596 | 652 | ||
597 | ret = ath10k_download_board_data(ar); | 653 | ret = ath10k_download_cal_file(ar); |
598 | if (ret) { | 654 | if (ret == 0) { |
599 | ath10k_err(ar, "failed to download board data: %d\n", ret); | 655 | ar->cal_mode = ATH10K_CAL_MODE_FILE; |
600 | return ret; | 656 | goto done; |
601 | } | 657 | } |
602 | 658 | ||
659 | ath10k_dbg(ar, ATH10K_DBG_BOOT, | ||
660 | "boot did not find a calibration file, try OTP next: %d\n", | ||
661 | ret); | ||
662 | |||
603 | ret = ath10k_download_and_run_otp(ar); | 663 | ret = ath10k_download_and_run_otp(ar); |
604 | if (ret) { | 664 | if (ret) { |
605 | ath10k_err(ar, "failed to run otp: %d\n", ret); | 665 | ath10k_err(ar, "failed to run otp: %d\n", ret); |
606 | return ret; | 666 | return ret; |
607 | } | 667 | } |
608 | 668 | ||
609 | ret = ath10k_download_fw(ar, mode); | 669 | 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 | 670 | ||
615 | return ret; | 671 | done: |
672 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot using calibration mode %s\n", | ||
673 | ath10k_cal_mode_str(ar->cal_mode)); | ||
674 | return 0; | ||
616 | } | 675 | } |
617 | 676 | ||
618 | static int ath10k_init_uart(struct ath10k *ar) | 677 | static int ath10k_init_uart(struct ath10k *ar) |
@@ -729,7 +788,11 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) | |||
729 | goto err; | 788 | goto err; |
730 | } | 789 | } |
731 | 790 | ||
732 | status = ath10k_init_download_firmware(ar, mode); | 791 | status = ath10k_download_cal_data(ar); |
792 | if (status) | ||
793 | goto err; | ||
794 | |||
795 | status = ath10k_download_fw(ar, mode); | ||
733 | if (status) | 796 | if (status) |
734 | goto err; | 797 | goto err; |
735 | 798 | ||
@@ -846,9 +909,9 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) | |||
846 | goto err_hif_stop; | 909 | goto err_hif_stop; |
847 | 910 | ||
848 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | 911 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) |
849 | ar->free_vdev_map = (1 << TARGET_10X_NUM_VDEVS) - 1; | 912 | ar->free_vdev_map = (1LL << TARGET_10X_NUM_VDEVS) - 1; |
850 | else | 913 | else |
851 | ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1; | 914 | ar->free_vdev_map = (1LL << TARGET_NUM_VDEVS) - 1; |
852 | 915 | ||
853 | INIT_LIST_HEAD(&ar->arvifs); | 916 | INIT_LIST_HEAD(&ar->arvifs); |
854 | 917 | ||
@@ -1084,6 +1147,7 @@ void ath10k_core_unregister(struct ath10k *ar) | |||
1084 | EXPORT_SYMBOL(ath10k_core_unregister); | 1147 | EXPORT_SYMBOL(ath10k_core_unregister); |
1085 | 1148 | ||
1086 | struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, | 1149 | struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, |
1150 | enum ath10k_bus bus, | ||
1087 | const struct ath10k_hif_ops *hif_ops) | 1151 | const struct ath10k_hif_ops *hif_ops) |
1088 | { | 1152 | { |
1089 | struct ath10k *ar; | 1153 | struct ath10k *ar; |
@@ -1100,6 +1164,7 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, | |||
1100 | ar->dev = dev; | 1164 | ar->dev = dev; |
1101 | 1165 | ||
1102 | ar->hif.ops = hif_ops; | 1166 | ar->hif.ops = hif_ops; |
1167 | ar->hif.bus = bus; | ||
1103 | 1168 | ||
1104 | init_completion(&ar->scan.started); | 1169 | init_completion(&ar->scan.started); |
1105 | init_completion(&ar->scan.completed); | 1170 | init_completion(&ar->scan.completed); |
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index fe531ea6926c..4ca6dc94dd05 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 | ||
@@ -371,6 +388,23 @@ enum ath10k_dev_flags { | |||
371 | ATH10K_FLAG_CORE_REGISTERED, | 388 | ATH10K_FLAG_CORE_REGISTERED, |
372 | }; | 389 | }; |
373 | 390 | ||
391 | enum ath10k_cal_mode { | ||
392 | ATH10K_CAL_MODE_FILE, | ||
393 | ATH10K_CAL_MODE_OTP, | ||
394 | }; | ||
395 | |||
396 | static inline const char *ath10k_cal_mode_str(enum ath10k_cal_mode mode) | ||
397 | { | ||
398 | switch (mode) { | ||
399 | case ATH10K_CAL_MODE_FILE: | ||
400 | return "file"; | ||
401 | case ATH10K_CAL_MODE_OTP: | ||
402 | return "otp"; | ||
403 | } | ||
404 | |||
405 | return "unknown"; | ||
406 | } | ||
407 | |||
374 | enum ath10k_scan_state { | 408 | enum ath10k_scan_state { |
375 | ATH10K_SCAN_IDLE, | 409 | ATH10K_SCAN_IDLE, |
376 | ATH10K_SCAN_STARTING, | 410 | ATH10K_SCAN_STARTING, |
@@ -421,6 +455,7 @@ struct ath10k { | |||
421 | bool p2p; | 455 | bool p2p; |
422 | 456 | ||
423 | struct { | 457 | struct { |
458 | enum ath10k_bus bus; | ||
424 | const struct ath10k_hif_ops *ops; | 459 | const struct ath10k_hif_ops *ops; |
425 | } hif; | 460 | } hif; |
426 | 461 | ||
@@ -456,7 +491,10 @@ struct ath10k { | |||
456 | const void *firmware_data; | 491 | const void *firmware_data; |
457 | size_t firmware_len; | 492 | size_t firmware_len; |
458 | 493 | ||
494 | const struct firmware *cal_file; | ||
495 | |||
459 | int fw_api; | 496 | int fw_api; |
497 | enum ath10k_cal_mode cal_mode; | ||
460 | 498 | ||
461 | struct { | 499 | struct { |
462 | struct completion started; | 500 | struct completion started; |
@@ -482,7 +520,7 @@ struct ath10k { | |||
482 | /* current operating channel definition */ | 520 | /* current operating channel definition */ |
483 | struct cfg80211_chan_def chandef; | 521 | struct cfg80211_chan_def chandef; |
484 | 522 | ||
485 | int free_vdev_map; | 523 | unsigned long long free_vdev_map; |
486 | bool monitor; | 524 | bool monitor; |
487 | int monitor_vdev_id; | 525 | int monitor_vdev_id; |
488 | bool monitor_started; | 526 | bool monitor_started; |
@@ -563,11 +601,19 @@ struct ath10k { | |||
563 | bool utf_monitor; | 601 | bool utf_monitor; |
564 | } testmode; | 602 | } testmode; |
565 | 603 | ||
604 | struct { | ||
605 | /* protected by data_lock */ | ||
606 | u32 fw_crash_counter; | ||
607 | u32 fw_warm_reset_counter; | ||
608 | u32 fw_cold_reset_counter; | ||
609 | } stats; | ||
610 | |||
566 | /* must be last */ | 611 | /* must be last */ |
567 | u8 drv_priv[0] __aligned(sizeof(void *)); | 612 | u8 drv_priv[0] __aligned(sizeof(void *)); |
568 | }; | 613 | }; |
569 | 614 | ||
570 | struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, | 615 | struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, |
616 | enum ath10k_bus bus, | ||
571 | const struct ath10k_hif_ops *hif_ops); | 617 | const struct ath10k_hif_ops *hif_ops); |
572 | void ath10k_core_destroy(struct ath10k *ar); | 618 | void ath10k_core_destroy(struct ath10k *ar); |
573 | 619 | ||
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 3756feba3223..9147dd36dcdd 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 | }; |
@@ -1029,6 +1131,166 @@ exit: | |||
1029 | return ret; | 1131 | return ret; |
1030 | } | 1132 | } |
1031 | 1133 | ||
1134 | /* TODO: Would be nice to always support ethtool stats, would need to | ||
1135 | * move the stats storage out of ath10k_debug, or always have ath10k_debug | ||
1136 | * struct available.. | ||
1137 | */ | ||
1138 | |||
1139 | /* This generally cooresponds to the debugfs fw_stats file */ | ||
1140 | static const char ath10k_gstrings_stats[][ETH_GSTRING_LEN] = { | ||
1141 | "tx_pkts_nic", | ||
1142 | "tx_bytes_nic", | ||
1143 | "rx_pkts_nic", | ||
1144 | "rx_bytes_nic", | ||
1145 | "d_noise_floor", | ||
1146 | "d_cycle_count", | ||
1147 | "d_phy_error", | ||
1148 | "d_rts_bad", | ||
1149 | "d_rts_good", | ||
1150 | "d_tx_power", /* in .5 dbM I think */ | ||
1151 | "d_rx_crc_err", /* fcs_bad */ | ||
1152 | "d_no_beacon", | ||
1153 | "d_tx_mpdus_queued", | ||
1154 | "d_tx_msdu_queued", | ||
1155 | "d_tx_msdu_dropped", | ||
1156 | "d_local_enqued", | ||
1157 | "d_local_freed", | ||
1158 | "d_tx_ppdu_hw_queued", | ||
1159 | "d_tx_ppdu_reaped", | ||
1160 | "d_tx_fifo_underrun", | ||
1161 | "d_tx_ppdu_abort", | ||
1162 | "d_tx_mpdu_requed", | ||
1163 | "d_tx_excessive_retries", | ||
1164 | "d_tx_hw_rate", | ||
1165 | "d_tx_dropped_sw_retries", | ||
1166 | "d_tx_illegal_rate", | ||
1167 | "d_tx_continuous_xretries", | ||
1168 | "d_tx_timeout", | ||
1169 | "d_tx_mpdu_txop_limit", | ||
1170 | "d_pdev_resets", | ||
1171 | "d_rx_mid_ppdu_route_change", | ||
1172 | "d_rx_status", | ||
1173 | "d_rx_extra_frags_ring0", | ||
1174 | "d_rx_extra_frags_ring1", | ||
1175 | "d_rx_extra_frags_ring2", | ||
1176 | "d_rx_extra_frags_ring3", | ||
1177 | "d_rx_msdu_htt", | ||
1178 | "d_rx_mpdu_htt", | ||
1179 | "d_rx_msdu_stack", | ||
1180 | "d_rx_mpdu_stack", | ||
1181 | "d_rx_phy_err", | ||
1182 | "d_rx_phy_err_drops", | ||
1183 | "d_rx_mpdu_errors", /* FCS, MIC, ENC */ | ||
1184 | "d_fw_crash_count", | ||
1185 | "d_fw_warm_reset_count", | ||
1186 | "d_fw_cold_reset_count", | ||
1187 | }; | ||
1188 | |||
1189 | #define ATH10K_SSTATS_LEN ARRAY_SIZE(ath10k_gstrings_stats) | ||
1190 | |||
1191 | void ath10k_debug_get_et_strings(struct ieee80211_hw *hw, | ||
1192 | struct ieee80211_vif *vif, | ||
1193 | u32 sset, u8 *data) | ||
1194 | { | ||
1195 | if (sset == ETH_SS_STATS) | ||
1196 | memcpy(data, *ath10k_gstrings_stats, | ||
1197 | sizeof(ath10k_gstrings_stats)); | ||
1198 | } | ||
1199 | |||
1200 | int ath10k_debug_get_et_sset_count(struct ieee80211_hw *hw, | ||
1201 | struct ieee80211_vif *vif, int sset) | ||
1202 | { | ||
1203 | if (sset == ETH_SS_STATS) | ||
1204 | return ATH10K_SSTATS_LEN; | ||
1205 | |||
1206 | return 0; | ||
1207 | } | ||
1208 | |||
1209 | void ath10k_debug_get_et_stats(struct ieee80211_hw *hw, | ||
1210 | struct ieee80211_vif *vif, | ||
1211 | struct ethtool_stats *stats, u64 *data) | ||
1212 | { | ||
1213 | struct ath10k *ar = hw->priv; | ||
1214 | static const struct ath10k_fw_stats_pdev zero_stats = {}; | ||
1215 | const struct ath10k_fw_stats_pdev *pdev_stats; | ||
1216 | int i = 0, ret; | ||
1217 | |||
1218 | mutex_lock(&ar->conf_mutex); | ||
1219 | |||
1220 | if (ar->state == ATH10K_STATE_ON) { | ||
1221 | ret = ath10k_debug_fw_stats_request(ar); | ||
1222 | if (ret) { | ||
1223 | /* just print a warning and try to use older results */ | ||
1224 | ath10k_warn(ar, | ||
1225 | "failed to get fw stats for ethtool: %d\n", | ||
1226 | ret); | ||
1227 | } | ||
1228 | } | ||
1229 | |||
1230 | pdev_stats = list_first_entry_or_null(&ar->debug.fw_stats.pdevs, | ||
1231 | struct ath10k_fw_stats_pdev, | ||
1232 | list); | ||
1233 | if (!pdev_stats) { | ||
1234 | /* no results available so just return zeroes */ | ||
1235 | pdev_stats = &zero_stats; | ||
1236 | } | ||
1237 | |||
1238 | spin_lock_bh(&ar->data_lock); | ||
1239 | |||
1240 | data[i++] = pdev_stats->hw_reaped; /* ppdu reaped */ | ||
1241 | data[i++] = 0; /* tx bytes */ | ||
1242 | data[i++] = pdev_stats->htt_mpdus; | ||
1243 | data[i++] = 0; /* rx bytes */ | ||
1244 | data[i++] = pdev_stats->ch_noise_floor; | ||
1245 | data[i++] = pdev_stats->cycle_count; | ||
1246 | data[i++] = pdev_stats->phy_err_count; | ||
1247 | data[i++] = pdev_stats->rts_bad; | ||
1248 | data[i++] = pdev_stats->rts_good; | ||
1249 | data[i++] = pdev_stats->chan_tx_power; | ||
1250 | data[i++] = pdev_stats->fcs_bad; | ||
1251 | data[i++] = pdev_stats->no_beacons; | ||
1252 | data[i++] = pdev_stats->mpdu_enqued; | ||
1253 | data[i++] = pdev_stats->msdu_enqued; | ||
1254 | data[i++] = pdev_stats->wmm_drop; | ||
1255 | data[i++] = pdev_stats->local_enqued; | ||
1256 | data[i++] = pdev_stats->local_freed; | ||
1257 | data[i++] = pdev_stats->hw_queued; | ||
1258 | data[i++] = pdev_stats->hw_reaped; | ||
1259 | data[i++] = pdev_stats->underrun; | ||
1260 | data[i++] = pdev_stats->tx_abort; | ||
1261 | data[i++] = pdev_stats->mpdus_requed; | ||
1262 | data[i++] = pdev_stats->tx_ko; | ||
1263 | data[i++] = pdev_stats->data_rc; | ||
1264 | data[i++] = pdev_stats->sw_retry_failure; | ||
1265 | data[i++] = pdev_stats->illgl_rate_phy_err; | ||
1266 | data[i++] = pdev_stats->pdev_cont_xretry; | ||
1267 | data[i++] = pdev_stats->pdev_tx_timeout; | ||
1268 | data[i++] = pdev_stats->txop_ovf; | ||
1269 | data[i++] = pdev_stats->pdev_resets; | ||
1270 | data[i++] = pdev_stats->mid_ppdu_route_change; | ||
1271 | data[i++] = pdev_stats->status_rcvd; | ||
1272 | data[i++] = pdev_stats->r0_frags; | ||
1273 | data[i++] = pdev_stats->r1_frags; | ||
1274 | data[i++] = pdev_stats->r2_frags; | ||
1275 | data[i++] = pdev_stats->r3_frags; | ||
1276 | data[i++] = pdev_stats->htt_msdus; | ||
1277 | data[i++] = pdev_stats->htt_mpdus; | ||
1278 | data[i++] = pdev_stats->loc_msdus; | ||
1279 | data[i++] = pdev_stats->loc_mpdus; | ||
1280 | data[i++] = pdev_stats->phy_errs; | ||
1281 | data[i++] = pdev_stats->phy_err_drop; | ||
1282 | data[i++] = pdev_stats->mpdu_errs; | ||
1283 | data[i++] = ar->stats.fw_crash_counter; | ||
1284 | data[i++] = ar->stats.fw_warm_reset_counter; | ||
1285 | data[i++] = ar->stats.fw_cold_reset_counter; | ||
1286 | |||
1287 | spin_unlock_bh(&ar->data_lock); | ||
1288 | |||
1289 | mutex_unlock(&ar->conf_mutex); | ||
1290 | |||
1291 | WARN_ON(i != ATH10K_SSTATS_LEN); | ||
1292 | } | ||
1293 | |||
1032 | static const struct file_operations fops_fw_dbglog = { | 1294 | static const struct file_operations fops_fw_dbglog = { |
1033 | .read = ath10k_read_fw_dbglog, | 1295 | .read = ath10k_read_fw_dbglog, |
1034 | .write = ath10k_write_fw_dbglog, | 1296 | .write = ath10k_write_fw_dbglog, |
@@ -1037,6 +1299,84 @@ static const struct file_operations fops_fw_dbglog = { | |||
1037 | .llseek = default_llseek, | 1299 | .llseek = default_llseek, |
1038 | }; | 1300 | }; |
1039 | 1301 | ||
1302 | static int ath10k_debug_cal_data_open(struct inode *inode, struct file *file) | ||
1303 | { | ||
1304 | struct ath10k *ar = inode->i_private; | ||
1305 | void *buf; | ||
1306 | u32 hi_addr; | ||
1307 | __le32 addr; | ||
1308 | int ret; | ||
1309 | |||
1310 | mutex_lock(&ar->conf_mutex); | ||
1311 | |||
1312 | if (ar->state != ATH10K_STATE_ON && | ||
1313 | ar->state != ATH10K_STATE_UTF) { | ||
1314 | ret = -ENETDOWN; | ||
1315 | goto err; | ||
1316 | } | ||
1317 | |||
1318 | buf = vmalloc(QCA988X_CAL_DATA_LEN); | ||
1319 | if (!buf) { | ||
1320 | ret = -ENOMEM; | ||
1321 | goto err; | ||
1322 | } | ||
1323 | |||
1324 | hi_addr = host_interest_item_address(HI_ITEM(hi_board_data)); | ||
1325 | |||
1326 | ret = ath10k_hif_diag_read(ar, hi_addr, &addr, sizeof(addr)); | ||
1327 | if (ret) { | ||
1328 | ath10k_warn(ar, "failed to read hi_board_data address: %d\n", ret); | ||
1329 | goto err_vfree; | ||
1330 | } | ||
1331 | |||
1332 | ret = ath10k_hif_diag_read(ar, le32_to_cpu(addr), buf, | ||
1333 | QCA988X_CAL_DATA_LEN); | ||
1334 | if (ret) { | ||
1335 | ath10k_warn(ar, "failed to read calibration data: %d\n", ret); | ||
1336 | goto err_vfree; | ||
1337 | } | ||
1338 | |||
1339 | file->private_data = buf; | ||
1340 | |||
1341 | mutex_unlock(&ar->conf_mutex); | ||
1342 | |||
1343 | return 0; | ||
1344 | |||
1345 | err_vfree: | ||
1346 | vfree(buf); | ||
1347 | |||
1348 | err: | ||
1349 | mutex_unlock(&ar->conf_mutex); | ||
1350 | |||
1351 | return ret; | ||
1352 | } | ||
1353 | |||
1354 | static ssize_t ath10k_debug_cal_data_read(struct file *file, | ||
1355 | char __user *user_buf, | ||
1356 | size_t count, loff_t *ppos) | ||
1357 | { | ||
1358 | void *buf = file->private_data; | ||
1359 | |||
1360 | return simple_read_from_buffer(user_buf, count, ppos, | ||
1361 | buf, QCA988X_CAL_DATA_LEN); | ||
1362 | } | ||
1363 | |||
1364 | static int ath10k_debug_cal_data_release(struct inode *inode, | ||
1365 | struct file *file) | ||
1366 | { | ||
1367 | vfree(file->private_data); | ||
1368 | |||
1369 | return 0; | ||
1370 | } | ||
1371 | |||
1372 | static const struct file_operations fops_cal_data = { | ||
1373 | .open = ath10k_debug_cal_data_open, | ||
1374 | .read = ath10k_debug_cal_data_read, | ||
1375 | .release = ath10k_debug_cal_data_release, | ||
1376 | .owner = THIS_MODULE, | ||
1377 | .llseek = default_llseek, | ||
1378 | }; | ||
1379 | |||
1040 | int ath10k_debug_start(struct ath10k *ar) | 1380 | int ath10k_debug_start(struct ath10k *ar) |
1041 | { | 1381 | { |
1042 | int ret; | 1382 | int ret; |
@@ -1057,7 +1397,22 @@ int ath10k_debug_start(struct ath10k *ar) | |||
1057 | ret); | 1397 | ret); |
1058 | } | 1398 | } |
1059 | 1399 | ||
1060 | return 0; | 1400 | if (ar->debug.pktlog_filter) { |
1401 | ret = ath10k_wmi_pdev_pktlog_enable(ar, | ||
1402 | ar->debug.pktlog_filter); | ||
1403 | if (ret) | ||
1404 | /* not serious */ | ||
1405 | ath10k_warn(ar, | ||
1406 | "failed to enable pktlog filter %x: %d\n", | ||
1407 | ar->debug.pktlog_filter, ret); | ||
1408 | } else { | ||
1409 | ret = ath10k_wmi_pdev_pktlog_disable(ar); | ||
1410 | if (ret) | ||
1411 | /* not serious */ | ||
1412 | ath10k_warn(ar, "failed to disable pktlog: %d\n", ret); | ||
1413 | } | ||
1414 | |||
1415 | return ret; | ||
1061 | } | 1416 | } |
1062 | 1417 | ||
1063 | void ath10k_debug_stop(struct ath10k *ar) | 1418 | void ath10k_debug_stop(struct ath10k *ar) |
@@ -1072,6 +1427,8 @@ void ath10k_debug_stop(struct ath10k *ar) | |||
1072 | 1427 | ||
1073 | ar->debug.htt_max_amsdu = 0; | 1428 | ar->debug.htt_max_amsdu = 0; |
1074 | ar->debug.htt_max_ampdu = 0; | 1429 | ar->debug.htt_max_ampdu = 0; |
1430 | |||
1431 | ath10k_wmi_pdev_pktlog_disable(ar); | ||
1075 | } | 1432 | } |
1076 | 1433 | ||
1077 | static ssize_t ath10k_write_simulate_radar(struct file *file, | 1434 | static ssize_t ath10k_write_simulate_radar(struct file *file, |
@@ -1154,12 +1511,78 @@ static const struct file_operations fops_dfs_stats = { | |||
1154 | .llseek = default_llseek, | 1511 | .llseek = default_llseek, |
1155 | }; | 1512 | }; |
1156 | 1513 | ||
1514 | static ssize_t ath10k_write_pktlog_filter(struct file *file, | ||
1515 | const char __user *ubuf, | ||
1516 | size_t count, loff_t *ppos) | ||
1517 | { | ||
1518 | struct ath10k *ar = file->private_data; | ||
1519 | u32 filter; | ||
1520 | int ret; | ||
1521 | |||
1522 | if (kstrtouint_from_user(ubuf, count, 0, &filter)) | ||
1523 | return -EINVAL; | ||
1524 | |||
1525 | mutex_lock(&ar->conf_mutex); | ||
1526 | |||
1527 | if (ar->state != ATH10K_STATE_ON) { | ||
1528 | ar->debug.pktlog_filter = filter; | ||
1529 | ret = count; | ||
1530 | goto out; | ||
1531 | } | ||
1532 | |||
1533 | if (filter && (filter != ar->debug.pktlog_filter)) { | ||
1534 | ret = ath10k_wmi_pdev_pktlog_enable(ar, filter); | ||
1535 | if (ret) { | ||
1536 | ath10k_warn(ar, "failed to enable pktlog filter %x: %d\n", | ||
1537 | ar->debug.pktlog_filter, ret); | ||
1538 | goto out; | ||
1539 | } | ||
1540 | } else { | ||
1541 | ret = ath10k_wmi_pdev_pktlog_disable(ar); | ||
1542 | if (ret) { | ||
1543 | ath10k_warn(ar, "failed to disable pktlog: %d\n", ret); | ||
1544 | goto out; | ||
1545 | } | ||
1546 | } | ||
1547 | |||
1548 | ar->debug.pktlog_filter = filter; | ||
1549 | ret = count; | ||
1550 | |||
1551 | out: | ||
1552 | mutex_unlock(&ar->conf_mutex); | ||
1553 | return ret; | ||
1554 | } | ||
1555 | |||
1556 | static ssize_t ath10k_read_pktlog_filter(struct file *file, char __user *ubuf, | ||
1557 | size_t count, loff_t *ppos) | ||
1558 | { | ||
1559 | char buf[32]; | ||
1560 | struct ath10k *ar = file->private_data; | ||
1561 | int len = 0; | ||
1562 | |||
1563 | mutex_lock(&ar->conf_mutex); | ||
1564 | len = scnprintf(buf, sizeof(buf) - len, "%08x\n", | ||
1565 | ar->debug.pktlog_filter); | ||
1566 | mutex_unlock(&ar->conf_mutex); | ||
1567 | |||
1568 | return simple_read_from_buffer(ubuf, count, ppos, buf, len); | ||
1569 | } | ||
1570 | |||
1571 | static const struct file_operations fops_pktlog_filter = { | ||
1572 | .read = ath10k_read_pktlog_filter, | ||
1573 | .write = ath10k_write_pktlog_filter, | ||
1574 | .open = simple_open | ||
1575 | }; | ||
1576 | |||
1157 | int ath10k_debug_create(struct ath10k *ar) | 1577 | int ath10k_debug_create(struct ath10k *ar) |
1158 | { | 1578 | { |
1159 | ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data)); | 1579 | ar->debug.fw_crash_data = vzalloc(sizeof(*ar->debug.fw_crash_data)); |
1160 | if (!ar->debug.fw_crash_data) | 1580 | if (!ar->debug.fw_crash_data) |
1161 | return -ENOMEM; | 1581 | return -ENOMEM; |
1162 | 1582 | ||
1583 | INIT_LIST_HEAD(&ar->debug.fw_stats.pdevs); | ||
1584 | INIT_LIST_HEAD(&ar->debug.fw_stats.peers); | ||
1585 | |||
1163 | return 0; | 1586 | return 0; |
1164 | } | 1587 | } |
1165 | 1588 | ||
@@ -1167,6 +1590,8 @@ void ath10k_debug_destroy(struct ath10k *ar) | |||
1167 | { | 1590 | { |
1168 | vfree(ar->debug.fw_crash_data); | 1591 | vfree(ar->debug.fw_crash_data); |
1169 | ar->debug.fw_crash_data = NULL; | 1592 | ar->debug.fw_crash_data = NULL; |
1593 | |||
1594 | ath10k_debug_fw_stats_reset(ar); | ||
1170 | } | 1595 | } |
1171 | 1596 | ||
1172 | int ath10k_debug_register(struct ath10k *ar) | 1597 | int ath10k_debug_register(struct ath10k *ar) |
@@ -1183,11 +1608,14 @@ int ath10k_debug_register(struct ath10k *ar) | |||
1183 | INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork, | 1608 | INIT_DELAYED_WORK(&ar->debug.htt_stats_dwork, |
1184 | ath10k_debug_htt_stats_dwork); | 1609 | ath10k_debug_htt_stats_dwork); |
1185 | 1610 | ||
1186 | init_completion(&ar->debug.event_stats_compl); | 1611 | init_completion(&ar->debug.fw_stats_complete); |
1187 | 1612 | ||
1188 | debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar, | 1613 | debugfs_create_file("fw_stats", S_IRUSR, ar->debug.debugfs_phy, ar, |
1189 | &fops_fw_stats); | 1614 | &fops_fw_stats); |
1190 | 1615 | ||
1616 | debugfs_create_file("fw_reset_stats", S_IRUSR, ar->debug.debugfs_phy, | ||
1617 | ar, &fops_fw_reset_stats); | ||
1618 | |||
1191 | debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar, | 1619 | debugfs_create_file("wmi_services", S_IRUSR, ar->debug.debugfs_phy, ar, |
1192 | &fops_wmi_services); | 1620 | &fops_wmi_services); |
1193 | 1621 | ||
@@ -1210,6 +1638,9 @@ int ath10k_debug_register(struct ath10k *ar) | |||
1210 | debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy, | 1638 | debugfs_create_file("fw_dbglog", S_IRUSR, ar->debug.debugfs_phy, |
1211 | ar, &fops_fw_dbglog); | 1639 | ar, &fops_fw_dbglog); |
1212 | 1640 | ||
1641 | debugfs_create_file("cal_data", S_IRUSR, ar->debug.debugfs_phy, | ||
1642 | ar, &fops_cal_data); | ||
1643 | |||
1213 | if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) { | 1644 | if (config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) { |
1214 | debugfs_create_file("dfs_simulate_radar", S_IWUSR, | 1645 | debugfs_create_file("dfs_simulate_radar", S_IWUSR, |
1215 | ar->debug.debugfs_phy, ar, | 1646 | ar->debug.debugfs_phy, ar, |
@@ -1224,6 +1655,9 @@ int ath10k_debug_register(struct ath10k *ar) | |||
1224 | &fops_dfs_stats); | 1655 | &fops_dfs_stats); |
1225 | } | 1656 | } |
1226 | 1657 | ||
1658 | debugfs_create_file("pktlog_filter", S_IRUGO | S_IWUSR, | ||
1659 | ar->debug.debugfs_phy, ar, &fops_pktlog_filter); | ||
1660 | |||
1227 | return 0; | 1661 | return 0; |
1228 | } | 1662 | } |
1229 | 1663 | ||
@@ -1260,11 +1694,26 @@ void ath10k_dbg_dump(struct ath10k *ar, | |||
1260 | const char *msg, const char *prefix, | 1694 | const char *msg, const char *prefix, |
1261 | const void *buf, size_t len) | 1695 | const void *buf, size_t len) |
1262 | { | 1696 | { |
1697 | char linebuf[256]; | ||
1698 | unsigned int linebuflen; | ||
1699 | const void *ptr; | ||
1700 | |||
1263 | if (ath10k_debug_mask & mask) { | 1701 | if (ath10k_debug_mask & mask) { |
1264 | if (msg) | 1702 | if (msg) |
1265 | ath10k_dbg(ar, mask, "%s\n", msg); | 1703 | ath10k_dbg(ar, mask, "%s\n", msg); |
1266 | 1704 | ||
1267 | print_hex_dump_bytes(prefix, DUMP_PREFIX_OFFSET, buf, len); | 1705 | for (ptr = buf; (ptr - buf) < len; ptr += 16) { |
1706 | linebuflen = 0; | ||
1707 | linebuflen += scnprintf(linebuf + linebuflen, | ||
1708 | sizeof(linebuf) - linebuflen, | ||
1709 | "%s%08x: ", | ||
1710 | (prefix ? prefix : ""), | ||
1711 | (unsigned int)(ptr - buf)); | ||
1712 | hex_dump_to_buffer(ptr, len - (ptr - buf), 16, 1, | ||
1713 | linebuf + linebuflen, | ||
1714 | sizeof(linebuf) - linebuflen, true); | ||
1715 | dev_printk(KERN_DEBUG, ar->dev, "%s\n", linebuf); | ||
1716 | } | ||
1268 | } | 1717 | } |
1269 | 1718 | ||
1270 | /* tracing code doesn't like null strings :/ */ | 1719 | /* 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..fbb3175d4d6e 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c | |||
@@ -291,6 +291,9 @@ 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 | trace_ath10k_htt_rx_pop_msdu(ar, msdu->data, msdu->len + | ||
295 | skb_tailroom(msdu)); | ||
296 | |||
294 | return msdu; | 297 | return msdu; |
295 | } | 298 | } |
296 | 299 | ||
@@ -316,6 +319,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, | |||
316 | int msdu_len, msdu_chaining = 0; | 319 | int msdu_len, msdu_chaining = 0; |
317 | struct sk_buff *msdu, *next; | 320 | struct sk_buff *msdu, *next; |
318 | struct htt_rx_desc *rx_desc; | 321 | struct htt_rx_desc *rx_desc; |
322 | u32 tsf; | ||
319 | 323 | ||
320 | lockdep_assert_held(&htt->rx_ring.lock); | 324 | lockdep_assert_held(&htt->rx_ring.lock); |
321 | 325 | ||
@@ -447,6 +451,9 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, | |||
447 | last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) & | 451 | last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) & |
448 | RX_MSDU_END_INFO0_LAST_MSDU; | 452 | RX_MSDU_END_INFO0_LAST_MSDU; |
449 | 453 | ||
454 | tsf = __le32_to_cpu(rx_desc->ppdu_end.tsf_timestamp); | ||
455 | trace_ath10k_htt_rx_desc(ar, tsf, &rx_desc->attention, | ||
456 | sizeof(*rx_desc) - sizeof(u32)); | ||
450 | if (last_msdu) { | 457 | if (last_msdu) { |
451 | msdu->next = NULL; | 458 | msdu->next = NULL; |
452 | break; | 459 | break; |
@@ -1674,6 +1681,15 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
1674 | case HTT_T2H_MSG_TYPE_RX_DELBA: | 1681 | case HTT_T2H_MSG_TYPE_RX_DELBA: |
1675 | ath10k_htt_rx_delba(ar, resp); | 1682 | ath10k_htt_rx_delba(ar, resp); |
1676 | break; | 1683 | break; |
1684 | case HTT_T2H_MSG_TYPE_PKTLOG: { | ||
1685 | struct ath10k_pktlog_hdr *hdr = | ||
1686 | (struct ath10k_pktlog_hdr *)resp->pktlog_msg.payload; | ||
1687 | |||
1688 | trace_ath10k_htt_pktlog(ar, resp->pktlog_msg.payload, | ||
1689 | sizeof(*hdr) + | ||
1690 | __le16_to_cpu(hdr->size)); | ||
1691 | break; | ||
1692 | } | ||
1677 | case HTT_T2H_MSG_TYPE_RX_FLUSH: { | 1693 | case HTT_T2H_MSG_TYPE_RX_FLUSH: { |
1678 | /* Ignore this event because mac80211 takes care of Rx | 1694 | /* Ignore this event because mac80211 takes care of Rx |
1679 | * aggregation reordering. | 1695 | * aggregation reordering. |
@@ -1681,8 +1697,8 @@ void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb) | |||
1681 | break; | 1697 | break; |
1682 | } | 1698 | } |
1683 | default: | 1699 | default: |
1684 | ath10k_dbg(ar, ATH10K_DBG_HTT, "htt event (%d) not handled\n", | 1700 | ath10k_warn(ar, "htt event (%d) not handled\n", |
1685 | resp->hdr.msg_type); | 1701 | resp->hdr.msg_type); |
1686 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ", | 1702 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt event: ", |
1687 | skb->data, skb->len); | 1703 | skb->data, skb->len); |
1688 | break; | 1704 | break; |
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index bd87a35201d8..b0df470250a2 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c | |||
@@ -557,12 +557,14 @@ 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); | 557 | 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); | 558 | skb_cb->htt.txbuf->cmd_tx.peerid = __cpu_to_le32(HTT_INVALID_PEERID); |
559 | 559 | ||
560 | trace_ath10k_htt_tx(ar, msdu_id, msdu->len, vdev_id, tid); | ||
560 | ath10k_dbg(ar, ATH10K_DBG_HTT, | 561 | 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", | 562 | "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, | 563 | flags0, flags1, msdu->len, msdu_id, frags_paddr, |
563 | (u32)skb_cb->paddr, vdev_id, tid); | 564 | (u32)skb_cb->paddr, vdev_id, tid); |
564 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ", | 565 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ", |
565 | msdu->data, msdu->len); | 566 | msdu->data, msdu->len); |
567 | trace_ath10k_htt_tx_msdu(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..61b006f42f95 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -479,6 +479,40 @@ 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; |
@@ -590,9 +624,9 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar) | |||
590 | return -ENOMEM; | 624 | return -ENOMEM; |
591 | } | 625 | } |
592 | 626 | ||
593 | bit = ffs(ar->free_vdev_map); | 627 | bit = __ffs64(ar->free_vdev_map); |
594 | 628 | ||
595 | ar->monitor_vdev_id = bit - 1; | 629 | ar->monitor_vdev_id = bit; |
596 | 630 | ||
597 | ret = ath10k_wmi_vdev_create(ar, ar->monitor_vdev_id, | 631 | ret = ath10k_wmi_vdev_create(ar, ar->monitor_vdev_id, |
598 | WMI_VDEV_TYPE_MONITOR, | 632 | WMI_VDEV_TYPE_MONITOR, |
@@ -603,7 +637,7 @@ static int ath10k_monitor_vdev_create(struct ath10k *ar) | |||
603 | return ret; | 637 | return ret; |
604 | } | 638 | } |
605 | 639 | ||
606 | ar->free_vdev_map &= ~(1 << ar->monitor_vdev_id); | 640 | ar->free_vdev_map &= ~(1LL << ar->monitor_vdev_id); |
607 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d created\n", | 641 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d created\n", |
608 | ar->monitor_vdev_id); | 642 | ar->monitor_vdev_id); |
609 | 643 | ||
@@ -623,7 +657,7 @@ static int ath10k_monitor_vdev_delete(struct ath10k *ar) | |||
623 | return ret; | 657 | return ret; |
624 | } | 658 | } |
625 | 659 | ||
626 | ar->free_vdev_map |= 1 << ar->monitor_vdev_id; | 660 | ar->free_vdev_map |= 1LL << ar->monitor_vdev_id; |
627 | 661 | ||
628 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d deleted\n", | 662 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac monitor vdev %d deleted\n", |
629 | ar->monitor_vdev_id); | 663 | ar->monitor_vdev_id); |
@@ -909,15 +943,7 @@ static void ath10k_control_beaconing(struct ath10k_vif *arvif, | |||
909 | arvif->is_up = false; | 943 | arvif->is_up = false; |
910 | 944 | ||
911 | spin_lock_bh(&arvif->ar->data_lock); | 945 | spin_lock_bh(&arvif->ar->data_lock); |
912 | if (arvif->beacon) { | 946 | 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); | 947 | spin_unlock_bh(&arvif->ar->data_lock); |
922 | 948 | ||
923 | return; | 949 | return; |
@@ -966,14 +992,6 @@ static void ath10k_control_ibss(struct ath10k_vif *arvif, | |||
966 | if (is_zero_ether_addr(arvif->bssid)) | 992 | if (is_zero_ether_addr(arvif->bssid)) |
967 | return; | 993 | return; |
968 | 994 | ||
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); | 995 | memset(arvif->bssid, 0, ETH_ALEN); |
978 | 996 | ||
979 | return; | 997 | return; |
@@ -1042,51 +1060,45 @@ static int ath10k_mac_vif_setup_ps(struct ath10k_vif *arvif) | |||
1042 | /* Station management */ | 1060 | /* Station management */ |
1043 | /**********************/ | 1061 | /**********************/ |
1044 | 1062 | ||
1063 | static u32 ath10k_peer_assoc_h_listen_intval(struct ath10k *ar, | ||
1064 | struct ieee80211_vif *vif) | ||
1065 | { | ||
1066 | /* Some firmware revisions have unstable STA powersave when listen | ||
1067 | * interval is set too high (e.g. 5). The symptoms are firmware doesn't | ||
1068 | * generate NullFunc frames properly even if buffered frames have been | ||
1069 | * indicated in Beacon TIM. Firmware would seldom wake up to pull | ||
1070 | * buffered frames. Often pinging the device from AP would simply fail. | ||
1071 | * | ||
1072 | * As a workaround set it to 1. | ||
1073 | */ | ||
1074 | if (vif->type == NL80211_IFTYPE_STATION) | ||
1075 | return 1; | ||
1076 | |||
1077 | return ar->hw->conf.listen_interval; | ||
1078 | } | ||
1079 | |||
1045 | static void ath10k_peer_assoc_h_basic(struct ath10k *ar, | 1080 | static void ath10k_peer_assoc_h_basic(struct ath10k *ar, |
1046 | struct ath10k_vif *arvif, | 1081 | struct ieee80211_vif *vif, |
1047 | struct ieee80211_sta *sta, | 1082 | struct ieee80211_sta *sta, |
1048 | struct ieee80211_bss_conf *bss_conf, | ||
1049 | struct wmi_peer_assoc_complete_arg *arg) | 1083 | struct wmi_peer_assoc_complete_arg *arg) |
1050 | { | 1084 | { |
1085 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
1086 | |||
1051 | lockdep_assert_held(&ar->conf_mutex); | 1087 | lockdep_assert_held(&ar->conf_mutex); |
1052 | 1088 | ||
1053 | ether_addr_copy(arg->addr, sta->addr); | 1089 | ether_addr_copy(arg->addr, sta->addr); |
1054 | arg->vdev_id = arvif->vdev_id; | 1090 | arg->vdev_id = arvif->vdev_id; |
1055 | arg->peer_aid = sta->aid; | 1091 | arg->peer_aid = sta->aid; |
1056 | arg->peer_flags |= WMI_PEER_AUTH; | 1092 | arg->peer_flags |= WMI_PEER_AUTH; |
1057 | 1093 | 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; | 1094 | arg->peer_num_spatial_streams = 1; |
1077 | 1095 | 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 | } | 1096 | } |
1084 | 1097 | ||
1085 | static void ath10k_peer_assoc_h_crypto(struct ath10k *ar, | 1098 | static void ath10k_peer_assoc_h_crypto(struct ath10k *ar, |
1086 | struct ath10k_vif *arvif, | 1099 | struct ieee80211_vif *vif, |
1087 | struct wmi_peer_assoc_complete_arg *arg) | 1100 | struct wmi_peer_assoc_complete_arg *arg) |
1088 | { | 1101 | { |
1089 | struct ieee80211_vif *vif = arvif->vif; | ||
1090 | struct ieee80211_bss_conf *info = &vif->bss_conf; | 1102 | struct ieee80211_bss_conf *info = &vif->bss_conf; |
1091 | struct cfg80211_bss *bss; | 1103 | struct cfg80211_bss *bss; |
1092 | const u8 *rsnie = NULL; | 1104 | const u8 *rsnie = NULL; |
@@ -1343,11 +1355,12 @@ static void ath10k_peer_assoc_h_vht(struct ath10k *ar, | |||
1343 | } | 1355 | } |
1344 | 1356 | ||
1345 | static void ath10k_peer_assoc_h_qos(struct ath10k *ar, | 1357 | static void ath10k_peer_assoc_h_qos(struct ath10k *ar, |
1346 | struct ath10k_vif *arvif, | 1358 | struct ieee80211_vif *vif, |
1347 | struct ieee80211_sta *sta, | 1359 | struct ieee80211_sta *sta, |
1348 | struct ieee80211_bss_conf *bss_conf, | ||
1349 | struct wmi_peer_assoc_complete_arg *arg) | 1360 | struct wmi_peer_assoc_complete_arg *arg) |
1350 | { | 1361 | { |
1362 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
1363 | |||
1351 | switch (arvif->vdev_type) { | 1364 | switch (arvif->vdev_type) { |
1352 | case WMI_VDEV_TYPE_AP: | 1365 | case WMI_VDEV_TYPE_AP: |
1353 | if (sta->wme) | 1366 | if (sta->wme) |
@@ -1359,7 +1372,7 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar, | |||
1359 | } | 1372 | } |
1360 | break; | 1373 | break; |
1361 | case WMI_VDEV_TYPE_STA: | 1374 | case WMI_VDEV_TYPE_STA: |
1362 | if (bss_conf->qos) | 1375 | if (vif->bss_conf.qos) |
1363 | arg->peer_flags |= WMI_PEER_QOS; | 1376 | arg->peer_flags |= WMI_PEER_QOS; |
1364 | break; | 1377 | break; |
1365 | default: | 1378 | default: |
@@ -1368,7 +1381,7 @@ static void ath10k_peer_assoc_h_qos(struct ath10k *ar, | |||
1368 | } | 1381 | } |
1369 | 1382 | ||
1370 | static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, | 1383 | static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, |
1371 | struct ath10k_vif *arvif, | 1384 | struct ieee80211_vif *vif, |
1372 | struct ieee80211_sta *sta, | 1385 | struct ieee80211_sta *sta, |
1373 | struct wmi_peer_assoc_complete_arg *arg) | 1386 | struct wmi_peer_assoc_complete_arg *arg) |
1374 | { | 1387 | { |
@@ -1419,22 +1432,21 @@ static void ath10k_peer_assoc_h_phymode(struct ath10k *ar, | |||
1419 | } | 1432 | } |
1420 | 1433 | ||
1421 | static int ath10k_peer_assoc_prepare(struct ath10k *ar, | 1434 | static int ath10k_peer_assoc_prepare(struct ath10k *ar, |
1422 | struct ath10k_vif *arvif, | 1435 | struct ieee80211_vif *vif, |
1423 | struct ieee80211_sta *sta, | 1436 | struct ieee80211_sta *sta, |
1424 | struct ieee80211_bss_conf *bss_conf, | ||
1425 | struct wmi_peer_assoc_complete_arg *arg) | 1437 | struct wmi_peer_assoc_complete_arg *arg) |
1426 | { | 1438 | { |
1427 | lockdep_assert_held(&ar->conf_mutex); | 1439 | lockdep_assert_held(&ar->conf_mutex); |
1428 | 1440 | ||
1429 | memset(arg, 0, sizeof(*arg)); | 1441 | memset(arg, 0, sizeof(*arg)); |
1430 | 1442 | ||
1431 | ath10k_peer_assoc_h_basic(ar, arvif, sta, bss_conf, arg); | 1443 | ath10k_peer_assoc_h_basic(ar, vif, sta, arg); |
1432 | ath10k_peer_assoc_h_crypto(ar, arvif, arg); | 1444 | ath10k_peer_assoc_h_crypto(ar, vif, arg); |
1433 | ath10k_peer_assoc_h_rates(ar, sta, arg); | 1445 | ath10k_peer_assoc_h_rates(ar, sta, arg); |
1434 | ath10k_peer_assoc_h_ht(ar, sta, arg); | 1446 | ath10k_peer_assoc_h_ht(ar, sta, arg); |
1435 | ath10k_peer_assoc_h_vht(ar, sta, arg); | 1447 | ath10k_peer_assoc_h_vht(ar, sta, arg); |
1436 | ath10k_peer_assoc_h_qos(ar, arvif, sta, bss_conf, arg); | 1448 | ath10k_peer_assoc_h_qos(ar, vif, sta, arg); |
1437 | ath10k_peer_assoc_h_phymode(ar, arvif, sta, arg); | 1449 | ath10k_peer_assoc_h_phymode(ar, vif, sta, arg); |
1438 | 1450 | ||
1439 | return 0; | 1451 | return 0; |
1440 | } | 1452 | } |
@@ -1480,6 +1492,9 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, | |||
1480 | 1492 | ||
1481 | lockdep_assert_held(&ar->conf_mutex); | 1493 | lockdep_assert_held(&ar->conf_mutex); |
1482 | 1494 | ||
1495 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i assoc bssid %pM aid %d\n", | ||
1496 | arvif->vdev_id, arvif->bssid, arvif->aid); | ||
1497 | |||
1483 | rcu_read_lock(); | 1498 | rcu_read_lock(); |
1484 | 1499 | ||
1485 | ap_sta = ieee80211_find_sta(vif, bss_conf->bssid); | 1500 | ap_sta = ieee80211_find_sta(vif, bss_conf->bssid); |
@@ -1494,8 +1509,7 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, | |||
1494 | * before calling ath10k_setup_peer_smps() which might sleep. */ | 1509 | * before calling ath10k_setup_peer_smps() which might sleep. */ |
1495 | ht_cap = ap_sta->ht_cap; | 1510 | ht_cap = ap_sta->ht_cap; |
1496 | 1511 | ||
1497 | ret = ath10k_peer_assoc_prepare(ar, arvif, ap_sta, | 1512 | ret = ath10k_peer_assoc_prepare(ar, vif, ap_sta, &peer_arg); |
1498 | bss_conf, &peer_arg); | ||
1499 | if (ret) { | 1513 | if (ret) { |
1500 | ath10k_warn(ar, "failed to prepare peer assoc for %pM vdev %i: %d\n", | 1514 | ath10k_warn(ar, "failed to prepare peer assoc for %pM vdev %i: %d\n", |
1501 | bss_conf->bssid, arvif->vdev_id, ret); | 1515 | bss_conf->bssid, arvif->vdev_id, ret); |
@@ -1523,6 +1537,8 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, | |||
1523 | "mac vdev %d up (associated) bssid %pM aid %d\n", | 1537 | "mac vdev %d up (associated) bssid %pM aid %d\n", |
1524 | arvif->vdev_id, bss_conf->bssid, bss_conf->aid); | 1538 | arvif->vdev_id, bss_conf->bssid, bss_conf->aid); |
1525 | 1539 | ||
1540 | WARN_ON(arvif->is_up); | ||
1541 | |||
1526 | arvif->aid = bss_conf->aid; | 1542 | arvif->aid = bss_conf->aid; |
1527 | ether_addr_copy(arvif->bssid, bss_conf->bssid); | 1543 | ether_addr_copy(arvif->bssid, bss_conf->bssid); |
1528 | 1544 | ||
@@ -1536,9 +1552,6 @@ static void ath10k_bss_assoc(struct ieee80211_hw *hw, | |||
1536 | arvif->is_up = true; | 1552 | arvif->is_up = true; |
1537 | } | 1553 | } |
1538 | 1554 | ||
1539 | /* | ||
1540 | * FIXME: flush TIDs | ||
1541 | */ | ||
1542 | static void ath10k_bss_disassoc(struct ieee80211_hw *hw, | 1555 | static void ath10k_bss_disassoc(struct ieee80211_hw *hw, |
1543 | struct ieee80211_vif *vif) | 1556 | struct ieee80211_vif *vif) |
1544 | { | 1557 | { |
@@ -1548,45 +1561,30 @@ static void ath10k_bss_disassoc(struct ieee80211_hw *hw, | |||
1548 | 1561 | ||
1549 | lockdep_assert_held(&ar->conf_mutex); | 1562 | lockdep_assert_held(&ar->conf_mutex); |
1550 | 1563 | ||
1551 | /* | 1564 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %i disassoc bssid %pM\n", |
1552 | * For some reason, calling VDEV-DOWN before VDEV-STOP | 1565 | 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 | 1566 | ||
1560 | /* FIXME: check return value */ | ||
1561 | ret = ath10k_vdev_stop(arvif); | ||
1562 | |||
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); | 1567 | ret = ath10k_wmi_vdev_down(ar, arvif->vdev_id); |
1568 | if (ret) | ||
1569 | ath10k_warn(ar, "faield to down vdev %i: %d\n", | ||
1570 | arvif->vdev_id, ret); | ||
1574 | 1571 | ||
1575 | arvif->def_wep_key_idx = 0; | 1572 | arvif->def_wep_key_idx = 0; |
1576 | |||
1577 | arvif->is_started = false; | ||
1578 | arvif->is_up = false; | 1573 | arvif->is_up = false; |
1579 | } | 1574 | } |
1580 | 1575 | ||
1581 | static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif, | 1576 | static int ath10k_station_assoc(struct ath10k *ar, |
1582 | struct ieee80211_sta *sta, bool reassoc) | 1577 | struct ieee80211_vif *vif, |
1578 | struct ieee80211_sta *sta, | ||
1579 | bool reassoc) | ||
1583 | { | 1580 | { |
1581 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
1584 | struct wmi_peer_assoc_complete_arg peer_arg; | 1582 | struct wmi_peer_assoc_complete_arg peer_arg; |
1585 | int ret = 0; | 1583 | int ret = 0; |
1586 | 1584 | ||
1587 | lockdep_assert_held(&ar->conf_mutex); | 1585 | lockdep_assert_held(&ar->conf_mutex); |
1588 | 1586 | ||
1589 | ret = ath10k_peer_assoc_prepare(ar, arvif, sta, NULL, &peer_arg); | 1587 | ret = ath10k_peer_assoc_prepare(ar, vif, sta, &peer_arg); |
1590 | if (ret) { | 1588 | if (ret) { |
1591 | ath10k_warn(ar, "failed to prepare WMI peer assoc for %pM vdev %i: %i\n", | 1589 | ath10k_warn(ar, "failed to prepare WMI peer assoc for %pM vdev %i: %i\n", |
1592 | sta->addr, arvif->vdev_id, ret); | 1590 | sta->addr, arvif->vdev_id, ret); |
@@ -1601,43 +1599,51 @@ static int ath10k_station_assoc(struct ath10k *ar, struct ath10k_vif *arvif, | |||
1601 | return ret; | 1599 | return ret; |
1602 | } | 1600 | } |
1603 | 1601 | ||
1604 | ret = ath10k_setup_peer_smps(ar, arvif, sta->addr, &sta->ht_cap); | 1602 | /* Re-assoc is run only to update supported rates for given station. It |
1605 | if (ret) { | 1603 | * doesn't make much sense to reconfigure the peer completely. |
1606 | ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n", | 1604 | */ |
1607 | arvif->vdev_id, ret); | 1605 | if (!reassoc) { |
1608 | return ret; | 1606 | ret = ath10k_setup_peer_smps(ar, arvif, sta->addr, |
1609 | } | 1607 | &sta->ht_cap); |
1610 | |||
1611 | if (!sta->wme && !reassoc) { | ||
1612 | arvif->num_legacy_stations++; | ||
1613 | ret = ath10k_recalc_rtscts_prot(arvif); | ||
1614 | if (ret) { | 1608 | if (ret) { |
1615 | ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n", | 1609 | ath10k_warn(ar, "failed to setup peer SMPS for vdev %d: %d\n", |
1616 | arvif->vdev_id, ret); | 1610 | arvif->vdev_id, ret); |
1617 | return ret; | 1611 | return ret; |
1618 | } | 1612 | } |
1619 | } | ||
1620 | 1613 | ||
1621 | ret = ath10k_install_peer_wep_keys(arvif, sta->addr); | 1614 | ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta); |
1622 | if (ret) { | 1615 | if (ret) { |
1623 | ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n", | 1616 | ath10k_warn(ar, "failed to set qos params for STA %pM for vdev %i: %d\n", |
1624 | arvif->vdev_id, ret); | 1617 | sta->addr, arvif->vdev_id, ret); |
1625 | return ret; | 1618 | return ret; |
1626 | } | 1619 | } |
1627 | 1620 | ||
1628 | ret = ath10k_peer_assoc_qos_ap(ar, arvif, sta); | 1621 | if (!sta->wme) { |
1629 | if (ret) { | 1622 | arvif->num_legacy_stations++; |
1630 | ath10k_warn(ar, "failed to set qos params for STA %pM for vdev %i: %d\n", | 1623 | ret = ath10k_recalc_rtscts_prot(arvif); |
1631 | sta->addr, arvif->vdev_id, ret); | 1624 | if (ret) { |
1632 | return ret; | 1625 | ath10k_warn(ar, "failed to recalculate rts/cts prot for vdev %d: %d\n", |
1626 | arvif->vdev_id, ret); | ||
1627 | return ret; | ||
1628 | } | ||
1629 | } | ||
1630 | |||
1631 | ret = ath10k_install_peer_wep_keys(arvif, sta->addr); | ||
1632 | if (ret) { | ||
1633 | ath10k_warn(ar, "failed to install peer wep keys for vdev %i: %d\n", | ||
1634 | arvif->vdev_id, ret); | ||
1635 | return ret; | ||
1636 | } | ||
1633 | } | 1637 | } |
1634 | 1638 | ||
1635 | return ret; | 1639 | return ret; |
1636 | } | 1640 | } |
1637 | 1641 | ||
1638 | static int ath10k_station_disassoc(struct ath10k *ar, struct ath10k_vif *arvif, | 1642 | static int ath10k_station_disassoc(struct ath10k *ar, |
1643 | struct ieee80211_vif *vif, | ||
1639 | struct ieee80211_sta *sta) | 1644 | struct ieee80211_sta *sta) |
1640 | { | 1645 | { |
1646 | struct ath10k_vif *arvif = ath10k_vif_to_arvif(vif); | ||
1641 | int ret = 0; | 1647 | int ret = 0; |
1642 | 1648 | ||
1643 | lockdep_assert_held(&ar->conf_mutex); | 1649 | lockdep_assert_held(&ar->conf_mutex); |
@@ -1729,6 +1735,7 @@ static int ath10k_update_channel_list(struct ath10k *ar) | |||
1729 | ch->passive = passive; | 1735 | ch->passive = passive; |
1730 | 1736 | ||
1731 | ch->freq = channel->center_freq; | 1737 | ch->freq = channel->center_freq; |
1738 | ch->band_center_freq1 = channel->center_freq; | ||
1732 | ch->min_power = 0; | 1739 | ch->min_power = 0; |
1733 | ch->max_power = channel->max_power * 2; | 1740 | ch->max_power = channel->max_power * 2; |
1734 | ch->max_reg_power = channel->max_reg_power * 2; | 1741 | ch->max_reg_power = channel->max_reg_power * 2; |
@@ -2376,16 +2383,8 @@ void ath10k_halt(struct ath10k *ar) | |||
2376 | ath10k_hif_power_down(ar); | 2383 | ath10k_hif_power_down(ar); |
2377 | 2384 | ||
2378 | spin_lock_bh(&ar->data_lock); | 2385 | spin_lock_bh(&ar->data_lock); |
2379 | list_for_each_entry(arvif, &ar->arvifs, list) { | 2386 | list_for_each_entry(arvif, &ar->arvifs, list) |
2380 | if (!arvif->beacon) | 2387 | 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); | 2388 | spin_unlock_bh(&ar->data_lock); |
2390 | } | 2389 | } |
2391 | 2390 | ||
@@ -2677,12 +2676,68 @@ static void ath10k_config_chan(struct ath10k *ar) | |||
2677 | ath10k_monitor_recalc(ar); | 2676 | ath10k_monitor_recalc(ar); |
2678 | } | 2677 | } |
2679 | 2678 | ||
2679 | static int ath10k_mac_txpower_setup(struct ath10k *ar, int txpower) | ||
2680 | { | ||
2681 | int ret; | ||
2682 | u32 param; | ||
2683 | |||
2684 | lockdep_assert_held(&ar->conf_mutex); | ||
2685 | |||
2686 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac txpower %d\n", txpower); | ||
2687 | |||
2688 | param = ar->wmi.pdev_param->txpower_limit2g; | ||
2689 | ret = ath10k_wmi_pdev_set_param(ar, param, txpower * 2); | ||
2690 | if (ret) { | ||
2691 | ath10k_warn(ar, "failed to set 2g txpower %d: %d\n", | ||
2692 | txpower, ret); | ||
2693 | return ret; | ||
2694 | } | ||
2695 | |||
2696 | param = ar->wmi.pdev_param->txpower_limit5g; | ||
2697 | ret = ath10k_wmi_pdev_set_param(ar, param, txpower * 2); | ||
2698 | if (ret) { | ||
2699 | ath10k_warn(ar, "failed to set 5g txpower %d: %d\n", | ||
2700 | txpower, ret); | ||
2701 | return ret; | ||
2702 | } | ||
2703 | |||
2704 | return 0; | ||
2705 | } | ||
2706 | |||
2707 | static int ath10k_mac_txpower_recalc(struct ath10k *ar) | ||
2708 | { | ||
2709 | struct ath10k_vif *arvif; | ||
2710 | int ret, txpower = -1; | ||
2711 | |||
2712 | lockdep_assert_held(&ar->conf_mutex); | ||
2713 | |||
2714 | list_for_each_entry(arvif, &ar->arvifs, list) { | ||
2715 | WARN_ON(arvif->txpower < 0); | ||
2716 | |||
2717 | if (txpower == -1) | ||
2718 | txpower = arvif->txpower; | ||
2719 | else | ||
2720 | txpower = min(txpower, arvif->txpower); | ||
2721 | } | ||
2722 | |||
2723 | if (WARN_ON(txpower == -1)) | ||
2724 | return -EINVAL; | ||
2725 | |||
2726 | ret = ath10k_mac_txpower_setup(ar, txpower); | ||
2727 | if (ret) { | ||
2728 | ath10k_warn(ar, "failed to setup tx power %d: %d\n", | ||
2729 | txpower, ret); | ||
2730 | return ret; | ||
2731 | } | ||
2732 | |||
2733 | return 0; | ||
2734 | } | ||
2735 | |||
2680 | static int ath10k_config(struct ieee80211_hw *hw, u32 changed) | 2736 | static int ath10k_config(struct ieee80211_hw *hw, u32 changed) |
2681 | { | 2737 | { |
2682 | struct ath10k *ar = hw->priv; | 2738 | struct ath10k *ar = hw->priv; |
2683 | struct ieee80211_conf *conf = &hw->conf; | 2739 | struct ieee80211_conf *conf = &hw->conf; |
2684 | int ret = 0; | 2740 | int ret = 0; |
2685 | u32 param; | ||
2686 | 2741 | ||
2687 | mutex_lock(&ar->conf_mutex); | 2742 | mutex_lock(&ar->conf_mutex); |
2688 | 2743 | ||
@@ -2706,25 +2761,6 @@ static int ath10k_config(struct ieee80211_hw *hw, u32 changed) | |||
2706 | } | 2761 | } |
2707 | } | 2762 | } |
2708 | 2763 | ||
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) | 2764 | if (changed & IEEE80211_CONF_CHANGE_PS) |
2729 | ath10k_config_ps(ar); | 2765 | ath10k_config_ps(ar); |
2730 | 2766 | ||
@@ -2772,9 +2808,12 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2772 | ret = -EBUSY; | 2808 | ret = -EBUSY; |
2773 | goto err; | 2809 | goto err; |
2774 | } | 2810 | } |
2775 | bit = ffs(ar->free_vdev_map); | 2811 | bit = __ffs64(ar->free_vdev_map); |
2812 | |||
2813 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac create vdev %i map %llx\n", | ||
2814 | bit, ar->free_vdev_map); | ||
2776 | 2815 | ||
2777 | arvif->vdev_id = bit - 1; | 2816 | arvif->vdev_id = bit; |
2778 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; | 2817 | arvif->vdev_subtype = WMI_VDEV_SUBTYPE_NONE; |
2779 | 2818 | ||
2780 | if (ar->p2p) | 2819 | if (ar->p2p) |
@@ -2804,8 +2843,39 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2804 | break; | 2843 | break; |
2805 | } | 2844 | } |
2806 | 2845 | ||
2807 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d\n", | 2846 | /* Some firmware revisions don't wait for beacon tx completion before |
2808 | arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype); | 2847 | * sending another SWBA event. This could lead to hardware using old |
2848 | * (freed) beacon data in some cases, e.g. tx credit starvation | ||
2849 | * combined with missed TBTT. This is very very rare. | ||
2850 | * | ||
2851 | * On non-IOMMU-enabled hosts this could be a possible security issue | ||
2852 | * because hw could beacon some random data on the air. On | ||
2853 | * IOMMU-enabled hosts DMAR faults would occur in most cases and target | ||
2854 | * device would crash. | ||
2855 | * | ||
2856 | * Since there are no beacon tx completions (implicit nor explicit) | ||
2857 | * propagated to host the only workaround for this is to allocate a | ||
2858 | * DMA-coherent buffer for a lifetime of a vif and use it for all | ||
2859 | * beacon tx commands. Worst case for this approach is some beacons may | ||
2860 | * become corrupted, e.g. have garbled IEs or out-of-date TIM bitmap. | ||
2861 | */ | ||
2862 | if (vif->type == NL80211_IFTYPE_ADHOC || | ||
2863 | vif->type == NL80211_IFTYPE_AP) { | ||
2864 | arvif->beacon_buf = dma_zalloc_coherent(ar->dev, | ||
2865 | IEEE80211_MAX_FRAME_LEN, | ||
2866 | &arvif->beacon_paddr, | ||
2867 | GFP_ATOMIC); | ||
2868 | if (!arvif->beacon_buf) { | ||
2869 | ret = -ENOMEM; | ||
2870 | ath10k_warn(ar, "failed to allocate beacon buffer: %d\n", | ||
2871 | ret); | ||
2872 | goto err; | ||
2873 | } | ||
2874 | } | ||
2875 | |||
2876 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev create %d (add interface) type %d subtype %d bcnmode %s\n", | ||
2877 | arvif->vdev_id, arvif->vdev_type, arvif->vdev_subtype, | ||
2878 | arvif->beacon_buf ? "single-buf" : "per-skb"); | ||
2809 | 2879 | ||
2810 | ret = ath10k_wmi_vdev_create(ar, arvif->vdev_id, arvif->vdev_type, | 2880 | ret = ath10k_wmi_vdev_create(ar, arvif->vdev_id, arvif->vdev_type, |
2811 | arvif->vdev_subtype, vif->addr); | 2881 | arvif->vdev_subtype, vif->addr); |
@@ -2815,7 +2885,7 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2815 | goto err; | 2885 | goto err; |
2816 | } | 2886 | } |
2817 | 2887 | ||
2818 | ar->free_vdev_map &= ~(1 << arvif->vdev_id); | 2888 | ar->free_vdev_map &= ~(1LL << arvif->vdev_id); |
2819 | list_add(&arvif->list, &ar->arvifs); | 2889 | list_add(&arvif->list, &ar->arvifs); |
2820 | 2890 | ||
2821 | vdev_param = ar->wmi.vdev_param->def_keyid; | 2891 | vdev_param = ar->wmi.vdev_param->def_keyid; |
@@ -2899,6 +2969,13 @@ static int ath10k_add_interface(struct ieee80211_hw *hw, | |||
2899 | goto err_peer_delete; | 2969 | goto err_peer_delete; |
2900 | } | 2970 | } |
2901 | 2971 | ||
2972 | arvif->txpower = vif->bss_conf.txpower; | ||
2973 | ret = ath10k_mac_txpower_recalc(ar); | ||
2974 | if (ret) { | ||
2975 | ath10k_warn(ar, "failed to recalc tx power: %d\n", ret); | ||
2976 | goto err_peer_delete; | ||
2977 | } | ||
2978 | |||
2902 | mutex_unlock(&ar->conf_mutex); | 2979 | mutex_unlock(&ar->conf_mutex); |
2903 | return 0; | 2980 | return 0; |
2904 | 2981 | ||
@@ -2908,10 +2985,16 @@ err_peer_delete: | |||
2908 | 2985 | ||
2909 | err_vdev_delete: | 2986 | err_vdev_delete: |
2910 | ath10k_wmi_vdev_delete(ar, arvif->vdev_id); | 2987 | ath10k_wmi_vdev_delete(ar, arvif->vdev_id); |
2911 | ar->free_vdev_map |= 1 << arvif->vdev_id; | 2988 | ar->free_vdev_map |= 1LL << arvif->vdev_id; |
2912 | list_del(&arvif->list); | 2989 | list_del(&arvif->list); |
2913 | 2990 | ||
2914 | err: | 2991 | err: |
2992 | if (arvif->beacon_buf) { | ||
2993 | dma_free_coherent(ar->dev, IEEE80211_MAX_FRAME_LEN, | ||
2994 | arvif->beacon_buf, arvif->beacon_paddr); | ||
2995 | arvif->beacon_buf = NULL; | ||
2996 | } | ||
2997 | |||
2915 | mutex_unlock(&ar->conf_mutex); | 2998 | mutex_unlock(&ar->conf_mutex); |
2916 | 2999 | ||
2917 | return ret; | 3000 | return ret; |
@@ -2929,14 +3012,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, | |||
2929 | cancel_work_sync(&arvif->wep_key_work); | 3012 | cancel_work_sync(&arvif->wep_key_work); |
2930 | 3013 | ||
2931 | spin_lock_bh(&ar->data_lock); | 3014 | spin_lock_bh(&ar->data_lock); |
2932 | if (arvif->beacon) { | 3015 | 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); | 3016 | spin_unlock_bh(&ar->data_lock); |
2941 | 3017 | ||
2942 | ret = ath10k_spectral_vif_stop(arvif); | 3018 | ret = ath10k_spectral_vif_stop(arvif); |
@@ -2944,7 +3020,7 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw, | |||
2944 | ath10k_warn(ar, "failed to stop spectral for vdev %i: %d\n", | 3020 | ath10k_warn(ar, "failed to stop spectral for vdev %i: %d\n", |
2945 | arvif->vdev_id, ret); | 3021 | arvif->vdev_id, ret); |
2946 | 3022 | ||
2947 | ar->free_vdev_map |= 1 << arvif->vdev_id; | 3023 | ar->free_vdev_map |= 1LL << arvif->vdev_id; |
2948 | list_del(&arvif->list); | 3024 | list_del(&arvif->list); |
2949 | 3025 | ||
2950 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { | 3026 | if (arvif->vdev_type == WMI_VDEV_TYPE_AP) { |
@@ -3068,54 +3144,8 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
3068 | arvif->u.ap.hidden_ssid = info->hidden_ssid; | 3144 | arvif->u.ap.hidden_ssid = info->hidden_ssid; |
3069 | } | 3145 | } |
3070 | 3146 | ||
3071 | /* | 3147 | if (changed & BSS_CHANGED_BSSID && !is_zero_ether_addr(info->bssid)) |
3072 | * Firmware manages AP self-peer internally so make sure to not create | 3148 | 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 | 3149 | ||
3120 | if (changed & BSS_CHANGED_BEACON_ENABLED) | 3150 | if (changed & BSS_CHANGED_BEACON_ENABLED) |
3121 | ath10k_control_beaconing(arvif, info); | 3151 | ath10k_control_beaconing(arvif, info); |
@@ -3177,10 +3207,21 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw, | |||
3177 | ath10k_monitor_stop(ar); | 3207 | ath10k_monitor_stop(ar); |
3178 | ath10k_bss_assoc(hw, vif, info); | 3208 | ath10k_bss_assoc(hw, vif, info); |
3179 | ath10k_monitor_recalc(ar); | 3209 | ath10k_monitor_recalc(ar); |
3210 | } else { | ||
3211 | ath10k_bss_disassoc(hw, vif); | ||
3180 | } | 3212 | } |
3181 | } | 3213 | } |
3182 | 3214 | ||
3183 | exit: | 3215 | if (changed & BSS_CHANGED_TXPOWER) { |
3216 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev_id %i txpower %d\n", | ||
3217 | arvif->vdev_id, info->txpower); | ||
3218 | |||
3219 | arvif->txpower = info->txpower; | ||
3220 | ret = ath10k_mac_txpower_recalc(ar); | ||
3221 | if (ret) | ||
3222 | ath10k_warn(ar, "failed to recalc tx power: %d\n", ret); | ||
3223 | } | ||
3224 | |||
3184 | mutex_unlock(&ar->conf_mutex); | 3225 | mutex_unlock(&ar->conf_mutex); |
3185 | } | 3226 | } |
3186 | 3227 | ||
@@ -3453,7 +3494,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", | 3494 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac update sta %pM supp rates\n", |
3454 | sta->addr); | 3495 | sta->addr); |
3455 | 3496 | ||
3456 | err = ath10k_station_assoc(ar, arvif, sta, true); | 3497 | err = ath10k_station_assoc(ar, arvif->vif, sta, true); |
3457 | if (err) | 3498 | if (err) |
3458 | ath10k_warn(ar, "failed to reassociate station: %pM\n", | 3499 | ath10k_warn(ar, "failed to reassociate station: %pM\n", |
3459 | sta->addr); | 3500 | sta->addr); |
@@ -3489,8 +3530,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
3489 | mutex_lock(&ar->conf_mutex); | 3530 | mutex_lock(&ar->conf_mutex); |
3490 | 3531 | ||
3491 | if (old_state == IEEE80211_STA_NOTEXIST && | 3532 | if (old_state == IEEE80211_STA_NOTEXIST && |
3492 | new_state == IEEE80211_STA_NONE && | 3533 | new_state == IEEE80211_STA_NONE) { |
3493 | vif->type != NL80211_IFTYPE_STATION) { | ||
3494 | /* | 3534 | /* |
3495 | * New station addition. | 3535 | * New station addition. |
3496 | */ | 3536 | */ |
@@ -3514,6 +3554,21 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
3514 | if (ret) | 3554 | if (ret) |
3515 | ath10k_warn(ar, "failed to add peer %pM for vdev %d when adding a new sta: %i\n", | 3555 | 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); | 3556 | sta->addr, arvif->vdev_id, ret); |
3557 | |||
3558 | if (vif->type == NL80211_IFTYPE_STATION) { | ||
3559 | WARN_ON(arvif->is_started); | ||
3560 | |||
3561 | ret = ath10k_vdev_start(arvif); | ||
3562 | if (ret) { | ||
3563 | ath10k_warn(ar, "failed to start vdev %i: %d\n", | ||
3564 | arvif->vdev_id, ret); | ||
3565 | WARN_ON(ath10k_peer_delete(ar, arvif->vdev_id, | ||
3566 | sta->addr)); | ||
3567 | goto exit; | ||
3568 | } | ||
3569 | |||
3570 | arvif->is_started = true; | ||
3571 | } | ||
3517 | } else if ((old_state == IEEE80211_STA_NONE && | 3572 | } else if ((old_state == IEEE80211_STA_NONE && |
3518 | new_state == IEEE80211_STA_NOTEXIST)) { | 3573 | new_state == IEEE80211_STA_NOTEXIST)) { |
3519 | /* | 3574 | /* |
@@ -3522,13 +3577,23 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
3522 | ath10k_dbg(ar, ATH10K_DBG_MAC, | 3577 | ath10k_dbg(ar, ATH10K_DBG_MAC, |
3523 | "mac vdev %d peer delete %pM (sta gone)\n", | 3578 | "mac vdev %d peer delete %pM (sta gone)\n", |
3524 | arvif->vdev_id, sta->addr); | 3579 | arvif->vdev_id, sta->addr); |
3580 | |||
3581 | if (vif->type == NL80211_IFTYPE_STATION) { | ||
3582 | WARN_ON(!arvif->is_started); | ||
3583 | |||
3584 | ret = ath10k_vdev_stop(arvif); | ||
3585 | if (ret) | ||
3586 | ath10k_warn(ar, "failed to stop vdev %i: %d\n", | ||
3587 | arvif->vdev_id, ret); | ||
3588 | |||
3589 | arvif->is_started = false; | ||
3590 | } | ||
3591 | |||
3525 | ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr); | 3592 | ret = ath10k_peer_delete(ar, arvif->vdev_id, sta->addr); |
3526 | if (ret) | 3593 | if (ret) |
3527 | ath10k_warn(ar, "failed to delete peer %pM for vdev %d: %i\n", | 3594 | ath10k_warn(ar, "failed to delete peer %pM for vdev %d: %i\n", |
3528 | sta->addr, arvif->vdev_id, ret); | 3595 | sta->addr, arvif->vdev_id, ret); |
3529 | 3596 | ||
3530 | if (vif->type == NL80211_IFTYPE_STATION) | ||
3531 | ath10k_bss_disassoc(hw, vif); | ||
3532 | } else if (old_state == IEEE80211_STA_AUTH && | 3597 | } else if (old_state == IEEE80211_STA_AUTH && |
3533 | new_state == IEEE80211_STA_ASSOC && | 3598 | new_state == IEEE80211_STA_ASSOC && |
3534 | (vif->type == NL80211_IFTYPE_AP || | 3599 | (vif->type == NL80211_IFTYPE_AP || |
@@ -3539,7 +3604,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
3539 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM associated\n", | 3604 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM associated\n", |
3540 | sta->addr); | 3605 | sta->addr); |
3541 | 3606 | ||
3542 | ret = ath10k_station_assoc(ar, arvif, sta, false); | 3607 | ret = ath10k_station_assoc(ar, vif, sta, false); |
3543 | if (ret) | 3608 | if (ret) |
3544 | ath10k_warn(ar, "failed to associate station %pM for vdev %i: %i\n", | 3609 | ath10k_warn(ar, "failed to associate station %pM for vdev %i: %i\n", |
3545 | sta->addr, arvif->vdev_id, ret); | 3610 | sta->addr, arvif->vdev_id, ret); |
@@ -3553,7 +3618,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, | |||
3553 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM disassociated\n", | 3618 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac sta %pM disassociated\n", |
3554 | sta->addr); | 3619 | sta->addr); |
3555 | 3620 | ||
3556 | ret = ath10k_station_disassoc(ar, arvif, sta); | 3621 | ret = ath10k_station_disassoc(ar, vif, sta); |
3557 | if (ret) | 3622 | if (ret) |
3558 | ath10k_warn(ar, "failed to disassociate station: %pM vdev %i: %i\n", | 3623 | ath10k_warn(ar, "failed to disassociate station: %pM vdev %i: %i\n", |
3559 | sta->addr, arvif->vdev_id, ret); | 3624 | sta->addr, arvif->vdev_id, ret); |
@@ -3929,10 +3994,14 @@ exit: | |||
3929 | } | 3994 | } |
3930 | #endif | 3995 | #endif |
3931 | 3996 | ||
3932 | static void ath10k_restart_complete(struct ieee80211_hw *hw) | 3997 | static void ath10k_reconfig_complete(struct ieee80211_hw *hw, |
3998 | enum ieee80211_reconfig_type reconfig_type) | ||
3933 | { | 3999 | { |
3934 | struct ath10k *ar = hw->priv; | 4000 | struct ath10k *ar = hw->priv; |
3935 | 4001 | ||
4002 | if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART) | ||
4003 | return; | ||
4004 | |||
3936 | mutex_lock(&ar->conf_mutex); | 4005 | mutex_lock(&ar->conf_mutex); |
3937 | 4006 | ||
3938 | /* If device failed to restart it will be in a different state, e.g. | 4007 | /* If device failed to restart it will be in a different state, e.g. |
@@ -4450,12 +4519,15 @@ static const struct ieee80211_ops ath10k_ops = { | |||
4450 | .tx_last_beacon = ath10k_tx_last_beacon, | 4519 | .tx_last_beacon = ath10k_tx_last_beacon, |
4451 | .set_antenna = ath10k_set_antenna, | 4520 | .set_antenna = ath10k_set_antenna, |
4452 | .get_antenna = ath10k_get_antenna, | 4521 | .get_antenna = ath10k_get_antenna, |
4453 | .restart_complete = ath10k_restart_complete, | 4522 | .reconfig_complete = ath10k_reconfig_complete, |
4454 | .get_survey = ath10k_get_survey, | 4523 | .get_survey = ath10k_get_survey, |
4455 | .set_bitrate_mask = ath10k_set_bitrate_mask, | 4524 | .set_bitrate_mask = ath10k_set_bitrate_mask, |
4456 | .sta_rc_update = ath10k_sta_rc_update, | 4525 | .sta_rc_update = ath10k_sta_rc_update, |
4457 | .get_tsf = ath10k_get_tsf, | 4526 | .get_tsf = ath10k_get_tsf, |
4458 | .ampdu_action = ath10k_ampdu_action, | 4527 | .ampdu_action = ath10k_ampdu_action, |
4528 | .get_et_sset_count = ath10k_debug_get_et_sset_count, | ||
4529 | .get_et_stats = ath10k_debug_get_et_stats, | ||
4530 | .get_et_strings = ath10k_debug_get_et_strings, | ||
4459 | 4531 | ||
4460 | CFG80211_TESTMODE_CMD(ath10k_tm_cmd) | 4532 | CFG80211_TESTMODE_CMD(ath10k_tm_cmd) |
4461 | 4533 | ||
@@ -4800,15 +4872,6 @@ int ath10k_mac_register(struct ath10k *ar) | |||
4800 | BIT(NL80211_IFTYPE_STATION) | | 4872 | BIT(NL80211_IFTYPE_STATION) | |
4801 | BIT(NL80211_IFTYPE_AP); | 4873 | BIT(NL80211_IFTYPE_AP); |
4802 | 4874 | ||
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; | 4875 | ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask; |
4813 | ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask; | 4876 | ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask; |
4814 | 4877 | ||
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index 6c80eeada3e2..965c51117499 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h | |||
@@ -39,6 +39,7 @@ 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); | ||
42 | 43 | ||
43 | static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) | 44 | static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) |
44 | { | 45 | { |
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 59e0ea83be50..4a4740b4bdc0 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; | ||
1128 | 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; | ||
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) |
@@ -1266,6 +1311,7 @@ static void ath10k_pci_hif_stop(struct ath10k *ar) | |||
1266 | ath10k_pci_warm_reset(ar); | 1311 | ath10k_pci_warm_reset(ar); |
1267 | 1312 | ||
1268 | ath10k_pci_irq_disable(ar); | 1313 | ath10k_pci_irq_disable(ar); |
1314 | ath10k_pci_irq_sync(ar); | ||
1269 | ath10k_pci_flush(ar); | 1315 | ath10k_pci_flush(ar); |
1270 | } | 1316 | } |
1271 | 1317 | ||
@@ -1569,23 +1615,40 @@ static int ath10k_pci_init_config(struct ath10k *ar) | |||
1569 | return 0; | 1615 | return 0; |
1570 | } | 1616 | } |
1571 | 1617 | ||
1572 | static int ath10k_pci_alloc_ce(struct ath10k *ar) | 1618 | static int ath10k_pci_alloc_pipes(struct ath10k *ar) |
1573 | { | 1619 | { |
1620 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | ||
1621 | struct ath10k_pci_pipe *pipe; | ||
1574 | int i, ret; | 1622 | int i, ret; |
1575 | 1623 | ||
1576 | for (i = 0; i < CE_COUNT; i++) { | 1624 | for (i = 0; i < CE_COUNT; i++) { |
1577 | ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i]); | 1625 | pipe = &ar_pci->pipe_info[i]; |
1626 | pipe->ce_hdl = &ar_pci->ce_states[i]; | ||
1627 | pipe->pipe_num = i; | ||
1628 | pipe->hif_ce_state = ar; | ||
1629 | |||
1630 | ret = ath10k_ce_alloc_pipe(ar, i, &host_ce_config_wlan[i], | ||
1631 | ath10k_pci_ce_send_done, | ||
1632 | ath10k_pci_ce_recv_data); | ||
1578 | if (ret) { | 1633 | if (ret) { |
1579 | ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n", | 1634 | ath10k_err(ar, "failed to allocate copy engine pipe %d: %d\n", |
1580 | i, ret); | 1635 | i, ret); |
1581 | return ret; | 1636 | return ret; |
1582 | } | 1637 | } |
1638 | |||
1639 | /* Last CE is Diagnostic Window */ | ||
1640 | if (i == CE_COUNT - 1) { | ||
1641 | ar_pci->ce_diag = pipe->ce_hdl; | ||
1642 | continue; | ||
1643 | } | ||
1644 | |||
1645 | pipe->buf_sz = (size_t)(host_ce_config_wlan[i].src_sz_max); | ||
1583 | } | 1646 | } |
1584 | 1647 | ||
1585 | return 0; | 1648 | return 0; |
1586 | } | 1649 | } |
1587 | 1650 | ||
1588 | static void ath10k_pci_free_ce(struct ath10k *ar) | 1651 | static void ath10k_pci_free_pipes(struct ath10k *ar) |
1589 | { | 1652 | { |
1590 | int i; | 1653 | int i; |
1591 | 1654 | ||
@@ -1593,39 +1656,17 @@ static void ath10k_pci_free_ce(struct ath10k *ar) | |||
1593 | ath10k_ce_free_pipe(ar, i); | 1656 | ath10k_ce_free_pipe(ar, i); |
1594 | } | 1657 | } |
1595 | 1658 | ||
1596 | static int ath10k_pci_ce_init(struct ath10k *ar) | 1659 | static int ath10k_pci_init_pipes(struct ath10k *ar) |
1597 | { | 1660 | { |
1598 | struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); | 1661 | int i, ret; |
1599 | struct ath10k_pci_pipe *pipe_info; | ||
1600 | const struct ce_attr *attr; | ||
1601 | int pipe_num, ret; | ||
1602 | 1662 | ||
1603 | for (pipe_num = 0; pipe_num < CE_COUNT; pipe_num++) { | 1663 | for (i = 0; i < CE_COUNT; i++) { |
1604 | pipe_info = &ar_pci->pipe_info[pipe_num]; | 1664 | 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) { | 1665 | if (ret) { |
1614 | ath10k_err(ar, "failed to initialize copy engine pipe %d: %d\n", | 1666 | ath10k_err(ar, "failed to initialize copy engine pipe %d: %d\n", |
1615 | pipe_num, ret); | 1667 | i, ret); |
1616 | return ret; | 1668 | return ret; |
1617 | } | 1669 | } |
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 | } | 1670 | } |
1630 | 1671 | ||
1631 | return 0; | 1672 | return 0; |
@@ -1672,6 +1713,12 @@ static int ath10k_pci_warm_reset(struct ath10k *ar) | |||
1672 | 1713 | ||
1673 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n"); | 1714 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n"); |
1674 | 1715 | ||
1716 | spin_lock_bh(&ar->data_lock); | ||
1717 | |||
1718 | ar->stats.fw_warm_reset_counter++; | ||
1719 | |||
1720 | spin_unlock_bh(&ar->data_lock); | ||
1721 | |||
1675 | /* debug */ | 1722 | /* debug */ |
1676 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + | 1723 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + |
1677 | PCIE_INTR_CAUSE_ADDRESS); | 1724 | PCIE_INTR_CAUSE_ADDRESS); |
@@ -1773,7 +1820,7 @@ static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset) | |||
1773 | goto err; | 1820 | goto err; |
1774 | } | 1821 | } |
1775 | 1822 | ||
1776 | ret = ath10k_pci_ce_init(ar); | 1823 | ret = ath10k_pci_init_pipes(ar); |
1777 | if (ret) { | 1824 | if (ret) { |
1778 | ath10k_err(ar, "failed to initialize CE: %d\n", ret); | 1825 | ath10k_err(ar, "failed to initialize CE: %d\n", ret); |
1779 | goto err; | 1826 | goto err; |
@@ -1921,6 +1968,7 @@ static int ath10k_pci_hif_resume(struct ath10k *ar) | |||
1921 | 1968 | ||
1922 | static const struct ath10k_hif_ops ath10k_pci_hif_ops = { | 1969 | static const struct ath10k_hif_ops ath10k_pci_hif_ops = { |
1923 | .tx_sg = ath10k_pci_hif_tx_sg, | 1970 | .tx_sg = ath10k_pci_hif_tx_sg, |
1971 | .diag_read = ath10k_pci_hif_diag_read, | ||
1924 | .exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg, | 1972 | .exchange_bmi_msg = ath10k_pci_hif_exchange_bmi_msg, |
1925 | .start = ath10k_pci_hif_start, | 1973 | .start = ath10k_pci_hif_start, |
1926 | .stop = ath10k_pci_hif_stop, | 1974 | .stop = ath10k_pci_hif_stop, |
@@ -2250,14 +2298,14 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar) | |||
2250 | 2298 | ||
2251 | if (ar_pci->num_msi_intrs == 0) | 2299 | if (ar_pci->num_msi_intrs == 0) |
2252 | /* Fix potential race by repeating CORE_BASE writes */ | 2300 | /* Fix potential race by repeating CORE_BASE writes */ |
2253 | ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + | 2301 | ath10k_pci_enable_legacy_irq(ar); |
2254 | PCIE_INTR_ENABLE_ADDRESS, | ||
2255 | PCIE_INTR_FIRMWARE_MASK | | ||
2256 | PCIE_INTR_CE_MASK_ALL); | ||
2257 | 2302 | ||
2258 | mdelay(10); | 2303 | mdelay(10); |
2259 | } while (time_before(jiffies, timeout)); | 2304 | } while (time_before(jiffies, timeout)); |
2260 | 2305 | ||
2306 | ath10k_pci_disable_and_clear_legacy_irq(ar); | ||
2307 | ath10k_pci_irq_msi_fw_mask(ar); | ||
2308 | |||
2261 | if (val == 0xffffffff) { | 2309 | if (val == 0xffffffff) { |
2262 | ath10k_err(ar, "failed to read device register, device is gone\n"); | 2310 | ath10k_err(ar, "failed to read device register, device is gone\n"); |
2263 | return -EIO; | 2311 | return -EIO; |
@@ -2287,6 +2335,12 @@ static int ath10k_pci_cold_reset(struct ath10k *ar) | |||
2287 | 2335 | ||
2288 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n"); | 2336 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot cold reset\n"); |
2289 | 2337 | ||
2338 | spin_lock_bh(&ar->data_lock); | ||
2339 | |||
2340 | ar->stats.fw_cold_reset_counter++; | ||
2341 | |||
2342 | spin_unlock_bh(&ar->data_lock); | ||
2343 | |||
2290 | /* Put Target, including PCIe, into RESET. */ | 2344 | /* Put Target, including PCIe, into RESET. */ |
2291 | val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS); | 2345 | val = ath10k_pci_reg_read32(ar, SOC_GLOBAL_RESET_ADDRESS); |
2292 | val |= 1; | 2346 | val |= 1; |
@@ -2400,6 +2454,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
2400 | u32 chip_id; | 2454 | u32 chip_id; |
2401 | 2455 | ||
2402 | ar = ath10k_core_create(sizeof(*ar_pci), &pdev->dev, | 2456 | ar = ath10k_core_create(sizeof(*ar_pci), &pdev->dev, |
2457 | ATH10K_BUS_PCI, | ||
2403 | &ath10k_pci_hif_ops); | 2458 | &ath10k_pci_hif_ops); |
2404 | if (!ar) { | 2459 | if (!ar) { |
2405 | dev_err(&pdev->dev, "failed to allocate core\n"); | 2460 | dev_err(&pdev->dev, "failed to allocate core\n"); |
@@ -2435,7 +2490,7 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
2435 | goto err_sleep; | 2490 | goto err_sleep; |
2436 | } | 2491 | } |
2437 | 2492 | ||
2438 | ret = ath10k_pci_alloc_ce(ar); | 2493 | ret = ath10k_pci_alloc_pipes(ar); |
2439 | if (ret) { | 2494 | if (ret) { |
2440 | ath10k_err(ar, "failed to allocate copy engine pipes: %d\n", | 2495 | ath10k_err(ar, "failed to allocate copy engine pipes: %d\n", |
2441 | ret); | 2496 | ret); |
@@ -2443,25 +2498,12 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
2443 | } | 2498 | } |
2444 | 2499 | ||
2445 | ath10k_pci_ce_deinit(ar); | 2500 | ath10k_pci_ce_deinit(ar); |
2446 | 2501 | 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 | 2502 | ||
2461 | ret = ath10k_pci_init_irq(ar); | 2503 | ret = ath10k_pci_init_irq(ar); |
2462 | if (ret) { | 2504 | if (ret) { |
2463 | ath10k_err(ar, "failed to init irqs: %d\n", ret); | 2505 | ath10k_err(ar, "failed to init irqs: %d\n", ret); |
2464 | goto err_free_ce; | 2506 | goto err_free_pipes; |
2465 | } | 2507 | } |
2466 | 2508 | ||
2467 | ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n", | 2509 | ath10k_info(ar, "pci irq %s interrupts %d irq_mode %d reset_mode %d\n", |
@@ -2474,9 +2516,6 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
2474 | goto err_deinit_irq; | 2516 | goto err_deinit_irq; |
2475 | } | 2517 | } |
2476 | 2518 | ||
2477 | /* This shouldn't race as the device has been reset above. */ | ||
2478 | ath10k_pci_irq_disable(ar); | ||
2479 | |||
2480 | ret = ath10k_core_register(ar, chip_id); | 2519 | ret = ath10k_core_register(ar, chip_id); |
2481 | if (ret) { | 2520 | if (ret) { |
2482 | ath10k_err(ar, "failed to register driver core: %d\n", ret); | 2521 | ath10k_err(ar, "failed to register driver core: %d\n", ret); |
@@ -2492,8 +2531,8 @@ err_free_irq: | |||
2492 | err_deinit_irq: | 2531 | err_deinit_irq: |
2493 | ath10k_pci_deinit_irq(ar); | 2532 | ath10k_pci_deinit_irq(ar); |
2494 | 2533 | ||
2495 | err_free_ce: | 2534 | err_free_pipes: |
2496 | ath10k_pci_free_ce(ar); | 2535 | ath10k_pci_free_pipes(ar); |
2497 | 2536 | ||
2498 | err_sleep: | 2537 | err_sleep: |
2499 | ath10k_pci_sleep(ar); | 2538 | ath10k_pci_sleep(ar); |
@@ -2527,7 +2566,7 @@ static void ath10k_pci_remove(struct pci_dev *pdev) | |||
2527 | ath10k_pci_kill_tasklet(ar); | 2566 | ath10k_pci_kill_tasklet(ar); |
2528 | ath10k_pci_deinit_irq(ar); | 2567 | ath10k_pci_deinit_irq(ar); |
2529 | ath10k_pci_ce_deinit(ar); | 2568 | ath10k_pci_ce_deinit(ar); |
2530 | ath10k_pci_free_ce(ar); | 2569 | ath10k_pci_free_pipes(ar); |
2531 | ath10k_pci_sleep(ar); | 2570 | ath10k_pci_sleep(ar); |
2532 | ath10k_pci_release(ar); | 2571 | ath10k_pci_release(ar); |
2533 | ath10k_core_destroy(ar); | 2572 | ath10k_core_destroy(ar); |
@@ -2565,5 +2604,7 @@ module_exit(ath10k_pci_exit); | |||
2565 | MODULE_AUTHOR("Qualcomm Atheros"); | 2604 | MODULE_AUTHOR("Qualcomm Atheros"); |
2566 | MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices"); | 2605 | MODULE_DESCRIPTION("Driver support for Atheros QCA988X PCIe devices"); |
2567 | MODULE_LICENSE("Dual BSD/GPL"); | 2606 | MODULE_LICENSE("Dual BSD/GPL"); |
2568 | MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_3_FILE); | 2607 | MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" QCA988X_HW_2_0_FW_FILE); |
2608 | MODULE_FIRMWARE(QCA988X_HW_2_0_FW_DIR "/" ATH10K_FW_API2_FILE); | ||
2609 | 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); | 2610 | 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..9d34e7f6c455 100644 --- a/drivers/net/wireless/ath/ath10k/trace.h +++ b/drivers/net/wireless/ath/ath10k/trace.h | |||
@@ -254,6 +254,169 @@ TRACE_EVENT(ath10k_wmi_dbglog, | |||
254 | ) | 254 | ) |
255 | ); | 255 | ); |
256 | 256 | ||
257 | TRACE_EVENT(ath10k_htt_pktlog, | ||
258 | TP_PROTO(struct ath10k *ar, void *buf, u16 buf_len), | ||
259 | |||
260 | TP_ARGS(ar, buf, buf_len), | ||
261 | |||
262 | TP_STRUCT__entry( | ||
263 | __string(device, dev_name(ar->dev)) | ||
264 | __string(driver, dev_driver_string(ar->dev)) | ||
265 | __field(u16, buf_len) | ||
266 | __dynamic_array(u8, pktlog, buf_len) | ||
267 | ), | ||
268 | |||
269 | TP_fast_assign( | ||
270 | __assign_str(device, dev_name(ar->dev)); | ||
271 | __assign_str(driver, dev_driver_string(ar->dev)); | ||
272 | __entry->buf_len = buf_len; | ||
273 | memcpy(__get_dynamic_array(pktlog), buf, buf_len); | ||
274 | ), | ||
275 | |||
276 | TP_printk( | ||
277 | "%s %s size %hu", | ||
278 | __get_str(driver), | ||
279 | __get_str(device), | ||
280 | __entry->buf_len | ||
281 | ) | ||
282 | ); | ||
283 | |||
284 | TRACE_EVENT(ath10k_htt_rx_desc, | ||
285 | TP_PROTO(struct ath10k *ar, u32 tsf, void *rxdesc, u16 len), | ||
286 | |||
287 | TP_ARGS(ar, tsf, rxdesc, len), | ||
288 | |||
289 | TP_STRUCT__entry( | ||
290 | __string(device, dev_name(ar->dev)) | ||
291 | __string(driver, dev_driver_string(ar->dev)) | ||
292 | __field(u32, tsf) | ||
293 | __field(u16, len) | ||
294 | __dynamic_array(u8, rxdesc, len) | ||
295 | ), | ||
296 | |||
297 | TP_fast_assign( | ||
298 | __assign_str(device, dev_name(ar->dev)); | ||
299 | __assign_str(driver, dev_driver_string(ar->dev)); | ||
300 | __entry->tsf = tsf; | ||
301 | __entry->len = len; | ||
302 | memcpy(__get_dynamic_array(rxdesc), rxdesc, len); | ||
303 | ), | ||
304 | |||
305 | TP_printk( | ||
306 | "%s %s %u len %hu", | ||
307 | __get_str(driver), | ||
308 | __get_str(device), | ||
309 | __entry->tsf, | ||
310 | __entry->len | ||
311 | ) | ||
312 | ); | ||
313 | |||
314 | TRACE_EVENT(ath10k_htt_tx, | ||
315 | TP_PROTO(struct ath10k *ar, u16 msdu_id, u16 msdu_len, | ||
316 | u8 vdev_id, u8 tid), | ||
317 | |||
318 | TP_ARGS(ar, msdu_id, msdu_len, vdev_id, tid), | ||
319 | |||
320 | TP_STRUCT__entry( | ||
321 | __string(device, dev_name(ar->dev)) | ||
322 | __string(driver, dev_driver_string(ar->dev)) | ||
323 | __field(u16, msdu_id) | ||
324 | __field(u16, msdu_len) | ||
325 | __field(u8, vdev_id) | ||
326 | __field(u8, tid) | ||
327 | ), | ||
328 | |||
329 | TP_fast_assign( | ||
330 | __assign_str(device, dev_name(ar->dev)); | ||
331 | __assign_str(driver, dev_driver_string(ar->dev)); | ||
332 | __entry->msdu_id = msdu_id; | ||
333 | __entry->msdu_len = msdu_len; | ||
334 | __entry->vdev_id = vdev_id; | ||
335 | __entry->tid = tid; | ||
336 | ), | ||
337 | |||
338 | TP_printk( | ||
339 | "%s %s msdu_id %d msdu_len %d vdev_id %d tid %d", | ||
340 | __get_str(driver), | ||
341 | __get_str(device), | ||
342 | __entry->msdu_id, | ||
343 | __entry->msdu_len, | ||
344 | __entry->vdev_id, | ||
345 | __entry->tid | ||
346 | ) | ||
347 | ); | ||
348 | |||
349 | TRACE_EVENT(ath10k_txrx_tx_unref, | ||
350 | TP_PROTO(struct ath10k *ar, u16 msdu_id), | ||
351 | |||
352 | TP_ARGS(ar, msdu_id), | ||
353 | |||
354 | TP_STRUCT__entry( | ||
355 | __string(device, dev_name(ar->dev)) | ||
356 | __string(driver, dev_driver_string(ar->dev)) | ||
357 | __field(u16, msdu_id) | ||
358 | ), | ||
359 | |||
360 | TP_fast_assign( | ||
361 | __assign_str(device, dev_name(ar->dev)); | ||
362 | __assign_str(driver, dev_driver_string(ar->dev)); | ||
363 | __entry->msdu_id = msdu_id; | ||
364 | ), | ||
365 | |||
366 | TP_printk( | ||
367 | "%s %s msdu_id %d", | ||
368 | __get_str(driver), | ||
369 | __get_str(device), | ||
370 | __entry->msdu_id | ||
371 | ) | ||
372 | ); | ||
373 | |||
374 | DECLARE_EVENT_CLASS(ath10k_data_event, | ||
375 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | ||
376 | |||
377 | TP_ARGS(ar, data, len), | ||
378 | |||
379 | TP_STRUCT__entry( | ||
380 | __string(device, dev_name(ar->dev)) | ||
381 | __string(driver, dev_driver_string(ar->dev)) | ||
382 | __field(size_t, len) | ||
383 | __dynamic_array(u8, data, len) | ||
384 | ), | ||
385 | |||
386 | TP_fast_assign( | ||
387 | __assign_str(device, dev_name(ar->dev)); | ||
388 | __assign_str(driver, dev_driver_string(ar->dev)); | ||
389 | __entry->len = len; | ||
390 | memcpy(__get_dynamic_array(data), data, len); | ||
391 | ), | ||
392 | |||
393 | TP_printk( | ||
394 | "%s %s len %zu\n", | ||
395 | __get_str(driver), | ||
396 | __get_str(device), | ||
397 | __entry->len | ||
398 | ) | ||
399 | ); | ||
400 | |||
401 | DEFINE_EVENT(ath10k_data_event, ath10k_htt_tx_msdu, | ||
402 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | ||
403 | TP_ARGS(ar, data, len) | ||
404 | ); | ||
405 | |||
406 | DEFINE_EVENT(ath10k_data_event, ath10k_htt_rx_pop_msdu, | ||
407 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | ||
408 | TP_ARGS(ar, data, len) | ||
409 | ); | ||
410 | |||
411 | DEFINE_EVENT(ath10k_data_event, ath10k_wmi_mgmt_tx, | ||
412 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | ||
413 | TP_ARGS(ar, data, len) | ||
414 | ); | ||
415 | |||
416 | DEFINE_EVENT(ath10k_data_event, ath10k_wmi_bcn_tx, | ||
417 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | ||
418 | TP_ARGS(ar, data, len) | ||
419 | ); | ||
257 | #endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/ | 420 | #endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/ |
258 | 421 | ||
259 | /* we don't want to use include/trace/events */ | 422 | /* 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..f9c90e37bc7c 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); |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 2c42bd504b79..ae746cece211 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; |
@@ -800,6 +834,7 @@ 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", | 834 | 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, | 835 | wmi_skb, wmi_skb->len, fc & IEEE80211_FCTL_FTYPE, |
802 | fc & IEEE80211_FCTL_STYPE); | 836 | fc & IEEE80211_FCTL_STYPE); |
837 | trace_ath10k_wmi_mgmt_tx(ar, skb->data, skb->len); | ||
803 | 838 | ||
804 | /* Send the management frame buffer to the target */ | 839 | /* Send the management frame buffer to the target */ |
805 | ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid); | 840 | ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid); |
@@ -1079,7 +1114,6 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) | |||
1079 | struct wmi_mgmt_rx_event_v2 *ev_v2; | 1114 | struct wmi_mgmt_rx_event_v2 *ev_v2; |
1080 | struct wmi_mgmt_rx_hdr_v1 *ev_hdr; | 1115 | struct wmi_mgmt_rx_hdr_v1 *ev_hdr; |
1081 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); | 1116 | struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); |
1082 | struct ieee80211_channel *ch; | ||
1083 | struct ieee80211_hdr *hdr; | 1117 | struct ieee80211_hdr *hdr; |
1084 | u32 rx_status; | 1118 | u32 rx_status; |
1085 | u32 channel; | 1119 | u32 channel; |
@@ -1132,25 +1166,26 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb) | |||
1132 | if (rx_status & WMI_RX_STATUS_ERR_MIC) | 1166 | if (rx_status & WMI_RX_STATUS_ERR_MIC) |
1133 | status->flag |= RX_FLAG_MMIC_ERROR; | 1167 | status->flag |= RX_FLAG_MMIC_ERROR; |
1134 | 1168 | ||
1135 | /* HW can Rx CCK rates on 5GHz. In that case phy_mode is set to | 1169 | /* 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 | 1170 | * MODE_11B. This means phy_mode is not a reliable source for the band |
1137 | * of mgmt rx. */ | 1171 | * of mgmt rx. |
1138 | 1172 | */ | |
1139 | ch = ar->scan_channel; | 1173 | if (channel >= 1 && channel <= 14) { |
1140 | if (!ch) | 1174 | status->band = IEEE80211_BAND_2GHZ; |
1141 | ch = ar->rx_channel; | 1175 | } else if (channel >= 36 && channel <= 165) { |
1142 | 1176 | 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 { | 1177 | } else { |
1150 | ath10k_warn(ar, "using (unreliable) phy_mode to extract band for mgmt rx\n"); | 1178 | /* Shouldn't happen unless list of advertised channels to |
1151 | status->band = phy_mode_to_band(phy_mode); | 1179 | * mac80211 has been changed. |
1180 | */ | ||
1181 | WARN_ON_ONCE(1); | ||
1182 | dev_kfree_skb(skb); | ||
1183 | return 0; | ||
1152 | } | 1184 | } |
1153 | 1185 | ||
1186 | if (phy_mode == MODE_11B && status->band == IEEE80211_BAND_5GHZ) | ||
1187 | ath10k_dbg(ar, ATH10K_DBG_MGMT, "wmi mgmt rx 11b (CCK) on 5GHz\n"); | ||
1188 | |||
1154 | status->freq = ieee80211_channel_to_frequency(channel, status->band); | 1189 | status->freq = ieee80211_channel_to_frequency(channel, status->band); |
1155 | status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; | 1190 | status->signal = snr + ATH10K_DEFAULT_NOISE_FLOOR; |
1156 | status->rate_idx = get_rate_idx(rate, status->band); | 1191 | status->rate_idx = get_rate_idx(rate, status->band); |
@@ -1295,14 +1330,196 @@ static int ath10k_wmi_event_debug_mesg(struct ath10k *ar, struct sk_buff *skb) | |||
1295 | return 0; | 1330 | return 0; |
1296 | } | 1331 | } |
1297 | 1332 | ||
1333 | static void ath10k_wmi_pull_pdev_stats(const struct wmi_pdev_stats *src, | ||
1334 | struct ath10k_fw_stats_pdev *dst) | ||
1335 | { | ||
1336 | const struct wal_dbg_tx_stats *tx = &src->wal.tx; | ||
1337 | const struct wal_dbg_rx_stats *rx = &src->wal.rx; | ||
1338 | |||
1339 | dst->ch_noise_floor = __le32_to_cpu(src->chan_nf); | ||
1340 | dst->tx_frame_count = __le32_to_cpu(src->tx_frame_count); | ||
1341 | dst->rx_frame_count = __le32_to_cpu(src->rx_frame_count); | ||
1342 | dst->rx_clear_count = __le32_to_cpu(src->rx_clear_count); | ||
1343 | dst->cycle_count = __le32_to_cpu(src->cycle_count); | ||
1344 | dst->phy_err_count = __le32_to_cpu(src->phy_err_count); | ||
1345 | dst->chan_tx_power = __le32_to_cpu(src->chan_tx_pwr); | ||
1346 | |||
1347 | dst->comp_queued = __le32_to_cpu(tx->comp_queued); | ||
1348 | dst->comp_delivered = __le32_to_cpu(tx->comp_delivered); | ||
1349 | dst->msdu_enqued = __le32_to_cpu(tx->msdu_enqued); | ||
1350 | dst->mpdu_enqued = __le32_to_cpu(tx->mpdu_enqued); | ||
1351 | dst->wmm_drop = __le32_to_cpu(tx->wmm_drop); | ||
1352 | dst->local_enqued = __le32_to_cpu(tx->local_enqued); | ||
1353 | dst->local_freed = __le32_to_cpu(tx->local_freed); | ||
1354 | dst->hw_queued = __le32_to_cpu(tx->hw_queued); | ||
1355 | dst->hw_reaped = __le32_to_cpu(tx->hw_reaped); | ||
1356 | dst->underrun = __le32_to_cpu(tx->underrun); | ||
1357 | dst->tx_abort = __le32_to_cpu(tx->tx_abort); | ||
1358 | dst->mpdus_requed = __le32_to_cpu(tx->mpdus_requed); | ||
1359 | dst->tx_ko = __le32_to_cpu(tx->tx_ko); | ||
1360 | dst->data_rc = __le32_to_cpu(tx->data_rc); | ||
1361 | dst->self_triggers = __le32_to_cpu(tx->self_triggers); | ||
1362 | dst->sw_retry_failure = __le32_to_cpu(tx->sw_retry_failure); | ||
1363 | dst->illgl_rate_phy_err = __le32_to_cpu(tx->illgl_rate_phy_err); | ||
1364 | dst->pdev_cont_xretry = __le32_to_cpu(tx->pdev_cont_xretry); | ||
1365 | dst->pdev_tx_timeout = __le32_to_cpu(tx->pdev_tx_timeout); | ||
1366 | dst->pdev_resets = __le32_to_cpu(tx->pdev_resets); | ||
1367 | dst->phy_underrun = __le32_to_cpu(tx->phy_underrun); | ||
1368 | dst->txop_ovf = __le32_to_cpu(tx->txop_ovf); | ||
1369 | |||
1370 | dst->mid_ppdu_route_change = __le32_to_cpu(rx->mid_ppdu_route_change); | ||
1371 | dst->status_rcvd = __le32_to_cpu(rx->status_rcvd); | ||
1372 | dst->r0_frags = __le32_to_cpu(rx->r0_frags); | ||
1373 | dst->r1_frags = __le32_to_cpu(rx->r1_frags); | ||
1374 | dst->r2_frags = __le32_to_cpu(rx->r2_frags); | ||
1375 | dst->r3_frags = __le32_to_cpu(rx->r3_frags); | ||
1376 | dst->htt_msdus = __le32_to_cpu(rx->htt_msdus); | ||
1377 | dst->htt_mpdus = __le32_to_cpu(rx->htt_mpdus); | ||
1378 | dst->loc_msdus = __le32_to_cpu(rx->loc_msdus); | ||
1379 | dst->loc_mpdus = __le32_to_cpu(rx->loc_mpdus); | ||
1380 | dst->oversize_amsdu = __le32_to_cpu(rx->oversize_amsdu); | ||
1381 | dst->phy_errs = __le32_to_cpu(rx->phy_errs); | ||
1382 | dst->phy_err_drop = __le32_to_cpu(rx->phy_err_drop); | ||
1383 | dst->mpdu_errs = __le32_to_cpu(rx->mpdu_errs); | ||
1384 | } | ||
1385 | |||
1386 | static void ath10k_wmi_pull_peer_stats(const struct wmi_peer_stats *src, | ||
1387 | struct ath10k_fw_stats_peer *dst) | ||
1388 | { | ||
1389 | ether_addr_copy(dst->peer_macaddr, src->peer_macaddr.addr); | ||
1390 | dst->peer_rssi = __le32_to_cpu(src->peer_rssi); | ||
1391 | dst->peer_tx_rate = __le32_to_cpu(src->peer_tx_rate); | ||
1392 | } | ||
1393 | |||
1394 | static int ath10k_wmi_main_pull_fw_stats(struct ath10k *ar, | ||
1395 | struct sk_buff *skb, | ||
1396 | struct ath10k_fw_stats *stats) | ||
1397 | { | ||
1398 | const struct wmi_stats_event *ev = (void *)skb->data; | ||
1399 | u32 num_pdev_stats, num_vdev_stats, num_peer_stats; | ||
1400 | int i; | ||
1401 | |||
1402 | if (!skb_pull(skb, sizeof(*ev))) | ||
1403 | return -EPROTO; | ||
1404 | |||
1405 | num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); | ||
1406 | num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); | ||
1407 | num_peer_stats = __le32_to_cpu(ev->num_peer_stats); | ||
1408 | |||
1409 | for (i = 0; i < num_pdev_stats; i++) { | ||
1410 | const struct wmi_pdev_stats *src; | ||
1411 | struct ath10k_fw_stats_pdev *dst; | ||
1412 | |||
1413 | src = (void *)skb->data; | ||
1414 | if (!skb_pull(skb, sizeof(*src))) | ||
1415 | return -EPROTO; | ||
1416 | |||
1417 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); | ||
1418 | if (!dst) | ||
1419 | continue; | ||
1420 | |||
1421 | ath10k_wmi_pull_pdev_stats(src, dst); | ||
1422 | list_add_tail(&dst->list, &stats->pdevs); | ||
1423 | } | ||
1424 | |||
1425 | /* fw doesn't implement vdev stats */ | ||
1426 | |||
1427 | for (i = 0; i < num_peer_stats; i++) { | ||
1428 | const struct wmi_peer_stats *src; | ||
1429 | struct ath10k_fw_stats_peer *dst; | ||
1430 | |||
1431 | src = (void *)skb->data; | ||
1432 | if (!skb_pull(skb, sizeof(*src))) | ||
1433 | return -EPROTO; | ||
1434 | |||
1435 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); | ||
1436 | if (!dst) | ||
1437 | continue; | ||
1438 | |||
1439 | ath10k_wmi_pull_peer_stats(src, dst); | ||
1440 | list_add_tail(&dst->list, &stats->peers); | ||
1441 | } | ||
1442 | |||
1443 | return 0; | ||
1444 | } | ||
1445 | |||
1446 | static int ath10k_wmi_10x_pull_fw_stats(struct ath10k *ar, | ||
1447 | struct sk_buff *skb, | ||
1448 | struct ath10k_fw_stats *stats) | ||
1449 | { | ||
1450 | const struct wmi_stats_event *ev = (void *)skb->data; | ||
1451 | u32 num_pdev_stats, num_vdev_stats, num_peer_stats; | ||
1452 | int i; | ||
1453 | |||
1454 | if (!skb_pull(skb, sizeof(*ev))) | ||
1455 | return -EPROTO; | ||
1456 | |||
1457 | num_pdev_stats = __le32_to_cpu(ev->num_pdev_stats); | ||
1458 | num_vdev_stats = __le32_to_cpu(ev->num_vdev_stats); | ||
1459 | num_peer_stats = __le32_to_cpu(ev->num_peer_stats); | ||
1460 | |||
1461 | for (i = 0; i < num_pdev_stats; i++) { | ||
1462 | const struct wmi_10x_pdev_stats *src; | ||
1463 | struct ath10k_fw_stats_pdev *dst; | ||
1464 | |||
1465 | src = (void *)skb->data; | ||
1466 | if (!skb_pull(skb, sizeof(*src))) | ||
1467 | return -EPROTO; | ||
1468 | |||
1469 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); | ||
1470 | if (!dst) | ||
1471 | continue; | ||
1472 | |||
1473 | ath10k_wmi_pull_pdev_stats(&src->old, dst); | ||
1474 | |||
1475 | dst->ack_rx_bad = __le32_to_cpu(src->ack_rx_bad); | ||
1476 | dst->rts_bad = __le32_to_cpu(src->rts_bad); | ||
1477 | dst->rts_good = __le32_to_cpu(src->rts_good); | ||
1478 | dst->fcs_bad = __le32_to_cpu(src->fcs_bad); | ||
1479 | dst->no_beacons = __le32_to_cpu(src->no_beacons); | ||
1480 | dst->mib_int_count = __le32_to_cpu(src->mib_int_count); | ||
1481 | |||
1482 | list_add_tail(&dst->list, &stats->pdevs); | ||
1483 | } | ||
1484 | |||
1485 | /* fw doesn't implement vdev stats */ | ||
1486 | |||
1487 | for (i = 0; i < num_peer_stats; i++) { | ||
1488 | const struct wmi_10x_peer_stats *src; | ||
1489 | struct ath10k_fw_stats_peer *dst; | ||
1490 | |||
1491 | src = (void *)skb->data; | ||
1492 | if (!skb_pull(skb, sizeof(*src))) | ||
1493 | return -EPROTO; | ||
1494 | |||
1495 | dst = kzalloc(sizeof(*dst), GFP_ATOMIC); | ||
1496 | if (!dst) | ||
1497 | continue; | ||
1498 | |||
1499 | ath10k_wmi_pull_peer_stats(&src->old, dst); | ||
1500 | |||
1501 | dst->peer_rx_rate = __le32_to_cpu(src->peer_rx_rate); | ||
1502 | |||
1503 | list_add_tail(&dst->list, &stats->peers); | ||
1504 | } | ||
1505 | |||
1506 | return 0; | ||
1507 | } | ||
1508 | |||
1509 | int ath10k_wmi_pull_fw_stats(struct ath10k *ar, struct sk_buff *skb, | ||
1510 | struct ath10k_fw_stats *stats) | ||
1511 | { | ||
1512 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | ||
1513 | return ath10k_wmi_10x_pull_fw_stats(ar, skb, stats); | ||
1514 | else | ||
1515 | return ath10k_wmi_main_pull_fw_stats(ar, skb, stats); | ||
1516 | } | ||
1517 | |||
1298 | static void ath10k_wmi_event_update_stats(struct ath10k *ar, | 1518 | static void ath10k_wmi_event_update_stats(struct ath10k *ar, |
1299 | struct sk_buff *skb) | 1519 | struct sk_buff *skb) |
1300 | { | 1520 | { |
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"); | 1521 | ath10k_dbg(ar, ATH10K_DBG_WMI, "WMI_UPDATE_STATS_EVENTID\n"); |
1304 | 1522 | ath10k_debug_fw_stats_process(ar, skb); | |
1305 | ath10k_debug_read_target_stats(ar, ev); | ||
1306 | } | 1523 | } |
1307 | 1524 | ||
1308 | static void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar, | 1525 | static void ath10k_wmi_event_vdev_start_resp(struct ath10k *ar, |
@@ -1579,6 +1796,7 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
1579 | struct wmi_bcn_info *bcn_info; | 1796 | struct wmi_bcn_info *bcn_info; |
1580 | struct ath10k_vif *arvif; | 1797 | struct ath10k_vif *arvif; |
1581 | struct sk_buff *bcn; | 1798 | struct sk_buff *bcn; |
1799 | dma_addr_t paddr; | ||
1582 | int ret, vdev_id = 0; | 1800 | int ret, vdev_id = 0; |
1583 | 1801 | ||
1584 | ev = (struct wmi_host_swba_event *)skb->data; | 1802 | ev = (struct wmi_host_swba_event *)skb->data; |
@@ -1647,27 +1865,35 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
1647 | ath10k_warn(ar, "SWBA overrun on vdev %d\n", | 1865 | ath10k_warn(ar, "SWBA overrun on vdev %d\n", |
1648 | arvif->vdev_id); | 1866 | arvif->vdev_id); |
1649 | 1867 | ||
1650 | dma_unmap_single(arvif->ar->dev, | 1868 | 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 | } | 1869 | } |
1656 | 1870 | ||
1657 | ATH10K_SKB_CB(bcn)->paddr = dma_map_single(arvif->ar->dev, | 1871 | if (!arvif->beacon_buf) { |
1658 | bcn->data, bcn->len, | 1872 | paddr = dma_map_single(arvif->ar->dev, bcn->data, |
1659 | DMA_TO_DEVICE); | 1873 | bcn->len, DMA_TO_DEVICE); |
1660 | ret = dma_mapping_error(arvif->ar->dev, | 1874 | ret = dma_mapping_error(arvif->ar->dev, paddr); |
1661 | ATH10K_SKB_CB(bcn)->paddr); | 1875 | if (ret) { |
1662 | if (ret) { | 1876 | ath10k_warn(ar, "failed to map beacon: %d\n", |
1663 | ath10k_warn(ar, "failed to map beacon: %d\n", ret); | 1877 | ret); |
1664 | dev_kfree_skb_any(bcn); | 1878 | dev_kfree_skb_any(bcn); |
1665 | goto skip; | 1879 | goto skip; |
1880 | } | ||
1881 | |||
1882 | ATH10K_SKB_CB(bcn)->paddr = paddr; | ||
1883 | } else { | ||
1884 | if (bcn->len > IEEE80211_MAX_FRAME_LEN) { | ||
1885 | ath10k_warn(ar, "trimming beacon %d -> %d bytes!\n", | ||
1886 | bcn->len, IEEE80211_MAX_FRAME_LEN); | ||
1887 | skb_trim(bcn, IEEE80211_MAX_FRAME_LEN); | ||
1888 | } | ||
1889 | memcpy(arvif->beacon_buf, bcn->data, bcn->len); | ||
1890 | ATH10K_SKB_CB(bcn)->paddr = arvif->beacon_paddr; | ||
1666 | } | 1891 | } |
1667 | 1892 | ||
1668 | arvif->beacon = bcn; | 1893 | arvif->beacon = bcn; |
1669 | arvif->beacon_sent = false; | 1894 | arvif->beacon_sent = false; |
1670 | 1895 | ||
1896 | trace_ath10k_wmi_bcn_tx(ar, bcn->data, bcn->len); | ||
1671 | ath10k_wmi_tx_beacon_nowait(arvif); | 1897 | ath10k_wmi_tx_beacon_nowait(arvif); |
1672 | skip: | 1898 | skip: |
1673 | spin_unlock_bh(&ar->data_lock); | 1899 | spin_unlock_bh(&ar->data_lock); |
@@ -1681,8 +1907,8 @@ static void ath10k_wmi_event_tbttoffset_update(struct ath10k *ar, | |||
1681 | } | 1907 | } |
1682 | 1908 | ||
1683 | static void ath10k_dfs_radar_report(struct ath10k *ar, | 1909 | static void ath10k_dfs_radar_report(struct ath10k *ar, |
1684 | struct wmi_single_phyerr_rx_event *event, | 1910 | const struct wmi_phyerr *phyerr, |
1685 | struct phyerr_radar_report *rr, | 1911 | const struct phyerr_radar_report *rr, |
1686 | u64 tsf) | 1912 | u64 tsf) |
1687 | { | 1913 | { |
1688 | u32 reg0, reg1, tsf32l; | 1914 | u32 reg0, reg1, tsf32l; |
@@ -1715,12 +1941,12 @@ static void ath10k_dfs_radar_report(struct ath10k *ar, | |||
1715 | return; | 1941 | return; |
1716 | 1942 | ||
1717 | /* report event to DFS pattern detector */ | 1943 | /* report event to DFS pattern detector */ |
1718 | tsf32l = __le32_to_cpu(event->hdr.tsf_timestamp); | 1944 | tsf32l = __le32_to_cpu(phyerr->tsf_timestamp); |
1719 | tsf64 = tsf & (~0xFFFFFFFFULL); | 1945 | tsf64 = tsf & (~0xFFFFFFFFULL); |
1720 | tsf64 |= tsf32l; | 1946 | tsf64 |= tsf32l; |
1721 | 1947 | ||
1722 | width = MS(reg1, RADAR_REPORT_REG1_PULSE_DUR); | 1948 | width = MS(reg1, RADAR_REPORT_REG1_PULSE_DUR); |
1723 | rssi = event->hdr.rssi_combined; | 1949 | rssi = phyerr->rssi_combined; |
1724 | 1950 | ||
1725 | /* hardware store this as 8 bit signed value, | 1951 | /* hardware store this as 8 bit signed value, |
1726 | * set to zero if negative number | 1952 | * set to zero if negative number |
@@ -1759,8 +1985,8 @@ static void ath10k_dfs_radar_report(struct ath10k *ar, | |||
1759 | } | 1985 | } |
1760 | 1986 | ||
1761 | static int ath10k_dfs_fft_report(struct ath10k *ar, | 1987 | static int ath10k_dfs_fft_report(struct ath10k *ar, |
1762 | struct wmi_single_phyerr_rx_event *event, | 1988 | const struct wmi_phyerr *phyerr, |
1763 | struct phyerr_fft_report *fftr, | 1989 | const struct phyerr_fft_report *fftr, |
1764 | u64 tsf) | 1990 | u64 tsf) |
1765 | { | 1991 | { |
1766 | u32 reg0, reg1; | 1992 | u32 reg0, reg1; |
@@ -1768,7 +1994,7 @@ static int ath10k_dfs_fft_report(struct ath10k *ar, | |||
1768 | 1994 | ||
1769 | reg0 = __le32_to_cpu(fftr->reg0); | 1995 | reg0 = __le32_to_cpu(fftr->reg0); |
1770 | reg1 = __le32_to_cpu(fftr->reg1); | 1996 | reg1 = __le32_to_cpu(fftr->reg1); |
1771 | rssi = event->hdr.rssi_combined; | 1997 | rssi = phyerr->rssi_combined; |
1772 | 1998 | ||
1773 | ath10k_dbg(ar, ATH10K_DBG_REGULATORY, | 1999 | 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", | 2000 | "wmi phyerr fft report total_gain_db %d base_pwr_db %d fft_chn_idx %d peak_sidx %d\n", |
@@ -1797,20 +2023,20 @@ static int ath10k_dfs_fft_report(struct ath10k *ar, | |||
1797 | } | 2023 | } |
1798 | 2024 | ||
1799 | static void ath10k_wmi_event_dfs(struct ath10k *ar, | 2025 | static void ath10k_wmi_event_dfs(struct ath10k *ar, |
1800 | struct wmi_single_phyerr_rx_event *event, | 2026 | const struct wmi_phyerr *phyerr, |
1801 | u64 tsf) | 2027 | u64 tsf) |
1802 | { | 2028 | { |
1803 | int buf_len, tlv_len, res, i = 0; | 2029 | int buf_len, tlv_len, res, i = 0; |
1804 | struct phyerr_tlv *tlv; | 2030 | const struct phyerr_tlv *tlv; |
1805 | struct phyerr_radar_report *rr; | 2031 | const struct phyerr_radar_report *rr; |
1806 | struct phyerr_fft_report *fftr; | 2032 | const struct phyerr_fft_report *fftr; |
1807 | u8 *tlv_buf; | 2033 | const u8 *tlv_buf; |
1808 | 2034 | ||
1809 | buf_len = __le32_to_cpu(event->hdr.buf_len); | 2035 | buf_len = __le32_to_cpu(phyerr->buf_len); |
1810 | ath10k_dbg(ar, ATH10K_DBG_REGULATORY, | 2036 | ath10k_dbg(ar, ATH10K_DBG_REGULATORY, |
1811 | "wmi event dfs err_code %d rssi %d tsfl 0x%X tsf64 0x%llX len %d\n", | 2037 | "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, | 2038 | phyerr->phy_err_code, phyerr->rssi_combined, |
1813 | __le32_to_cpu(event->hdr.tsf_timestamp), tsf, buf_len); | 2039 | __le32_to_cpu(phyerr->tsf_timestamp), tsf, buf_len); |
1814 | 2040 | ||
1815 | /* Skip event if DFS disabled */ | 2041 | /* Skip event if DFS disabled */ |
1816 | if (!config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) | 2042 | if (!config_enabled(CONFIG_ATH10K_DFS_CERTIFIED)) |
@@ -1825,9 +2051,9 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar, | |||
1825 | return; | 2051 | return; |
1826 | } | 2052 | } |
1827 | 2053 | ||
1828 | tlv = (struct phyerr_tlv *)&event->bufp[i]; | 2054 | tlv = (struct phyerr_tlv *)&phyerr->buf[i]; |
1829 | tlv_len = __le16_to_cpu(tlv->len); | 2055 | tlv_len = __le16_to_cpu(tlv->len); |
1830 | tlv_buf = &event->bufp[i + sizeof(*tlv)]; | 2056 | tlv_buf = &phyerr->buf[i + sizeof(*tlv)]; |
1831 | ath10k_dbg(ar, ATH10K_DBG_REGULATORY, | 2057 | ath10k_dbg(ar, ATH10K_DBG_REGULATORY, |
1832 | "wmi event dfs tlv_len %d tlv_tag 0x%02X tlv_sig 0x%02X\n", | 2058 | "wmi event dfs tlv_len %d tlv_tag 0x%02X tlv_sig 0x%02X\n", |
1833 | tlv_len, tlv->tag, tlv->sig); | 2059 | tlv_len, tlv->tag, tlv->sig); |
@@ -1841,7 +2067,7 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar, | |||
1841 | } | 2067 | } |
1842 | 2068 | ||
1843 | rr = (struct phyerr_radar_report *)tlv_buf; | 2069 | rr = (struct phyerr_radar_report *)tlv_buf; |
1844 | ath10k_dfs_radar_report(ar, event, rr, tsf); | 2070 | ath10k_dfs_radar_report(ar, phyerr, rr, tsf); |
1845 | break; | 2071 | break; |
1846 | case PHYERR_TLV_TAG_SEARCH_FFT_REPORT: | 2072 | case PHYERR_TLV_TAG_SEARCH_FFT_REPORT: |
1847 | if (i + sizeof(*tlv) + sizeof(*fftr) > buf_len) { | 2073 | if (i + sizeof(*tlv) + sizeof(*fftr) > buf_len) { |
@@ -1851,7 +2077,7 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar, | |||
1851 | } | 2077 | } |
1852 | 2078 | ||
1853 | fftr = (struct phyerr_fft_report *)tlv_buf; | 2079 | fftr = (struct phyerr_fft_report *)tlv_buf; |
1854 | res = ath10k_dfs_fft_report(ar, event, fftr, tsf); | 2080 | res = ath10k_dfs_fft_report(ar, phyerr, fftr, tsf); |
1855 | if (res) | 2081 | if (res) |
1856 | return; | 2082 | return; |
1857 | break; | 2083 | break; |
@@ -1863,16 +2089,16 @@ static void ath10k_wmi_event_dfs(struct ath10k *ar, | |||
1863 | 2089 | ||
1864 | static void | 2090 | static void |
1865 | ath10k_wmi_event_spectral_scan(struct ath10k *ar, | 2091 | ath10k_wmi_event_spectral_scan(struct ath10k *ar, |
1866 | struct wmi_single_phyerr_rx_event *event, | 2092 | const struct wmi_phyerr *phyerr, |
1867 | u64 tsf) | 2093 | u64 tsf) |
1868 | { | 2094 | { |
1869 | int buf_len, tlv_len, res, i = 0; | 2095 | int buf_len, tlv_len, res, i = 0; |
1870 | struct phyerr_tlv *tlv; | 2096 | struct phyerr_tlv *tlv; |
1871 | u8 *tlv_buf; | 2097 | const void *tlv_buf; |
1872 | struct phyerr_fft_report *fftr; | 2098 | const struct phyerr_fft_report *fftr; |
1873 | size_t fftr_len; | 2099 | size_t fftr_len; |
1874 | 2100 | ||
1875 | buf_len = __le32_to_cpu(event->hdr.buf_len); | 2101 | buf_len = __le32_to_cpu(phyerr->buf_len); |
1876 | 2102 | ||
1877 | while (i < buf_len) { | 2103 | while (i < buf_len) { |
1878 | if (i + sizeof(*tlv) > buf_len) { | 2104 | if (i + sizeof(*tlv) > buf_len) { |
@@ -1881,9 +2107,9 @@ ath10k_wmi_event_spectral_scan(struct ath10k *ar, | |||
1881 | return; | 2107 | return; |
1882 | } | 2108 | } |
1883 | 2109 | ||
1884 | tlv = (struct phyerr_tlv *)&event->bufp[i]; | 2110 | tlv = (struct phyerr_tlv *)&phyerr->buf[i]; |
1885 | tlv_len = __le16_to_cpu(tlv->len); | 2111 | tlv_len = __le16_to_cpu(tlv->len); |
1886 | tlv_buf = &event->bufp[i + sizeof(*tlv)]; | 2112 | tlv_buf = &phyerr->buf[i + sizeof(*tlv)]; |
1887 | 2113 | ||
1888 | if (i + sizeof(*tlv) + tlv_len > buf_len) { | 2114 | if (i + sizeof(*tlv) + tlv_len > buf_len) { |
1889 | ath10k_warn(ar, "failed to parse phyerr tlv payload at byte %d\n", | 2115 | ath10k_warn(ar, "failed to parse phyerr tlv payload at byte %d\n", |
@@ -1900,8 +2126,8 @@ ath10k_wmi_event_spectral_scan(struct ath10k *ar, | |||
1900 | } | 2126 | } |
1901 | 2127 | ||
1902 | fftr_len = tlv_len - sizeof(*fftr); | 2128 | fftr_len = tlv_len - sizeof(*fftr); |
1903 | fftr = (struct phyerr_fft_report *)tlv_buf; | 2129 | fftr = tlv_buf; |
1904 | res = ath10k_spectral_process_fft(ar, event, | 2130 | res = ath10k_spectral_process_fft(ar, phyerr, |
1905 | fftr, fftr_len, | 2131 | fftr, fftr_len, |
1906 | tsf); | 2132 | tsf); |
1907 | if (res < 0) { | 2133 | if (res < 0) { |
@@ -1918,8 +2144,8 @@ ath10k_wmi_event_spectral_scan(struct ath10k *ar, | |||
1918 | 2144 | ||
1919 | static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) | 2145 | static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) |
1920 | { | 2146 | { |
1921 | struct wmi_comb_phyerr_rx_event *comb_event; | 2147 | const struct wmi_phyerr_event *ev; |
1922 | struct wmi_single_phyerr_rx_event *event; | 2148 | const struct wmi_phyerr *phyerr; |
1923 | u32 count, i, buf_len, phy_err_code; | 2149 | u32 count, i, buf_len, phy_err_code; |
1924 | u64 tsf; | 2150 | u64 tsf; |
1925 | int left_len = skb->len; | 2151 | int left_len = skb->len; |
@@ -1927,38 +2153,38 @@ static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) | |||
1927 | ATH10K_DFS_STAT_INC(ar, phy_errors); | 2153 | ATH10K_DFS_STAT_INC(ar, phy_errors); |
1928 | 2154 | ||
1929 | /* Check if combined event available */ | 2155 | /* Check if combined event available */ |
1930 | if (left_len < sizeof(*comb_event)) { | 2156 | if (left_len < sizeof(*ev)) { |
1931 | ath10k_warn(ar, "wmi phyerr combined event wrong len\n"); | 2157 | ath10k_warn(ar, "wmi phyerr combined event wrong len\n"); |
1932 | return; | 2158 | return; |
1933 | } | 2159 | } |
1934 | 2160 | ||
1935 | left_len -= sizeof(*comb_event); | 2161 | left_len -= sizeof(*ev); |
1936 | 2162 | ||
1937 | /* Check number of included events */ | 2163 | /* Check number of included events */ |
1938 | comb_event = (struct wmi_comb_phyerr_rx_event *)skb->data; | 2164 | ev = (const struct wmi_phyerr_event *)skb->data; |
1939 | count = __le32_to_cpu(comb_event->hdr.num_phyerr_events); | 2165 | count = __le32_to_cpu(ev->num_phyerrs); |
1940 | 2166 | ||
1941 | tsf = __le32_to_cpu(comb_event->hdr.tsf_u32); | 2167 | tsf = __le32_to_cpu(ev->tsf_u32); |
1942 | tsf <<= 32; | 2168 | tsf <<= 32; |
1943 | tsf |= __le32_to_cpu(comb_event->hdr.tsf_l32); | 2169 | tsf |= __le32_to_cpu(ev->tsf_l32); |
1944 | 2170 | ||
1945 | ath10k_dbg(ar, ATH10K_DBG_WMI, | 2171 | ath10k_dbg(ar, ATH10K_DBG_WMI, |
1946 | "wmi event phyerr count %d tsf64 0x%llX\n", | 2172 | "wmi event phyerr count %d tsf64 0x%llX\n", |
1947 | count, tsf); | 2173 | count, tsf); |
1948 | 2174 | ||
1949 | event = (struct wmi_single_phyerr_rx_event *)comb_event->bufp; | 2175 | phyerr = ev->phyerrs; |
1950 | for (i = 0; i < count; i++) { | 2176 | for (i = 0; i < count; i++) { |
1951 | /* Check if we can read event header */ | 2177 | /* Check if we can read event header */ |
1952 | if (left_len < sizeof(*event)) { | 2178 | if (left_len < sizeof(*phyerr)) { |
1953 | ath10k_warn(ar, "single event (%d) wrong head len\n", | 2179 | ath10k_warn(ar, "single event (%d) wrong head len\n", |
1954 | i); | 2180 | i); |
1955 | return; | 2181 | return; |
1956 | } | 2182 | } |
1957 | 2183 | ||
1958 | left_len -= sizeof(*event); | 2184 | left_len -= sizeof(*phyerr); |
1959 | 2185 | ||
1960 | buf_len = __le32_to_cpu(event->hdr.buf_len); | 2186 | buf_len = __le32_to_cpu(phyerr->buf_len); |
1961 | phy_err_code = event->hdr.phy_err_code; | 2187 | phy_err_code = phyerr->phy_err_code; |
1962 | 2188 | ||
1963 | if (left_len < buf_len) { | 2189 | if (left_len < buf_len) { |
1964 | ath10k_warn(ar, "single event (%d) wrong buf len\n", i); | 2190 | ath10k_warn(ar, "single event (%d) wrong buf len\n", i); |
@@ -1969,20 +2195,20 @@ static void ath10k_wmi_event_phyerr(struct ath10k *ar, struct sk_buff *skb) | |||
1969 | 2195 | ||
1970 | switch (phy_err_code) { | 2196 | switch (phy_err_code) { |
1971 | case PHY_ERROR_RADAR: | 2197 | case PHY_ERROR_RADAR: |
1972 | ath10k_wmi_event_dfs(ar, event, tsf); | 2198 | ath10k_wmi_event_dfs(ar, phyerr, tsf); |
1973 | break; | 2199 | break; |
1974 | case PHY_ERROR_SPECTRAL_SCAN: | 2200 | case PHY_ERROR_SPECTRAL_SCAN: |
1975 | ath10k_wmi_event_spectral_scan(ar, event, tsf); | 2201 | ath10k_wmi_event_spectral_scan(ar, phyerr, tsf); |
1976 | break; | 2202 | break; |
1977 | case PHY_ERROR_FALSE_RADAR_EXT: | 2203 | case PHY_ERROR_FALSE_RADAR_EXT: |
1978 | ath10k_wmi_event_dfs(ar, event, tsf); | 2204 | ath10k_wmi_event_dfs(ar, phyerr, tsf); |
1979 | ath10k_wmi_event_spectral_scan(ar, event, tsf); | 2205 | ath10k_wmi_event_spectral_scan(ar, phyerr, tsf); |
1980 | break; | 2206 | break; |
1981 | default: | 2207 | default: |
1982 | break; | 2208 | break; |
1983 | } | 2209 | } |
1984 | 2210 | ||
1985 | event += sizeof(*event) + buf_len; | 2211 | phyerr = (void *)phyerr + sizeof(*phyerr) + buf_len; |
1986 | } | 2212 | } |
1987 | } | 2213 | } |
1988 | 2214 | ||
@@ -2163,30 +2389,113 @@ static int ath10k_wmi_alloc_host_mem(struct ath10k *ar, u32 req_id, | |||
2163 | return 0; | 2389 | return 0; |
2164 | } | 2390 | } |
2165 | 2391 | ||
2166 | static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, | 2392 | static int ath10k_wmi_main_pull_svc_rdy_ev(struct sk_buff *skb, |
2167 | struct sk_buff *skb) | 2393 | struct wmi_svc_rdy_ev_arg *arg) |
2168 | { | 2394 | { |
2169 | struct wmi_service_ready_event *ev = (void *)skb->data; | 2395 | struct wmi_service_ready_event *ev; |
2396 | size_t i, n; | ||
2397 | |||
2398 | if (skb->len < sizeof(*ev)) | ||
2399 | return -EPROTO; | ||
2400 | |||
2401 | ev = (void *)skb->data; | ||
2402 | skb_pull(skb, sizeof(*ev)); | ||
2403 | arg->min_tx_power = ev->hw_min_tx_power; | ||
2404 | arg->max_tx_power = ev->hw_max_tx_power; | ||
2405 | arg->ht_cap = ev->ht_cap_info; | ||
2406 | arg->vht_cap = ev->vht_cap_info; | ||
2407 | arg->sw_ver0 = ev->sw_version; | ||
2408 | arg->sw_ver1 = ev->sw_version_1; | ||
2409 | arg->phy_capab = ev->phy_capability; | ||
2410 | arg->num_rf_chains = ev->num_rf_chains; | ||
2411 | arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd; | ||
2412 | arg->num_mem_reqs = ev->num_mem_reqs; | ||
2413 | arg->service_map = ev->wmi_service_bitmap; | ||
2414 | |||
2415 | n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs), | ||
2416 | ARRAY_SIZE(arg->mem_reqs)); | ||
2417 | for (i = 0; i < n; i++) | ||
2418 | arg->mem_reqs[i] = &ev->mem_reqs[i]; | ||
2419 | |||
2420 | if (skb->len < | ||
2421 | __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0])) | ||
2422 | return -EPROTO; | ||
2423 | |||
2424 | return 0; | ||
2425 | } | ||
2426 | |||
2427 | static int ath10k_wmi_10x_pull_svc_rdy_ev(struct sk_buff *skb, | ||
2428 | struct wmi_svc_rdy_ev_arg *arg) | ||
2429 | { | ||
2430 | struct wmi_10x_service_ready_event *ev; | ||
2431 | int i, n; | ||
2432 | |||
2433 | if (skb->len < sizeof(*ev)) | ||
2434 | return -EPROTO; | ||
2435 | |||
2436 | ev = (void *)skb->data; | ||
2437 | skb_pull(skb, sizeof(*ev)); | ||
2438 | arg->min_tx_power = ev->hw_min_tx_power; | ||
2439 | arg->max_tx_power = ev->hw_max_tx_power; | ||
2440 | arg->ht_cap = ev->ht_cap_info; | ||
2441 | arg->vht_cap = ev->vht_cap_info; | ||
2442 | arg->sw_ver0 = ev->sw_version; | ||
2443 | arg->phy_capab = ev->phy_capability; | ||
2444 | arg->num_rf_chains = ev->num_rf_chains; | ||
2445 | arg->eeprom_rd = ev->hal_reg_capabilities.eeprom_rd; | ||
2446 | arg->num_mem_reqs = ev->num_mem_reqs; | ||
2447 | arg->service_map = ev->wmi_service_bitmap; | ||
2448 | |||
2449 | n = min_t(size_t, __le32_to_cpu(arg->num_mem_reqs), | ||
2450 | ARRAY_SIZE(arg->mem_reqs)); | ||
2451 | for (i = 0; i < n; i++) | ||
2452 | arg->mem_reqs[i] = &ev->mem_reqs[i]; | ||
2453 | |||
2454 | if (skb->len < | ||
2455 | __le32_to_cpu(arg->num_mem_reqs) * sizeof(arg->mem_reqs[0])) | ||
2456 | return -EPROTO; | ||
2457 | |||
2458 | return 0; | ||
2459 | } | ||
2460 | |||
2461 | static void ath10k_wmi_event_service_ready(struct ath10k *ar, | ||
2462 | struct sk_buff *skb) | ||
2463 | { | ||
2464 | struct wmi_svc_rdy_ev_arg arg = {}; | ||
2465 | u32 num_units, req_id, unit_size, num_mem_reqs, num_unit_info, i; | ||
2170 | DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {}; | 2466 | DECLARE_BITMAP(svc_bmap, WMI_SERVICE_MAX) = {}; |
2467 | int ret; | ||
2468 | |||
2469 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { | ||
2470 | ret = ath10k_wmi_10x_pull_svc_rdy_ev(skb, &arg); | ||
2471 | wmi_10x_svc_map(arg.service_map, svc_bmap); | ||
2472 | } else { | ||
2473 | ret = ath10k_wmi_main_pull_svc_rdy_ev(skb, &arg); | ||
2474 | wmi_main_svc_map(arg.service_map, svc_bmap); | ||
2475 | } | ||
2171 | 2476 | ||
2172 | if (skb->len < sizeof(*ev)) { | 2477 | if (ret) { |
2173 | ath10k_warn(ar, "Service ready event was %d B but expected %zu B. Wrong firmware version?\n", | 2478 | ath10k_warn(ar, "failed to parse service ready: %d\n", ret); |
2174 | skb->len, sizeof(*ev)); | ||
2175 | return; | 2479 | return; |
2176 | } | 2480 | } |
2177 | 2481 | ||
2178 | ar->hw_min_tx_power = __le32_to_cpu(ev->hw_min_tx_power); | 2482 | 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); | 2483 | ar->hw_max_tx_power = __le32_to_cpu(arg.max_tx_power); |
2180 | ar->ht_cap_info = __le32_to_cpu(ev->ht_cap_info); | 2484 | ar->ht_cap_info = __le32_to_cpu(arg.ht_cap); |
2181 | ar->vht_cap_info = __le32_to_cpu(ev->vht_cap_info); | 2485 | ar->vht_cap_info = __le32_to_cpu(arg.vht_cap); |
2182 | ar->fw_version_major = | 2486 | ar->fw_version_major = |
2183 | (__le32_to_cpu(ev->sw_version) & 0xff000000) >> 24; | 2487 | (__le32_to_cpu(arg.sw_ver0) & 0xff000000) >> 24; |
2184 | ar->fw_version_minor = (__le32_to_cpu(ev->sw_version) & 0x00ffffff); | 2488 | ar->fw_version_minor = (__le32_to_cpu(arg.sw_ver0) & 0x00ffffff); |
2185 | ar->fw_version_release = | 2489 | ar->fw_version_release = |
2186 | (__le32_to_cpu(ev->sw_version_1) & 0xffff0000) >> 16; | 2490 | (__le32_to_cpu(arg.sw_ver1) & 0xffff0000) >> 16; |
2187 | ar->fw_version_build = (__le32_to_cpu(ev->sw_version_1) & 0x0000ffff); | 2491 | ar->fw_version_build = (__le32_to_cpu(arg.sw_ver1) & 0x0000ffff); |
2188 | ar->phy_capability = __le32_to_cpu(ev->phy_capability); | 2492 | ar->phy_capability = __le32_to_cpu(arg.phy_capab); |
2189 | ar->num_rf_chains = __le32_to_cpu(ev->num_rf_chains); | 2493 | ar->num_rf_chains = __le32_to_cpu(arg.num_rf_chains); |
2494 | ar->ath_common.regulatory.current_rd = __le32_to_cpu(arg.eeprom_rd); | ||
2495 | |||
2496 | ath10k_debug_read_service_map(ar, svc_bmap, sizeof(svc_bmap)); | ||
2497 | ath10k_dbg_dump(ar, ATH10K_DBG_WMI, NULL, "wmi svc: ", | ||
2498 | arg.service_map, sizeof(arg.service_map)); | ||
2190 | 2499 | ||
2191 | /* only manually set fw features when not using FW IE format */ | 2500 | /* only manually set fw features when not using FW IE format */ |
2192 | if (ar->fw_api == 1 && ar->fw_version_build > 636) | 2501 | if (ar->fw_api == 1 && ar->fw_version_build > 636) |
@@ -2198,13 +2507,8 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, | |||
2198 | ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM; | 2507 | ar->num_rf_chains = WMI_MAX_SPATIAL_STREAM; |
2199 | } | 2508 | } |
2200 | 2509 | ||
2201 | ar->ath_common.regulatory.current_rd = | 2510 | ar->supp_tx_chainmask = (1 << ar->num_rf_chains) - 1; |
2202 | __le32_to_cpu(ev->hal_reg_capabilities.eeprom_rd); | 2511 | 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 | 2512 | ||
2209 | if (strlen(ar->hw->wiphy->fw_version) == 0) { | 2513 | if (strlen(ar->hw->wiphy->fw_version) == 0) { |
2210 | snprintf(ar->hw->wiphy->fw_version, | 2514 | snprintf(ar->hw->wiphy->fw_version, |
@@ -2216,93 +2520,18 @@ static void ath10k_wmi_service_ready_event_rx(struct ath10k *ar, | |||
2216 | ar->fw_version_build); | 2520 | ar->fw_version_build); |
2217 | } | 2521 | } |
2218 | 2522 | ||
2219 | /* FIXME: it probably should be better to support this */ | 2523 | num_mem_reqs = __le32_to_cpu(arg.num_mem_reqs); |
2220 | if (__le32_to_cpu(ev->num_mem_reqs) > 0) { | 2524 | 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", | 2525 | ath10k_warn(ar, "requested memory chunks number (%d) exceeds the limit\n", |
2291 | num_mem_reqs); | 2526 | num_mem_reqs); |
2292 | return; | 2527 | return; |
2293 | } | 2528 | } |
2294 | 2529 | ||
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) { | 2530 | for (i = 0; i < num_mem_reqs; ++i) { |
2302 | req_id = __le32_to_cpu(ev->mem_reqs[i].req_id); | 2531 | req_id = __le32_to_cpu(arg.mem_reqs[i]->req_id); |
2303 | num_units = __le32_to_cpu(ev->mem_reqs[i].num_units); | 2532 | num_units = __le32_to_cpu(arg.mem_reqs[i]->num_units); |
2304 | unit_size = __le32_to_cpu(ev->mem_reqs[i].unit_size); | 2533 | 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); | 2534 | num_unit_info = __le32_to_cpu(arg.mem_reqs[i]->num_unit_info); |
2306 | 2535 | ||
2307 | if (num_unit_info & NUM_UNITS_IS_NUM_PEERS) | 2536 | if (num_unit_info & NUM_UNITS_IS_NUM_PEERS) |
2308 | /* number of units to allocate is number of | 2537 | /* number of units to allocate is number of |
@@ -2316,7 +2545,7 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar, | |||
2316 | ath10k_dbg(ar, ATH10K_DBG_WMI, | 2545 | 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", | 2546 | "wmi mem_req_id %d num_units %d num_unit_info %d unit size %d actual units %d\n", |
2318 | req_id, | 2547 | req_id, |
2319 | __le32_to_cpu(ev->mem_reqs[i].num_units), | 2548 | __le32_to_cpu(arg.mem_reqs[i]->num_units), |
2320 | num_unit_info, | 2549 | num_unit_info, |
2321 | unit_size, | 2550 | unit_size, |
2322 | num_units); | 2551 | num_units); |
@@ -2327,23 +2556,23 @@ static void ath10k_wmi_10x_service_ready_event_rx(struct ath10k *ar, | |||
2327 | return; | 2556 | return; |
2328 | } | 2557 | } |
2329 | 2558 | ||
2330 | exit: | ||
2331 | ath10k_dbg(ar, ATH10K_DBG_WMI, | 2559 | 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", | 2560 | "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), | 2561 | __le32_to_cpu(arg.min_tx_power), |
2334 | __le32_to_cpu(ev->abi_version), | 2562 | __le32_to_cpu(arg.max_tx_power), |
2335 | __le32_to_cpu(ev->phy_capability), | 2563 | __le32_to_cpu(arg.ht_cap), |
2336 | __le32_to_cpu(ev->ht_cap_info), | 2564 | __le32_to_cpu(arg.vht_cap), |
2337 | __le32_to_cpu(ev->vht_cap_info), | 2565 | __le32_to_cpu(arg.sw_ver0), |
2338 | __le32_to_cpu(ev->vht_supp_mcs), | 2566 | __le32_to_cpu(arg.sw_ver1), |
2339 | __le32_to_cpu(ev->sys_cap_info), | 2567 | __le32_to_cpu(arg.phy_capab), |
2340 | __le32_to_cpu(ev->num_mem_reqs), | 2568 | __le32_to_cpu(arg.num_rf_chains), |
2341 | __le32_to_cpu(ev->num_rf_chains)); | 2569 | __le32_to_cpu(arg.eeprom_rd), |
2570 | __le32_to_cpu(arg.num_mem_reqs)); | ||
2342 | 2571 | ||
2343 | complete(&ar->wmi.service_ready); | 2572 | complete(&ar->wmi.service_ready); |
2344 | } | 2573 | } |
2345 | 2574 | ||
2346 | static int ath10k_wmi_ready_event_rx(struct ath10k *ar, struct sk_buff *skb) | 2575 | static int ath10k_wmi_event_ready(struct ath10k *ar, struct sk_buff *skb) |
2347 | { | 2576 | { |
2348 | struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data; | 2577 | struct wmi_ready_event *ev = (struct wmi_ready_event *)skb->data; |
2349 | 2578 | ||
@@ -2466,10 +2695,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); | 2695 | ath10k_wmi_event_vdev_install_key_complete(ar, skb); |
2467 | break; | 2696 | break; |
2468 | case WMI_SERVICE_READY_EVENTID: | 2697 | case WMI_SERVICE_READY_EVENTID: |
2469 | ath10k_wmi_service_ready_event_rx(ar, skb); | 2698 | ath10k_wmi_event_service_ready(ar, skb); |
2470 | break; | 2699 | break; |
2471 | case WMI_READY_EVENTID: | 2700 | case WMI_READY_EVENTID: |
2472 | ath10k_wmi_ready_event_rx(ar, skb); | 2701 | ath10k_wmi_event_ready(ar, skb); |
2473 | break; | 2702 | break; |
2474 | default: | 2703 | default: |
2475 | ath10k_warn(ar, "Unknown eventid: %d\n", id); | 2704 | ath10k_warn(ar, "Unknown eventid: %d\n", id); |
@@ -2586,10 +2815,10 @@ static void ath10k_wmi_10x_process_rx(struct ath10k *ar, struct sk_buff *skb) | |||
2586 | ath10k_wmi_event_vdev_resume_req(ar, skb); | 2815 | ath10k_wmi_event_vdev_resume_req(ar, skb); |
2587 | break; | 2816 | break; |
2588 | case WMI_10X_SERVICE_READY_EVENTID: | 2817 | case WMI_10X_SERVICE_READY_EVENTID: |
2589 | ath10k_wmi_10x_service_ready_event_rx(ar, skb); | 2818 | ath10k_wmi_event_service_ready(ar, skb); |
2590 | break; | 2819 | break; |
2591 | case WMI_10X_READY_EVENTID: | 2820 | case WMI_10X_READY_EVENTID: |
2592 | ath10k_wmi_ready_event_rx(ar, skb); | 2821 | ath10k_wmi_event_ready(ar, skb); |
2593 | break; | 2822 | break; |
2594 | case WMI_10X_PDEV_UTF_EVENTID: | 2823 | case WMI_10X_PDEV_UTF_EVENTID: |
2595 | /* ignore utf events */ | 2824 | /* ignore utf events */ |
@@ -2697,10 +2926,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); | 2926 | ath10k_wmi_event_vdev_resume_req(ar, skb); |
2698 | break; | 2927 | break; |
2699 | case WMI_10_2_SERVICE_READY_EVENTID: | 2928 | case WMI_10_2_SERVICE_READY_EVENTID: |
2700 | ath10k_wmi_10x_service_ready_event_rx(ar, skb); | 2929 | ath10k_wmi_event_service_ready(ar, skb); |
2701 | break; | 2930 | break; |
2702 | case WMI_10_2_READY_EVENTID: | 2931 | case WMI_10_2_READY_EVENTID: |
2703 | ath10k_wmi_ready_event_rx(ar, skb); | 2932 | ath10k_wmi_event_ready(ar, skb); |
2704 | break; | 2933 | break; |
2705 | case WMI_10_2_RTT_KEEPALIVE_EVENTID: | 2934 | case WMI_10_2_RTT_KEEPALIVE_EVENTID: |
2706 | case WMI_10_2_GPIO_INPUT_EVENTID: | 2935 | case WMI_10_2_GPIO_INPUT_EVENTID: |
@@ -2732,45 +2961,6 @@ static void ath10k_wmi_process_rx(struct ath10k *ar, struct sk_buff *skb) | |||
2732 | } | 2961 | } |
2733 | } | 2962 | } |
2734 | 2963 | ||
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) | 2964 | int ath10k_wmi_connect(struct ath10k *ar) |
2775 | { | 2965 | { |
2776 | int status; | 2966 | int status; |
@@ -2865,42 +3055,6 @@ int ath10k_wmi_pdev_set_regdomain(struct ath10k *ar, u16 rd, u16 rd2g, | |||
2865 | ctl2g, ctl5g); | 3055 | ctl2g, ctl5g); |
2866 | } | 3056 | } |
2867 | 3057 | ||
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) | 3058 | int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt) |
2905 | { | 3059 | { |
2906 | struct wmi_pdev_suspend_cmd *cmd; | 3060 | struct wmi_pdev_suspend_cmd *cmd; |
@@ -2951,13 +3105,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); | 3105 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->pdev_set_param_cmdid); |
2952 | } | 3106 | } |
2953 | 3107 | ||
3108 | static void ath10k_wmi_put_host_mem_chunks(struct ath10k *ar, | ||
3109 | struct wmi_host_mem_chunks *chunks) | ||
3110 | { | ||
3111 | struct host_memory_chunk *chunk; | ||
3112 | int i; | ||
3113 | |||
3114 | chunks->count = __cpu_to_le32(ar->wmi.num_mem_chunks); | ||
3115 | |||
3116 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | ||
3117 | chunk = &chunks->items[i]; | ||
3118 | chunk->ptr = __cpu_to_le32(ar->wmi.mem_chunks[i].paddr); | ||
3119 | chunk->size = __cpu_to_le32(ar->wmi.mem_chunks[i].len); | ||
3120 | chunk->req_id = __cpu_to_le32(ar->wmi.mem_chunks[i].req_id); | ||
3121 | |||
3122 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
3123 | "wmi chunk %d len %d requested, addr 0x%llx\n", | ||
3124 | i, | ||
3125 | ar->wmi.mem_chunks[i].len, | ||
3126 | (unsigned long long)ar->wmi.mem_chunks[i].paddr); | ||
3127 | } | ||
3128 | } | ||
3129 | |||
2954 | static int ath10k_wmi_main_cmd_init(struct ath10k *ar) | 3130 | static int ath10k_wmi_main_cmd_init(struct ath10k *ar) |
2955 | { | 3131 | { |
2956 | struct wmi_init_cmd *cmd; | 3132 | struct wmi_init_cmd *cmd; |
2957 | struct sk_buff *buf; | 3133 | struct sk_buff *buf; |
2958 | struct wmi_resource_config config = {}; | 3134 | struct wmi_resource_config config = {}; |
2959 | u32 len, val; | 3135 | u32 len, val; |
2960 | int i; | ||
2961 | 3136 | ||
2962 | config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS); | 3137 | config.num_vdevs = __cpu_to_le32(TARGET_NUM_VDEVS); |
2963 | config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS); | 3138 | config.num_peers = __cpu_to_le32(TARGET_NUM_PEERS + TARGET_NUM_VDEVS); |
@@ -3019,32 +3194,8 @@ static int ath10k_wmi_main_cmd_init(struct ath10k *ar) | |||
3019 | 3194 | ||
3020 | cmd = (struct wmi_init_cmd *)buf->data; | 3195 | cmd = (struct wmi_init_cmd *)buf->data; |
3021 | 3196 | ||
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)); | 3197 | memcpy(&cmd->resource_config, &config, sizeof(config)); |
3198 | ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks); | ||
3048 | 3199 | ||
3049 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init\n"); | 3200 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init\n"); |
3050 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); | 3201 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); |
@@ -3056,7 +3207,6 @@ static int ath10k_wmi_10x_cmd_init(struct ath10k *ar) | |||
3056 | struct sk_buff *buf; | 3207 | struct sk_buff *buf; |
3057 | struct wmi_resource_config_10x config = {}; | 3208 | struct wmi_resource_config_10x config = {}; |
3058 | u32 len, val; | 3209 | u32 len, val; |
3059 | int i; | ||
3060 | 3210 | ||
3061 | config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); | 3211 | config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); |
3062 | config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); | 3212 | config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); |
@@ -3110,32 +3260,8 @@ static int ath10k_wmi_10x_cmd_init(struct ath10k *ar) | |||
3110 | 3260 | ||
3111 | cmd = (struct wmi_init_cmd_10x *)buf->data; | 3261 | cmd = (struct wmi_init_cmd_10x *)buf->data; |
3112 | 3262 | ||
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)); | 3263 | memcpy(&cmd->resource_config, &config, sizeof(config)); |
3264 | ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks); | ||
3139 | 3265 | ||
3140 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10x\n"); | 3266 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10x\n"); |
3141 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); | 3267 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); |
@@ -3147,7 +3273,6 @@ static int ath10k_wmi_10_2_cmd_init(struct ath10k *ar) | |||
3147 | struct sk_buff *buf; | 3273 | struct sk_buff *buf; |
3148 | struct wmi_resource_config_10x config = {}; | 3274 | struct wmi_resource_config_10x config = {}; |
3149 | u32 len, val; | 3275 | u32 len, val; |
3150 | int i; | ||
3151 | 3276 | ||
3152 | config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); | 3277 | config.num_vdevs = __cpu_to_le32(TARGET_10X_NUM_VDEVS); |
3153 | config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); | 3278 | config.num_peers = __cpu_to_le32(TARGET_10X_NUM_PEERS); |
@@ -3201,32 +3326,8 @@ static int ath10k_wmi_10_2_cmd_init(struct ath10k *ar) | |||
3201 | 3326 | ||
3202 | cmd = (struct wmi_init_cmd_10_2 *)buf->data; | 3327 | cmd = (struct wmi_init_cmd_10_2 *)buf->data; |
3203 | 3328 | ||
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)); | 3329 | memcpy(&cmd->resource_config.common, &config, sizeof(config)); |
3330 | ath10k_wmi_put_host_mem_chunks(ar, &cmd->mem_chunks); | ||
3230 | 3331 | ||
3231 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10.2\n"); | 3332 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi init 10.2\n"); |
3232 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); | 3333 | return ath10k_wmi_cmd_send(ar, buf, ar->wmi.cmd->init_cmdid); |
@@ -3248,52 +3349,50 @@ int ath10k_wmi_cmd_init(struct ath10k *ar) | |||
3248 | return ret; | 3349 | return ret; |
3249 | } | 3350 | } |
3250 | 3351 | ||
3251 | static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar, | 3352 | static int ath10k_wmi_start_scan_verify(const struct wmi_start_scan_arg *arg) |
3252 | const struct wmi_start_scan_arg *arg) | ||
3253 | { | 3353 | { |
3254 | int len; | 3354 | if (arg->ie_len && !arg->ie) |
3355 | return -EINVAL; | ||
3356 | if (arg->n_channels && !arg->channels) | ||
3357 | return -EINVAL; | ||
3358 | if (arg->n_ssids && !arg->ssids) | ||
3359 | return -EINVAL; | ||
3360 | if (arg->n_bssids && !arg->bssids) | ||
3361 | return -EINVAL; | ||
3255 | 3362 | ||
3256 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | 3363 | if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN) |
3257 | len = sizeof(struct wmi_start_scan_cmd_10x); | 3364 | return -EINVAL; |
3258 | else | 3365 | if (arg->n_channels > ARRAY_SIZE(arg->channels)) |
3259 | len = sizeof(struct wmi_start_scan_cmd); | 3366 | return -EINVAL; |
3367 | if (arg->n_ssids > WLAN_SCAN_PARAMS_MAX_SSID) | ||
3368 | return -EINVAL; | ||
3369 | if (arg->n_bssids > WLAN_SCAN_PARAMS_MAX_BSSID) | ||
3370 | return -EINVAL; | ||
3260 | 3371 | ||
3261 | if (arg->ie_len) { | 3372 | return 0; |
3262 | if (!arg->ie) | 3373 | } |
3263 | return -EINVAL; | ||
3264 | if (arg->ie_len > WLAN_SCAN_PARAMS_MAX_IE_LEN) | ||
3265 | return -EINVAL; | ||
3266 | 3374 | ||
3375 | static size_t | ||
3376 | ath10k_wmi_start_scan_tlvs_len(const struct wmi_start_scan_arg *arg) | ||
3377 | { | ||
3378 | int len = 0; | ||
3379 | |||
3380 | if (arg->ie_len) { | ||
3267 | len += sizeof(struct wmi_ie_data); | 3381 | len += sizeof(struct wmi_ie_data); |
3268 | len += roundup(arg->ie_len, 4); | 3382 | len += roundup(arg->ie_len, 4); |
3269 | } | 3383 | } |
3270 | 3384 | ||
3271 | if (arg->n_channels) { | 3385 | 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); | 3386 | len += sizeof(struct wmi_chan_list); |
3278 | len += sizeof(__le32) * arg->n_channels; | 3387 | len += sizeof(__le32) * arg->n_channels; |
3279 | } | 3388 | } |
3280 | 3389 | ||
3281 | if (arg->n_ssids) { | 3390 | 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); | 3391 | len += sizeof(struct wmi_ssid_list); |
3288 | len += sizeof(struct wmi_ssid) * arg->n_ssids; | 3392 | len += sizeof(struct wmi_ssid) * arg->n_ssids; |
3289 | } | 3393 | } |
3290 | 3394 | ||
3291 | if (arg->n_bssids) { | 3395 | 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); | 3396 | len += sizeof(struct wmi_bssid_list); |
3298 | len += sizeof(struct wmi_mac_addr) * arg->n_bssids; | 3397 | len += sizeof(struct wmi_mac_addr) * arg->n_bssids; |
3299 | } | 3398 | } |
@@ -3301,28 +3400,12 @@ static int ath10k_wmi_start_scan_calc_len(struct ath10k *ar, | |||
3301 | return len; | 3400 | return len; |
3302 | } | 3401 | } |
3303 | 3402 | ||
3304 | int ath10k_wmi_start_scan(struct ath10k *ar, | 3403 | static void |
3305 | const struct wmi_start_scan_arg *arg) | 3404 | ath10k_wmi_put_start_scan_common(struct wmi_start_scan_common *cmn, |
3405 | const struct wmi_start_scan_arg *arg) | ||
3306 | { | 3406 | { |
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; | 3407 | u32 scan_id; |
3314 | u32 scan_req_id; | 3408 | 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 | 3409 | ||
3327 | scan_id = WMI_HOST_SCAN_REQ_ID_PREFIX; | 3410 | scan_id = WMI_HOST_SCAN_REQ_ID_PREFIX; |
3328 | scan_id |= arg->scan_id; | 3411 | scan_id |= arg->scan_id; |
@@ -3330,35 +3413,36 @@ int ath10k_wmi_start_scan(struct ath10k *ar, | |||
3330 | scan_req_id = WMI_HOST_SCAN_REQUESTOR_ID_PREFIX; | 3413 | scan_req_id = WMI_HOST_SCAN_REQUESTOR_ID_PREFIX; |
3331 | scan_req_id |= arg->scan_req_id; | 3414 | scan_req_id |= arg->scan_req_id; |
3332 | 3415 | ||
3333 | cmd = (struct wmi_start_scan_cmd *)skb->data; | 3416 | cmn->scan_id = __cpu_to_le32(scan_id); |
3334 | cmd->scan_id = __cpu_to_le32(scan_id); | 3417 | cmn->scan_req_id = __cpu_to_le32(scan_req_id); |
3335 | cmd->scan_req_id = __cpu_to_le32(scan_req_id); | 3418 | cmn->vdev_id = __cpu_to_le32(arg->vdev_id); |
3336 | cmd->vdev_id = __cpu_to_le32(arg->vdev_id); | 3419 | cmn->scan_priority = __cpu_to_le32(arg->scan_priority); |
3337 | cmd->scan_priority = __cpu_to_le32(arg->scan_priority); | 3420 | cmn->notify_scan_events = __cpu_to_le32(arg->notify_scan_events); |
3338 | cmd->notify_scan_events = __cpu_to_le32(arg->notify_scan_events); | 3421 | cmn->dwell_time_active = __cpu_to_le32(arg->dwell_time_active); |
3339 | cmd->dwell_time_active = __cpu_to_le32(arg->dwell_time_active); | 3422 | cmn->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive); |
3340 | cmd->dwell_time_passive = __cpu_to_le32(arg->dwell_time_passive); | 3423 | cmn->min_rest_time = __cpu_to_le32(arg->min_rest_time); |
3341 | cmd->min_rest_time = __cpu_to_le32(arg->min_rest_time); | 3424 | cmn->max_rest_time = __cpu_to_le32(arg->max_rest_time); |
3342 | cmd->max_rest_time = __cpu_to_le32(arg->max_rest_time); | 3425 | cmn->repeat_probe_time = __cpu_to_le32(arg->repeat_probe_time); |
3343 | cmd->repeat_probe_time = __cpu_to_le32(arg->repeat_probe_time); | 3426 | cmn->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time); |
3344 | cmd->probe_spacing_time = __cpu_to_le32(arg->probe_spacing_time); | 3427 | cmn->idle_time = __cpu_to_le32(arg->idle_time); |
3345 | cmd->idle_time = __cpu_to_le32(arg->idle_time); | 3428 | cmn->max_scan_time = __cpu_to_le32(arg->max_scan_time); |
3346 | cmd->max_scan_time = __cpu_to_le32(arg->max_scan_time); | 3429 | cmn->probe_delay = __cpu_to_le32(arg->probe_delay); |
3347 | cmd->probe_delay = __cpu_to_le32(arg->probe_delay); | 3430 | cmn->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags); |
3348 | cmd->scan_ctrl_flags = __cpu_to_le32(arg->scan_ctrl_flags); | 3431 | } |
3349 | 3432 | ||
3350 | /* TLV list starts after fields included in the struct */ | 3433 | static void |
3351 | /* There's just one filed that differes the two start_scan | 3434 | ath10k_wmi_put_start_scan_tlvs(struct wmi_start_scan_tlvs *tlvs, |
3352 | * structures - burst_duration, which we are not using btw, | 3435 | const struct wmi_start_scan_arg *arg) |
3353 | no point to make the split here, just shift the buffer to fit with | 3436 | { |
3354 | given FW */ | 3437 | struct wmi_ie_data *ie; |
3355 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | 3438 | struct wmi_chan_list *channels; |
3356 | off = sizeof(struct wmi_start_scan_cmd_10x); | 3439 | struct wmi_ssid_list *ssids; |
3357 | else | 3440 | struct wmi_bssid_list *bssids; |
3358 | off = sizeof(struct wmi_start_scan_cmd); | 3441 | void *ptr = tlvs->tlvs; |
3442 | int i; | ||
3359 | 3443 | ||
3360 | if (arg->n_channels) { | 3444 | if (arg->n_channels) { |
3361 | channels = (void *)skb->data + off; | 3445 | channels = ptr; |
3362 | channels->tag = __cpu_to_le32(WMI_CHAN_LIST_TAG); | 3446 | channels->tag = __cpu_to_le32(WMI_CHAN_LIST_TAG); |
3363 | channels->num_chan = __cpu_to_le32(arg->n_channels); | 3447 | channels->num_chan = __cpu_to_le32(arg->n_channels); |
3364 | 3448 | ||
@@ -3366,12 +3450,12 @@ int ath10k_wmi_start_scan(struct ath10k *ar, | |||
3366 | channels->channel_list[i].freq = | 3450 | channels->channel_list[i].freq = |
3367 | __cpu_to_le16(arg->channels[i]); | 3451 | __cpu_to_le16(arg->channels[i]); |
3368 | 3452 | ||
3369 | off += sizeof(*channels); | 3453 | ptr += sizeof(*channels); |
3370 | off += sizeof(__le32) * arg->n_channels; | 3454 | ptr += sizeof(__le32) * arg->n_channels; |
3371 | } | 3455 | } |
3372 | 3456 | ||
3373 | if (arg->n_ssids) { | 3457 | if (arg->n_ssids) { |
3374 | ssids = (void *)skb->data + off; | 3458 | ssids = ptr; |
3375 | ssids->tag = __cpu_to_le32(WMI_SSID_LIST_TAG); | 3459 | ssids->tag = __cpu_to_le32(WMI_SSID_LIST_TAG); |
3376 | ssids->num_ssids = __cpu_to_le32(arg->n_ssids); | 3460 | ssids->num_ssids = __cpu_to_le32(arg->n_ssids); |
3377 | 3461 | ||
@@ -3383,12 +3467,12 @@ int ath10k_wmi_start_scan(struct ath10k *ar, | |||
3383 | arg->ssids[i].len); | 3467 | arg->ssids[i].len); |
3384 | } | 3468 | } |
3385 | 3469 | ||
3386 | off += sizeof(*ssids); | 3470 | ptr += sizeof(*ssids); |
3387 | off += sizeof(struct wmi_ssid) * arg->n_ssids; | 3471 | ptr += sizeof(struct wmi_ssid) * arg->n_ssids; |
3388 | } | 3472 | } |
3389 | 3473 | ||
3390 | if (arg->n_bssids) { | 3474 | if (arg->n_bssids) { |
3391 | bssids = (void *)skb->data + off; | 3475 | bssids = ptr; |
3392 | bssids->tag = __cpu_to_le32(WMI_BSSID_LIST_TAG); | 3476 | bssids->tag = __cpu_to_le32(WMI_BSSID_LIST_TAG); |
3393 | bssids->num_bssid = __cpu_to_le32(arg->n_bssids); | 3477 | bssids->num_bssid = __cpu_to_le32(arg->n_bssids); |
3394 | 3478 | ||
@@ -3397,23 +3481,57 @@ int ath10k_wmi_start_scan(struct ath10k *ar, | |||
3397 | arg->bssids[i].bssid, | 3481 | arg->bssids[i].bssid, |
3398 | ETH_ALEN); | 3482 | ETH_ALEN); |
3399 | 3483 | ||
3400 | off += sizeof(*bssids); | 3484 | ptr += sizeof(*bssids); |
3401 | off += sizeof(struct wmi_mac_addr) * arg->n_bssids; | 3485 | ptr += sizeof(struct wmi_mac_addr) * arg->n_bssids; |
3402 | } | 3486 | } |
3403 | 3487 | ||
3404 | if (arg->ie_len) { | 3488 | if (arg->ie_len) { |
3405 | ie = (void *)skb->data + off; | 3489 | ie = ptr; |
3406 | ie->tag = __cpu_to_le32(WMI_IE_TAG); | 3490 | ie->tag = __cpu_to_le32(WMI_IE_TAG); |
3407 | ie->ie_len = __cpu_to_le32(arg->ie_len); | 3491 | ie->ie_len = __cpu_to_le32(arg->ie_len); |
3408 | memcpy(ie->ie_data, arg->ie, arg->ie_len); | 3492 | memcpy(ie->ie_data, arg->ie, arg->ie_len); |
3409 | 3493 | ||
3410 | off += sizeof(*ie); | 3494 | ptr += sizeof(*ie); |
3411 | off += roundup(arg->ie_len, 4); | 3495 | ptr += roundup(arg->ie_len, 4); |
3412 | } | 3496 | } |
3497 | } | ||
3413 | 3498 | ||
3414 | if (off != skb->len) { | 3499 | int ath10k_wmi_start_scan(struct ath10k *ar, |
3415 | dev_kfree_skb(skb); | 3500 | const struct wmi_start_scan_arg *arg) |
3416 | return -EINVAL; | 3501 | { |
3502 | struct sk_buff *skb; | ||
3503 | size_t len; | ||
3504 | int ret; | ||
3505 | |||
3506 | ret = ath10k_wmi_start_scan_verify(arg); | ||
3507 | if (ret) | ||
3508 | return ret; | ||
3509 | |||
3510 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) | ||
3511 | len = sizeof(struct wmi_10x_start_scan_cmd) + | ||
3512 | ath10k_wmi_start_scan_tlvs_len(arg); | ||
3513 | else | ||
3514 | len = sizeof(struct wmi_start_scan_cmd) + | ||
3515 | ath10k_wmi_start_scan_tlvs_len(arg); | ||
3516 | |||
3517 | skb = ath10k_wmi_alloc_skb(ar, len); | ||
3518 | if (!skb) | ||
3519 | return -ENOMEM; | ||
3520 | |||
3521 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { | ||
3522 | struct wmi_10x_start_scan_cmd *cmd; | ||
3523 | |||
3524 | cmd = (struct wmi_10x_start_scan_cmd *)skb->data; | ||
3525 | ath10k_wmi_put_start_scan_common(&cmd->common, arg); | ||
3526 | ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg); | ||
3527 | } else { | ||
3528 | struct wmi_start_scan_cmd *cmd; | ||
3529 | |||
3530 | cmd = (struct wmi_start_scan_cmd *)skb->data; | ||
3531 | cmd->burst_duration_ms = __cpu_to_le32(0); | ||
3532 | |||
3533 | ath10k_wmi_put_start_scan_common(&cmd->common, arg); | ||
3534 | ath10k_wmi_put_start_scan_tlvs(&cmd->tlvs, arg); | ||
3417 | } | 3535 | } |
3418 | 3536 | ||
3419 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi start scan\n"); | 3537 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi start scan\n"); |
@@ -3532,7 +3650,6 @@ ath10k_wmi_vdev_start_restart(struct ath10k *ar, | |||
3532 | struct sk_buff *skb; | 3650 | struct sk_buff *skb; |
3533 | const char *cmdname; | 3651 | const char *cmdname; |
3534 | u32 flags = 0; | 3652 | u32 flags = 0; |
3535 | u32 ch_flags = 0; | ||
3536 | 3653 | ||
3537 | if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid && | 3654 | if (cmd_id != ar->wmi.cmd->vdev_start_request_cmdid && |
3538 | cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid) | 3655 | cmd_id != ar->wmi.cmd->vdev_restart_request_cmdid) |
@@ -3559,8 +3676,6 @@ ath10k_wmi_vdev_start_restart(struct ath10k *ar, | |||
3559 | flags |= WMI_VDEV_START_HIDDEN_SSID; | 3676 | flags |= WMI_VDEV_START_HIDDEN_SSID; |
3560 | if (arg->pmf_enabled) | 3677 | if (arg->pmf_enabled) |
3561 | flags |= WMI_VDEV_START_PMF_ENABLED; | 3678 | flags |= WMI_VDEV_START_PMF_ENABLED; |
3562 | if (arg->channel.chan_radar) | ||
3563 | ch_flags |= WMI_CHAN_FLAG_DFS; | ||
3564 | 3679 | ||
3565 | cmd = (struct wmi_vdev_start_request_cmd *)skb->data; | 3680 | cmd = (struct wmi_vdev_start_request_cmd *)skb->data; |
3566 | cmd->vdev_id = __cpu_to_le32(arg->vdev_id); | 3681 | cmd->vdev_id = __cpu_to_le32(arg->vdev_id); |
@@ -3576,18 +3691,7 @@ ath10k_wmi_vdev_start_restart(struct ath10k *ar, | |||
3576 | memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len); | 3691 | memcpy(cmd->ssid.ssid, arg->ssid, arg->ssid_len); |
3577 | } | 3692 | } |
3578 | 3693 | ||
3579 | cmd->chan.mhz = __cpu_to_le32(arg->channel.freq); | 3694 | 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 | 3695 | ||
3592 | ath10k_dbg(ar, ATH10K_DBG_WMI, | 3696 | 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", | 3697 | "wmi vdev %s id 0x%x flags: 0x%0X, freq %d, mode %d, ch_flags: 0x%0X, max_power: %d\n", |
@@ -3968,35 +4072,10 @@ int ath10k_wmi_scan_chan_list(struct ath10k *ar, | |||
3968 | cmd->num_scan_chans = __cpu_to_le32(arg->n_channels); | 4072 | cmd->num_scan_chans = __cpu_to_le32(arg->n_channels); |
3969 | 4073 | ||
3970 | for (i = 0; i < arg->n_channels; i++) { | 4074 | for (i = 0; i < arg->n_channels; i++) { |
3971 | u32 flags = 0; | ||
3972 | |||
3973 | ch = &arg->channels[i]; | 4075 | ch = &arg->channels[i]; |
3974 | ci = &cmd->chan_info[i]; | 4076 | ci = &cmd->chan_info[i]; |
3975 | 4077 | ||
3976 | if (ch->passive) | 4078 | 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 | } | 4079 | } |
4001 | 4080 | ||
4002 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid); | 4081 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->scan_chan_list_cmdid); |
@@ -4267,3 +4346,74 @@ int ath10k_wmi_dbglog_cfg(struct ath10k *ar, u32 module_enable) | |||
4267 | 4346 | ||
4268 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->dbglog_cfg_cmdid); | 4347 | return ath10k_wmi_cmd_send(ar, skb, ar->wmi.cmd->dbglog_cfg_cmdid); |
4269 | } | 4348 | } |
4349 | |||
4350 | int ath10k_wmi_pdev_pktlog_enable(struct ath10k *ar, u32 ev_bitmap) | ||
4351 | { | ||
4352 | struct wmi_pdev_pktlog_enable_cmd *cmd; | ||
4353 | struct sk_buff *skb; | ||
4354 | |||
4355 | skb = ath10k_wmi_alloc_skb(ar, sizeof(*cmd)); | ||
4356 | if (!skb) | ||
4357 | return -ENOMEM; | ||
4358 | |||
4359 | ev_bitmap &= ATH10K_PKTLOG_ANY; | ||
4360 | ath10k_dbg(ar, ATH10K_DBG_WMI, | ||
4361 | "wmi enable pktlog filter:%x\n", ev_bitmap); | ||
4362 | |||
4363 | cmd = (struct wmi_pdev_pktlog_enable_cmd *)skb->data; | ||
4364 | cmd->ev_bitmap = __cpu_to_le32(ev_bitmap); | ||
4365 | return ath10k_wmi_cmd_send(ar, skb, | ||
4366 | ar->wmi.cmd->pdev_pktlog_enable_cmdid); | ||
4367 | } | ||
4368 | |||
4369 | int ath10k_wmi_pdev_pktlog_disable(struct ath10k *ar) | ||
4370 | { | ||
4371 | struct sk_buff *skb; | ||
4372 | |||
4373 | skb = ath10k_wmi_alloc_skb(ar, 0); | ||
4374 | if (!skb) | ||
4375 | return -ENOMEM; | ||
4376 | |||
4377 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi disable pktlog\n"); | ||
4378 | |||
4379 | return ath10k_wmi_cmd_send(ar, skb, | ||
4380 | ar->wmi.cmd->pdev_pktlog_disable_cmdid); | ||
4381 | } | ||
4382 | |||
4383 | int ath10k_wmi_attach(struct ath10k *ar) | ||
4384 | { | ||
4385 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { | ||
4386 | if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features)) | ||
4387 | ar->wmi.cmd = &wmi_10_2_cmd_map; | ||
4388 | else | ||
4389 | ar->wmi.cmd = &wmi_10x_cmd_map; | ||
4390 | |||
4391 | ar->wmi.vdev_param = &wmi_10x_vdev_param_map; | ||
4392 | ar->wmi.pdev_param = &wmi_10x_pdev_param_map; | ||
4393 | } else { | ||
4394 | ar->wmi.cmd = &wmi_cmd_map; | ||
4395 | ar->wmi.vdev_param = &wmi_vdev_param_map; | ||
4396 | ar->wmi.pdev_param = &wmi_pdev_param_map; | ||
4397 | } | ||
4398 | |||
4399 | init_completion(&ar->wmi.service_ready); | ||
4400 | init_completion(&ar->wmi.unified_ready); | ||
4401 | init_waitqueue_head(&ar->wmi.tx_credits_wq); | ||
4402 | |||
4403 | return 0; | ||
4404 | } | ||
4405 | |||
4406 | void ath10k_wmi_detach(struct ath10k *ar) | ||
4407 | { | ||
4408 | int i; | ||
4409 | |||
4410 | /* free the host memory chunks requested by firmware */ | ||
4411 | for (i = 0; i < ar->wmi.num_mem_chunks; i++) { | ||
4412 | dma_free_coherent(ar->dev, | ||
4413 | ar->wmi.mem_chunks[i].len, | ||
4414 | ar->wmi.mem_chunks[i].vaddr, | ||
4415 | ar->wmi.mem_chunks[i].paddr); | ||
4416 | } | ||
4417 | |||
4418 | ar->wmi.num_mem_chunks = 0; | ||
4419 | } | ||
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/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/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig index 896e63281b3b..ca101d7cb99f 100644 --- a/drivers/net/wireless/ath/ath9k/Kconfig +++ b/drivers/net/wireless/ath/ath9k/Kconfig | |||
@@ -148,6 +148,11 @@ config ATH9K_CHANNEL_CONTEXT | |||
148 | for multi-channel concurrency. Enable this if P2P PowerSave support | 148 | for multi-channel concurrency. Enable this if P2P PowerSave support |
149 | is required. | 149 | is required. |
150 | 150 | ||
151 | config ATH9K_PCOEM | ||
152 | bool "Atheros ath9k support for PC OEM cards" if EXPERT | ||
153 | depends on ATH9K | ||
154 | default y | ||
155 | |||
151 | config ATH9K_HTC | 156 | config ATH9K_HTC |
152 | tristate "Atheros HTC based wireless cards support" | 157 | tristate "Atheros HTC based wireless cards support" |
153 | depends on USB && MAC80211 | 158 | depends on USB && MAC80211 |
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile index 73704c1be736..22b934b07bd4 100644 --- a/drivers/net/wireless/ath/ath9k/Makefile +++ b/drivers/net/wireless/ath/ath9k/Makefile | |||
@@ -32,7 +32,6 @@ ath9k_hw-y:= \ | |||
32 | ar5008_phy.o \ | 32 | ar5008_phy.o \ |
33 | ar9002_calib.o \ | 33 | ar9002_calib.o \ |
34 | ar9003_calib.o \ | 34 | ar9003_calib.o \ |
35 | ar9003_rtt.o \ | ||
36 | calib.o \ | 35 | calib.o \ |
37 | eeprom.o \ | 36 | eeprom.o \ |
38 | eeprom_def.o \ | 37 | eeprom_def.o \ |
@@ -50,6 +49,8 @@ ath9k_hw-$(CONFIG_ATH9K_WOW) += ar9003_wow.o | |||
50 | ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \ | 49 | ath9k_hw-$(CONFIG_ATH9K_BTCOEX_SUPPORT) += btcoex.o \ |
51 | ar9003_mci.o | 50 | ar9003_mci.o |
52 | 51 | ||
52 | ath9k_hw-$(CONFIG_ATH9K_PCOEM) += ar9003_rtt.o | ||
53 | |||
53 | ath9k_hw-$(CONFIG_ATH9K_DYNACK) += dynack.o | 54 | ath9k_hw-$(CONFIG_ATH9K_DYNACK) += dynack.o |
54 | 55 | ||
55 | obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o | 56 | obj-$(CONFIG_ATH9K_HW) += ath9k_hw.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/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_hw.c b/drivers/net/wireless/ath/ath9k/ar9003_hw.c index ddef9eedbac6..cb09102245b2 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_hw.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_hw.c | |||
@@ -670,9 +670,6 @@ static void ar9003_tx_gain_table_mode5(struct ath_hw *ah) | |||
670 | if (AR_SREV_9485_11_OR_LATER(ah)) | 670 | if (AR_SREV_9485_11_OR_LATER(ah)) |
671 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 671 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
672 | ar9485Modes_green_ob_db_tx_gain_1_1); | 672 | 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)) | 673 | else if (AR_SREV_9580(ah)) |
677 | INIT_INI_ARRAY(&ah->iniModesTxGain, | 674 | INIT_INI_ARRAY(&ah->iniModesTxGain, |
678 | ar9580_1p0_type5_tx_gain_table); | 675 | ar9580_1p0_type5_tx_gain_table); |
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c index 697c4ae90af0..9bdaa0afc37f 100644 --- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c +++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c | |||
@@ -1348,7 +1348,7 @@ static void ar9003_hw_set_radar_params(struct ath_hw *ah, | |||
1348 | struct ath_hw_radar_conf *conf) | 1348 | struct ath_hw_radar_conf *conf) |
1349 | { | 1349 | { |
1350 | unsigned int regWrites = 0; | 1350 | unsigned int regWrites = 0; |
1351 | u32 radar_0 = 0, radar_1 = 0; | 1351 | u32 radar_0 = 0, radar_1; |
1352 | 1352 | ||
1353 | if (!conf) { | 1353 | if (!conf) { |
1354 | REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); | 1354 | REG_CLR_BIT(ah, AR_PHY_RADAR_0, AR_PHY_RADAR_0_ENA); |
@@ -1362,6 +1362,9 @@ static void ar9003_hw_set_radar_params(struct ath_hw *ah, | |||
1362 | radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI); | 1362 | radar_0 |= SM(conf->pulse_rssi, AR_PHY_RADAR_0_PRSSI); |
1363 | radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND); | 1363 | radar_0 |= SM(conf->pulse_inband, AR_PHY_RADAR_0_INBAND); |
1364 | 1364 | ||
1365 | radar_1 = REG_READ(ah, AR_PHY_RADAR_1); | ||
1366 | radar_1 &= ~(AR_PHY_RADAR_1_MAXLEN | AR_PHY_RADAR_1_RELSTEP_THRESH | | ||
1367 | AR_PHY_RADAR_1_RELPWR_THRESH); | ||
1365 | radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI; | 1368 | radar_1 |= AR_PHY_RADAR_1_MAX_RRSSI; |
1366 | radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK; | 1369 | radar_1 |= AR_PHY_RADAR_1_BLOCK_CHECK; |
1367 | radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN); | 1370 | radar_1 |= SM(conf->pulse_maxlen, AR_PHY_RADAR_1_MAXLEN); |
@@ -1388,7 +1391,7 @@ static void ar9003_hw_set_radar_conf(struct ath_hw *ah) | |||
1388 | conf->fir_power = -28; | 1391 | conf->fir_power = -28; |
1389 | conf->radar_rssi = 0; | 1392 | conf->radar_rssi = 0; |
1390 | conf->pulse_height = 10; | 1393 | conf->pulse_height = 10; |
1391 | conf->pulse_rssi = 24; | 1394 | conf->pulse_rssi = 15; |
1392 | conf->pulse_inband = 8; | 1395 | conf->pulse_inband = 8; |
1393 | conf->pulse_maxlen = 255; | 1396 | conf->pulse_maxlen = 255; |
1394 | conf->pulse_inband_step = 12; | 1397 | 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/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 01a7db061c6a..85d74ff0767c 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -345,6 +345,7 @@ struct ath_chanctx { | |||
345 | u64 tsf_val; | 345 | u64 tsf_val; |
346 | u32 last_beacon; | 346 | u32 last_beacon; |
347 | 347 | ||
348 | int flush_timeout; | ||
348 | u16 txpower; | 349 | u16 txpower; |
349 | bool offchannel; | 350 | bool offchannel; |
350 | bool stopped; | 351 | bool stopped; |
@@ -362,7 +363,7 @@ enum ath_chanctx_event { | |||
362 | ATH_CHANCTX_EVENT_BEACON_SENT, | 363 | ATH_CHANCTX_EVENT_BEACON_SENT, |
363 | ATH_CHANCTX_EVENT_TSF_TIMER, | 364 | ATH_CHANCTX_EVENT_TSF_TIMER, |
364 | ATH_CHANCTX_EVENT_BEACON_RECEIVED, | 365 | ATH_CHANCTX_EVENT_BEACON_RECEIVED, |
365 | ATH_CHANCTX_EVENT_ASSOC, | 366 | ATH_CHANCTX_EVENT_AUTHORIZED, |
366 | ATH_CHANCTX_EVENT_SWITCH, | 367 | ATH_CHANCTX_EVENT_SWITCH, |
367 | ATH_CHANCTX_EVENT_ASSIGN, | 368 | ATH_CHANCTX_EVENT_ASSIGN, |
368 | ATH_CHANCTX_EVENT_UNASSIGN, | 369 | ATH_CHANCTX_EVENT_UNASSIGN, |
@@ -384,6 +385,7 @@ struct ath_chanctx_sched { | |||
384 | bool wait_switch; | 385 | bool wait_switch; |
385 | bool force_noa_update; | 386 | bool force_noa_update; |
386 | bool extend_absence; | 387 | bool extend_absence; |
388 | bool mgd_prepare_tx; | ||
387 | enum ath_chanctx_state state; | 389 | enum ath_chanctx_state state; |
388 | u8 beacon_miss; | 390 | u8 beacon_miss; |
389 | 391 | ||
@@ -468,6 +470,7 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force); | |||
468 | void ath_offchannel_next(struct ath_softc *sc); | 470 | void ath_offchannel_next(struct ath_softc *sc); |
469 | void ath_scan_complete(struct ath_softc *sc, bool abort); | 471 | void ath_scan_complete(struct ath_softc *sc, bool abort); |
470 | void ath_roc_complete(struct ath_softc *sc, bool abort); | 472 | void ath_roc_complete(struct ath_softc *sc, bool abort); |
473 | struct ath_chanctx* ath_is_go_chanctx_present(struct ath_softc *sc); | ||
471 | 474 | ||
472 | #else | 475 | #else |
473 | 476 | ||
@@ -540,7 +543,6 @@ static inline void ath_chanctx_check_active(struct ath_softc *sc, | |||
540 | 543 | ||
541 | #endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */ | 544 | #endif /* CONFIG_ATH9K_CHANNEL_CONTEXT */ |
542 | 545 | ||
543 | int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan); | ||
544 | void ath_startrecv(struct ath_softc *sc); | 546 | void ath_startrecv(struct ath_softc *sc); |
545 | bool ath_stoprecv(struct ath_softc *sc); | 547 | bool ath_stoprecv(struct ath_softc *sc); |
546 | u32 ath_calcrxfilter(struct ath_softc *sc); | 548 | u32 ath_calcrxfilter(struct ath_softc *sc); |
@@ -595,7 +597,7 @@ struct ath_vif { | |||
595 | u16 seq_no; | 597 | u16 seq_no; |
596 | 598 | ||
597 | /* BSS info */ | 599 | /* BSS info */ |
598 | u8 bssid[ETH_ALEN]; | 600 | u8 bssid[ETH_ALEN] __aligned(2); |
599 | u16 aid; | 601 | u16 aid; |
600 | bool assoc; | 602 | bool assoc; |
601 | 603 | ||
@@ -618,6 +620,7 @@ struct ath_vif { | |||
618 | u32 noa_start; | 620 | u32 noa_start; |
619 | u32 noa_duration; | 621 | u32 noa_duration; |
620 | bool periodic_noa; | 622 | bool periodic_noa; |
623 | bool oneshot_noa; | ||
621 | }; | 624 | }; |
622 | 625 | ||
623 | struct ath9k_vif_iter_data { | 626 | struct ath9k_vif_iter_data { |
@@ -715,7 +718,8 @@ int ath_update_survey_stats(struct ath_softc *sc); | |||
715 | void ath_update_survey_nf(struct ath_softc *sc, int channel); | 718 | void ath_update_survey_nf(struct ath_softc *sc, int channel); |
716 | void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type); | 719 | void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type); |
717 | void ath_ps_full_sleep(unsigned long data); | 720 | void ath_ps_full_sleep(unsigned long data); |
718 | void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop); | 721 | void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop, |
722 | bool sw_pending, bool timeout_override); | ||
719 | 723 | ||
720 | /**********/ | 724 | /**********/ |
721 | /* BTCOEX */ | 725 | /* BTCOEX */ |
@@ -975,6 +979,7 @@ struct ath_softc { | |||
975 | struct ath_chanctx_sched sched; | 979 | struct ath_chanctx_sched sched; |
976 | struct ath_offchannel offchannel; | 980 | struct ath_offchannel offchannel; |
977 | struct ath_chanctx *next_chan; | 981 | struct ath_chanctx *next_chan; |
982 | struct completion go_beacon; | ||
978 | #endif | 983 | #endif |
979 | 984 | ||
980 | unsigned long driver_data; | 985 | unsigned long driver_data; |
@@ -1069,7 +1074,7 @@ void ath9k_tasklet(unsigned long data); | |||
1069 | int ath_cabq_update(struct ath_softc *); | 1074 | int ath_cabq_update(struct ath_softc *); |
1070 | u8 ath9k_parse_mpdudensity(u8 mpdudensity); | 1075 | u8 ath9k_parse_mpdudensity(u8 mpdudensity); |
1071 | irqreturn_t ath_isr(int irq, void *dev); | 1076 | irqreturn_t ath_isr(int irq, void *dev); |
1072 | int ath_reset(struct ath_softc *sc); | 1077 | int ath_reset(struct ath_softc *sc, struct ath9k_channel *hchan); |
1073 | void ath_cancel_work(struct ath_softc *sc); | 1078 | void ath_cancel_work(struct ath_softc *sc); |
1074 | void ath_restart_work(struct ath_softc *sc); | 1079 | void ath_restart_work(struct ath_softc *sc); |
1075 | int ath9k_init_device(u16 devid, struct ath_softc *sc, | 1080 | int ath9k_init_device(u16 devid, struct ath_softc *sc, |
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..c7234d5dda34 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 | ||
@@ -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,15 @@ 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->cur_chan->tsf_val) | ||
663 | break; | ||
664 | |||
665 | ath_chanctx_adjust_tbtt_delta(sc); | ||
666 | |||
502 | /* TSF time might have been updated by the incoming beacon, | 667 | /* TSF time might have been updated by the incoming beacon, |
503 | * need update the channel switch timer to reflect the change. | 668 | * need update the channel switch timer to reflect the change. |
504 | */ | 669 | */ |
@@ -510,7 +675,7 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
510 | 675 | ||
511 | ath_chanctx_setup_timer(sc, tsf_time); | 676 | ath_chanctx_setup_timer(sc, tsf_time); |
512 | break; | 677 | break; |
513 | case ATH_CHANCTX_EVENT_ASSOC: | 678 | case ATH_CHANCTX_EVENT_AUTHORIZED: |
514 | if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE || | 679 | if (sc->sched.state != ATH_CHANCTX_STATE_FORCE_ACTIVE || |
515 | avp->chanctx != sc->cur_chan) | 680 | avp->chanctx != sc->cur_chan) |
516 | break; | 681 | break; |
@@ -578,22 +743,6 @@ void ath_chanctx_event(struct ath_softc *sc, struct ieee80211_vif *vif, | |||
578 | ieee80211_queue_work(sc->hw, &sc->chanctx_work); | 743 | ieee80211_queue_work(sc->hw, &sc->chanctx_work); |
579 | break; | 744 | break; |
580 | case ATH_CHANCTX_EVENT_ASSIGN: | 745 | 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; | 746 | break; |
598 | case ATH_CHANCTX_EVENT_CHANGE: | 747 | case ATH_CHANCTX_EVENT_CHANGE: |
599 | break; | 748 | break; |
@@ -770,7 +919,7 @@ void ath_roc_complete(struct ath_softc *sc, bool abort) | |||
770 | 919 | ||
771 | sc->offchannel.roc_vif = NULL; | 920 | sc->offchannel.roc_vif = NULL; |
772 | sc->offchannel.roc_chan = NULL; | 921 | sc->offchannel.roc_chan = NULL; |
773 | if (!abort) | 922 | if (abort) |
774 | ieee80211_remain_on_channel_expired(sc->hw); | 923 | ieee80211_remain_on_channel_expired(sc->hw); |
775 | ath_offchannel_next(sc); | 924 | ath_offchannel_next(sc); |
776 | ath9k_ps_restore(sc); | 925 | ath9k_ps_restore(sc); |
@@ -904,6 +1053,7 @@ static void ath_offchannel_timer(unsigned long data) | |||
904 | case ATH_OFFCHANNEL_ROC_WAIT: | 1053 | case ATH_OFFCHANNEL_ROC_WAIT: |
905 | ctx = ath_chanctx_get_oper_chan(sc, false); | 1054 | ctx = ath_chanctx_get_oper_chan(sc, false); |
906 | sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE; | 1055 | sc->offchannel.state = ATH_OFFCHANNEL_ROC_DONE; |
1056 | ieee80211_remain_on_channel_expired(sc->hw); | ||
907 | ath_chanctx_switch(sc, ctx, NULL); | 1057 | ath_chanctx_switch(sc, ctx, NULL); |
908 | break; | 1058 | break; |
909 | default: | 1059 | default: |
@@ -1082,10 +1232,11 @@ void ath_chanctx_set_next(struct ath_softc *sc, bool force) | |||
1082 | ath9k_chanctx_stop_queues(sc, sc->cur_chan); | 1232 | ath9k_chanctx_stop_queues(sc, sc->cur_chan); |
1083 | queues_stopped = true; | 1233 | queues_stopped = true; |
1084 | 1234 | ||
1085 | __ath9k_flush(sc->hw, ~0, true); | 1235 | __ath9k_flush(sc->hw, ~0, true, false, false); |
1086 | 1236 | ||
1087 | if (ath_chanctx_send_ps_frame(sc, true)) | 1237 | if (ath_chanctx_send_ps_frame(sc, true)) |
1088 | __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), false); | 1238 | __ath9k_flush(sc->hw, BIT(IEEE80211_AC_VO), |
1239 | false, false, false); | ||
1089 | 1240 | ||
1090 | send_ps = true; | 1241 | send_ps = true; |
1091 | spin_lock_bh(&sc->chan_lock); | 1242 | spin_lock_bh(&sc->chan_lock); |
@@ -1177,6 +1328,8 @@ void ath9k_init_channel_context(struct ath_softc *sc) | |||
1177 | (unsigned long)sc); | 1328 | (unsigned long)sc); |
1178 | setup_timer(&sc->sched.timer, ath_chanctx_timer, | 1329 | setup_timer(&sc->sched.timer, ath_chanctx_timer, |
1179 | (unsigned long)sc); | 1330 | (unsigned long)sc); |
1331 | |||
1332 | init_completion(&sc->go_beacon); | ||
1180 | } | 1333 | } |
1181 | 1334 | ||
1182 | void ath9k_deinit_channel_context(struct ath_softc *sc) | 1335 | void ath9k_deinit_channel_context(struct ath_softc *sc) |
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c index 5c45e787814e..c9afc15cd4d3 100644 --- a/drivers/net/wireless/ath/ath9k/debug.c +++ b/drivers/net/wireless/ath/ath9k/debug.c | |||
@@ -852,36 +852,31 @@ static ssize_t read_file_reset(struct file *file, char __user *user_buf, | |||
852 | size_t count, loff_t *ppos) | 852 | size_t count, loff_t *ppos) |
853 | { | 853 | { |
854 | struct ath_softc *sc = file->private_data; | 854 | struct ath_softc *sc = file->private_data; |
855 | static const char * const reset_cause[__RESET_TYPE_MAX] = { | ||
856 | [RESET_TYPE_BB_HANG] = "Baseband Hang", | ||
857 | [RESET_TYPE_BB_WATCHDOG] = "Baseband Watchdog", | ||
858 | [RESET_TYPE_FATAL_INT] = "Fatal HW Error", | ||
859 | [RESET_TYPE_TX_ERROR] = "TX HW error", | ||
860 | [RESET_TYPE_TX_GTT] = "Transmit timeout", | ||
861 | [RESET_TYPE_TX_HANG] = "TX Path Hang", | ||
862 | [RESET_TYPE_PLL_HANG] = "PLL RX Hang", | ||
863 | [RESET_TYPE_MAC_HANG] = "MAC Hang", | ||
864 | [RESET_TYPE_BEACON_STUCK] = "Stuck Beacon", | ||
865 | [RESET_TYPE_MCI] = "MCI Reset", | ||
866 | [RESET_TYPE_CALIBRATION] = "Calibration error", | ||
867 | }; | ||
855 | char buf[512]; | 868 | char buf[512]; |
856 | unsigned int len = 0; | 869 | unsigned int len = 0; |
870 | int i; | ||
857 | 871 | ||
858 | len += scnprintf(buf + len, sizeof(buf) - len, | 872 | for (i = 0; i < ARRAY_SIZE(reset_cause); i++) { |
859 | "%17s: %2d\n", "Baseband Hang", | 873 | if (!reset_cause[i]) |
860 | sc->debug.stats.reset[RESET_TYPE_BB_HANG]); | 874 | continue; |
861 | len += scnprintf(buf + len, sizeof(buf) - len, | 875 | |
862 | "%17s: %2d\n", "Baseband Watchdog", | 876 | len += scnprintf(buf + len, sizeof(buf) - len, |
863 | sc->debug.stats.reset[RESET_TYPE_BB_WATCHDOG]); | 877 | "%17s: %2d\n", reset_cause[i], |
864 | len += scnprintf(buf + len, sizeof(buf) - len, | 878 | sc->debug.stats.reset[i]); |
865 | "%17s: %2d\n", "Fatal HW Error", | 879 | } |
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 | 880 | ||
886 | if (len > sizeof(buf)) | 881 | if (len > sizeof(buf)) |
887 | len = sizeof(buf); | 882 | len = sizeof(buf); |
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/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..ee9fb52cec62 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 | } |
@@ -1953,8 +1962,10 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, | |||
1953 | if (ath9k_hw_mci_is_enabled(ah)) | 1962 | if (ath9k_hw_mci_is_enabled(ah)) |
1954 | ar9003_mci_check_bt(ah); | 1963 | ar9003_mci_check_bt(ah); |
1955 | 1964 | ||
1956 | ath9k_hw_loadnf(ah, chan); | 1965 | if (AR_SREV_9300_20_OR_LATER(ah)) { |
1957 | ath9k_hw_start_nfcal(ah, true); | 1966 | ath9k_hw_loadnf(ah, chan); |
1967 | ath9k_hw_start_nfcal(ah, true); | ||
1968 | } | ||
1958 | 1969 | ||
1959 | if (AR_SREV_9300_20_OR_LATER(ah)) | 1970 | if (AR_SREV_9300_20_OR_LATER(ah)) |
1960 | ar9003_hw_bb_watchdog_config(ah); | 1971 | ar9003_hw_bb_watchdog_config(ah); |
@@ -2342,17 +2353,25 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah) | |||
2342 | } | 2353 | } |
2343 | 2354 | ||
2344 | eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); | 2355 | eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); |
2345 | if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) { | 2356 | |
2346 | ath_err(common, | 2357 | if (eeval & AR5416_OPFLAGS_11A) { |
2347 | "no band has been marked as supported in EEPROM\n"); | 2358 | if (ah->disable_5ghz) |
2348 | return -EINVAL; | 2359 | ath_warn(common, "disabling 5GHz band\n"); |
2360 | else | ||
2361 | pCap->hw_caps |= ATH9K_HW_CAP_5GHZ; | ||
2349 | } | 2362 | } |
2350 | 2363 | ||
2351 | if (eeval & AR5416_OPFLAGS_11A) | 2364 | if (eeval & AR5416_OPFLAGS_11G) { |
2352 | pCap->hw_caps |= ATH9K_HW_CAP_5GHZ; | 2365 | if (ah->disable_2ghz) |
2366 | ath_warn(common, "disabling 2GHz band\n"); | ||
2367 | else | ||
2368 | pCap->hw_caps |= ATH9K_HW_CAP_2GHZ; | ||
2369 | } | ||
2353 | 2370 | ||
2354 | if (eeval & AR5416_OPFLAGS_11G) | 2371 | if ((pCap->hw_caps & (ATH9K_HW_CAP_2GHZ | ATH9K_HW_CAP_5GHZ)) == 0) { |
2355 | pCap->hw_caps |= ATH9K_HW_CAP_2GHZ; | 2372 | ath_err(common, "both bands are disabled\n"); |
2373 | return -EINVAL; | ||
2374 | } | ||
2356 | 2375 | ||
2357 | if (AR_SREV_9485(ah) || | 2376 | if (AR_SREV_9485(ah) || |
2358 | AR_SREV_9285(ah) || | 2377 | AR_SREV_9285(ah) || |
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h index 975074fc11bc..e49721e85f6a 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 | /* |
@@ -681,10 +688,8 @@ struct ath_hw_ops { | |||
681 | bool power_off); | 688 | bool power_off); |
682 | void (*rx_enable)(struct ath_hw *ah); | 689 | void (*rx_enable)(struct ath_hw *ah); |
683 | void (*set_desc_link)(void *ds, u32 link); | 690 | void (*set_desc_link)(void *ds, u32 link); |
684 | bool (*calibrate)(struct ath_hw *ah, | 691 | int (*calibrate)(struct ath_hw *ah, struct ath9k_channel *chan, |
685 | struct ath9k_channel *chan, | 692 | u8 rxchainmask, bool longcal); |
686 | u8 rxchainmask, | ||
687 | bool longcal); | ||
688 | bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked, | 693 | bool (*get_isr)(struct ath_hw *ah, enum ath9k_int *masked, |
689 | u32 *sync_cause_p); | 694 | u32 *sync_cause_p); |
690 | void (*set_txdesc)(struct ath_hw *ah, void *ds, | 695 | void (*set_txdesc)(struct ath_hw *ah, void *ds, |
@@ -726,6 +731,7 @@ enum ath_cal_list { | |||
726 | #define AH_USE_EEPROM 0x1 | 731 | #define AH_USE_EEPROM 0x1 |
727 | #define AH_UNPLUGGED 0x2 /* The card has been physically removed. */ | 732 | #define AH_UNPLUGGED 0x2 /* The card has been physically removed. */ |
728 | #define AH_FASTCC 0x4 | 733 | #define AH_FASTCC 0x4 |
734 | #define AH_NO_EEP_SWAP 0x8 /* Do not swap EEPROM data */ | ||
729 | 735 | ||
730 | struct ath_hw { | 736 | struct ath_hw { |
731 | struct ath_ops reg_ops; | 737 | struct ath_ops reg_ops; |
@@ -924,6 +930,8 @@ struct ath_hw { | |||
924 | bool is_clk_25mhz; | 930 | bool is_clk_25mhz; |
925 | int (*get_mac_revision)(void); | 931 | int (*get_mac_revision)(void); |
926 | int (*external_reset)(void); | 932 | int (*external_reset)(void); |
933 | bool disable_2ghz; | ||
934 | bool disable_5ghz; | ||
927 | 935 | ||
928 | const struct firmware *eeprom_blob; | 936 | const struct firmware *eeprom_blob; |
929 | 937 | ||
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c index 3bd030494986..a4d69a059753 100644 --- a/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c | |||
@@ -362,6 +362,9 @@ static void ath9k_init_pcoem_platform(struct ath_softc *sc) | |||
362 | struct ath9k_hw_capabilities *pCap = &ah->caps; | 362 | struct ath9k_hw_capabilities *pCap = &ah->caps; |
363 | struct ath_common *common = ath9k_hw_common(ah); | 363 | struct ath_common *common = ath9k_hw_common(ah); |
364 | 364 | ||
365 | if (!IS_ENABLED(CONFIG_ATH9K_PCOEM)) | ||
366 | return; | ||
367 | |||
365 | if (common->bus_ops->ath_bus_type != ATH_PCI) | 368 | if (common->bus_ops->ath_bus_type != ATH_PCI) |
366 | return; | 369 | return; |
367 | 370 | ||
@@ -528,6 +531,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, | |||
528 | ah->is_clk_25mhz = pdata->is_clk_25mhz; | 531 | ah->is_clk_25mhz = pdata->is_clk_25mhz; |
529 | ah->get_mac_revision = pdata->get_mac_revision; | 532 | ah->get_mac_revision = pdata->get_mac_revision; |
530 | ah->external_reset = pdata->external_reset; | 533 | ah->external_reset = pdata->external_reset; |
534 | ah->disable_2ghz = pdata->disable_2ghz; | ||
535 | ah->disable_5ghz = pdata->disable_5ghz; | ||
536 | if (!pdata->endian_check) | ||
537 | ah->ah_flags |= AH_NO_EEP_SWAP; | ||
531 | } | 538 | } |
532 | 539 | ||
533 | common->ops = &ah->reg_ops; | 540 | common->ops = &ah->reg_ops; |
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 30c66dfcd7a0..a91ee92d9d3f 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 | ||
@@ -270,7 +274,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
270 | return true; | 274 | return true; |
271 | } | 275 | } |
272 | 276 | ||
273 | int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) | 277 | static int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) |
274 | { | 278 | { |
275 | struct ath_hw *ah = sc->sc_ah; | 279 | struct ath_hw *ah = sc->sc_ah; |
276 | struct ath_common *common = ath9k_hw_common(ah); | 280 | struct ath_common *common = ath9k_hw_common(ah); |
@@ -281,6 +285,7 @@ int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) | |||
281 | __ath_cancel_work(sc); | 285 | __ath_cancel_work(sc); |
282 | 286 | ||
283 | tasklet_disable(&sc->intr_tq); | 287 | tasklet_disable(&sc->intr_tq); |
288 | tasklet_disable(&sc->bcon_tasklet); | ||
284 | spin_lock_bh(&sc->sc_pcu_lock); | 289 | spin_lock_bh(&sc->sc_pcu_lock); |
285 | 290 | ||
286 | if (!sc->cur_chan->offchannel) { | 291 | if (!sc->cur_chan->offchannel) { |
@@ -326,6 +331,7 @@ int ath_reset_internal(struct ath_softc *sc, struct ath9k_channel *hchan) | |||
326 | 331 | ||
327 | out: | 332 | out: |
328 | spin_unlock_bh(&sc->sc_pcu_lock); | 333 | spin_unlock_bh(&sc->sc_pcu_lock); |
334 | tasklet_enable(&sc->bcon_tasklet); | ||
329 | tasklet_enable(&sc->intr_tq); | 335 | tasklet_enable(&sc->intr_tq); |
330 | 336 | ||
331 | return r; | 337 | return r; |
@@ -539,11 +545,10 @@ irqreturn_t ath_isr(int irq, void *dev) | |||
539 | sched = true; | 545 | sched = true; |
540 | 546 | ||
541 | /* | 547 | /* |
542 | * If a FATAL or RXORN interrupt is received, we have to reset the | 548 | * If a FATAL interrupt is received, we have to reset the chip |
543 | * chip immediately. | 549 | * immediately. |
544 | */ | 550 | */ |
545 | if ((status & ATH9K_INT_FATAL) || ((status & ATH9K_INT_RXORN) && | 551 | if (status & ATH9K_INT_FATAL) |
546 | !(ah->caps.hw_caps & ATH9K_HW_CAP_EDMA))) | ||
547 | goto chip_reset; | 552 | goto chip_reset; |
548 | 553 | ||
549 | if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) && | 554 | if ((ah->config.hw_hang_checks & HW_BB_WATCHDOG) && |
@@ -598,17 +603,29 @@ chip_reset: | |||
598 | #undef SCHED_INTR | 603 | #undef SCHED_INTR |
599 | } | 604 | } |
600 | 605 | ||
601 | int ath_reset(struct ath_softc *sc) | 606 | /* |
607 | * This function is called when a HW reset cannot be deferred | ||
608 | * and has to be immediate. | ||
609 | */ | ||
610 | int ath_reset(struct ath_softc *sc, struct ath9k_channel *hchan) | ||
602 | { | 611 | { |
612 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
603 | int r; | 613 | int r; |
604 | 614 | ||
615 | set_bit(ATH_OP_HW_RESET, &common->op_flags); | ||
616 | |||
605 | ath9k_ps_wakeup(sc); | 617 | ath9k_ps_wakeup(sc); |
606 | r = ath_reset_internal(sc, NULL); | 618 | r = ath_reset_internal(sc, hchan); |
607 | ath9k_ps_restore(sc); | 619 | ath9k_ps_restore(sc); |
608 | 620 | ||
609 | return r; | 621 | return r; |
610 | } | 622 | } |
611 | 623 | ||
624 | /* | ||
625 | * When a HW reset can be deferred, it is added to the | ||
626 | * hw_reset_work workqueue, but we set ATH_OP_HW_RESET before | ||
627 | * queueing. | ||
628 | */ | ||
612 | void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type) | 629 | void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type) |
613 | { | 630 | { |
614 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 631 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
@@ -623,7 +640,9 @@ void ath_reset_work(struct work_struct *work) | |||
623 | { | 640 | { |
624 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work); | 641 | struct ath_softc *sc = container_of(work, struct ath_softc, hw_reset_work); |
625 | 642 | ||
626 | ath_reset(sc); | 643 | ath9k_ps_wakeup(sc); |
644 | ath_reset_internal(sc, NULL); | ||
645 | ath9k_ps_restore(sc); | ||
627 | } | 646 | } |
628 | 647 | ||
629 | /**********************/ | 648 | /**********************/ |
@@ -1037,7 +1056,7 @@ static void ath9k_set_offchannel_state(struct ath_softc *sc) | |||
1037 | 1056 | ||
1038 | eth_zero_addr(common->curbssid); | 1057 | eth_zero_addr(common->curbssid); |
1039 | eth_broadcast_addr(common->bssidmask); | 1058 | eth_broadcast_addr(common->bssidmask); |
1040 | ether_addr_copy(common->macaddr, vif->addr); | 1059 | memcpy(common->macaddr, vif->addr, ETH_ALEN); |
1041 | common->curaid = 0; | 1060 | common->curaid = 0; |
1042 | ah->opmode = vif->type; | 1061 | ah->opmode = vif->type; |
1043 | ah->imask &= ~ATH9K_INT_SWBA; | 1062 | ah->imask &= ~ATH9K_INT_SWBA; |
@@ -1078,7 +1097,7 @@ void ath9k_calculate_summary_state(struct ath_softc *sc, | |||
1078 | ath9k_calculate_iter_data(sc, ctx, &iter_data); | 1097 | ath9k_calculate_iter_data(sc, ctx, &iter_data); |
1079 | 1098 | ||
1080 | if (iter_data.has_hw_macaddr) | 1099 | if (iter_data.has_hw_macaddr) |
1081 | ether_addr_copy(common->macaddr, iter_data.hw_macaddr); | 1100 | memcpy(common->macaddr, iter_data.hw_macaddr, ETH_ALEN); |
1082 | 1101 | ||
1083 | memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); | 1102 | memcpy(common->bssidmask, iter_data.mask, ETH_ALEN); |
1084 | ath_hw_setbssidmask(common); | 1103 | ath_hw_setbssidmask(common); |
@@ -1550,6 +1569,40 @@ static int ath9k_sta_remove(struct ieee80211_hw *hw, | |||
1550 | return 0; | 1569 | return 0; |
1551 | } | 1570 | } |
1552 | 1571 | ||
1572 | static int ath9k_sta_state(struct ieee80211_hw *hw, | ||
1573 | struct ieee80211_vif *vif, | ||
1574 | struct ieee80211_sta *sta, | ||
1575 | enum ieee80211_sta_state old_state, | ||
1576 | enum ieee80211_sta_state new_state) | ||
1577 | { | ||
1578 | struct ath_softc *sc = hw->priv; | ||
1579 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1580 | int ret = 0; | ||
1581 | |||
1582 | if (old_state == IEEE80211_STA_AUTH && | ||
1583 | new_state == IEEE80211_STA_ASSOC) { | ||
1584 | ret = ath9k_sta_add(hw, vif, sta); | ||
1585 | ath_dbg(common, CONFIG, | ||
1586 | "Add station: %pM\n", sta->addr); | ||
1587 | } else if (old_state == IEEE80211_STA_ASSOC && | ||
1588 | new_state == IEEE80211_STA_AUTH) { | ||
1589 | ret = ath9k_sta_remove(hw, vif, sta); | ||
1590 | ath_dbg(common, CONFIG, | ||
1591 | "Remove station: %pM\n", sta->addr); | ||
1592 | } | ||
1593 | |||
1594 | if (ath9k_is_chanctx_enabled()) { | ||
1595 | if (vif->type == NL80211_IFTYPE_STATION) { | ||
1596 | if (old_state == IEEE80211_STA_ASSOC && | ||
1597 | new_state == IEEE80211_STA_AUTHORIZED) | ||
1598 | ath_chanctx_event(sc, vif, | ||
1599 | ATH_CHANCTX_EVENT_AUTHORIZED); | ||
1600 | } | ||
1601 | } | ||
1602 | |||
1603 | return ret; | ||
1604 | } | ||
1605 | |||
1553 | static void ath9k_sta_set_tx_filter(struct ath_hw *ah, | 1606 | static void ath9k_sta_set_tx_filter(struct ath_hw *ah, |
1554 | struct ath_node *an, | 1607 | struct ath_node *an, |
1555 | bool set) | 1608 | bool set) |
@@ -1734,17 +1787,11 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
1734 | ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n", | 1787 | ath_dbg(common, CONFIG, "BSSID %pM Changed ASSOC %d\n", |
1735 | bss_conf->bssid, bss_conf->assoc); | 1788 | bss_conf->bssid, bss_conf->assoc); |
1736 | 1789 | ||
1737 | ether_addr_copy(avp->bssid, bss_conf->bssid); | 1790 | memcpy(avp->bssid, bss_conf->bssid, ETH_ALEN); |
1738 | avp->aid = bss_conf->aid; | 1791 | avp->aid = bss_conf->aid; |
1739 | avp->assoc = bss_conf->assoc; | 1792 | avp->assoc = bss_conf->assoc; |
1740 | 1793 | ||
1741 | ath9k_calculate_summary_state(sc, avp->chanctx); | 1794 | ath9k_calculate_summary_state(sc, avp->chanctx); |
1742 | |||
1743 | if (ath9k_is_chanctx_enabled()) { | ||
1744 | if (bss_conf->assoc) | ||
1745 | ath_chanctx_event(sc, vif, | ||
1746 | ATH_CHANCTX_EVENT_ASSOC); | ||
1747 | } | ||
1748 | } | 1795 | } |
1749 | 1796 | ||
1750 | if (changed & BSS_CHANGED_IBSS) { | 1797 | if (changed & BSS_CHANGED_IBSS) { |
@@ -1840,6 +1887,7 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1840 | u16 tid, u16 *ssn, u8 buf_size) | 1887 | u16 tid, u16 *ssn, u8 buf_size) |
1841 | { | 1888 | { |
1842 | struct ath_softc *sc = hw->priv; | 1889 | struct ath_softc *sc = hw->priv; |
1890 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1843 | bool flush = false; | 1891 | bool flush = false; |
1844 | int ret = 0; | 1892 | int ret = 0; |
1845 | 1893 | ||
@@ -1851,6 +1899,12 @@ static int ath9k_ampdu_action(struct ieee80211_hw *hw, | |||
1851 | case IEEE80211_AMPDU_RX_STOP: | 1899 | case IEEE80211_AMPDU_RX_STOP: |
1852 | break; | 1900 | break; |
1853 | case IEEE80211_AMPDU_TX_START: | 1901 | case IEEE80211_AMPDU_TX_START: |
1902 | if (ath9k_is_chanctx_enabled()) { | ||
1903 | if (test_bit(ATH_OP_SCANNING, &common->op_flags)) { | ||
1904 | ret = -EBUSY; | ||
1905 | break; | ||
1906 | } | ||
1907 | } | ||
1854 | ath9k_ps_wakeup(sc); | 1908 | ath9k_ps_wakeup(sc); |
1855 | ret = ath_tx_aggr_start(sc, sta, tid, ssn); | 1909 | ret = ath_tx_aggr_start(sc, sta, tid, ssn); |
1856 | if (!ret) | 1910 | if (!ret) |
@@ -1964,7 +2018,8 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, | |||
1964 | mutex_unlock(&sc->mutex); | 2018 | mutex_unlock(&sc->mutex); |
1965 | } | 2019 | } |
1966 | 2020 | ||
1967 | static bool ath9k_has_tx_pending(struct ath_softc *sc) | 2021 | static bool ath9k_has_tx_pending(struct ath_softc *sc, |
2022 | bool sw_pending) | ||
1968 | { | 2023 | { |
1969 | int i, npend = 0; | 2024 | int i, npend = 0; |
1970 | 2025 | ||
@@ -1972,7 +2027,8 @@ static bool ath9k_has_tx_pending(struct ath_softc *sc) | |||
1972 | if (!ATH_TXQ_SETUP(sc, i)) | 2027 | if (!ATH_TXQ_SETUP(sc, i)) |
1973 | continue; | 2028 | continue; |
1974 | 2029 | ||
1975 | npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]); | 2030 | npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i], |
2031 | sw_pending); | ||
1976 | if (npend) | 2032 | if (npend) |
1977 | break; | 2033 | break; |
1978 | } | 2034 | } |
@@ -1984,18 +2040,38 @@ static void ath9k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
1984 | u32 queues, bool drop) | 2040 | u32 queues, bool drop) |
1985 | { | 2041 | { |
1986 | struct ath_softc *sc = hw->priv; | 2042 | struct ath_softc *sc = hw->priv; |
2043 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | ||
1987 | 2044 | ||
2045 | if (ath9k_is_chanctx_enabled()) { | ||
2046 | if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) | ||
2047 | goto flush; | ||
2048 | |||
2049 | /* | ||
2050 | * If MCC is active, extend the flush timeout | ||
2051 | * and wait for the HW/SW queues to become | ||
2052 | * empty. This needs to be done outside the | ||
2053 | * sc->mutex lock to allow the channel scheduler | ||
2054 | * to switch channel contexts. | ||
2055 | * | ||
2056 | * The vif queues have been stopped in mac80211, | ||
2057 | * so there won't be any incoming frames. | ||
2058 | */ | ||
2059 | __ath9k_flush(hw, queues, drop, true, true); | ||
2060 | return; | ||
2061 | } | ||
2062 | flush: | ||
1988 | mutex_lock(&sc->mutex); | 2063 | mutex_lock(&sc->mutex); |
1989 | __ath9k_flush(hw, queues, drop); | 2064 | __ath9k_flush(hw, queues, drop, true, false); |
1990 | mutex_unlock(&sc->mutex); | 2065 | mutex_unlock(&sc->mutex); |
1991 | } | 2066 | } |
1992 | 2067 | ||
1993 | void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | 2068 | void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop, |
2069 | bool sw_pending, bool timeout_override) | ||
1994 | { | 2070 | { |
1995 | struct ath_softc *sc = hw->priv; | 2071 | struct ath_softc *sc = hw->priv; |
1996 | struct ath_hw *ah = sc->sc_ah; | 2072 | struct ath_hw *ah = sc->sc_ah; |
1997 | struct ath_common *common = ath9k_hw_common(ah); | 2073 | struct ath_common *common = ath9k_hw_common(ah); |
1998 | int timeout = HZ / 5; /* 200 ms */ | 2074 | int timeout; |
1999 | bool drain_txq; | 2075 | bool drain_txq; |
2000 | 2076 | ||
2001 | cancel_delayed_work_sync(&sc->tx_complete_work); | 2077 | cancel_delayed_work_sync(&sc->tx_complete_work); |
@@ -2010,7 +2086,17 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | |||
2010 | return; | 2086 | return; |
2011 | } | 2087 | } |
2012 | 2088 | ||
2013 | if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc), | 2089 | spin_lock_bh(&sc->chan_lock); |
2090 | if (timeout_override) | ||
2091 | timeout = HZ / 5; | ||
2092 | else | ||
2093 | timeout = sc->cur_chan->flush_timeout; | ||
2094 | spin_unlock_bh(&sc->chan_lock); | ||
2095 | |||
2096 | ath_dbg(common, CHAN_CTX, | ||
2097 | "Flush timeout: %d\n", jiffies_to_msecs(timeout)); | ||
2098 | |||
2099 | if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc, sw_pending), | ||
2014 | timeout) > 0) | 2100 | timeout) > 0) |
2015 | drop = false; | 2101 | drop = false; |
2016 | 2102 | ||
@@ -2021,7 +2107,7 @@ void __ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop) | |||
2021 | spin_unlock_bh(&sc->sc_pcu_lock); | 2107 | spin_unlock_bh(&sc->sc_pcu_lock); |
2022 | 2108 | ||
2023 | if (!drain_txq) | 2109 | if (!drain_txq) |
2024 | ath_reset(sc); | 2110 | ath_reset(sc, NULL); |
2025 | 2111 | ||
2026 | ath9k_ps_restore(sc); | 2112 | ath9k_ps_restore(sc); |
2027 | } | 2113 | } |
@@ -2033,7 +2119,7 @@ static bool ath9k_tx_frames_pending(struct ieee80211_hw *hw) | |||
2033 | { | 2119 | { |
2034 | struct ath_softc *sc = hw->priv; | 2120 | struct ath_softc *sc = hw->priv; |
2035 | 2121 | ||
2036 | return ath9k_has_tx_pending(sc); | 2122 | return ath9k_has_tx_pending(sc, true); |
2037 | } | 2123 | } |
2038 | 2124 | ||
2039 | static int ath9k_tx_last_beacon(struct ieee80211_hw *hw) | 2125 | static int ath9k_tx_last_beacon(struct ieee80211_hw *hw) |
@@ -2310,7 +2396,6 @@ static int ath9k_add_chanctx(struct ieee80211_hw *hw, | |||
2310 | conf->def.chan->center_freq); | 2396 | conf->def.chan->center_freq); |
2311 | 2397 | ||
2312 | ath_chanctx_set_channel(sc, ctx, &conf->def); | 2398 | ath_chanctx_set_channel(sc, ctx, &conf->def); |
2313 | ath_chanctx_event(sc, NULL, ATH_CHANCTX_EVENT_ASSIGN); | ||
2314 | 2399 | ||
2315 | mutex_unlock(&sc->mutex); | 2400 | mutex_unlock(&sc->mutex); |
2316 | return 0; | 2401 | return 0; |
@@ -2419,7 +2504,11 @@ static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw, | |||
2419 | struct ath_softc *sc = hw->priv; | 2504 | struct ath_softc *sc = hw->priv; |
2420 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 2505 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
2421 | struct ath_vif *avp = (struct ath_vif *) vif->drv_priv; | 2506 | struct ath_vif *avp = (struct ath_vif *) vif->drv_priv; |
2507 | struct ath_beacon_config *cur_conf; | ||
2508 | struct ath_chanctx *go_ctx; | ||
2509 | unsigned long timeout; | ||
2422 | bool changed = false; | 2510 | bool changed = false; |
2511 | u32 beacon_int; | ||
2423 | 2512 | ||
2424 | if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) | 2513 | if (!test_bit(ATH_OP_MULTI_CHANNEL, &common->op_flags)) |
2425 | return; | 2514 | return; |
@@ -2430,19 +2519,59 @@ static void ath9k_mgd_prepare_tx(struct ieee80211_hw *hw, | |||
2430 | mutex_lock(&sc->mutex); | 2519 | mutex_lock(&sc->mutex); |
2431 | 2520 | ||
2432 | spin_lock_bh(&sc->chan_lock); | 2521 | spin_lock_bh(&sc->chan_lock); |
2433 | if (sc->next_chan || (sc->cur_chan != avp->chanctx)) { | 2522 | if (sc->next_chan || (sc->cur_chan != avp->chanctx)) |
2434 | sc->next_chan = avp->chanctx; | ||
2435 | changed = true; | 2523 | changed = true; |
2524 | spin_unlock_bh(&sc->chan_lock); | ||
2525 | |||
2526 | if (!changed) | ||
2527 | goto out; | ||
2528 | |||
2529 | if (test_bit(ATH_OP_SCANNING, &common->op_flags)) { | ||
2530 | ath_dbg(common, CHAN_CTX, | ||
2531 | "%s: Aborting HW scan\n", __func__); | ||
2532 | |||
2533 | mutex_unlock(&sc->mutex); | ||
2534 | |||
2535 | del_timer_sync(&sc->offchannel.timer); | ||
2536 | ath_scan_complete(sc, true); | ||
2537 | flush_work(&sc->chanctx_work); | ||
2538 | |||
2539 | mutex_lock(&sc->mutex); | ||
2540 | } | ||
2541 | |||
2542 | go_ctx = ath_is_go_chanctx_present(sc); | ||
2543 | |||
2544 | if (go_ctx) { | ||
2545 | /* | ||
2546 | * Wait till the GO interface gets a chance | ||
2547 | * to send out an NoA. | ||
2548 | */ | ||
2549 | spin_lock_bh(&sc->chan_lock); | ||
2550 | sc->sched.mgd_prepare_tx = true; | ||
2551 | cur_conf = &go_ctx->beacon; | ||
2552 | beacon_int = TU_TO_USEC(cur_conf->beacon_interval); | ||
2553 | spin_unlock_bh(&sc->chan_lock); | ||
2554 | |||
2555 | timeout = usecs_to_jiffies(beacon_int); | ||
2556 | init_completion(&sc->go_beacon); | ||
2557 | |||
2558 | if (wait_for_completion_timeout(&sc->go_beacon, | ||
2559 | timeout) == 0) | ||
2560 | ath_dbg(common, CHAN_CTX, | ||
2561 | "Failed to send new NoA\n"); | ||
2436 | } | 2562 | } |
2563 | |||
2437 | ath_dbg(common, CHAN_CTX, | 2564 | ath_dbg(common, CHAN_CTX, |
2438 | "%s: Set chanctx state to FORCE_ACTIVE, changed: %d\n", | 2565 | "%s: Set chanctx state to FORCE_ACTIVE for vif: %pM\n", |
2439 | __func__, changed); | 2566 | __func__, vif->addr); |
2567 | |||
2568 | spin_lock_bh(&sc->chan_lock); | ||
2569 | sc->next_chan = avp->chanctx; | ||
2440 | sc->sched.state = ATH_CHANCTX_STATE_FORCE_ACTIVE; | 2570 | sc->sched.state = ATH_CHANCTX_STATE_FORCE_ACTIVE; |
2441 | spin_unlock_bh(&sc->chan_lock); | 2571 | spin_unlock_bh(&sc->chan_lock); |
2442 | 2572 | ||
2443 | if (changed) | 2573 | ath_chanctx_set_next(sc, true); |
2444 | ath_chanctx_set_next(sc, true); | 2574 | out: |
2445 | |||
2446 | mutex_unlock(&sc->mutex); | 2575 | mutex_unlock(&sc->mutex); |
2447 | } | 2576 | } |
2448 | 2577 | ||
@@ -2474,8 +2603,7 @@ struct ieee80211_ops ath9k_ops = { | |||
2474 | .remove_interface = ath9k_remove_interface, | 2603 | .remove_interface = ath9k_remove_interface, |
2475 | .config = ath9k_config, | 2604 | .config = ath9k_config, |
2476 | .configure_filter = ath9k_configure_filter, | 2605 | .configure_filter = ath9k_configure_filter, |
2477 | .sta_add = ath9k_sta_add, | 2606 | .sta_state = ath9k_sta_state, |
2478 | .sta_remove = ath9k_sta_remove, | ||
2479 | .sta_notify = ath9k_sta_notify, | 2607 | .sta_notify = ath9k_sta_notify, |
2480 | .conf_tx = ath9k_conf_tx, | 2608 | .conf_tx = ath9k_conf_tx, |
2481 | .bss_info_changed = ath9k_bss_info_changed, | 2609 | .bss_info_changed = ath9k_bss_info_changed, |
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c index c018dea0b2e8..e3f60d5c5263 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, |
@@ -657,6 +662,7 @@ static const struct pci_device_id ath_pci_id_table[] = { | |||
657 | /* PCI-E AR9565 (WB335) */ | 662 | /* PCI-E AR9565 (WB335) */ |
658 | { PCI_VDEVICE(ATHEROS, 0x0036), | 663 | { PCI_VDEVICE(ATHEROS, 0x0036), |
659 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, | 664 | .driver_data = ATH9K_PCI_BT_ANT_DIV }, |
665 | #endif | ||
660 | 666 | ||
661 | { 0 } | 667 | { 0 } |
662 | }; | 668 | }; |
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h index 2a938f4feac5..1c0b1c1c5350 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) \ |
diff --git a/drivers/net/wireless/ath/ath9k/tx99.c b/drivers/net/wireless/ath/ath9k/tx99.c index 40ab65e6882f..ac4781f37e78 100644 --- a/drivers/net/wireless/ath/ath9k/tx99.c +++ b/drivers/net/wireless/ath/ath9k/tx99.c | |||
@@ -99,7 +99,7 @@ static struct sk_buff *ath9k_build_tx99_skb(struct ath_softc *sc) | |||
99 | 99 | ||
100 | static void ath9k_tx99_deinit(struct ath_softc *sc) | 100 | static void ath9k_tx99_deinit(struct ath_softc *sc) |
101 | { | 101 | { |
102 | ath_reset(sc); | 102 | ath_reset(sc, NULL); |
103 | 103 | ||
104 | ath9k_ps_wakeup(sc); | 104 | ath9k_ps_wakeup(sc); |
105 | ath9k_tx99_stop(sc); | 105 | ath9k_tx99_stop(sc); |
@@ -127,7 +127,7 @@ static int ath9k_tx99_init(struct ath_softc *sc) | |||
127 | memset(&txctl, 0, sizeof(txctl)); | 127 | memset(&txctl, 0, sizeof(txctl)); |
128 | txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; | 128 | txctl.txq = sc->tx.txq_map[IEEE80211_AC_VO]; |
129 | 129 | ||
130 | ath_reset(sc); | 130 | ath_reset(sc, NULL); |
131 | 131 | ||
132 | ath9k_ps_wakeup(sc); | 132 | ath9k_ps_wakeup(sc); |
133 | 133 | ||
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/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/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..e418969679c9 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 |
@@ -2779,6 +2779,44 @@ static __always_inline void brcmf_delay(u32 ms) | |||
2779 | } | 2779 | } |
2780 | } | 2780 | } |
2781 | 2781 | ||
2782 | static s32 brcmf_config_wowl_pattern(struct brcmf_if *ifp, u8 cmd[4], | ||
2783 | u8 *pattern, u32 patternsize, u8 *mask, | ||
2784 | u32 packet_offset) | ||
2785 | { | ||
2786 | struct brcmf_fil_wowl_pattern_le *filter; | ||
2787 | u32 masksize; | ||
2788 | u32 patternoffset; | ||
2789 | u8 *buf; | ||
2790 | u32 bufsize; | ||
2791 | s32 ret; | ||
2792 | |||
2793 | masksize = (patternsize + 7) / 8; | ||
2794 | patternoffset = sizeof(*filter) - sizeof(filter->cmd) + masksize; | ||
2795 | |||
2796 | bufsize = sizeof(*filter) + patternsize + masksize; | ||
2797 | buf = kzalloc(bufsize, GFP_KERNEL); | ||
2798 | if (!buf) | ||
2799 | return -ENOMEM; | ||
2800 | filter = (struct brcmf_fil_wowl_pattern_le *)buf; | ||
2801 | |||
2802 | memcpy(filter->cmd, cmd, 4); | ||
2803 | filter->masksize = cpu_to_le32(masksize); | ||
2804 | filter->offset = cpu_to_le32(packet_offset); | ||
2805 | filter->patternoffset = cpu_to_le32(patternoffset); | ||
2806 | filter->patternsize = cpu_to_le32(patternsize); | ||
2807 | filter->type = cpu_to_le32(BRCMF_WOWL_PATTERN_TYPE_BITMAP); | ||
2808 | |||
2809 | if ((mask) && (masksize)) | ||
2810 | memcpy(buf + sizeof(*filter), mask, masksize); | ||
2811 | if ((pattern) && (patternsize)) | ||
2812 | memcpy(buf + sizeof(*filter) + masksize, pattern, patternsize); | ||
2813 | |||
2814 | ret = brcmf_fil_iovar_data_set(ifp, "wowl_pattern", buf, bufsize); | ||
2815 | |||
2816 | kfree(buf); | ||
2817 | return ret; | ||
2818 | } | ||
2819 | |||
2782 | static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) | 2820 | static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) |
2783 | { | 2821 | { |
2784 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 2822 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
@@ -2788,10 +2826,11 @@ static s32 brcmf_cfg80211_resume(struct wiphy *wiphy) | |||
2788 | brcmf_dbg(TRACE, "Enter\n"); | 2826 | brcmf_dbg(TRACE, "Enter\n"); |
2789 | 2827 | ||
2790 | if (cfg->wowl_enabled) { | 2828 | if (cfg->wowl_enabled) { |
2829 | brcmf_configure_arp_offload(ifp, true); | ||
2791 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, | 2830 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, |
2792 | cfg->pre_wowl_pmmode); | 2831 | 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); | 2832 | brcmf_fil_iovar_int_set(ifp, "wowl_clear", 0); |
2833 | brcmf_config_wowl_pattern(ifp, "clr", NULL, 0, NULL, 0); | ||
2795 | cfg->wowl_enabled = false; | 2834 | cfg->wowl_enabled = false; |
2796 | } | 2835 | } |
2797 | return 0; | 2836 | return 0; |
@@ -2802,21 +2841,29 @@ static void brcmf_configure_wowl(struct brcmf_cfg80211_info *cfg, | |||
2802 | struct cfg80211_wowlan *wowl) | 2841 | struct cfg80211_wowlan *wowl) |
2803 | { | 2842 | { |
2804 | u32 wowl_config; | 2843 | u32 wowl_config; |
2844 | u32 i; | ||
2805 | 2845 | ||
2806 | brcmf_dbg(TRACE, "Suspend, wowl config.\n"); | 2846 | brcmf_dbg(TRACE, "Suspend, wowl config.\n"); |
2807 | 2847 | ||
2848 | brcmf_configure_arp_offload(ifp, false); | ||
2808 | brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_PM, &cfg->pre_wowl_pmmode); | 2849 | 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); | 2850 | brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_PM, PM_MAX); |
2810 | 2851 | ||
2811 | wowl_config = 0; | 2852 | wowl_config = 0; |
2812 | if (wowl->disconnect) | 2853 | if (wowl->disconnect) |
2813 | wowl_config |= WL_WOWL_DIS | WL_WOWL_BCN | WL_WOWL_RETR; | 2854 | 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) | 2855 | if (wowl->magic_pkt) |
2819 | wowl_config |= WL_WOWL_MAGIC; | 2856 | wowl_config |= BRCMF_WOWL_MAGIC; |
2857 | if ((wowl->patterns) && (wowl->n_patterns)) { | ||
2858 | wowl_config |= BRCMF_WOWL_NET; | ||
2859 | for (i = 0; i < wowl->n_patterns; i++) { | ||
2860 | brcmf_config_wowl_pattern(ifp, "add", | ||
2861 | (u8 *)wowl->patterns[i].pattern, | ||
2862 | wowl->patterns[i].pattern_len, | ||
2863 | (u8 *)wowl->patterns[i].mask, | ||
2864 | wowl->patterns[i].pkt_offset); | ||
2865 | } | ||
2866 | } | ||
2820 | brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config); | 2867 | brcmf_fil_iovar_int_set(ifp, "wowl", wowl_config); |
2821 | brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1); | 2868 | brcmf_fil_iovar_int_set(ifp, "wowl_activate", 1); |
2822 | brcmf_bus_wowl_config(cfg->pub->bus_if, true); | 2869 | brcmf_bus_wowl_config(cfg->pub->bus_if, true); |
@@ -3998,24 +4045,24 @@ brcmf_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev, | |||
3998 | 4045 | ||
3999 | static int | 4046 | static int |
4000 | brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, | 4047 | brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, |
4001 | const u8 *mac) | 4048 | struct station_del_parameters *params) |
4002 | { | 4049 | { |
4003 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); | 4050 | struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); |
4004 | struct brcmf_scb_val_le scbval; | 4051 | struct brcmf_scb_val_le scbval; |
4005 | struct brcmf_if *ifp = netdev_priv(ndev); | 4052 | struct brcmf_if *ifp = netdev_priv(ndev); |
4006 | s32 err; | 4053 | s32 err; |
4007 | 4054 | ||
4008 | if (!mac) | 4055 | if (!params->mac) |
4009 | return -EFAULT; | 4056 | return -EFAULT; |
4010 | 4057 | ||
4011 | brcmf_dbg(TRACE, "Enter %pM\n", mac); | 4058 | brcmf_dbg(TRACE, "Enter %pM\n", params->mac); |
4012 | 4059 | ||
4013 | if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) | 4060 | if (ifp->vif == cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif) |
4014 | ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; | 4061 | ifp = cfg->p2p.bss_idx[P2PAPI_BSSCFG_PRIMARY].vif->ifp; |
4015 | if (!check_vif_up(ifp->vif)) | 4062 | if (!check_vif_up(ifp->vif)) |
4016 | return -EIO; | 4063 | return -EIO; |
4017 | 4064 | ||
4018 | memcpy(&scbval.ea, mac, ETH_ALEN); | 4065 | memcpy(&scbval.ea, params->mac, ETH_ALEN); |
4019 | scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING); | 4066 | scbval.val = cpu_to_le32(WLAN_REASON_DEAUTH_LEAVING); |
4020 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON, | 4067 | err = brcmf_fil_cmd_data_set(ifp, BRCMF_C_SCB_DEAUTHENTICATE_FOR_REASON, |
4021 | &scbval, sizeof(scbval)); | 4068 | &scbval, sizeof(scbval)); |
@@ -5440,10 +5487,13 @@ static void brcmf_wiphy_pno_params(struct wiphy *wiphy) | |||
5440 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; | 5487 | wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; |
5441 | } | 5488 | } |
5442 | 5489 | ||
5443 | |||
5444 | #ifdef CONFIG_PM | 5490 | #ifdef CONFIG_PM |
5445 | static const struct wiphy_wowlan_support brcmf_wowlan_support = { | 5491 | static const struct wiphy_wowlan_support brcmf_wowlan_support = { |
5446 | .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, | 5492 | .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, |
5493 | .n_patterns = BRCMF_WOWL_MAXPATTERNS, | ||
5494 | .pattern_max_len = BRCMF_WOWL_MAXPATTERNSIZE, | ||
5495 | .pattern_min_len = 1, | ||
5496 | .max_pkt_offset = 1500, | ||
5447 | }; | 5497 | }; |
5448 | #endif | 5498 | #endif |
5449 | 5499 | ||
@@ -5607,7 +5657,8 @@ enum nl80211_iftype brcmf_cfg80211_get_iftype(struct brcmf_if *ifp) | |||
5607 | return wdev->iftype; | 5657 | return wdev->iftype; |
5608 | } | 5658 | } |
5609 | 5659 | ||
5610 | bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, unsigned long state) | 5660 | bool brcmf_get_vif_state_any(struct brcmf_cfg80211_info *cfg, |
5661 | unsigned long state) | ||
5611 | { | 5662 | { |
5612 | struct brcmf_cfg80211_vif *vif; | 5663 | struct brcmf_cfg80211_vif *vif; |
5613 | 5664 | ||
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..0f157f151282 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]; |
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..02d39ce8dbca 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 | ||
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 d20d4e6f391a..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 */ |
@@ -2762,6 +2762,48 @@ static struct pktq *brcmf_sdio_bus_gettxq(struct device *dev) | |||
2762 | return &bus->txq; | 2762 | return &bus->txq; |
2763 | } | 2763 | } |
2764 | 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 | |||
2765 | 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) |
2766 | { | 2808 | { |
2767 | int ret = -EBADE; | 2809 | int ret = -EBADE; |
@@ -2787,7 +2829,7 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2787 | spin_lock_bh(&bus->txq_lock); | 2829 | spin_lock_bh(&bus->txq_lock); |
2788 | /* reset bus_flags in packet cb */ | 2830 | /* reset bus_flags in packet cb */ |
2789 | *(u16 *)(pkt->cb) = 0; | 2831 | *(u16 *)(pkt->cb) = 0; |
2790 | if (!brcmf_c_prec_enq(bus->sdiodev->dev, &bus->txq, pkt, prec)) { | 2832 | if (!brcmf_sdio_prec_enq(&bus->txq, pkt, prec)) { |
2791 | skb_pull(pkt, bus->tx_hdrlen); | 2833 | skb_pull(pkt, bus->tx_hdrlen); |
2792 | brcmf_err("out of bus->txq !!!\n"); | 2834 | brcmf_err("out of bus->txq !!!\n"); |
2793 | ret = -ENOSR; | 2835 | ret = -ENOSR; |
@@ -2797,7 +2839,7 @@ static int brcmf_sdio_bus_txdata(struct device *dev, struct sk_buff *pkt) | |||
2797 | 2839 | ||
2798 | if (pktq_len(&bus->txq) >= TXHI) { | 2840 | if (pktq_len(&bus->txq) >= TXHI) { |
2799 | bus->txoff = true; | 2841 | bus->txoff = true; |
2800 | brcmf_txflowblock(bus->sdiodev->dev, true); | 2842 | brcmf_txflowblock(dev, true); |
2801 | } | 2843 | } |
2802 | spin_unlock_bh(&bus->txq_lock); | 2844 | spin_unlock_bh(&bus->txq_lock); |
2803 | 2845 | ||
@@ -3948,6 +3990,7 @@ static struct brcmf_bus_ops brcmf_sdio_bus_ops = { | |||
3948 | .txctl = brcmf_sdio_bus_txctl, | 3990 | .txctl = brcmf_sdio_bus_txctl, |
3949 | .rxctl = brcmf_sdio_bus_rxctl, | 3991 | .rxctl = brcmf_sdio_bus_rxctl, |
3950 | .gettxq = brcmf_sdio_bus_gettxq, | 3992 | .gettxq = brcmf_sdio_bus_gettxq, |
3993 | .wowl_config = brcmf_sdio_wowl_config | ||
3951 | }; | 3994 | }; |
3952 | 3995 | ||
3953 | static void brcmf_sdio_firmware_callback(struct device *dev, | 3996 | static void brcmf_sdio_firmware_callback(struct device *dev, |
@@ -4074,7 +4117,7 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev) | |||
4074 | 4117 | ||
4075 | /* platform specific configuration: | 4118 | /* platform specific configuration: |
4076 | * alignments must be at least 4 bytes for ADMA | 4119 | * alignments must be at least 4 bytes for ADMA |
4077 | */ | 4120 | */ |
4078 | bus->head_align = ALIGNMENT; | 4121 | bus->head_align = ALIGNMENT; |
4079 | bus->sgentry_align = ALIGNMENT; | 4122 | bus->sgentry_align = ALIGNMENT; |
4080 | 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/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c index 1b474828d5b8..bc9be78faafa 100644 --- a/drivers/net/wireless/brcm80211/brcmsmac/main.c +++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c | |||
@@ -3081,7 +3081,7 @@ static bool brcms_c_ps_allowed(struct brcms_c_info *wlc) | |||
3081 | static void brcms_c_statsupd(struct brcms_c_info *wlc) | 3081 | static void brcms_c_statsupd(struct brcms_c_info *wlc) |
3082 | { | 3082 | { |
3083 | int i; | 3083 | int i; |
3084 | struct macstat macstats; | 3084 | struct macstat *macstats; |
3085 | #ifdef DEBUG | 3085 | #ifdef DEBUG |
3086 | u16 delta; | 3086 | u16 delta; |
3087 | u16 rxf0ovfl; | 3087 | u16 rxf0ovfl; |
@@ -3092,31 +3092,31 @@ static void brcms_c_statsupd(struct brcms_c_info *wlc) | |||
3092 | if (!wlc->pub->up) | 3092 | if (!wlc->pub->up) |
3093 | return; | 3093 | return; |
3094 | 3094 | ||
3095 | macstats = wlc->core->macstat_snapshot; | ||
3096 | |||
3095 | #ifdef DEBUG | 3097 | #ifdef DEBUG |
3096 | /* save last rx fifo 0 overflow count */ | 3098 | /* save last rx fifo 0 overflow count */ |
3097 | rxf0ovfl = wlc->core->macstat_snapshot->rxf0ovfl; | 3099 | rxf0ovfl = macstats->rxf0ovfl; |
3098 | 3100 | ||
3099 | /* save last tx fifo underflow count */ | 3101 | /* save last tx fifo underflow count */ |
3100 | for (i = 0; i < NFIFO; i++) | 3102 | for (i = 0; i < NFIFO; i++) |
3101 | txfunfl[i] = wlc->core->macstat_snapshot->txfunfl[i]; | 3103 | txfunfl[i] = macstats->txfunfl[i]; |
3102 | #endif /* DEBUG */ | 3104 | #endif /* DEBUG */ |
3103 | 3105 | ||
3104 | /* Read mac stats from contiguous shared memory */ | 3106 | /* Read mac stats from contiguous shared memory */ |
3105 | brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, &macstats, | 3107 | brcms_b_copyfrom_objmem(wlc->hw, M_UCODE_MACSTAT, macstats, |
3106 | sizeof(struct macstat), OBJADDR_SHM_SEL); | 3108 | sizeof(*macstats), OBJADDR_SHM_SEL); |
3107 | 3109 | ||
3108 | #ifdef DEBUG | 3110 | #ifdef DEBUG |
3109 | /* check for rx fifo 0 overflow */ | 3111 | /* check for rx fifo 0 overflow */ |
3110 | delta = (u16) (wlc->core->macstat_snapshot->rxf0ovfl - rxf0ovfl); | 3112 | delta = (u16)(macstats->rxf0ovfl - rxf0ovfl); |
3111 | if (delta) | 3113 | if (delta) |
3112 | brcms_err(wlc->hw->d11core, "wl%d: %u rx fifo 0 overflows!\n", | 3114 | brcms_err(wlc->hw->d11core, "wl%d: %u rx fifo 0 overflows!\n", |
3113 | wlc->pub->unit, delta); | 3115 | wlc->pub->unit, delta); |
3114 | 3116 | ||
3115 | /* check for tx fifo underflows */ | 3117 | /* check for tx fifo underflows */ |
3116 | for (i = 0; i < NFIFO; i++) { | 3118 | for (i = 0; i < NFIFO; i++) { |
3117 | delta = | 3119 | delta = macstats->txfunfl[i] - txfunfl[i]; |
3118 | (u16) (wlc->core->macstat_snapshot->txfunfl[i] - | ||
3119 | txfunfl[i]); | ||
3120 | if (delta) | 3120 | if (delta) |
3121 | brcms_err(wlc->hw->d11core, | 3121 | brcms_err(wlc->hw->d11core, |
3122 | "wl%d: %u tx fifo %d underflows!\n", | 3122 | "wl%d: %u tx fifo %d underflows!\n", |
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c index edc344334a75..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, |
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 2d66984079bb..a6877dd6ba73 100644 --- a/drivers/net/wireless/ipw2x00/libipw_rx.c +++ b/drivers/net/wireless/ipw2x00/libipw_rx.c | |||
@@ -1298,13 +1298,6 @@ static int libipw_parse_info_param(struct libipw_info_element | |||
1298 | break; | 1298 | break; |
1299 | 1299 | ||
1300 | case WLAN_EID_IBSS_DFS: | 1300 | case WLAN_EID_IBSS_DFS: |
1301 | if (network->ibss_dfs) | ||
1302 | break; | ||
1303 | network->ibss_dfs = kmemdup(info_element->data, | ||
1304 | info_element->len, | ||
1305 | GFP_ATOMIC); | ||
1306 | if (!network->ibss_dfs) | ||
1307 | return 1; | ||
1308 | network->flags |= NETWORK_HAS_IBSS_DFS; | 1301 | network->flags |= NETWORK_HAS_IBSS_DFS; |
1309 | break; | 1302 | break; |
1310 | 1303 | ||
@@ -1335,9 +1328,7 @@ static int libipw_parse_info_param(struct libipw_info_element | |||
1335 | 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 |
1336 | *frame, struct libipw_rx_stats *stats) | 1329 | *frame, struct libipw_rx_stats *stats) |
1337 | { | 1330 | { |
1338 | struct libipw_network network_resp = { | 1331 | struct libipw_network network_resp = { }; |
1339 | .ibss_dfs = NULL, | ||
1340 | }; | ||
1341 | struct libipw_network *network = &network_resp; | 1332 | struct libipw_network *network = &network_resp; |
1342 | struct net_device *dev = ieee->dev; | 1333 | struct net_device *dev = ieee->dev; |
1343 | 1334 | ||
@@ -1472,9 +1463,6 @@ static void update_network(struct libipw_network *dst, | |||
1472 | int qos_active; | 1463 | int qos_active; |
1473 | u8 old_param; | 1464 | u8 old_param; |
1474 | 1465 | ||
1475 | libipw_network_reset(dst); | ||
1476 | dst->ibss_dfs = src->ibss_dfs; | ||
1477 | |||
1478 | /* We only update the statistics if they were created by receiving | 1466 | /* We only update the statistics if they were created by receiving |
1479 | * the network information on the actual channel the network is on. | 1467 | * the network information on the actual channel the network is on. |
1480 | * | 1468 | * |
@@ -1548,9 +1536,7 @@ static void libipw_process_probe_response(struct libipw_device | |||
1548 | *stats) | 1536 | *stats) |
1549 | { | 1537 | { |
1550 | struct net_device *dev = ieee->dev; | 1538 | struct net_device *dev = ieee->dev; |
1551 | struct libipw_network network = { | 1539 | struct libipw_network network = { }; |
1552 | .ibss_dfs = NULL, | ||
1553 | }; | ||
1554 | struct libipw_network *target; | 1540 | struct libipw_network *target; |
1555 | struct libipw_network *oldest = NULL; | 1541 | struct libipw_network *oldest = NULL; |
1556 | #ifdef CONFIG_LIBIPW_DEBUG | 1542 | #ifdef CONFIG_LIBIPW_DEBUG |
@@ -1618,7 +1604,6 @@ static void libipw_process_probe_response(struct libipw_device | |||
1618 | LIBIPW_DEBUG_SCAN("Expired '%*pE' (%pM) from network list.\n", | 1604 | LIBIPW_DEBUG_SCAN("Expired '%*pE' (%pM) from network list.\n", |
1619 | target->ssid_len, target->ssid, | 1605 | target->ssid_len, target->ssid, |
1620 | target->bssid); | 1606 | target->bssid); |
1621 | libipw_network_reset(target); | ||
1622 | } else { | 1607 | } else { |
1623 | /* Otherwise just pull from the free list */ | 1608 | /* Otherwise just pull from the free list */ |
1624 | target = list_entry(ieee->network_free_list.next, | 1609 | target = list_entry(ieee->network_free_list.next, |
@@ -1634,7 +1619,6 @@ static void libipw_process_probe_response(struct libipw_device | |||
1634 | "BEACON" : "PROBE RESPONSE"); | 1619 | "BEACON" : "PROBE RESPONSE"); |
1635 | #endif | 1620 | #endif |
1636 | memcpy(target, &network, sizeof(*target)); | 1621 | memcpy(target, &network, sizeof(*target)); |
1637 | network.ibss_dfs = NULL; | ||
1638 | list_add_tail(&target->list, &ieee->network_list); | 1622 | list_add_tail(&target->list, &ieee->network_list); |
1639 | } else { | 1623 | } else { |
1640 | LIBIPW_DEBUG_SCAN("Updating '%*pE' (%pM) via %s.\n", | 1624 | LIBIPW_DEBUG_SCAN("Updating '%*pE' (%pM) via %s.\n", |
@@ -1643,7 +1627,6 @@ static void libipw_process_probe_response(struct libipw_device | |||
1643 | is_beacon(beacon->header.frame_ctl) ? | 1627 | is_beacon(beacon->header.frame_ctl) ? |
1644 | "BEACON" : "PROBE RESPONSE"); | 1628 | "BEACON" : "PROBE RESPONSE"); |
1645 | update_network(target, &network); | 1629 | update_network(target, &network); |
1646 | network.ibss_dfs = NULL; | ||
1647 | } | 1630 | } |
1648 | 1631 | ||
1649 | spin_unlock_irqrestore(&ieee->lock, flags); | 1632 | spin_unlock_irqrestore(&ieee->lock, flags); |
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/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig index 267e48a2915e..139de90c2aaf 100644 --- a/drivers/net/wireless/iwlwifi/Kconfig +++ b/drivers/net/wireless/iwlwifi/Kconfig | |||
@@ -59,6 +59,7 @@ config IWLDVM | |||
59 | 59 | ||
60 | config IWLMVM | 60 | config IWLMVM |
61 | tristate "Intel Wireless WiFi MVM Firmware support" | 61 | tristate "Intel Wireless WiFi MVM Firmware support" |
62 | select BACKPORT_WANT_DEV_COREDUMP | ||
62 | help | 63 | help |
63 | This is the driver that supports the MVM firmware which is | 64 | This is the driver that supports the MVM firmware which is |
64 | currently only available for 7260 and 3160 devices. | 65 | currently only available for 7260 and 3160 devices. |
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c index 2191621d69c1..02e4ede2b042 100644 --- a/drivers/net/wireless/iwlwifi/dvm/lib.c +++ b/drivers/net/wireless/iwlwifi/dvm/lib.c | |||
@@ -418,8 +418,8 @@ void iwlagn_bt_adjust_rssi_monitor(struct iwl_priv *priv, bool rssi_ena) | |||
418 | 418 | ||
419 | static bool iwlagn_bt_traffic_is_sco(struct iwl_bt_uart_msg *uart_msg) | 419 | static bool iwlagn_bt_traffic_is_sco(struct iwl_bt_uart_msg *uart_msg) |
420 | { | 420 | { |
421 | return BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3 >> | 421 | return (BT_UART_MSG_FRAME3SCOESCO_MSK & uart_msg->frame3) >> |
422 | BT_UART_MSG_FRAME3SCOESCO_POS; | 422 | BT_UART_MSG_FRAME3SCOESCO_POS; |
423 | } | 423 | } |
424 | 424 | ||
425 | static void iwlagn_bt_traffic_change_work(struct work_struct *work) | 425 | static void iwlagn_bt_traffic_change_work(struct work_struct *work) |
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/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c index d2b7234b1c73..896ea906549c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-8000.c +++ b/drivers/net/wireless/iwlwifi/iwl-8000.c | |||
@@ -104,6 +104,7 @@ static const struct iwl_base_params iwl8000_base_params = { | |||
104 | }; | 104 | }; |
105 | 105 | ||
106 | static const struct iwl_ht_params iwl8000_ht_params = { | 106 | static const struct iwl_ht_params iwl8000_ht_params = { |
107 | .stbc = true, | ||
107 | .ldpc = true, | 108 | .ldpc = true, |
108 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), | 109 | .ht40_bands = BIT(IEEE80211_BAND_2GHZ) | BIT(IEEE80211_BAND_5GHZ), |
109 | }; | 110 | }; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 2ef83a39ff10..f8aa9cf08279 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h | |||
@@ -87,6 +87,16 @@ enum iwl_device_family { | |||
87 | IWL_DEVICE_FAMILY_8000, | 87 | IWL_DEVICE_FAMILY_8000, |
88 | }; | 88 | }; |
89 | 89 | ||
90 | static inline bool iwl_has_secure_boot(u32 hw_rev, | ||
91 | enum iwl_device_family family) | ||
92 | { | ||
93 | /* return 1 only for family 8000 B0 */ | ||
94 | if ((family == IWL_DEVICE_FAMILY_8000) && (hw_rev & 0xC)) | ||
95 | return 1; | ||
96 | |||
97 | return 0; | ||
98 | } | ||
99 | |||
90 | /* | 100 | /* |
91 | * LED mode | 101 | * LED mode |
92 | * IWL_LED_DEFAULT: use device default | 102 | * IWL_LED_DEFAULT: use device default |
@@ -246,6 +256,7 @@ struct iwl_pwr_tx_backoff { | |||
246 | * @nvm_hw_section_num: the ID of the HW NVM section | 256 | * @nvm_hw_section_num: the ID of the HW NVM section |
247 | * @pwr_tx_backoffs: translation table between power limits and backoffs | 257 | * @pwr_tx_backoffs: translation table between power limits and backoffs |
248 | * @max_rx_agg_size: max RX aggregation size of the ADDBA request/response | 258 | * @max_rx_agg_size: max RX aggregation size of the ADDBA request/response |
259 | * @max_tx_agg_size: max TX aggregation size of the ADDBA request/response | ||
249 | * | 260 | * |
250 | * We enable the driver to be backward compatible wrt. hardware features. | 261 | * We enable the driver to be backward compatible wrt. hardware features. |
251 | * API differences in uCode shouldn't be handled here but through TLVs | 262 | * API differences in uCode shouldn't be handled here but through TLVs |
@@ -285,6 +296,7 @@ struct iwl_cfg { | |||
285 | const char *default_nvm_file; | 296 | const char *default_nvm_file; |
286 | unsigned int max_rx_agg_size; | 297 | unsigned int max_rx_agg_size; |
287 | bool disable_dummy_notification; | 298 | bool disable_dummy_notification; |
299 | unsigned int max_tx_agg_size; | ||
288 | }; | 300 | }; |
289 | 301 | ||
290 | /* | 302 | /* |
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c index 0f1084f09caa..d9fa8e034da2 100644 --- a/drivers/net/wireless/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/iwlwifi/iwl-drv.c | |||
@@ -807,19 +807,16 @@ static int iwl_parse_tlv_firmware(struct iwl_drv *drv, | |||
807 | iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR, | 807 | iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_REGULAR, |
808 | tlv_len); | 808 | tlv_len); |
809 | drv->fw.mvm_fw = true; | 809 | drv->fw.mvm_fw = true; |
810 | drv->fw.img[IWL_UCODE_REGULAR].is_secure = true; | ||
811 | break; | 810 | break; |
812 | case IWL_UCODE_TLV_SECURE_SEC_INIT: | 811 | case IWL_UCODE_TLV_SECURE_SEC_INIT: |
813 | iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT, | 812 | iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_INIT, |
814 | tlv_len); | 813 | tlv_len); |
815 | drv->fw.mvm_fw = true; | 814 | drv->fw.mvm_fw = true; |
816 | drv->fw.img[IWL_UCODE_INIT].is_secure = true; | ||
817 | break; | 815 | break; |
818 | case IWL_UCODE_TLV_SECURE_SEC_WOWLAN: | 816 | case IWL_UCODE_TLV_SECURE_SEC_WOWLAN: |
819 | iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN, | 817 | iwl_store_ucode_sec(pieces, tlv_data, IWL_UCODE_WOWLAN, |
820 | tlv_len); | 818 | tlv_len); |
821 | drv->fw.mvm_fw = true; | 819 | drv->fw.mvm_fw = true; |
822 | drv->fw.img[IWL_UCODE_WOWLAN].is_secure = true; | ||
823 | break; | 820 | break; |
824 | case IWL_UCODE_TLV_NUM_OF_CPU: | 821 | case IWL_UCODE_TLV_NUM_OF_CPU: |
825 | if (tlv_len != sizeof(u32)) | 822 | if (tlv_len != sizeof(u32)) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h index 4f6e66892acc..6f7ae5f7bdae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-fw.h +++ b/drivers/net/wireless/iwlwifi/iwl-fw.h | |||
@@ -227,7 +227,6 @@ struct fw_desc { | |||
227 | 227 | ||
228 | struct fw_img { | 228 | struct fw_img { |
229 | struct fw_desc sec[IWL_UCODE_SECTION_MAX]; | 229 | struct fw_desc sec[IWL_UCODE_SECTION_MAX]; |
230 | bool is_secure; | ||
231 | bool is_dual_cpus; | 230 | bool is_dual_cpus; |
232 | }; | 231 | }; |
233 | 232 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h index d8fc548c0d6c..0768f83e709d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/iwlwifi/iwl-trans.h | |||
@@ -535,9 +535,7 @@ struct iwl_trans_ops { | |||
535 | void (*ref)(struct iwl_trans *trans); | 535 | void (*ref)(struct iwl_trans *trans); |
536 | void (*unref)(struct iwl_trans *trans); | 536 | void (*unref)(struct iwl_trans *trans); |
537 | 537 | ||
538 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
539 | struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans); | 538 | struct iwl_trans_dump_data *(*dump_data)(struct iwl_trans *trans); |
540 | #endif | ||
541 | }; | 539 | }; |
542 | 540 | ||
543 | /** | 541 | /** |
@@ -704,7 +702,6 @@ static inline void iwl_trans_unref(struct iwl_trans *trans) | |||
704 | trans->ops->unref(trans); | 702 | trans->ops->unref(trans); |
705 | } | 703 | } |
706 | 704 | ||
707 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
708 | static inline struct iwl_trans_dump_data * | 705 | static inline struct iwl_trans_dump_data * |
709 | iwl_trans_dump_data(struct iwl_trans *trans) | 706 | iwl_trans_dump_data(struct iwl_trans *trans) |
710 | { | 707 | { |
@@ -712,7 +709,6 @@ iwl_trans_dump_data(struct iwl_trans *trans) | |||
712 | return NULL; | 709 | return NULL; |
713 | return trans->ops->dump_data(trans); | 710 | return trans->ops->dump_data(trans); |
714 | } | 711 | } |
715 | #endif | ||
716 | 712 | ||
717 | static inline int iwl_trans_send_cmd(struct iwl_trans *trans, | 713 | static inline int iwl_trans_send_cmd(struct iwl_trans *trans, |
718 | struct iwl_host_cmd *cmd) | 714 | struct iwl_host_cmd *cmd) |
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index da2ffb785194..508c81359e41 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c | |||
@@ -72,8 +72,6 @@ | |||
72 | #include "mvm.h" | 72 | #include "mvm.h" |
73 | #include "iwl-debug.h" | 73 | #include "iwl-debug.h" |
74 | 74 | ||
75 | #define BT_ANTENNA_COUPLING_THRESHOLD (30) | ||
76 | |||
77 | const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = { | 75 | const u32 iwl_bt_ctl_kill_msk[BT_KILL_MSK_MAX] = { |
78 | [BT_KILL_MSK_DEFAULT] = 0xfffffc00, | 76 | [BT_KILL_MSK_DEFAULT] = 0xfffffc00, |
79 | [BT_KILL_MSK_NEVER] = 0xffffffff, | 77 | [BT_KILL_MSK_NEVER] = 0xffffffff, |
@@ -302,11 +300,6 @@ static const __le64 iwl_ci_mask[][3] = { | |||
302 | }, | 300 | }, |
303 | }; | 301 | }; |
304 | 302 | ||
305 | static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = { | ||
306 | cpu_to_le32(0x2e402280), | ||
307 | cpu_to_le32(0x7711a751), | ||
308 | }; | ||
309 | |||
310 | struct corunning_block_luts { | 303 | struct corunning_block_luts { |
311 | u8 range; | 304 | u8 range; |
312 | __le32 lut20[BT_COEX_CORUN_LUT_SIZE]; | 305 | __le32 lut20[BT_COEX_CORUN_LUT_SIZE]; |
@@ -605,7 +598,7 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
605 | 598 | ||
606 | bt_cmd->max_kill = cpu_to_le32(5); | 599 | bt_cmd->max_kill = cpu_to_le32(5); |
607 | bt_cmd->bt4_antenna_isolation_thr = | 600 | bt_cmd->bt4_antenna_isolation_thr = |
608 | cpu_to_le32(BT_ANTENNA_COUPLING_THRESHOLD); | 601 | cpu_to_le32(IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS); |
609 | bt_cmd->bt4_tx_tx_delta_freq_thr = cpu_to_le32(15); | 602 | bt_cmd->bt4_tx_tx_delta_freq_thr = cpu_to_le32(15); |
610 | bt_cmd->bt4_tx_rx_max_freq0 = cpu_to_le32(15); | 603 | bt_cmd->bt4_tx_rx_max_freq0 = cpu_to_le32(15); |
611 | bt_cmd->override_primary_lut = cpu_to_le32(BT_COEX_INVALID_LUT); | 604 | bt_cmd->override_primary_lut = cpu_to_le32(BT_COEX_INVALID_LUT); |
@@ -638,8 +631,8 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) | |||
638 | 631 | ||
639 | memcpy(&bt_cmd->mplut_prio_boost, iwl_bt_prio_boost, | 632 | memcpy(&bt_cmd->mplut_prio_boost, iwl_bt_prio_boost, |
640 | sizeof(iwl_bt_prio_boost)); | 633 | sizeof(iwl_bt_prio_boost)); |
641 | memcpy(&bt_cmd->multiprio_lut, iwl_bt_mprio_lut, | 634 | bt_cmd->multiprio_lut[0] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG0); |
642 | sizeof(iwl_bt_mprio_lut)); | 635 | bt_cmd->multiprio_lut[1] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG1); |
643 | 636 | ||
644 | send_cmd: | 637 | send_cmd: |
645 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); | 638 | memset(&mvm->last_bt_notif, 0, sizeof(mvm->last_bt_notif)); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c index 8a1d2f33d5b7..b571e1b0550c 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex_legacy.c | |||
@@ -102,8 +102,6 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = { | |||
102 | 102 | ||
103 | #undef EVENT_PRIO_ANT | 103 | #undef EVENT_PRIO_ANT |
104 | 104 | ||
105 | #define BT_ANTENNA_COUPLING_THRESHOLD (30) | ||
106 | |||
107 | static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) | 105 | static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm) |
108 | { | 106 | { |
109 | if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) | 107 | if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) |
@@ -290,11 +288,6 @@ static const __le64 iwl_ci_mask[][3] = { | |||
290 | }, | 288 | }, |
291 | }; | 289 | }; |
292 | 290 | ||
293 | static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = { | ||
294 | cpu_to_le32(0x2e402280), | ||
295 | cpu_to_le32(0x7711a751), | ||
296 | }; | ||
297 | |||
298 | struct corunning_block_luts { | 291 | struct corunning_block_luts { |
299 | u8 range; | 292 | u8 range; |
300 | __le32 lut20[BT_COEX_CORUN_LUT_SIZE]; | 293 | __le32 lut20[BT_COEX_CORUN_LUT_SIZE]; |
@@ -593,7 +586,8 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm) | |||
593 | } | 586 | } |
594 | 587 | ||
595 | bt_cmd->max_kill = 5; | 588 | bt_cmd->max_kill = 5; |
596 | bt_cmd->bt4_antenna_isolation_thr = BT_ANTENNA_COUPLING_THRESHOLD; | 589 | bt_cmd->bt4_antenna_isolation_thr = |
590 | IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS; | ||
597 | bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling; | 591 | bt_cmd->bt4_antenna_isolation = iwlwifi_mod_params.ant_coupling; |
598 | bt_cmd->bt4_tx_tx_delta_freq_thr = 15; | 592 | bt_cmd->bt4_tx_tx_delta_freq_thr = 15; |
599 | bt_cmd->bt4_tx_rx_max_freq0 = 15; | 593 | bt_cmd->bt4_tx_rx_max_freq0 = 15; |
@@ -649,8 +643,8 @@ int iwl_send_bt_init_conf_old(struct iwl_mvm *mvm) | |||
649 | 643 | ||
650 | memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost, | 644 | memcpy(&bt_cmd->bt_prio_boost, iwl_bt_prio_boost, |
651 | sizeof(iwl_bt_prio_boost)); | 645 | sizeof(iwl_bt_prio_boost)); |
652 | memcpy(&bt_cmd->bt4_multiprio_lut, iwl_bt_mprio_lut, | 646 | bt_cmd->bt4_multiprio_lut[0] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG0); |
653 | sizeof(iwl_bt_mprio_lut)); | 647 | bt_cmd->bt4_multiprio_lut[1] = cpu_to_le32(IWL_MVM_BT_COEX_MPLUT_REG1); |
654 | 648 | ||
655 | send_cmd: | 649 | send_cmd: |
656 | memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old)); | 650 | memset(&mvm->last_bt_notif_old, 0, sizeof(mvm->last_bt_notif_old)); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/constants.h b/drivers/net/wireless/iwlwifi/mvm/constants.h index d4dfbe4cb66d..5c1ea80d5e3b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/constants.h +++ b/drivers/net/wireless/iwlwifi/mvm/constants.h | |||
@@ -92,8 +92,13 @@ | |||
92 | #define IWL_MVM_BT_COEX_SYNC2SCO 1 | 92 | #define IWL_MVM_BT_COEX_SYNC2SCO 1 |
93 | #define IWL_MVM_BT_COEX_CORUNNING 0 | 93 | #define IWL_MVM_BT_COEX_CORUNNING 0 |
94 | #define IWL_MVM_BT_COEX_MPLUT 1 | 94 | #define IWL_MVM_BT_COEX_MPLUT 1 |
95 | #define IWL_MVM_BT_COEX_MPLUT_REG0 0x2e402280 | ||
96 | #define IWL_MVM_BT_COEX_MPLUT_REG1 0x7711a751 | ||
97 | #define IWL_MVM_BT_COEX_ANTENNA_COUPLING_THRS 30 | ||
95 | #define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0 | 98 | #define IWL_MVM_FW_MCAST_FILTER_PASS_ALL 0 |
99 | #define IWL_MVM_FW_BCAST_FILTER_PASS_ALL 0 | ||
96 | #define IWL_MVM_QUOTA_THRESHOLD 8 | 100 | #define IWL_MVM_QUOTA_THRESHOLD 8 |
97 | #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 | 101 | #define IWL_MVM_RS_RSSI_BASED_INIT_RATE 0 |
102 | #define IWL_MVM_RS_DISABLE_MIMO 0 | ||
98 | 103 | ||
99 | #endif /* __MVM_CONSTANTS_H */ | 104 | #endif /* __MVM_CONSTANTS_H */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c index c17be0fb7283..3bbb511b0b38 100644 --- a/drivers/net/wireless/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/iwlwifi/mvm/d3.c | |||
@@ -601,33 +601,6 @@ static int iwl_mvm_send_remote_wake_cfg(struct iwl_mvm *mvm, | |||
601 | return ret; | 601 | return ret; |
602 | } | 602 | } |
603 | 603 | ||
604 | struct iwl_d3_iter_data { | ||
605 | struct iwl_mvm *mvm; | ||
606 | struct ieee80211_vif *vif; | ||
607 | bool error; | ||
608 | }; | ||
609 | |||
610 | static void iwl_mvm_d3_iface_iterator(void *_data, u8 *mac, | ||
611 | struct ieee80211_vif *vif) | ||
612 | { | ||
613 | struct iwl_d3_iter_data *data = _data; | ||
614 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
615 | |||
616 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | ||
617 | return; | ||
618 | |||
619 | if (mvmvif->ap_sta_id == IWL_MVM_STATION_COUNT) | ||
620 | return; | ||
621 | |||
622 | if (data->vif) { | ||
623 | IWL_ERR(data->mvm, "More than one managed interface active!\n"); | ||
624 | data->error = true; | ||
625 | return; | ||
626 | } | ||
627 | |||
628 | data->vif = vif; | ||
629 | } | ||
630 | |||
631 | static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 604 | static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
632 | struct ieee80211_sta *ap_sta) | 605 | struct ieee80211_sta *ap_sta) |
633 | { | 606 | { |
@@ -783,6 +756,35 @@ void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
783 | IWL_ERR(mvm, "failed to set non-QoS seqno\n"); | 756 | IWL_ERR(mvm, "failed to set non-QoS seqno\n"); |
784 | } | 757 | } |
785 | 758 | ||
759 | static int iwl_mvm_switch_to_d3(struct iwl_mvm *mvm) | ||
760 | { | ||
761 | iwl_mvm_cancel_scan(mvm); | ||
762 | |||
763 | iwl_trans_stop_device(mvm->trans); | ||
764 | |||
765 | /* | ||
766 | * Set the HW restart bit -- this is mostly true as we're | ||
767 | * going to load new firmware and reprogram that, though | ||
768 | * the reprogramming is going to be manual to avoid adding | ||
769 | * all the MACs that aren't support. | ||
770 | * We don't have to clear up everything though because the | ||
771 | * reprogramming is manual. When we resume, we'll actually | ||
772 | * go through a proper restart sequence again to switch | ||
773 | * back to the runtime firmware image. | ||
774 | */ | ||
775 | set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); | ||
776 | |||
777 | /* We reprogram keys and shouldn't allocate new key indices */ | ||
778 | memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); | ||
779 | |||
780 | mvm->ptk_ivlen = 0; | ||
781 | mvm->ptk_icvlen = 0; | ||
782 | mvm->ptk_ivlen = 0; | ||
783 | mvm->ptk_icvlen = 0; | ||
784 | |||
785 | return iwl_mvm_load_d3_fw(mvm); | ||
786 | } | ||
787 | |||
786 | static int | 788 | static int |
787 | iwl_mvm_send_wowlan_config_cmd(struct iwl_mvm *mvm, | 789 | iwl_mvm_send_wowlan_config_cmd(struct iwl_mvm *mvm, |
788 | const struct iwl_wowlan_config_cmd_v3 *cmd) | 790 | const struct iwl_wowlan_config_cmd_v3 *cmd) |
@@ -797,116 +799,52 @@ iwl_mvm_send_wowlan_config_cmd(struct iwl_mvm *mvm, | |||
797 | cmd_len, cmd); | 799 | cmd_len, cmd); |
798 | } | 800 | } |
799 | 801 | ||
800 | static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | 802 | static int |
801 | struct cfg80211_wowlan *wowlan, | 803 | iwl_mvm_get_wowlan_config(struct iwl_mvm *mvm, |
802 | bool test) | 804 | struct cfg80211_wowlan *wowlan, |
805 | struct iwl_wowlan_config_cmd_v3 *wowlan_config_cmd, | ||
806 | struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif, | ||
807 | struct ieee80211_sta *ap_sta) | ||
803 | { | 808 | { |
804 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
805 | struct iwl_d3_iter_data suspend_iter_data = { | ||
806 | .mvm = mvm, | ||
807 | }; | ||
808 | struct ieee80211_vif *vif; | ||
809 | struct iwl_mvm_vif *mvmvif; | ||
810 | struct ieee80211_sta *ap_sta; | ||
811 | struct iwl_mvm_sta *mvm_ap_sta; | ||
812 | struct iwl_wowlan_config_cmd_v3 wowlan_config_cmd = {}; | ||
813 | struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; | ||
814 | struct iwl_wowlan_tkip_params_cmd tkip_cmd = {}; | ||
815 | struct iwl_d3_manager_config d3_cfg_cmd_data = { | ||
816 | /* | ||
817 | * Program the minimum sleep time to 10 seconds, as many | ||
818 | * platforms have issues processing a wakeup signal while | ||
819 | * still being in the process of suspending. | ||
820 | */ | ||
821 | .min_sleep_time = cpu_to_le32(10 * 1000 * 1000), | ||
822 | }; | ||
823 | struct iwl_host_cmd d3_cfg_cmd = { | ||
824 | .id = D3_CONFIG_CMD, | ||
825 | .flags = CMD_WANT_SKB, | ||
826 | .data[0] = &d3_cfg_cmd_data, | ||
827 | .len[0] = sizeof(d3_cfg_cmd_data), | ||
828 | }; | ||
829 | struct wowlan_key_data key_data = { | ||
830 | .use_rsc_tsc = false, | ||
831 | .tkip = &tkip_cmd, | ||
832 | .use_tkip = false, | ||
833 | }; | ||
834 | int ret; | 809 | int ret; |
835 | int len __maybe_unused; | 810 | struct iwl_mvm_sta *mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv; |
836 | |||
837 | if (!wowlan) { | ||
838 | /* | ||
839 | * mac80211 shouldn't get here, but for D3 test | ||
840 | * it doesn't warrant a warning | ||
841 | */ | ||
842 | WARN_ON(!test); | ||
843 | return -EINVAL; | ||
844 | } | ||
845 | |||
846 | key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL); | ||
847 | if (!key_data.rsc_tsc) | ||
848 | return -ENOMEM; | ||
849 | |||
850 | mutex_lock(&mvm->mutex); | ||
851 | |||
852 | /* see if there's only a single BSS vif and it's associated */ | ||
853 | ieee80211_iterate_active_interfaces_atomic( | ||
854 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
855 | iwl_mvm_d3_iface_iterator, &suspend_iter_data); | ||
856 | |||
857 | if (suspend_iter_data.error || !suspend_iter_data.vif) { | ||
858 | ret = 1; | ||
859 | goto out_noreset; | ||
860 | } | ||
861 | |||
862 | vif = suspend_iter_data.vif; | ||
863 | mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
864 | |||
865 | ap_sta = rcu_dereference_protected( | ||
866 | mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], | ||
867 | lockdep_is_held(&mvm->mutex)); | ||
868 | if (IS_ERR_OR_NULL(ap_sta)) { | ||
869 | ret = -EINVAL; | ||
870 | goto out_noreset; | ||
871 | } | ||
872 | |||
873 | mvm_ap_sta = (struct iwl_mvm_sta *)ap_sta->drv_priv; | ||
874 | 811 | ||
875 | /* TODO: wowlan_config_cmd.common.wowlan_ba_teardown_tids */ | 812 | /* TODO: wowlan_config_cmd->common.wowlan_ba_teardown_tids */ |
876 | 813 | ||
877 | wowlan_config_cmd.common.is_11n_connection = | 814 | wowlan_config_cmd->common.is_11n_connection = |
878 | ap_sta->ht_cap.ht_supported; | 815 | ap_sta->ht_cap.ht_supported; |
879 | 816 | ||
880 | /* Query the last used seqno and set it */ | 817 | /* Query the last used seqno and set it */ |
881 | ret = iwl_mvm_get_last_nonqos_seq(mvm, vif); | 818 | ret = iwl_mvm_get_last_nonqos_seq(mvm, vif); |
882 | if (ret < 0) | 819 | if (ret < 0) |
883 | goto out_noreset; | 820 | return ret; |
884 | wowlan_config_cmd.common.non_qos_seq = cpu_to_le16(ret); | ||
885 | 821 | ||
886 | iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, &wowlan_config_cmd.common); | 822 | wowlan_config_cmd->common.non_qos_seq = cpu_to_le16(ret); |
823 | |||
824 | iwl_mvm_set_wowlan_qos_seq(mvm_ap_sta, &wowlan_config_cmd->common); | ||
887 | 825 | ||
888 | if (wowlan->disconnect) | 826 | if (wowlan->disconnect) |
889 | wowlan_config_cmd.common.wakeup_filter |= | 827 | wowlan_config_cmd->common.wakeup_filter |= |
890 | cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS | | 828 | cpu_to_le32(IWL_WOWLAN_WAKEUP_BEACON_MISS | |
891 | IWL_WOWLAN_WAKEUP_LINK_CHANGE); | 829 | IWL_WOWLAN_WAKEUP_LINK_CHANGE); |
892 | if (wowlan->magic_pkt) | 830 | if (wowlan->magic_pkt) |
893 | wowlan_config_cmd.common.wakeup_filter |= | 831 | wowlan_config_cmd->common.wakeup_filter |= |
894 | cpu_to_le32(IWL_WOWLAN_WAKEUP_MAGIC_PACKET); | 832 | cpu_to_le32(IWL_WOWLAN_WAKEUP_MAGIC_PACKET); |
895 | if (wowlan->gtk_rekey_failure) | 833 | if (wowlan->gtk_rekey_failure) |
896 | wowlan_config_cmd.common.wakeup_filter |= | 834 | wowlan_config_cmd->common.wakeup_filter |= |
897 | cpu_to_le32(IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL); | 835 | cpu_to_le32(IWL_WOWLAN_WAKEUP_GTK_REKEY_FAIL); |
898 | if (wowlan->eap_identity_req) | 836 | if (wowlan->eap_identity_req) |
899 | wowlan_config_cmd.common.wakeup_filter |= | 837 | wowlan_config_cmd->common.wakeup_filter |= |
900 | cpu_to_le32(IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ); | 838 | cpu_to_le32(IWL_WOWLAN_WAKEUP_EAP_IDENT_REQ); |
901 | if (wowlan->four_way_handshake) | 839 | if (wowlan->four_way_handshake) |
902 | wowlan_config_cmd.common.wakeup_filter |= | 840 | wowlan_config_cmd->common.wakeup_filter |= |
903 | cpu_to_le32(IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE); | 841 | cpu_to_le32(IWL_WOWLAN_WAKEUP_4WAY_HANDSHAKE); |
904 | if (wowlan->n_patterns) | 842 | if (wowlan->n_patterns) |
905 | wowlan_config_cmd.common.wakeup_filter |= | 843 | wowlan_config_cmd->common.wakeup_filter |= |
906 | cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH); | 844 | cpu_to_le32(IWL_WOWLAN_WAKEUP_PATTERN_MATCH); |
907 | 845 | ||
908 | if (wowlan->rfkill_release) | 846 | if (wowlan->rfkill_release) |
909 | wowlan_config_cmd.common.wakeup_filter |= | 847 | wowlan_config_cmd->common.wakeup_filter |= |
910 | cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT); | 848 | cpu_to_le32(IWL_WOWLAN_WAKEUP_RF_KILL_DEASSERT); |
911 | 849 | ||
912 | if (wowlan->tcp) { | 850 | if (wowlan->tcp) { |
@@ -914,44 +852,39 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
914 | * Set the "link change" (really "link lost") flag as well | 852 | * Set the "link change" (really "link lost") flag as well |
915 | * since that implies losing the TCP connection. | 853 | * since that implies losing the TCP connection. |
916 | */ | 854 | */ |
917 | wowlan_config_cmd.common.wakeup_filter |= | 855 | wowlan_config_cmd->common.wakeup_filter |= |
918 | cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS | | 856 | cpu_to_le32(IWL_WOWLAN_WAKEUP_REMOTE_LINK_LOSS | |
919 | IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE | | 857 | IWL_WOWLAN_WAKEUP_REMOTE_SIGNATURE_TABLE | |
920 | IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET | | 858 | IWL_WOWLAN_WAKEUP_REMOTE_WAKEUP_PACKET | |
921 | IWL_WOWLAN_WAKEUP_LINK_CHANGE); | 859 | IWL_WOWLAN_WAKEUP_LINK_CHANGE); |
922 | } | 860 | } |
923 | 861 | ||
924 | iwl_mvm_cancel_scan(mvm); | 862 | return 0; |
925 | 863 | } | |
926 | iwl_trans_stop_device(mvm->trans); | ||
927 | |||
928 | /* | ||
929 | * Set the HW restart bit -- this is mostly true as we're | ||
930 | * going to load new firmware and reprogram that, though | ||
931 | * the reprogramming is going to be manual to avoid adding | ||
932 | * all the MACs that aren't support. | ||
933 | * We don't have to clear up everything though because the | ||
934 | * reprogramming is manual. When we resume, we'll actually | ||
935 | * go through a proper restart sequence again to switch | ||
936 | * back to the runtime firmware image. | ||
937 | */ | ||
938 | set_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status); | ||
939 | |||
940 | /* We reprogram keys and shouldn't allocate new key indices */ | ||
941 | memset(mvm->fw_key_table, 0, sizeof(mvm->fw_key_table)); | ||
942 | |||
943 | mvm->ptk_ivlen = 0; | ||
944 | mvm->ptk_icvlen = 0; | ||
945 | mvm->ptk_ivlen = 0; | ||
946 | mvm->ptk_icvlen = 0; | ||
947 | 864 | ||
948 | ret = iwl_mvm_load_d3_fw(mvm); | 865 | static int |
949 | if (ret) | 866 | iwl_mvm_wowlan_config(struct iwl_mvm *mvm, |
950 | goto out; | 867 | struct cfg80211_wowlan *wowlan, |
868 | struct iwl_wowlan_config_cmd_v3 *wowlan_config_cmd, | ||
869 | struct ieee80211_vif *vif, struct iwl_mvm_vif *mvmvif, | ||
870 | struct ieee80211_sta *ap_sta) | ||
871 | { | ||
872 | struct iwl_wowlan_kek_kck_material_cmd kek_kck_cmd = {}; | ||
873 | struct iwl_wowlan_tkip_params_cmd tkip_cmd = {}; | ||
874 | struct wowlan_key_data key_data = { | ||
875 | .use_rsc_tsc = false, | ||
876 | .tkip = &tkip_cmd, | ||
877 | .use_tkip = false, | ||
878 | }; | ||
879 | int ret; | ||
951 | 880 | ||
952 | ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta); | 881 | ret = iwl_mvm_d3_reprogram(mvm, vif, ap_sta); |
953 | if (ret) | 882 | if (ret) |
954 | goto out; | 883 | return ret; |
884 | |||
885 | key_data.rsc_tsc = kzalloc(sizeof(*key_data.rsc_tsc), GFP_KERNEL); | ||
886 | if (!key_data.rsc_tsc) | ||
887 | return -ENOMEM; | ||
955 | 888 | ||
956 | if (!iwlwifi_mod_params.sw_crypto) { | 889 | if (!iwlwifi_mod_params.sw_crypto) { |
957 | /* | 890 | /* |
@@ -1010,7 +943,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
1010 | } | 943 | } |
1011 | } | 944 | } |
1012 | 945 | ||
1013 | ret = iwl_mvm_send_wowlan_config_cmd(mvm, &wowlan_config_cmd); | 946 | ret = iwl_mvm_send_wowlan_config_cmd(mvm, wowlan_config_cmd); |
1014 | if (ret) | 947 | if (ret) |
1015 | goto out; | 948 | goto out; |
1016 | 949 | ||
@@ -1023,8 +956,93 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
1023 | goto out; | 956 | goto out; |
1024 | 957 | ||
1025 | ret = iwl_mvm_send_remote_wake_cfg(mvm, vif, wowlan->tcp); | 958 | ret = iwl_mvm_send_remote_wake_cfg(mvm, vif, wowlan->tcp); |
1026 | if (ret) | 959 | |
1027 | goto out; | 960 | out: |
961 | kfree(key_data.rsc_tsc); | ||
962 | return ret; | ||
963 | } | ||
964 | |||
965 | static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | ||
966 | struct cfg80211_wowlan *wowlan, | ||
967 | bool test) | ||
968 | { | ||
969 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
970 | struct ieee80211_vif *vif = NULL; | ||
971 | struct iwl_mvm_vif *mvmvif = NULL; | ||
972 | struct ieee80211_sta *ap_sta = NULL; | ||
973 | struct iwl_wowlan_config_cmd_v3 wowlan_config_cmd = {}; | ||
974 | struct iwl_d3_manager_config d3_cfg_cmd_data = { | ||
975 | /* | ||
976 | * Program the minimum sleep time to 10 seconds, as many | ||
977 | * platforms have issues processing a wakeup signal while | ||
978 | * still being in the process of suspending. | ||
979 | */ | ||
980 | .min_sleep_time = cpu_to_le32(10 * 1000 * 1000), | ||
981 | }; | ||
982 | struct iwl_host_cmd d3_cfg_cmd = { | ||
983 | .id = D3_CONFIG_CMD, | ||
984 | .flags = CMD_WANT_SKB, | ||
985 | .data[0] = &d3_cfg_cmd_data, | ||
986 | .len[0] = sizeof(d3_cfg_cmd_data), | ||
987 | }; | ||
988 | int ret; | ||
989 | int len __maybe_unused; | ||
990 | |||
991 | if (!wowlan) { | ||
992 | /* | ||
993 | * mac80211 shouldn't get here, but for D3 test | ||
994 | * it doesn't warrant a warning | ||
995 | */ | ||
996 | WARN_ON(!test); | ||
997 | return -EINVAL; | ||
998 | } | ||
999 | |||
1000 | mutex_lock(&mvm->mutex); | ||
1001 | |||
1002 | vif = iwl_mvm_get_bss_vif(mvm); | ||
1003 | if (IS_ERR_OR_NULL(vif)) { | ||
1004 | ret = 1; | ||
1005 | goto out_noreset; | ||
1006 | } | ||
1007 | |||
1008 | mvmvif = iwl_mvm_vif_from_mac80211(vif); | ||
1009 | |||
1010 | /* if we're associated, this is wowlan */ | ||
1011 | if (mvmvif->ap_sta_id != IWL_MVM_STATION_COUNT) { | ||
1012 | ap_sta = rcu_dereference_protected( | ||
1013 | mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], | ||
1014 | lockdep_is_held(&mvm->mutex)); | ||
1015 | if (IS_ERR_OR_NULL(ap_sta)) { | ||
1016 | ret = -EINVAL; | ||
1017 | goto out_noreset; | ||
1018 | } | ||
1019 | |||
1020 | ret = iwl_mvm_get_wowlan_config(mvm, wowlan, &wowlan_config_cmd, | ||
1021 | vif, mvmvif, ap_sta); | ||
1022 | if (ret) | ||
1023 | goto out_noreset; | ||
1024 | |||
1025 | ret = iwl_mvm_switch_to_d3(mvm); | ||
1026 | if (ret) | ||
1027 | goto out; | ||
1028 | |||
1029 | ret = iwl_mvm_wowlan_config(mvm, wowlan, &wowlan_config_cmd, | ||
1030 | vif, mvmvif, ap_sta); | ||
1031 | if (ret) | ||
1032 | goto out; | ||
1033 | } else if (mvm->nd_config) { | ||
1034 | ret = iwl_mvm_switch_to_d3(mvm); | ||
1035 | if (ret) | ||
1036 | goto out; | ||
1037 | |||
1038 | ret = iwl_mvm_scan_offload_start(mvm, vif, mvm->nd_config, | ||
1039 | mvm->nd_ies); | ||
1040 | if (ret) | ||
1041 | goto out; | ||
1042 | } else { | ||
1043 | ret = 1; | ||
1044 | goto out_noreset; | ||
1045 | } | ||
1028 | 1046 | ||
1029 | ret = iwl_mvm_power_update_device(mvm); | 1047 | ret = iwl_mvm_power_update_device(mvm); |
1030 | if (ret) | 1048 | if (ret) |
@@ -1060,8 +1078,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw, | |||
1060 | if (ret < 0) | 1078 | if (ret < 0) |
1061 | ieee80211_restart_hw(mvm->hw); | 1079 | ieee80211_restart_hw(mvm->hw); |
1062 | out_noreset: | 1080 | out_noreset: |
1063 | kfree(key_data.rsc_tsc); | ||
1064 | |||
1065 | mutex_unlock(&mvm->mutex); | 1081 | mutex_unlock(&mvm->mutex); |
1066 | 1082 | ||
1067 | return ret; | 1083 | return ret; |
@@ -1592,9 +1608,6 @@ static void iwl_mvm_d3_disconnect_iter(void *data, u8 *mac, | |||
1592 | 1608 | ||
1593 | static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) | 1609 | static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) |
1594 | { | 1610 | { |
1595 | struct iwl_d3_iter_data resume_iter_data = { | ||
1596 | .mvm = mvm, | ||
1597 | }; | ||
1598 | struct ieee80211_vif *vif = NULL; | 1611 | struct ieee80211_vif *vif = NULL; |
1599 | int ret; | 1612 | int ret; |
1600 | enum iwl_d3_status d3_status; | 1613 | enum iwl_d3_status d3_status; |
@@ -1603,15 +1616,10 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) | |||
1603 | mutex_lock(&mvm->mutex); | 1616 | mutex_lock(&mvm->mutex); |
1604 | 1617 | ||
1605 | /* get the BSS vif pointer again */ | 1618 | /* get the BSS vif pointer again */ |
1606 | ieee80211_iterate_active_interfaces_atomic( | 1619 | vif = iwl_mvm_get_bss_vif(mvm); |
1607 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | 1620 | if (IS_ERR_OR_NULL(vif)) |
1608 | iwl_mvm_d3_iface_iterator, &resume_iter_data); | ||
1609 | |||
1610 | if (WARN_ON(resume_iter_data.error || !resume_iter_data.vif)) | ||
1611 | goto out_unlock; | 1621 | goto out_unlock; |
1612 | 1622 | ||
1613 | vif = resume_iter_data.vif; | ||
1614 | |||
1615 | ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test); | 1623 | ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test); |
1616 | if (ret) | 1624 | if (ret) |
1617 | goto out_unlock; | 1625 | goto out_unlock; |
@@ -1741,7 +1749,9 @@ static int iwl_mvm_d3_test_release(struct inode *inode, struct file *file) | |||
1741 | int remaining_time = 10; | 1749 | int remaining_time = 10; |
1742 | 1750 | ||
1743 | mvm->d3_test_active = false; | 1751 | mvm->d3_test_active = false; |
1752 | rtnl_lock(); | ||
1744 | __iwl_mvm_resume(mvm, true); | 1753 | __iwl_mvm_resume(mvm, true); |
1754 | rtnl_unlock(); | ||
1745 | iwl_abort_notification_waits(&mvm->notif_wait); | 1755 | iwl_abort_notification_waits(&mvm->notif_wait); |
1746 | ieee80211_restart_hw(mvm->hw); | 1756 | ieee80211_restart_hw(mvm->hw); |
1747 | 1757 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c index 50527a9bb267..51b7116965ed 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c | |||
@@ -121,78 +121,6 @@ static ssize_t iwl_dbgfs_sta_drain_write(struct iwl_mvm *mvm, char *buf, | |||
121 | return ret; | 121 | return ret; |
122 | } | 122 | } |
123 | 123 | ||
124 | static int iwl_dbgfs_fw_error_dump_open(struct inode *inode, struct file *file) | ||
125 | { | ||
126 | struct iwl_mvm *mvm = inode->i_private; | ||
127 | int ret; | ||
128 | |||
129 | if (!mvm) | ||
130 | return -EINVAL; | ||
131 | |||
132 | mutex_lock(&mvm->mutex); | ||
133 | if (!mvm->fw_error_dump) { | ||
134 | ret = -ENODATA; | ||
135 | goto out; | ||
136 | } | ||
137 | |||
138 | file->private_data = mvm->fw_error_dump; | ||
139 | mvm->fw_error_dump = NULL; | ||
140 | ret = 0; | ||
141 | |||
142 | out: | ||
143 | mutex_unlock(&mvm->mutex); | ||
144 | return ret; | ||
145 | } | ||
146 | |||
147 | static ssize_t iwl_dbgfs_fw_error_dump_read(struct file *file, | ||
148 | char __user *user_buf, | ||
149 | size_t count, loff_t *ppos) | ||
150 | { | ||
151 | struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data; | ||
152 | ssize_t bytes_read = 0; | ||
153 | ssize_t bytes_read_trans = 0; | ||
154 | |||
155 | if (*ppos < dump_ptrs->op_mode_len) | ||
156 | bytes_read += | ||
157 | simple_read_from_buffer(user_buf, count, ppos, | ||
158 | dump_ptrs->op_mode_ptr, | ||
159 | dump_ptrs->op_mode_len); | ||
160 | |||
161 | if (bytes_read < 0 || *ppos < dump_ptrs->op_mode_len) | ||
162 | return bytes_read; | ||
163 | |||
164 | if (dump_ptrs->trans_ptr) { | ||
165 | *ppos -= dump_ptrs->op_mode_len; | ||
166 | bytes_read_trans = | ||
167 | simple_read_from_buffer(user_buf + bytes_read, | ||
168 | count - bytes_read, ppos, | ||
169 | dump_ptrs->trans_ptr->data, | ||
170 | dump_ptrs->trans_ptr->len); | ||
171 | *ppos += dump_ptrs->op_mode_len; | ||
172 | |||
173 | if (bytes_read_trans >= 0) | ||
174 | bytes_read += bytes_read_trans; | ||
175 | else if (!bytes_read) | ||
176 | /* propagate the failure */ | ||
177 | return bytes_read_trans; | ||
178 | } | ||
179 | |||
180 | return bytes_read; | ||
181 | |||
182 | } | ||
183 | |||
184 | static int iwl_dbgfs_fw_error_dump_release(struct inode *inode, | ||
185 | struct file *file) | ||
186 | { | ||
187 | struct iwl_mvm_dump_ptrs *dump_ptrs = (void *)file->private_data; | ||
188 | |||
189 | vfree(dump_ptrs->op_mode_ptr); | ||
190 | vfree(dump_ptrs->trans_ptr); | ||
191 | kfree(dump_ptrs); | ||
192 | |||
193 | return 0; | ||
194 | } | ||
195 | |||
196 | static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, | 124 | static ssize_t iwl_dbgfs_sram_read(struct file *file, char __user *user_buf, |
197 | size_t count, loff_t *ppos) | 125 | size_t count, loff_t *ppos) |
198 | { | 126 | { |
@@ -1250,6 +1178,126 @@ static ssize_t iwl_dbgfs_d3_sram_read(struct file *file, char __user *user_buf, | |||
1250 | 1178 | ||
1251 | return ret; | 1179 | return ret; |
1252 | } | 1180 | } |
1181 | |||
1182 | #define MAX_NUM_ND_MATCHSETS 10 | ||
1183 | |||
1184 | static ssize_t iwl_dbgfs_netdetect_write(struct iwl_mvm *mvm, char *buf, | ||
1185 | size_t count, loff_t *ppos) | ||
1186 | { | ||
1187 | const char *seps = ",\n"; | ||
1188 | char *buf_ptr = buf; | ||
1189 | char *value_str = NULL; | ||
1190 | int ret, i; | ||
1191 | |||
1192 | /* TODO: don't free if write is being called several times in one go */ | ||
1193 | if (mvm->nd_config) { | ||
1194 | kfree(mvm->nd_config->match_sets); | ||
1195 | kfree(mvm->nd_config); | ||
1196 | mvm->nd_config = NULL; | ||
1197 | kfree(mvm->nd_ies); | ||
1198 | mvm->nd_ies = NULL; | ||
1199 | } | ||
1200 | |||
1201 | mvm->nd_ies = kzalloc(sizeof(*mvm->nd_ies), GFP_KERNEL); | ||
1202 | if (!mvm->nd_ies) | ||
1203 | return -ENOMEM; | ||
1204 | |||
1205 | mvm->nd_config = kzalloc(sizeof(*mvm->nd_config) + | ||
1206 | (11 * sizeof(struct ieee80211_channel *)), | ||
1207 | GFP_KERNEL); | ||
1208 | if (!mvm->nd_config) { | ||
1209 | ret = -ENOMEM; | ||
1210 | goto out_free; | ||
1211 | } | ||
1212 | |||
1213 | mvm->nd_config->n_channels = 11; | ||
1214 | mvm->nd_config->scan_width = NL80211_BSS_CHAN_WIDTH_20; | ||
1215 | mvm->nd_config->interval = 5; | ||
1216 | mvm->nd_config->min_rssi_thold = -80; | ||
1217 | for (i = 0; i < mvm->nd_config->n_channels; i++) | ||
1218 | mvm->nd_config->channels[i] = &mvm->nvm_data->channels[i]; | ||
1219 | |||
1220 | mvm->nd_config->match_sets = | ||
1221 | kcalloc(MAX_NUM_ND_MATCHSETS, | ||
1222 | sizeof(*mvm->nd_config->match_sets), | ||
1223 | GFP_KERNEL); | ||
1224 | if (!mvm->nd_config->match_sets) { | ||
1225 | ret = -ENOMEM; | ||
1226 | goto out_free; | ||
1227 | } | ||
1228 | |||
1229 | while ((value_str = strsep(&buf_ptr, seps)) && | ||
1230 | strlen(value_str)) { | ||
1231 | struct cfg80211_match_set *set; | ||
1232 | |||
1233 | if (mvm->nd_config->n_match_sets >= MAX_NUM_ND_MATCHSETS) { | ||
1234 | ret = -EINVAL; | ||
1235 | goto out_free; | ||
1236 | } | ||
1237 | |||
1238 | set = &mvm->nd_config->match_sets[mvm->nd_config->n_match_sets]; | ||
1239 | set->ssid.ssid_len = strlen(value_str); | ||
1240 | |||
1241 | if (set->ssid.ssid_len > IEEE80211_MAX_SSID_LEN) { | ||
1242 | ret = -EINVAL; | ||
1243 | goto out_free; | ||
1244 | } | ||
1245 | |||
1246 | memcpy(set->ssid.ssid, value_str, set->ssid.ssid_len); | ||
1247 | |||
1248 | mvm->nd_config->n_match_sets++; | ||
1249 | } | ||
1250 | |||
1251 | ret = count; | ||
1252 | |||
1253 | if (mvm->nd_config->n_match_sets) | ||
1254 | goto out; | ||
1255 | |||
1256 | out_free: | ||
1257 | if (mvm->nd_config) | ||
1258 | kfree(mvm->nd_config->match_sets); | ||
1259 | kfree(mvm->nd_config); | ||
1260 | mvm->nd_config = NULL; | ||
1261 | kfree(mvm->nd_ies); | ||
1262 | mvm->nd_ies = NULL; | ||
1263 | out: | ||
1264 | return ret; | ||
1265 | } | ||
1266 | |||
1267 | static ssize_t | ||
1268 | iwl_dbgfs_netdetect_read(struct file *file, char __user *user_buf, | ||
1269 | size_t count, loff_t *ppos) | ||
1270 | { | ||
1271 | struct iwl_mvm *mvm = file->private_data; | ||
1272 | size_t bufsz, ret; | ||
1273 | char *buf; | ||
1274 | int i, n_match_sets, pos = 0; | ||
1275 | |||
1276 | n_match_sets = mvm->nd_config ? mvm->nd_config->n_match_sets : 0; | ||
1277 | |||
1278 | bufsz = n_match_sets * (IEEE80211_MAX_SSID_LEN + 1) + 1; | ||
1279 | buf = kzalloc(bufsz, GFP_KERNEL); | ||
1280 | if (!buf) | ||
1281 | return -ENOMEM; | ||
1282 | |||
1283 | for (i = 0; i < n_match_sets; i++) { | ||
1284 | if (pos + | ||
1285 | mvm->nd_config->match_sets[i].ssid.ssid_len + 2 > bufsz) { | ||
1286 | ret = -EIO; | ||
1287 | goto out; | ||
1288 | } | ||
1289 | |||
1290 | memcpy(buf + pos, mvm->nd_config->match_sets[i].ssid.ssid, | ||
1291 | mvm->nd_config->match_sets[i].ssid.ssid_len); | ||
1292 | pos += mvm->nd_config->match_sets[i].ssid.ssid_len; | ||
1293 | buf[pos++] = '\n'; | ||
1294 | } | ||
1295 | |||
1296 | ret = simple_read_from_buffer(user_buf, count, ppos, buf, pos); | ||
1297 | out: | ||
1298 | kfree(buf); | ||
1299 | return ret; | ||
1300 | } | ||
1253 | #endif | 1301 | #endif |
1254 | 1302 | ||
1255 | #define PRINT_MVM_REF(ref) do { \ | 1303 | #define PRINT_MVM_REF(ref) do { \ |
@@ -1415,12 +1463,6 @@ MVM_DEBUGFS_WRITE_FILE_OPS(bt_force_ant, 10); | |||
1415 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); | 1463 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(scan_ant_rxchain, 8); |
1416 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); | 1464 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d0i3_refs, 8); |
1417 | 1465 | ||
1418 | static const struct file_operations iwl_dbgfs_fw_error_dump_ops = { | ||
1419 | .open = iwl_dbgfs_fw_error_dump_open, | ||
1420 | .read = iwl_dbgfs_fw_error_dump_read, | ||
1421 | .release = iwl_dbgfs_fw_error_dump_release, | ||
1422 | }; | ||
1423 | |||
1424 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING | 1466 | #ifdef CONFIG_IWLWIFI_BCAST_FILTERING |
1425 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); | 1467 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters, 256); |
1426 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); | 1468 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); |
@@ -1428,6 +1470,7 @@ MVM_DEBUGFS_READ_WRITE_FILE_OPS(bcast_filters_macs, 256); | |||
1428 | 1470 | ||
1429 | #ifdef CONFIG_PM_SLEEP | 1471 | #ifdef CONFIG_PM_SLEEP |
1430 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8); | 1472 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(d3_sram, 8); |
1473 | MVM_DEBUGFS_READ_WRITE_FILE_OPS(netdetect, 384); | ||
1431 | #endif | 1474 | #endif |
1432 | 1475 | ||
1433 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | 1476 | int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) |
@@ -1446,7 +1489,6 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
1446 | S_IWUSR | S_IRUSR); | 1489 | S_IWUSR | S_IRUSR); |
1447 | MVM_DEBUGFS_ADD_FILE(nic_temp, dbgfs_dir, S_IRUSR); | 1490 | MVM_DEBUGFS_ADD_FILE(nic_temp, dbgfs_dir, S_IRUSR); |
1448 | MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); | 1491 | MVM_DEBUGFS_ADD_FILE(stations, dbgfs_dir, S_IRUSR); |
1449 | MVM_DEBUGFS_ADD_FILE(fw_error_dump, dbgfs_dir, S_IRUSR); | ||
1450 | MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); | 1492 | MVM_DEBUGFS_ADD_FILE(bt_notif, dbgfs_dir, S_IRUSR); |
1451 | MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR); | 1493 | MVM_DEBUGFS_ADD_FILE(bt_cmd, dbgfs_dir, S_IRUSR); |
1452 | MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, | 1494 | MVM_DEBUGFS_ADD_FILE(disable_power_off, mvm->debugfs_dir, |
@@ -1487,6 +1529,7 @@ int iwl_mvm_dbgfs_register(struct iwl_mvm *mvm, struct dentry *dbgfs_dir) | |||
1487 | if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR, | 1529 | if (!debugfs_create_bool("d3_wake_sysassert", S_IRUSR | S_IWUSR, |
1488 | mvm->debugfs_dir, &mvm->d3_wake_sysassert)) | 1530 | mvm->debugfs_dir, &mvm->d3_wake_sysassert)) |
1489 | goto err; | 1531 | goto err; |
1532 | MVM_DEBUGFS_ADD_FILE(netdetect, mvm->debugfs_dir, S_IRUSR | S_IWUSR); | ||
1490 | #endif | 1533 | #endif |
1491 | 1534 | ||
1492 | if (!debugfs_create_u8("low_latency_agg_frame_limit", S_IRUSR | S_IWUSR, | 1535 | if (!debugfs_create_u8("low_latency_agg_frame_limit", S_IRUSR | S_IWUSR, |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 0c5c0b0e23f5..b8ab4a108720 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c | |||
@@ -197,8 +197,7 @@ static void iwl_mvm_mac_tsf_id_iter(void *_data, u8 *mac, | |||
197 | /* | 197 | /* |
198 | * Get the mask of the queues used by the vif | 198 | * Get the mask of the queues used by the vif |
199 | */ | 199 | */ |
200 | u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, | 200 | u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif) |
201 | struct ieee80211_vif *vif) | ||
202 | { | 201 | { |
203 | u32 qmask = 0, ac; | 202 | u32 qmask = 0, ac; |
204 | 203 | ||
@@ -227,7 +226,7 @@ static void iwl_mvm_mac_iface_iterator(void *_data, u8 *mac, | |||
227 | } | 226 | } |
228 | 227 | ||
229 | /* Mark the queues used by the vif */ | 228 | /* Mark the queues used by the vif */ |
230 | data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(data->mvm, vif); | 229 | data->used_hw_queues |= iwl_mvm_mac_get_queues_mask(vif); |
231 | 230 | ||
232 | /* Mark MAC IDs as used by clearing the available bit, and | 231 | /* Mark MAC IDs as used by clearing the available bit, and |
233 | * (below) mark TSFs as used if their existing use is not | 232 | * (below) mark TSFs as used if their existing use is not |
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index b62405865b25..57325589ee5b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c | |||
@@ -69,6 +69,7 @@ | |||
69 | #include <linux/etherdevice.h> | 69 | #include <linux/etherdevice.h> |
70 | #include <linux/ip.h> | 70 | #include <linux/ip.h> |
71 | #include <linux/if_arp.h> | 71 | #include <linux/if_arp.h> |
72 | #include <linux/devcoredump.h> | ||
72 | #include <net/mac80211.h> | 73 | #include <net/mac80211.h> |
73 | #include <net/ieee80211_radiotap.h> | 74 | #include <net/ieee80211_radiotap.h> |
74 | #include <net/tcp.h> | 75 | #include <net/tcp.h> |
@@ -679,10 +680,51 @@ static void iwl_mvm_cleanup_iterator(void *data, u8 *mac, | |||
679 | memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data)); | 680 | memset(&mvmvif->bf_data, 0, sizeof(mvmvif->bf_data)); |
680 | } | 681 | } |
681 | 682 | ||
682 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 683 | static ssize_t iwl_mvm_read_coredump(char *buffer, loff_t offset, size_t count, |
684 | const void *data, size_t datalen) | ||
685 | { | ||
686 | const struct iwl_mvm_dump_ptrs *dump_ptrs = data; | ||
687 | ssize_t bytes_read; | ||
688 | ssize_t bytes_read_trans; | ||
689 | |||
690 | if (offset < dump_ptrs->op_mode_len) { | ||
691 | bytes_read = min_t(ssize_t, count, | ||
692 | dump_ptrs->op_mode_len - offset); | ||
693 | memcpy(buffer, (u8 *)dump_ptrs->op_mode_ptr + offset, | ||
694 | bytes_read); | ||
695 | offset += bytes_read; | ||
696 | count -= bytes_read; | ||
697 | |||
698 | if (count == 0) | ||
699 | return bytes_read; | ||
700 | } else { | ||
701 | bytes_read = 0; | ||
702 | } | ||
703 | |||
704 | if (!dump_ptrs->trans_ptr) | ||
705 | return bytes_read; | ||
706 | |||
707 | offset -= dump_ptrs->op_mode_len; | ||
708 | bytes_read_trans = min_t(ssize_t, count, | ||
709 | dump_ptrs->trans_ptr->len - offset); | ||
710 | memcpy(buffer + bytes_read, | ||
711 | (u8 *)dump_ptrs->trans_ptr->data + offset, | ||
712 | bytes_read_trans); | ||
713 | |||
714 | return bytes_read + bytes_read_trans; | ||
715 | } | ||
716 | |||
717 | static void iwl_mvm_free_coredump(const void *data) | ||
718 | { | ||
719 | const struct iwl_mvm_dump_ptrs *fw_error_dump = data; | ||
720 | |||
721 | vfree(fw_error_dump->op_mode_ptr); | ||
722 | vfree(fw_error_dump->trans_ptr); | ||
723 | kfree(fw_error_dump); | ||
724 | } | ||
725 | |||
683 | void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | 726 | void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) |
684 | { | 727 | { |
685 | static char *env[] = { "DRIVER=iwlwifi", "EVENT=error_dump", NULL }; | ||
686 | struct iwl_fw_error_dump_file *dump_file; | 728 | struct iwl_fw_error_dump_file *dump_file; |
687 | struct iwl_fw_error_dump_data *dump_data; | 729 | struct iwl_fw_error_dump_data *dump_data; |
688 | struct iwl_fw_error_dump_info *dump_info; | 730 | struct iwl_fw_error_dump_info *dump_info; |
@@ -695,10 +737,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
695 | 737 | ||
696 | lockdep_assert_held(&mvm->mutex); | 738 | lockdep_assert_held(&mvm->mutex); |
697 | 739 | ||
698 | if (mvm->fw_error_dump) | 740 | fw_error_dump = kzalloc(sizeof(*fw_error_dump), GFP_KERNEL); |
699 | return; | ||
700 | |||
701 | fw_error_dump = kzalloc(sizeof(*mvm->fw_error_dump), GFP_KERNEL); | ||
702 | if (!fw_error_dump) | 741 | if (!fw_error_dump) |
703 | return; | 742 | return; |
704 | 743 | ||
@@ -773,12 +812,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) | |||
773 | if (fw_error_dump->trans_ptr) | 812 | if (fw_error_dump->trans_ptr) |
774 | file_len += fw_error_dump->trans_ptr->len; | 813 | file_len += fw_error_dump->trans_ptr->len; |
775 | dump_file->file_len = cpu_to_le32(file_len); | 814 | dump_file->file_len = cpu_to_le32(file_len); |
776 | mvm->fw_error_dump = fw_error_dump; | ||
777 | 815 | ||
778 | /* notify the userspace about the error we had */ | 816 | dev_coredumpm(mvm->trans->dev, THIS_MODULE, fw_error_dump, 0, |
779 | kobject_uevent_env(&mvm->hw->wiphy->dev.kobj, KOBJ_CHANGE, env); | 817 | GFP_KERNEL, iwl_mvm_read_coredump, iwl_mvm_free_coredump); |
780 | } | 818 | } |
781 | #endif | ||
782 | 819 | ||
783 | static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) | 820 | static void iwl_mvm_restart_cleanup(struct iwl_mvm *mvm) |
784 | { | 821 | { |
@@ -859,9 +896,8 @@ static int iwl_mvm_mac_start(struct ieee80211_hw *hw) | |||
859 | return ret; | 896 | return ret; |
860 | } | 897 | } |
861 | 898 | ||
862 | static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw) | 899 | static void iwl_mvm_restart_complete(struct iwl_mvm *mvm) |
863 | { | 900 | { |
864 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
865 | int ret; | 901 | int ret; |
866 | 902 | ||
867 | mutex_lock(&mvm->mutex); | 903 | mutex_lock(&mvm->mutex); |
@@ -879,6 +915,21 @@ static void iwl_mvm_mac_restart_complete(struct ieee80211_hw *hw) | |||
879 | mutex_unlock(&mvm->mutex); | 915 | mutex_unlock(&mvm->mutex); |
880 | } | 916 | } |
881 | 917 | ||
918 | static void | ||
919 | iwl_mvm_mac_reconfig_complete(struct ieee80211_hw *hw, | ||
920 | enum ieee80211_reconfig_type reconfig_type) | ||
921 | { | ||
922 | struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); | ||
923 | |||
924 | switch (reconfig_type) { | ||
925 | case IEEE80211_RECONFIG_TYPE_RESTART: | ||
926 | iwl_mvm_restart_complete(mvm); | ||
927 | break; | ||
928 | case IEEE80211_RECONFIG_TYPE_SUSPEND: | ||
929 | break; | ||
930 | } | ||
931 | } | ||
932 | |||
882 | void __iwl_mvm_mac_stop(struct iwl_mvm *mvm) | 933 | void __iwl_mvm_mac_stop(struct iwl_mvm *mvm) |
883 | { | 934 | { |
884 | lockdep_assert_held(&mvm->mutex); | 935 | lockdep_assert_held(&mvm->mutex); |
@@ -1087,7 +1138,7 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw, | |||
1087 | static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, | 1138 | static void iwl_mvm_prepare_mac_removal(struct iwl_mvm *mvm, |
1088 | struct ieee80211_vif *vif) | 1139 | struct ieee80211_vif *vif) |
1089 | { | 1140 | { |
1090 | u32 tfd_msk = iwl_mvm_mac_get_queues_mask(mvm, vif); | 1141 | u32 tfd_msk = iwl_mvm_mac_get_queues_mask(vif); |
1091 | 1142 | ||
1092 | if (tfd_msk) { | 1143 | if (tfd_msk) { |
1093 | mutex_lock(&mvm->mutex); | 1144 | mutex_lock(&mvm->mutex); |
@@ -1383,6 +1434,9 @@ bool iwl_mvm_bcast_filter_build_cmd(struct iwl_mvm *mvm, | |||
1383 | .cmd = cmd, | 1434 | .cmd = cmd, |
1384 | }; | 1435 | }; |
1385 | 1436 | ||
1437 | if (IWL_MVM_FW_BCAST_FILTER_PASS_ALL) | ||
1438 | return false; | ||
1439 | |||
1386 | memset(cmd, 0, sizeof(*cmd)); | 1440 | memset(cmd, 0, sizeof(*cmd)); |
1387 | cmd->max_bcast_filters = ARRAY_SIZE(cmd->filters); | 1441 | cmd->max_bcast_filters = ARRAY_SIZE(cmd->filters); |
1388 | cmd->max_macs = ARRAY_SIZE(cmd->macs); | 1442 | cmd->max_macs = ARRAY_SIZE(cmd->macs); |
@@ -2171,25 +2225,9 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw, | |||
2171 | 2225 | ||
2172 | mvm->scan_status = IWL_MVM_SCAN_SCHED; | 2226 | mvm->scan_status = IWL_MVM_SCAN_SCHED; |
2173 | 2227 | ||
2174 | if (!(mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) { | 2228 | ret = iwl_mvm_scan_offload_start(mvm, vif, req, ies); |
2175 | ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies); | ||
2176 | if (ret) | ||
2177 | goto err; | ||
2178 | } | ||
2179 | |||
2180 | ret = iwl_mvm_config_sched_scan_profiles(mvm, req); | ||
2181 | if (ret) | 2229 | if (ret) |
2182 | goto err; | 2230 | mvm->scan_status = IWL_MVM_SCAN_NONE; |
2183 | |||
2184 | if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN) | ||
2185 | ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies); | ||
2186 | else | ||
2187 | ret = iwl_mvm_sched_scan_start(mvm, req); | ||
2188 | |||
2189 | if (!ret) | ||
2190 | goto out; | ||
2191 | err: | ||
2192 | mvm->scan_status = IWL_MVM_SCAN_NONE; | ||
2193 | out: | 2231 | out: |
2194 | mutex_unlock(&mvm->mutex); | 2232 | mutex_unlock(&mvm->mutex); |
2195 | return ret; | 2233 | return ret; |
@@ -3011,25 +3049,31 @@ static void iwl_mvm_mac_flush(struct ieee80211_hw *hw, | |||
3011 | mvmvif = iwl_mvm_vif_from_mac80211(vif); | 3049 | mvmvif = iwl_mvm_vif_from_mac80211(vif); |
3012 | mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id); | 3050 | mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id); |
3013 | 3051 | ||
3014 | if (WARN_ON_ONCE(!mvmsta)) | 3052 | if (WARN_ON_ONCE(!mvmsta)) { |
3015 | goto done; | 3053 | mutex_unlock(&mvm->mutex); |
3054 | return; | ||
3055 | } | ||
3016 | 3056 | ||
3017 | if (drop) { | 3057 | if (drop) { |
3018 | if (iwl_mvm_flush_tx_path(mvm, mvmsta->tfd_queue_msk, true)) | 3058 | if (iwl_mvm_flush_tx_path(mvm, mvmsta->tfd_queue_msk, true)) |
3019 | IWL_ERR(mvm, "flush request fail\n"); | 3059 | IWL_ERR(mvm, "flush request fail\n"); |
3060 | mutex_unlock(&mvm->mutex); | ||
3020 | } else { | 3061 | } else { |
3021 | iwl_trans_wait_tx_queue_empty(mvm->trans, | 3062 | u32 tfd_queue_msk = mvmsta->tfd_queue_msk; |
3022 | mvmsta->tfd_queue_msk); | 3063 | mutex_unlock(&mvm->mutex); |
3064 | |||
3065 | /* this can take a while, and we may need/want other operations | ||
3066 | * to succeed while doing this, so do it without the mutex held | ||
3067 | */ | ||
3068 | iwl_trans_wait_tx_queue_empty(mvm->trans, tfd_queue_msk); | ||
3023 | } | 3069 | } |
3024 | done: | ||
3025 | mutex_unlock(&mvm->mutex); | ||
3026 | } | 3070 | } |
3027 | 3071 | ||
3028 | const struct ieee80211_ops iwl_mvm_hw_ops = { | 3072 | const struct ieee80211_ops iwl_mvm_hw_ops = { |
3029 | .tx = iwl_mvm_mac_tx, | 3073 | .tx = iwl_mvm_mac_tx, |
3030 | .ampdu_action = iwl_mvm_mac_ampdu_action, | 3074 | .ampdu_action = iwl_mvm_mac_ampdu_action, |
3031 | .start = iwl_mvm_mac_start, | 3075 | .start = iwl_mvm_mac_start, |
3032 | .restart_complete = iwl_mvm_mac_restart_complete, | 3076 | .reconfig_complete = iwl_mvm_mac_reconfig_complete, |
3033 | .stop = iwl_mvm_mac_stop, | 3077 | .stop = iwl_mvm_mac_stop, |
3034 | .add_interface = iwl_mvm_mac_add_interface, | 3078 | .add_interface = iwl_mvm_mac_add_interface, |
3035 | .remove_interface = iwl_mvm_mac_remove_interface, | 3079 | .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 845429c88cf4..d015fac06a62 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h | |||
@@ -649,7 +649,6 @@ struct iwl_mvm { | |||
649 | /* -1 for always, 0 for never, >0 for that many times */ | 649 | /* -1 for always, 0 for never, >0 for that many times */ |
650 | s8 restart_fw; | 650 | s8 restart_fw; |
651 | struct work_struct fw_error_dump_wk; | 651 | struct work_struct fw_error_dump_wk; |
652 | struct iwl_mvm_dump_ptrs *fw_error_dump; | ||
653 | 652 | ||
654 | #ifdef CONFIG_IWLWIFI_LEDS | 653 | #ifdef CONFIG_IWLWIFI_LEDS |
655 | struct led_classdev led; | 654 | struct led_classdev led; |
@@ -660,6 +659,10 @@ struct iwl_mvm { | |||
660 | #ifdef CONFIG_PM_SLEEP | 659 | #ifdef CONFIG_PM_SLEEP |
661 | struct wiphy_wowlan_support wowlan; | 660 | struct wiphy_wowlan_support wowlan; |
662 | int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; | 661 | int gtk_ivlen, gtk_icvlen, ptk_ivlen, ptk_icvlen; |
662 | |||
663 | /* sched scan settings for net detect */ | ||
664 | struct cfg80211_sched_scan_request *nd_config; | ||
665 | struct ieee80211_scan_ies *nd_ies; | ||
663 | #ifdef CONFIG_IWLWIFI_DEBUGFS | 666 | #ifdef CONFIG_IWLWIFI_DEBUGFS |
664 | u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */ | 667 | u32 d3_wake_sysassert; /* must be u32 for debugfs_create_bool */ |
665 | bool d3_test_active; | 668 | bool d3_test_active; |
@@ -906,8 +909,7 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | |||
906 | int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | 909 | int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif, |
907 | bool force_assoc_off, const u8 *bssid_override); | 910 | bool force_assoc_off, const u8 *bssid_override); |
908 | int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif); | 911 | int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif); |
909 | u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm, | 912 | u32 iwl_mvm_mac_get_queues_mask(struct ieee80211_vif *vif); |
910 | struct ieee80211_vif *vif); | ||
911 | int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, | 913 | int iwl_mvm_mac_ctxt_beacon_changed(struct iwl_mvm *mvm, |
912 | struct ieee80211_vif *vif); | 914 | struct ieee80211_vif *vif); |
913 | int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, | 915 | int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm, |
@@ -950,6 +952,10 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm, | |||
950 | struct cfg80211_sched_scan_request *req); | 952 | struct cfg80211_sched_scan_request *req); |
951 | int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | 953 | int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, |
952 | struct cfg80211_sched_scan_request *req); | 954 | struct cfg80211_sched_scan_request *req); |
955 | int iwl_mvm_scan_offload_start(struct iwl_mvm *mvm, | ||
956 | struct ieee80211_vif *vif, | ||
957 | struct cfg80211_sched_scan_request *req, | ||
958 | struct ieee80211_scan_ies *ies); | ||
953 | int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify); | 959 | int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify); |
954 | int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm, | 960 | int iwl_mvm_rx_scan_offload_results(struct iwl_mvm *mvm, |
955 | struct iwl_rx_cmd_buffer *rxb, | 961 | struct iwl_rx_cmd_buffer *rxb, |
@@ -1207,11 +1213,9 @@ void iwl_mvm_recalc_tdls_state(struct iwl_mvm *mvm, struct ieee80211_vif *vif, | |||
1207 | void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw, | 1213 | void iwl_mvm_mac_mgd_protect_tdls_discover(struct ieee80211_hw *hw, |
1208 | struct ieee80211_vif *vif); | 1214 | struct ieee80211_vif *vif); |
1209 | 1215 | ||
1216 | struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm); | ||
1217 | |||
1210 | void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error); | 1218 | void iwl_mvm_nic_restart(struct iwl_mvm *mvm, bool fw_error); |
1211 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
1212 | void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm); | 1219 | void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm); |
1213 | #else | ||
1214 | static inline void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm) {} | ||
1215 | #endif | ||
1216 | 1220 | ||
1217 | #endif /* __IWL_MVM_H__ */ | 1221 | #endif /* __IWL_MVM_H__ */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c index 5b719ee8e789..7a9578567f4f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/iwlwifi/mvm/ops.c | |||
@@ -403,6 +403,9 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg, | |||
403 | if (cfg->max_rx_agg_size) | 403 | if (cfg->max_rx_agg_size) |
404 | hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size; | 404 | hw->max_rx_aggregation_subframes = cfg->max_rx_agg_size; |
405 | 405 | ||
406 | if (cfg->max_tx_agg_size) | ||
407 | hw->max_tx_aggregation_subframes = cfg->max_tx_agg_size; | ||
408 | |||
406 | op_mode = hw->priv; | 409 | op_mode = hw->priv; |
407 | op_mode->ops = &iwl_mvm_ops; | 410 | op_mode->ops = &iwl_mvm_ops; |
408 | 411 | ||
@@ -585,16 +588,18 @@ static void iwl_op_mode_mvm_stop(struct iwl_op_mode *op_mode) | |||
585 | ieee80211_unregister_hw(mvm->hw); | 588 | ieee80211_unregister_hw(mvm->hw); |
586 | 589 | ||
587 | kfree(mvm->scan_cmd); | 590 | kfree(mvm->scan_cmd); |
588 | if (mvm->fw_error_dump) { | ||
589 | vfree(mvm->fw_error_dump->op_mode_ptr); | ||
590 | vfree(mvm->fw_error_dump->trans_ptr); | ||
591 | kfree(mvm->fw_error_dump); | ||
592 | } | ||
593 | kfree(mvm->mcast_filter_cmd); | 591 | kfree(mvm->mcast_filter_cmd); |
594 | mvm->mcast_filter_cmd = NULL; | 592 | mvm->mcast_filter_cmd = NULL; |
595 | 593 | ||
596 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS) | 594 | #if defined(CONFIG_PM_SLEEP) && defined(CONFIG_IWLWIFI_DEBUGFS) |
597 | kfree(mvm->d3_resume_sram); | 595 | kfree(mvm->d3_resume_sram); |
596 | if (mvm->nd_config) { | ||
597 | kfree(mvm->nd_config->match_sets); | ||
598 | kfree(mvm->nd_config); | ||
599 | mvm->nd_config = NULL; | ||
600 | kfree(mvm->nd_ies); | ||
601 | mvm->nd_ies = NULL; | ||
602 | } | ||
598 | #endif | 603 | #endif |
599 | 604 | ||
600 | iwl_trans_op_mode_leave(mvm->trans); | 605 | iwl_trans_op_mode_leave(mvm->trans); |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c index 18a539999580..ce884847cc8a 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.c +++ b/drivers/net/wireless/iwlwifi/mvm/rs.c | |||
@@ -505,10 +505,11 @@ static const char *rs_pretty_lq_type(enum iwl_table_type type) | |||
505 | static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate, | 505 | static inline void rs_dump_rate(struct iwl_mvm *mvm, const struct rs_rate *rate, |
506 | const char *prefix) | 506 | const char *prefix) |
507 | { | 507 | { |
508 | IWL_DEBUG_RATE(mvm, "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d\n", | 508 | IWL_DEBUG_RATE(mvm, |
509 | "%s: (%s: %d) ANT: %s BW: %d SGI: %d LDPC: %d STBC %d\n", | ||
509 | prefix, rs_pretty_lq_type(rate->type), | 510 | prefix, rs_pretty_lq_type(rate->type), |
510 | rate->index, rs_pretty_ant(rate->ant), | 511 | rate->index, rs_pretty_ant(rate->ant), |
511 | rate->bw, rate->sgi, rate->ldpc); | 512 | rate->bw, rate->sgi, rate->ldpc, rate->stbc); |
512 | } | 513 | } |
513 | 514 | ||
514 | static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) | 515 | static void rs_rate_scale_clear_window(struct iwl_rate_scale_data *window) |
@@ -741,6 +742,12 @@ static u32 ucode_rate_from_rs_rate(struct iwl_mvm *mvm, | |||
741 | IWL_ERR(mvm, "Invalid rate->type %d\n", rate->type); | 742 | IWL_ERR(mvm, "Invalid rate->type %d\n", rate->type); |
742 | } | 743 | } |
743 | 744 | ||
745 | if (is_siso(rate) && rate->stbc) { | ||
746 | /* To enable STBC we need to set both a flag and ANT_AB */ | ||
747 | ucode_rate |= RATE_MCS_ANT_AB_MSK; | ||
748 | ucode_rate |= RATE_MCS_VHT_STBC_MSK; | ||
749 | } | ||
750 | |||
744 | ucode_rate |= rate->bw; | 751 | ucode_rate |= rate->bw; |
745 | if (rate->sgi) | 752 | if (rate->sgi) |
746 | ucode_rate |= RATE_MCS_SGI_MSK; | 753 | ucode_rate |= RATE_MCS_SGI_MSK; |
@@ -785,6 +792,8 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, | |||
785 | rate->sgi = true; | 792 | rate->sgi = true; |
786 | if (ucode_rate & RATE_MCS_LDPC_MSK) | 793 | if (ucode_rate & RATE_MCS_LDPC_MSK) |
787 | rate->ldpc = true; | 794 | rate->ldpc = true; |
795 | if (ucode_rate & RATE_MCS_VHT_STBC_MSK) | ||
796 | rate->stbc = true; | ||
788 | 797 | ||
789 | rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK; | 798 | rate->bw = ucode_rate & RATE_MCS_CHAN_WIDTH_MSK; |
790 | 799 | ||
@@ -794,7 +803,7 @@ static int rs_rate_from_ucode_rate(const u32 ucode_rate, | |||
794 | 803 | ||
795 | if (nss == 1) { | 804 | if (nss == 1) { |
796 | rate->type = LQ_HT_SISO; | 805 | rate->type = LQ_HT_SISO; |
797 | WARN_ON_ONCE(num_of_ant != 1); | 806 | WARN_ON_ONCE(!rate->stbc && num_of_ant != 1); |
798 | } else if (nss == 2) { | 807 | } else if (nss == 2) { |
799 | rate->type = LQ_HT_MIMO2; | 808 | rate->type = LQ_HT_MIMO2; |
800 | WARN_ON_ONCE(num_of_ant != 2); | 809 | WARN_ON_ONCE(num_of_ant != 2); |
@@ -992,7 +1001,15 @@ static void rs_get_lower_rate_down_column(struct iwl_lq_sta *lq_sta, | |||
992 | static inline bool rs_rate_match(struct rs_rate *a, | 1001 | static inline bool rs_rate_match(struct rs_rate *a, |
993 | struct rs_rate *b) | 1002 | struct rs_rate *b) |
994 | { | 1003 | { |
995 | return (a->type == b->type) && (a->ant == b->ant) && (a->sgi == b->sgi); | 1004 | bool ant_match; |
1005 | |||
1006 | if (a->stbc) | ||
1007 | ant_match = (b->ant == ANT_A || b->ant == ANT_B); | ||
1008 | else | ||
1009 | ant_match = (a->ant == b->ant); | ||
1010 | |||
1011 | return (a->type == b->type) && (a->bw == b->bw) && (a->sgi == b->sgi) | ||
1012 | && ant_match; | ||
996 | } | 1013 | } |
997 | 1014 | ||
998 | static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags) | 1015 | static u32 rs_ch_width_from_mac_flags(enum mac80211_rate_control_flags flags) |
@@ -1225,7 +1242,7 @@ void iwl_mvm_rs_tx_status(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
1225 | IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp); | 1242 | IWL_DEBUG_RATE(mvm, "reduced txpower: %d\n", reduced_txp); |
1226 | done: | 1243 | done: |
1227 | /* See if there's a better rate or modulation mode to try. */ | 1244 | /* See if there's a better rate or modulation mode to try. */ |
1228 | if (sta && sta->supp_rates[info->band]) | 1245 | if (sta->supp_rates[info->band]) |
1229 | rs_rate_scale_perform(mvm, sta, lq_sta, tid); | 1246 | rs_rate_scale_perform(mvm, sta, lq_sta, tid); |
1230 | } | 1247 | } |
1231 | 1248 | ||
@@ -1623,6 +1640,8 @@ static int rs_switch_to_column(struct iwl_mvm *mvm, | |||
1623 | else | 1640 | else |
1624 | rate->type = LQ_LEGACY_G; | 1641 | rate->type = LQ_LEGACY_G; |
1625 | 1642 | ||
1643 | rate->bw = RATE_MCS_CHAN_WIDTH_20; | ||
1644 | rate->ldpc = false; | ||
1626 | rate_mask = lq_sta->active_legacy_rate; | 1645 | rate_mask = lq_sta->active_legacy_rate; |
1627 | } else if (column->mode == RS_SISO) { | 1646 | } else if (column->mode == RS_SISO) { |
1628 | rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO; | 1647 | rate->type = lq_sta->is_vht ? LQ_VHT_SISO : LQ_HT_SISO; |
@@ -1634,8 +1653,11 @@ static int rs_switch_to_column(struct iwl_mvm *mvm, | |||
1634 | WARN_ON_ONCE("Bad column mode"); | 1653 | WARN_ON_ONCE("Bad column mode"); |
1635 | } | 1654 | } |
1636 | 1655 | ||
1637 | rate->bw = rs_bw_from_sta_bw(sta); | 1656 | if (column->mode != RS_LEGACY) { |
1638 | rate->ldpc = lq_sta->ldpc; | 1657 | rate->bw = rs_bw_from_sta_bw(sta); |
1658 | rate->ldpc = lq_sta->ldpc; | ||
1659 | } | ||
1660 | |||
1639 | search_tbl->column = col_id; | 1661 | search_tbl->column = col_id; |
1640 | rs_set_expected_tpt_table(lq_sta, search_tbl); | 1662 | rs_set_expected_tpt_table(lq_sta, search_tbl); |
1641 | 1663 | ||
@@ -1754,6 +1776,29 @@ out: | |||
1754 | return action; | 1776 | return action; |
1755 | } | 1777 | } |
1756 | 1778 | ||
1779 | static bool rs_stbc_allow(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | ||
1780 | struct iwl_lq_sta *lq_sta) | ||
1781 | { | ||
1782 | struct iwl_mvm_sta *mvmsta = iwl_mvm_sta_from_mac80211(sta); | ||
1783 | struct ieee80211_vif *vif = mvmsta->vif; | ||
1784 | bool sta_ps_disabled = (vif->type == NL80211_IFTYPE_STATION && | ||
1785 | !vif->bss_conf.ps); | ||
1786 | |||
1787 | /* Our chip supports Tx STBC and the peer is an HT/VHT STA which | ||
1788 | * supports STBC of at least 1*SS | ||
1789 | */ | ||
1790 | if (!lq_sta->stbc) | ||
1791 | return false; | ||
1792 | |||
1793 | if (!mvm->ps_disabled && !sta_ps_disabled) | ||
1794 | return false; | ||
1795 | |||
1796 | if (!iwl_mvm_bt_coex_is_mimo_allowed(mvm, sta)) | ||
1797 | return false; | ||
1798 | |||
1799 | return true; | ||
1800 | } | ||
1801 | |||
1757 | static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index, | 1802 | static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index, |
1758 | int *weaker, int *stronger) | 1803 | int *weaker, int *stronger) |
1759 | { | 1804 | { |
@@ -2675,6 +2720,11 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
2675 | if (mvm->cfg->ht_params->ldpc && | 2720 | if (mvm->cfg->ht_params->ldpc && |
2676 | (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)) | 2721 | (ht_cap->cap & IEEE80211_HT_CAP_LDPC_CODING)) |
2677 | lq_sta->ldpc = true; | 2722 | lq_sta->ldpc = true; |
2723 | |||
2724 | if (mvm->cfg->ht_params->stbc && | ||
2725 | (num_of_ant(mvm->fw->valid_tx_ant) > 1) && | ||
2726 | (ht_cap->cap & IEEE80211_HT_CAP_RX_STBC)) | ||
2727 | lq_sta->stbc = true; | ||
2678 | } else { | 2728 | } else { |
2679 | rs_vht_set_enabled_rates(sta, vht_cap, lq_sta); | 2729 | rs_vht_set_enabled_rates(sta, vht_cap, lq_sta); |
2680 | lq_sta->is_vht = true; | 2730 | lq_sta->is_vht = true; |
@@ -2682,8 +2732,16 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
2682 | if (mvm->cfg->ht_params->ldpc && | 2732 | if (mvm->cfg->ht_params->ldpc && |
2683 | (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)) | 2733 | (vht_cap->cap & IEEE80211_VHT_CAP_RXLDPC)) |
2684 | lq_sta->ldpc = true; | 2734 | lq_sta->ldpc = true; |
2735 | |||
2736 | if (mvm->cfg->ht_params->stbc && | ||
2737 | (num_of_ant(mvm->fw->valid_tx_ant) > 1) && | ||
2738 | (vht_cap->cap & IEEE80211_VHT_CAP_RXSTBC_MASK)) | ||
2739 | lq_sta->stbc = true; | ||
2685 | } | 2740 | } |
2686 | 2741 | ||
2742 | if (IWL_MVM_RS_DISABLE_MIMO) | ||
2743 | lq_sta->active_mimo2_rate = 0; | ||
2744 | |||
2687 | lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate, | 2745 | lq_sta->max_legacy_rate_idx = find_last_bit(&lq_sta->active_legacy_rate, |
2688 | BITS_PER_LONG); | 2746 | BITS_PER_LONG); |
2689 | lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate, | 2747 | lq_sta->max_siso_rate_idx = find_last_bit(&lq_sta->active_siso_rate, |
@@ -2692,11 +2750,11 @@ void iwl_mvm_rs_rate_init(struct iwl_mvm *mvm, struct ieee80211_sta *sta, | |||
2692 | BITS_PER_LONG); | 2750 | BITS_PER_LONG); |
2693 | 2751 | ||
2694 | IWL_DEBUG_RATE(mvm, | 2752 | IWL_DEBUG_RATE(mvm, |
2695 | "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d\n", | 2753 | "RATE MASK: LEGACY=%lX SISO=%lX MIMO2=%lX VHT=%d LDPC=%d STBC%d\n", |
2696 | lq_sta->active_legacy_rate, | 2754 | lq_sta->active_legacy_rate, |
2697 | lq_sta->active_siso_rate, | 2755 | lq_sta->active_siso_rate, |
2698 | lq_sta->active_mimo2_rate, | 2756 | lq_sta->active_mimo2_rate, |
2699 | lq_sta->is_vht, lq_sta->ldpc); | 2757 | lq_sta->is_vht, lq_sta->ldpc, lq_sta->stbc); |
2700 | IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n", | 2758 | IWL_DEBUG_RATE(mvm, "MAX RATE: LEGACY=%d SISO=%d MIMO2=%d\n", |
2701 | lq_sta->max_legacy_rate_idx, | 2759 | lq_sta->max_legacy_rate_idx, |
2702 | lq_sta->max_siso_rate_idx, | 2760 | lq_sta->max_siso_rate_idx, |
@@ -2820,6 +2878,7 @@ static void rs_fill_rates_for_column(struct iwl_mvm *mvm, | |||
2820 | * rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps | 2878 | * rate[15] 0x800D Legacy | ANT: B Rate: 6 Mbps |
2821 | */ | 2879 | */ |
2822 | static void rs_build_rates_table(struct iwl_mvm *mvm, | 2880 | static void rs_build_rates_table(struct iwl_mvm *mvm, |
2881 | struct ieee80211_sta *sta, | ||
2823 | struct iwl_lq_sta *lq_sta, | 2882 | struct iwl_lq_sta *lq_sta, |
2824 | const struct rs_rate *initial_rate) | 2883 | const struct rs_rate *initial_rate) |
2825 | { | 2884 | { |
@@ -2832,6 +2891,7 @@ static void rs_build_rates_table(struct iwl_mvm *mvm, | |||
2832 | memcpy(&rate, initial_rate, sizeof(rate)); | 2891 | memcpy(&rate, initial_rate, sizeof(rate)); |
2833 | 2892 | ||
2834 | valid_tx_ant = mvm->fw->valid_tx_ant; | 2893 | valid_tx_ant = mvm->fw->valid_tx_ant; |
2894 | rate.stbc = rs_stbc_allow(mvm, sta, lq_sta); | ||
2835 | 2895 | ||
2836 | if (is_siso(&rate)) { | 2896 | if (is_siso(&rate)) { |
2837 | num_rates = RS_INITIAL_SISO_NUM_RATES; | 2897 | num_rates = RS_INITIAL_SISO_NUM_RATES; |
@@ -2903,7 +2963,7 @@ static void rs_fill_lq_cmd(struct iwl_mvm *mvm, | |||
2903 | if (WARN_ON_ONCE(!sta || !initial_rate)) | 2963 | if (WARN_ON_ONCE(!sta || !initial_rate)) |
2904 | return; | 2964 | return; |
2905 | 2965 | ||
2906 | rs_build_rates_table(mvm, lq_sta, initial_rate); | 2966 | rs_build_rates_table(mvm, sta, lq_sta, initial_rate); |
2907 | 2967 | ||
2908 | if (num_of_ant(initial_rate->ant) == 1) | 2968 | if (num_of_ant(initial_rate->ant) == 1) |
2909 | lq_cmd->single_stream_ant_msk = initial_rate->ant; | 2969 | lq_cmd->single_stream_ant_msk = initial_rate->ant; |
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.h b/drivers/net/wireless/iwlwifi/mvm/rs.h index eb34c1209acc..defd70a6d9e6 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rs.h +++ b/drivers/net/wireless/iwlwifi/mvm/rs.h | |||
@@ -208,6 +208,7 @@ struct rs_rate { | |||
208 | u32 bw; | 208 | u32 bw; |
209 | bool sgi; | 209 | bool sgi; |
210 | bool ldpc; | 210 | bool ldpc; |
211 | bool stbc; | ||
211 | }; | 212 | }; |
212 | 213 | ||
213 | 214 | ||
@@ -331,6 +332,7 @@ struct iwl_lq_sta { | |||
331 | u64 last_tx; | 332 | u64 last_tx; |
332 | bool is_vht; | 333 | bool is_vht; |
333 | bool ldpc; /* LDPC Rx is supported by the STA */ | 334 | bool ldpc; /* LDPC Rx is supported by the STA */ |
335 | bool stbc; /* Tx STBC is supported by chip and Rx by STA */ | ||
334 | enum ieee80211_band band; | 336 | enum ieee80211_band band; |
335 | 337 | ||
336 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ | 338 | /* The following are bitmaps of rates; IWL_RATE_6M_MASK, etc. */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c index b280d5d87127..5cd59a43e1da 100644 --- a/drivers/net/wireless/iwlwifi/mvm/scan.c +++ b/drivers/net/wireless/iwlwifi/mvm/scan.c | |||
@@ -270,7 +270,8 @@ static void iwl_mvm_scan_condition_iterator(void *data, u8 *mac, | |||
270 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); | 270 | struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); |
271 | bool *global_bound = data; | 271 | bool *global_bound = data; |
272 | 272 | ||
273 | if (mvmvif->phy_ctxt && mvmvif->phy_ctxt->id < MAX_PHYS) | 273 | if (vif->type != NL80211_IFTYPE_P2P_DEVICE && mvmvif->phy_ctxt && |
274 | mvmvif->phy_ctxt->id < MAX_PHYS) | ||
274 | *global_bound = true; | 275 | *global_bound = true; |
275 | } | 276 | } |
276 | 277 | ||
@@ -672,6 +673,7 @@ int iwl_mvm_rx_scan_offload_complete_notif(struct iwl_mvm *mvm, | |||
672 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 673 | mvm->scan_status = IWL_MVM_SCAN_NONE; |
673 | ieee80211_scan_completed(mvm->hw, | 674 | ieee80211_scan_completed(mvm->hw, |
674 | status == IWL_SCAN_OFFLOAD_ABORTED); | 675 | status == IWL_SCAN_OFFLOAD_ABORTED); |
676 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | ||
675 | } | 677 | } |
676 | 678 | ||
677 | mvm->last_ebs_successful = !ebs_status; | 679 | mvm->last_ebs_successful = !ebs_status; |
@@ -1007,6 +1009,31 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm, | |||
1007 | sizeof(scan_req), &scan_req); | 1009 | sizeof(scan_req), &scan_req); |
1008 | } | 1010 | } |
1009 | 1011 | ||
1012 | int iwl_mvm_scan_offload_start(struct iwl_mvm *mvm, | ||
1013 | struct ieee80211_vif *vif, | ||
1014 | struct cfg80211_sched_scan_request *req, | ||
1015 | struct ieee80211_scan_ies *ies) | ||
1016 | { | ||
1017 | int ret; | ||
1018 | |||
1019 | if ((mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_LMAC_SCAN)) { | ||
1020 | ret = iwl_mvm_config_sched_scan_profiles(mvm, req); | ||
1021 | if (ret) | ||
1022 | return ret; | ||
1023 | ret = iwl_mvm_unified_sched_scan_lmac(mvm, vif, req, ies); | ||
1024 | } else { | ||
1025 | ret = iwl_mvm_config_sched_scan(mvm, vif, req, ies); | ||
1026 | if (ret) | ||
1027 | return ret; | ||
1028 | ret = iwl_mvm_config_sched_scan_profiles(mvm, req); | ||
1029 | if (ret) | ||
1030 | return ret; | ||
1031 | ret = iwl_mvm_sched_scan_start(mvm, req); | ||
1032 | } | ||
1033 | |||
1034 | return ret; | ||
1035 | } | ||
1036 | |||
1010 | static int iwl_mvm_send_scan_offload_abort(struct iwl_mvm *mvm) | 1037 | static int iwl_mvm_send_scan_offload_abort(struct iwl_mvm *mvm) |
1011 | { | 1038 | { |
1012 | int ret; | 1039 | int ret; |
@@ -1081,8 +1108,12 @@ int iwl_mvm_scan_offload_stop(struct iwl_mvm *mvm, bool notify) | |||
1081 | /* | 1108 | /* |
1082 | * Clear the scan status so the next scan requests will succeed. This | 1109 | * Clear the scan status so the next scan requests will succeed. This |
1083 | * also ensures the Rx handler doesn't do anything, as the scan was | 1110 | * also ensures the Rx handler doesn't do anything, as the scan was |
1084 | * stopped from above. | 1111 | * stopped from above. Since the rx handler won't do anything now, |
1112 | * we have to release the scan reference here. | ||
1085 | */ | 1113 | */ |
1114 | if (mvm->scan_status == IWL_MVM_SCAN_OS) | ||
1115 | iwl_mvm_unref(mvm, IWL_MVM_REF_SCAN); | ||
1116 | |||
1086 | mvm->scan_status = IWL_MVM_SCAN_NONE; | 1117 | mvm->scan_status = IWL_MVM_SCAN_NONE; |
1087 | 1118 | ||
1088 | if (notify) { | 1119 | if (notify) { |
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c index 1731c205c81d..dd0dc5bf8583 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/iwlwifi/mvm/sta.c | |||
@@ -609,7 +609,7 @@ int iwl_mvm_alloc_bcast_sta(struct iwl_mvm *mvm, struct ieee80211_vif *vif) | |||
609 | 609 | ||
610 | lockdep_assert_held(&mvm->mutex); | 610 | lockdep_assert_held(&mvm->mutex); |
611 | 611 | ||
612 | qmask = iwl_mvm_mac_get_queues_mask(mvm, vif); | 612 | qmask = iwl_mvm_mac_get_queues_mask(vif); |
613 | 613 | ||
614 | /* | 614 | /* |
615 | * The firmware defines the TFD queue mask to only be relevant | 615 | * The firmware defines the TFD queue mask to only be relevant |
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c index acca44a45086..d4f2c29025c7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tt.c +++ b/drivers/net/wireless/iwlwifi/mvm/tt.c | |||
@@ -64,10 +64,6 @@ | |||
64 | *****************************************************************************/ | 64 | *****************************************************************************/ |
65 | 65 | ||
66 | #include "mvm.h" | 66 | #include "mvm.h" |
67 | #include "iwl-config.h" | ||
68 | #include "iwl-io.h" | ||
69 | #include "iwl-csr.h" | ||
70 | #include "iwl-prph.h" | ||
71 | 67 | ||
72 | #define IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT HZ | 68 | #define IWL_MVM_TEMP_NOTIF_WAIT_TIMEOUT HZ |
73 | 69 | ||
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index c6a517c771df..8d848735cdb8 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c | |||
@@ -189,8 +189,10 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, | |||
189 | 189 | ||
190 | /* HT rate doesn't make sense for a non data frame */ | 190 | /* HT rate doesn't make sense for a non data frame */ |
191 | WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS, | 191 | WARN_ONCE(info->control.rates[0].flags & IEEE80211_TX_RC_MCS, |
192 | "Got an HT rate for a non data frame 0x%x\n", | 192 | "Got an HT rate (flags:0x%x/mcs:%d) for a non data frame (fc:0x%x)\n", |
193 | info->control.rates[0].flags); | 193 | info->control.rates[0].flags, |
194 | info->control.rates[0].idx, | ||
195 | le16_to_cpu(fc)); | ||
194 | 196 | ||
195 | rate_idx = info->control.rates[0].idx; | 197 | rate_idx = info->control.rates[0].idx; |
196 | /* if the rate isn't a well known legacy rate, take the lowest one */ | 198 | /* if the rate isn't a well known legacy rate, take the lowest one */ |
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c index 8021f6eec27f..e56e77ef5d2e 100644 --- a/drivers/net/wireless/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/iwlwifi/mvm/utils.c | |||
@@ -734,3 +734,40 @@ bool iwl_mvm_is_idle(struct iwl_mvm *mvm) | |||
734 | 734 | ||
735 | return idle; | 735 | return idle; |
736 | } | 736 | } |
737 | |||
738 | struct iwl_bss_iter_data { | ||
739 | struct ieee80211_vif *vif; | ||
740 | bool error; | ||
741 | }; | ||
742 | |||
743 | static void iwl_mvm_bss_iface_iterator(void *_data, u8 *mac, | ||
744 | struct ieee80211_vif *vif) | ||
745 | { | ||
746 | struct iwl_bss_iter_data *data = _data; | ||
747 | |||
748 | if (vif->type != NL80211_IFTYPE_STATION || vif->p2p) | ||
749 | return; | ||
750 | |||
751 | if (data->vif) { | ||
752 | data->error = true; | ||
753 | return; | ||
754 | } | ||
755 | |||
756 | data->vif = vif; | ||
757 | } | ||
758 | |||
759 | struct ieee80211_vif *iwl_mvm_get_bss_vif(struct iwl_mvm *mvm) | ||
760 | { | ||
761 | struct iwl_bss_iter_data bss_iter_data = {}; | ||
762 | |||
763 | ieee80211_iterate_active_interfaces_atomic( | ||
764 | mvm->hw, IEEE80211_IFACE_ITER_NORMAL, | ||
765 | iwl_mvm_bss_iface_iterator, &bss_iter_data); | ||
766 | |||
767 | if (bss_iter_data.error) { | ||
768 | IWL_ERR(mvm, "More than one managed interface active!\n"); | ||
769 | return ERR_PTR(-EINVAL); | ||
770 | } | ||
771 | |||
772 | return bss_iter_data.vif; | ||
773 | } | ||
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c index 160c3ebc48d0..836725e92687 100644 --- a/drivers/net/wireless/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/iwlwifi/pcie/trans.c | |||
@@ -133,7 +133,7 @@ static void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans) | |||
133 | break; | 133 | break; |
134 | } | 134 | } |
135 | 135 | ||
136 | if (!page) | 136 | if (WARN_ON_ONCE(!page)) |
137 | return; | 137 | return; |
138 | 138 | ||
139 | trans_pcie->fw_mon_page = page; | 139 | trans_pcie->fw_mon_page = page; |
@@ -747,14 +747,11 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, | |||
747 | int first_ucode_section; | 747 | int first_ucode_section; |
748 | 748 | ||
749 | IWL_DEBUG_FW(trans, | 749 | IWL_DEBUG_FW(trans, |
750 | "working with %s image\n", | ||
751 | image->is_secure ? "Secured" : "Non Secured"); | ||
752 | IWL_DEBUG_FW(trans, | ||
753 | "working with %s CPU\n", | 750 | "working with %s CPU\n", |
754 | image->is_dual_cpus ? "Dual" : "Single"); | 751 | image->is_dual_cpus ? "Dual" : "Single"); |
755 | 752 | ||
756 | /* configure the ucode to be ready to get the secured image */ | 753 | /* configure the ucode to be ready to get the secured image */ |
757 | if (image->is_secure) { | 754 | if (iwl_has_secure_boot(trans->hw_rev, trans->cfg->device_family)) { |
758 | /* set secure boot inspector addresses */ | 755 | /* set secure boot inspector addresses */ |
759 | iwl_write_prph(trans, | 756 | iwl_write_prph(trans, |
760 | LMPM_SECURE_INSPECTOR_CODE_ADDR, | 757 | LMPM_SECURE_INSPECTOR_CODE_ADDR, |
@@ -790,7 +787,8 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, | |||
790 | LMPM_SECURE_CPU2_HDR_MEM_SPACE); | 787 | LMPM_SECURE_CPU2_HDR_MEM_SPACE); |
791 | 788 | ||
792 | /* load to FW the binary sections of CPU2 */ | 789 | /* load to FW the binary sections of CPU2 */ |
793 | if (image->is_secure) | 790 | if (iwl_has_secure_boot(trans->hw_rev, |
791 | trans->cfg->device_family)) | ||
794 | ret = iwl_pcie_load_cpu_secured_sections( | 792 | ret = iwl_pcie_load_cpu_secured_sections( |
795 | trans, image, 2, | 793 | trans, image, 2, |
796 | &first_ucode_section); | 794 | &first_ucode_section); |
@@ -821,7 +819,7 @@ static int iwl_pcie_load_given_ucode(struct iwl_trans *trans, | |||
821 | else | 819 | else |
822 | iwl_write32(trans, CSR_RESET, 0); | 820 | iwl_write32(trans, CSR_RESET, 0); |
823 | 821 | ||
824 | if (image->is_secure) { | 822 | if (iwl_has_secure_boot(trans->hw_rev, trans->cfg->device_family)) { |
825 | /* wait for image verification to complete */ | 823 | /* wait for image verification to complete */ |
826 | ret = iwl_poll_prph_bit(trans, | 824 | ret = iwl_poll_prph_bit(trans, |
827 | LMPM_SECURE_BOOT_CPU1_STATUS_ADDR, | 825 | LMPM_SECURE_BOOT_CPU1_STATUS_ADDR, |
@@ -1023,14 +1021,6 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, | |||
1023 | return 0; | 1021 | return 0; |
1024 | } | 1022 | } |
1025 | 1023 | ||
1026 | iwl_pcie_set_pwr(trans, false); | ||
1027 | |||
1028 | val = iwl_read32(trans, CSR_RESET); | ||
1029 | if (val & CSR_RESET_REG_FLAG_NEVO_RESET) { | ||
1030 | *status = IWL_D3_STATUS_RESET; | ||
1031 | return 0; | ||
1032 | } | ||
1033 | |||
1034 | /* | 1024 | /* |
1035 | * Also enables interrupts - none will happen as the device doesn't | 1025 | * Also enables interrupts - none will happen as the device doesn't |
1036 | * know we're waking it up, only when the opmode actually tells it | 1026 | * know we're waking it up, only when the opmode actually tells it |
@@ -1050,6 +1040,8 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, | |||
1050 | return ret; | 1040 | return ret; |
1051 | } | 1041 | } |
1052 | 1042 | ||
1043 | iwl_pcie_set_pwr(trans, false); | ||
1044 | |||
1053 | iwl_trans_pcie_tx_reset(trans); | 1045 | iwl_trans_pcie_tx_reset(trans); |
1054 | 1046 | ||
1055 | ret = iwl_pcie_rx_init(trans); | 1047 | ret = iwl_pcie_rx_init(trans); |
@@ -1058,7 +1050,12 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, | |||
1058 | return ret; | 1050 | return ret; |
1059 | } | 1051 | } |
1060 | 1052 | ||
1061 | *status = IWL_D3_STATUS_ALIVE; | 1053 | val = iwl_read32(trans, CSR_RESET); |
1054 | if (val & CSR_RESET_REG_FLAG_NEVO_RESET) | ||
1055 | *status = IWL_D3_STATUS_RESET; | ||
1056 | else | ||
1057 | *status = IWL_D3_STATUS_ALIVE; | ||
1058 | |||
1062 | return 0; | 1059 | return 0; |
1063 | } | 1060 | } |
1064 | 1061 | ||
@@ -1767,6 +1764,13 @@ err: | |||
1767 | IWL_ERR(trans, "failed to create the trans debugfs entry\n"); | 1764 | IWL_ERR(trans, "failed to create the trans debugfs entry\n"); |
1768 | return -ENOMEM; | 1765 | return -ENOMEM; |
1769 | } | 1766 | } |
1767 | #else | ||
1768 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | ||
1769 | struct dentry *dir) | ||
1770 | { | ||
1771 | return 0; | ||
1772 | } | ||
1773 | #endif /*CONFIG_IWLWIFI_DEBUGFS */ | ||
1770 | 1774 | ||
1771 | static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd) | 1775 | static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd) |
1772 | { | 1776 | { |
@@ -2045,13 +2049,6 @@ struct iwl_trans_dump_data *iwl_trans_pcie_dump_data(struct iwl_trans *trans) | |||
2045 | 2049 | ||
2046 | return dump_data; | 2050 | return dump_data; |
2047 | } | 2051 | } |
2048 | #else | ||
2049 | static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans, | ||
2050 | struct dentry *dir) | ||
2051 | { | ||
2052 | return 0; | ||
2053 | } | ||
2054 | #endif /*CONFIG_IWLWIFI_DEBUGFS */ | ||
2055 | 2052 | ||
2056 | static const struct iwl_trans_ops trans_ops_pcie = { | 2053 | static const struct iwl_trans_ops trans_ops_pcie = { |
2057 | .start_hw = iwl_trans_pcie_start_hw, | 2054 | .start_hw = iwl_trans_pcie_start_hw, |
@@ -2088,9 +2085,7 @@ static const struct iwl_trans_ops trans_ops_pcie = { | |||
2088 | .release_nic_access = iwl_trans_pcie_release_nic_access, | 2085 | .release_nic_access = iwl_trans_pcie_release_nic_access, |
2089 | .set_bits_mask = iwl_trans_pcie_set_bits_mask, | 2086 | .set_bits_mask = iwl_trans_pcie_set_bits_mask, |
2090 | 2087 | ||
2091 | #ifdef CONFIG_IWLWIFI_DEBUGFS | ||
2092 | .dump_data = iwl_trans_pcie_dump_data, | 2088 | .dump_data = iwl_trans_pcie_dump_data, |
2093 | #endif | ||
2094 | }; | 2089 | }; |
2095 | 2090 | ||
2096 | struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, | 2091 | struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, |
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index c9ad4cf1adfb..77fbf3035038 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -412,6 +412,9 @@ 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; | ||
415 | 418 | ||
416 | struct ieee80211_channel *tmp_chan; | 419 | struct ieee80211_channel *tmp_chan; |
417 | struct delayed_work roc_done; | 420 | struct delayed_work roc_done; |
@@ -436,7 +439,7 @@ struct mac80211_hwsim_data { | |||
436 | /* | 439 | /* |
437 | * Only radios in the same group can communicate together (the | 440 | * Only radios in the same group can communicate together (the |
438 | * channel has to match too). Each bit represents a group. A | 441 | * channel has to match too). Each bit represents a group. A |
439 | * radio can be in more then one group. | 442 | * radio can be in more than one group. |
440 | */ | 443 | */ |
441 | u64 group; | 444 | u64 group; |
442 | 445 | ||
@@ -447,6 +450,14 @@ struct mac80211_hwsim_data { | |||
447 | s64 bcn_delta; | 450 | s64 bcn_delta; |
448 | /* absolute beacon transmission time. Used to cover up "tx" delay. */ | 451 | /* absolute beacon transmission time. Used to cover up "tx" delay. */ |
449 | u64 abs_bcn_ts; | 452 | u64 abs_bcn_ts; |
453 | |||
454 | /* Stats */ | ||
455 | u64 tx_pkts; | ||
456 | u64 rx_pkts; | ||
457 | u64 tx_bytes; | ||
458 | u64 rx_bytes; | ||
459 | u64 tx_dropped; | ||
460 | u64 tx_failed; | ||
450 | }; | 461 | }; |
451 | 462 | ||
452 | 463 | ||
@@ -476,6 +487,14 @@ static struct genl_family hwsim_genl_family = { | |||
476 | .maxattr = HWSIM_ATTR_MAX, | 487 | .maxattr = HWSIM_ATTR_MAX, |
477 | }; | 488 | }; |
478 | 489 | ||
490 | enum hwsim_multicast_groups { | ||
491 | HWSIM_MCGRP_CONFIG, | ||
492 | }; | ||
493 | |||
494 | static const struct genl_multicast_group hwsim_mcgrps[] = { | ||
495 | [HWSIM_MCGRP_CONFIG] = { .name = "config", }, | ||
496 | }; | ||
497 | |||
479 | /* MAC80211_HWSIM netlink policy */ | 498 | /* MAC80211_HWSIM netlink policy */ |
480 | 499 | ||
481 | static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { | 500 | static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { |
@@ -496,6 +515,10 @@ static const struct nla_policy hwsim_genl_policy[HWSIM_ATTR_MAX + 1] = { | |||
496 | [HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 }, | 515 | [HWSIM_ATTR_REG_CUSTOM_REG] = { .type = NLA_U32 }, |
497 | [HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG }, | 516 | [HWSIM_ATTR_REG_STRICT_REG] = { .type = NLA_FLAG }, |
498 | [HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG }, | 517 | [HWSIM_ATTR_SUPPORT_P2P_DEVICE] = { .type = NLA_FLAG }, |
518 | [HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE] = { .type = NLA_FLAG }, | ||
519 | [HWSIM_ATTR_RADIO_NAME] = { .type = NLA_STRING }, | ||
520 | [HWSIM_ATTR_NO_VIF] = { .type = NLA_FLAG }, | ||
521 | [HWSIM_ATTR_FREQ] = { .type = NLA_U32 }, | ||
499 | }; | 522 | }; |
500 | 523 | ||
501 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, | 524 | static void mac80211_hwsim_tx_frame(struct ieee80211_hw *hw, |
@@ -861,8 +884,10 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, | |||
861 | /* If the queue contains MAX_QUEUE skb's drop some */ | 884 | /* If the queue contains MAX_QUEUE skb's drop some */ |
862 | if (skb_queue_len(&data->pending) >= MAX_QUEUE) { | 885 | if (skb_queue_len(&data->pending) >= MAX_QUEUE) { |
863 | /* Droping until WARN_QUEUE level */ | 886 | /* Droping until WARN_QUEUE level */ |
864 | while (skb_queue_len(&data->pending) >= WARN_QUEUE) | 887 | while (skb_queue_len(&data->pending) >= WARN_QUEUE) { |
865 | skb_dequeue(&data->pending); | 888 | ieee80211_free_txskb(hw, skb_dequeue(&data->pending)); |
889 | data->tx_dropped++; | ||
890 | } | ||
866 | } | 891 | } |
867 | 892 | ||
868 | skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC); | 893 | skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_ATOMIC); |
@@ -896,6 +921,9 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, | |||
896 | if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags)) | 921 | if (nla_put_u32(skb, HWSIM_ATTR_FLAGS, hwsim_flags)) |
897 | goto nla_put_failure; | 922 | goto nla_put_failure; |
898 | 923 | ||
924 | if (nla_put_u32(skb, HWSIM_ATTR_FREQ, data->channel->center_freq)) | ||
925 | goto nla_put_failure; | ||
926 | |||
899 | /* We get the tx control (rate and retries) info*/ | 927 | /* We get the tx control (rate and retries) info*/ |
900 | 928 | ||
901 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { | 929 | for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { |
@@ -917,10 +945,14 @@ static void mac80211_hwsim_tx_frame_nl(struct ieee80211_hw *hw, | |||
917 | 945 | ||
918 | /* Enqueue the packet */ | 946 | /* Enqueue the packet */ |
919 | skb_queue_tail(&data->pending, my_skb); | 947 | skb_queue_tail(&data->pending, my_skb); |
948 | data->tx_pkts++; | ||
949 | data->tx_bytes += my_skb->len; | ||
920 | return; | 950 | return; |
921 | 951 | ||
922 | nla_put_failure: | 952 | nla_put_failure: |
923 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); | 953 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); |
954 | ieee80211_free_txskb(hw, my_skb); | ||
955 | data->tx_failed++; | ||
924 | } | 956 | } |
925 | 957 | ||
926 | static bool hwsim_chans_compat(struct ieee80211_channel *c1, | 958 | static bool hwsim_chans_compat(struct ieee80211_channel *c1, |
@@ -1066,6 +1098,8 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw, | |||
1066 | rx_status.mactime = now + data2->tsf_offset; | 1098 | rx_status.mactime = now + data2->tsf_offset; |
1067 | 1099 | ||
1068 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); | 1100 | memcpy(IEEE80211_SKB_RXCB(nskb), &rx_status, sizeof(rx_status)); |
1101 | data2->rx_pkts++; | ||
1102 | data2->rx_bytes += nskb->len; | ||
1069 | ieee80211_rx_irqsafe(data2->hw, nskb); | 1103 | ieee80211_rx_irqsafe(data2->hw, nskb); |
1070 | } | 1104 | } |
1071 | spin_unlock(&hwsim_radio_lock); | 1105 | spin_unlock(&hwsim_radio_lock); |
@@ -1133,6 +1167,8 @@ static void mac80211_hwsim_tx(struct ieee80211_hw *hw, | |||
1133 | return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); | 1167 | return mac80211_hwsim_tx_frame_nl(hw, skb, _portid); |
1134 | 1168 | ||
1135 | /* NO wmediumd detected, perfect medium simulation */ | 1169 | /* NO wmediumd detected, perfect medium simulation */ |
1170 | data->tx_pkts++; | ||
1171 | data->tx_bytes += skb->len; | ||
1136 | ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel); | 1172 | ack = mac80211_hwsim_tx_frame_no_nl(hw, skb, channel); |
1137 | 1173 | ||
1138 | if (ack && skb->len >= 16) { | 1174 | if (ack && skb->len >= 16) { |
@@ -1916,6 +1952,57 @@ static void mac80211_hwsim_unassign_vif_chanctx(struct ieee80211_hw *hw, | |||
1916 | hwsim_check_chanctx_magic(ctx); | 1952 | hwsim_check_chanctx_magic(ctx); |
1917 | } | 1953 | } |
1918 | 1954 | ||
1955 | static const char mac80211_hwsim_gstrings_stats[][ETH_GSTRING_LEN] = { | ||
1956 | "tx_pkts_nic", | ||
1957 | "tx_bytes_nic", | ||
1958 | "rx_pkts_nic", | ||
1959 | "rx_bytes_nic", | ||
1960 | "d_tx_dropped", | ||
1961 | "d_tx_failed", | ||
1962 | "d_ps_mode", | ||
1963 | "d_group", | ||
1964 | "d_tx_power", | ||
1965 | }; | ||
1966 | |||
1967 | #define MAC80211_HWSIM_SSTATS_LEN ARRAY_SIZE(mac80211_hwsim_gstrings_stats) | ||
1968 | |||
1969 | static void mac80211_hwsim_get_et_strings(struct ieee80211_hw *hw, | ||
1970 | struct ieee80211_vif *vif, | ||
1971 | u32 sset, u8 *data) | ||
1972 | { | ||
1973 | if (sset == ETH_SS_STATS) | ||
1974 | memcpy(data, *mac80211_hwsim_gstrings_stats, | ||
1975 | sizeof(mac80211_hwsim_gstrings_stats)); | ||
1976 | } | ||
1977 | |||
1978 | static int mac80211_hwsim_get_et_sset_count(struct ieee80211_hw *hw, | ||
1979 | struct ieee80211_vif *vif, int sset) | ||
1980 | { | ||
1981 | if (sset == ETH_SS_STATS) | ||
1982 | return MAC80211_HWSIM_SSTATS_LEN; | ||
1983 | return 0; | ||
1984 | } | ||
1985 | |||
1986 | static void mac80211_hwsim_get_et_stats(struct ieee80211_hw *hw, | ||
1987 | struct ieee80211_vif *vif, | ||
1988 | struct ethtool_stats *stats, u64 *data) | ||
1989 | { | ||
1990 | struct mac80211_hwsim_data *ar = hw->priv; | ||
1991 | int i = 0; | ||
1992 | |||
1993 | data[i++] = ar->tx_pkts; | ||
1994 | data[i++] = ar->tx_bytes; | ||
1995 | data[i++] = ar->rx_pkts; | ||
1996 | data[i++] = ar->rx_bytes; | ||
1997 | data[i++] = ar->tx_dropped; | ||
1998 | data[i++] = ar->tx_failed; | ||
1999 | data[i++] = ar->ps; | ||
2000 | data[i++] = ar->group; | ||
2001 | data[i++] = ar->power_level; | ||
2002 | |||
2003 | WARN_ON(i != MAC80211_HWSIM_SSTATS_LEN); | ||
2004 | } | ||
2005 | |||
1919 | static const struct ieee80211_ops mac80211_hwsim_ops = { | 2006 | static const struct ieee80211_ops mac80211_hwsim_ops = { |
1920 | .tx = mac80211_hwsim_tx, | 2007 | .tx = mac80211_hwsim_tx, |
1921 | .start = mac80211_hwsim_start, | 2008 | .start = mac80211_hwsim_start, |
@@ -1939,14 +2026,131 @@ static const struct ieee80211_ops mac80211_hwsim_ops = { | |||
1939 | .flush = mac80211_hwsim_flush, | 2026 | .flush = mac80211_hwsim_flush, |
1940 | .get_tsf = mac80211_hwsim_get_tsf, | 2027 | .get_tsf = mac80211_hwsim_get_tsf, |
1941 | .set_tsf = mac80211_hwsim_set_tsf, | 2028 | .set_tsf = mac80211_hwsim_set_tsf, |
2029 | .get_et_sset_count = mac80211_hwsim_get_et_sset_count, | ||
2030 | .get_et_stats = mac80211_hwsim_get_et_stats, | ||
2031 | .get_et_strings = mac80211_hwsim_get_et_strings, | ||
1942 | }; | 2032 | }; |
1943 | 2033 | ||
1944 | static struct ieee80211_ops mac80211_hwsim_mchan_ops; | 2034 | static struct ieee80211_ops mac80211_hwsim_mchan_ops; |
1945 | 2035 | ||
1946 | static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | 2036 | struct hwsim_new_radio_params { |
1947 | const struct ieee80211_regdomain *regd, | 2037 | unsigned int channels; |
1948 | bool reg_strict, bool p2p_device, | 2038 | const char *reg_alpha2; |
1949 | bool use_chanctx) | 2039 | const struct ieee80211_regdomain *regd; |
2040 | bool reg_strict; | ||
2041 | bool p2p_device; | ||
2042 | bool use_chanctx; | ||
2043 | bool destroy_on_close; | ||
2044 | const char *hwname; | ||
2045 | bool no_vif; | ||
2046 | }; | ||
2047 | |||
2048 | static void hwsim_mcast_config_msg(struct sk_buff *mcast_skb, | ||
2049 | struct genl_info *info) | ||
2050 | { | ||
2051 | if (info) | ||
2052 | genl_notify(&hwsim_genl_family, mcast_skb, | ||
2053 | genl_info_net(info), info->snd_portid, | ||
2054 | HWSIM_MCGRP_CONFIG, info->nlhdr, GFP_KERNEL); | ||
2055 | else | ||
2056 | genlmsg_multicast(&hwsim_genl_family, mcast_skb, 0, | ||
2057 | HWSIM_MCGRP_CONFIG, GFP_KERNEL); | ||
2058 | } | ||
2059 | |||
2060 | static struct sk_buff *build_radio_msg(int cmd, int id, | ||
2061 | struct hwsim_new_radio_params *param) | ||
2062 | { | ||
2063 | struct sk_buff *skb; | ||
2064 | void *data; | ||
2065 | int ret; | ||
2066 | |||
2067 | skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
2068 | if (!skb) | ||
2069 | return NULL; | ||
2070 | |||
2071 | data = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0, cmd); | ||
2072 | if (!data) | ||
2073 | goto error; | ||
2074 | |||
2075 | ret = nla_put_u32(skb, HWSIM_ATTR_RADIO_ID, id); | ||
2076 | if (ret < 0) | ||
2077 | goto error; | ||
2078 | |||
2079 | if (param->channels) { | ||
2080 | ret = nla_put_u32(skb, HWSIM_ATTR_CHANNELS, param->channels); | ||
2081 | if (ret < 0) | ||
2082 | goto error; | ||
2083 | } | ||
2084 | |||
2085 | if (param->reg_alpha2) { | ||
2086 | ret = nla_put(skb, HWSIM_ATTR_REG_HINT_ALPHA2, 2, | ||
2087 | param->reg_alpha2); | ||
2088 | if (ret < 0) | ||
2089 | goto error; | ||
2090 | } | ||
2091 | |||
2092 | if (param->regd) { | ||
2093 | int i; | ||
2094 | |||
2095 | for (i = 0; hwsim_world_regdom_custom[i] != param->regd && | ||
2096 | i < ARRAY_SIZE(hwsim_world_regdom_custom); i++) | ||
2097 | ; | ||
2098 | |||
2099 | if (i < ARRAY_SIZE(hwsim_world_regdom_custom)) { | ||
2100 | ret = nla_put_u32(skb, HWSIM_ATTR_REG_CUSTOM_REG, i); | ||
2101 | if (ret < 0) | ||
2102 | goto error; | ||
2103 | } | ||
2104 | } | ||
2105 | |||
2106 | if (param->reg_strict) { | ||
2107 | ret = nla_put_flag(skb, HWSIM_ATTR_REG_STRICT_REG); | ||
2108 | if (ret < 0) | ||
2109 | goto error; | ||
2110 | } | ||
2111 | |||
2112 | if (param->p2p_device) { | ||
2113 | ret = nla_put_flag(skb, HWSIM_ATTR_SUPPORT_P2P_DEVICE); | ||
2114 | if (ret < 0) | ||
2115 | goto error; | ||
2116 | } | ||
2117 | |||
2118 | if (param->use_chanctx) { | ||
2119 | ret = nla_put_flag(skb, HWSIM_ATTR_USE_CHANCTX); | ||
2120 | if (ret < 0) | ||
2121 | goto error; | ||
2122 | } | ||
2123 | |||
2124 | if (param->hwname) { | ||
2125 | ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME, | ||
2126 | strlen(param->hwname), param->hwname); | ||
2127 | if (ret < 0) | ||
2128 | goto error; | ||
2129 | } | ||
2130 | |||
2131 | genlmsg_end(skb, data); | ||
2132 | |||
2133 | return skb; | ||
2134 | |||
2135 | error: | ||
2136 | nlmsg_free(skb); | ||
2137 | return NULL; | ||
2138 | } | ||
2139 | |||
2140 | static void hswim_mcast_new_radio(int id, struct genl_info *info, | ||
2141 | struct hwsim_new_radio_params *param) | ||
2142 | { | ||
2143 | struct sk_buff *mcast_skb; | ||
2144 | |||
2145 | mcast_skb = build_radio_msg(HWSIM_CMD_NEW_RADIO, id, param); | ||
2146 | if (!mcast_skb) | ||
2147 | return; | ||
2148 | |||
2149 | hwsim_mcast_config_msg(mcast_skb, info); | ||
2150 | } | ||
2151 | |||
2152 | static int mac80211_hwsim_new_radio(struct genl_info *info, | ||
2153 | struct hwsim_new_radio_params *param) | ||
1950 | { | 2154 | { |
1951 | int err; | 2155 | int err; |
1952 | u8 addr[ETH_ALEN]; | 2156 | u8 addr[ETH_ALEN]; |
@@ -1956,16 +2160,16 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
1956 | const struct ieee80211_ops *ops = &mac80211_hwsim_ops; | 2160 | const struct ieee80211_ops *ops = &mac80211_hwsim_ops; |
1957 | int idx; | 2161 | int idx; |
1958 | 2162 | ||
1959 | if (WARN_ON(channels > 1 && !use_chanctx)) | 2163 | if (WARN_ON(param->channels > 1 && !param->use_chanctx)) |
1960 | return -EINVAL; | 2164 | return -EINVAL; |
1961 | 2165 | ||
1962 | spin_lock_bh(&hwsim_radio_lock); | 2166 | spin_lock_bh(&hwsim_radio_lock); |
1963 | idx = hwsim_radio_idx++; | 2167 | idx = hwsim_radio_idx++; |
1964 | spin_unlock_bh(&hwsim_radio_lock); | 2168 | spin_unlock_bh(&hwsim_radio_lock); |
1965 | 2169 | ||
1966 | if (use_chanctx) | 2170 | if (param->use_chanctx) |
1967 | ops = &mac80211_hwsim_mchan_ops; | 2171 | ops = &mac80211_hwsim_mchan_ops; |
1968 | hw = ieee80211_alloc_hw(sizeof(*data), ops); | 2172 | hw = ieee80211_alloc_hw_nm(sizeof(*data), ops, param->hwname); |
1969 | if (!hw) { | 2173 | if (!hw) { |
1970 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw failed\n"); | 2174 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_alloc_hw failed\n"); |
1971 | err = -ENOMEM; | 2175 | err = -ENOMEM; |
@@ -2003,9 +2207,12 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2003 | hw->wiphy->n_addresses = 2; | 2207 | hw->wiphy->n_addresses = 2; |
2004 | hw->wiphy->addresses = data->addresses; | 2208 | hw->wiphy->addresses = data->addresses; |
2005 | 2209 | ||
2006 | data->channels = channels; | 2210 | data->channels = param->channels; |
2007 | data->use_chanctx = use_chanctx; | 2211 | data->use_chanctx = param->use_chanctx; |
2008 | data->idx = idx; | 2212 | data->idx = idx; |
2213 | data->destroy_on_close = param->destroy_on_close; | ||
2214 | if (info) | ||
2215 | data->portid = info->snd_portid; | ||
2009 | 2216 | ||
2010 | if (data->use_chanctx) { | 2217 | if (data->use_chanctx) { |
2011 | hw->wiphy->max_scan_ssids = 255; | 2218 | hw->wiphy->max_scan_ssids = 255; |
@@ -2014,12 +2221,12 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2014 | /* For channels > 1 DFS is not allowed */ | 2221 | /* For channels > 1 DFS is not allowed */ |
2015 | hw->wiphy->n_iface_combinations = 1; | 2222 | hw->wiphy->n_iface_combinations = 1; |
2016 | hw->wiphy->iface_combinations = &data->if_combination; | 2223 | hw->wiphy->iface_combinations = &data->if_combination; |
2017 | if (p2p_device) | 2224 | if (param->p2p_device) |
2018 | data->if_combination = hwsim_if_comb_p2p_dev[0]; | 2225 | data->if_combination = hwsim_if_comb_p2p_dev[0]; |
2019 | else | 2226 | else |
2020 | data->if_combination = hwsim_if_comb[0]; | 2227 | data->if_combination = hwsim_if_comb[0]; |
2021 | data->if_combination.num_different_channels = data->channels; | 2228 | data->if_combination.num_different_channels = data->channels; |
2022 | } else if (p2p_device) { | 2229 | } else if (param->p2p_device) { |
2023 | hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev; | 2230 | hw->wiphy->iface_combinations = hwsim_if_comb_p2p_dev; |
2024 | hw->wiphy->n_iface_combinations = | 2231 | hw->wiphy->n_iface_combinations = |
2025 | ARRAY_SIZE(hwsim_if_comb_p2p_dev); | 2232 | ARRAY_SIZE(hwsim_if_comb_p2p_dev); |
@@ -2040,7 +2247,7 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2040 | BIT(NL80211_IFTYPE_ADHOC) | | 2247 | BIT(NL80211_IFTYPE_ADHOC) | |
2041 | BIT(NL80211_IFTYPE_MESH_POINT); | 2248 | BIT(NL80211_IFTYPE_MESH_POINT); |
2042 | 2249 | ||
2043 | if (p2p_device) | 2250 | if (param->p2p_device) |
2044 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE); | 2251 | hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_DEVICE); |
2045 | 2252 | ||
2046 | hw->flags = IEEE80211_HW_MFP_CAPABLE | | 2253 | hw->flags = IEEE80211_HW_MFP_CAPABLE | |
@@ -2095,6 +2302,7 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2095 | sband->ht_cap.ht_supported = true; | 2302 | sband->ht_cap.ht_supported = true; |
2096 | sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | | 2303 | sband->ht_cap.cap = IEEE80211_HT_CAP_SUP_WIDTH_20_40 | |
2097 | IEEE80211_HT_CAP_GRN_FLD | | 2304 | IEEE80211_HT_CAP_GRN_FLD | |
2305 | IEEE80211_HT_CAP_SGI_20 | | ||
2098 | IEEE80211_HT_CAP_SGI_40 | | 2306 | IEEE80211_HT_CAP_SGI_40 | |
2099 | IEEE80211_HT_CAP_DSSSCCK40; | 2307 | IEEE80211_HT_CAP_DSSSCCK40; |
2100 | sband->ht_cap.ampdu_factor = 0x3; | 2308 | sband->ht_cap.ampdu_factor = 0x3; |
@@ -2142,15 +2350,18 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2142 | hw->max_rates = 4; | 2350 | hw->max_rates = 4; |
2143 | hw->max_rate_tries = 11; | 2351 | hw->max_rate_tries = 11; |
2144 | 2352 | ||
2145 | if (reg_strict) | 2353 | if (param->reg_strict) |
2146 | hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG; | 2354 | hw->wiphy->regulatory_flags |= REGULATORY_STRICT_REG; |
2147 | if (regd) { | 2355 | if (param->regd) { |
2148 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; | 2356 | hw->wiphy->regulatory_flags |= REGULATORY_CUSTOM_REG; |
2149 | wiphy_apply_custom_regulatory(hw->wiphy, regd); | 2357 | wiphy_apply_custom_regulatory(hw->wiphy, param->regd); |
2150 | /* give the regulatory workqueue a chance to run */ | 2358 | /* give the regulatory workqueue a chance to run */ |
2151 | schedule_timeout_interruptible(1); | 2359 | schedule_timeout_interruptible(1); |
2152 | } | 2360 | } |
2153 | 2361 | ||
2362 | if (param->no_vif) | ||
2363 | hw->flags |= IEEE80211_HW_NO_AUTO_VIF; | ||
2364 | |||
2154 | err = ieee80211_register_hw(hw); | 2365 | err = ieee80211_register_hw(hw); |
2155 | if (err < 0) { | 2366 | if (err < 0) { |
2156 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n", | 2367 | printk(KERN_DEBUG "mac80211_hwsim: ieee80211_register_hw failed (%d)\n", |
@@ -2160,8 +2371,8 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2160 | 2371 | ||
2161 | wiphy_debug(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr); | 2372 | wiphy_debug(hw->wiphy, "hwaddr %pM registered\n", hw->wiphy->perm_addr); |
2162 | 2373 | ||
2163 | if (reg_alpha2) | 2374 | if (param->reg_alpha2) |
2164 | regulatory_hint(hw->wiphy, reg_alpha2); | 2375 | regulatory_hint(hw->wiphy, param->reg_alpha2); |
2165 | 2376 | ||
2166 | data->debugfs = debugfs_create_dir("hwsim", hw->wiphy->debugfsdir); | 2377 | data->debugfs = debugfs_create_dir("hwsim", hw->wiphy->debugfsdir); |
2167 | debugfs_create_file("ps", 0666, data->debugfs, data, &hwsim_fops_ps); | 2378 | debugfs_create_file("ps", 0666, data->debugfs, data, &hwsim_fops_ps); |
@@ -2180,6 +2391,9 @@ static int mac80211_hwsim_create_radio(int channels, const char *reg_alpha2, | |||
2180 | list_add_tail(&data->list, &hwsim_radios); | 2391 | list_add_tail(&data->list, &hwsim_radios); |
2181 | spin_unlock_bh(&hwsim_radio_lock); | 2392 | spin_unlock_bh(&hwsim_radio_lock); |
2182 | 2393 | ||
2394 | if (idx > 0) | ||
2395 | hswim_mcast_new_radio(idx, info, param); | ||
2396 | |||
2183 | return idx; | 2397 | return idx; |
2184 | 2398 | ||
2185 | failed_hw: | 2399 | failed_hw: |
@@ -2192,8 +2406,48 @@ failed: | |||
2192 | return err; | 2406 | return err; |
2193 | } | 2407 | } |
2194 | 2408 | ||
2195 | static void mac80211_hwsim_destroy_radio(struct mac80211_hwsim_data *data) | 2409 | static void hwsim_mcast_del_radio(int id, const char *hwname, |
2410 | struct genl_info *info) | ||
2411 | { | ||
2412 | struct sk_buff *skb; | ||
2413 | void *data; | ||
2414 | int ret; | ||
2415 | |||
2416 | skb = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
2417 | if (!skb) | ||
2418 | return; | ||
2419 | |||
2420 | data = genlmsg_put(skb, 0, 0, &hwsim_genl_family, 0, | ||
2421 | HWSIM_CMD_DEL_RADIO); | ||
2422 | if (!data) | ||
2423 | goto error; | ||
2424 | |||
2425 | ret = nla_put_u32(skb, HWSIM_ATTR_RADIO_ID, id); | ||
2426 | if (ret < 0) | ||
2427 | goto error; | ||
2428 | |||
2429 | if (hwname) { | ||
2430 | ret = nla_put(skb, HWSIM_ATTR_RADIO_NAME, strlen(hwname), | ||
2431 | hwname); | ||
2432 | if (ret < 0) | ||
2433 | goto error; | ||
2434 | } | ||
2435 | |||
2436 | genlmsg_end(skb, data); | ||
2437 | |||
2438 | hwsim_mcast_config_msg(skb, info); | ||
2439 | |||
2440 | return; | ||
2441 | |||
2442 | error: | ||
2443 | nlmsg_free(skb); | ||
2444 | } | ||
2445 | |||
2446 | static void mac80211_hwsim_del_radio(struct mac80211_hwsim_data *data, | ||
2447 | const char *hwname, | ||
2448 | struct genl_info *info) | ||
2196 | { | 2449 | { |
2450 | hwsim_mcast_del_radio(data->idx, hwname, info); | ||
2197 | debugfs_remove_recursive(data->debugfs); | 2451 | debugfs_remove_recursive(data->debugfs); |
2198 | ieee80211_unregister_hw(data->hw); | 2452 | ieee80211_unregister_hw(data->hw); |
2199 | device_release_driver(data->dev); | 2453 | device_release_driver(data->dev); |
@@ -2211,7 +2465,7 @@ static void mac80211_hwsim_free(void) | |||
2211 | list))) { | 2465 | list))) { |
2212 | list_del(&data->list); | 2466 | list_del(&data->list); |
2213 | spin_unlock_bh(&hwsim_radio_lock); | 2467 | spin_unlock_bh(&hwsim_radio_lock); |
2214 | mac80211_hwsim_destroy_radio(data); | 2468 | mac80211_hwsim_del_radio(data, NULL, NULL); |
2215 | spin_lock_bh(&hwsim_radio_lock); | 2469 | spin_lock_bh(&hwsim_radio_lock); |
2216 | } | 2470 | } |
2217 | spin_unlock_bh(&hwsim_radio_lock); | 2471 | spin_unlock_bh(&hwsim_radio_lock); |
@@ -2339,7 +2593,6 @@ out: | |||
2339 | static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, | 2593 | static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, |
2340 | struct genl_info *info) | 2594 | struct genl_info *info) |
2341 | { | 2595 | { |
2342 | |||
2343 | struct mac80211_hwsim_data *data2; | 2596 | struct mac80211_hwsim_data *data2; |
2344 | struct ieee80211_rx_status rx_status; | 2597 | struct ieee80211_rx_status rx_status; |
2345 | const u8 *dst; | 2598 | const u8 *dst; |
@@ -2382,18 +2635,22 @@ static int hwsim_cloned_frame_received_nl(struct sk_buff *skb_2, | |||
2382 | 2635 | ||
2383 | /* A frame is received from user space */ | 2636 | /* A frame is received from user space */ |
2384 | memset(&rx_status, 0, sizeof(rx_status)); | 2637 | memset(&rx_status, 0, sizeof(rx_status)); |
2638 | /* TODO: Check ATTR_FREQ if it exists, and maybe throw away off-channel | ||
2639 | * packets? | ||
2640 | */ | ||
2385 | rx_status.freq = data2->channel->center_freq; | 2641 | rx_status.freq = data2->channel->center_freq; |
2386 | rx_status.band = data2->channel->band; | 2642 | rx_status.band = data2->channel->band; |
2387 | rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]); | 2643 | rx_status.rate_idx = nla_get_u32(info->attrs[HWSIM_ATTR_RX_RATE]); |
2388 | rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); | 2644 | rx_status.signal = nla_get_u32(info->attrs[HWSIM_ATTR_SIGNAL]); |
2389 | 2645 | ||
2390 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); | 2646 | memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status)); |
2647 | data2->rx_pkts++; | ||
2648 | data2->rx_bytes += skb->len; | ||
2391 | ieee80211_rx_irqsafe(data2->hw, skb); | 2649 | ieee80211_rx_irqsafe(data2->hw, skb); |
2392 | 2650 | ||
2393 | return 0; | 2651 | return 0; |
2394 | err: | 2652 | err: |
2395 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); | 2653 | printk(KERN_DEBUG "mac80211_hwsim: error occurred in %s\n", __func__); |
2396 | goto out; | ||
2397 | out: | 2654 | out: |
2398 | dev_kfree_skb(skb); | 2655 | dev_kfree_skb(skb); |
2399 | return -EINVAL; | 2656 | return -EINVAL; |
@@ -2429,54 +2686,72 @@ static int hwsim_register_received_nl(struct sk_buff *skb_2, | |||
2429 | return 0; | 2686 | return 0; |
2430 | } | 2687 | } |
2431 | 2688 | ||
2432 | static int hwsim_create_radio_nl(struct sk_buff *msg, struct genl_info *info) | 2689 | static int hwsim_new_radio_nl(struct sk_buff *msg, struct genl_info *info) |
2433 | { | 2690 | { |
2434 | unsigned int chans = channels; | 2691 | struct hwsim_new_radio_params param = { 0 }; |
2435 | const char *alpha2 = NULL; | 2692 | |
2436 | const struct ieee80211_regdomain *regd = NULL; | 2693 | param.reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; |
2437 | bool reg_strict = info->attrs[HWSIM_ATTR_REG_STRICT_REG]; | 2694 | param.p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE]; |
2438 | bool p2p_device = info->attrs[HWSIM_ATTR_SUPPORT_P2P_DEVICE]; | 2695 | param.channels = channels; |
2439 | bool use_chanctx; | 2696 | param.destroy_on_close = |
2697 | info->attrs[HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE]; | ||
2440 | 2698 | ||
2441 | if (info->attrs[HWSIM_ATTR_CHANNELS]) | 2699 | if (info->attrs[HWSIM_ATTR_CHANNELS]) |
2442 | chans = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]); | 2700 | param.channels = nla_get_u32(info->attrs[HWSIM_ATTR_CHANNELS]); |
2701 | |||
2702 | if (info->attrs[HWSIM_ATTR_NO_VIF]) | ||
2703 | param.no_vif = true; | ||
2704 | |||
2705 | if (info->attrs[HWSIM_ATTR_RADIO_NAME]) | ||
2706 | param.hwname = nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]); | ||
2443 | 2707 | ||
2444 | if (info->attrs[HWSIM_ATTR_USE_CHANCTX]) | 2708 | if (info->attrs[HWSIM_ATTR_USE_CHANCTX]) |
2445 | use_chanctx = true; | 2709 | param.use_chanctx = true; |
2446 | else | 2710 | else |
2447 | use_chanctx = (chans > 1); | 2711 | param.use_chanctx = (param.channels > 1); |
2448 | 2712 | ||
2449 | if (info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]) | 2713 | if (info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]) |
2450 | alpha2 = nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]); | 2714 | param.reg_alpha2 = |
2715 | nla_data(info->attrs[HWSIM_ATTR_REG_HINT_ALPHA2]); | ||
2451 | 2716 | ||
2452 | if (info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]) { | 2717 | if (info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]) { |
2453 | u32 idx = nla_get_u32(info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]); | 2718 | u32 idx = nla_get_u32(info->attrs[HWSIM_ATTR_REG_CUSTOM_REG]); |
2454 | 2719 | ||
2455 | if (idx >= ARRAY_SIZE(hwsim_world_regdom_custom)) | 2720 | if (idx >= ARRAY_SIZE(hwsim_world_regdom_custom)) |
2456 | return -EINVAL; | 2721 | return -EINVAL; |
2457 | regd = hwsim_world_regdom_custom[idx]; | 2722 | param.regd = hwsim_world_regdom_custom[idx]; |
2458 | } | 2723 | } |
2459 | 2724 | ||
2460 | return mac80211_hwsim_create_radio(chans, alpha2, regd, reg_strict, | 2725 | return mac80211_hwsim_new_radio(info, ¶m); |
2461 | p2p_device, use_chanctx); | ||
2462 | } | 2726 | } |
2463 | 2727 | ||
2464 | static int hwsim_destroy_radio_nl(struct sk_buff *msg, struct genl_info *info) | 2728 | static int hwsim_del_radio_nl(struct sk_buff *msg, struct genl_info *info) |
2465 | { | 2729 | { |
2466 | struct mac80211_hwsim_data *data; | 2730 | struct mac80211_hwsim_data *data; |
2467 | int idx; | 2731 | s64 idx = -1; |
2732 | const char *hwname = NULL; | ||
2468 | 2733 | ||
2469 | if (!info->attrs[HWSIM_ATTR_RADIO_ID]) | 2734 | if (info->attrs[HWSIM_ATTR_RADIO_ID]) |
2735 | idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); | ||
2736 | else if (info->attrs[HWSIM_ATTR_RADIO_NAME]) | ||
2737 | hwname = (void *)nla_data(info->attrs[HWSIM_ATTR_RADIO_NAME]); | ||
2738 | else | ||
2470 | return -EINVAL; | 2739 | return -EINVAL; |
2471 | idx = nla_get_u32(info->attrs[HWSIM_ATTR_RADIO_ID]); | ||
2472 | 2740 | ||
2473 | spin_lock_bh(&hwsim_radio_lock); | 2741 | spin_lock_bh(&hwsim_radio_lock); |
2474 | list_for_each_entry(data, &hwsim_radios, list) { | 2742 | list_for_each_entry(data, &hwsim_radios, list) { |
2475 | if (data->idx != idx) | 2743 | if (idx >= 0) { |
2476 | continue; | 2744 | if (data->idx != idx) |
2745 | continue; | ||
2746 | } else { | ||
2747 | if (hwname && | ||
2748 | strcmp(hwname, wiphy_name(data->hw->wiphy))) | ||
2749 | continue; | ||
2750 | } | ||
2751 | |||
2477 | list_del(&data->list); | 2752 | list_del(&data->list); |
2478 | spin_unlock_bh(&hwsim_radio_lock); | 2753 | spin_unlock_bh(&hwsim_radio_lock); |
2479 | mac80211_hwsim_destroy_radio(data); | 2754 | mac80211_hwsim_del_radio(data, hwname, info); |
2480 | return 0; | 2755 | return 0; |
2481 | } | 2756 | } |
2482 | spin_unlock_bh(&hwsim_radio_lock); | 2757 | spin_unlock_bh(&hwsim_radio_lock); |
@@ -2503,19 +2778,42 @@ static const struct genl_ops hwsim_ops[] = { | |||
2503 | .doit = hwsim_tx_info_frame_received_nl, | 2778 | .doit = hwsim_tx_info_frame_received_nl, |
2504 | }, | 2779 | }, |
2505 | { | 2780 | { |
2506 | .cmd = HWSIM_CMD_CREATE_RADIO, | 2781 | .cmd = HWSIM_CMD_NEW_RADIO, |
2507 | .policy = hwsim_genl_policy, | 2782 | .policy = hwsim_genl_policy, |
2508 | .doit = hwsim_create_radio_nl, | 2783 | .doit = hwsim_new_radio_nl, |
2509 | .flags = GENL_ADMIN_PERM, | 2784 | .flags = GENL_ADMIN_PERM, |
2510 | }, | 2785 | }, |
2511 | { | 2786 | { |
2512 | .cmd = HWSIM_CMD_DESTROY_RADIO, | 2787 | .cmd = HWSIM_CMD_DEL_RADIO, |
2513 | .policy = hwsim_genl_policy, | 2788 | .policy = hwsim_genl_policy, |
2514 | .doit = hwsim_destroy_radio_nl, | 2789 | .doit = hwsim_del_radio_nl, |
2515 | .flags = GENL_ADMIN_PERM, | 2790 | .flags = GENL_ADMIN_PERM, |
2516 | }, | 2791 | }, |
2517 | }; | 2792 | }; |
2518 | 2793 | ||
2794 | static void destroy_radio(struct work_struct *work) | ||
2795 | { | ||
2796 | struct mac80211_hwsim_data *data = | ||
2797 | container_of(work, struct mac80211_hwsim_data, destroy_work); | ||
2798 | |||
2799 | mac80211_hwsim_del_radio(data, NULL, NULL); | ||
2800 | } | ||
2801 | |||
2802 | static void remove_user_radios(u32 portid) | ||
2803 | { | ||
2804 | struct mac80211_hwsim_data *entry, *tmp; | ||
2805 | |||
2806 | spin_lock_bh(&hwsim_radio_lock); | ||
2807 | list_for_each_entry_safe(entry, tmp, &hwsim_radios, list) { | ||
2808 | if (entry->destroy_on_close && entry->portid == portid) { | ||
2809 | list_del(&entry->list); | ||
2810 | INIT_WORK(&entry->destroy_work, destroy_radio); | ||
2811 | schedule_work(&entry->destroy_work); | ||
2812 | } | ||
2813 | } | ||
2814 | spin_unlock_bh(&hwsim_radio_lock); | ||
2815 | } | ||
2816 | |||
2519 | static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, | 2817 | static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, |
2520 | unsigned long state, | 2818 | unsigned long state, |
2521 | void *_notify) | 2819 | void *_notify) |
@@ -2525,6 +2823,8 @@ static int mac80211_hwsim_netlink_notify(struct notifier_block *nb, | |||
2525 | if (state != NETLINK_URELEASE) | 2823 | if (state != NETLINK_URELEASE) |
2526 | return NOTIFY_DONE; | 2824 | return NOTIFY_DONE; |
2527 | 2825 | ||
2826 | remove_user_radios(notify->portid); | ||
2827 | |||
2528 | if (notify->portid == wmediumd_portid) { | 2828 | if (notify->portid == wmediumd_portid) { |
2529 | printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink" | 2829 | printk(KERN_INFO "mac80211_hwsim: wmediumd released netlink" |
2530 | " socket, switching to perfect channel medium\n"); | 2830 | " socket, switching to perfect channel medium\n"); |
@@ -2544,7 +2844,9 @@ static int hwsim_init_netlink(void) | |||
2544 | 2844 | ||
2545 | printk(KERN_INFO "mac80211_hwsim: initializing netlink\n"); | 2845 | printk(KERN_INFO "mac80211_hwsim: initializing netlink\n"); |
2546 | 2846 | ||
2547 | rc = genl_register_family_with_ops(&hwsim_genl_family, hwsim_ops); | 2847 | rc = genl_register_family_with_ops_groups(&hwsim_genl_family, |
2848 | hwsim_ops, | ||
2849 | hwsim_mcgrps); | ||
2548 | if (rc) | 2850 | if (rc) |
2549 | goto failure; | 2851 | goto failure; |
2550 | 2852 | ||
@@ -2605,69 +2907,73 @@ static int __init init_mac80211_hwsim(void) | |||
2605 | goto out_unregister_driver; | 2907 | goto out_unregister_driver; |
2606 | } | 2908 | } |
2607 | 2909 | ||
2910 | err = hwsim_init_netlink(); | ||
2911 | if (err < 0) | ||
2912 | goto out_unregister_driver; | ||
2913 | |||
2608 | for (i = 0; i < radios; i++) { | 2914 | for (i = 0; i < radios; i++) { |
2609 | const char *reg_alpha2 = NULL; | 2915 | struct hwsim_new_radio_params param = { 0 }; |
2610 | const struct ieee80211_regdomain *regd = NULL; | 2916 | |
2611 | bool reg_strict = false; | 2917 | param.channels = channels; |
2612 | 2918 | ||
2613 | switch (regtest) { | 2919 | switch (regtest) { |
2614 | case HWSIM_REGTEST_DIFF_COUNTRY: | 2920 | case HWSIM_REGTEST_DIFF_COUNTRY: |
2615 | if (i < ARRAY_SIZE(hwsim_alpha2s)) | 2921 | if (i < ARRAY_SIZE(hwsim_alpha2s)) |
2616 | reg_alpha2 = hwsim_alpha2s[i]; | 2922 | param.reg_alpha2 = hwsim_alpha2s[i]; |
2617 | break; | 2923 | break; |
2618 | case HWSIM_REGTEST_DRIVER_REG_FOLLOW: | 2924 | case HWSIM_REGTEST_DRIVER_REG_FOLLOW: |
2619 | if (!i) | 2925 | if (!i) |
2620 | reg_alpha2 = hwsim_alpha2s[0]; | 2926 | param.reg_alpha2 = hwsim_alpha2s[0]; |
2621 | break; | 2927 | break; |
2622 | case HWSIM_REGTEST_STRICT_ALL: | 2928 | case HWSIM_REGTEST_STRICT_ALL: |
2623 | reg_strict = true; | 2929 | param.reg_strict = true; |
2624 | case HWSIM_REGTEST_DRIVER_REG_ALL: | 2930 | case HWSIM_REGTEST_DRIVER_REG_ALL: |
2625 | reg_alpha2 = hwsim_alpha2s[0]; | 2931 | param.reg_alpha2 = hwsim_alpha2s[0]; |
2626 | break; | 2932 | break; |
2627 | case HWSIM_REGTEST_WORLD_ROAM: | 2933 | case HWSIM_REGTEST_WORLD_ROAM: |
2628 | if (i == 0) | 2934 | if (i == 0) |
2629 | regd = &hwsim_world_regdom_custom_01; | 2935 | param.regd = &hwsim_world_regdom_custom_01; |
2630 | break; | 2936 | break; |
2631 | case HWSIM_REGTEST_CUSTOM_WORLD: | 2937 | case HWSIM_REGTEST_CUSTOM_WORLD: |
2632 | regd = &hwsim_world_regdom_custom_01; | 2938 | param.regd = &hwsim_world_regdom_custom_01; |
2633 | break; | 2939 | break; |
2634 | case HWSIM_REGTEST_CUSTOM_WORLD_2: | 2940 | case HWSIM_REGTEST_CUSTOM_WORLD_2: |
2635 | if (i == 0) | 2941 | if (i == 0) |
2636 | regd = &hwsim_world_regdom_custom_01; | 2942 | param.regd = &hwsim_world_regdom_custom_01; |
2637 | else if (i == 1) | 2943 | else if (i == 1) |
2638 | regd = &hwsim_world_regdom_custom_02; | 2944 | param.regd = &hwsim_world_regdom_custom_02; |
2639 | break; | 2945 | break; |
2640 | case HWSIM_REGTEST_STRICT_FOLLOW: | 2946 | case HWSIM_REGTEST_STRICT_FOLLOW: |
2641 | if (i == 0) { | 2947 | if (i == 0) { |
2642 | reg_strict = true; | 2948 | param.reg_strict = true; |
2643 | reg_alpha2 = hwsim_alpha2s[0]; | 2949 | param.reg_alpha2 = hwsim_alpha2s[0]; |
2644 | } | 2950 | } |
2645 | break; | 2951 | break; |
2646 | case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: | 2952 | case HWSIM_REGTEST_STRICT_AND_DRIVER_REG: |
2647 | if (i == 0) { | 2953 | if (i == 0) { |
2648 | reg_strict = true; | 2954 | param.reg_strict = true; |
2649 | reg_alpha2 = hwsim_alpha2s[0]; | 2955 | param.reg_alpha2 = hwsim_alpha2s[0]; |
2650 | } else if (i == 1) { | 2956 | } else if (i == 1) { |
2651 | reg_alpha2 = hwsim_alpha2s[1]; | 2957 | param.reg_alpha2 = hwsim_alpha2s[1]; |
2652 | } | 2958 | } |
2653 | break; | 2959 | break; |
2654 | case HWSIM_REGTEST_ALL: | 2960 | case HWSIM_REGTEST_ALL: |
2655 | switch (i) { | 2961 | switch (i) { |
2656 | case 0: | 2962 | case 0: |
2657 | regd = &hwsim_world_regdom_custom_01; | 2963 | param.regd = &hwsim_world_regdom_custom_01; |
2658 | break; | 2964 | break; |
2659 | case 1: | 2965 | case 1: |
2660 | regd = &hwsim_world_regdom_custom_02; | 2966 | param.regd = &hwsim_world_regdom_custom_02; |
2661 | break; | 2967 | break; |
2662 | case 2: | 2968 | case 2: |
2663 | reg_alpha2 = hwsim_alpha2s[0]; | 2969 | param.reg_alpha2 = hwsim_alpha2s[0]; |
2664 | break; | 2970 | break; |
2665 | case 3: | 2971 | case 3: |
2666 | reg_alpha2 = hwsim_alpha2s[1]; | 2972 | param.reg_alpha2 = hwsim_alpha2s[1]; |
2667 | break; | 2973 | break; |
2668 | case 4: | 2974 | case 4: |
2669 | reg_strict = true; | 2975 | param.reg_strict = true; |
2670 | reg_alpha2 = hwsim_alpha2s[2]; | 2976 | param.reg_alpha2 = hwsim_alpha2s[2]; |
2671 | break; | 2977 | break; |
2672 | } | 2978 | } |
2673 | break; | 2979 | break; |
@@ -2675,10 +2981,10 @@ static int __init init_mac80211_hwsim(void) | |||
2675 | break; | 2981 | break; |
2676 | } | 2982 | } |
2677 | 2983 | ||
2678 | err = mac80211_hwsim_create_radio(channels, reg_alpha2, | 2984 | param.p2p_device = support_p2p_device; |
2679 | regd, reg_strict, | 2985 | param.use_chanctx = channels > 1; |
2680 | support_p2p_device, | 2986 | |
2681 | channels > 1); | 2987 | err = mac80211_hwsim_new_radio(NULL, ¶m); |
2682 | if (err < 0) | 2988 | if (err < 0) |
2683 | goto out_free_radios; | 2989 | goto out_free_radios; |
2684 | } | 2990 | } |
@@ -2704,10 +3010,6 @@ static int __init init_mac80211_hwsim(void) | |||
2704 | } | 3010 | } |
2705 | rtnl_unlock(); | 3011 | rtnl_unlock(); |
2706 | 3012 | ||
2707 | err = hwsim_init_netlink(); | ||
2708 | if (err < 0) | ||
2709 | goto out_free_mon; | ||
2710 | |||
2711 | return 0; | 3013 | return 0; |
2712 | 3014 | ||
2713 | out_free_mon: | 3015 | out_free_mon: |
diff --git a/drivers/net/wireless/mac80211_hwsim.h b/drivers/net/wireless/mac80211_hwsim.h index c9d0315575ba..f08debdd639b 100644 --- a/drivers/net/wireless/mac80211_hwsim.h +++ b/drivers/net/wireless/mac80211_hwsim.h | |||
@@ -60,14 +60,15 @@ 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 | ||
71 | * @__HWSIM_CMD_MAX: enum limit | 72 | * @__HWSIM_CMD_MAX: enum limit |
72 | */ | 73 | */ |
73 | enum { | 74 | enum { |
@@ -75,12 +76,15 @@ enum { | |||
75 | HWSIM_CMD_REGISTER, | 76 | HWSIM_CMD_REGISTER, |
76 | HWSIM_CMD_FRAME, | 77 | HWSIM_CMD_FRAME, |
77 | HWSIM_CMD_TX_INFO_FRAME, | 78 | HWSIM_CMD_TX_INFO_FRAME, |
78 | HWSIM_CMD_CREATE_RADIO, | 79 | HWSIM_CMD_NEW_RADIO, |
79 | HWSIM_CMD_DESTROY_RADIO, | 80 | HWSIM_CMD_DEL_RADIO, |
80 | __HWSIM_CMD_MAX, | 81 | __HWSIM_CMD_MAX, |
81 | }; | 82 | }; |
82 | #define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1) | 83 | #define HWSIM_CMD_MAX (_HWSIM_CMD_MAX - 1) |
83 | 84 | ||
85 | #define HWSIM_CMD_CREATE_RADIO HWSIM_CMD_NEW_RADIO | ||
86 | #define HWSIM_CMD_DESTROY_RADIO HWSIM_CMD_DEL_RADIO | ||
87 | |||
84 | /** | 88 | /** |
85 | * enum hwsim_attrs - hwsim netlink attributes | 89 | * enum hwsim_attrs - hwsim netlink attributes |
86 | * | 90 | * |
@@ -111,6 +115,11 @@ enum { | |||
111 | * @HWSIM_ATTR_USE_CHANCTX: used with the %HWSIM_CMD_CREATE_RADIO | 115 | * @HWSIM_ATTR_USE_CHANCTX: used with the %HWSIM_CMD_CREATE_RADIO |
112 | * command to force use of channel contexts even when only a | 116 | * command to force use of channel contexts even when only a |
113 | * single channel is supported | 117 | * single channel is supported |
118 | * @HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE: used with the %HWSIM_CMD_CREATE_RADIO | ||
119 | * command to force radio removal when process that created the radio dies | ||
120 | * @HWSIM_ATTR_RADIO_NAME: Name of radio, e.g. phy666 | ||
121 | * @HWSIM_ATTR_NO_VIF: Do not create vif (wlanX) when creating radio. | ||
122 | * @HWSIM_ATTR_FREQ: Frequency at which packet is transmitted or received. | ||
114 | * @__HWSIM_ATTR_MAX: enum limit | 123 | * @__HWSIM_ATTR_MAX: enum limit |
115 | */ | 124 | */ |
116 | 125 | ||
@@ -132,6 +141,10 @@ enum { | |||
132 | HWSIM_ATTR_REG_STRICT_REG, | 141 | HWSIM_ATTR_REG_STRICT_REG, |
133 | HWSIM_ATTR_SUPPORT_P2P_DEVICE, | 142 | HWSIM_ATTR_SUPPORT_P2P_DEVICE, |
134 | HWSIM_ATTR_USE_CHANCTX, | 143 | HWSIM_ATTR_USE_CHANCTX, |
144 | HWSIM_ATTR_DESTROY_RADIO_ON_CLOSE, | ||
145 | HWSIM_ATTR_RADIO_NAME, | ||
146 | HWSIM_ATTR_NO_VIF, | ||
147 | HWSIM_ATTR_FREQ, | ||
135 | __HWSIM_ATTR_MAX, | 148 | __HWSIM_ATTR_MAX, |
136 | }; | 149 | }; |
137 | #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) | 150 | #define HWSIM_ATTR_MAX (__HWSIM_ATTR_MAX - 1) |
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c index 0dd672954ad1..f63abfd8acd7 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, |
@@ -2779,6 +2826,7 @@ static struct cfg80211_ops mwifiex_cfg80211_ops = { | |||
2779 | .disconnect = mwifiex_cfg80211_disconnect, | 2826 | .disconnect = mwifiex_cfg80211_disconnect, |
2780 | .get_station = mwifiex_cfg80211_get_station, | 2827 | .get_station = mwifiex_cfg80211_get_station, |
2781 | .dump_station = mwifiex_cfg80211_dump_station, | 2828 | .dump_station = mwifiex_cfg80211_dump_station, |
2829 | .dump_survey = mwifiex_cfg80211_dump_survey, | ||
2782 | .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, | 2830 | .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, |
2783 | .join_ibss = mwifiex_cfg80211_join_ibss, | 2831 | .join_ibss = mwifiex_cfg80211_join_ibss, |
2784 | .leave_ibss = mwifiex_cfg80211_leave_ibss, | 2832 | .leave_ibss = mwifiex_cfg80211_leave_ibss, |
@@ -2840,6 +2888,25 @@ static const struct wiphy_coalesce_support mwifiex_coalesce_support = { | |||
2840 | .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN, | 2888 | .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN, |
2841 | }; | 2889 | }; |
2842 | 2890 | ||
2891 | int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter) | ||
2892 | { | ||
2893 | u32 n_channels_bg, n_channels_a = 0; | ||
2894 | |||
2895 | n_channels_bg = mwifiex_band_2ghz.n_channels; | ||
2896 | |||
2897 | if (adapter->config_bands & BAND_A) | ||
2898 | n_channels_a = mwifiex_band_5ghz.n_channels; | ||
2899 | |||
2900 | adapter->num_in_chan_stats = max_t(u32, n_channels_bg, n_channels_a); | ||
2901 | adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) * | ||
2902 | adapter->num_in_chan_stats); | ||
2903 | |||
2904 | if (!adapter->chan_stats) | ||
2905 | return -ENOMEM; | ||
2906 | |||
2907 | return 0; | ||
2908 | } | ||
2909 | |||
2843 | /* | 2910 | /* |
2844 | * This function registers the device with CFG802.11 subsystem. | 2911 | * This function registers the device with CFG802.11 subsystem. |
2845 | * | 2912 | * |
diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h index e0d00a7f0ec3..f53e5b50d3d8 100644 --- a/drivers/net/wireless/mwifiex/decl.h +++ b/drivers/net/wireless/mwifiex/decl.h | |||
@@ -185,4 +185,14 @@ struct mwifiex_arp_eth_header { | |||
185 | u8 ar_tha[ETH_ALEN]; | 185 | u8 ar_tha[ETH_ALEN]; |
186 | u8 ar_tip[4]; | 186 | u8 ar_tip[4]; |
187 | } __packed; | 187 | } __packed; |
188 | |||
189 | struct mwifiex_chan_stats { | ||
190 | u8 chan_num; | ||
191 | u8 bandcfg; | ||
192 | u8 flags; | ||
193 | s8 noise; | ||
194 | u16 total_bss; | ||
195 | u16 cca_scan_dur; | ||
196 | u16 cca_busy_dur; | ||
197 | } __packed; | ||
188 | #endif /* !_MWIFIEX_DECL_H_ */ | 198 | #endif /* !_MWIFIEX_DECL_H_ */ |
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h index 1eb61739071f..7f922a882c13 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 | ||
@@ -611,6 +612,16 @@ struct uap_rxpd { | |||
611 | u8 reserved1; | 612 | u8 reserved1; |
612 | }; | 613 | }; |
613 | 614 | ||
615 | struct mwifiex_fw_chan_stats { | ||
616 | u8 chan_num; | ||
617 | u8 bandcfg; | ||
618 | u8 flags; | ||
619 | s8 noise; | ||
620 | __le16 total_bss; | ||
621 | __le16 cca_scan_dur; | ||
622 | __le16 cca_busy_dur; | ||
623 | } __packed; | ||
624 | |||
614 | enum mwifiex_chan_scan_mode_bitmasks { | 625 | enum mwifiex_chan_scan_mode_bitmasks { |
615 | MWIFIEX_PASSIVE_SCAN = BIT(0), | 626 | MWIFIEX_PASSIVE_SCAN = BIT(0), |
616 | MWIFIEX_DISABLE_CHAN_FILT = BIT(1), | 627 | MWIFIEX_DISABLE_CHAN_FILT = BIT(1), |
@@ -660,6 +671,11 @@ struct mwifiex_ie_types_scan_chan_gap { | |||
660 | __le16 chan_gap; | 671 | __le16 chan_gap; |
661 | } __packed; | 672 | } __packed; |
662 | 673 | ||
674 | struct mwifiex_ietypes_chanstats { | ||
675 | struct mwifiex_ie_types_header header; | ||
676 | struct mwifiex_fw_chan_stats chanstats[0]; | ||
677 | } __packed; | ||
678 | |||
663 | struct mwifiex_ie_types_wildcard_ssid_params { | 679 | struct mwifiex_ie_types_wildcard_ssid_params { |
664 | struct mwifiex_ie_types_header header; | 680 | struct mwifiex_ie_types_header header; |
665 | u8 max_ssid_length; | 681 | u8 max_ssid_length; |
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c index d5070c444fe1..f26420dbab6f 100644 --- a/drivers/net/wireless/mwifiex/main.c +++ b/drivers/net/wireless/mwifiex/main.c | |||
@@ -122,6 +122,7 @@ static int mwifiex_unregister(struct mwifiex_adapter *adapter) | |||
122 | } | 122 | } |
123 | } | 123 | } |
124 | 124 | ||
125 | vfree(adapter->chan_stats); | ||
125 | kfree(adapter); | 126 | kfree(adapter); |
126 | return 0; | 127 | return 0; |
127 | } | 128 | } |
@@ -447,6 +448,11 @@ static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) | |||
447 | goto err_init_fw; | 448 | goto err_init_fw; |
448 | } | 449 | } |
449 | 450 | ||
451 | if (mwifiex_init_channel_scan_gap(adapter)) { | ||
452 | dev_err(adapter->dev, "could not init channel stats table\n"); | ||
453 | goto err_init_fw; | ||
454 | } | ||
455 | |||
450 | rtnl_lock(); | 456 | rtnl_lock(); |
451 | /* Create station interface by default */ | 457 | /* Create station interface by default */ |
452 | wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", | 458 | wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", |
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h index f55658d15c60..cb393195eee1 100644 --- a/drivers/net/wireless/mwifiex/main.h +++ b/drivers/net/wireless/mwifiex/main.h | |||
@@ -845,6 +845,9 @@ struct mwifiex_adapter { | |||
845 | u8 curr_mem_idx; | 845 | u8 curr_mem_idx; |
846 | bool scan_chan_gap_enabled; | 846 | bool scan_chan_gap_enabled; |
847 | struct sk_buff_head rx_data_q; | 847 | struct sk_buff_head rx_data_q; |
848 | struct mwifiex_chan_stats *chan_stats; | ||
849 | u32 num_in_chan_stats; | ||
850 | int survey_idx; | ||
848 | }; | 851 | }; |
849 | 852 | ||
850 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); | 853 | int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); |
@@ -1031,7 +1034,8 @@ void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv); | |||
1031 | int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, | 1034 | int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, |
1032 | struct host_cmd_ds_command *cmd, | 1035 | struct host_cmd_ds_command *cmd, |
1033 | void *data_buf); | 1036 | void *data_buf); |
1034 | int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv); | 1037 | int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv, |
1038 | struct host_cmd_ds_command *resp); | ||
1035 | int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv, | 1039 | int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv, |
1036 | void *buf); | 1040 | void *buf); |
1037 | 1041 | ||
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/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/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/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/rtlwifi/rtl8821ae/phy.c b/drivers/net/wireless/rtlwifi/rtl8821ae/phy.c index 1e9570fa874f..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); |
@@ -3746,7 +3746,7 @@ static void _rtl8821ae_iqk_tx_fill_iqc(struct ieee80211_hw *hw, | |||
3746 | break; | 3746 | break; |
3747 | default: | 3747 | default: |
3748 | break; | 3748 | break; |
3749 | }; | 3749 | } |
3750 | } | 3750 | } |
3751 | 3751 | ||
3752 | static void _rtl8821ae_iqk_rx_fill_iqc(struct ieee80211_hw *hw, | 3752 | static void _rtl8821ae_iqk_rx_fill_iqc(struct ieee80211_hw *hw, |
@@ -3767,7 +3767,7 @@ static void _rtl8821ae_iqk_rx_fill_iqc(struct ieee80211_hw *hw, | |||
3767 | break; | 3767 | break; |
3768 | default: | 3768 | default: |
3769 | break; | 3769 | break; |
3770 | }; | 3770 | } |
3771 | } | 3771 | } |
3772 | 3772 | ||
3773 | #define cal_num 10 | 3773 | #define cal_num 10 |
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: |