mirror of
https://github.com/Telecominfraproject/wlan-ap.git
synced 2025-12-20 10:51:27 +00:00
435 lines
13 KiB
Diff
435 lines
13 KiB
Diff
From 143b11a194c50b6666983c0f8d0bbd6bb64404eb Mon Sep 17 00:00:00 2001
|
|
From: Karthik M <quic_karm@quicinc.com>
|
|
Date: Tue, 9 Aug 2022 22:10:12 +0530
|
|
Subject: [PATCH] ath12k: Encoding regdb.bin in board-2.bin
|
|
|
|
Add support to encode regdb.bin in board-2.bin along with the bdf files.
|
|
|
|
Check Regdb.bin file in board-2.bin first. If its not found, check in
|
|
the firmware location of the chip.
|
|
|
|
Signed-off-by: Karthik M <quic_karm@quicinc.com>
|
|
---
|
|
drivers/net/wireless/ath/ath12k/core.c | 2 +-
|
|
drivers/net/wireless/ath/ath12k/core.h | 3 +++
|
|
drivers/net/wireless/ath/ath12k/qmi.c | 16 ++++++++++++----
|
|
3 files changed, 16 insertions(+), 5 deletions(-)
|
|
|
|
--- a/drivers/net/wireless/ath/ath12k/core.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/core.c
|
|
@@ -325,7 +325,7 @@ int ath12k_core_check_dt(struct ath12k_b
|
|
}
|
|
|
|
static int ath12k_core_create_board_name(struct ath12k_base *ab, char *name,
|
|
- size_t name_len)
|
|
+ char *defaultname, size_t name_len)
|
|
{
|
|
/* strlen(',variant=') + strlen(ab->qmi.target.bdf_ext) */
|
|
char variant[9 + ATH12K_QMI_BDF_EXT_STR_LENGTH] = { 0 };
|
|
@@ -333,12 +333,33 @@ static int ath12k_core_create_board_name
|
|
if (ab->qmi.target.bdf_ext[0] != '\0')
|
|
scnprintf(variant, sizeof(variant), ",variant=%s",
|
|
ab->qmi.target.bdf_ext);
|
|
-
|
|
- scnprintf(name, name_len,
|
|
- "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s",
|
|
- ath12k_bus_str(ab->hif.bus),
|
|
- ab->qmi.target.chip_id,
|
|
- ab->qmi.target.board_id, variant);
|
|
+ switch (ab->id.bdf_search) {
|
|
+ case ATH12K_BDF_SEARCH_BUS_AND_BOARD:
|
|
+ scnprintf(name, name_len,
|
|
+ "bus=%s,vendor=%04x,device=%04x,subsystem-vendor=%04x,"
|
|
+ "subsystem-device=%04x,qmi-chip-id=%d,qmi-board-id=%d%s",
|
|
+ ath12k_bus_str(ab->hif.bus),
|
|
+ ab->id.vendor, ab->id.device,
|
|
+ ab->id.subsystem_vendor,
|
|
+ ab->id.subsystem_device,
|
|
+ ab->qmi.target.chip_id,
|
|
+ ab->qmi.target.board_id,
|
|
+ variant);
|
|
+ break;
|
|
+ default:
|
|
+ scnprintf(name, name_len,
|
|
+ "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s",
|
|
+ ath12k_bus_str(ab->hif.bus),
|
|
+ ab->qmi.target.chip_id,
|
|
+ ab->qmi.target.board_id, variant);
|
|
+
|
|
+ scnprintf(defaultname, name_len,
|
|
+ "bus=%s,qmi-chip-id=%d,qmi-board-id=%d%s",
|
|
+ ath12k_bus_str(ab->hif.bus),
|
|
+ ab->qmi.target.chip_id,
|
|
+ ATH12K_DEFAULT_ID, variant);
|
|
+ break;
|
|
+ }
|
|
|
|
ath12k_dbg(ab, ATH12K_DBG_BOOT, "boot using board name '%s'\n", name);
|
|
|
|
@@ -379,7 +400,9 @@ static int ath12k_core_parse_bd_ie_board
|
|
struct ath12k_board_data *bd,
|
|
const void *buf, size_t buf_len,
|
|
const char *boardname,
|
|
- int bd_ie_type)
|
|
+ int ie_id,
|
|
+ int name_id,
|
|
+ int data_id)
|
|
{
|
|
const struct ath12k_fw_ie *hdr;
|
|
bool name_match_found;
|
|
@@ -389,7 +412,7 @@ static int ath12k_core_parse_bd_ie_board
|
|
|
|
name_match_found = false;
|
|
|
|
- /* go through ATH12K_BD_IE_BOARD_ elements */
|
|
+ /* go through ATH12K_BD_IE_BOARD_/ATH12K_BD_IE_REGDB_ elements */
|
|
while (buf_len > sizeof(struct ath12k_fw_ie)) {
|
|
hdr = buf;
|
|
board_ie_id = le32_to_cpu(hdr->id);
|
|
@@ -400,48 +423,51 @@ static int ath12k_core_parse_bd_ie_board
|
|
buf += sizeof(*hdr);
|
|
|
|
if (buf_len < ALIGN(board_ie_len, 4)) {
|
|
- ath12k_err(ab, "invalid ATH12K_BD_IE_BOARD length: %zu < %zu\n",
|
|
- buf_len, ALIGN(board_ie_len, 4));
|
|
+ ath12k_err(ab, "invalid %s length: %zu < %zu\n",
|
|
+ ath12k_bd_ie_type_str(ie_id),
|
|
+ buf_len, ALIGN(board_ie_len, 4));
|
|
ret = -EINVAL;
|
|
goto out;
|
|
}
|
|
|
|
- switch (board_ie_id) {
|
|
- case ATH12K_BD_IE_BOARD_NAME:
|
|
+ if (board_ie_id == name_id) {
|
|
ath12k_dbg_dump(ab, ATH12K_DBG_BOOT, "board name", "",
|
|
board_ie_data, board_ie_len);
|
|
|
|
if (board_ie_len != strlen(boardname))
|
|
- break;
|
|
+ goto next;
|
|
|
|
ret = memcmp(board_ie_data, boardname, strlen(boardname));
|
|
if (ret)
|
|
- break;
|
|
+ goto next;
|
|
|
|
name_match_found = true;
|
|
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
|
- "boot found match for name '%s'",
|
|
+ "boot found match %s for name '%s'",
|
|
+ ath12k_bd_ie_type_str(ie_id),
|
|
boardname);
|
|
- break;
|
|
- case ATH12K_BD_IE_BOARD_DATA:
|
|
+ } else if (board_ie_id == data_id) {
|
|
if (!name_match_found)
|
|
/* no match found */
|
|
- break;
|
|
+ goto next;
|
|
|
|
ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
|
- "boot found board data for '%s'", boardname);
|
|
+ "boot found %s for '%s'",
|
|
+ ath12k_bd_ie_type_str(ie_id),
|
|
+ boardname);
|
|
|
|
bd->data = board_ie_data;
|
|
bd->len = board_ie_len;
|
|
|
|
ret = 0;
|
|
goto out;
|
|
- default:
|
|
- ath12k_warn(ab, "unknown ATH12K_BD_IE_BOARD found: %d\n",
|
|
- board_ie_id);
|
|
- break;
|
|
+ } else {
|
|
+ ath12k_warn(ab, "unknown %s id found: %d\n",
|
|
+ ath12k_bd_ie_type_str(ie_id),
|
|
+ board_ie_id);
|
|
}
|
|
|
|
+next:
|
|
/* jump over the padding */
|
|
board_ie_len = ALIGN(board_ie_len, 4);
|
|
|
|
@@ -457,8 +483,11 @@ out:
|
|
}
|
|
|
|
static int ath12k_core_fetch_board_data_api_n(struct ath12k_base *ab,
|
|
- struct ath12k_board_data *bd,
|
|
- const char *boardname)
|
|
+ struct ath12k_board_data *bd,
|
|
+ const char *boardname,
|
|
+ int ie_id_match,
|
|
+ int name_id,
|
|
+ int data_id)
|
|
{
|
|
size_t len, magic_len;
|
|
const u8 *data;
|
|
@@ -523,15 +552,16 @@ static int ath12k_core_fetch_board_data_
|
|
goto err;
|
|
}
|
|
|
|
- switch (ie_id) {
|
|
- case ATH12K_BD_IE_BOARD:
|
|
+ if (ie_id == ie_id_match) {
|
|
ret = ath12k_core_parse_bd_ie_board(ab, bd, data,
|
|
ie_len,
|
|
boardname,
|
|
- ATH12K_BD_IE_BOARD);
|
|
+ ie_id_match,
|
|
+ name_id,
|
|
+ data_id);
|
|
if (ret == -ENOENT)
|
|
/* no match found, continue */
|
|
- break;
|
|
+ goto next;
|
|
else if (ret)
|
|
/* there was an error, bail out */
|
|
goto err;
|
|
@@ -539,6 +569,7 @@ static int ath12k_core_fetch_board_data_
|
|
goto out;
|
|
}
|
|
|
|
+next:
|
|
/* jump over the padding */
|
|
ie_len = ALIGN(ie_len, 4);
|
|
|
|
@@ -548,9 +579,10 @@ static int ath12k_core_fetch_board_data_
|
|
|
|
out:
|
|
if (!bd->data || !bd->len) {
|
|
- ath12k_err(ab,
|
|
- "failed to fetch board data for %s from %s\n",
|
|
- boardname, filepath);
|
|
+ ath12k_dbg(ab, ATH12K_DBG_BOOT,
|
|
+ "failed to fetch %s for %s from %s\n",
|
|
+ ath12k_bd_ie_type_str(ie_id_match),
|
|
+ boardname, filepath);
|
|
ret = -ENODATA;
|
|
goto err;
|
|
}
|
|
@@ -567,6 +599,7 @@ int ath12k_core_fetch_board_data_api_1(s
|
|
char *filename)
|
|
{
|
|
bd->fw = ath12k_core_firmware_request(ab, filename);
|
|
+
|
|
if (IS_ERR(bd->fw))
|
|
return PTR_ERR(bd->fw);
|
|
|
|
@@ -576,28 +609,43 @@ int ath12k_core_fetch_board_data_api_1(s
|
|
return 0;
|
|
}
|
|
|
|
-#define BOARD_NAME_SIZE 100
|
|
int ath12k_core_fetch_bdf(struct ath12k_base *ab, struct ath12k_board_data *bd)
|
|
{
|
|
- char boardname[BOARD_NAME_SIZE];
|
|
+ char boardname[BOARD_NAME_SIZE], boarddefaultname[BOARD_NAME_SIZE];
|
|
int ret;
|
|
|
|
- ret = ath12k_core_create_board_name(ab, boardname, BOARD_NAME_SIZE);
|
|
+ ret = ath12k_core_create_board_name(ab, boardname, boarddefaultname,
|
|
+ BOARD_NAME_SIZE);
|
|
if (ret) {
|
|
ath12k_err(ab, "failed to create board name: %d", ret);
|
|
return ret;
|
|
}
|
|
|
|
ab->bd_api = 2;
|
|
- ret = ath12k_core_fetch_board_data_api_n(ab, bd, boardname);
|
|
+ ret = ath12k_core_fetch_board_data_api_n(ab, bd, boardname,
|
|
+ ATH12K_BD_IE_BOARD,
|
|
+ ATH12K_BD_IE_BOARD_NAME,
|
|
+ ATH12K_BD_IE_BOARD_DATA);
|
|
+ if (!ret)
|
|
+ goto success;
|
|
+
|
|
+ ret = ath12k_core_fetch_board_data_api_n(ab, bd, boarddefaultname,
|
|
+ ATH12K_BD_IE_BOARD,
|
|
+ ATH12K_BD_IE_BOARD_NAME,
|
|
+ ATH12K_BD_IE_BOARD_DATA);
|
|
if (!ret)
|
|
goto success;
|
|
|
|
ab->bd_api = 1;
|
|
ret = ath12k_core_fetch_board_data_api_1(ab, bd, ATH12K_DEFAULT_BOARD_FILE);
|
|
if (ret) {
|
|
- ath12k_err(ab, "failed to fetch board-2.bin or board.bin from %s\n",
|
|
+ ath12k_err(ab, "failed to fetch board-2.bin from %s\n",
|
|
ab->hw_params->fw.dir);
|
|
+ } else {
|
|
+ ret = ath12k_core_fetch_board_data_api_1(ab, bd, ATH12K_BOARD_API2_FILE);
|
|
+ if (ret)
|
|
+ ath12k_err(ab, "failed to fetch board-2.bin from %s\n",
|
|
+ ab->hw_params->fw.dir);
|
|
return ret;
|
|
}
|
|
|
|
@@ -606,6 +654,45 @@ success:
|
|
return 0;
|
|
}
|
|
|
|
+int ath12k_core_fetch_regdb(struct ath12k_base *ab, struct ath12k_board_data *bd)
|
|
+{
|
|
+ char regdbname[REGDB_NAME_SIZE], regdbdefaultname[REGDB_NAME_SIZE];
|
|
+ int ret;
|
|
+
|
|
+ ret = ath12k_core_create_board_name(ab, regdbname, regdbdefaultname,
|
|
+ REGDB_NAME_SIZE);
|
|
+ if (ret) {
|
|
+ ath12k_err(ab, "failed to create regdb name: %d", ret);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+ ab->bd_api = 2;
|
|
+ ret = ath12k_core_fetch_board_data_api_n(ab, bd, regdbname,
|
|
+ ATH12K_BD_IE_REGDB,
|
|
+ ATH12K_BD_IE_REGDB_NAME,
|
|
+ ATH12K_BD_IE_REGDB_DATA);
|
|
+ if (!ret)
|
|
+ goto success;
|
|
+
|
|
+ ret = ath12k_core_fetch_board_data_api_n(ab, bd, regdbdefaultname,
|
|
+ ATH12K_BD_IE_REGDB,
|
|
+ ATH12K_BD_IE_REGDB_NAME,
|
|
+ ATH12K_BD_IE_REGDB_DATA);
|
|
+ if (!ret)
|
|
+ goto success;
|
|
+
|
|
+ ab->bd_api = 1;
|
|
+ ret = ath12k_core_fetch_board_data_api_1(ab, bd, ATH12K_REGDB_FILE_NAME);
|
|
+ if (ret) {
|
|
+ ath12k_err(ab, "failed to fetch %s file from %s\n",
|
|
+ ATH12K_REGDB_FILE_NAME, ab->hw_params->fw.dir);
|
|
+ return ret;
|
|
+ }
|
|
+
|
|
+success:
|
|
+ ath12k_dbg(ab, ATH12K_DBG_BOOT, "using board api %d\n", ab->bd_api);
|
|
+ return 0;
|
|
+}
|
|
static void ath12k_core_stop(struct ath12k_base *ab)
|
|
{
|
|
lockdep_assert_held(&ab->ag->mutex_lock);
|
|
--- a/drivers/net/wireless/ath/ath12k/core.h
|
|
+++ b/drivers/net/wireless/ath/ath12k/core.h
|
|
@@ -60,6 +60,11 @@ enum ath12k_supported_bw {
|
|
ATH12K_BW_320 = 4,
|
|
};
|
|
|
|
+enum ath12k_bdf_search {
|
|
+ ATH12K_BDF_SEARCH_DEFAULT,
|
|
+ ATH12K_BDF_SEARCH_BUS_AND_BOARD,
|
|
+};
|
|
+
|
|
enum wme_ac {
|
|
WME_AC_BE,
|
|
WME_AC_BK,
|
|
@@ -853,6 +858,9 @@ struct ath12k_pdev {
|
|
struct mlo_timestamp timestamp;
|
|
};
|
|
|
|
+#define BOARD_NAME_SIZE 100
|
|
+#define REGDB_NAME_SIZE 100
|
|
+
|
|
struct ath12k_board_data {
|
|
const struct firmware *fw;
|
|
const void *data;
|
|
@@ -913,6 +921,13 @@ struct ath12k_reg_freq {
|
|
u32 end_freq;
|
|
};
|
|
|
|
+struct vendor_info {
|
|
+ enum ath12k_bdf_search bdf_search;
|
|
+ u32 vendor;
|
|
+ u32 device;
|
|
+ u32 subsystem_vendor;
|
|
+ u32 subsystem_device;
|
|
+};
|
|
|
|
struct ath12k_hw {
|
|
struct ieee80211_hw *hw;
|
|
@@ -1058,6 +1073,8 @@ struct ath12k_base {
|
|
bool stats_disable;
|
|
u32 rx_hash;
|
|
|
|
+ struct vendor_info id;
|
|
+
|
|
/* must be last */
|
|
u8 drv_priv[0] __aligned(sizeof(void *));
|
|
};
|
|
@@ -1198,6 +1215,8 @@ int ath12k_core_fetch_board_data_api_1(s
|
|
char *filename);
|
|
int ath12k_core_fetch_bdf(struct ath12k_base *ath12k,
|
|
struct ath12k_board_data *bd);
|
|
+int ath12k_core_fetch_regdb(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);
|
|
|
|
--- a/drivers/net/wireless/ath/ath12k/qmi.c
|
|
+++ b/drivers/net/wireless/ath/ath12k/qmi.c
|
|
@@ -3441,12 +3441,12 @@ static int ath12k_qmi_load_bdf_qmi(struc
|
|
|
|
break;
|
|
case ATH12K_QMI_BDF_TYPE_REGDB:
|
|
- ret = ath12k_core_fetch_board_data_api_1(ab, &bd,
|
|
- ATH12K_REGDB_FILE_NAME);
|
|
+ ret = ath12k_core_fetch_regdb(ab, &bd);
|
|
if (ret) {
|
|
- ath12k_warn(ab, "qmi failed to load regdb bin:\n");
|
|
+ ath12k_warn(ab, "qmi failed to load regdb:\n");
|
|
goto out;
|
|
}
|
|
+ type = ATH12K_QMI_BDF_TYPE_REGDB;
|
|
break;
|
|
default:
|
|
ath12k_warn(ab, "unknown file type for load %d", type);
|
|
--- a/drivers/net/wireless/ath/ath12k/hw.h
|
|
+++ b/drivers/net/wireless/ath/ath12k/hw.h
|
|
@@ -84,6 +84,8 @@
|
|
#define ATH12K_AMSS_FILE "amss.bin"
|
|
#define ATH12K_M3_FILE "m3.bin"
|
|
#define ATH12K_REGDB_FILE_NAME "regdb.bin"
|
|
+#define ATH12K_REGDB_BINARY "regdb"
|
|
+#define ATH12K_DEFAULT_ID 255
|
|
|
|
enum ath12k_hw_rate_cck {
|
|
ATH12K_HW_RATE_CCK_LP_11M = 0,
|
|
@@ -255,12 +257,32 @@ enum ath12k_bd_ie_board_type {
|
|
ATH12K_BD_IE_BOARD_DATA = 1,
|
|
};
|
|
|
|
+enum ath12k_bd_ie_regdb_type {
|
|
+ ATH12K_BD_IE_REGDB_NAME = 0,
|
|
+ ATH12K_BD_IE_REGDB_DATA = 1,
|
|
+};
|
|
+
|
|
enum ath12k_bd_ie_type {
|
|
/* contains sub IEs of enum ath12k_bd_ie_board_type */
|
|
ATH12K_BD_IE_BOARD = 0,
|
|
- ATH12K_BD_IE_BOARD_EXT = 1,
|
|
+ ATH12K_BD_IE_REGDB = 1,
|
|
+ ATH12K_BD_IE_BOARD_EXT = 2,
|
|
};
|
|
|
|
+static inline const char *ath12k_bd_ie_type_str(enum ath12k_bd_ie_type type)
|
|
+{
|
|
+ switch (type) {
|
|
+ case ATH12K_BD_IE_BOARD:
|
|
+ return "board data";
|
|
+ case ATH12K_BD_IE_REGDB:
|
|
+ return "regdb data";
|
|
+ case ATH12K_BD_IE_BOARD_EXT:
|
|
+ return "board data ext";
|
|
+ }
|
|
+
|
|
+ return "unknown";
|
|
+}
|
|
+
|
|
struct ath12k_hw_regs {
|
|
u32 hal_tcl1_ring_id;
|
|
u32 hal_tcl1_ring_misc;
|