summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath
diff options
context:
space:
mode:
authorJakub Kicinski <kuba@kernel.org>2023-10-18 02:52:53 +0300
committerJakub Kicinski <kuba@kernel.org>2023-10-18 02:52:54 +0300
commit56a7bb12c78ffa1b02e154b1d779ed2a1555fa3c (patch)
tree4a1236780c8a32834546ebd0dc34f5658ac558a4 /drivers/net/wireless/ath
parent7713ec844756a9883ba9a91381369256275de4fb (diff)
parentb650981501bf00bc84f09cf3b3e0b6190cfed794 (diff)
downloadlinux-56a7bb12c78ffa1b02e154b1d779ed2a1555fa3c.tar.xz
Merge tag 'wireless-next-2023-10-16' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next
Kalle Valo says: ==================== wireless-next patches for v6.7 The second pull request for v6.7, with only driver changes this time. We have now support for mt7925 PCIe and USB variants, few new features and of course some fixes. Major changes: mt76 - mt7925 support ath12k - read board data variant name from SMBIOS wfx - Remain-On-Channel (ROC) support * tag 'wireless-next-2023-10-16' of git://git.kernel.org/pub/scm/linux/kernel/git/wireless/wireless-next: (109 commits) wifi: rtw89: mac: do bf_monitor only if WiFi 6 chips wifi: rtw89: mac: set bf_assoc capabilities according to chip gen wifi: rtw89: mac: set bfee_ctrl() according to chip gen wifi: rtw89: mac: add registers of MU-EDCA parameters for WiFi 7 chips wifi: rtw89: mac: generalize register of MU-EDCA switch according to chip gen wifi: rtw89: mac: update RTS threshold according to chip gen wifi: rtlwifi: simplify TX command fill callbacks wifi: hostap: remove unused ioctl function wifi: atmel: remove unused ioctl function wifi: rtw89: coex: add annotation __counted_by() to struct rtw89_btc_btf_set_mon_reg wifi: rtw89: coex: add annotation __counted_by() for struct rtw89_btc_btf_set_slot_table wifi: rtw89: add EHT radiotap in monitor mode wifi: rtw89: show EHT rate in debugfs wifi: rtw89: parse TX EHT rate selected by firmware from RA C2H report wifi: rtw89: Add EHT rate mask as parameters of RA H2C command wifi: rtw89: parse EHT information from RX descriptor and PPDU status packet wifi: radiotap: add bandwidth definition of EHT U-SIG wifi: rtlwifi: use convenient list_count_nodes() wifi: p54: Annotate struct p54_cal_database with __counted_by wifi: brcmfmac: fweh: Add __counted_by for struct brcmf_fweh_queue_item and use struct_size() ... ==================== Link: https://lore.kernel.org/r/20231016143822.880D8C433C8@smtp.kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers/net/wireless/ath')
-rw-r--r--drivers/net/wireless/ath/ath10k/debug.c47
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c26
-rw-r--r--drivers/net/wireless/ath/ath10k/snoc.c18
-rw-r--r--drivers/net/wireless/ath/ath10k/spectral.c26
-rw-r--r--drivers/net/wireless/ath/ath11k/mac.c27
-rw-r--r--drivers/net/wireless/ath/ath12k/core.c69
-rw-r--r--drivers/net/wireless/ath/ath12k/core.h21
-rw-r--r--drivers/net/wireless/ath/ath12k/debug.c2
-rw-r--r--drivers/net/wireless/ath/ath12k/dp_rx.c12
-rw-r--r--drivers/net/wireless/ath/ath12k/mac.c65
-rw-r--r--drivers/net/wireless/ath/ath12k/mhi.c11
-rw-r--r--drivers/net/wireless/ath/ath12k/qmi.c5
-rw-r--r--drivers/net/wireless/ath/ath12k/wmi.h3
-rw-r--r--drivers/net/wireless/ath/carl9170/usb.c10
-rw-r--r--drivers/net/wireless/ath/dfs_pattern_detector.c21
15 files changed, 248 insertions, 115 deletions
diff --git a/drivers/net/wireless/ath/ath10k/debug.c b/drivers/net/wireless/ath/ath10k/debug.c
index fe89bc61e531..ad9cf953a2fc 100644
--- a/drivers/net/wireless/ath/ath10k/debug.c
+++ b/drivers/net/wireless/ath/ath10k/debug.c
@@ -1964,20 +1964,13 @@ static ssize_t ath10k_write_btcoex(struct file *file,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
- char buf[32];
- size_t buf_size;
- int ret;
+ ssize_t ret;
bool val;
u32 pdev_param;
- buf_size = min(count, (sizeof(buf) - 1));
- if (copy_from_user(buf, ubuf, buf_size))
- return -EFAULT;
-
- buf[buf_size] = '\0';
-
- if (kstrtobool(buf, &val) != 0)
- return -EINVAL;
+ ret = kstrtobool_from_user(ubuf, count, &val);
+ if (ret)
+ return ret;
if (!ar->coex_support)
return -EOPNOTSUPP;
@@ -2000,7 +1993,7 @@ static ssize_t ath10k_write_btcoex(struct file *file,
ar->running_fw->fw_file.fw_features)) {
ret = ath10k_wmi_pdev_set_param(ar, pdev_param, val);
if (ret) {
- ath10k_warn(ar, "failed to enable btcoex: %d\n", ret);
+ ath10k_warn(ar, "failed to enable btcoex: %zd\n", ret);
ret = count;
goto exit;
}
@@ -2103,19 +2096,12 @@ static ssize_t ath10k_write_peer_stats(struct file *file,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
- char buf[32];
- size_t buf_size;
- int ret;
+ ssize_t ret;
bool val;
- buf_size = min(count, (sizeof(buf) - 1));
- if (copy_from_user(buf, ubuf, buf_size))
- return -EFAULT;
-
- buf[buf_size] = '\0';
-
- if (kstrtobool(buf, &val) != 0)
- return -EINVAL;
+ ret = kstrtobool_from_user(ubuf, count, &val);
+ if (ret)
+ return ret;
mutex_lock(&ar->conf_mutex);
@@ -2239,21 +2225,16 @@ static ssize_t ath10k_sta_tid_stats_mask_write(struct file *file,
size_t count, loff_t *ppos)
{
struct ath10k *ar = file->private_data;
- char buf[32];
- ssize_t len;
+ ssize_t ret;
u32 mask;
- len = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, len))
- return -EFAULT;
-
- buf[len] = '\0';
- if (kstrtoint(buf, 0, &mask))
- return -EINVAL;
+ ret = kstrtoint_from_user(user_buf, count, 0, &mask);
+ if (ret)
+ return ret;
ar->sta_tid_stats_mask = mask;
- return len;
+ return count;
}
static const struct file_operations fops_sta_tid_stats_mask = {
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 03e7bc5b6c0b..2cf693f3fea9 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -728,20 +728,13 @@ static int ath10k_peer_create(struct ath10k *ar,
const u8 *addr,
enum wmi_peer_type peer_type)
{
- struct ath10k_vif *arvif;
struct ath10k_peer *peer;
- int num_peers = 0;
int ret;
lockdep_assert_held(&ar->conf_mutex);
- num_peers = ar->num_peers;
-
- /* Each vdev consumes a peer entry as well */
- list_for_each_entry(arvif, &ar->arvifs, list)
- num_peers++;
-
- if (num_peers >= ar->max_num_peers)
+ /* Each vdev consumes a peer entry as well. */
+ if (ar->num_peers + list_count_nodes(&ar->arvifs) >= ar->max_num_peers)
return -ENOBUFS;
ret = ath10k_wmi_peer_create(ar, vdev_id, addr, peer_type);
@@ -4503,18 +4496,21 @@ void __ath10k_scan_finish(struct ath10k *ar)
break;
case ATH10K_SCAN_RUNNING:
case ATH10K_SCAN_ABORTING:
+ if (ar->scan.is_roc && ar->scan.roc_notify)
+ ieee80211_remain_on_channel_expired(ar->hw);
+ fallthrough;
+ case ATH10K_SCAN_STARTING:
if (!ar->scan.is_roc) {
struct cfg80211_scan_info info = {
- .aborted = (ar->scan.state ==
- ATH10K_SCAN_ABORTING),
+ .aborted = ((ar->scan.state ==
+ ATH10K_SCAN_ABORTING) ||
+ (ar->scan.state ==
+ ATH10K_SCAN_STARTING)),
};
ieee80211_scan_completed(ar->hw, &info);
- } else if (ar->scan.roc_notify) {
- ieee80211_remain_on_channel_expired(ar->hw);
}
- fallthrough;
- case ATH10K_SCAN_STARTING:
+
ar->scan.state = ATH10K_SCAN_IDLE;
ar->scan_channel = NULL;
ar->scan.roc_freq = 0;
diff --git a/drivers/net/wireless/ath/ath10k/snoc.c b/drivers/net/wireless/ath/ath10k/snoc.c
index 26214c00cd0d..2c39bad7ebfb 100644
--- a/drivers/net/wireless/ath/ath10k/snoc.c
+++ b/drivers/net/wireless/ath/ath10k/snoc.c
@@ -828,12 +828,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)
@@ -1090,6 +1098,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:
@@ -1253,8 +1263,8 @@ static int ath10k_snoc_request_irq(struct ath10k *ar)
for (id = 0; id < CE_COUNT_MAX; id++) {
ret = request_irq(ar_snoc->ce_irqs[id].irq_line,
- ath10k_snoc_per_engine_handler, 0,
- ce_name[id], ar);
+ ath10k_snoc_per_engine_handler,
+ IRQF_NO_AUTOEN, ce_name[id], ar);
if (ret) {
ath10k_err(ar,
"failed to register IRQ handler for CE %d: %d\n",
diff --git a/drivers/net/wireless/ath/ath10k/spectral.c b/drivers/net/wireless/ath/ath10k/spectral.c
index 68254a967ccb..2240994390ed 100644
--- a/drivers/net/wireless/ath/ath10k/spectral.c
+++ b/drivers/net/wireless/ath/ath10k/spectral.c
@@ -384,16 +384,11 @@ static ssize_t write_file_spectral_count(struct file *file,
{
struct ath10k *ar = file->private_data;
unsigned long val;
- char buf[32];
- ssize_t len;
-
- len = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, len))
- return -EFAULT;
+ ssize_t ret;
- buf[len] = '\0';
- if (kstrtoul(buf, 0, &val))
- return -EINVAL;
+ ret = kstrtoul_from_user(user_buf, count, 0, &val);
+ if (ret)
+ return ret;
if (val > 255)
return -EINVAL;
@@ -440,16 +435,11 @@ static ssize_t write_file_spectral_bins(struct file *file,
{
struct ath10k *ar = file->private_data;
unsigned long val;
- char buf[32];
- ssize_t len;
-
- len = min(count, sizeof(buf) - 1);
- if (copy_from_user(buf, user_buf, len))
- return -EFAULT;
+ ssize_t ret;
- buf[len] = '\0';
- if (kstrtoul(buf, 0, &val))
- return -EINVAL;
+ ret = kstrtoul_from_user(user_buf, count, 0, &val);
+ if (ret)
+ return ret;
if (val < 64 || val > SPECTRAL_ATH10K_MAX_NUM_BINS)
return -EINVAL;
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 20b04723daec..a36208a0aab5 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -5,6 +5,7 @@
*/
#include <net/mac80211.h>
+#include <net/cfg80211.h>
#include <linux/etherdevice.h>
#include <linux/bitfield.h>
#include <linux/inetdevice.h>
@@ -7196,6 +7197,7 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
struct wmi_vdev_start_req_arg arg = {};
const struct cfg80211_chan_def *chandef = &ctx->def;
int ret = 0;
+ unsigned int dfs_cac_time;
lockdep_assert_held(&ar->conf_mutex);
@@ -7275,20 +7277,21 @@ ath11k_mac_vdev_start_restart(struct ath11k_vif *arvif,
ath11k_dbg(ab, ATH11K_DBG_MAC, "vdev %pM started, vdev_id %d\n",
arvif->vif->addr, arvif->vdev_id);
- /* Enable CAC Flag in the driver by checking the channel DFS cac time,
- * i.e dfs_cac_ms value which will be valid only for radar channels
- * and state as NL80211_DFS_USABLE which indicates CAC needs to be
+ /* Enable CAC Flag in the driver by checking the all sub-channel's DFS
+ * state as NL80211_DFS_USABLE which indicates CAC needs to be
* done before channel usage. This flags is used to drop rx packets.
* during CAC.
*/
/* TODO Set the flag for other interface types as required */
- if (arvif->vdev_type == WMI_VDEV_TYPE_AP &&
- chandef->chan->dfs_cac_ms &&
- chandef->chan->dfs_state == NL80211_DFS_USABLE) {
+ if (arvif->vdev_type == WMI_VDEV_TYPE_AP && ctx->radar_enabled &&
+ cfg80211_chandef_dfs_usable(ar->hw->wiphy, chandef)) {
set_bit(ATH11K_CAC_RUNNING, &ar->dev_flags);
+ dfs_cac_time = cfg80211_chandef_dfs_cac_time(ar->hw->wiphy,
+ chandef);
ath11k_dbg(ab, ATH11K_DBG_MAC,
- "CAC Started in chan_freq %d for vdev %d\n",
- arg.channel.freq, arg.vdev_id);
+ "cac started dfs_cac_time %u center_freq %d center_freq1 %d for vdev %d\n",
+ dfs_cac_time, arg.channel.freq, chandef->center_freq1,
+ arg.vdev_id);
}
ret = ath11k_mac_set_txbf_conf(arvif);
@@ -9057,6 +9060,14 @@ static int ath11k_mac_op_get_txpower(struct ieee80211_hw *hw,
if (ar->state != ATH11K_STATE_ON)
goto err_fallback;
+ /* Firmware doesn't provide Tx power during CAC hence no need to fetch
+ * the stats.
+ */
+ if (test_bit(ATH11K_CAC_RUNNING, &ar->dev_flags)) {
+ mutex_unlock(&ar->conf_mutex);
+ return -EAGAIN;
+ }
+
req_param.pdev_id = ar->pdev->pdev_id;
req_param.stats_id = WMI_REQUEST_PDEV_STAT;
diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index 9a9a471ff130..c68750cb3c4d 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -398,6 +398,75 @@ static void ath12k_core_stop(struct ath12k_base *ab)
/* De-Init of components as needed */
}
+static void ath12k_core_check_bdfext(const struct dmi_header *hdr, void *data)
+{
+ struct ath12k_base *ab = data;
+ const char *magic = ATH12K_SMBIOS_BDF_EXT_MAGIC;
+ struct ath12k_smbios_bdf *smbios = (struct ath12k_smbios_bdf *)hdr;
+ ssize_t copied;
+ size_t len;
+ int i;
+
+ if (ab->qmi.target.bdf_ext[0] != '\0')
+ return;
+
+ if (hdr->type != ATH12K_SMBIOS_BDF_EXT_TYPE)
+ return;
+
+ if (hdr->length != ATH12K_SMBIOS_BDF_EXT_LENGTH) {
+ ath12k_dbg(ab, ATH12K_DBG_BOOT,
+ "wrong smbios bdf ext type length (%d).\n",
+ hdr->length);
+ return;
+ }
+
+ if (!smbios->bdf_enabled) {
+ ath12k_dbg(ab, ATH12K_DBG_BOOT, "bdf variant name not found.\n");
+ return;
+ }
+
+ /* Only one string exists (per spec) */
+ if (memcmp(smbios->bdf_ext, magic, strlen(magic)) != 0) {
+ ath12k_dbg(ab, ATH12K_DBG_BOOT,
+ "bdf variant magic does not match.\n");
+ return;
+ }
+
+ len = min_t(size_t,
+ strlen(smbios->bdf_ext), sizeof(ab->qmi.target.bdf_ext));
+ for (i = 0; i < len; i++) {
+ if (!isascii(smbios->bdf_ext[i]) || !isprint(smbios->bdf_ext[i])) {
+ ath12k_dbg(ab, ATH12K_DBG_BOOT,
+ "bdf variant name contains non ascii chars.\n");
+ return;
+ }
+ }
+
+ /* Copy extension name without magic prefix */
+ copied = strscpy(ab->qmi.target.bdf_ext, smbios->bdf_ext + strlen(magic),
+ sizeof(ab->qmi.target.bdf_ext));
+ if (copied < 0) {
+ ath12k_dbg(ab, ATH12K_DBG_BOOT,
+ "bdf variant string is longer than the buffer can accommodate\n");
+ return;
+ }
+
+ ath12k_dbg(ab, ATH12K_DBG_BOOT,
+ "found and validated bdf variant smbios_type 0x%x bdf %s\n",
+ ATH12K_SMBIOS_BDF_EXT_TYPE, ab->qmi.target.bdf_ext);
+}
+
+int ath12k_core_check_smbios(struct ath12k_base *ab)
+{
+ ab->qmi.target.bdf_ext[0] = '\0';
+ dmi_walk(ath12k_core_check_bdfext, ab);
+
+ if (ab->qmi.target.bdf_ext[0] == '\0')
+ return -ENODATA;
+
+ return 0;
+}
+
static int ath12k_core_soc_create(struct ath12k_base *ab)
{
int ret;
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 3f5f0471f640..254eb42a85c5 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -11,6 +11,8 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/bitfield.h>
+#include <linux/dmi.h>
+#include <linux/ctype.h>
#include "qmi.h"
#include "htc.h"
#include "wmi.h"
@@ -32,6 +34,15 @@
/* Pending management packets threshold for dropping probe responses */
#define ATH12K_PRB_RSP_DROP_THRESHOLD ((ATH12K_TX_MGMT_TARGET_MAX_SUPPORT_WMI * 3) / 4)
+/* SMBIOS type containing Board Data File Name Extension */
+#define ATH12K_SMBIOS_BDF_EXT_TYPE 0xF8
+
+/* SMBIOS type structure length (excluding strings-set) */
+#define ATH12K_SMBIOS_BDF_EXT_LENGTH 0x9
+
+/* The magic used by QCA spec */
+#define ATH12K_SMBIOS_BDF_EXT_MAGIC "BDF_"
+
#define ATH12K_INVALID_HW_MAC_ID 0xFF
#define ATH12K_RX_RATE_TABLE_NUM 320
#define ATH12K_RX_RATE_TABLE_11AX_NUM 576
@@ -129,6 +140,13 @@ struct ath12k_ext_irq_grp {
struct net_device napi_ndev;
};
+struct ath12k_smbios_bdf {
+ struct dmi_header hdr;
+ u32 padding;
+ u8 bdf_enabled;
+ u8 bdf_ext[];
+} __packed;
+
#define HEHANDLE_CAP_PHYINFO_SIZE 3
#define HECAP_PHYINFO_SIZE 9
#define HECAP_MACINFO_SIZE 5
@@ -792,7 +810,8 @@ int ath12k_core_fetch_board_data_api_1(struct ath12k_base *ab,
int ath12k_core_fetch_bdf(struct ath12k_base *ath12k,
struct ath12k_board_data *bd);
void ath12k_core_free_bdf(struct ath12k_base *ab, struct ath12k_board_data *bd);
-
+int ath12k_core_check_dt(struct ath12k_base *ath12k);
+int ath12k_core_check_smbios(struct ath12k_base *ab);
void ath12k_core_halt(struct ath12k *ar);
int ath12k_core_resume(struct ath12k_base *ab);
int ath12k_core_suspend(struct ath12k_base *ab);
diff --git a/drivers/net/wireless/ath/ath12k/debug.c b/drivers/net/wireless/ath/ath12k/debug.c
index 67893923e010..45d33279e665 100644
--- a/drivers/net/wireless/ath/ath12k/debug.c
+++ b/drivers/net/wireless/ath/ath12k/debug.c
@@ -64,7 +64,7 @@ void __ath12k_dbg(struct ath12k_base *ab, enum ath12k_debug_mask mask,
vaf.va = &args;
if (ath12k_debug_mask & mask)
- dev_dbg(ab->dev, "%pV", &vaf);
+ dev_printk(KERN_DEBUG, ab->dev, "%pV", &vaf);
/* TODO: trace log */
diff --git a/drivers/net/wireless/ath/ath12k/dp_rx.c b/drivers/net/wireless/ath/ath12k/dp_rx.c
index 39ef3c0d2e65..54e0a09bf8dd 100644
--- a/drivers/net/wireless/ath/ath12k/dp_rx.c
+++ b/drivers/net/wireless/ath/ath12k/dp_rx.c
@@ -3526,23 +3526,13 @@ static int ath12k_dp_rx_h_null_q_desc(struct ath12k *ar, struct sk_buff *msdu,
struct sk_buff_head *msdu_list)
{
struct ath12k_base *ab = ar->ab;
- u16 msdu_len, peer_id;
+ u16 msdu_len;
struct hal_rx_desc *desc = (struct hal_rx_desc *)msdu->data;
u8 l3pad_bytes;
struct ath12k_skb_rxcb *rxcb = ATH12K_SKB_RXCB(msdu);
u32 hal_rx_desc_sz = ar->ab->hw_params->hal_desc_sz;
msdu_len = ath12k_dp_rx_h_msdu_len(ab, desc);
- peer_id = ath12k_dp_rx_h_peer_id(ab, desc);
-
- spin_lock(&ab->base_lock);
- if (!ath12k_peer_find_by_id(ab, peer_id)) {
- spin_unlock(&ab->base_lock);
- ath12k_dbg(ab, ATH12K_DBG_DATA, "invalid peer id received in wbm err pkt%d\n",
- peer_id);
- return -EINVAL;
- }
- spin_unlock(&ab->base_lock);
if (!rxcb->is_frag && ((msdu_len + hal_rx_desc_sz) > DP_RX_BUFFER_SIZE)) {
/* First buffer will be freed by the caller, so deduct it's length */
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index d4a2f82612b6..c092451f8580 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -4554,7 +4554,8 @@ static void ath12k_mac_copy_eht_ppe_thresh(struct ath12k_wmi_ppe_threshold_arg *
}
}
-static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap,
+static void ath12k_mac_copy_eht_cap(struct ath12k *ar,
+ struct ath12k_band_cap *band_cap,
struct ieee80211_he_cap_elem *he_cap_elem,
int iftype,
struct ieee80211_sta_eht_cap *eht_cap)
@@ -4562,6 +4563,10 @@ static void ath12k_mac_copy_eht_cap(struct ath12k_band_cap *band_cap,
struct ieee80211_eht_cap_elem_fixed *eht_cap_elem = &eht_cap->eht_cap_elem;
memset(eht_cap, 0, sizeof(struct ieee80211_sta_eht_cap));
+
+ if (!(test_bit(WMI_TLV_SERVICE_11BE, ar->ab->wmi_ab.svc_map)))
+ return;
+
eht_cap->has_eht = true;
memcpy(eht_cap_elem->mac_cap_info, band_cap->eht_cap_mac_info,
sizeof(eht_cap_elem->mac_cap_info));
@@ -4627,7 +4632,7 @@ static int ath12k_mac_copy_sband_iftype_data(struct ath12k *ar,
data[idx].he_6ghz_capa.capa =
ath12k_mac_setup_he_6ghz_cap(cap, band_cap);
}
- ath12k_mac_copy_eht_cap(band_cap, &he_cap->he_cap_elem, i,
+ ath12k_mac_copy_eht_cap(ar, band_cap, &he_cap->he_cap_elem, i,
&data[idx].eht_cap);
idx++;
}
@@ -5847,6 +5852,59 @@ static void ath12k_mac_op_remove_chanctx(struct ieee80211_hw *hw,
mutex_unlock(&ar->conf_mutex);
}
+static enum wmi_phy_mode
+ath12k_mac_check_down_grade_phy_mode(struct ath12k *ar,
+ enum wmi_phy_mode mode,
+ enum nl80211_band band,
+ enum nl80211_iftype type)
+{
+ struct ieee80211_sta_eht_cap *eht_cap;
+ enum wmi_phy_mode down_mode;
+
+ if (mode < MODE_11BE_EHT20)
+ return mode;
+
+ eht_cap = &ar->mac.iftype[band][type].eht_cap;
+ if (eht_cap->has_eht)
+ return mode;
+
+ switch (mode) {
+ case MODE_11BE_EHT20:
+ down_mode = MODE_11AX_HE20;
+ break;
+ case MODE_11BE_EHT40:
+ down_mode = MODE_11AX_HE40;
+ break;
+ case MODE_11BE_EHT80:
+ down_mode = MODE_11AX_HE80;
+ break;
+ case MODE_11BE_EHT80_80:
+ down_mode = MODE_11AX_HE80_80;
+ break;
+ case MODE_11BE_EHT160:
+ case MODE_11BE_EHT160_160:
+ case MODE_11BE_EHT320:
+ down_mode = MODE_11AX_HE160;
+ break;
+ case MODE_11BE_EHT20_2G:
+ down_mode = MODE_11AX_HE20_2G;
+ break;
+ case MODE_11BE_EHT40_2G:
+ down_mode = MODE_11AX_HE40_2G;
+ break;
+ default:
+ down_mode = mode;
+ break;
+ }
+
+ ath12k_dbg(ar->ab, ATH12K_DBG_MAC,
+ "mac vdev start phymode %s downgrade to %s\n",
+ ath12k_mac_phymode_str(mode),
+ ath12k_mac_phymode_str(down_mode));
+
+ return down_mode;
+}
+
static int
ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
struct ieee80211_chanctx_conf *ctx,
@@ -5873,6 +5931,9 @@ ath12k_mac_vdev_start_restart(struct ath12k_vif *arvif,
arg.band_center_freq2 = chandef->center_freq2;
arg.mode = ath12k_phymodes[chandef->chan->band][chandef->width];
+ arg.mode = ath12k_mac_check_down_grade_phy_mode(ar, arg.mode,
+ chandef->chan->band,
+ arvif->vif->type);
arg.min_power = 0;
arg.max_power = chandef->chan->max_power * 2;
arg.max_reg_power = chandef->chan->max_reg_power * 2;
diff --git a/drivers/net/wireless/ath/ath12k/mhi.c b/drivers/net/wireless/ath/ath12k/mhi.c
index 42f1140baa4f..f83d3e09ae36 100644
--- a/drivers/net/wireless/ath/ath12k/mhi.c
+++ b/drivers/net/wireless/ath/ath12k/mhi.c
@@ -370,8 +370,7 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci)
ret = ath12k_mhi_get_msi(ab_pci);
if (ret) {
ath12k_err(ab, "failed to get msi for mhi\n");
- mhi_free_controller(mhi_ctrl);
- return ret;
+ goto free_controller;
}
mhi_ctrl->iova_start = 0;
@@ -388,11 +387,15 @@ int ath12k_mhi_register(struct ath12k_pci *ab_pci)
ret = mhi_register_controller(mhi_ctrl, ab->hw_params->mhi_config);
if (ret) {
ath12k_err(ab, "failed to register to mhi bus, err = %d\n", ret);
- mhi_free_controller(mhi_ctrl);
- return ret;
+ goto free_controller;
}
return 0;
+
+free_controller:
+ mhi_free_controller(mhi_ctrl);
+ ab_pci->mhi_ctrl = NULL;
+ return ret;
}
void ath12k_mhi_unregister(struct ath12k_pci *ab_pci)
diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c
index b2db0436bdde..fd1bf53c2502 100644
--- a/drivers/net/wireless/ath/ath12k/qmi.c
+++ b/drivers/net/wireless/ath/ath12k/qmi.c
@@ -2213,6 +2213,7 @@ static int ath12k_qmi_request_target_cap(struct ath12k_base *ab)
struct qmi_txn txn = {};
unsigned int board_id = ATH12K_BOARD_ID_DEFAULT;
int ret = 0;
+ int r;
int i;
memset(&req, 0, sizeof(req));
@@ -2297,6 +2298,10 @@ static int ath12k_qmi_request_target_cap(struct ath12k_base *ab)
ab->qmi.target.fw_build_timestamp,
ab->qmi.target.fw_build_id);
+ r = ath12k_core_check_smbios(ab);
+ if (r)
+ ath12k_dbg(ab, ATH12K_DBG_QMI, "SMBIOS bdf variant name not set.\n");
+
out:
return ret;
}
diff --git a/drivers/net/wireless/ath/ath12k/wmi.h b/drivers/net/wireless/ath/ath12k/wmi.h
index 965755b4cbfd..629373d67421 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.h
+++ b/drivers/net/wireless/ath/ath12k/wmi.h
@@ -2158,6 +2158,9 @@ enum wmi_tlv_service {
WMI_MAX_EXT_SERVICE = 256,
WMI_TLV_SERVICE_REG_CC_EXT_EVENT_SUPPORT = 281,
+
+ WMI_TLV_SERVICE_11BE = 289,
+
WMI_MAX_EXT2_SERVICE,
};
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
index e4eb666c6eea..c4edf8355941 100644
--- a/drivers/net/wireless/ath/carl9170/usb.c
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -178,7 +178,7 @@ static void carl9170_usb_tx_data_complete(struct urb *urb)
switch (urb->status) {
/* everything is fine */
case 0:
- carl9170_tx_callback(ar, (void *)urb->context);
+ carl9170_tx_callback(ar, urb->context);
break;
/* disconnect */
@@ -369,7 +369,7 @@ void carl9170_usb_handle_tx_err(struct ar9170 *ar)
struct urb *urb;
while ((urb = usb_get_from_anchor(&ar->tx_err))) {
- struct sk_buff *skb = (void *)urb->context;
+ struct sk_buff *skb = urb->context;
carl9170_tx_drop(ar, skb);
carl9170_tx_callback(ar, skb);
@@ -397,7 +397,7 @@ static void carl9170_usb_tasklet(struct tasklet_struct *t)
static void carl9170_usb_rx_complete(struct urb *urb)
{
- struct ar9170 *ar = (struct ar9170 *)urb->context;
+ struct ar9170 *ar = urb->context;
int err;
if (WARN_ON_ONCE(!ar))
@@ -559,7 +559,7 @@ static int carl9170_usb_flush(struct ar9170 *ar)
int ret, err = 0;
while ((urb = usb_get_from_anchor(&ar->tx_wait))) {
- struct sk_buff *skb = (void *)urb->context;
+ struct sk_buff *skb = urb->context;
carl9170_tx_drop(ar, skb);
carl9170_tx_callback(ar, skb);
usb_free_urb(urb);
@@ -668,7 +668,7 @@ int carl9170_exec_cmd(struct ar9170 *ar, const enum carl9170_cmd_oids cmd,
memcpy(ar->cmd.data, payload, plen);
spin_lock_bh(&ar->cmd_lock);
- ar->readbuf = (u8 *)out;
+ ar->readbuf = out;
ar->readlen = outlen;
spin_unlock_bh(&ar->cmd_lock);
diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c
index 27f4d74a41c8..700da9f4531e 100644
--- a/drivers/net/wireless/ath/dfs_pattern_detector.c
+++ b/drivers/net/wireless/ath/dfs_pattern_detector.c
@@ -161,7 +161,7 @@ get_dfs_domain_radar_types(enum nl80211_dfs_regions region)
struct channel_detector {
struct list_head head;
u16 freq;
- struct pri_detector **detectors;
+ struct pri_detector *detectors[];
};
/* channel_detector_reset() - reset detector lines for a given channel */
@@ -183,14 +183,13 @@ static void channel_detector_exit(struct dfs_pattern_detector *dpd,
if (cd == NULL)
return;
list_del(&cd->head);
- if (cd->detectors) {
- for (i = 0; i < dpd->num_radar_types; i++) {
- struct pri_detector *de = cd->detectors[i];
- if (de != NULL)
- de->exit(de);
- }
+
+ for (i = 0; i < dpd->num_radar_types; i++) {
+ struct pri_detector *de = cd->detectors[i];
+ if (de != NULL)
+ de->exit(de);
}
- kfree(cd->detectors);
+
kfree(cd);
}
@@ -200,16 +199,12 @@ channel_detector_create(struct dfs_pattern_detector *dpd, u16 freq)
u32 i;
struct channel_detector *cd;
- cd = kmalloc(sizeof(*cd), GFP_ATOMIC);
+ cd = kzalloc(struct_size(cd, detectors, dpd->num_radar_types), GFP_ATOMIC);
if (cd == NULL)
goto fail;
INIT_LIST_HEAD(&cd->head);
cd->freq = freq;
- cd->detectors = kmalloc_array(dpd->num_radar_types,
- sizeof(*cd->detectors), GFP_ATOMIC);
- if (cd->detectors == NULL)
- goto fail;
for (i = 0; i < dpd->num_radar_types; i++) {
const struct radar_detector_specs *rs = &dpd->radar_spec[i];