diff options
| author | Johannes Berg <johannes.berg@intel.com> | 2026-10-13 14:03:34 +0200 |
|---|---|---|
| committer | Johannes Berg <johannes.berg@intel.com> | 2026-10-13 14:03:49 +0200 |
| commit | cd026e68fdbf88b9cc522b76c7a9d92c9a41f709 (patch) | |
| tree | 7eb9db63064208af1adb960edc48167340e16bbe | |
| parent | fbcdcc450c47b2dbc0e3c790a40071e7485bb68c (diff) | |
| parent | 4aa45334eb23d40bf31c43405daea9b73469f2a6 (diff) | |
Merge tag 'ath-next-20261012' of git://git.kernel.org/pub/scm/linux/kernel/git/ath/ath
Jeff Johnson says:
==================
ath.git patches for v7.4 (PR #3)
Nothing special here, just a bunch of assorted cleanups and bug fixes
spread across the ath family of Wi-Fi drivers.
==================
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/htt_tx.c | 12 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath10k/qmi.c | 1 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath11k/core.c | 21 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath11k/mac.c | 33 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath11k/mac.h | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/ahb.c | 41 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/core.c | 37 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/dp.h | 8 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/dp_rx.c | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/hw.h | 1 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/mac.c | 87 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/mac.h | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/wifi7/hal_desc.h | 26 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/wifi7/hw.c | 6 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath12k/wmi.c | 17 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath6kl/cfg80211.c | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/channel.c | 2 | ||||
| -rw-r--r-- | drivers/net/wireless/ath/ath9k/common-spectral.c | 9 |
19 files changed, 217 insertions, 94 deletions
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c index e46f579d745d..efaea150025b 100644 --- a/drivers/net/wireless/ath/ath10k/htt_tx.c +++ b/drivers/net/wireless/ath/ath10k/htt_tx.c @@ -505,9 +505,8 @@ free_idr_pending_tx: return ret; } -static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx) +static void ath10k_htt_tx_clean_up_pending(int msdu_id, struct ath10k *ar) { - struct ath10k *ar = ctx; struct ath10k_htt *htt = &ar->htt; struct htt_tx_done tx_done = {}; @@ -517,8 +516,6 @@ static int ath10k_htt_tx_clean_up_pending(int msdu_id, void *skb, void *ctx) tx_done.status = HTT_TX_COMPL_STATE_DISCARD; ath10k_txrx_tx_unref(htt, &tx_done); - - return 0; } void ath10k_htt_tx_destroy(struct ath10k_htt *htt) @@ -535,8 +532,13 @@ void ath10k_htt_tx_destroy(struct ath10k_htt *htt) static void ath10k_htt_flush_tx_queue(struct ath10k_htt *htt) { + struct sk_buff *msdu; + int msdu_id; + ath10k_htc_stop_hl(htt->ar); - idr_for_each(&htt->pending_tx, ath10k_htt_tx_clean_up_pending, htt->ar); + + idr_for_each_entry(&htt->pending_tx, msdu, msdu_id) + ath10k_htt_tx_clean_up_pending(msdu_id, htt->ar); } void ath10k_htt_tx_stop(struct ath10k_htt *htt) diff --git a/drivers/net/wireless/ath/ath10k/qmi.c b/drivers/net/wireless/ath/ath10k/qmi.c index 0d74548a5f34..08a64f737fb4 100644 --- a/drivers/net/wireless/ath/ath10k/qmi.c +++ b/drivers/net/wireless/ath/ath10k/qmi.c @@ -1128,6 +1128,7 @@ err_release_qmi_handle: err: kfree(qmi); + ar_snoc->qmi = NULL; return ret; } diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c index d2ed6a0ea7e3..766ae27306f4 100644 --- a/drivers/net/wireless/ath/ath11k/core.c +++ b/drivers/net/wireless/ath/ath11k/core.c @@ -1275,9 +1275,6 @@ int ath11k_core_suspend_late(struct ath11k_base *ab) if (ab->actual_pm_policy == ATH11K_PM_WOW) return 0; - ath11k_hif_irq_disable(ab); - ath11k_hif_ce_irq_disable(ab); - ath11k_hif_power_down(ab, true); return 0; @@ -2333,17 +2330,9 @@ static int ath11k_core_reconfigure_on_crash(struct ath11k_base *ab) int ret; mutex_lock(&ab->core_lock); + ath11k_hif_irq_disable(ab); + ath11k_hif_ce_irq_disable(ab); ath11k_thermal_unregister(ab); - - /* - * ath11k_core_reset() already disabled the interrupts on the reset - * path; only the firmware crash path reaches here with them live. - */ - if (!ab->is_reset) { - ath11k_hif_irq_disable(ab); - ath11k_hif_ce_irq_disable(ab); - } - ath11k_dp_pdev_free(ab); ath11k_cfr_deinit(ab); ath11k_spectral_deinit(ab); @@ -2459,8 +2448,7 @@ void ath11k_core_pre_reconfigure_recovery(struct ath11k_base *ab) complete(&ar->thermal.wmi_sync); wake_up(&ar->dp.tx_empty_waitq); - idr_for_each(&ar->txmgmt_idr, - ath11k_mac_tx_mgmt_pending_free, ar); + ath11k_mac_tx_mgmt_pending_free(ar); idr_destroy(&ar->txmgmt_idr); wake_up(&ar->txmgmt_empty_waitq); @@ -2605,9 +2593,6 @@ static void ath11k_core_reset(struct work_struct *work) time_left = wait_for_completion_timeout(&ab->recovery_start, ATH11K_RECOVER_START_TIMEOUT_HZ); - ath11k_hif_irq_disable(ab); - ath11k_hif_ce_irq_disable(ab); - ath11k_hif_power_down(ab, false); ath11k_hif_power_up(ab); diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c index c1fa42edd363..1a237adaa37d 100644 --- a/drivers/net/wireless/ath/ath11k/mac.c +++ b/drivers/net/wireless/ath/ath11k/mac.c @@ -6167,25 +6167,27 @@ static void ath11k_mac_tx_mgmt_free(struct ath11k *ar, int buf_id) ath11k_mgmt_over_wmi_tx_drop(ar, msdu); } -int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx) +void ath11k_mac_tx_mgmt_pending_free(struct ath11k *ar) { - struct ath11k *ar = ctx; - - ath11k_mac_tx_mgmt_free(ar, buf_id); + struct sk_buff *msdu; + int buf_id; - return 0; + idr_for_each_entry(&ar->txmgmt_idr, msdu, buf_id) + ath11k_mac_tx_mgmt_free(ar, buf_id); } -static int ath11k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx) +static void ath11k_mac_vif_txmgmt_cleanup(struct ath11k *ar, + struct ieee80211_vif *vif) { - struct ieee80211_vif *vif = ctx; - struct ath11k_skb_cb *skb_cb = ATH11K_SKB_CB((struct sk_buff *)skb); - struct ath11k *ar = skb_cb->ar; - - if (skb_cb->vif == vif) - ath11k_mac_tx_mgmt_free(ar, buf_id); + struct ath11k_skb_cb *skb_cb; + struct sk_buff *skb; + int buf_id; - return 0; + idr_for_each_entry(&ar->txmgmt_idr, skb, buf_id) { + skb_cb = ATH11K_SKB_CB(skb); + if (skb_cb->vif == vif) + ath11k_mac_tx_mgmt_free(ar, buf_id); + } } static int ath11k_mac_mgmt_tx_wmi(struct ath11k *ar, struct ath11k_vif *arvif, @@ -7417,8 +7419,7 @@ err_vdev_del: ath11k_peer_cleanup(ar, arvif->vdev_id); - idr_for_each(&ar->txmgmt_idr, - ath11k_mac_vif_txmgmt_idr_remove, vif); + ath11k_mac_vif_txmgmt_cleanup(ar, vif); for (i = 0; i < ab->hw_params.hal_params->num_tx_rings; i++) { spin_lock_bh(&ab->dp.tx_ring[i].tx_idr_lock); @@ -10418,7 +10419,7 @@ static void __ath11k_mac_unregister(struct ath11k *ar) ieee80211_unregister_hw(ar->hw); - idr_for_each(&ar->txmgmt_idr, ath11k_mac_tx_mgmt_pending_free, ar); + ath11k_mac_tx_mgmt_pending_free(ar); idr_destroy(&ar->txmgmt_idr); kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels); diff --git a/drivers/net/wireless/ath/ath11k/mac.h b/drivers/net/wireless/ath/ath11k/mac.h index 59f83c7175fd..127cb476b44b 100644 --- a/drivers/net/wireless/ath/ath11k/mac.h +++ b/drivers/net/wireless/ath/ath11k/mac.h @@ -162,7 +162,7 @@ struct ath11k *ath11k_mac_get_ar_by_pdev_id(struct ath11k_base *ab, u32 pdev_id) void ath11k_mac_drain_tx(struct ath11k *ar); void ath11k_mac_peer_cleanup_all(struct ath11k *ar); -int ath11k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx); +void ath11k_mac_tx_mgmt_pending_free(struct ath11k *ar); u8 ath11k_mac_bw_to_mac80211_bw(u8 bw); enum nl80211_he_gi ath11k_mac_he_gi_to_nl80211_he_gi(u8 sgi); enum nl80211_he_ru_alloc ath11k_mac_phy_he_ru_to_nl80211_he_ru_alloc(u16 ru_phy); diff --git a/drivers/net/wireless/ath/ath12k/ahb.c b/drivers/net/wireless/ath/ath12k/ahb.c index 85360365aa4b..2c55aae06dd0 100644 --- a/drivers/net/wireless/ath/ath12k/ahb.c +++ b/drivers/net/wireless/ath/ath12k/ahb.c @@ -191,6 +191,26 @@ static void __ath12k_ahb_ext_irq_disable(struct ath12k_base *ab) } } +static void ath12k_ahb_free_napi_for_group(struct ath12k_ext_irq_grp *irq_grp) +{ + netif_napi_del(&irq_grp->napi); + free_netdev(irq_grp->napi_ndev); + irq_grp->napi_ndev = NULL; +} + +static void ath12k_ahb_free_napi(struct ath12k_base *ab, int num_ext_irq_grp) +{ + int i; + + for (i = 0; i < num_ext_irq_grp; i++) + ath12k_ahb_free_napi_for_group(&ab->ext_irq_grp[i]); +} + +static void ath12k_ahb_free_ext_napi(struct ath12k_base *ab) +{ + ath12k_ahb_free_napi(ab, ATH12K_EXT_IRQ_GRP_NUM_MAX); +} + static void ath12k_ahb_ext_grp_enable(struct ath12k_ext_irq_grp *irq_grp) { int i; @@ -622,8 +642,10 @@ static int ath12k_ahb_config_ext_irq(struct ath12k_base *ab) irq_grp->grp_id = i; irq_grp->napi_ndev = alloc_netdev_dummy(0); - if (!irq_grp->napi_ndev) - return -ENOMEM; + if (!irq_grp->napi_ndev) { + ret = -ENOMEM; + goto free_napi_ndev; + } netif_napi_add(irq_grp->napi_ndev, &irq_grp->napi, ath12k_ahb_ext_grp_napi_poll); @@ -675,12 +697,19 @@ static int ath12k_ahb_config_ext_irq(struct ath12k_base *ab) ath12k_ahb_ext_interrupt_handler, IRQF_TRIGGER_RISING, irq_name[irq_idx], irq_grp); - if (ret) + if (ret) { ath12k_warn(ab, "failed request_irq for %d\n", irq); + ath12k_ahb_free_napi_for_group(irq_grp); + goto free_napi_ndev; + } } } return 0; + +free_napi_ndev: + ath12k_ahb_free_napi(ab, i); + return ret; } static int ath12k_ahb_config_irq(struct ath12k_base *ab) @@ -1353,7 +1382,7 @@ static int ath12k_ahb_probe(struct platform_device *pdev) ret = ab_ahb->device_family_ops->arch_init(ab); if (ret) { ath12k_err(ab, "AHB arch_init failed %d\n", ret); - goto err_rproc_deconfigure; + goto err_free_ext_napi; } ret = ath12k_core_init(ab); @@ -1367,6 +1396,9 @@ static int ath12k_ahb_probe(struct platform_device *pdev) err_deinit_arch: ab_ahb->device_family_ops->arch_deinit(ab); +err_free_ext_napi: + ath12k_ahb_free_ext_napi(ab); + err_rproc_deconfigure: mutex_lock(&ath12k_rproc_info_lock); ath12k_ahb_deconfigure_rproc(ab); @@ -1409,6 +1441,7 @@ static void ath12k_ahb_free_resources(struct ath12k_base *ab) struct platform_device *pdev = ab->pdev; struct ath12k_ahb *ab_ahb = ath12k_ab_to_ahb(ab); + ath12k_ahb_free_ext_napi(ab); ath12k_hal_srng_deinit(ab); ath12k_ce_free_pipes(ab); ath12k_ahb_resource_deinit(ab); diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index e527b59ecba5..25987bc58556 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -54,6 +54,7 @@ ath12k_mem_profile_based_param ath12k_mem_profile_based_param[] = { .num_pool_tx_desc = 32768, .rx_desc_count = 12288, .rx_release_ring_size = 16384, + .rxdma_buf_ring_size = 8192, }, }, [ATH12K_QMI_MEMORY_MODE_LOW_512_M] = { @@ -68,10 +69,40 @@ ath12k_mem_profile_based_param ath12k_mem_profile_based_param[] = { .num_pool_tx_desc = 16384, .rx_desc_count = 6144, .rx_release_ring_size = 8192, + .rxdma_buf_ring_size = 4096, }, }, }; +/* + * On these machines the OS cannot control the WCN7850 hardware rfkill + * input, which reads as "radio off", so hardware rfkill must stay + * disabled. Ideally this would come from the connector node of the board + * DT, but that binding does not exist yet. + */ +static const struct ath12k_core_broken_rfkill_table { + enum ath12k_hw_rev hw_rev; + const char *compatible; +} ath12k_core_broken_rfkill_table[] = { + { ATH12K_HW_WCN7850_HW20, "microsoft,denali" }, + { ATH12K_HW_WCN7850_HW20, "microsoft,romulus13" }, + { ATH12K_HW_WCN7850_HW20, "microsoft,romulus15" }, + { /* Sentinel */ } +}; + +static bool ath12k_core_rfkill_is_broken(struct ath12k_base *ab) +{ + const struct ath12k_core_broken_rfkill_table *entry; + + for (entry = ath12k_core_broken_rfkill_table; entry->compatible; entry++) { + if (ab->hw_rev == entry->hw_rev && + of_machine_is_compatible(entry->compatible)) + return true; + } + + return false; +} + static int ath12k_core_rfkill_config(struct ath12k_base *ab) { struct ath12k *ar; @@ -83,6 +114,9 @@ static int ath12k_core_rfkill_config(struct ath12k_base *ab) if (ath12k_acpi_get_disable_rfkill(ab)) return 0; + if (ath12k_core_rfkill_is_broken(ab)) + return 0; + for (i = 0; i < ab->num_radios; i++) { ar = ab->pdevs[i].ar; @@ -1537,8 +1571,7 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab) complete_all(&ar->thermal.wmi_sync); wake_up(&ar->dp.tx_empty_waitq); - idr_for_each(&ar->txmgmt_idr, - ath12k_mac_tx_mgmt_pending_free, ar); + ath12k_mac_tx_mgmt_pending_free(ar); idr_destroy(&ar->txmgmt_idr); wake_up(&ar->txmgmt_empty_waitq); diff --git a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c index b772181a496e..f84f1828275a 100644 --- a/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c +++ b/drivers/net/wireless/ath/ath12k/debugfs_htt_stats.c @@ -6190,7 +6190,7 @@ static ssize_t ath12k_write_htt_stats_type(struct file *file, const int size = 32; int num_args; - if (count > size) + if (count >= size) return -EINVAL; char *buf __free(kfree) = kzalloc(size, GFP_KERNEL); diff --git a/drivers/net/wireless/ath/ath12k/dp.h b/drivers/net/wireless/ath/ath12k/dp.h index c53eac20b989..108e27dd5797 100644 --- a/drivers/net/wireless/ath/ath12k/dp.h +++ b/drivers/net/wireless/ath/ath12k/dp.h @@ -31,6 +31,7 @@ struct ath12k_dp_profile_params { u32 num_pool_tx_desc; u32 rx_desc_count; u32 rx_release_ring_size; + u32 rxdma_buf_ring_size; }; #define DP_MON_PURGE_TIMEOUT_MS 100 @@ -210,7 +211,6 @@ struct ath12k_pdev_dp { #define DP_REO_EXCEPTION_RING_SIZE 128 #define DP_REO_CMD_RING_SIZE 256 #define DP_REO_STATUS_RING_SIZE 2048 -#define DP_RXDMA_BUF_RING_SIZE 4096 #define DP_RX_MAC_BUF_RING_SIZE 4096 #define DP_RXDMA_REFILL_RING_SIZE 2048 #define DP_RXDMA_ERR_DST_RING_SIZE 1024 @@ -730,6 +730,12 @@ ath12k_dp_rx_release_ring_size(const struct ath12k_dp_profile_params *p) return p->rx_release_ring_size; } +static inline u32 +ath12k_dp_rxdma_buf_ring_size(const struct ath12k_dp_profile_params *p) +{ + return p->rxdma_buf_ring_size; +} + void ath12k_dp_vdev_tx_attach(struct ath12k *ar, struct ath12k_link_vif *arvif); void ath12k_dp_partner_cc_init(struct ath12k_base *ab); int ath12k_dp_pdev_alloc(struct ath12k_base *ab); diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c index cfaf26ae2720..36be543b7c50 100644 --- a/drivers/net/wireless/ath/ath12k/dp_rx.c +++ b/drivers/net/wireless/ath/ath12k/dp_rx.c @@ -1699,7 +1699,7 @@ int ath12k_dp_rx_alloc(struct ath12k_base *ab) ret = ath12k_dp_srng_setup(ab, &dp->rx_refill_buf_ring.refill_buf_ring, HAL_RXDMA_BUF, 0, 0, - DP_RXDMA_BUF_RING_SIZE); + ath12k_dp_rxdma_buf_ring_size(dp_params)); if (ret) { ath12k_warn(ab, "failed to setup rx_refill_buf_ring\n"); return ret; diff --git a/drivers/net/wireless/ath/ath12k/hw.h b/drivers/net/wireless/ath/ath12k/hw.h index 1e652dc0d247..52558dd126a0 100644 --- a/drivers/net/wireless/ath/ath12k/hw.h +++ b/drivers/net/wireless/ath/ath12k/hw.h @@ -239,6 +239,7 @@ struct ath12k_hw_params { } client; bool host_alloc_ml_id; + bool advertise_iface_mac_pool; }; struct ath12k_hw_ops { diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c index 196b807210de..01f8c6572f65 100644 --- a/drivers/net/wireless/ath/ath12k/mac.c +++ b/drivers/net/wireless/ath/ath12k/mac.c @@ -9194,25 +9194,27 @@ static void ath12k_mac_tx_mgmt_free(struct ath12k *ar, int buf_id) ath12k_mgmt_over_wmi_tx_drop(ar, msdu); } -int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx) +void ath12k_mac_tx_mgmt_pending_free(struct ath12k *ar) { - struct ath12k *ar = ctx; - - ath12k_mac_tx_mgmt_free(ar, buf_id); + struct sk_buff *msdu; + int buf_id; - return 0; + idr_for_each_entry(&ar->txmgmt_idr, msdu, buf_id) + ath12k_mac_tx_mgmt_free(ar, buf_id); } -static int ath12k_mac_vif_txmgmt_idr_remove(int buf_id, void *skb, void *ctx) +static void ath12k_mac_vif_txmgmt_cleanup(struct ath12k *ar, + struct ieee80211_vif *vif) { - struct ieee80211_vif *vif = ctx; - struct ath12k_skb_cb *skb_cb = ATH12K_SKB_CB(skb); - struct ath12k *ar = skb_cb->ar; - - if (skb_cb->vif == vif) - ath12k_mac_tx_mgmt_free(ar, buf_id); + struct ath12k_skb_cb *skb_cb; + struct sk_buff *skb; + int buf_id; - return 0; + idr_for_each_entry(&ar->txmgmt_idr, skb, buf_id) { + skb_cb = ATH12K_SKB_CB(skb); + if (skb_cb->vif == vif) + ath12k_mac_tx_mgmt_free(ar, buf_id); + } } static int ath12k_mac_mgmt_tx_wmi(struct ath12k *ar, struct ath12k_link_vif *arvif, @@ -10977,8 +10979,7 @@ err_vdev_del: ath12k_peer_cleanup(ar, arvif->vdev_id); ath12k_ahvif_put_link_cache(ahvif, arvif->link_id); - idr_for_each(&ar->txmgmt_idr, - ath12k_mac_vif_txmgmt_idr_remove, vif); + ath12k_mac_vif_txmgmt_cleanup(ar, vif); ath12k_mac_vif_unref(ath12k_ab_to_dp(ab), vif); @@ -14738,7 +14739,7 @@ static struct wiphy_iftype_ext_capab ath12k_iftypes_ext_capa[] = { static void ath12k_mac_cleanup_unregister(struct ath12k *ar) { - idr_for_each(&ar->txmgmt_idr, ath12k_mac_tx_mgmt_pending_free, ar); + ath12k_mac_tx_mgmt_pending_free(ar); idr_destroy(&ar->txmgmt_idr); kfree(ar->mac.sbands[NL80211_BAND_2GHZ].channels); @@ -14746,6 +14747,56 @@ static void ath12k_mac_cleanup_unregister(struct ath12k *ar) kfree(ar->mac.sbands[NL80211_BAND_6GHZ].channels); } +static void ath12k_mac_cleanup_mac_address_list(struct ath12k_hw *ah) +{ + kfree(ah->hw->wiphy->addresses); + ah->hw->wiphy->addresses = NULL; + ah->hw->wiphy->n_addresses = 0; +} + +static void ath12k_mac_setup_mac_address_list(struct ath12k_hw *ah, + const u8 *mac_addr) +{ + struct mac_address *addresses; + struct ath12k *ar; + u16 n_addresses; + int i; + + /* + * wiphy->addresses is per wiphy, so the generated interface MAC + * pool is advertised for the whole ath12k_hw. The hw_params flag is + * expected to be consistent across all radios in an ath12k_hw, so + * use the first radio as the source. + */ + ar = ath12k_ah_to_ar(ah, 0); + if (!ar->ab->hw_params->advertise_iface_mac_pool) + return; + + /* + * Only the upper nibble of the first octet is varied, so at most 16 + * addresses can be derived from one base. + */ + n_addresses = min_t(u16, TARGET_NUM_VDEVS(ar->ab), 16); + if (n_addresses <= 1) + return; + + addresses = kzalloc_objs(*addresses, n_addresses); + if (!addresses) + return; + + ether_addr_copy(addresses[0].addr, mac_addr); + for (i = 1; i < n_addresses; i++) { + ether_addr_copy(addresses[i].addr, mac_addr); + /* set Local Administered Address bit */ + addresses[i].addr[0] |= 0x2; + + addresses[i].addr[0] += i << 4; + } + + ah->hw->wiphy->addresses = addresses; + ah->hw->wiphy->n_addresses = n_addresses; +} + static void ath12k_mac_hw_unregister(struct ath12k_hw *ah) { struct ieee80211_hw *hw = ah->hw; @@ -14765,6 +14816,7 @@ static void ath12k_mac_hw_unregister(struct ath12k_hw *ah) ath12k_mac_cleanup_unregister(ar); ath12k_mac_cleanup_iface_combinations(ah); + ath12k_mac_cleanup_mac_address_list(ah); SET_IEEE80211_DEV(hw, NULL); } @@ -14881,6 +14933,7 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah) wiphy->available_antennas_tx = antennas_tx; SET_IEEE80211_PERM_ADDR(hw, mac_addr); + ath12k_mac_setup_mac_address_list(ah, mac_addr); SET_IEEE80211_DEV(hw, ab->dev); ret = ath12k_mac_setup_iface_combinations(ah); @@ -15123,6 +15176,8 @@ err_cleanup_unregister: ath12k_mac_cleanup_unregister(ar); } + ath12k_mac_cleanup_mac_address_list(ah); + SET_IEEE80211_DEV(hw, NULL); return ret; diff --git a/drivers/net/wireless/ath/ath12k/mac.h b/drivers/net/wireless/ath/ath12k/mac.h index aba98afd4365..ae44ebfd9bd9 100644 --- a/drivers/net/wireless/ath/ath12k/mac.h +++ b/drivers/net/wireless/ath/ath12k/mac.h @@ -173,7 +173,7 @@ struct ath12k *ath12k_mac_get_ar_by_pdev_id(struct ath12k_base *ab, u32 pdev_id) void ath12k_mac_drain_tx(struct ath12k *ar); void ath12k_mac_peer_cleanup_all(struct ath12k *ar); void ath12k_mac_dp_peer_cleanup(struct ath12k_hw *ah); -int ath12k_mac_tx_mgmt_pending_free(int buf_id, void *skb, void *ctx); +void ath12k_mac_tx_mgmt_pending_free(struct ath12k *ar); enum rate_info_bw ath12k_mac_bw_to_mac80211_bw(enum ath12k_supported_bw bw); enum ath12k_supported_bw ath12k_mac_mac80211_bw_to_ath12k_bw(enum rate_info_bw bw); enum hal_encrypt_type ath12k_dp_tx_get_encrypt_type(u32 cipher); diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hal_desc.h b/drivers/net/wireless/ath/ath12k/wifi7/hal_desc.h index e1ab47b44433..822de3a4abc8 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hal_desc.h +++ b/drivers/net/wireless/ath/ath12k/wifi7/hal_desc.h @@ -2100,41 +2100,15 @@ enum hal_rx_reo_queue_pn_size { #define HAL_RX_REO_QUEUE_INFO0_VLD BIT(0) #define HAL_RX_REO_QUEUE_INFO0_ASSOC_LNK_DESC_COUNTER GENMASK(2, 1) -#define HAL_RX_REO_QUEUE_INFO0_DIS_DUP_DETECTION BIT(3) -#define HAL_RX_REO_QUEUE_INFO0_SOFT_REORDER_EN BIT(4) #define HAL_RX_REO_QUEUE_INFO0_AC GENMASK(6, 5) -#define HAL_RX_REO_QUEUE_INFO0_BAR BIT(7) #define HAL_RX_REO_QUEUE_INFO0_RETRY BIT(8) -#define HAL_RX_REO_QUEUE_INFO0_CHECK_2K_MODE BIT(9) -#define HAL_RX_REO_QUEUE_INFO0_OOR_MODE BIT(10) #define HAL_RX_REO_QUEUE_INFO0_BA_WINDOW_SIZE GENMASK(20, 11) #define HAL_RX_REO_QUEUE_INFO0_PN_CHECK BIT(21) -#define HAL_RX_REO_QUEUE_INFO0_EVEN_PN BIT(22) -#define HAL_RX_REO_QUEUE_INFO0_UNEVEN_PN BIT(23) -#define HAL_RX_REO_QUEUE_INFO0_PN_HANDLE_ENABLE BIT(24) #define HAL_RX_REO_QUEUE_INFO0_PN_SIZE GENMASK(26, 25) #define HAL_RX_REO_QUEUE_INFO0_IGNORE_AMPDU_FLG BIT(27) #define HAL_RX_REO_QUEUE_INFO1_SVLD BIT(0) #define HAL_RX_REO_QUEUE_INFO1_SSN GENMASK(12, 1) -#define HAL_RX_REO_QUEUE_INFO1_CURRENT_IDX GENMASK(22, 13) -#define HAL_RX_REO_QUEUE_INFO1_SEQ_2K_ERR BIT(23) -#define HAL_RX_REO_QUEUE_INFO1_PN_ERR BIT(24) -#define HAL_RX_REO_QUEUE_INFO1_PN_VALID BIT(31) - -#define HAL_RX_REO_QUEUE_INFO2_MPDU_COUNT GENMASK(6, 0) -#define HAL_RX_REO_QUEUE_INFO2_MSDU_COUNT (31, 7) - -#define HAL_RX_REO_QUEUE_INFO3_TIMEOUT_COUNT GENMASK(9, 4) -#define HAL_RX_REO_QUEUE_INFO3_FWD_DUE_TO_BAR_CNT GENMASK(15, 10) -#define HAL_RX_REO_QUEUE_INFO3_DUPLICATE_COUNT GENMASK(31, 16) - -#define HAL_RX_REO_QUEUE_INFO4_FRAME_IN_ORD_COUNT GENMASK(23, 0) -#define HAL_RX_REO_QUEUE_INFO4_BAR_RECVD_COUNT GENMASK(31, 24) - -#define HAL_RX_REO_QUEUE_INFO5_LATE_RX_MPDU_COUNT GENMASK(11, 0) -#define HAL_RX_REO_QUEUE_INFO5_WINDOW_JUMP_2K GENMASK(15, 12) -#define HAL_RX_REO_QUEUE_INFO5_HOLE_COUNT GENMASK(31, 16) struct hal_rx_reo_queue { struct hal_desc_header desc_hdr; diff --git a/drivers/net/wireless/ath/ath12k/wifi7/hw.c b/drivers/net/wireless/ath/ath12k/wifi7/hw.c index aec7c652808c..b1c17cc197df 100644 --- a/drivers/net/wireless/ath/ath12k/wifi7/hw.c +++ b/drivers/net/wireless/ath/ath12k/wifi7/hw.c @@ -447,6 +447,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = { }, .host_alloc_ml_id = true, + .advertise_iface_mac_pool = false, }, { .name = "wcn7850 hw2.0", @@ -542,6 +543,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = { }, .host_alloc_ml_id = false, + .advertise_iface_mac_pool = true, }, { .name = "qcn9274 hw2.0", @@ -633,6 +635,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = { }, .host_alloc_ml_id = true, + .advertise_iface_mac_pool = false, }, { .name = "ipq5332 hw1.0", @@ -718,6 +721,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = { }, .host_alloc_ml_id = true, + .advertise_iface_mac_pool = false, }, { .name = "qcc2072 hw1.0", @@ -814,6 +818,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = { }, .host_alloc_ml_id = false, + .advertise_iface_mac_pool = true, }, { .name = "ipq5424 hw1.0", @@ -902,6 +907,7 @@ static const struct ath12k_hw_params ath12k_wifi7_hw_params[] = { }, .host_alloc_ml_id = true, + .advertise_iface_mac_pool = false, }, }; diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c index 3149b6376c94..75b259990c79 100644 --- a/drivers/net/wireless/ath/ath12k/wmi.c +++ b/drivers/net/wireless/ath/ath12k/wmi.c @@ -5050,6 +5050,7 @@ static int ath12k_wmi_svc_rdy_ext_parse(struct ath12k_base *ab, u16 tag, u16 len, const void *ptr, void *data) { + struct ath12k_svc_ext_info *svc_ext_info = &ab->wmi_ab.svc_ext_info; struct ath12k_wmi_pdev *wmi_handle = &ab->wmi_ab.wmi[0]; struct ath12k_wmi_svc_rdy_ext_parse *svc_rdy_ext = data; int ret; @@ -5094,6 +5095,22 @@ static int ath12k_wmi_svc_rdy_ext_parse(struct ath12k_base *ab, return ret; } + if (svc_rdy_ext->tot_phy_id > + ARRAY_SIZE(svc_ext_info->mac_phy_info)) { + ath12k_warn(ab, "too many PHY entries %u (max %zu)\n", + svc_rdy_ext->tot_phy_id, + ARRAY_SIZE(svc_ext_info->mac_phy_info)); + return -EINVAL; + } + + if (svc_rdy_ext->n_mac_phy_caps < svc_rdy_ext->tot_phy_id) { + ath12k_warn(ab, + "not enough MAC/PHY caps %u, expected %u\n", + svc_rdy_ext->n_mac_phy_caps, + svc_rdy_ext->tot_phy_id); + return -EINVAL; + } + ath12k_wmi_save_all_mac_phy_info(ab, svc_rdy_ext); svc_rdy_ext->mac_phy_done = true; diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c index a9a35476fecd..65b7c68a9297 100644 --- a/drivers/net/wireless/ath/ath6kl/cfg80211.c +++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c @@ -1560,9 +1560,7 @@ static int ath6kl_cfg80211_del_iface(struct wiphy *wiphy, ath6kl_cfg80211_vif_stop(vif, test_bit(WMI_READY, &ar->flag)); - rtnl_lock(); ath6kl_cfg80211_vif_cleanup(vif); - rtnl_unlock(); return 0; } diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 8b27d8cc086a..cfb1c90eb4b6 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c @@ -1363,6 +1363,8 @@ void ath9k_init_channel_context(struct ath_softc *sc) void ath9k_deinit_channel_context(struct ath_softc *sc) { + timer_shutdown_sync(&sc->sched.timer); + timer_shutdown_sync(&sc->offchannel.timer); cancel_work_sync(&sc->chanctx_work); } diff --git a/drivers/net/wireless/ath/ath9k/common-spectral.c b/drivers/net/wireless/ath/ath9k/common-spectral.c index ca01a07f6630..beedabee7d47 100644 --- a/drivers/net/wireless/ath/ath9k/common-spectral.c +++ b/drivers/net/wireless/ath/ath9k/common-spectral.c @@ -805,6 +805,15 @@ static ssize_t write_file_spec_scan_ctl(struct file *file, buf[len] = '\0'; + /* + * Every command below drives PHY register writes. Refuse them while + * the hardware is disabled (the interface is down): on the AR9271 + * that traffic hangs the firmware until the device is re-enumerated. + * The reset control refuses on the same flag. + */ + if (test_bit(ATH_OP_INVALID, &common->op_flags)) + return -EBUSY; + if (strncmp("trigger", buf, 7) == 0) { ath9k_cmn_spectral_scan_trigger(common, spec_priv); } else if (strncmp("background", buf, 10) == 0) { |
