diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath10k')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/ce.c | 9 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/core.c | 30 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/core.h | 5 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/debug.c | 7 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/htt_rx.c | 99 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/htt_tx.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/mac.c | 27 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/mac.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/pci.c | 364 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/trace.h | 109 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/txrx.c | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi.c | 16 |
12 files changed, 388 insertions, 286 deletions
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 9b89ac133946..a156e6e48708 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c | |||
@@ -558,6 +558,7 @@ int ath10k_ce_revoke_recv_next(struct ath10k_ce_pipe *ce_state, | |||
558 | 558 | ||
559 | /* sanity */ | 559 | /* sanity */ |
560 | dest_ring->per_transfer_context[sw_index] = NULL; | 560 | dest_ring->per_transfer_context[sw_index] = NULL; |
561 | desc->nbytes = 0; | ||
561 | 562 | ||
562 | /* Update sw_index */ | 563 | /* Update sw_index */ |
563 | sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); | 564 | sw_index = CE_RING_IDX_INCR(nentries_mask, sw_index); |
@@ -835,8 +836,8 @@ static int ath10k_ce_init_src_ring(struct ath10k *ar, | |||
835 | 836 | ||
836 | nentries = roundup_pow_of_two(attr->src_nentries); | 837 | nentries = roundup_pow_of_two(attr->src_nentries); |
837 | 838 | ||
838 | memset(src_ring->per_transfer_context, 0, | 839 | memset(src_ring->base_addr_owner_space, 0, |
839 | nentries * sizeof(*src_ring->per_transfer_context)); | 840 | nentries * sizeof(struct ce_desc)); |
840 | 841 | ||
841 | src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); | 842 | src_ring->sw_index = ath10k_ce_src_ring_read_index_get(ar, ctrl_addr); |
842 | src_ring->sw_index &= src_ring->nentries_mask; | 843 | src_ring->sw_index &= src_ring->nentries_mask; |
@@ -872,8 +873,8 @@ static int ath10k_ce_init_dest_ring(struct ath10k *ar, | |||
872 | 873 | ||
873 | nentries = roundup_pow_of_two(attr->dest_nentries); | 874 | nentries = roundup_pow_of_two(attr->dest_nentries); |
874 | 875 | ||
875 | memset(dest_ring->per_transfer_context, 0, | 876 | memset(dest_ring->base_addr_owner_space, 0, |
876 | nentries * sizeof(*dest_ring->per_transfer_context)); | 877 | nentries * sizeof(struct ce_desc)); |
877 | 878 | ||
878 | dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr); | 879 | dest_ring->sw_index = ath10k_ce_dest_ring_read_index_get(ar, ctrl_addr); |
879 | dest_ring->sw_index &= dest_ring->nentries_mask; | 880 | dest_ring->sw_index &= dest_ring->nentries_mask; |
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 5c23d00f7d60..f660553c6c48 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c | |||
@@ -31,12 +31,17 @@ | |||
31 | unsigned int ath10k_debug_mask; | 31 | unsigned int ath10k_debug_mask; |
32 | static bool uart_print; | 32 | static bool uart_print; |
33 | static unsigned int ath10k_p2p; | 33 | static unsigned int ath10k_p2p; |
34 | static bool skip_otp; | ||
35 | |||
34 | module_param_named(debug_mask, ath10k_debug_mask, uint, 0644); | 36 | module_param_named(debug_mask, ath10k_debug_mask, uint, 0644); |
35 | module_param(uart_print, bool, 0644); | 37 | module_param(uart_print, bool, 0644); |
36 | module_param_named(p2p, ath10k_p2p, uint, 0644); | 38 | module_param_named(p2p, ath10k_p2p, uint, 0644); |
39 | module_param(skip_otp, bool, 0644); | ||
40 | |||
37 | MODULE_PARM_DESC(debug_mask, "Debugging mask"); | 41 | MODULE_PARM_DESC(debug_mask, "Debugging mask"); |
38 | MODULE_PARM_DESC(uart_print, "Uart target debugging"); | 42 | MODULE_PARM_DESC(uart_print, "Uart target debugging"); |
39 | MODULE_PARM_DESC(p2p, "Enable ath10k P2P support"); | 43 | MODULE_PARM_DESC(p2p, "Enable ath10k P2P support"); |
44 | MODULE_PARM_DESC(skip_otp, "Skip otp failure for calibration in testmode"); | ||
40 | 45 | ||
41 | static const struct ath10k_hw_params ath10k_hw_params_list[] = { | 46 | static const struct ath10k_hw_params ath10k_hw_params_list[] = { |
42 | { | 47 | { |
@@ -280,7 +285,7 @@ static int ath10k_download_and_run_otp(struct ath10k *ar) | |||
280 | 285 | ||
281 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); | 286 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot otp execute result %d\n", result); |
282 | 287 | ||
283 | if (result != 0) { | 288 | if (!skip_otp && result != 0) { |
284 | ath10k_err(ar, "otp calibration failed: %d", result); | 289 | ath10k_err(ar, "otp calibration failed: %d", result); |
285 | return -EINVAL; | 290 | return -EINVAL; |
286 | } | 291 | } |
@@ -744,6 +749,25 @@ static void ath10k_core_restart(struct work_struct *work) | |||
744 | { | 749 | { |
745 | struct ath10k *ar = container_of(work, struct ath10k, restart_work); | 750 | struct ath10k *ar = container_of(work, struct ath10k, restart_work); |
746 | 751 | ||
752 | set_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); | ||
753 | |||
754 | /* Place a barrier to make sure the compiler doesn't reorder | ||
755 | * CRASH_FLUSH and calling other functions. | ||
756 | */ | ||
757 | barrier(); | ||
758 | |||
759 | ieee80211_stop_queues(ar->hw); | ||
760 | ath10k_drain_tx(ar); | ||
761 | complete_all(&ar->scan.started); | ||
762 | complete_all(&ar->scan.completed); | ||
763 | complete_all(&ar->scan.on_channel); | ||
764 | complete_all(&ar->offchan_tx_completed); | ||
765 | complete_all(&ar->install_key_done); | ||
766 | complete_all(&ar->vdev_setup_done); | ||
767 | wake_up(&ar->htt.empty_tx_wq); | ||
768 | wake_up(&ar->wmi.tx_credits_wq); | ||
769 | wake_up(&ar->peer_mapping_wq); | ||
770 | |||
747 | mutex_lock(&ar->conf_mutex); | 771 | mutex_lock(&ar->conf_mutex); |
748 | 772 | ||
749 | switch (ar->state) { | 773 | switch (ar->state) { |
@@ -781,6 +805,8 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode) | |||
781 | 805 | ||
782 | lockdep_assert_held(&ar->conf_mutex); | 806 | lockdep_assert_held(&ar->conf_mutex); |
783 | 807 | ||
808 | clear_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags); | ||
809 | |||
784 | ath10k_bmi_start(ar); | 810 | ath10k_bmi_start(ar); |
785 | 811 | ||
786 | if (ath10k_init_configure_target(ar)) { | 812 | if (ath10k_init_configure_target(ar)) { |
@@ -1185,6 +1211,8 @@ struct ath10k *ath10k_core_create(size_t priv_size, struct device *dev, | |||
1185 | 1211 | ||
1186 | INIT_LIST_HEAD(&ar->peers); | 1212 | INIT_LIST_HEAD(&ar->peers); |
1187 | init_waitqueue_head(&ar->peer_mapping_wq); | 1213 | init_waitqueue_head(&ar->peer_mapping_wq); |
1214 | init_waitqueue_head(&ar->htt.empty_tx_wq); | ||
1215 | init_waitqueue_head(&ar->wmi.tx_credits_wq); | ||
1188 | 1216 | ||
1189 | init_completion(&ar->offchan_tx_completed); | 1217 | init_completion(&ar->offchan_tx_completed); |
1190 | INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work); | 1218 | INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work); |
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h index 4ca6dc94dd05..8f86bd34e823 100644 --- a/drivers/net/wireless/ath/ath10k/core.h +++ b/drivers/net/wireless/ath/ath10k/core.h | |||
@@ -386,6 +386,11 @@ enum ath10k_dev_flags { | |||
386 | /* Indicates that ath10k device is during CAC phase of DFS */ | 386 | /* Indicates that ath10k device is during CAC phase of DFS */ |
387 | ATH10K_CAC_RUNNING, | 387 | ATH10K_CAC_RUNNING, |
388 | ATH10K_FLAG_CORE_REGISTERED, | 388 | ATH10K_FLAG_CORE_REGISTERED, |
389 | |||
390 | /* Device has crashed and needs to restart. This indicates any pending | ||
391 | * waiters should immediately cancel instead of waiting for a time out. | ||
392 | */ | ||
393 | ATH10K_FLAG_CRASH_FLUSH, | ||
389 | }; | 394 | }; |
390 | 395 | ||
391 | enum ath10k_cal_mode { | 396 | enum ath10k_cal_mode { |
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 9147dd36dcdd..a8f5a72ba259 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c | |||
@@ -695,7 +695,8 @@ static ssize_t ath10k_read_simulate_fw_crash(struct file *file, | |||
695 | "To simulate firmware crash write one of the keywords to this file:\n" | 695 | "To simulate firmware crash write one of the keywords to this file:\n" |
696 | "`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n" | 696 | "`soft` - this will send WMI_FORCE_FW_HANG_ASSERT to firmware if FW supports that command.\n" |
697 | "`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n" | 697 | "`hard` - this will send to firmware command with illegal parameters causing firmware crash.\n" |
698 | "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n"; | 698 | "`assert` - this will send special illegal parameter to firmware to cause assert failure and crash.\n" |
699 | "`hw-restart` - this will simply queue hw restart without fw/hw actually crashing.\n"; | ||
699 | 700 | ||
700 | return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); | 701 | return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf)); |
701 | } | 702 | } |
@@ -748,6 +749,10 @@ static ssize_t ath10k_write_simulate_fw_crash(struct file *file, | |||
748 | } else if (!strcmp(buf, "assert")) { | 749 | } else if (!strcmp(buf, "assert")) { |
749 | ath10k_info(ar, "simulating firmware assert crash\n"); | 750 | ath10k_info(ar, "simulating firmware assert crash\n"); |
750 | ret = ath10k_debug_fw_assert(ar); | 751 | ret = ath10k_debug_fw_assert(ar); |
752 | } else if (!strcmp(buf, "hw-restart")) { | ||
753 | ath10k_info(ar, "user requested hw restart\n"); | ||
754 | queue_work(ar->workqueue, &ar->restart_work); | ||
755 | ret = 0; | ||
751 | } else { | 756 | } else { |
752 | ret = -EINVAL; | 757 | ret = -EINVAL; |
753 | goto exit; | 758 | goto exit; |
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c index fbb3175d4d6e..52c630672718 100644 --- a/drivers/net/wireless/ath/ath10k/htt_rx.c +++ b/drivers/net/wireless/ath/ath10k/htt_rx.c | |||
@@ -291,8 +291,12 @@ 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 + | 294 | dma_unmap_single(htt->ar->dev, |
295 | skb_tailroom(msdu)); | 295 | ATH10K_SKB_CB(msdu)->paddr, |
296 | msdu->len + skb_tailroom(msdu), | ||
297 | DMA_FROM_DEVICE); | ||
298 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx netbuf pop: ", | ||
299 | msdu->data, msdu->len + skb_tailroom(msdu)); | ||
296 | 300 | ||
297 | return msdu; | 301 | return msdu; |
298 | } | 302 | } |
@@ -319,7 +323,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, | |||
319 | int msdu_len, msdu_chaining = 0; | 323 | int msdu_len, msdu_chaining = 0; |
320 | struct sk_buff *msdu, *next; | 324 | struct sk_buff *msdu, *next; |
321 | struct htt_rx_desc *rx_desc; | 325 | struct htt_rx_desc *rx_desc; |
322 | u32 tsf; | ||
323 | 326 | ||
324 | lockdep_assert_held(&htt->rx_ring.lock); | 327 | lockdep_assert_held(&htt->rx_ring.lock); |
325 | 328 | ||
@@ -332,14 +335,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, | |||
332 | while (msdu) { | 335 | while (msdu) { |
333 | int last_msdu, msdu_len_invalid, msdu_chained; | 336 | int last_msdu, msdu_len_invalid, msdu_chained; |
334 | 337 | ||
335 | dma_unmap_single(htt->ar->dev, | ||
336 | ATH10K_SKB_CB(msdu)->paddr, | ||
337 | msdu->len + skb_tailroom(msdu), | ||
338 | DMA_FROM_DEVICE); | ||
339 | |||
340 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt rx pop: ", | ||
341 | msdu->data, msdu->len + skb_tailroom(msdu)); | ||
342 | |||
343 | rx_desc = (struct htt_rx_desc *)msdu->data; | 338 | rx_desc = (struct htt_rx_desc *)msdu->data; |
344 | 339 | ||
345 | /* FIXME: we must report msdu payload since this is what caller | 340 | /* FIXME: we must report msdu payload since this is what caller |
@@ -430,14 +425,14 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, | |||
430 | while (msdu_chained--) { | 425 | while (msdu_chained--) { |
431 | struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt); | 426 | struct sk_buff *next = ath10k_htt_rx_netbuf_pop(htt); |
432 | 427 | ||
433 | dma_unmap_single(htt->ar->dev, | 428 | if (!next) { |
434 | ATH10K_SKB_CB(next)->paddr, | 429 | ath10k_warn(ar, "failed to pop chained msdu\n"); |
435 | next->len + skb_tailroom(next), | 430 | ath10k_htt_rx_free_msdu_chain(*head_msdu); |
436 | DMA_FROM_DEVICE); | 431 | *head_msdu = NULL; |
437 | 432 | msdu = NULL; | |
438 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, | 433 | htt->rx_confused = true; |
439 | "htt rx chained: ", next->data, | 434 | break; |
440 | next->len + skb_tailroom(next)); | 435 | } |
441 | 436 | ||
442 | skb_trim(next, 0); | 437 | skb_trim(next, 0); |
443 | skb_put(next, min(msdu_len, HTT_RX_BUF_SIZE)); | 438 | skb_put(next, min(msdu_len, HTT_RX_BUF_SIZE)); |
@@ -451,8 +446,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt, | |||
451 | last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) & | 446 | last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) & |
452 | RX_MSDU_END_INFO0_LAST_MSDU; | 447 | RX_MSDU_END_INFO0_LAST_MSDU; |
453 | 448 | ||
454 | tsf = __le32_to_cpu(rx_desc->ppdu_end.tsf_timestamp); | 449 | trace_ath10k_htt_rx_desc(ar, &rx_desc->attention, |
455 | trace_ath10k_htt_rx_desc(ar, tsf, &rx_desc->attention, | ||
456 | sizeof(*rx_desc) - sizeof(u32)); | 450 | sizeof(*rx_desc) - sizeof(u32)); |
457 | if (last_msdu) { | 451 | if (last_msdu) { |
458 | msdu->next = NULL; | 452 | msdu->next = NULL; |
@@ -499,6 +493,8 @@ int ath10k_htt_rx_alloc(struct ath10k_htt *htt) | |||
499 | size_t size; | 493 | size_t size; |
500 | struct timer_list *timer = &htt->rx_ring.refill_retry_timer; | 494 | struct timer_list *timer = &htt->rx_ring.refill_retry_timer; |
501 | 495 | ||
496 | htt->rx_confused = false; | ||
497 | |||
502 | htt->rx_ring.size = ath10k_htt_rx_ring_size(htt); | 498 | htt->rx_ring.size = ath10k_htt_rx_ring_size(htt); |
503 | if (!is_power_of_2(htt->rx_ring.size)) { | 499 | if (!is_power_of_2(htt->rx_ring.size)) { |
504 | ath10k_warn(ar, "htt rx ring size is not power of 2\n"); | 500 | ath10k_warn(ar, "htt rx ring size is not power of 2\n"); |
@@ -588,41 +584,47 @@ static int ath10k_htt_rx_crypto_param_len(struct ath10k *ar, | |||
588 | enum htt_rx_mpdu_encrypt_type type) | 584 | enum htt_rx_mpdu_encrypt_type type) |
589 | { | 585 | { |
590 | switch (type) { | 586 | switch (type) { |
587 | case HTT_RX_MPDU_ENCRYPT_NONE: | ||
588 | return 0; | ||
591 | case HTT_RX_MPDU_ENCRYPT_WEP40: | 589 | case HTT_RX_MPDU_ENCRYPT_WEP40: |
592 | case HTT_RX_MPDU_ENCRYPT_WEP104: | 590 | case HTT_RX_MPDU_ENCRYPT_WEP104: |
593 | return 4; | 591 | return IEEE80211_WEP_IV_LEN; |
594 | case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC: | 592 | case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC: |
595 | case HTT_RX_MPDU_ENCRYPT_WEP128: /* not tested */ | ||
596 | case HTT_RX_MPDU_ENCRYPT_TKIP_WPA: | 593 | case HTT_RX_MPDU_ENCRYPT_TKIP_WPA: |
597 | case HTT_RX_MPDU_ENCRYPT_WAPI: /* not tested */ | 594 | return IEEE80211_TKIP_IV_LEN; |
598 | case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: | 595 | case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: |
599 | return 8; | 596 | return IEEE80211_CCMP_HDR_LEN; |
600 | case HTT_RX_MPDU_ENCRYPT_NONE: | 597 | case HTT_RX_MPDU_ENCRYPT_WEP128: |
601 | return 0; | 598 | case HTT_RX_MPDU_ENCRYPT_WAPI: |
599 | break; | ||
602 | } | 600 | } |
603 | 601 | ||
604 | ath10k_warn(ar, "unknown encryption type %d\n", type); | 602 | ath10k_warn(ar, "unsupported encryption type %d\n", type); |
605 | return 0; | 603 | return 0; |
606 | } | 604 | } |
607 | 605 | ||
606 | #define MICHAEL_MIC_LEN 8 | ||
607 | |||
608 | static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar, | 608 | static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar, |
609 | enum htt_rx_mpdu_encrypt_type type) | 609 | enum htt_rx_mpdu_encrypt_type type) |
610 | { | 610 | { |
611 | switch (type) { | 611 | switch (type) { |
612 | case HTT_RX_MPDU_ENCRYPT_NONE: | 612 | case HTT_RX_MPDU_ENCRYPT_NONE: |
613 | return 0; | ||
613 | case HTT_RX_MPDU_ENCRYPT_WEP40: | 614 | case HTT_RX_MPDU_ENCRYPT_WEP40: |
614 | case HTT_RX_MPDU_ENCRYPT_WEP104: | 615 | case HTT_RX_MPDU_ENCRYPT_WEP104: |
615 | case HTT_RX_MPDU_ENCRYPT_WEP128: | 616 | return IEEE80211_WEP_ICV_LEN; |
616 | case HTT_RX_MPDU_ENCRYPT_WAPI: | ||
617 | return 0; | ||
618 | case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC: | 617 | case HTT_RX_MPDU_ENCRYPT_TKIP_WITHOUT_MIC: |
619 | case HTT_RX_MPDU_ENCRYPT_TKIP_WPA: | 618 | case HTT_RX_MPDU_ENCRYPT_TKIP_WPA: |
620 | return 4; | 619 | return IEEE80211_TKIP_ICV_LEN; |
621 | case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: | 620 | case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2: |
622 | return 8; | 621 | return IEEE80211_CCMP_MIC_LEN; |
622 | case HTT_RX_MPDU_ENCRYPT_WEP128: | ||
623 | case HTT_RX_MPDU_ENCRYPT_WAPI: | ||
624 | break; | ||
623 | } | 625 | } |
624 | 626 | ||
625 | ath10k_warn(ar, "unknown encryption type %d\n", type); | 627 | ath10k_warn(ar, "unsupported encryption type %d\n", type); |
626 | return 0; | 628 | return 0; |
627 | } | 629 | } |
628 | 630 | ||
@@ -899,6 +901,8 @@ static void ath10k_process_rx(struct ath10k *ar, | |||
899 | !!(status->flag & RX_FLAG_AMSDU_MORE)); | 901 | !!(status->flag & RX_FLAG_AMSDU_MORE)); |
900 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ", | 902 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "rx skb: ", |
901 | skb->data, skb->len); | 903 | skb->data, skb->len); |
904 | trace_ath10k_rx_hdr(ar, skb->data, skb->len); | ||
905 | trace_ath10k_rx_payload(ar, skb->data, skb->len); | ||
902 | 906 | ||
903 | ieee80211_rx(ar->hw, skb); | 907 | ieee80211_rx(ar->hw, skb); |
904 | } | 908 | } |
@@ -1176,7 +1180,6 @@ static int ath10k_unchain_msdu(struct sk_buff *msdu_head) | |||
1176 | 1180 | ||
1177 | static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt, | 1181 | static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt, |
1178 | struct sk_buff *head, | 1182 | struct sk_buff *head, |
1179 | enum htt_rx_mpdu_status status, | ||
1180 | bool channel_set, | 1183 | bool channel_set, |
1181 | u32 attention) | 1184 | u32 attention) |
1182 | { | 1185 | { |
@@ -1200,22 +1203,11 @@ static bool ath10k_htt_rx_amsdu_allowed(struct ath10k_htt *htt, | |||
1200 | } | 1203 | } |
1201 | 1204 | ||
1202 | /* Skip mgmt frames while we handle this in WMI */ | 1205 | /* Skip mgmt frames while we handle this in WMI */ |
1203 | if (status == HTT_RX_IND_MPDU_STATUS_MGMT_CTRL || | 1206 | if (attention & RX_ATTENTION_FLAGS_MGMT_TYPE) { |
1204 | attention & RX_ATTENTION_FLAGS_MGMT_TYPE) { | ||
1205 | ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx mgmt ctrl\n"); | 1207 | ath10k_dbg(ar, ATH10K_DBG_HTT, "htt rx mgmt ctrl\n"); |
1206 | return false; | 1208 | return false; |
1207 | } | 1209 | } |
1208 | 1210 | ||
1209 | if (status != HTT_RX_IND_MPDU_STATUS_OK && | ||
1210 | status != HTT_RX_IND_MPDU_STATUS_TKIP_MIC_ERR && | ||
1211 | status != HTT_RX_IND_MPDU_STATUS_ERR_INV_PEER && | ||
1212 | !htt->ar->monitor_started) { | ||
1213 | ath10k_dbg(ar, ATH10K_DBG_HTT, | ||
1214 | "htt rx ignoring frame w/ status %d\n", | ||
1215 | status); | ||
1216 | return false; | ||
1217 | } | ||
1218 | |||
1219 | if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) { | 1211 | if (test_bit(ATH10K_CAC_RUNNING, &htt->ar->dev_flags)) { |
1220 | ath10k_dbg(ar, ATH10K_DBG_HTT, | 1212 | ath10k_dbg(ar, ATH10K_DBG_HTT, |
1221 | "htt rx CAC running\n"); | 1213 | "htt rx CAC running\n"); |
@@ -1231,8 +1223,6 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
1231 | struct ath10k *ar = htt->ar; | 1223 | struct ath10k *ar = htt->ar; |
1232 | struct ieee80211_rx_status *rx_status = &htt->rx_status; | 1224 | struct ieee80211_rx_status *rx_status = &htt->rx_status; |
1233 | struct htt_rx_indication_mpdu_range *mpdu_ranges; | 1225 | struct htt_rx_indication_mpdu_range *mpdu_ranges; |
1234 | struct htt_rx_desc *rxd; | ||
1235 | enum htt_rx_mpdu_status status; | ||
1236 | struct ieee80211_hdr *hdr; | 1226 | struct ieee80211_hdr *hdr; |
1237 | int num_mpdu_ranges; | 1227 | int num_mpdu_ranges; |
1238 | u32 attention; | 1228 | u32 attention; |
@@ -1280,8 +1270,6 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
1280 | num_mpdu_ranges)); | 1270 | num_mpdu_ranges)); |
1281 | 1271 | ||
1282 | for (i = 0; i < num_mpdu_ranges; i++) { | 1272 | for (i = 0; i < num_mpdu_ranges; i++) { |
1283 | status = mpdu_ranges[i].mpdu_range_status; | ||
1284 | |||
1285 | for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) { | 1273 | for (j = 0; j < mpdu_ranges[i].mpdu_count; j++) { |
1286 | struct sk_buff *msdu_head, *msdu_tail; | 1274 | struct sk_buff *msdu_head, *msdu_tail; |
1287 | 1275 | ||
@@ -1302,12 +1290,7 @@ static void ath10k_htt_rx_handler(struct ath10k_htt *htt, | |||
1302 | continue; | 1290 | continue; |
1303 | } | 1291 | } |
1304 | 1292 | ||
1305 | rxd = container_of((void *)msdu_head->data, | ||
1306 | struct htt_rx_desc, | ||
1307 | msdu_payload); | ||
1308 | |||
1309 | if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head, | 1293 | if (!ath10k_htt_rx_amsdu_allowed(htt, msdu_head, |
1310 | status, | ||
1311 | channel_set, | 1294 | channel_set, |
1312 | attention)) { | 1295 | attention)) { |
1313 | ath10k_htt_rx_free_msdu_chain(msdu_head); | 1296 | ath10k_htt_rx_free_msdu_chain(msdu_head); |
@@ -1372,6 +1355,8 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, | |||
1372 | &attention); | 1355 | &attention); |
1373 | spin_unlock_bh(&htt->rx_ring.lock); | 1356 | spin_unlock_bh(&htt->rx_ring.lock); |
1374 | 1357 | ||
1358 | tasklet_schedule(&htt->rx_replenish_task); | ||
1359 | |||
1375 | ath10k_dbg(ar, ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n"); | 1360 | ath10k_dbg(ar, ATH10K_DBG_HTT_DUMP, "htt rx frag ahead\n"); |
1376 | 1361 | ||
1377 | if (ret) { | 1362 | if (ret) { |
@@ -1433,7 +1418,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt, | |||
1433 | /* last fragment of TKIP frags has MIC */ | 1418 | /* last fragment of TKIP frags has MIC */ |
1434 | if (!ieee80211_has_morefrags(hdr->frame_control) && | 1419 | if (!ieee80211_has_morefrags(hdr->frame_control) && |
1435 | enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) | 1420 | enctype == HTT_RX_MPDU_ENCRYPT_TKIP_WPA) |
1436 | trim += 8; | 1421 | trim += MICHAEL_MIC_LEN; |
1437 | 1422 | ||
1438 | if (trim > msdu_head->len) { | 1423 | if (trim > msdu_head->len) { |
1439 | ath10k_warn(ar, "htt rx fragment: trailer longer than the frame itself? drop\n"); | 1424 | ath10k_warn(ar, "htt rx fragment: trailer longer than the frame itself? drop\n"); |
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index b0df470250a2..5b7e42f7377c 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c | |||
@@ -92,7 +92,6 @@ int ath10k_htt_tx_alloc(struct ath10k_htt *htt) | |||
92 | struct ath10k *ar = htt->ar; | 92 | struct ath10k *ar = htt->ar; |
93 | 93 | ||
94 | spin_lock_init(&htt->tx_lock); | 94 | spin_lock_init(&htt->tx_lock); |
95 | init_waitqueue_head(&htt->empty_tx_wq); | ||
96 | 95 | ||
97 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, htt->ar->fw_features)) | 96 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, htt->ar->fw_features)) |
98 | htt->max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC; | 97 | htt->max_num_pending_tx = TARGET_10X_NUM_MSDU_DESC; |
@@ -564,7 +563,8 @@ int ath10k_htt_tx(struct ath10k_htt *htt, struct sk_buff *msdu) | |||
564 | (u32)skb_cb->paddr, vdev_id, tid); | 563 | (u32)skb_cb->paddr, vdev_id, tid); |
565 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ", | 564 | ath10k_dbg_dump(ar, ATH10K_DBG_HTT_DUMP, NULL, "htt tx msdu: ", |
566 | msdu->data, msdu->len); | 565 | msdu->data, msdu->len); |
567 | trace_ath10k_htt_tx_msdu(ar, msdu->data, msdu->len); | 566 | trace_ath10k_tx_hdr(ar, msdu->data, msdu->len); |
567 | trace_ath10k_tx_payload(ar, msdu->data, msdu->len); | ||
568 | 568 | ||
569 | sg_items[0].transfer_id = 0; | 569 | sg_items[0].transfer_id = 0; |
570 | sg_items[0].transfer_context = NULL; | 570 | sg_items[0].transfer_context = NULL; |
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 61b006f42f95..1245ac8c5c6f 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c | |||
@@ -519,6 +519,9 @@ static inline int ath10k_vdev_setup_sync(struct ath10k *ar) | |||
519 | 519 | ||
520 | lockdep_assert_held(&ar->conf_mutex); | 520 | lockdep_assert_held(&ar->conf_mutex); |
521 | 521 | ||
522 | if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) | ||
523 | return -ESHUTDOWN; | ||
524 | |||
522 | ret = wait_for_completion_timeout(&ar->vdev_setup_done, | 525 | ret = wait_for_completion_timeout(&ar->vdev_setup_done, |
523 | ATH10K_VDEV_SETUP_TIMEOUT_HZ); | 526 | ATH10K_VDEV_SETUP_TIMEOUT_HZ); |
524 | if (ret == 0) | 527 | if (ret == 0) |
@@ -551,6 +554,8 @@ static int ath10k_monitor_vdev_start(struct ath10k *ar, int vdev_id) | |||
551 | arg.channel.max_reg_power = channel->max_reg_power * 2; | 554 | arg.channel.max_reg_power = channel->max_reg_power * 2; |
552 | arg.channel.max_antenna_gain = channel->max_antenna_gain * 2; | 555 | arg.channel.max_antenna_gain = channel->max_antenna_gain * 2; |
553 | 556 | ||
557 | reinit_completion(&ar->vdev_setup_done); | ||
558 | |||
554 | ret = ath10k_wmi_vdev_start(ar, &arg); | 559 | ret = ath10k_wmi_vdev_start(ar, &arg); |
555 | if (ret) { | 560 | if (ret) { |
556 | ath10k_warn(ar, "failed to request monitor vdev %i start: %d\n", | 561 | ath10k_warn(ar, "failed to request monitor vdev %i start: %d\n", |
@@ -598,6 +603,8 @@ static int ath10k_monitor_vdev_stop(struct ath10k *ar) | |||
598 | ath10k_warn(ar, "failed to put down monitor vdev %i: %d\n", | 603 | ath10k_warn(ar, "failed to put down monitor vdev %i: %d\n", |
599 | ar->monitor_vdev_id, ret); | 604 | ar->monitor_vdev_id, ret); |
600 | 605 | ||
606 | reinit_completion(&ar->vdev_setup_done); | ||
607 | |||
601 | ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); | 608 | ret = ath10k_wmi_vdev_stop(ar, ar->monitor_vdev_id); |
602 | if (ret) | 609 | if (ret) |
603 | ath10k_warn(ar, "failed to to request monitor vdev %i stop: %d\n", | 610 | ath10k_warn(ar, "failed to to request monitor vdev %i stop: %d\n", |
@@ -2350,7 +2357,7 @@ static void ath10k_tx(struct ieee80211_hw *hw, | |||
2350 | } | 2357 | } |
2351 | 2358 | ||
2352 | /* Must not be called with conf_mutex held as workers can use that also. */ | 2359 | /* Must not be called with conf_mutex held as workers can use that also. */ |
2353 | static void ath10k_drain_tx(struct ath10k *ar) | 2360 | void ath10k_drain_tx(struct ath10k *ar) |
2354 | { | 2361 | { |
2355 | /* make sure rcu-protected mac80211 tx path itself is drained */ | 2362 | /* make sure rcu-protected mac80211 tx path itself is drained */ |
2356 | synchronize_net(); | 2363 | synchronize_net(); |
@@ -3307,9 +3314,10 @@ static void ath10k_cancel_hw_scan(struct ieee80211_hw *hw, | |||
3307 | struct ath10k *ar = hw->priv; | 3314 | struct ath10k *ar = hw->priv; |
3308 | 3315 | ||
3309 | mutex_lock(&ar->conf_mutex); | 3316 | mutex_lock(&ar->conf_mutex); |
3310 | cancel_delayed_work_sync(&ar->scan.timeout); | ||
3311 | ath10k_scan_abort(ar); | 3317 | ath10k_scan_abort(ar); |
3312 | mutex_unlock(&ar->conf_mutex); | 3318 | mutex_unlock(&ar->conf_mutex); |
3319 | |||
3320 | cancel_delayed_work_sync(&ar->scan.timeout); | ||
3313 | } | 3321 | } |
3314 | 3322 | ||
3315 | static void ath10k_set_key_h_def_keyidx(struct ath10k *ar, | 3323 | static void ath10k_set_key_h_def_keyidx(struct ath10k *ar, |
@@ -3826,10 +3834,11 @@ static int ath10k_cancel_remain_on_channel(struct ieee80211_hw *hw) | |||
3826 | struct ath10k *ar = hw->priv; | 3834 | struct ath10k *ar = hw->priv; |
3827 | 3835 | ||
3828 | mutex_lock(&ar->conf_mutex); | 3836 | mutex_lock(&ar->conf_mutex); |
3829 | cancel_delayed_work_sync(&ar->scan.timeout); | ||
3830 | ath10k_scan_abort(ar); | 3837 | ath10k_scan_abort(ar); |
3831 | mutex_unlock(&ar->conf_mutex); | 3838 | mutex_unlock(&ar->conf_mutex); |
3832 | 3839 | ||
3840 | cancel_delayed_work_sync(&ar->scan.timeout); | ||
3841 | |||
3833 | return 0; | 3842 | return 0; |
3834 | } | 3843 | } |
3835 | 3844 | ||
@@ -3872,7 +3881,7 @@ static int ath10k_set_frag_threshold(struct ieee80211_hw *hw, u32 value) | |||
3872 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d fragmentation threshold %d\n", | 3881 | ath10k_dbg(ar, ATH10K_DBG_MAC, "mac vdev %d fragmentation threshold %d\n", |
3873 | arvif->vdev_id, value); | 3882 | arvif->vdev_id, value); |
3874 | 3883 | ||
3875 | ret = ath10k_mac_set_rts(arvif, value); | 3884 | ret = ath10k_mac_set_frag(arvif, value); |
3876 | if (ret) { | 3885 | if (ret) { |
3877 | ath10k_warn(ar, "failed to set fragmentation threshold for vdev %d: %d\n", | 3886 | ath10k_warn(ar, "failed to set fragmentation threshold for vdev %d: %d\n", |
3878 | arvif->vdev_id, ret); | 3887 | arvif->vdev_id, ret); |
@@ -3908,7 +3917,9 @@ static void ath10k_flush(struct ieee80211_hw *hw, struct ieee80211_vif *vif, | |||
3908 | empty = (ar->htt.num_pending_tx == 0); | 3917 | empty = (ar->htt.num_pending_tx == 0); |
3909 | spin_unlock_bh(&ar->htt.tx_lock); | 3918 | spin_unlock_bh(&ar->htt.tx_lock); |
3910 | 3919 | ||
3911 | skip = (ar->state == ATH10K_STATE_WEDGED); | 3920 | skip = (ar->state == ATH10K_STATE_WEDGED) || |
3921 | test_bit(ATH10K_FLAG_CRASH_FLUSH, | ||
3922 | &ar->dev_flags); | ||
3912 | 3923 | ||
3913 | (empty || skip); | 3924 | (empty || skip); |
3914 | }), ATH10K_FLUSH_TIMEOUT_HZ); | 3925 | }), ATH10K_FLUSH_TIMEOUT_HZ); |
@@ -4009,6 +4020,7 @@ static void ath10k_reconfig_complete(struct ieee80211_hw *hw, | |||
4009 | if (ar->state == ATH10K_STATE_RESTARTED) { | 4020 | if (ar->state == ATH10K_STATE_RESTARTED) { |
4010 | ath10k_info(ar, "device successfully recovered\n"); | 4021 | ath10k_info(ar, "device successfully recovered\n"); |
4011 | ar->state = ATH10K_STATE_ON; | 4022 | ar->state = ATH10K_STATE_ON; |
4023 | ieee80211_wake_queues(ar->hw); | ||
4012 | } | 4024 | } |
4013 | 4025 | ||
4014 | mutex_unlock(&ar->conf_mutex); | 4026 | mutex_unlock(&ar->conf_mutex); |
@@ -4044,6 +4056,9 @@ static int ath10k_get_survey(struct ieee80211_hw *hw, int idx, | |||
4044 | 4056 | ||
4045 | survey->channel = &sband->channels[idx]; | 4057 | survey->channel = &sband->channels[idx]; |
4046 | 4058 | ||
4059 | if (ar->rx_channel == survey->channel) | ||
4060 | survey->filled |= SURVEY_INFO_IN_USE; | ||
4061 | |||
4047 | exit: | 4062 | exit: |
4048 | mutex_unlock(&ar->conf_mutex); | 4063 | mutex_unlock(&ar->conf_mutex); |
4049 | return ret; | 4064 | return ret; |
@@ -4917,6 +4932,8 @@ int ath10k_mac_register(struct ath10k *ar) | |||
4917 | ar->hw->wiphy->max_remain_on_channel_duration = 5000; | 4932 | ar->hw->wiphy->max_remain_on_channel_duration = 5000; |
4918 | 4933 | ||
4919 | ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; | 4934 | ar->hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD; |
4935 | ar->hw->wiphy->features |= NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE; | ||
4936 | |||
4920 | /* | 4937 | /* |
4921 | * on LL hardware queues are managed entirely by the FW | 4938 | * on LL hardware queues are managed entirely by the FW |
4922 | * so we only advertise to mac we can do the queues thing | 4939 | * so we only advertise to mac we can do the queues thing |
diff --git a/drivers/net/wireless/ath/ath10k/mac.h b/drivers/net/wireless/ath/ath10k/mac.h index 965c51117499..4e3c989aa841 100644 --- a/drivers/net/wireless/ath/ath10k/mac.h +++ b/drivers/net/wireless/ath/ath10k/mac.h | |||
@@ -40,6 +40,7 @@ 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 | void ath10k_mac_vif_beacon_free(struct ath10k_vif *arvif); |
43 | void ath10k_drain_tx(struct ath10k *ar); | ||
43 | 44 | ||
44 | static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) | 45 | static inline struct ath10k_vif *ath10k_vif_to_arvif(struct ieee80211_vif *vif) |
45 | { | 46 | { |
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 4a4740b4bdc0..3a6b8a5ca96c 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c | |||
@@ -1196,64 +1196,74 @@ static int ath10k_pci_hif_start(struct ath10k *ar) | |||
1196 | return 0; | 1196 | return 0; |
1197 | } | 1197 | } |
1198 | 1198 | ||
1199 | static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info) | 1199 | static void ath10k_pci_rx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) |
1200 | { | 1200 | { |
1201 | struct ath10k *ar; | 1201 | struct ath10k *ar; |
1202 | struct ath10k_pci *ar_pci; | 1202 | struct ath10k_ce_pipe *ce_pipe; |
1203 | struct ath10k_ce_pipe *ce_hdl; | 1203 | struct ath10k_ce_ring *ce_ring; |
1204 | u32 buf_sz; | 1204 | struct sk_buff *skb; |
1205 | struct sk_buff *netbuf; | 1205 | int i; |
1206 | u32 ce_data; | ||
1207 | 1206 | ||
1208 | buf_sz = pipe_info->buf_sz; | 1207 | ar = pci_pipe->hif_ce_state; |
1208 | ce_pipe = pci_pipe->ce_hdl; | ||
1209 | ce_ring = ce_pipe->dest_ring; | ||
1209 | 1210 | ||
1210 | /* Unused Copy Engine */ | 1211 | if (!ce_ring) |
1211 | if (buf_sz == 0) | ||
1212 | return; | 1212 | return; |
1213 | 1213 | ||
1214 | ar = pipe_info->hif_ce_state; | 1214 | if (!pci_pipe->buf_sz) |
1215 | ar_pci = ath10k_pci_priv(ar); | 1215 | return; |
1216 | ce_hdl = pipe_info->ce_hdl; | ||
1217 | 1216 | ||
1218 | while (ath10k_ce_revoke_recv_next(ce_hdl, (void **)&netbuf, | 1217 | for (i = 0; i < ce_ring->nentries; i++) { |
1219 | &ce_data) == 0) { | 1218 | skb = ce_ring->per_transfer_context[i]; |
1220 | dma_unmap_single(ar->dev, ATH10K_SKB_CB(netbuf)->paddr, | 1219 | if (!skb) |
1221 | netbuf->len + skb_tailroom(netbuf), | 1220 | continue; |
1221 | |||
1222 | ce_ring->per_transfer_context[i] = NULL; | ||
1223 | |||
1224 | dma_unmap_single(ar->dev, ATH10K_SKB_CB(skb)->paddr, | ||
1225 | skb->len + skb_tailroom(skb), | ||
1222 | DMA_FROM_DEVICE); | 1226 | DMA_FROM_DEVICE); |
1223 | dev_kfree_skb_any(netbuf); | 1227 | dev_kfree_skb_any(skb); |
1224 | } | 1228 | } |
1225 | } | 1229 | } |
1226 | 1230 | ||
1227 | static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pipe_info) | 1231 | static void ath10k_pci_tx_pipe_cleanup(struct ath10k_pci_pipe *pci_pipe) |
1228 | { | 1232 | { |
1229 | struct ath10k *ar; | 1233 | struct ath10k *ar; |
1230 | struct ath10k_pci *ar_pci; | 1234 | struct ath10k_pci *ar_pci; |
1231 | struct ath10k_ce_pipe *ce_hdl; | 1235 | struct ath10k_ce_pipe *ce_pipe; |
1232 | struct sk_buff *netbuf; | 1236 | struct ath10k_ce_ring *ce_ring; |
1233 | u32 ce_data; | 1237 | struct ce_desc *ce_desc; |
1234 | unsigned int nbytes; | 1238 | struct sk_buff *skb; |
1235 | unsigned int id; | 1239 | unsigned int id; |
1236 | u32 buf_sz; | 1240 | int i; |
1237 | 1241 | ||
1238 | buf_sz = pipe_info->buf_sz; | 1242 | ar = pci_pipe->hif_ce_state; |
1243 | ar_pci = ath10k_pci_priv(ar); | ||
1244 | ce_pipe = pci_pipe->ce_hdl; | ||
1245 | ce_ring = ce_pipe->src_ring; | ||
1239 | 1246 | ||
1240 | /* Unused Copy Engine */ | 1247 | if (!ce_ring) |
1241 | if (buf_sz == 0) | ||
1242 | return; | 1248 | return; |
1243 | 1249 | ||
1244 | ar = pipe_info->hif_ce_state; | 1250 | if (!pci_pipe->buf_sz) |
1245 | ar_pci = ath10k_pci_priv(ar); | 1251 | return; |
1246 | ce_hdl = pipe_info->ce_hdl; | ||
1247 | 1252 | ||
1248 | while (ath10k_ce_cancel_send_next(ce_hdl, (void **)&netbuf, | 1253 | ce_desc = ce_ring->shadow_base; |
1249 | &ce_data, &nbytes, &id) == 0) { | 1254 | if (WARN_ON(!ce_desc)) |
1250 | /* no need to call tx completion for NULL pointers */ | 1255 | return; |
1251 | if (!netbuf) | 1256 | |
1257 | for (i = 0; i < ce_ring->nentries; i++) { | ||
1258 | skb = ce_ring->per_transfer_context[i]; | ||
1259 | if (!skb) | ||
1252 | continue; | 1260 | continue; |
1253 | 1261 | ||
1254 | ar_pci->msg_callbacks_current.tx_completion(ar, | 1262 | ce_ring->per_transfer_context[i] = NULL; |
1255 | netbuf, | 1263 | id = MS(__le16_to_cpu(ce_desc[i].flags), |
1256 | id); | 1264 | CE_DESC_FLAGS_META_DATA); |
1265 | |||
1266 | ar_pci->msg_callbacks_current.tx_completion(ar, skb, id); | ||
1257 | } | 1267 | } |
1258 | } | 1268 | } |
1259 | 1269 | ||
@@ -1432,6 +1442,9 @@ static void ath10k_pci_bmi_recv_data(struct ath10k_ce_pipe *ce_state) | |||
1432 | &nbytes, &transfer_id, &flags)) | 1442 | &nbytes, &transfer_id, &flags)) |
1433 | return; | 1443 | return; |
1434 | 1444 | ||
1445 | if (WARN_ON_ONCE(!xfer)) | ||
1446 | return; | ||
1447 | |||
1435 | if (!xfer->wait_for_resp) { | 1448 | if (!xfer->wait_for_resp) { |
1436 | ath10k_warn(ar, "unexpected: BMI data received; ignoring\n"); | 1449 | ath10k_warn(ar, "unexpected: BMI data received; ignoring\n"); |
1437 | return; | 1450 | return; |
@@ -1707,99 +1720,167 @@ static void ath10k_pci_warm_reset_si0(struct ath10k *ar) | |||
1707 | msleep(10); | 1720 | msleep(10); |
1708 | } | 1721 | } |
1709 | 1722 | ||
1710 | static int ath10k_pci_warm_reset(struct ath10k *ar) | 1723 | static void ath10k_pci_warm_reset_cpu(struct ath10k *ar) |
1711 | { | 1724 | { |
1712 | u32 val; | 1725 | u32 val; |
1713 | 1726 | ||
1714 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n"); | 1727 | ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, 0); |
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 | |||
1722 | /* debug */ | ||
1723 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + | ||
1724 | PCIE_INTR_CAUSE_ADDRESS); | ||
1725 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n", | ||
1726 | val); | ||
1727 | 1728 | ||
1728 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + | 1729 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + |
1729 | CPU_INTR_ADDRESS); | 1730 | SOC_RESET_CONTROL_ADDRESS); |
1730 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n", | 1731 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, |
1731 | val); | 1732 | val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK); |
1733 | } | ||
1732 | 1734 | ||
1733 | /* disable pending irqs */ | 1735 | static void ath10k_pci_warm_reset_ce(struct ath10k *ar) |
1734 | ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + | 1736 | { |
1735 | PCIE_INTR_ENABLE_ADDRESS, 0); | 1737 | u32 val; |
1736 | 1738 | ||
1737 | ath10k_pci_write32(ar, SOC_CORE_BASE_ADDRESS + | 1739 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + |
1738 | PCIE_INTR_CLR_ADDRESS, ~0); | 1740 | SOC_RESET_CONTROL_ADDRESS); |
1739 | 1741 | ||
1740 | msleep(100); | 1742 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, |
1743 | val | SOC_RESET_CONTROL_CE_RST_MASK); | ||
1744 | msleep(10); | ||
1745 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, | ||
1746 | val & ~SOC_RESET_CONTROL_CE_RST_MASK); | ||
1747 | } | ||
1741 | 1748 | ||
1742 | /* clear fw indicator */ | 1749 | static void ath10k_pci_warm_reset_clear_lf(struct ath10k *ar) |
1743 | ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS, 0); | 1750 | { |
1751 | u32 val; | ||
1744 | 1752 | ||
1745 | /* clear target LF timer interrupts */ | ||
1746 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + | 1753 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + |
1747 | SOC_LF_TIMER_CONTROL0_ADDRESS); | 1754 | SOC_LF_TIMER_CONTROL0_ADDRESS); |
1748 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + | 1755 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + |
1749 | SOC_LF_TIMER_CONTROL0_ADDRESS, | 1756 | SOC_LF_TIMER_CONTROL0_ADDRESS, |
1750 | val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK); | 1757 | val & ~SOC_LF_TIMER_CONTROL0_ENABLE_MASK); |
1758 | } | ||
1751 | 1759 | ||
1752 | /* reset CE */ | 1760 | static int ath10k_pci_warm_reset(struct ath10k *ar) |
1753 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + | 1761 | { |
1754 | SOC_RESET_CONTROL_ADDRESS); | 1762 | int ret; |
1755 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, | ||
1756 | val | SOC_RESET_CONTROL_CE_RST_MASK); | ||
1757 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + | ||
1758 | SOC_RESET_CONTROL_ADDRESS); | ||
1759 | msleep(10); | ||
1760 | 1763 | ||
1761 | /* unreset CE */ | 1764 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset\n"); |
1762 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, | 1765 | |
1763 | val & ~SOC_RESET_CONTROL_CE_RST_MASK); | 1766 | spin_lock_bh(&ar->data_lock); |
1764 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + | 1767 | ar->stats.fw_warm_reset_counter++; |
1765 | SOC_RESET_CONTROL_ADDRESS); | 1768 | spin_unlock_bh(&ar->data_lock); |
1766 | msleep(10); | ||
1767 | 1769 | ||
1770 | ath10k_pci_irq_disable(ar); | ||
1771 | |||
1772 | /* Make sure the target CPU is not doing anything dangerous, e.g. if it | ||
1773 | * were to access copy engine while host performs copy engine reset | ||
1774 | * then it is possible for the device to confuse pci-e controller to | ||
1775 | * the point of bringing host system to a complete stop (i.e. hang). | ||
1776 | */ | ||
1768 | ath10k_pci_warm_reset_si0(ar); | 1777 | ath10k_pci_warm_reset_si0(ar); |
1778 | ath10k_pci_warm_reset_cpu(ar); | ||
1779 | ath10k_pci_init_pipes(ar); | ||
1780 | ath10k_pci_wait_for_target_init(ar); | ||
1769 | 1781 | ||
1770 | /* debug */ | 1782 | ath10k_pci_warm_reset_clear_lf(ar); |
1771 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + | 1783 | ath10k_pci_warm_reset_ce(ar); |
1772 | PCIE_INTR_CAUSE_ADDRESS); | 1784 | ath10k_pci_warm_reset_cpu(ar); |
1773 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot host cpu intr cause: 0x%08x\n", | 1785 | ath10k_pci_init_pipes(ar); |
1774 | val); | ||
1775 | 1786 | ||
1776 | val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS + | 1787 | ret = ath10k_pci_wait_for_target_init(ar); |
1777 | CPU_INTR_ADDRESS); | 1788 | if (ret) { |
1778 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target cpu intr cause: 0x%08x\n", | 1789 | ath10k_warn(ar, "failed to wait for target init: %d\n", ret); |
1779 | val); | 1790 | return ret; |
1791 | } | ||
1780 | 1792 | ||
1781 | /* CPU warm reset */ | 1793 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset complete\n"); |
1782 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + | ||
1783 | SOC_RESET_CONTROL_ADDRESS); | ||
1784 | ath10k_pci_write32(ar, RTC_SOC_BASE_ADDRESS + SOC_RESET_CONTROL_ADDRESS, | ||
1785 | val | SOC_RESET_CONTROL_CPU_WARM_RST_MASK); | ||
1786 | 1794 | ||
1787 | val = ath10k_pci_read32(ar, RTC_SOC_BASE_ADDRESS + | 1795 | return 0; |
1788 | SOC_RESET_CONTROL_ADDRESS); | 1796 | } |
1789 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot target reset state: 0x%08x\n", | ||
1790 | val); | ||
1791 | 1797 | ||
1792 | msleep(100); | 1798 | static int ath10k_pci_chip_reset(struct ath10k *ar) |
1799 | { | ||
1800 | int i, ret; | ||
1801 | u32 val; | ||
1793 | 1802 | ||
1794 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot warm reset complete\n"); | 1803 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset\n"); |
1804 | |||
1805 | /* Some hardware revisions (e.g. CUS223v2) has issues with cold reset. | ||
1806 | * It is thus preferred to use warm reset which is safer but may not be | ||
1807 | * able to recover the device from all possible fail scenarios. | ||
1808 | * | ||
1809 | * Warm reset doesn't always work on first try so attempt it a few | ||
1810 | * times before giving up. | ||
1811 | */ | ||
1812 | for (i = 0; i < ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS; i++) { | ||
1813 | ret = ath10k_pci_warm_reset(ar); | ||
1814 | if (ret) { | ||
1815 | ath10k_warn(ar, "failed to warm reset attempt %d of %d: %d\n", | ||
1816 | i + 1, ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS, | ||
1817 | ret); | ||
1818 | continue; | ||
1819 | } | ||
1820 | |||
1821 | /* FIXME: Sometimes copy engine doesn't recover after warm | ||
1822 | * reset. In most cases this needs cold reset. In some of these | ||
1823 | * cases the device is in such a state that a cold reset may | ||
1824 | * lock up the host. | ||
1825 | * | ||
1826 | * Reading any host interest register via copy engine is | ||
1827 | * sufficient to verify if device is capable of booting | ||
1828 | * firmware blob. | ||
1829 | */ | ||
1830 | ret = ath10k_pci_init_pipes(ar); | ||
1831 | if (ret) { | ||
1832 | ath10k_warn(ar, "failed to init copy engine: %d\n", | ||
1833 | ret); | ||
1834 | continue; | ||
1835 | } | ||
1836 | |||
1837 | ret = ath10k_pci_diag_read32(ar, QCA988X_HOST_INTEREST_ADDRESS, | ||
1838 | &val); | ||
1839 | if (ret) { | ||
1840 | ath10k_warn(ar, "failed to poke copy engine: %d\n", | ||
1841 | ret); | ||
1842 | continue; | ||
1843 | } | ||
1844 | |||
1845 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset complete (warm)\n"); | ||
1846 | return 0; | ||
1847 | } | ||
1848 | |||
1849 | if (ath10k_pci_reset_mode == ATH10K_PCI_RESET_WARM_ONLY) { | ||
1850 | ath10k_warn(ar, "refusing cold reset as requested\n"); | ||
1851 | return -EPERM; | ||
1852 | } | ||
1853 | |||
1854 | ret = ath10k_pci_cold_reset(ar); | ||
1855 | if (ret) { | ||
1856 | ath10k_warn(ar, "failed to cold reset: %d\n", ret); | ||
1857 | return ret; | ||
1858 | } | ||
1859 | |||
1860 | ret = ath10k_pci_wait_for_target_init(ar); | ||
1861 | if (ret) { | ||
1862 | ath10k_warn(ar, "failed to wait for target after cold reset: %d\n", | ||
1863 | ret); | ||
1864 | return ret; | ||
1865 | } | ||
1866 | |||
1867 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot chip reset complete (cold)\n"); | ||
1795 | 1868 | ||
1796 | return 0; | 1869 | return 0; |
1797 | } | 1870 | } |
1798 | 1871 | ||
1799 | static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset) | 1872 | static int ath10k_pci_hif_power_up(struct ath10k *ar) |
1800 | { | 1873 | { |
1801 | int ret; | 1874 | int ret; |
1802 | 1875 | ||
1876 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power up\n"); | ||
1877 | |||
1878 | ret = ath10k_pci_wake(ar); | ||
1879 | if (ret) { | ||
1880 | ath10k_err(ar, "failed to wake up target: %d\n", ret); | ||
1881 | return ret; | ||
1882 | } | ||
1883 | |||
1803 | /* | 1884 | /* |
1804 | * Bring the target up cleanly. | 1885 | * Bring the target up cleanly. |
1805 | * | 1886 | * |
@@ -1810,26 +1891,16 @@ static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset) | |||
1810 | * is in an unexpected state. We try to catch that here in order to | 1891 | * is in an unexpected state. We try to catch that here in order to |
1811 | * reset the Target and retry the probe. | 1892 | * reset the Target and retry the probe. |
1812 | */ | 1893 | */ |
1813 | if (cold_reset) | 1894 | ret = ath10k_pci_chip_reset(ar); |
1814 | ret = ath10k_pci_cold_reset(ar); | ||
1815 | else | ||
1816 | ret = ath10k_pci_warm_reset(ar); | ||
1817 | |||
1818 | if (ret) { | 1895 | if (ret) { |
1819 | ath10k_err(ar, "failed to reset target: %d\n", ret); | 1896 | ath10k_err(ar, "failed to reset chip: %d\n", ret); |
1820 | goto err; | 1897 | goto err_sleep; |
1821 | } | 1898 | } |
1822 | 1899 | ||
1823 | ret = ath10k_pci_init_pipes(ar); | 1900 | ret = ath10k_pci_init_pipes(ar); |
1824 | if (ret) { | 1901 | if (ret) { |
1825 | ath10k_err(ar, "failed to initialize CE: %d\n", ret); | 1902 | ath10k_err(ar, "failed to initialize CE: %d\n", ret); |
1826 | goto err; | 1903 | goto err_sleep; |
1827 | } | ||
1828 | |||
1829 | ret = ath10k_pci_wait_for_target_init(ar); | ||
1830 | if (ret) { | ||
1831 | ath10k_err(ar, "failed to wait for target to init: %d\n", ret); | ||
1832 | goto err_ce; | ||
1833 | } | 1904 | } |
1834 | 1905 | ||
1835 | ret = ath10k_pci_init_config(ar); | 1906 | ret = ath10k_pci_init_config(ar); |
@@ -1848,73 +1919,21 @@ static int __ath10k_pci_hif_power_up(struct ath10k *ar, bool cold_reset) | |||
1848 | 1919 | ||
1849 | err_ce: | 1920 | err_ce: |
1850 | ath10k_pci_ce_deinit(ar); | 1921 | ath10k_pci_ce_deinit(ar); |
1851 | ath10k_pci_warm_reset(ar); | ||
1852 | err: | ||
1853 | return ret; | ||
1854 | } | ||
1855 | |||
1856 | static int ath10k_pci_hif_power_up_warm(struct ath10k *ar) | ||
1857 | { | ||
1858 | int i, ret; | ||
1859 | |||
1860 | /* | ||
1861 | * Sometime warm reset succeeds after retries. | ||
1862 | * | ||
1863 | * FIXME: It might be possible to tune ath10k_pci_warm_reset() to work | ||
1864 | * at first try. | ||
1865 | */ | ||
1866 | for (i = 0; i < ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS; i++) { | ||
1867 | ret = __ath10k_pci_hif_power_up(ar, false); | ||
1868 | if (ret == 0) | ||
1869 | break; | ||
1870 | |||
1871 | ath10k_warn(ar, "failed to warm reset (attempt %d out of %d): %d\n", | ||
1872 | i + 1, ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS, ret); | ||
1873 | } | ||
1874 | 1922 | ||
1923 | err_sleep: | ||
1924 | ath10k_pci_sleep(ar); | ||
1875 | return ret; | 1925 | return ret; |
1876 | } | 1926 | } |
1877 | 1927 | ||
1878 | static int ath10k_pci_hif_power_up(struct ath10k *ar) | ||
1879 | { | ||
1880 | int ret; | ||
1881 | |||
1882 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power up\n"); | ||
1883 | |||
1884 | /* | ||
1885 | * Hardware CUS232 version 2 has some issues with cold reset and the | ||
1886 | * preferred (and safer) way to perform a device reset is through a | ||
1887 | * warm reset. | ||
1888 | * | ||
1889 | * Warm reset doesn't always work though so fall back to cold reset may | ||
1890 | * be necessary. | ||
1891 | */ | ||
1892 | ret = ath10k_pci_hif_power_up_warm(ar); | ||
1893 | if (ret) { | ||
1894 | ath10k_warn(ar, "failed to power up target using warm reset: %d\n", | ||
1895 | ret); | ||
1896 | |||
1897 | if (ath10k_pci_reset_mode == ATH10K_PCI_RESET_WARM_ONLY) | ||
1898 | return ret; | ||
1899 | |||
1900 | ath10k_warn(ar, "trying cold reset\n"); | ||
1901 | |||
1902 | ret = __ath10k_pci_hif_power_up(ar, true); | ||
1903 | if (ret) { | ||
1904 | ath10k_err(ar, "failed to power up target using cold reset too (%d)\n", | ||
1905 | ret); | ||
1906 | return ret; | ||
1907 | } | ||
1908 | } | ||
1909 | |||
1910 | return 0; | ||
1911 | } | ||
1912 | |||
1913 | static void ath10k_pci_hif_power_down(struct ath10k *ar) | 1928 | static void ath10k_pci_hif_power_down(struct ath10k *ar) |
1914 | { | 1929 | { |
1915 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power down\n"); | 1930 | ath10k_dbg(ar, ATH10K_DBG_BOOT, "boot hif power down\n"); |
1916 | 1931 | ||
1917 | ath10k_pci_warm_reset(ar); | 1932 | /* Currently hif_power_up performs effectively a reset and hif_stop |
1933 | * resets the chip as well so there's no point in resetting here. | ||
1934 | */ | ||
1935 | |||
1936 | ath10k_pci_sleep(ar); | ||
1918 | } | 1937 | } |
1919 | 1938 | ||
1920 | #ifdef CONFIG_PM | 1939 | #ifdef CONFIG_PM |
@@ -2516,6 +2535,8 @@ static int ath10k_pci_probe(struct pci_dev *pdev, | |||
2516 | goto err_deinit_irq; | 2535 | goto err_deinit_irq; |
2517 | } | 2536 | } |
2518 | 2537 | ||
2538 | ath10k_pci_sleep(ar); | ||
2539 | |||
2519 | ret = ath10k_core_register(ar, chip_id); | 2540 | ret = ath10k_core_register(ar, chip_id); |
2520 | if (ret) { | 2541 | if (ret) { |
2521 | ath10k_err(ar, "failed to register driver core: %d\n", ret); | 2542 | ath10k_err(ar, "failed to register driver core: %d\n", ret); |
@@ -2567,7 +2588,6 @@ static void ath10k_pci_remove(struct pci_dev *pdev) | |||
2567 | ath10k_pci_deinit_irq(ar); | 2588 | ath10k_pci_deinit_irq(ar); |
2568 | ath10k_pci_ce_deinit(ar); | 2589 | ath10k_pci_ce_deinit(ar); |
2569 | ath10k_pci_free_pipes(ar); | 2590 | ath10k_pci_free_pipes(ar); |
2570 | ath10k_pci_sleep(ar); | ||
2571 | ath10k_pci_release(ar); | 2591 | ath10k_pci_release(ar); |
2572 | ath10k_core_destroy(ar); | 2592 | ath10k_core_destroy(ar); |
2573 | } | 2593 | } |
diff --git a/drivers/net/wireless/ath/ath10k/trace.h b/drivers/net/wireless/ath/ath10k/trace.h index 9d34e7f6c455..ceea5668f3f6 100644 --- a/drivers/net/wireless/ath/ath10k/trace.h +++ b/drivers/net/wireless/ath/ath10k/trace.h | |||
@@ -20,6 +20,13 @@ | |||
20 | #include <linux/tracepoint.h> | 20 | #include <linux/tracepoint.h> |
21 | #include "core.h" | 21 | #include "core.h" |
22 | 22 | ||
23 | #if !defined(_TRACE_H_) | ||
24 | static inline u32 ath10k_frm_hdr_len(void *buf) | ||
25 | { | ||
26 | return ieee80211_hdrlen(((struct ieee80211_hdr *)buf)->frame_control); | ||
27 | } | ||
28 | #endif | ||
29 | |||
23 | #define _TRACE_H_ | 30 | #define _TRACE_H_ |
24 | 31 | ||
25 | /* create empty functions when tracing is disabled */ | 32 | /* create empty functions when tracing is disabled */ |
@@ -281,36 +288,6 @@ TRACE_EVENT(ath10k_htt_pktlog, | |||
281 | ) | 288 | ) |
282 | ); | 289 | ); |
283 | 290 | ||
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, | 291 | TRACE_EVENT(ath10k_htt_tx, |
315 | TP_PROTO(struct ath10k *ar, u16 msdu_id, u16 msdu_len, | 292 | TP_PROTO(struct ath10k *ar, u16 msdu_id, u16 msdu_len, |
316 | u8 vdev_id, u8 tid), | 293 | u8 vdev_id, u8 tid), |
@@ -371,7 +348,7 @@ TRACE_EVENT(ath10k_txrx_tx_unref, | |||
371 | ) | 348 | ) |
372 | ); | 349 | ); |
373 | 350 | ||
374 | DECLARE_EVENT_CLASS(ath10k_data_event, | 351 | DECLARE_EVENT_CLASS(ath10k_hdr_event, |
375 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | 352 | TP_PROTO(struct ath10k *ar, void *data, size_t len), |
376 | 353 | ||
377 | TP_ARGS(ar, data, len), | 354 | TP_ARGS(ar, data, len), |
@@ -380,14 +357,14 @@ DECLARE_EVENT_CLASS(ath10k_data_event, | |||
380 | __string(device, dev_name(ar->dev)) | 357 | __string(device, dev_name(ar->dev)) |
381 | __string(driver, dev_driver_string(ar->dev)) | 358 | __string(driver, dev_driver_string(ar->dev)) |
382 | __field(size_t, len) | 359 | __field(size_t, len) |
383 | __dynamic_array(u8, data, len) | 360 | __dynamic_array(u8, data, ath10k_frm_hdr_len(data)) |
384 | ), | 361 | ), |
385 | 362 | ||
386 | TP_fast_assign( | 363 | TP_fast_assign( |
387 | __assign_str(device, dev_name(ar->dev)); | 364 | __assign_str(device, dev_name(ar->dev)); |
388 | __assign_str(driver, dev_driver_string(ar->dev)); | 365 | __assign_str(driver, dev_driver_string(ar->dev)); |
389 | __entry->len = len; | 366 | __entry->len = ath10k_frm_hdr_len(data); |
390 | memcpy(__get_dynamic_array(data), data, len); | 367 | memcpy(__get_dynamic_array(data), data, __entry->len); |
391 | ), | 368 | ), |
392 | 369 | ||
393 | TP_printk( | 370 | TP_printk( |
@@ -398,25 +375,81 @@ DECLARE_EVENT_CLASS(ath10k_data_event, | |||
398 | ) | 375 | ) |
399 | ); | 376 | ); |
400 | 377 | ||
401 | DEFINE_EVENT(ath10k_data_event, ath10k_htt_tx_msdu, | 378 | DECLARE_EVENT_CLASS(ath10k_payload_event, |
379 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | ||
380 | |||
381 | TP_ARGS(ar, data, len), | ||
382 | |||
383 | TP_STRUCT__entry( | ||
384 | __string(device, dev_name(ar->dev)) | ||
385 | __string(driver, dev_driver_string(ar->dev)) | ||
386 | __field(size_t, len) | ||
387 | __dynamic_array(u8, payload, (len - ath10k_frm_hdr_len(data))) | ||
388 | ), | ||
389 | |||
390 | TP_fast_assign( | ||
391 | __assign_str(device, dev_name(ar->dev)); | ||
392 | __assign_str(driver, dev_driver_string(ar->dev)); | ||
393 | __entry->len = len - ath10k_frm_hdr_len(data); | ||
394 | memcpy(__get_dynamic_array(payload), | ||
395 | data + ath10k_frm_hdr_len(data), __entry->len); | ||
396 | ), | ||
397 | |||
398 | TP_printk( | ||
399 | "%s %s len %zu\n", | ||
400 | __get_str(driver), | ||
401 | __get_str(device), | ||
402 | __entry->len | ||
403 | ) | ||
404 | ); | ||
405 | |||
406 | DEFINE_EVENT(ath10k_hdr_event, ath10k_tx_hdr, | ||
402 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | 407 | TP_PROTO(struct ath10k *ar, void *data, size_t len), |
403 | TP_ARGS(ar, data, len) | 408 | TP_ARGS(ar, data, len) |
404 | ); | 409 | ); |
405 | 410 | ||
406 | DEFINE_EVENT(ath10k_data_event, ath10k_htt_rx_pop_msdu, | 411 | DEFINE_EVENT(ath10k_payload_event, ath10k_tx_payload, |
407 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | 412 | TP_PROTO(struct ath10k *ar, void *data, size_t len), |
408 | TP_ARGS(ar, data, len) | 413 | TP_ARGS(ar, data, len) |
409 | ); | 414 | ); |
410 | 415 | ||
411 | DEFINE_EVENT(ath10k_data_event, ath10k_wmi_mgmt_tx, | 416 | DEFINE_EVENT(ath10k_hdr_event, ath10k_rx_hdr, |
412 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | 417 | TP_PROTO(struct ath10k *ar, void *data, size_t len), |
413 | TP_ARGS(ar, data, len) | 418 | TP_ARGS(ar, data, len) |
414 | ); | 419 | ); |
415 | 420 | ||
416 | DEFINE_EVENT(ath10k_data_event, ath10k_wmi_bcn_tx, | 421 | DEFINE_EVENT(ath10k_payload_event, ath10k_rx_payload, |
417 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | 422 | TP_PROTO(struct ath10k *ar, void *data, size_t len), |
418 | TP_ARGS(ar, data, len) | 423 | TP_ARGS(ar, data, len) |
419 | ); | 424 | ); |
425 | |||
426 | TRACE_EVENT(ath10k_htt_rx_desc, | ||
427 | TP_PROTO(struct ath10k *ar, void *data, size_t len), | ||
428 | |||
429 | TP_ARGS(ar, data, len), | ||
430 | |||
431 | TP_STRUCT__entry( | ||
432 | __string(device, dev_name(ar->dev)) | ||
433 | __string(driver, dev_driver_string(ar->dev)) | ||
434 | __field(u16, len) | ||
435 | __dynamic_array(u8, rxdesc, len) | ||
436 | ), | ||
437 | |||
438 | TP_fast_assign( | ||
439 | __assign_str(device, dev_name(ar->dev)); | ||
440 | __assign_str(driver, dev_driver_string(ar->dev)); | ||
441 | __entry->len = len; | ||
442 | memcpy(__get_dynamic_array(rxdesc), data, len); | ||
443 | ), | ||
444 | |||
445 | TP_printk( | ||
446 | "%s %s rxdesc len %d", | ||
447 | __get_str(driver), | ||
448 | __get_str(device), | ||
449 | __entry->len | ||
450 | ) | ||
451 | ); | ||
452 | |||
420 | #endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/ | 453 | #endif /* _TRACE_H_ || TRACE_HEADER_MULTI_READ*/ |
421 | 454 | ||
422 | /* we don't want to use include/trace/events */ | 455 | /* we don't want to use include/trace/events */ |
diff --git a/drivers/net/wireless/ath/ath10k/txrx.c b/drivers/net/wireless/ath/ath10k/txrx.c index f9c90e37bc7c..7579de8e7a8c 100644 --- a/drivers/net/wireless/ath/ath10k/txrx.c +++ b/drivers/net/wireless/ath/ath10k/txrx.c | |||
@@ -146,7 +146,8 @@ static int ath10k_wait_for_peer_common(struct ath10k *ar, int vdev_id, | |||
146 | mapped = !!ath10k_peer_find(ar, vdev_id, addr); | 146 | mapped = !!ath10k_peer_find(ar, vdev_id, addr); |
147 | spin_unlock_bh(&ar->data_lock); | 147 | spin_unlock_bh(&ar->data_lock); |
148 | 148 | ||
149 | mapped == expect_mapped; | 149 | (mapped == expect_mapped || |
150 | test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)); | ||
150 | }), 3*HZ); | 151 | }), 3*HZ); |
151 | 152 | ||
152 | if (ret <= 0) | 153 | if (ret <= 0) |
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index ae746cece211..c2bc8282f6cb 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c | |||
@@ -779,6 +779,10 @@ int ath10k_wmi_cmd_send(struct ath10k *ar, struct sk_buff *skb, u32 cmd_id) | |||
779 | ath10k_wmi_tx_beacons_nowait(ar); | 779 | ath10k_wmi_tx_beacons_nowait(ar); |
780 | 780 | ||
781 | ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id); | 781 | ret = ath10k_wmi_cmd_send_nowait(ar, skb, cmd_id); |
782 | |||
783 | if (ret && test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) | ||
784 | ret = -ESHUTDOWN; | ||
785 | |||
782 | (ret != -EAGAIN); | 786 | (ret != -EAGAIN); |
783 | }), 3*HZ); | 787 | }), 3*HZ); |
784 | 788 | ||
@@ -834,7 +838,8 @@ int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb) | |||
834 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n", | 838 | ath10k_dbg(ar, ATH10K_DBG_WMI, "wmi mgmt tx skb %p len %d ftype %02x stype %02x\n", |
835 | wmi_skb, wmi_skb->len, fc & IEEE80211_FCTL_FTYPE, | 839 | wmi_skb, wmi_skb->len, fc & IEEE80211_FCTL_FTYPE, |
836 | fc & IEEE80211_FCTL_STYPE); | 840 | fc & IEEE80211_FCTL_STYPE); |
837 | trace_ath10k_wmi_mgmt_tx(ar, skb->data, skb->len); | 841 | trace_ath10k_tx_hdr(ar, skb->data, skb->len); |
842 | trace_ath10k_tx_payload(ar, skb->data, skb->len); | ||
838 | 843 | ||
839 | /* Send the management frame buffer to the target */ | 844 | /* Send the management frame buffer to the target */ |
840 | ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid); | 845 | ret = ath10k_wmi_cmd_send(ar, wmi_skb, ar->wmi.cmd->mgmt_tx_cmdid); |
@@ -1893,7 +1898,9 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb) | |||
1893 | arvif->beacon = bcn; | 1898 | arvif->beacon = bcn; |
1894 | arvif->beacon_sent = false; | 1899 | arvif->beacon_sent = false; |
1895 | 1900 | ||
1896 | trace_ath10k_wmi_bcn_tx(ar, bcn->data, bcn->len); | 1901 | trace_ath10k_tx_hdr(ar, bcn->data, bcn->len); |
1902 | trace_ath10k_tx_payload(ar, bcn->data, bcn->len); | ||
1903 | |||
1897 | ath10k_wmi_tx_beacon_nowait(arvif); | 1904 | ath10k_wmi_tx_beacon_nowait(arvif); |
1898 | skip: | 1905 | skip: |
1899 | spin_unlock_bh(&ar->data_lock); | 1906 | spin_unlock_bh(&ar->data_lock); |
@@ -4187,9 +4194,9 @@ int ath10k_wmi_peer_assoc(struct ath10k *ar, | |||
4187 | 4194 | ||
4188 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { | 4195 | if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) { |
4189 | if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features)) | 4196 | if (test_bit(ATH10K_FW_FEATURE_WMI_10_2, ar->fw_features)) |
4190 | ath10k_wmi_peer_assoc_fill_10_1(ar, skb->data, arg); | ||
4191 | else | ||
4192 | ath10k_wmi_peer_assoc_fill_10_2(ar, skb->data, arg); | 4197 | ath10k_wmi_peer_assoc_fill_10_2(ar, skb->data, arg); |
4198 | else | ||
4199 | ath10k_wmi_peer_assoc_fill_10_1(ar, skb->data, arg); | ||
4193 | } else { | 4200 | } else { |
4194 | ath10k_wmi_peer_assoc_fill_main(ar, skb->data, arg); | 4201 | ath10k_wmi_peer_assoc_fill_main(ar, skb->data, arg); |
4195 | } | 4202 | } |
@@ -4398,7 +4405,6 @@ int ath10k_wmi_attach(struct ath10k *ar) | |||
4398 | 4405 | ||
4399 | init_completion(&ar->wmi.service_ready); | 4406 | init_completion(&ar->wmi.service_ready); |
4400 | init_completion(&ar->wmi.unified_ready); | 4407 | init_completion(&ar->wmi.unified_ready); |
4401 | init_waitqueue_head(&ar->wmi.tx_credits_wq); | ||
4402 | 4408 | ||
4403 | return 0; | 4409 | return 0; |
4404 | } | 4410 | } |