diff --git a/ath10k-5.10/core.c b/ath10k-5.10/core.c index 7711a27..5465474 100644 --- a/ath10k-5.10/core.c +++ b/ath10k-5.10/core.c @@ -3560,7 +3560,7 @@ int ath10k_core_start(struct ath10k *ar, enum ath10k_firmware_mode mode, */ ar->ct_all_pkts_htt = false; } - + if (test_bit(ATH10K_FW_FEATURE_SET_SPECIAL_CT, ar->running_fw->fw_file.fw_features)) { /* Apply user-supplied configuration changes. */ diff --git a/ath10k-5.10/htt_tx.c b/ath10k-5.10/htt_tx.c index d89eba3..8bcd151 100644 --- a/ath10k-5.10/htt_tx.c +++ b/ath10k-5.10/htt_tx.c @@ -1499,7 +1499,8 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, info->flags & IEEE80211_TX_CTL_TX_OFFCHAN, txmode); } - /* ath10k_warn(ar, "info: %p vif: %p arvif: %p txo-active: %d\n", info, vif, arvif, arvif && arvif->txo_active); */ + /*ath10k_warn(ar, "info: %p vif: %p arvif: %p txo-active: %d\n", + info, vif, arvif, arvif && arvif->txo_active); */ if (unlikely(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)) freq = ar->scan.roc_freq; @@ -1549,14 +1550,14 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, } num_retries = info->control.rates[0].count; - } else if ((msdu->len >= 100) && - (ieee80211_is_data_qos(fc) || ieee80211_is_data(fc)) && - (!(ieee80211_is_qos_nullfunc(fc) || ieee80211_is_nullfunc(fc)))) { + } else if ((msdu->len >= 400) && + (ieee80211_is_data_qos(fc) || ieee80211_is_data(fc)) && + (!(ieee80211_is_qos_nullfunc(fc) || ieee80211_is_nullfunc(fc)))) { /* Only do the overrides for data frames. */ - /*ath10k_warn(ar, "qos-data: %d data: %d qos-nullfunc: %d nullfunc: %d\n", - ieee80211_is_data_qos(fc), ieee80211_is_data(fc), - ieee80211_is_qos_nullfunc(fc), ieee80211_is_nullfunc(fc));*/ - /* In order to allow ARP to work, don't mess with frames < 100 bytes in length, assume + /* ath10k_warn(ar, "msdu->len: %d qos-data: %d data: %d qos-nullfunc: %d nullfunc: %d\n", + msdu->len, ieee80211_is_data_qos(fc), ieee80211_is_data(fc), + ieee80211_is_qos_nullfunc(fc), ieee80211_is_nullfunc(fc)); */ + /* In order to allow ARP, DHCP, other such frames, don't mess with frames < 400 bytes in length, assume * test frames are larger. */ diff --git a/ath10k-5.10/usb.c b/ath10k-5.10/usb.c index 05a620f..19b9c27 100644 --- a/ath10k-5.10/usb.c +++ b/ath10k-5.10/usb.c @@ -997,6 +997,8 @@ static int ath10k_usb_probe(struct usb_interface *interface, ar_usb = ath10k_usb_priv(ar); ret = ath10k_usb_create(ar, interface); + if (ret) + goto err; ar_usb->ar = ar; ar->dev_id = product_id; @@ -1009,7 +1011,7 @@ static int ath10k_usb_probe(struct usb_interface *interface, ret = ath10k_core_register(ar, &bus_params); if (ret) { ath10k_warn(ar, "failed to register driver core: %d\n", ret); - goto err; + goto err_usb_destroy; } /* TODO: remove this once USB support is fully implemented */ @@ -1017,6 +1019,9 @@ static int ath10k_usb_probe(struct usb_interface *interface, return 0; +err_usb_destroy: + ath10k_usb_destroy(ar); + err: ath10k_core_destroy(ar); diff --git a/ath10k-5.10/wmi-tlv.c b/ath10k-5.10/wmi-tlv.c index 2bccf43..31af69d 100644 --- a/ath10k-5.10/wmi-tlv.c +++ b/ath10k-5.10/wmi-tlv.c @@ -1401,13 +1401,15 @@ static int ath10k_wmi_tlv_svc_avail_parse(struct ath10k *ar, u16 tag, u16 len, switch (tag) { case WMI_TLV_TAG_STRUCT_SERVICE_AVAILABLE_EVENT: + arg->service_map_ext_valid = true; arg->service_map_ext_len = *(__le32 *)ptr; arg->service_map_ext = ptr + sizeof(__le32); return 0; default: break; } - return -EPROTO; + + return 0; } static int ath10k_wmi_tlv_op_pull_svc_avail(struct ath10k *ar, diff --git a/ath10k-5.10/wmi.c b/ath10k-5.10/wmi.c index 4bf3194..8dd982f 100644 --- a/ath10k-5.10/wmi.c +++ b/ath10k-5.10/wmi.c @@ -6198,8 +6198,13 @@ void ath10k_wmi_event_service_available(struct ath10k *ar, struct sk_buff *skb) ret); } - ath10k_wmi_map_svc_ext(ar, arg.service_map_ext, ar->wmi.svc_map, - __le32_to_cpu(arg.service_map_ext_len)); + /* + * Initialization of "arg.service_map_ext_valid" to ZERO is necessary + * for the below logic to work. + */ + if (arg.service_map_ext_valid) + ath10k_wmi_map_svc_ext(ar, arg.service_map_ext, ar->wmi.svc_map, + __le32_to_cpu(arg.service_map_ext_len)); } static int ath10k_wmi_event_temperature(struct ath10k *ar, struct sk_buff *skb) diff --git a/ath10k-5.10/wmi.h b/ath10k-5.10/wmi.h index 99b615b..d9af683 100644 --- a/ath10k-5.10/wmi.h +++ b/ath10k-5.10/wmi.h @@ -7365,6 +7365,7 @@ struct wmi_svc_rdy_ev_arg { }; struct wmi_svc_avail_ev_arg { + bool service_map_ext_valid; __le32 service_map_ext_len; const __le32 *service_map_ext; }; diff --git a/ath10k-5.4/ce.c b/ath10k-5.4/ce.c index eca87f7..01e05af 100644 --- a/ath10k-5.4/ce.c +++ b/ath10k-5.4/ce.c @@ -1555,7 +1555,7 @@ ath10k_ce_alloc_src_ring(struct ath10k *ar, unsigned int ce_id, ret = ath10k_ce_alloc_shadow_base(ar, src_ring, nentries); if (ret) { dma_free_coherent(ar->dev, - (nentries * sizeof(struct ce_desc_64) + + (nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN), src_ring->base_addr_owner_space_unaligned, base_addr); diff --git a/ath10k-5.4/debug.c b/ath10k-5.4/debug.c index ab8cbec..344d38d 100644 --- a/ath10k-5.4/debug.c +++ b/ath10k-5.4/debug.c @@ -2963,7 +2963,7 @@ static void ath10k_tpc_stats_print(struct ath10k_tpc_stats *tpc_stats, *len += scnprintf(buf + *len, buf_len - *len, "No. Preamble Rate_code "); - for (i = 0; i < WMI_TPC_TX_N_CHAIN; i++) + for (i = 0; i < tpc_stats->num_tx_chain; i++) *len += scnprintf(buf + *len, buf_len - *len, "tpc_value%d ", i); @@ -4339,6 +4339,7 @@ void ath10k_debug_destroy(struct ath10k *ar) ath10k_debug_fw_stats_reset(ar); kfree(ar->debug.tpc_stats); + kfree(ar->debug.tpc_stats_final); cancel_delayed_work_sync(&ar->debug.nop_dwork); } diff --git a/ath10k-5.4/htt_rx.c b/ath10k-5.4/htt_rx.c index 9d85e9c..23fa8e1 100644 --- a/ath10k-5.4/htt_rx.c +++ b/ath10k-5.4/htt_rx.c @@ -142,6 +142,14 @@ static int __ath10k_htt_rx_ring_fill_n(struct ath10k_htt *htt, int num) BUILD_BUG_ON(HTT_RX_RING_FILL_LEVEL >= HTT_RX_RING_SIZE / 2); idx = __le32_to_cpu(*htt->rx_ring.alloc_idx.vaddr); + + if (idx < 0 || idx >= htt->rx_ring.size) { + ath10k_err(htt->ar, "rx ring index is not valid, firmware malfunctioning?\n"); + idx &= htt->rx_ring.size_mask; + ret = -ENOMEM; + goto fail; + } + while (num > 0) { skb = dev_alloc_skb(HTT_RX_BUF_SIZE + HTT_RX_DESC_ALIGN); if (!skb) { @@ -949,6 +957,7 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, u8 preamble = 0; u8 group_id; u32 info1, info2, info3; + u32 stbc, nsts_su; info1 = __le32_to_cpu(rxd->ppdu_start.info1); info2 = __le32_to_cpu(rxd->ppdu_start.info2); @@ -993,11 +1002,16 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar, */ bw = info2 & 3; sgi = info3 & 1; + stbc = (info2 >> 3) & 1; group_id = (info2 >> 4) & 0x3F; if (GROUP_ID_IS_SU_MIMO(group_id)) { mcs = (info3 >> 4) & 0x0F; - nss = ((info2 >> 10) & 0x07) + 1; + nsts_su = ((info2 >> 10) & 0x07); + if (stbc) + nss = (nsts_su >> 2) + 1; + else + nss = (nsts_su + 1); } else { /* Hardware doesn't decode VHT-SIG-B into Rx descriptor * so it's impossible to decode MCS. Also since diff --git a/ath10k-5.4/htt_tx.c b/ath10k-5.4/htt_tx.c index 8cfdfb2..2f83260 100644 --- a/ath10k-5.4/htt_tx.c +++ b/ath10k-5.4/htt_tx.c @@ -1445,7 +1445,8 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, info->flags & IEEE80211_TX_CTL_TX_OFFCHAN, txmode); } - /* ath10k_warn(ar, "info: %p vif: %p arvif: %p txo-active: %d\n", info, vif, arvif, arvif && arvif->txo_active); */ + /*ath10k_warn(ar, "info: %p vif: %p arvif: %p txo-active: %d\n", + info, vif, arvif, arvif && arvif->txo_active); */ if (unlikely(info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)) freq = ar->scan.roc_freq; @@ -1495,14 +1496,14 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, } num_retries = info->control.rates[0].count; - } else if ((msdu->len >= 100) && - (ieee80211_is_data_qos(fc) || ieee80211_is_data(fc)) && - (!(ieee80211_is_qos_nullfunc(fc) || ieee80211_is_nullfunc(fc)))) { + } else if ((msdu->len >= 400) && + (ieee80211_is_data_qos(fc) || ieee80211_is_data(fc)) && + (!(ieee80211_is_qos_nullfunc(fc) || ieee80211_is_nullfunc(fc)))) { /* Only do the overrides for data frames. */ - /*ath10k_warn(ar, "qos-data: %d data: %d qos-nullfunc: %d nullfunc: %d\n", - ieee80211_is_data_qos(fc), ieee80211_is_data(fc), - ieee80211_is_qos_nullfunc(fc), ieee80211_is_nullfunc(fc));*/ - /* In order to allow ARP to work, don't mess with frames < 100 bytes in length, assume + /* ath10k_warn(ar, "msdu->len: %d qos-data: %d data: %d qos-nullfunc: %d nullfunc: %d\n", + msdu->len, ieee80211_is_data_qos(fc), ieee80211_is_data(fc), + ieee80211_is_qos_nullfunc(fc), ieee80211_is_nullfunc(fc)); */ + /* In order to allow ARP, DHCP, other such frames, don't mess with frames < 400 bytes in length, assume * test frames are larger. */ @@ -1757,7 +1758,9 @@ static int ath10k_htt_tx_32(struct ath10k_htt *htt, err_unmap_msdu: dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); err_free_msdu_id: + spin_lock_bh(&htt->tx_lock); ath10k_htt_tx_free_msdu_id(htt, msdu_id); + spin_unlock_bh(&htt->tx_lock); err: return res; } @@ -1977,7 +1980,9 @@ static int ath10k_htt_tx_64(struct ath10k_htt *htt, err_unmap_msdu: dma_unmap_single(dev, skb_cb->paddr, msdu->len, DMA_TO_DEVICE); err_free_msdu_id: + spin_lock_bh(&htt->tx_lock); ath10k_htt_tx_free_msdu_id(htt, msdu_id); + spin_unlock_bh(&htt->tx_lock); err: return res; } diff --git a/ath10k-5.4/mac.c b/ath10k-5.4/mac.c index cabb033..b518a3e 100644 --- a/ath10k-5.4/mac.c +++ b/ath10k-5.4/mac.c @@ -8226,7 +8226,7 @@ ath10k_mac_update_bss_chan_survey(struct ath10k *ar, struct ieee80211_channel *channel) { int ret; - enum wmi_bss_survey_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ_CLEAR; + enum wmi_bss_survey_req_type type = WMI_BSS_SURVEY_REQ_TYPE_READ; lockdep_assert_held(&ar->conf_mutex); diff --git a/ath10k-5.4/sdio.c b/ath10k-5.4/sdio.c index 9870d2d..24b1927 100644 --- a/ath10k-5.4/sdio.c +++ b/ath10k-5.4/sdio.c @@ -550,6 +550,10 @@ static int ath10k_sdio_mbox_rx_alloc(struct ath10k *ar, le16_to_cpu(htc_hdr->len), ATH10K_HTC_MBOX_MAX_PAYLOAD_LENGTH); ret = -ENOMEM; + + queue_work(ar->workqueue, &ar->restart_work); + ath10k_warn(ar, "exceeds length, start recovery\n"); + goto err; } @@ -1582,23 +1586,33 @@ static int ath10k_sdio_hif_diag_read(struct ath10k *ar, u32 address, void *buf, size_t buf_len) { int ret; + void *mem; + + mem = kzalloc(buf_len, GFP_KERNEL); + if (!mem) + return -ENOMEM; /* set window register to start read cycle */ ret = ath10k_sdio_write32(ar, MBOX_WINDOW_READ_ADDR_ADDRESS, address); if (ret) { ath10k_warn(ar, "failed to set mbox window read address: %d", ret); - return ret; + goto out; } /* read the data */ - ret = ath10k_sdio_read(ar, MBOX_WINDOW_DATA_ADDRESS, buf, buf_len); + ret = ath10k_sdio_read(ar, MBOX_WINDOW_DATA_ADDRESS, mem, buf_len); if (ret) { ath10k_warn(ar, "failed to read from mbox window data address: %d\n", ret); - return ret; + goto out; } - return 0; + memcpy(buf, mem, buf_len); + +out: + kfree(mem); + + return ret; } static int ath10k_sdio_hif_diag_read32(struct ath10k *ar, u32 address, diff --git a/ath10k-5.4/usb.c b/ath10k-5.4/usb.c index 1e03430..05c0d5e 100644 --- a/ath10k-5.4/usb.c +++ b/ath10k-5.4/usb.c @@ -1009,6 +1009,8 @@ static int ath10k_usb_probe(struct usb_interface *interface, ar_usb = ath10k_usb_priv(ar); ret = ath10k_usb_create(ar, interface); + if (ret) + goto err; ar_usb->ar = ar; ar->dev_id = product_id; @@ -1021,7 +1023,7 @@ static int ath10k_usb_probe(struct usb_interface *interface, ret = ath10k_core_register(ar, &bus_params); if (ret) { ath10k_warn(ar, "failed to register driver core: %d\n", ret); - goto err; + goto err_usb_destroy; } /* TODO: remove this once USB support is fully implemented */ @@ -1029,6 +1031,9 @@ static int ath10k_usb_probe(struct usb_interface *interface, return 0; +err_usb_destroy: + ath10k_usb_destroy(ar); + err: ath10k_core_destroy(ar); diff --git a/ath10k-5.4/wmi-tlv.c b/ath10k-5.4/wmi-tlv.c index 70b35d4..53469e5 100644 --- a/ath10k-5.4/wmi-tlv.c +++ b/ath10k-5.4/wmi-tlv.c @@ -1260,13 +1260,15 @@ static int ath10k_wmi_tlv_svc_avail_parse(struct ath10k *ar, u16 tag, u16 len, switch (tag) { case WMI_TLV_TAG_STRUCT_SERVICE_AVAILABLE_EVENT: + arg->service_map_ext_valid = true; arg->service_map_ext_len = *(__le32 *)ptr; arg->service_map_ext = ptr + sizeof(__le32); return 0; default: break; } - return -EPROTO; + + return 0; } static int ath10k_wmi_tlv_op_pull_svc_avail(struct ath10k *ar, diff --git a/ath10k-5.4/wmi.c b/ath10k-5.4/wmi.c index 94aa5dc..9bc49dc 100644 --- a/ath10k-5.4/wmi.c +++ b/ath10k-5.4/wmi.c @@ -5074,16 +5074,13 @@ static void ath10k_tpc_config_disp_tables(struct ath10k *ar, } pream_idx = 0; - for (i = 0; i < __le32_to_cpu(ev->rate_max); i++) { + for (i = 0; i < tpc_stats->rate_max; i++) { memset(tpc_value, 0, sizeof(tpc_value)); memset(buff, 0, sizeof(buff)); if (i == pream_table[pream_idx]) pream_idx++; - for (j = 0; j < WMI_TPC_TX_N_CHAIN; j++) { - if (j >= __le32_to_cpu(ev->num_tx_chain)) - break; - + for (j = 0; j < tpc_stats->num_tx_chain; j++) { tpc[j] = ath10k_tpc_config_get_rate(ar, ev, i, j + 1, rate_code[i], type); @@ -5196,7 +5193,7 @@ void ath10k_wmi_tpc_config_get_rate_code(u8 *rate_code, u16 *pream_table, void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb) { - u32 num_tx_chain; + u32 num_tx_chain, rate_max; u8 rate_code[WMI_TPC_RATE_MAX]; u16 pream_table[WMI_TPC_PREAM_TABLE_MAX]; struct wmi_pdev_tpc_config_event *ev; @@ -5212,6 +5209,13 @@ void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb) return; } + rate_max = __le32_to_cpu(ev->rate_max); + if (rate_max > WMI_TPC_RATE_MAX) { + ath10k_warn(ar, "number of rate is %d greater than TPC configured rate %d\n", + rate_max, WMI_TPC_RATE_MAX); + rate_max = WMI_TPC_RATE_MAX; + } + tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC); if (!tpc_stats) return; @@ -5228,8 +5232,8 @@ void ath10k_wmi_event_pdev_tpc_config(struct ath10k *ar, struct sk_buff *skb) __le32_to_cpu(ev->twice_antenna_reduction); tpc_stats->power_limit = __le32_to_cpu(ev->power_limit); tpc_stats->twice_max_rd_power = __le32_to_cpu(ev->twice_max_rd_power); - tpc_stats->num_tx_chain = __le32_to_cpu(ev->num_tx_chain); - tpc_stats->rate_max = __le32_to_cpu(ev->rate_max); + tpc_stats->num_tx_chain = num_tx_chain; + tpc_stats->rate_max = rate_max; ath10k_tpc_config_disp_tables(ar, ev, tpc_stats, rate_code, pream_table, @@ -5424,16 +5428,13 @@ ath10k_wmi_tpc_stats_final_disp_tables(struct ath10k *ar, } pream_idx = 0; - for (i = 0; i < __le32_to_cpu(ev->rate_max); i++) { + for (i = 0; i < tpc_stats->rate_max; i++) { memset(tpc_value, 0, sizeof(tpc_value)); memset(buff, 0, sizeof(buff)); if (i == pream_table[pream_idx]) pream_idx++; - for (j = 0; j < WMI_TPC_TX_N_CHAIN; j++) { - if (j >= __le32_to_cpu(ev->num_tx_chain)) - break; - + for (j = 0; j < tpc_stats->num_tx_chain; j++) { tpc[j] = ath10k_wmi_tpc_final_get_rate(ar, ev, i, j + 1, rate_code[i], type, pream_idx); @@ -5449,7 +5450,7 @@ ath10k_wmi_tpc_stats_final_disp_tables(struct ath10k *ar, void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb) { - u32 num_tx_chain; + u32 num_tx_chain, rate_max; u8 rate_code[WMI_TPC_FINAL_RATE_MAX]; u16 pream_table[WMI_TPC_PREAM_TABLE_MAX]; struct wmi_pdev_tpc_final_table_event *ev; @@ -5457,12 +5458,24 @@ void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb) ev = (struct wmi_pdev_tpc_final_table_event *)skb->data; + num_tx_chain = __le32_to_cpu(ev->num_tx_chain); + if (num_tx_chain > WMI_TPC_TX_N_CHAIN) { + ath10k_warn(ar, "number of tx chain is %d greater than TPC final configured tx chain %d\n", + num_tx_chain, WMI_TPC_TX_N_CHAIN); + return; + } + + rate_max = __le32_to_cpu(ev->rate_max); + if (rate_max > WMI_TPC_FINAL_RATE_MAX) { + ath10k_warn(ar, "number of rate is %d greater than TPC final configured rate %d\n", + rate_max, WMI_TPC_FINAL_RATE_MAX); + rate_max = WMI_TPC_FINAL_RATE_MAX; + } + tpc_stats = kzalloc(sizeof(*tpc_stats), GFP_ATOMIC); if (!tpc_stats) return; - num_tx_chain = __le32_to_cpu(ev->num_tx_chain); - ath10k_wmi_tpc_config_get_rate_code(rate_code, pream_table, num_tx_chain); @@ -5475,8 +5488,8 @@ void ath10k_wmi_event_tpc_final_table(struct ath10k *ar, struct sk_buff *skb) __le32_to_cpu(ev->twice_antenna_reduction); tpc_stats->power_limit = __le32_to_cpu(ev->power_limit); tpc_stats->twice_max_rd_power = __le32_to_cpu(ev->twice_max_rd_power); - tpc_stats->num_tx_chain = __le32_to_cpu(ev->num_tx_chain); - tpc_stats->rate_max = __le32_to_cpu(ev->rate_max); + tpc_stats->num_tx_chain = num_tx_chain; + tpc_stats->rate_max = rate_max; ath10k_wmi_tpc_stats_final_disp_tables(ar, ev, tpc_stats, rate_code, pream_table, @@ -6098,8 +6111,13 @@ void ath10k_wmi_event_service_available(struct ath10k *ar, struct sk_buff *skb) ret); } - ath10k_wmi_map_svc_ext(ar, arg.service_map_ext, ar->wmi.svc_map, - __le32_to_cpu(arg.service_map_ext_len)); + /* + * Initialization of "arg.service_map_ext_valid" to ZERO is necessary + * for the below logic to work. + */ + if (arg.service_map_ext_valid) + ath10k_wmi_map_svc_ext(ar, arg.service_map_ext, ar->wmi.svc_map, + __le32_to_cpu(arg.service_map_ext_len)); } static int ath10k_wmi_event_temperature(struct ath10k *ar, struct sk_buff *skb) diff --git a/ath10k-5.4/wmi.h b/ath10k-5.4/wmi.h index 041dffa..9bef5a9 100644 --- a/ath10k-5.4/wmi.h +++ b/ath10k-5.4/wmi.h @@ -7304,6 +7304,7 @@ struct wmi_svc_rdy_ev_arg { }; struct wmi_svc_avail_ev_arg { + bool service_map_ext_valid; __le32 service_map_ext_len; const __le32 *service_map_ext; };