summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/ath/ath12k
diff options
context:
space:
mode:
authorKalle Valo <kvalo@kernel.org>2023-10-09 09:45:08 +0300
committerKalle Valo <kvalo@kernel.org>2023-10-09 09:45:08 +0300
commit164f1842d993e75925a68461722bf8130cbbe1b0 (patch)
tree7bb4a80c06108b3184c00e423baa2d344ecc186c /drivers/net/wireless/ath/ath12k
parent089482a06b74a40d45773b1871182e8f04be026b (diff)
parent453a62a3ee65aeba6e69bfd09227fc2f19290bea (diff)
Merge ath-next from git://git.kernel.org/pub/scm/linux/kernel/git/kvalo/ath.git
ath.git patches for v6.7. Major changes: ath12k * read board data variant name from SMBIOS
Diffstat (limited to 'drivers/net/wireless/ath/ath12k')
-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
8 files changed, 169 insertions, 19 deletions
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,
};