diff options
Diffstat (limited to 'drivers/net/wireless/ath/ath10k')
-rw-r--r-- | drivers/net/wireless/ath/ath10k/ce.c | 79 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/ce.h | 15 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/core.c | 15 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/debug.c | 2 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/hw.h | 3 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/mac.c | 54 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/pci.c | 29 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/snoc.c | 36 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/snoc.h | 1 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi-tlv.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath10k/wmi.c | 4 |
11 files changed, 130 insertions, 112 deletions
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c index 01e05af5ae08..a03b7535c254 100644 --- a/drivers/net/wireless/ath/ath10k/ce.c +++ b/drivers/net/wireless/ath/ath10k/ce.c @@ -1299,29 +1299,24 @@ void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id) struct ath10k_hw_ce_host_wm_regs *wm_regs = ar->hw_ce_regs->wm_regs; u32 ctrl_addr = ce_state->ctrl_addr; - spin_lock_bh(&ce->ce_lock); - - /* Clear the copy-complete interrupts that will be handled here. */ + /* + * Clear before handling + * + * Misc CE interrupts are not being handled, but still need + * to be cleared. + * + * NOTE: When the last copy engine interrupt is cleared the + * hardware will go to sleep. Once this happens any access to + * the CE registers can cause a hardware fault. + */ ath10k_ce_engine_int_status_clear(ar, ctrl_addr, - wm_regs->cc_mask); - - spin_unlock_bh(&ce->ce_lock); + wm_regs->cc_mask | wm_regs->wm_mask); if (ce_state->recv_cb) ce_state->recv_cb(ce_state); if (ce_state->send_cb) ce_state->send_cb(ce_state); - - spin_lock_bh(&ce->ce_lock); - - /* - * Misc CE interrupts are not being handled, but still need - * to be cleared. - */ - ath10k_ce_engine_int_status_clear(ar, ctrl_addr, wm_regs->wm_mask); - - spin_unlock_bh(&ce->ce_lock); } EXPORT_SYMBOL(ath10k_ce_per_engine_service); @@ -1372,45 +1367,55 @@ static void ath10k_ce_per_engine_handler_adjust(struct ath10k_ce_pipe *ce_state) ath10k_ce_watermark_intr_disable(ar, ctrl_addr); } -int ath10k_ce_disable_interrupts(struct ath10k *ar) +void ath10k_ce_disable_interrupt(struct ath10k *ar, int ce_id) { struct ath10k_ce *ce = ath10k_ce_priv(ar); struct ath10k_ce_pipe *ce_state; u32 ctrl_addr; - int ce_id; - for (ce_id = 0; ce_id < CE_COUNT; ce_id++) { - ce_state = &ce->ce_states[ce_id]; - if (ce_state->attr_flags & CE_ATTR_POLL) - continue; + ce_state = &ce->ce_states[ce_id]; + if (ce_state->attr_flags & CE_ATTR_POLL) + return; - ctrl_addr = ath10k_ce_base_address(ar, ce_id); + ctrl_addr = ath10k_ce_base_address(ar, ce_id); - ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr); - ath10k_ce_error_intr_disable(ar, ctrl_addr); - ath10k_ce_watermark_intr_disable(ar, ctrl_addr); - } + ath10k_ce_copy_complete_intr_disable(ar, ctrl_addr); + ath10k_ce_error_intr_disable(ar, ctrl_addr); + ath10k_ce_watermark_intr_disable(ar, ctrl_addr); +} +EXPORT_SYMBOL(ath10k_ce_disable_interrupt); - return 0; +void ath10k_ce_disable_interrupts(struct ath10k *ar) +{ + int ce_id; + + for (ce_id = 0; ce_id < CE_COUNT; ce_id++) + ath10k_ce_disable_interrupt(ar, ce_id); } EXPORT_SYMBOL(ath10k_ce_disable_interrupts); -void ath10k_ce_enable_interrupts(struct ath10k *ar) +void ath10k_ce_enable_interrupt(struct ath10k *ar, int ce_id) { struct ath10k_ce *ce = ath10k_ce_priv(ar); - int ce_id; struct ath10k_ce_pipe *ce_state; + ce_state = &ce->ce_states[ce_id]; + if (ce_state->attr_flags & CE_ATTR_POLL) + return; + + ath10k_ce_per_engine_handler_adjust(ce_state); +} +EXPORT_SYMBOL(ath10k_ce_enable_interrupt); + +void ath10k_ce_enable_interrupts(struct ath10k *ar) +{ + int ce_id; + /* Enable interrupts for copy engine that * are not using polling mode. */ - for (ce_id = 0; ce_id < CE_COUNT; ce_id++) { - ce_state = &ce->ce_states[ce_id]; - if (ce_state->attr_flags & CE_ATTR_POLL) - continue; - - ath10k_ce_per_engine_handler_adjust(ce_state); - } + for (ce_id = 0; ce_id < CE_COUNT; ce_id++) + ath10k_ce_enable_interrupt(ar, ce_id); } EXPORT_SYMBOL(ath10k_ce_enable_interrupts); diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h index a7478c240f78..fe07521550b7 100644 --- a/drivers/net/wireless/ath/ath10k/ce.h +++ b/drivers/net/wireless/ath/ath10k/ce.h @@ -255,10 +255,13 @@ int ath10k_ce_cancel_send_next(struct ath10k_ce_pipe *ce_state, /*==================CE Interrupt Handlers====================*/ void ath10k_ce_per_engine_service_any(struct ath10k *ar); void ath10k_ce_per_engine_service(struct ath10k *ar, unsigned int ce_id); -int ath10k_ce_disable_interrupts(struct ath10k *ar); +void ath10k_ce_disable_interrupt(struct ath10k *ar, int ce_id); +void ath10k_ce_disable_interrupts(struct ath10k *ar); +void ath10k_ce_enable_interrupt(struct ath10k *ar, int ce_id); void ath10k_ce_enable_interrupts(struct ath10k *ar); void ath10k_ce_dump_registers(struct ath10k *ar, struct ath10k_fw_crash_data *crash_data); + void ath10k_ce_alloc_rri(struct ath10k *ar); void ath10k_ce_free_rri(struct ath10k *ar); @@ -369,18 +372,14 @@ static inline u32 ath10k_ce_base_address(struct ath10k *ar, unsigned int ce_id) (((x) & CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_MASK) >> \ CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_LSB) #define CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS 0x0000 -#define CE_INTERRUPT_SUMMARY (GENMASK(CE_COUNT_MAX - 1, 0)) static inline u32 ath10k_ce_interrupt_summary(struct ath10k *ar) { struct ath10k_ce *ce = ath10k_ce_priv(ar); - if (!ar->hw_params.per_ce_irq) - return CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET( - ce->bus_ops->read32((ar), CE_WRAPPER_BASE_ADDRESS + - CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS)); - else - return CE_INTERRUPT_SUMMARY; + return CE_WRAPPER_INTERRUPT_SUMMARY_HOST_MSI_GET( + ce->bus_ops->read32((ar), CE_WRAPPER_BASE_ADDRESS + + CE_WRAPPER_INTERRUPT_SUMMARY_ADDRESS)); } /* Host software's Copy Engine configuration. */ diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c index 383d4fa555a8..09e77be6e314 100644 --- a/drivers/net/wireless/ath/ath10k/core.c +++ b/drivers/net/wireless/ath/ath10k/core.c @@ -118,7 +118,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .num_wds_entries = 0x20, .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, - .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, .hw_filter_reset_required = true, @@ -154,7 +153,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .num_wds_entries = 0x20, .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, - .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, .hw_filter_reset_required = true, @@ -217,7 +215,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .num_wds_entries = 0x20, .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, - .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, .hw_filter_reset_required = true, @@ -252,7 +249,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .num_wds_entries = 0x20, .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, - .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, .hw_filter_reset_required = true, @@ -287,7 +283,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .num_wds_entries = 0x20, .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, - .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, .hw_filter_reset_required = true, @@ -325,7 +320,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .num_wds_entries = 0x20, .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, - .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, .hw_filter_reset_required = true, @@ -366,7 +360,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .num_wds_entries = 0x20, .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, - .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, .hw_filter_reset_required = true, @@ -414,7 +407,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .num_wds_entries = 0x20, .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, - .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, .hw_filter_reset_required = true, @@ -459,7 +451,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .num_wds_entries = 0x20, .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, - .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, .hw_filter_reset_required = true, @@ -494,7 +485,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .num_wds_entries = 0x20, .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, - .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, .hw_filter_reset_required = true, @@ -531,7 +521,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .num_wds_entries = 0x20, .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, - .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, .hw_filter_reset_required = true, @@ -573,7 +562,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .num_wds_entries = 0x20, .target_64bit = false, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL, - .per_ce_irq = false, .shadow_reg_support = false, .rri_on_ddr = false, .hw_filter_reset_required = true, @@ -601,7 +589,6 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = { .num_wds_entries = TARGET_HL_TLV_NUM_WDS_ENTRIES, .target_64bit = true, .rx_ring_fill_level = HTT_RX_RING_FILL_LEVEL_DUAL_MAC, - .per_ce_irq = true, .shadow_reg_support = true, .rri_on_ddr = true, .hw_filter_reset_required = false, @@ -2157,7 +2144,7 @@ static int ath10k_init_uart(struct ath10k *ar) static int ath10k_init_hw_params(struct ath10k *ar) { - const struct ath10k_hw_params *uninitialized_var(hw_params); + const struct ath10k_hw_params *hw_params; int i; for (i = 0; i < ARRAY_SIZE(ath10k_hw_params_list); i++) { diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c index 04c50a26a4f4..34db968c4bd0 100644 --- a/drivers/net/wireless/ath/ath10k/debug.c +++ b/drivers/net/wireless/ath/ath10k/debug.c @@ -1138,7 +1138,7 @@ void ath10k_debug_get_et_strings(struct ieee80211_hw *hw, u32 sset, u8 *data) { if (sset == ETH_SS_STATS) - memcpy(data, *ath10k_gstrings_stats, + memcpy(data, ath10k_gstrings_stats, sizeof(ath10k_gstrings_stats)); } diff --git a/drivers/net/wireless/ath/ath10k/hw.h b/drivers/net/wireless/ath/ath10k/hw.h index ae4c9edc445c..705ab83cdff4 100644 --- a/drivers/net/wireless/ath/ath10k/hw.h +++ b/drivers/net/wireless/ath/ath10k/hw.h @@ -590,9 +590,6 @@ struct ath10k_hw_params { /* Target rx ring fill level */ u32 rx_ring_fill_level; - /* target supporting per ce IRQ */ - bool per_ce_irq; - /* target supporting shadow register for ce write */ bool shadow_reg_support; diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c index 3026eb54a7f2..afa3cc92fc2a 100644 --- a/drivers/net/wireless/ath/ath10k/mac.c +++ b/drivers/net/wireless/ath/ath10k/mac.c @@ -856,11 +856,36 @@ static int ath10k_peer_delete(struct ath10k *ar, u32 vdev_id, const u8 *addr) return 0; } +static void ath10k_peer_map_cleanup(struct ath10k *ar, struct ath10k_peer *peer) +{ + int peer_id, i; + + lockdep_assert_held(&ar->conf_mutex); + + for_each_set_bit(peer_id, peer->peer_ids, + ATH10K_MAX_NUM_PEER_IDS) { + ar->peer_map[peer_id] = NULL; + } + + /* Double check that peer is properly un-referenced from + * the peer_map + */ + for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) { + if (ar->peer_map[i] == peer) { + ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n", + peer->addr, peer, i); + ar->peer_map[i] = NULL; + } + } + + list_del(&peer->list); + kfree(peer); + ar->num_peers--; +} + static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id) { struct ath10k_peer *peer, *tmp; - int peer_id; - int i; lockdep_assert_held(&ar->conf_mutex); @@ -872,25 +897,7 @@ static void ath10k_peer_cleanup(struct ath10k *ar, u32 vdev_id) ath10k_warn(ar, "removing stale peer %pM from vdev_id %d\n", peer->addr, vdev_id); - for_each_set_bit(peer_id, peer->peer_ids, - ATH10K_MAX_NUM_PEER_IDS) { - ar->peer_map[peer_id] = NULL; - } - - /* Double check that peer is properly un-referenced from - * the peer_map - */ - for (i = 0; i < ARRAY_SIZE(ar->peer_map); i++) { - if (ar->peer_map[i] == peer) { - ath10k_warn(ar, "removing stale peer_map entry for %pM (ptr %pK idx %d)\n", - peer->addr, peer, i); - ar->peer_map[i] = NULL; - } - } - - list_del(&peer->list); - kfree(peer); - ar->num_peers--; + ath10k_peer_map_cleanup(ar, peer); } spin_unlock_bh(&ar->data_lock); } @@ -6641,10 +6648,7 @@ static int ath10k_sta_state(struct ieee80211_hw *hw, /* Clean up the peer object as well since we * must have failed to do this above. */ - list_del(&peer->list); - ar->peer_map[i] = NULL; - kfree(peer); - ar->num_peers--; + ath10k_peer_map_cleanup(ar, peer); } } spin_unlock_bh(&ar->data_lock); diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 0f055e577749..464dd0246a97 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -1960,8 +1960,9 @@ static int ath10k_pci_hif_start(struct ath10k *ar) ath10k_pci_irq_enable(ar); ath10k_pci_rx_post(ar); - pcie_capability_write_word(ar_pci->pdev, PCI_EXP_LNKCTL, - ar_pci->link_ctl); + pcie_capability_clear_and_set_word(ar_pci->pdev, PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_ASPMC, + ar_pci->link_ctl & PCI_EXP_LNKCTL_ASPMC); return 0; } @@ -2818,8 +2819,8 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar, pcie_capability_read_word(ar_pci->pdev, PCI_EXP_LNKCTL, &ar_pci->link_ctl); - pcie_capability_write_word(ar_pci->pdev, PCI_EXP_LNKCTL, - ar_pci->link_ctl & ~PCI_EXP_LNKCTL_ASPMC); + pcie_capability_clear_word(ar_pci->pdev, PCI_EXP_LNKCTL, + PCI_EXP_LNKCTL_ASPMC); /* * Bring the target up cleanly. @@ -3769,18 +3770,22 @@ static struct pci_driver ath10k_pci_driver = { static int __init ath10k_pci_init(void) { - int ret; + int ret1, ret2; - ret = pci_register_driver(&ath10k_pci_driver); - if (ret) + ret1 = pci_register_driver(&ath10k_pci_driver); + if (ret1) printk(KERN_ERR "failed to register ath10k pci driver: %d\n", - ret); + ret1); - ret = ath10k_ahb_init(); - if (ret) - printk(KERN_ERR "ahb init failed: %d\n", ret); + ret2 = ath10k_ahb_init(); + if (ret2) + printk(KERN_ERR "ahb init failed: %d\n", ret2); - return ret; + if (ret1 && ret2) + return ret1; + + /* registered to at least one bus */ + return 0; } module_init(ath10k_pci_init); diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c index d4589b2ab3b6..e8700f0b23f7 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.c +++ b/drivers/net/wireless/ath/ath10k/snoc.c @@ -3,6 +3,7 @@ * Copyright (c) 2018 The Linux Foundation. All rights reserved. */ +#include <linux/bits.h> #include <linux/clk.h> #include <linux/kernel.h> #include <linux/module.h> @@ -821,12 +822,20 @@ static void ath10k_snoc_hif_get_default_pipe(struct ath10k *ar, static inline void ath10k_snoc_irq_disable(struct ath10k *ar) { - ath10k_ce_disable_interrupts(ar); + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + int id; + + for (id = 0; id < CE_COUNT_MAX; id++) + disable_irq(ar_snoc->ce_irqs[id].irq_line); } static inline void ath10k_snoc_irq_enable(struct ath10k *ar) { - ath10k_ce_enable_interrupts(ar); + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + int id; + + for (id = 0; id < CE_COUNT_MAX; id++) + enable_irq(ar_snoc->ce_irqs[id].irq_line); } static void ath10k_snoc_rx_pipe_cleanup(struct ath10k_snoc_pipe *snoc_pipe) @@ -919,6 +928,7 @@ static int ath10k_snoc_hif_start(struct ath10k *ar) { struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); + bitmap_clear(ar_snoc->pending_ce_irqs, 0, CE_COUNT_MAX); napi_enable(&ar->napi); ath10k_snoc_irq_enable(ar); ath10k_snoc_rx_post(ar); @@ -1042,6 +1052,8 @@ static int ath10k_snoc_hif_power_up(struct ath10k *ar, goto err_free_rri; } + ath10k_ce_enable_interrupts(ar); + return 0; err_free_rri: @@ -1156,7 +1168,9 @@ static irqreturn_t ath10k_snoc_per_engine_handler(int irq, void *arg) return IRQ_HANDLED; } - ath10k_snoc_irq_disable(ar); + ath10k_ce_disable_interrupt(ar, ce_id); + set_bit(ce_id, ar_snoc->pending_ce_irqs); + napi_schedule(&ar->napi); return IRQ_HANDLED; @@ -1165,20 +1179,25 @@ static irqreturn_t ath10k_snoc_per_engine_handler(int irq, void *arg) static int ath10k_snoc_napi_poll(struct napi_struct *ctx, int budget) { struct ath10k *ar = container_of(ctx, struct ath10k, napi); + struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); int done = 0; + int ce_id; if (test_bit(ATH10K_FLAG_CRASH_FLUSH, &ar->dev_flags)) { napi_complete(ctx); return done; } - ath10k_ce_per_engine_service_any(ar); + for (ce_id = 0; ce_id < CE_COUNT; ce_id++) + if (test_and_clear_bit(ce_id, ar_snoc->pending_ce_irqs)) { + ath10k_ce_per_engine_service(ar, ce_id); + ath10k_ce_enable_interrupt(ar, ce_id); + } + done = ath10k_htt_txrx_compl_task(ar, budget); - if (done < budget) { + if (done < budget) napi_complete(ctx); - ath10k_snoc_irq_enable(ar); - } return done; } @@ -1192,13 +1211,12 @@ static void ath10k_snoc_init_napi(struct ath10k *ar) static int ath10k_snoc_request_irq(struct ath10k *ar) { struct ath10k_snoc *ar_snoc = ath10k_snoc_priv(ar); - int irqflags = IRQF_TRIGGER_RISING; int ret, id; for (id = 0; id < CE_COUNT_MAX; id++) { ret = request_irq(ar_snoc->ce_irqs[id].irq_line, ath10k_snoc_per_engine_handler, - irqflags, ce_name[id], ar); + IRQF_NO_AUTOEN, ce_name[id], ar); if (ret) { ath10k_err(ar, "failed to register IRQ handler for CE %d: %d", diff --git a/drivers/net/wireless/ath/ath10k/snoc.h b/drivers/net/wireless/ath/ath10k/snoc.h index 9db823e46314..d61ca374fdf6 100644 --- a/drivers/net/wireless/ath/ath10k/snoc.h +++ b/drivers/net/wireless/ath/ath10k/snoc.h @@ -81,6 +81,7 @@ struct ath10k_snoc { struct ath10k_clk_info *clk; struct ath10k_qmi *qmi; unsigned long flags; + DECLARE_BITMAP(pending_ce_irqs, CE_COUNT_MAX); }; static inline struct ath10k_snoc *ath10k_snoc_priv(struct ath10k *ar) diff --git a/drivers/net/wireless/ath/ath10k/wmi-tlv.c b/drivers/net/wireless/ath/ath10k/wmi-tlv.c index 315d20f5c8eb..ee1c86bb5078 100644 --- a/drivers/net/wireless/ath/ath10k/wmi-tlv.c +++ b/drivers/net/wireless/ath/ath10k/wmi-tlv.c @@ -707,6 +707,10 @@ ath10k_wmi_tlv_op_pull_mgmt_tx_compl_ev(struct ath10k *ar, struct sk_buff *skb, } ev = tb[WMI_TLV_TAG_STRUCT_MGMT_TX_COMPL_EVENT]; + if (!ev) { + kfree(tb); + return -EPROTO; + } arg->desc_id = ev->desc_id; arg->status = ev->status; diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c index 796bd93c599b..4adbe3ab9c87 100644 --- a/drivers/net/wireless/ath/ath10k/wmi.c +++ b/drivers/net/wireless/ath/ath10k/wmi.c @@ -9462,7 +9462,5 @@ void ath10k_wmi_detach(struct ath10k *ar) } cancel_work_sync(&ar->svc_rdy_work); - - if (ar->svc_rdy_skb) - dev_kfree_skb(ar->svc_rdy_skb); + dev_kfree_skb(ar->svc_rdy_skb); } |