From 143b11a194c50b6666983c0f8d0bbd6bb64404eb Mon Sep 17 00:00:00 2001 From: Karthik M 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 --- 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;