diff options
56 files changed, 2674 insertions, 515 deletions
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index 579b9306f533..fbec6dd551d6 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -1820,6 +1820,10 @@ brcmf_set_key_mgmt(struct net_device *ndev, struct cfg80211_connect_params *sme) switch (sme->crypto.akm_suites[0]) { case WLAN_AKM_SUITE_SAE: val = WPA3_AUTH_SAE_PSK; + if (sme->crypto.sae_pwd) { + brcmf_dbg(INFO, "using SAE offload\n"); + profile->use_fwsup = BRCMF_PROFILE_FWSUP_SAE; + } break; default: bphy_err(drvr, "invalid cipher group (%d)\n", @@ -2105,11 +2109,6 @@ brcmf_cfg80211_connect(struct wiphy *wiphy, struct net_device *ndev, goto done; } - if (sme->crypto.sae_pwd) { - brcmf_dbg(INFO, "using SAE offload\n"); - profile->use_fwsup = BRCMF_PROFILE_FWSUP_SAE; - } - if (sme->crypto.psk && profile->use_fwsup != BRCMF_PROFILE_FWSUP_SAE) { if (WARN_ON(profile->use_fwsup != BRCMF_PROFILE_FWSUP_NONE)) { @@ -5548,7 +5547,8 @@ static bool brcmf_is_linkup(struct brcmf_cfg80211_vif *vif, u32 event = e->event_code; u32 status = e->status; - if (vif->profile.use_fwsup == BRCMF_PROFILE_FWSUP_PSK && + if ((vif->profile.use_fwsup == BRCMF_PROFILE_FWSUP_PSK || + vif->profile.use_fwsup == BRCMF_PROFILE_FWSUP_SAE) && event == BRCMF_E_PSK_SUP && status == BRCMF_E_STATUS_FWSUP_COMPLETED) set_bit(BRCMF_VIF_STATUS_EAP_SUCCESS, &vif->sme_state); diff --git a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c index 2f741f5e3a7d..1daa653bcb99 100644 --- a/drivers/net/wireless/intel/iwlwifi/cfg/22000.c +++ b/drivers/net/wireless/intel/iwlwifi/cfg/22000.c @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2019 Intel Corporation + * Copyright (C) 2018-2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -20,7 +20,7 @@ * BSD LICENSE * * Copyright(c) 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2019 Intel Corporation + * Copyright (C) 2018-2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -57,7 +57,7 @@ #include "iwl-prph.h" /* Highest firmware API version supported */ -#define IWL_22000_UCODE_API_MAX 53 +#define IWL_22000_UCODE_API_MAX 55 /* Lowest firmware API version supported */ #define IWL_22000_UCODE_API_MIN 39 @@ -73,11 +73,8 @@ #define IWL_22000_SMEM_OFFSET 0x400000 #define IWL_22000_SMEM_LEN 0xD0000 -#define IWL_22000_JF_FW_PRE "iwlwifi-Qu-a0-jf-b0-" -#define IWL_22000_HR_FW_PRE "iwlwifi-Qu-a0-hr-a0-" -#define IWL_22000_HR_CDB_FW_PRE "iwlwifi-QuIcp-z0-hrcdb-a0-" -#define IWL_22000_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-" -#define IWL_22000_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-" +#define IWL_QU_B_HR_B_FW_PRE "iwlwifi-Qu-b0-hr-b0-" +#define IWL_QNJ_B_HR_B_FW_PRE "iwlwifi-QuQnj-b0-hr-b0-" #define IWL_QU_C_HR_B_FW_PRE "iwlwifi-Qu-c0-hr-b0-" #define IWL_QU_B_JF_B_FW_PRE "iwlwifi-Qu-b0-jf-b0-" #define IWL_QU_C_JF_B_FW_PRE "iwlwifi-Qu-c0-jf-b0-" @@ -85,22 +82,18 @@ #define IWL_QUZ_A_JF_B_FW_PRE "iwlwifi-QuZ-a0-jf-b0-" #define IWL_QNJ_B_JF_B_FW_PRE "iwlwifi-QuQnj-b0-jf-b0-" #define IWL_CC_A_FW_PRE "iwlwifi-cc-a0-" -#define IWL_22000_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0-" -#define IWL_22000_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0-" -#define IWL_22000_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0-" -#define IWL_22000_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0-" -#define IWL_22000_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0-" +#define IWL_SO_A_JF_B_FW_PRE "iwlwifi-so-a0-jf-b0-" +#define IWL_SO_A_HR_B_FW_PRE "iwlwifi-so-a0-hr-b0-" +#define IWL_SO_A_GF_A_FW_PRE "iwlwifi-so-a0-gf-a0-" +#define IWL_TY_A_GF_A_FW_PRE "iwlwifi-ty-a0-gf-a0-" +#define IWL_SO_A_GF4_A_FW_PRE "iwlwifi-so-a0-gf4-a0-" #define IWL_SNJ_A_GF4_A_FW_PRE "iwlwifi-SoSnj-a0-gf4-a0-" #define IWL_SNJ_A_GF_A_FW_PRE "iwlwifi-SoSnj-a0-gf-a0-" -#define IWL_22000_HR_MODULE_FIRMWARE(api) \ - IWL_22000_HR_FW_PRE __stringify(api) ".ucode" -#define IWL_22000_JF_MODULE_FIRMWARE(api) \ - IWL_22000_JF_FW_PRE __stringify(api) ".ucode" -#define IWL_22000_QU_B_HR_B_MODULE_FIRMWARE(api) \ - IWL_22000_QU_B_HR_B_FW_PRE __stringify(api) ".ucode" -#define IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(api) \ - IWL_22000_HR_B_FW_PRE __stringify(api) ".ucode" +#define IWL_QU_B_HR_B_MODULE_FIRMWARE(api) \ + IWL_QU_B_HR_B_FW_PRE __stringify(api) ".ucode" +#define IWL_QNJ_B_HR_B_MODULE_FIRMWARE(api) \ + IWL_QNJ_B_HR_B_FW_PRE __stringify(api) ".ucode" #define IWL_QUZ_A_HR_B_MODULE_FIRMWARE(api) \ IWL_QUZ_A_HR_B_FW_PRE __stringify(api) ".ucode" #define IWL_QUZ_A_JF_B_MODULE_FIRMWARE(api) \ @@ -113,14 +106,14 @@ IWL_QNJ_B_JF_B_FW_PRE __stringify(api) ".ucode" #define IWL_CC_A_MODULE_FIRMWARE(api) \ IWL_CC_A_FW_PRE __stringify(api) ".ucode" -#define IWL_22000_SO_A_JF_B_MODULE_FIRMWARE(api) \ - IWL_22000_SO_A_JF_B_FW_PRE __stringify(api) ".ucode" -#define IWL_22000_SO_A_HR_B_MODULE_FIRMWARE(api) \ - IWL_22000_SO_A_HR_B_FW_PRE __stringify(api) ".ucode" -#define IWL_22000_SO_A_GF_A_MODULE_FIRMWARE(api) \ - IWL_22000_SO_A_GF_A_FW_PRE __stringify(api) ".ucode" -#define IWL_22000_TY_A_GF_A_MODULE_FIRMWARE(api) \ - IWL_22000_TY_A_GF_A_FW_PRE __stringify(api) ".ucode" +#define IWL_SO_A_JF_B_MODULE_FIRMWARE(api) \ + IWL_SO_A_JF_B_FW_PRE __stringify(api) ".ucode" +#define IWL_SO_A_HR_B_MODULE_FIRMWARE(api) \ + IWL_SO_A_HR_B_FW_PRE __stringify(api) ".ucode" +#define IWL_SO_A_GF_A_MODULE_FIRMWARE(api) \ + IWL_SO_A_GF_A_FW_PRE __stringify(api) ".ucode" +#define IWL_TY_A_GF_A_MODULE_FIRMWARE(api) \ + IWL_TY_A_GF_A_FW_PRE __stringify(api) ".ucode" #define IWL_SNJ_A_GF4_A_MODULE_FIRMWARE(api) \ IWL_SNJ_A_GF4_A_FW_PRE __stringify(api) ".ucode" #define IWL_SNJ_A_GF_A_MODULE_FIRMWARE(api) \ @@ -218,7 +211,7 @@ static const struct iwl_ht_params iwl_22000_ht_params = { .trans.base_params = &iwl_ax210_base_params, \ .min_txq_size = 128, \ .gp2_reg_addr = 0xd02c68, \ - .min_256_ba_txq_size = 512, \ + .min_256_ba_txq_size = 1024, \ .mon_dram_regs = { \ .write_ptr = { \ .addr = DBGC_CUR_DBGBUF_STATUS, \ @@ -343,15 +336,16 @@ const struct iwl_cfg_trans_params iwl_ax200_trans_cfg = { }; const char iwl_ax200_name[] = "Intel(R) Wi-Fi 6 AX200 160MHz"; +const char iwl_ax201_name[] = "Intel(R) Wi-Fi 6 AX201 160MHz"; +const char iwl_ax101_name[] = "Intel(R) Wi-Fi 6 AX101"; const char iwl_ax200_killer_1650w_name[] = "Killer(R) Wi-Fi 6 AX1650w 160MHz Wireless Network Adapter (200D2W)"; const char iwl_ax200_killer_1650x_name[] = "Killer(R) Wi-Fi 6 AX1650x 160MHz Wireless Network Adapter (200NGW)"; -const struct iwl_cfg iwl_ax101_cfg_qu_hr = { - .name = "Intel(R) Wi-Fi 6 AX101", - .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE, +const struct iwl_cfg iwl_qu_b0_hr1_b0 = { + .fw_name_pre = IWL_QU_B_HR_B_FW_PRE, IWL_DEVICE_22500, /* * This device doesn't support receiving BlockAck with a large bitmap @@ -365,7 +359,7 @@ const struct iwl_cfg iwl_ax101_cfg_qu_hr = { const struct iwl_cfg iwl_ax201_cfg_qu_hr = { .name = "Intel(R) Wi-Fi 6 AX201 160MHz", - .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE, + .fw_name_pre = IWL_QU_B_HR_B_FW_PRE, IWL_DEVICE_22500, /* * This device doesn't support receiving BlockAck with a large bitmap @@ -376,8 +370,7 @@ const struct iwl_cfg iwl_ax201_cfg_qu_hr = { .num_rbds = IWL_NUM_RBDS_22000_HE, }; -const struct iwl_cfg iwl_ax101_cfg_qu_c0_hr_b0 = { - .name = "Intel(R) Wi-Fi 6 AX101", +const struct iwl_cfg iwl_qu_c0_hr1_b0 = { .fw_name_pre = IWL_QU_C_HR_B_FW_PRE, IWL_DEVICE_22500, /* @@ -403,8 +396,7 @@ const struct iwl_cfg iwl_ax201_cfg_qu_c0_hr_b0 = { .num_rbds = IWL_NUM_RBDS_22000_HE, }; -const struct iwl_cfg iwl_ax101_cfg_quz_hr = { - .name = "Intel(R) Wi-Fi 6 AX101", +const struct iwl_cfg iwl_quz_a0_hr1_b0 = { .fw_name_pre = IWL_QUZ_A_HR_B_FW_PRE, IWL_DEVICE_22500, /* @@ -470,7 +462,7 @@ const struct iwl_cfg iwl_ax200_cfg_cc = { const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = { .name = "Killer(R) Wi-Fi 6 AX1650i 160MHz Wireless Network Adapter (201NGW)", - .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE, + .fw_name_pre = IWL_QU_B_HR_B_FW_PRE, IWL_DEVICE_22500, /* * This device doesn't support receiving BlockAck with a large bitmap @@ -483,7 +475,7 @@ const struct iwl_cfg killer1650s_2ax_cfg_qu_b0_hr_b0 = { const struct iwl_cfg killer1650i_2ax_cfg_qu_b0_hr_b0 = { .name = "Killer(R) Wi-Fi 6 AX1650s 160MHz Wireless Network Adapter (201D2W)", - .fw_name_pre = IWL_22000_QU_B_HR_B_FW_PRE, + .fw_name_pre = IWL_QU_B_HR_B_FW_PRE, IWL_DEVICE_22500, /* * This device doesn't support receiving BlockAck with a large bitmap @@ -520,9 +512,8 @@ const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0 = { .num_rbds = IWL_NUM_RBDS_22000_HE, }; -const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0 = { - .name = "Intel(R) Dual Band Wireless AX 22000", - .fw_name_pre = IWL_22000_HR_B_FW_PRE, +const struct iwl_cfg iwl_qnj_b0_hr_b0_cfg = { + .fw_name_pre = IWL_QNJ_B_HR_B_FW_PRE, IWL_DEVICE_22500, /* * This device doesn't support receiving BlockAck with a large bitmap @@ -535,21 +526,21 @@ const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0 = { const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0 = { .name = "Intel(R) Wireless-AC 9560 160MHz", - .fw_name_pre = IWL_22000_SO_A_JF_B_FW_PRE, + .fw_name_pre = IWL_SO_A_JF_B_FW_PRE, IWL_DEVICE_AX210, .num_rbds = IWL_NUM_RBDS_NON_HE, }; const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0 = { .name = "Intel(R) Wi-Fi 6 AX210 160MHz", - .fw_name_pre = IWL_22000_SO_A_HR_B_FW_PRE, + .fw_name_pre = IWL_SO_A_HR_B_FW_PRE, IWL_DEVICE_AX210, .num_rbds = IWL_NUM_RBDS_AX210_HE, }; const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = { .name = "Intel(R) Wi-Fi 6 AX211 160MHz", - .fw_name_pre = IWL_22000_SO_A_GF_A_FW_PRE, + .fw_name_pre = IWL_SO_A_GF_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_AX210, .num_rbds = IWL_NUM_RBDS_AX210_HE, @@ -557,7 +548,7 @@ const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0 = { const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long = { .name = "Intel(R) Wi-Fi 6 AX211 160MHz", - .fw_name_pre = IWL_22000_SO_A_GF_A_FW_PRE, + .fw_name_pre = IWL_SO_A_GF_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_AX210, .num_rbds = IWL_NUM_RBDS_AX210_HE, @@ -567,7 +558,7 @@ const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0_long = { const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = { .name = "Intel(R) Wi-Fi 6 AX210 160MHz", - .fw_name_pre = IWL_22000_TY_A_GF_A_FW_PRE, + .fw_name_pre = IWL_TY_A_GF_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_AX210, .num_rbds = IWL_NUM_RBDS_AX210_HE, @@ -575,7 +566,7 @@ const struct iwl_cfg iwlax210_2ax_cfg_ty_gf_a0 = { const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = { .name = "Intel(R) Wi-Fi 6 AX411 160MHz", - .fw_name_pre = IWL_22000_SO_A_GF4_A_FW_PRE, + .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_AX210, .num_rbds = IWL_NUM_RBDS_AX210_HE, @@ -583,7 +574,7 @@ const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0 = { const struct iwl_cfg iwlax411_2ax_cfg_so_gf4_a0_long = { .name = "Intel(R) Wi-Fi 6 AX411 160MHz", - .fw_name_pre = IWL_22000_SO_A_GF4_A_FW_PRE, + .fw_name_pre = IWL_SO_A_GF4_A_FW_PRE, .uhb_supported = true, IWL_DEVICE_AX210, .num_rbds = IWL_NUM_RBDS_AX210_HE, @@ -607,18 +598,17 @@ const struct iwl_cfg iwlax211_cfg_snj_gf_a0 = { .num_rbds = IWL_NUM_RBDS_AX210_HE, }; -MODULE_FIRMWARE(IWL_22000_HR_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_22000_JF_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_22000_HR_B_QNJ_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QU_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_QNJ_B_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QU_C_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QU_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QUZ_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QUZ_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_QNJ_B_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_CC_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_22000_SO_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_22000_SO_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_22000_SO_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); -MODULE_FIRMWARE(IWL_22000_TY_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SO_A_JF_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SO_A_HR_B_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_SO_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); +MODULE_FIRMWARE(IWL_TY_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_SNJ_A_GF4_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); MODULE_FIRMWARE(IWL_SNJ_A_GF_A_MODULE_FIRMWARE(IWL_22000_UCODE_API_MAX)); diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h index 8d8380026180..4bd792c06ff6 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/dev.h +++ b/drivers/net/wireless/intel/iwlwifi/dvm/dev.h @@ -1,7 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /****************************************************************************** * - * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2014, 2020 Intel Corporation. All rights reserved. * * Contact Information: * Intel Linux Wireless <[email protected]> @@ -810,7 +810,6 @@ struct iwl_priv { u8 bt_traffic_load, last_bt_traffic_load; bool bt_ch_announce; bool bt_full_concurrent; - bool bt_ant_couple_ok; __le32 kill_ack_mask; __le32 kill_cts_mask; __le16 bt_valid; diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/main.c b/drivers/net/wireless/intel/iwlwifi/dvm/main.c index 598ee7315558..b882705ff66d 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/main.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/main.c @@ -1,9 +1,8 @@ // SPDX-License-Identifier: GPL-2.0-only /****************************************************************************** * - * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2003 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2015 Intel Deutschland GmbH - * Copyright (C) 2018 - 2019 Intel Corporation * * Portions of this file are derived from the ipw3945 project, as well * as portions of the ieee80211 subsystem header files. @@ -53,7 +52,7 @@ #define DRV_DESCRIPTION "Intel(R) Wireless WiFi Link AGN driver for Linux" MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); +MODULE_AUTHOR(DRV_AUTHOR); MODULE_LICENSE("GPL"); /* Please keep this array *SORTED* by hex value. @@ -1370,12 +1369,6 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans, IWL_DEBUG_INFO(priv, "*** LOAD DRIVER ***\n"); - /* is antenna coupling more than 35dB ? */ - priv->bt_ant_couple_ok = - (iwlwifi_mod_params.antenna_coupling > - IWL_BT_ANTENNA_COUPLING_THRESHOLD) ? - true : false; - /* bt channel inhibition enabled*/ priv->bt_ch_announce = true; IWL_DEBUG_INFO(priv, "BT channel inhibition is %s\n", diff --git a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c index dac809df7f1d..4fa4eab2d7f3 100644 --- a/drivers/net/wireless/intel/iwlwifi/dvm/rs.c +++ b/drivers/net/wireless/intel/iwlwifi/dvm/rs.c @@ -2,6 +2,7 @@ /****************************************************************************** * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. + * Copyright (C) 2019 - 2020 Intel Corporation * * Contact Information: * Intel Linux Wireless <[email protected]> @@ -846,16 +847,6 @@ static void rs_bt_update_lq(struct iwl_priv *priv, struct iwl_rxon_context *ctx, struct iwl_scale_tbl_info *tbl; bool full_concurrent = priv->bt_full_concurrent; - if (priv->bt_ant_couple_ok) { - /* - * Is there a need to switch between - * full concurrency and 3-wire? - */ - if (priv->bt_ci_compliance) - full_concurrent = true; - else - full_concurrent = false; - } if ((priv->bt_traffic_load != priv->last_bt_traffic_load) || (priv->bt_full_concurrent != full_concurrent)) { priv->bt_full_concurrent = full_concurrent; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h index b9d7ed93311c..74ac65bd545a 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/dbg-tlv.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright (C) 2018 - 2019 Intel Corporation + * Copyright (C) 2018 - 2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -25,7 +25,7 @@ * * BSD LICENSE * - * Copyright (C) 2018 - 2019 Intel Corporation + * Copyright (C) 2018 - 2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -304,6 +304,7 @@ enum iwl_fw_ini_buffer_location { IWL_FW_INI_LOCATION_SRAM_PATH, IWL_FW_INI_LOCATION_DRAM_PATH, IWL_FW_INI_LOCATION_NPK_PATH, + IWL_FW_INI_LOCATION_NUM, }; /* FW_DEBUG_TLV_BUFFER_LOCATION_E_VER_1 */ /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h index 98e957ecbeed..94b1a1268476 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/debug.h @@ -5,10 +5,9 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 - 2019 Intel Corporation + * Copyright(c) 2007 - 2014, 2018 - 2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,10 +27,9 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 - 2019 Intel Corporation + * Copyright(c) 2005 - 2014, 2018 - 2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -218,6 +216,8 @@ struct iwl_shared_mem_lmac_cfg { * @page_buff_size: size of %page_buff_addr * @lmac_num: number of LMACs (1 or 2) * @lmac_smem: per - LMAC smem data + * @rxfifo2_control_addr: start addr of RXF2C + * @rxfifo2_control_size: size of RXF2C */ struct iwl_shared_mem_cfg { __le32 shared_mem_addr; @@ -229,8 +229,10 @@ struct iwl_shared_mem_cfg { __le32 page_buff_addr; __le32 page_buff_size; __le32 lmac_num; - struct iwl_shared_mem_lmac_cfg lmac_smem[2]; -} __packed; /* SHARED_MEM_ALLOC_API_S_VER_3 */ + struct iwl_shared_mem_lmac_cfg lmac_smem[3]; + __le32 rxfifo2_control_addr; + __le32 rxfifo2_control_size; +} __packed; /* SHARED_MEM_ALLOC_API_S_VER_4 */ /** * struct iwl_mfuart_load_notif - mfuart image version & status diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h index 0214e553d5ae..7ffad19d80fd 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/location.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/location.h @@ -6,8 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation - * Copyright (C) 2019 Intel Corporation + * Copyright (C) 2018 - 2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,8 +27,7 @@ * BSD LICENSE * * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation - * Copyright (C) 2019 Intel Corporation + * Copyright (C) 2018 - 2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -147,6 +145,7 @@ struct iwl_tof_config_cmd { * @IWL_TOF_BW_40: 40 MHz * @IWL_TOF_BW_80: 80 MHz * @IWL_TOF_BW_160: 160 MHz + * @IWL_TOF_BW_NUM: number of tof bandwidths */ enum iwl_tof_bandwidth { IWL_TOF_BW_20_LEGACY, @@ -154,6 +153,7 @@ enum iwl_tof_bandwidth { IWL_TOF_BW_40, IWL_TOF_BW_80, IWL_TOF_BW_160, + IWL_TOF_BW_NUM, }; /* LOCAT_BW_TYPE_E */ /* @@ -430,6 +430,9 @@ struct iwl_tof_range_req_ap_entry_v2 { * @IWL_INITIATOR_AP_FLAGS_NON_TB: Use non trigger based flow * @IWL_INITIATOR_AP_FLAGS_TB: Use trigger based flow * @IWL_INITIATOR_AP_FLAGS_SECURED: request secured measurement + * @IWL_INITIATOR_AP_FLAGS_LMR_FEEDBACK: Send LMR feedback + * @IWL_INITIATOR_AP_FLAGS_USE_CALIB: Use calibration values from the request + * instead of fw internal values. */ enum iwl_initiator_ap_flags { IWL_INITIATOR_AP_FLAGS_ASAP = BIT(1), @@ -442,6 +445,8 @@ enum iwl_initiator_ap_flags { IWL_INITIATOR_AP_FLAGS_NON_TB = BIT(9), IWL_INITIATOR_AP_FLAGS_TB = BIT(10), IWL_INITIATOR_AP_FLAGS_SECURED = BIT(11), + IWL_INITIATOR_AP_FLAGS_LMR_FEEDBACK = BIT(12), + IWL_INITIATOR_AP_FLAGS_USE_CALIB = BIT(13), }; /** @@ -508,7 +513,7 @@ enum iwl_location_bw { #define LOCATION_BW_POS 4 /** - * struct iwl_tof_range_req_ap_entry - AP configuration parameters + * struct iwl_tof_range_req_ap_entry_v4 - AP configuration parameters * @initiator_ap_flags: see &enum iwl_initiator_ap_flags. * @channel_num: AP Channel number * @format_bw: bits 0 - 3: &enum iwl_location_frame_format. @@ -527,7 +532,7 @@ enum iwl_location_bw { * @hltk: HLTK to be used for secured 11az measurement * @tk: TK to be used for secured 11az measurement */ -struct iwl_tof_range_req_ap_entry { +struct iwl_tof_range_req_ap_entry_v4 { __le32 initiator_ap_flags; u8 channel_num; u8 format_bw; @@ -543,6 +548,65 @@ struct iwl_tof_range_req_ap_entry { } __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_4 */ /** + * enum iwl_location_cipher - location cipher selection + * @IWL_LOCATION_CIPHER_CCMP_128: CCMP 128 + * @IWL_LOCATION_CIPHER_CCMP_256: CCMP 256 + * @IWL_LOCATION_CIPHER_GCMP_128: GCMP 128 + * @IWL_LOCATION_CIPHER_GCMP_256: GCMP 256 + */ +enum iwl_location_cipher { + IWL_LOCATION_CIPHER_CCMP_128, + IWL_LOCATION_CIPHER_CCMP_256, + IWL_LOCATION_CIPHER_GCMP_128, + IWL_LOCATION_CIPHER_GCMP_256, +}; + +/** + * struct iwl_tof_range_req_ap_entry - AP configuration parameters + * @initiator_ap_flags: see &enum iwl_initiator_ap_flags. + * @channel_num: AP Channel number + * @format_bw: bits 0 - 3: &enum iwl_location_frame_format. + * bits 4 - 7: &enum iwl_location_bw. + * @ctrl_ch_position: Coding of the control channel position relative to the + * center frequency, see iwl_mvm_get_ctrl_pos(). + * @ftmr_max_retries: Max number of retries to send the FTMR in case of no + * reply from the AP. + * @bssid: AP's BSSID + * @burst_period: Recommended value to be sent to the AP. Measurement + * periodicity In units of 100ms. ignored if num_of_bursts_exp = 0 + * @samples_per_burst: the number of FTMs pairs in single Burst (1-31); + * @num_of_bursts: Recommended value to be sent to the AP. 2s Exponent of + * the number of measurement iterations (min 2^0 = 1, max 2^14) + * @reserved: For alignment and future use + * @cipher: pairwise cipher suite for secured measurement. + * &enum iwl_location_cipher. + * @hltk: HLTK to be used for secured 11az measurement + * @tk: TK to be used for secured 11az measurement + * @calib: An array of calibration values per FTM rx bandwidth. + * If &IWL_INITIATOR_AP_FLAGS_USE_CALIB is set, the fw will use the + * calibration value that corresponds to the rx bandwidth of the FTM + * frame. + * @reserved2: For alignment and future use. + */ +struct iwl_tof_range_req_ap_entry { + __le32 initiator_ap_flags; + u8 channel_num; + u8 format_bw; + u8 ctrl_ch_position; + u8 ftmr_max_retries; + u8 bssid[ETH_ALEN]; + __le16 burst_period; + u8 samples_per_burst; + u8 num_of_bursts; + u8 reserved; + u8 cipher; + u8 hltk[HLTK_11AZ_LEN]; + u8 tk[TK_11AZ_LEN]; + __le16 calib[IWL_TOF_BW_NUM]; + __le16 reserved2; +} __packed; /* LOCATION_RANGE_REQ_AP_ENTRY_CMD_API_S_VER_5 */ + +/** * enum iwl_tof_response_mode * @IWL_MVM_TOF_RESPONSE_ASAP: report each AP measurement separately as soon as * possible (not supported for this release) @@ -676,7 +740,7 @@ struct iwl_tof_range_req_cmd_v7 { } __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_7 */ /** - * struct iwl_tof_range_req_cmd - start measurement cmd + * struct iwl_tof_range_req_cmd_v8 - start measurement cmd * @initiator_flags: see flags @ iwl_tof_initiator_flags * @request_id: A Token incremented per request. The same Token will be * sent back in the range response @@ -693,7 +757,7 @@ struct iwl_tof_range_req_cmd_v7 { * @specific_calib: The specific calib value to inject to this measurement calc * @ap: per-AP request data, see &struct iwl_tof_range_req_ap_entry_v2. */ -struct iwl_tof_range_req_cmd { +struct iwl_tof_range_req_cmd_v8 { __le32 initiator_flags; u8 request_id; u8 num_of_ap; @@ -704,9 +768,37 @@ struct iwl_tof_range_req_cmd { __le32 tsf_mac_id; __le16 common_calib; __le16 specific_calib; - struct iwl_tof_range_req_ap_entry ap[IWL_MVM_TOF_MAX_APS]; + struct iwl_tof_range_req_ap_entry_v4 ap[IWL_MVM_TOF_MAX_APS]; } __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_8 */ +/** + * struct iwl_tof_range_req_cmd - start measurement cmd + * @initiator_flags: see flags @ iwl_tof_initiator_flags + * @request_id: A Token incremented per request. The same Token will be + * sent back in the range response + * @num_of_ap: Number of APs to measure (error if > IWL_MVM_TOF_MAX_APS) + * @range_req_bssid: ranging request BSSID + * @macaddr_mask: Bits set to 0 shall be copied from the MAC address template. + * Bits set to 1 shall be randomized by the UMAC + * @macaddr_template: MAC address template to use for non-randomized bits + * @req_timeout_ms: Requested timeout of the response in units of milliseconds. + * This is the session time for completing the measurement. + * @tsf_mac_id: report the measurement start time for each ap in terms of the + * TSF of this mac id. 0xff to disable TSF reporting. + * @ap: per-AP request data, see &struct iwl_tof_range_req_ap_entry_v2. + */ +struct iwl_tof_range_req_cmd { + __le32 initiator_flags; + u8 request_id; + u8 num_of_ap; + u8 range_req_bssid[ETH_ALEN]; + u8 macaddr_mask[ETH_ALEN]; + u8 macaddr_template[ETH_ALEN]; + __le32 req_timeout_ms; + __le32 tsf_mac_id; + struct iwl_tof_range_req_ap_entry ap[IWL_MVM_TOF_MAX_APS]; +} __packed; /* LOCATION_RANGE_REQ_CMD_API_S_VER_9 */ + /* * enum iwl_tof_range_request_status - status of the sent request * @IWL_TOF_RANGE_REQUEST_STATUS_SUCCESSFUL - FW successfully received the diff --git a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h index 88bc7733065f..b8b36a4f9eb9 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/api/rx.h @@ -5,10 +5,9 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,10 +27,9 @@ * * BSD LICENSE * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -535,9 +533,9 @@ struct iwl_rx_mpdu_desc_v3 { __le32 filter_match; /** - * @phy_data2: depends on info type (see @phy_data1) + * @phy_data3: depends on info type (see @phy_data1) */ - __le32 phy_data2; + __le32 phy_data3; }; /* DW8 - carries rss_hash only when rpa_en == 1 */ @@ -548,9 +546,9 @@ struct iwl_rx_mpdu_desc_v3 { __le32 rss_hash; /** - * @phy_data3: depends on info type (see @phy_data1) + * @phy_data2: depends on info type (see @phy_data1) */ - __le32 phy_data3; + __le32 phy_data2; }; /* DW9 */ /** diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 39c8332be3ac..4d3687cc83a4 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -1367,33 +1367,57 @@ static void iwl_ini_get_rxf_data(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data; u32 fid1 = le32_to_cpu(reg->fifos.fid[0]); u32 fid2 = le32_to_cpu(reg->fifos.fid[1]); - u32 fifo_idx; + u8 fifo_idx; if (!data) return; + /* make sure only one bit is set in only one fid */ + if (WARN_ONCE(hweight_long(fid1) + hweight_long(fid2) != 1, + "fid1=%x, fid2=%x\n", fid1, fid2)) + return; + memset(data, 0, sizeof(*data)); - if (WARN_ON_ONCE((fid1 && fid2) || (!fid1 && !fid2))) - return; + if (fid1) { + fifo_idx = ffs(fid1) - 1; + if (WARN_ONCE(fifo_idx >= MAX_NUM_LMAC, "fifo_idx=%d\n", + fifo_idx)) + return; - fifo_idx = ffs(fid1) - 1; - if (fid1 && !WARN_ON_ONCE((~BIT(fifo_idx) & fid1) || - fifo_idx >= MAX_NUM_LMAC)) { data->size = fwrt->smem_cfg.lmac[fifo_idx].rxfifo1_size; data->fifo_num = fifo_idx; - return; - } + } else { + u8 max_idx; + + fifo_idx = ffs(fid2) - 1; + if (iwl_fw_lookup_notif_ver(fwrt->fw, SYSTEM_GROUP, + SHARED_MEM_CFG_CMD, 0) <= 3) + max_idx = 0; + else + max_idx = 1; + + if (WARN_ONCE(fifo_idx > max_idx, + "invalid umac fifo idx %d", fifo_idx)) + return; - fifo_idx = ffs(fid2) - 1; - if (fid2 && !WARN_ON_ONCE(fifo_idx != 0)) { - data->size = fwrt->smem_cfg.rxfifo2_size; - data->offset = RXF_DIFF_FROM_PREV; /* use bit 31 to distinguish between umac and lmac rxf while * parsing the dump */ data->fifo_num = fifo_idx | IWL_RXF_UMAC_BIT; - return; + + switch (fifo_idx) { + case 0: + data->size = fwrt->smem_cfg.rxfifo2_size; + data->offset = iwl_umac_prph(fwrt->trans, + RXF_DIFF_FROM_PREV); + break; + case 1: + data->size = fwrt->smem_cfg.rxfifo2_control_size; + data->offset = iwl_umac_prph(fwrt->trans, + RXF2C_DIFF_FROM_PREV); + break; + } } } @@ -1934,6 +1958,7 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt, struct iwl_fw_ini_dump_cfg_name *cfg_name; u32 size = sizeof(*tlv) + sizeof(*dump); u32 num_of_cfg_names = 0; + u32 hw_type; list_for_each_entry(node, &fwrt->trans->dbg.debug_info_tlv_list, list) { size += sizeof(*cfg_name); @@ -1962,7 +1987,26 @@ static u32 iwl_dump_ini_info(struct iwl_fw_runtime *fwrt, dump->ver_subtype = cpu_to_le32(fwrt->dump.fw_ver.subtype); dump->hw_step = cpu_to_le32(CSR_HW_REV_STEP(fwrt->trans->hw_rev)); - dump->hw_type = cpu_to_le32(CSR_HW_REV_TYPE(fwrt->trans->hw_rev)); + + /* + * Several HWs all have type == 0x42, so we'll override this value + * according to the detected HW + */ + hw_type = CSR_HW_REV_TYPE(fwrt->trans->hw_rev); + if (hw_type == IWL_AX210_HW_TYPE) { + u32 prph_val = iwl_read_prph(fwrt->trans, WFPM_OTP_CFG1_ADDR); + u32 is_jacket = !!(prph_val & WFPM_OTP_CFG1_IS_JACKET_BIT); + u32 is_cdb = !!(prph_val & WFPM_OTP_CFG1_IS_CDB_BIT); + u32 masked_bits = is_jacket | (is_cdb << 1); + + /* + * The HW type depends on certain bits in this case, so add + * these bits to the HW type. We won't have collisions since we + * add these bits after the highest possible bit in the mask. + */ + hw_type |= masked_bits << IWL_AX210_HW_TYPE_ADDITION_SHIFT; + } + dump->hw_type = cpu_to_le32(hw_type); dump->rf_id_flavor = cpu_to_le32(CSR_HW_RFID_FLAVOR(fwrt->trans->hw_rf_id)); @@ -2095,7 +2139,11 @@ static u32 iwl_dump_ini_trigger(struct iwl_fw_runtime *fwrt, u32 size = 0; u64 regions_mask = le64_to_cpu(trigger->regions_mask); - for (i = 0; i < 64; i++) { + BUILD_BUG_ON(sizeof(trigger->regions_mask) != sizeof(regions_mask)); + BUILD_BUG_ON((sizeof(trigger->regions_mask) * BITS_PER_BYTE) < + ARRAY_SIZE(fwrt->trans->dbg.active_regions)); + + for (i = 0; i < ARRAY_SIZE(fwrt->trans->dbg.active_regions); i++) { u32 reg_type; struct iwl_fw_ini_region_tlv *reg; @@ -2174,12 +2222,11 @@ static u32 iwl_dump_ini_file_gen(struct iwl_fw_runtime *fwrt, } static inline void iwl_fw_free_dump_desc(struct iwl_fw_runtime *fwrt, - const struct iwl_fw_dump_desc **desc) + const struct iwl_fw_dump_desc *desc) { - if (desc && *desc != &iwl_dump_desc_assert) - kfree(*desc); + if (desc && desc != &iwl_dump_desc_assert) + kfree(desc); - *desc = NULL; fwrt->dump.lmac_err_id[0] = 0; if (fwrt->smem_cfg.num_lmacs > 1) fwrt->dump.lmac_err_id[1] = 0; @@ -2291,7 +2338,7 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, unsigned long idx; if (iwl_trans_dbg_ini_valid(fwrt->trans)) { - iwl_fw_free_dump_desc(fwrt, &desc); + iwl_fw_free_dump_desc(fwrt, desc); return 0; } @@ -2312,7 +2359,7 @@ int iwl_fw_dbg_collect_desc(struct iwl_fw_runtime *fwrt, wk_data = &fwrt->dump.wks[idx]; if (WARN_ON(wk_data->dump_data.desc)) - iwl_fw_free_dump_desc(fwrt, &wk_data->dump_data.desc); + iwl_fw_free_dump_desc(fwrt, wk_data->dump_data.desc); wk_data->dump_data.desc = desc; wk_data->dump_data.monitor_only = monitor_only; @@ -2569,10 +2616,12 @@ static void iwl_fw_dbg_collect_sync(struct iwl_fw_runtime *fwrt, u8 wk_idx) iwl_fw_dbg_stop_restart_recording(fwrt, ¶ms, false); out: - if (iwl_trans_dbg_ini_valid(fwrt->trans)) + if (iwl_trans_dbg_ini_valid(fwrt->trans)) { iwl_fw_error_dump_data_free(dump_data); - else - iwl_fw_free_dump_desc(fwrt, &dump_data->desc); + } else { + iwl_fw_free_dump_desc(fwrt, dump_data->desc); + dump_data->desc = NULL; + } clear_bit(wk_idx, &fwrt->dump.active_wks); } @@ -2731,7 +2780,7 @@ void iwl_fw_dbg_stop_restart_recording(struct iwl_fw_runtime *fwrt, struct iwl_fw_dbg_params *params, bool stop) { - int ret = 0; + int ret __maybe_unused = 0; if (test_bit(STATUS_FW_ERROR, &fwrt->trans->status)) return; diff --git a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c index 89f74116569d..6e72c27f527b 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/debugfs.c @@ -5,10 +5,9 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,10 +27,9 @@ * * BSD LICENSE * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 Intel Corporation + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -64,6 +62,7 @@ #include "api/commands.h" #include "debugfs.h" #include "dbg.h" +#include <linux/seq_file.h> #define FWRT_DEBUGFS_OPEN_WRAPPER(name, buflen, argtype) \ struct dbgfs_##name##_data { \ @@ -329,11 +328,108 @@ static ssize_t iwl_dbgfs_fw_dbg_domain_read(struct iwl_fw_runtime *fwrt, FWRT_DEBUGFS_READ_FILE_OPS(fw_dbg_domain, 20); +struct iwl_dbgfs_fw_info_priv { + struct iwl_fw_runtime *fwrt; +}; + +struct iwl_dbgfs_fw_info_state { + loff_t pos; +}; + +static void *iwl_dbgfs_fw_info_seq_next(struct seq_file *seq, + void *v, loff_t *pos) +{ + struct iwl_dbgfs_fw_info_state *state = v; + struct iwl_dbgfs_fw_info_priv *priv = seq->private; + const struct iwl_fw *fw = priv->fwrt->fw; + + *pos = ++state->pos; + if (*pos >= fw->ucode_capa.n_cmd_versions) + return NULL; + + return state; +} + +static void iwl_dbgfs_fw_info_seq_stop(struct seq_file *seq, + void *v) +{ + kfree(v); +} + +static void *iwl_dbgfs_fw_info_seq_start(struct seq_file *seq, loff_t *pos) +{ + struct iwl_dbgfs_fw_info_priv *priv = seq->private; + const struct iwl_fw *fw = priv->fwrt->fw; + struct iwl_dbgfs_fw_info_state *state; + + if (*pos >= fw->ucode_capa.n_cmd_versions) + return NULL; + + state = kzalloc(sizeof(*state), GFP_KERNEL); + if (!state) + return NULL; + state->pos = *pos; + return state; +}; + +static int iwl_dbgfs_fw_info_seq_show(struct seq_file *seq, void *v) +{ + struct iwl_dbgfs_fw_info_state *state = v; + struct iwl_dbgfs_fw_info_priv *priv = seq->private; + const struct iwl_fw *fw = priv->fwrt->fw; + const struct iwl_fw_cmd_version *ver; + u32 cmd_id; + + if (!state->pos) + seq_puts(seq, "fw_api_ver:\n"); + + ver = &fw->ucode_capa.cmd_versions[state->pos]; + + cmd_id = iwl_cmd_id(ver->cmd, ver->group, 0); + + seq_printf(seq, " 0x%04x:\n", cmd_id); + seq_printf(seq, " name: %s\n", + iwl_get_cmd_string(priv->fwrt->trans, cmd_id)); + seq_printf(seq, " cmd_ver: %d\n", ver->cmd_ver); + seq_printf(seq, " notif_ver: %d\n", ver->notif_ver); + return 0; +} + +static const struct seq_operations iwl_dbgfs_info_seq_ops = { + .start = iwl_dbgfs_fw_info_seq_start, + .next = iwl_dbgfs_fw_info_seq_next, + .stop = iwl_dbgfs_fw_info_seq_stop, + .show = iwl_dbgfs_fw_info_seq_show, +}; + +static int iwl_dbgfs_fw_info_open(struct inode *inode, struct file *filp) +{ + struct iwl_dbgfs_fw_info_priv *priv; + + priv = __seq_open_private(filp, &iwl_dbgfs_info_seq_ops, + sizeof(*priv)); + + if (!priv) + return -ENOMEM; + + priv->fwrt = inode->i_private; + return 0; +} + +static const struct file_operations iwl_dbgfs_fw_info_ops = { + .owner = THIS_MODULE, + .open = iwl_dbgfs_fw_info_open, + .read = seq_read, + .llseek = seq_lseek, + .release = seq_release_private, +}; + void iwl_fwrt_dbgfs_register(struct iwl_fw_runtime *fwrt, struct dentry *dbgfs_dir) { INIT_DELAYED_WORK(&fwrt->timestamp.wk, iwl_fw_timestamp_marker_wk); FWRT_DEBUGFS_ADD_FILE(timestamp_marker, dbgfs_dir, 0200); + FWRT_DEBUGFS_ADD_FILE(fw_info, dbgfs_dir, 0200); FWRT_DEBUGFS_ADD_FILE(send_hcmd, dbgfs_dir, 0200); FWRT_DEBUGFS_ADD_FILE(fw_dbg_domain, dbgfs_dir, 0400); } diff --git a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h index f008e1bbfdf4..72bfc64580ab 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/error-dump.h @@ -8,7 +8,7 @@ * Copyright(c) 2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 - 2019 Intel Corporation + * Copyright (C) 2018 - 2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2014 Intel Corporation. All rights reserved. * Copyright(c) 2014 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright (C) 2018 - 2019 Intel Corporation + * Copyright (C) 2018 - 2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -394,6 +394,15 @@ struct iwl_fw_ini_dump_cfg_name { u8 cfg_name[IWL_FW_INI_MAX_CFG_NAME]; } __packed; +/* AX210's HW type */ +#define IWL_AX210_HW_TYPE 0x42 +/* How many bits to roll when adding to the HW type of AX210 HW */ +#define IWL_AX210_HW_TYPE_ADDITION_SHIFT 12 +/* This prph is used to tell apart HW_TYPE == 0x42 NICs */ +#define WFPM_OTP_CFG1_ADDR 0xd03098 +#define WFPM_OTP_CFG1_IS_JACKET_BIT BIT(4) +#define WFPM_OTP_CFG1_IS_CDB_BIT BIT(5) + /* struct iwl_fw_ini_dump_info - ini dump information * @version: dump version * @time_point: time point that caused the dump collection diff --git a/drivers/net/wireless/intel/iwlwifi/fw/init.c b/drivers/net/wireless/intel/iwlwifi/fw/init.c index ba00d162ce72..b373606e1241 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/init.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/init.c @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2019 Intel Corporation + * Copyright(c) 2019 - 2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -27,7 +27,7 @@ * BSD LICENSE * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2019 Intel Corporation + * Copyright(c) 2019 - 2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -62,6 +62,9 @@ #include "dbg.h" #include "debugfs.h" +#include "fw/api/soc.h" +#include "fw/api/commands.h" + void iwl_fw_runtime_init(struct iwl_fw_runtime *fwrt, struct iwl_trans *trans, const struct iwl_fw *fw, const struct iwl_fw_runtime_ops *ops, void *ops_ctx, @@ -95,3 +98,51 @@ void iwl_fw_runtime_resume(struct iwl_fw_runtime *fwrt) iwl_fw_resume_timestamp(fwrt); } IWL_EXPORT_SYMBOL(iwl_fw_runtime_resume); + +/* set device type and latency */ +int iwl_set_soc_latency(struct iwl_fw_runtime *fwrt) +{ + struct iwl_soc_configuration_cmd cmd = {}; + struct iwl_host_cmd hcmd = { + .id = iwl_cmd_id(SOC_CONFIGURATION_CMD, SYSTEM_GROUP, 0), + .data[0] = &cmd, + .len[0] = sizeof(cmd), + }; + int ret; + + /* + * In VER_1 of this command, the discrete value is considered + * an integer; In VER_2, it's a bitmask. Since we have only 2 + * values in VER_1, this is backwards-compatible with VER_2, + * as long as we don't set any other bits. + */ + if (!fwrt->trans->trans_cfg->integrated) + cmd.flags = cpu_to_le32(SOC_CONFIG_CMD_FLAGS_DISCRETE); + + BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_NONE != + SOC_FLAGS_LTR_APPLY_DELAY_NONE); + BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_200US != + SOC_FLAGS_LTR_APPLY_DELAY_200); + BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_2500US != + SOC_FLAGS_LTR_APPLY_DELAY_2500); + BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_1820US != + SOC_FLAGS_LTR_APPLY_DELAY_1820); + + if (fwrt->trans->trans_cfg->ltr_delay != IWL_CFG_TRANS_LTR_DELAY_NONE && + !WARN_ON(!fwrt->trans->trans_cfg->integrated)) + cmd.flags |= le32_encode_bits(fwrt->trans->trans_cfg->ltr_delay, + SOC_FLAGS_LTR_APPLY_DELAY_MASK); + + if (iwl_fw_lookup_cmd_ver(fwrt->fw, IWL_ALWAYS_LONG_GROUP, + SCAN_REQ_UMAC) >= 2 && + fwrt->trans->trans_cfg->low_latency_xtal) + cmd.flags |= cpu_to_le32(SOC_CONFIG_CMD_FLAGS_LOW_LATENCY); + + cmd.latency = cpu_to_le32(fwrt->trans->trans_cfg->xtal_latency); + + ret = iwl_trans_send_cmd(fwrt->trans, &hcmd); + if (ret) + IWL_ERR(fwrt, "Failed to set soc latency: %d\n", ret); + return ret; +} +IWL_EXPORT_SYMBOL(iwl_set_soc_latency); diff --git a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h index 9906d9b9bdd5..b5e5e32b6152 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/runtime.h +++ b/drivers/net/wireless/intel/iwlwifi/fw/runtime.h @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2019 Intel Corporation + * Copyright (C) 2018-2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -27,7 +27,7 @@ * BSD LICENSE * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2019 Intel Corporation + * Copyright (C) 2018-2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -86,6 +86,7 @@ struct iwl_fwrt_shared_mem_cfg { u32 rxfifo1_size; } lmac[MAX_NUM_LMAC]; u32 rxfifo2_size; + u32 rxfifo2_control_size; u32 internal_txfifo_addr; u32 internal_txfifo_size[TX_FIFO_INTERNAL_MAX_NUM]; }; @@ -241,5 +242,6 @@ int iwl_init_paging(struct iwl_fw_runtime *fwrt, enum iwl_ucode_type type); void iwl_free_fw_paging(struct iwl_fw_runtime *fwrt); void iwl_get_shared_mem_conf(struct iwl_fw_runtime *fwrt); +int iwl_set_soc_latency(struct iwl_fw_runtime *fwrt); #endif /* __iwl_fw_runtime_h__ */ diff --git a/drivers/net/wireless/intel/iwlwifi/fw/smem.c b/drivers/net/wireless/intel/iwlwifi/fw/smem.c index 409b2dd854ac..700fdab14209 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/smem.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/smem.c @@ -5,10 +5,9 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,10 +27,9 @@ * * BSD LICENSE * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -71,6 +69,8 @@ static void iwl_parse_shared_mem_22000(struct iwl_fw_runtime *fwrt, struct iwl_shared_mem_cfg *mem_cfg = (void *)pkt->data; int i, lmac; int lmac_num = le32_to_cpu(mem_cfg->lmac_num); + u8 api_ver = iwl_fw_lookup_notif_ver(fwrt->fw, SYSTEM_GROUP, + SHARED_MEM_CFG_CMD, 0); if (WARN_ON(lmac_num > ARRAY_SIZE(mem_cfg->lmac_smem))) return; @@ -80,6 +80,12 @@ static void iwl_parse_shared_mem_22000(struct iwl_fw_runtime *fwrt, ARRAY_SIZE(mem_cfg->lmac_smem[0].txfifo_size); fwrt->smem_cfg.rxfifo2_size = le32_to_cpu(mem_cfg->rxfifo2_size); + if (api_ver >= 4 && + !WARN_ON_ONCE(iwl_rx_packet_payload_len(pkt) < sizeof(*mem_cfg))) { + fwrt->smem_cfg.rxfifo2_control_size = + le32_to_cpu(mem_cfg->rxfifo2_control_size); + } + for (lmac = 0; lmac < lmac_num; lmac++) { struct iwl_shared_mem_lmac_cfg *lmac_cfg = &mem_cfg->lmac_smem[lmac]; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 3a9a33851793..244899f3f3bf 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -477,12 +477,16 @@ struct iwl_cfg { #define IWL_CFG_RF_TYPE_TH1 0x108 #define IWL_CFG_RF_TYPE_JF2 0x105 #define IWL_CFG_RF_TYPE_JF1 0x108 +#define IWL_CFG_RF_TYPE_HR2 0x10A +#define IWL_CFG_RF_TYPE_HR1 0x10C #define IWL_CFG_RF_ID_TH 0x1 #define IWL_CFG_RF_ID_TH1 0x1 #define IWL_CFG_RF_ID_JF 0x3 #define IWL_CFG_RF_ID_JF1 0x6 #define IWL_CFG_RF_ID_JF1_DIV 0xA +#define IWL_CFG_RF_ID_HR 0x7 +#define IWL_CFG_RF_ID_HR1 0x4 #define IWL_CFG_NO_160 0x0 #define IWL_CFG_160 0x1 @@ -535,6 +539,8 @@ extern const char iwl9260_killer_1550_name[]; extern const char iwl9560_killer_1550i_name[]; extern const char iwl9560_killer_1550s_name[]; extern const char iwl_ax200_name[]; +extern const char iwl_ax201_name[]; +extern const char iwl_ax101_name[]; extern const char iwl_ax200_killer_1650w_name[]; extern const char iwl_ax200_killer_1650x_name[]; @@ -609,9 +615,9 @@ extern const struct iwl_cfg iwl9560_qu_c0_jf_b0_cfg; extern const struct iwl_cfg iwl9560_quz_a0_jf_b0_cfg; extern const struct iwl_cfg iwl9560_qnj_b0_jf_b0_cfg; extern const struct iwl_cfg iwl9560_2ac_cfg_soc; -extern const struct iwl_cfg iwl_ax101_cfg_qu_hr; -extern const struct iwl_cfg iwl_ax101_cfg_qu_c0_hr_b0; -extern const struct iwl_cfg iwl_ax101_cfg_quz_hr; +extern const struct iwl_cfg iwl_qu_b0_hr1_b0; +extern const struct iwl_cfg iwl_qu_c0_hr1_b0; +extern const struct iwl_cfg iwl_quz_a0_hr1_b0; extern const struct iwl_cfg iwl_ax200_cfg_cc; extern const struct iwl_cfg iwl_ax201_cfg_qu_hr; extern const struct iwl_cfg iwl_ax201_cfg_qu_hr; @@ -625,8 +631,7 @@ extern const struct iwl_cfg killer1650s_2ax_cfg_qu_c0_hr_b0; extern const struct iwl_cfg killer1650i_2ax_cfg_qu_c0_hr_b0; extern const struct iwl_cfg killer1650x_2ax_cfg; extern const struct iwl_cfg killer1650w_2ax_cfg; -extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0_f0; -extern const struct iwl_cfg iwl22000_2ax_cfg_qnj_hr_b0; +extern const struct iwl_cfg iwl_qnj_b0_hr_b0_cfg; extern const struct iwl_cfg iwlax210_2ax_cfg_so_jf_a0; extern const struct iwl_cfg iwlax210_2ax_cfg_so_hr_a0; extern const struct iwl_cfg iwlax211_2ax_cfg_so_gf_a0; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 9eb8fbfaa2a2..7987a288917b 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -165,38 +165,36 @@ static int iwl_dbg_tlv_alloc_buf_alloc(struct iwl_trans *trans, struct iwl_ucode_tlv *tlv) { struct iwl_fw_ini_allocation_tlv *alloc = (void *)tlv->data; - u32 buf_location = le32_to_cpu(alloc->buf_location); - u32 alloc_id = le32_to_cpu(alloc->alloc_id); + u32 buf_location; + u32 alloc_id; - if (le32_to_cpu(tlv->length) != sizeof(*alloc) || - (buf_location != IWL_FW_INI_LOCATION_SRAM_PATH && - buf_location != IWL_FW_INI_LOCATION_DRAM_PATH && - buf_location != IWL_FW_INI_LOCATION_NPK_PATH)) { - IWL_ERR(trans, - "WRT: Invalid allocation TLV\n"); + if (le32_to_cpu(tlv->length) != sizeof(*alloc)) return -EINVAL; - } - if ((buf_location == IWL_FW_INI_LOCATION_SRAM_PATH || - buf_location == IWL_FW_INI_LOCATION_NPK_PATH) && - alloc_id != IWL_FW_INI_ALLOCATION_ID_DBGC1) { - IWL_ERR(trans, - "WRT: Allocation TLV for SMEM/NPK path must have id %u (current: %u)\n", - IWL_FW_INI_ALLOCATION_ID_DBGC1, alloc_id); - return -EINVAL; - } + buf_location = le32_to_cpu(alloc->buf_location); + alloc_id = le32_to_cpu(alloc->alloc_id); + + if (buf_location == IWL_FW_INI_LOCATION_INVALID || + buf_location >= IWL_FW_INI_LOCATION_NUM) + goto err; if (alloc_id == IWL_FW_INI_ALLOCATION_INVALID || - alloc_id >= IWL_FW_INI_ALLOCATION_NUM) { - IWL_ERR(trans, - "WRT: Invalid allocation id %u for allocation TLV\n", - alloc_id); - return -EINVAL; - } + alloc_id >= IWL_FW_INI_ALLOCATION_NUM) + goto err; + + if ((buf_location == IWL_FW_INI_LOCATION_SRAM_PATH || + buf_location == IWL_FW_INI_LOCATION_NPK_PATH) && + alloc_id != IWL_FW_INI_ALLOCATION_ID_DBGC1) + goto err; trans->dbg.fw_mon_cfg[alloc_id] = *alloc; return 0; +err: + IWL_ERR(trans, + "WRT: Invalid allocation id %u and/or location id %u for allocation TLV\n", + alloc_id, buf_location); + return -EINVAL; } static int iwl_dbg_tlv_alloc_hcmd(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c index a483d389d9c2..04f14bfdd091 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.c @@ -5,10 +5,9 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2007 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,10 +27,9 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -87,7 +85,7 @@ #define DRV_DESCRIPTION "Intel(R) Wireless WiFi driver for Linux" MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); +MODULE_AUTHOR(DRV_AUTHOR); MODULE_LICENSE("GPL"); #ifdef CONFIG_IWLWIFI_DEBUGFS @@ -1776,7 +1774,6 @@ static int __init iwl_drv_init(void) INIT_LIST_HEAD(&iwlwifi_opmode_table[i].drv); pr_info(DRV_DESCRIPTION "\n"); - pr_info(DRV_COPYRIGHT "\n"); #ifdef CONFIG_IWLWIFI_DEBUGFS /* Create the root of iwlwifi debugfs subsystem. */ @@ -1824,11 +1821,6 @@ MODULE_PARM_DESC(amsdu_size, module_param_named(fw_restart, iwlwifi_mod_params.fw_restart, bool, 0444); MODULE_PARM_DESC(fw_restart, "restart firmware in case of error (default true)"); -module_param_named(antenna_coupling, iwlwifi_mod_params.antenna_coupling, - int, 0444); -MODULE_PARM_DESC(antenna_coupling, - "specify antenna coupling in dB (default: 0 dB)"); - module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, 0444); MODULE_PARM_DESC(nvm_file, "NVM file name"); diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h index 2be30af7bdc3..8938a6467996 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-drv.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-drv.h @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2008 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2008 - 2014, 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * * This program is free software; you can redistribute it and/or modify @@ -26,7 +26,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2005 - 2014, 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * All rights reserved. * @@ -63,8 +63,7 @@ /* for all modules */ #define DRV_NAME "iwlwifi" -#define DRV_COPYRIGHT "Copyright(c) 2003- 2015 Intel Corporation" -#define DRV_AUTHOR "<[email protected]>" +#define DRV_AUTHOR "Intel Corporation <[email protected]>" /* radio config bits (actual values from NVM definition) */ #define NVM_RF_CFG_DASH_MSK(x) (x & 0x3) /* bits 0-1 */ diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h index bf673ce5f183..e77d8d13cb51 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-fh.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-fh.h @@ -7,7 +7,7 @@ * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2018 - 2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -29,7 +29,7 @@ * * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2018 - 2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -646,8 +646,7 @@ struct iwl_rb_status { #define TFD_QUEUE_CB_SIZE(x) (ilog2(x) - 3) #define TFD_QUEUE_SIZE_BC_DUP (64) #define TFD_QUEUE_BC_SIZE (TFD_QUEUE_SIZE_MAX + TFD_QUEUE_SIZE_BC_DUP) -#define TFD_QUEUE_BC_SIZE_GEN3 (TFD_QUEUE_SIZE_MAX_GEN3 + \ - TFD_QUEUE_SIZE_BC_DUP) +#define TFD_QUEUE_BC_SIZE_GEN3 1024 #define IWL_TX_DMA_MASK DMA_BIT_MASK(36) #define IWL_NUM_OF_TBS 20 #define IWL_TFH_NUM_TBS 25 diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h index b094cc1e9be0..e8ce3a300857 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-modparams.h @@ -5,8 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2007 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -26,8 +25,7 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2005 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -111,7 +109,6 @@ enum iwl_uapsd_disable { * @power_save: enable power save, default = false * @power_level: power level, default = 1 * @debug_level: levels are IWL_DL_* - * @antenna_coupling: antenna coupling in dB, default = 0 * @nvm_file: specifies a external NVM file * @uapsd_disable: disable U-APSD, see &enum iwl_uapsd_disable, default = * IWL_DISABLE_UAPSD_BSS | IWL_DISABLE_UAPSD_P2P_CLIENT @@ -131,7 +128,6 @@ struct iwl_mod_params { #ifdef CONFIG_IWLWIFI_DEBUG u32 debug_level; #endif - int antenna_coupling; char *nvm_file; u32 uapsd_disable; bool disable_11ac; diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h index 1136d9784f9d..8e254c0eda13 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-prph.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-prph.h @@ -5,10 +5,9 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 Intel Deutschland GmbH - * Copyright (C) 2018 - 2019 Intel Corporation + * Copyright(c) 2005 - 2014, 2018 - 2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,10 +27,9 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. - * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH + * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 Intel Deutschland GmbH - * Copyright (C) 2018 - 2019 Intel Corporation + * Copyright(c) 2005 - 2014, 2018 - 2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -326,6 +324,7 @@ #define RXF_SIZE_BYTE_CND_POS (7) #define RXF_SIZE_BYTE_CNT_MSK (0x3ff << RXF_SIZE_BYTE_CND_POS) #define RXF_DIFF_FROM_PREV (0x200) +#define RXF2C_DIFF_FROM_PREV (0x4e00) #define RXF_LD_FENCE_OFFSET_ADDR (0xa00c10) #define RXF_FIFO_RD_FENCE_ADDR (0xa00c0c) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c index 3d2abbc5c76c..5ae22cd7ecdb 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/coex.c @@ -5,7 +5,7 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2013 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * * This program is free software; you can redistribute it and/or modify @@ -26,7 +26,7 @@ * * BSD LICENSE * - * Copyright(c) 2013 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2013 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * All rights reserved. * @@ -216,8 +216,7 @@ int iwl_mvm_send_bt_init_conf(struct iwl_mvm *mvm) goto send_cmd; } - mode = iwlwifi_mod_params.bt_coex_active ? BT_COEX_NW : BT_COEX_DISABLE; - bt_cmd.mode = cpu_to_le32(mode); + bt_cmd.mode = cpu_to_le32(BT_COEX_NW); if (IWL_MVM_BT_COEX_SYNC2SCO) bt_cmd.enabled_modules |= diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c index 222775714859..2a94545d737f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/d3.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/d3.c @@ -5,10 +5,9 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,10 +27,9 @@ * * BSD LICENSE * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -80,9 +78,6 @@ void iwl_mvm_set_rekey_data(struct ieee80211_hw *hw, struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw); struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif); - if (iwlwifi_mod_params.swcrypto) - return; - mutex_lock(&mvm->mutex); memcpy(mvmvif->rekey_data.kek, data->kek, NL80211_KEK_LEN); @@ -843,18 +838,16 @@ iwl_mvm_wowlan_config(struct iwl_mvm *mvm, return ret; } - if (!iwlwifi_mod_params.swcrypto) { - /* - * This needs to be unlocked due to lock ordering - * constraints. Since we're in the suspend path - * that isn't really a problem though. - */ - mutex_unlock(&mvm->mutex); - ret = iwl_mvm_wowlan_config_key_params(mvm, vif, CMD_ASYNC); - mutex_lock(&mvm->mutex); - if (ret) - return ret; - } + /* + * This needs to be unlocked due to lock ordering + * constraints. Since we're in the suspend path + * that isn't really a problem though. + */ + mutex_unlock(&mvm->mutex); + ret = iwl_mvm_wowlan_config_key_params(mvm, vif, CMD_ASYNC); + mutex_lock(&mvm->mutex); + if (ret) + return ret; ret = iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0, sizeof(*wowlan_config_cmd), @@ -1993,6 +1986,9 @@ static int __iwl_mvm_resume(struct iwl_mvm *mvm, bool test) goto err; } + iwl_dbg_tlv_time_point(&mvm->fwrt, IWL_FW_INI_TIME_POINT_HOST_D3_END, + NULL); + ret = iwl_trans_d3_resume(mvm->trans, &d3_status, test, !unified_image); if (ret) goto err; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 3beef8d077b8..8fae7e707374 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -5,10 +5,9 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,10 +27,9 @@ * * BSD LICENSE * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -481,6 +479,11 @@ static ssize_t iwl_dbgfs_amsdu_len_write(struct ieee80211_sta *sta, if (kstrtou16(buf, 0, &amsdu_len)) return -EINVAL; + /* only change from debug set <-> debug unset */ + if ((amsdu_len && mvmsta->orig_amsdu_len) || + (!!amsdu_len && mvmsta->orig_amsdu_len)) + return -EBUSY; + if (amsdu_len) { mvmsta->orig_amsdu_len = sta->max_amsdu_len; sta->max_amsdu_len = amsdu_len; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c index cdb87139100d..aaa7dd1788b1 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ftm-initiator.c @@ -164,9 +164,10 @@ static void iwl_mvm_ftm_cmd_v5(struct iwl_mvm *mvm, struct ieee80211_vif *vif, eth_broadcast_addr(cmd->range_req_bssid); } -static void iwl_mvm_ftm_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, - struct iwl_tof_range_req_cmd *cmd, - struct cfg80211_pmsr_request *req) +static void iwl_mvm_ftm_cmd_common(struct iwl_mvm *mvm, + struct ieee80211_vif *vif, + struct iwl_tof_range_req_cmd *cmd, + struct cfg80211_pmsr_request *req) { int i; @@ -210,6 +211,13 @@ static void iwl_mvm_ftm_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, cmd->tsf_mac_id = cpu_to_le32(0xff); } +static void iwl_mvm_ftm_cmd_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct iwl_tof_range_req_cmd_v8 *cmd, + struct cfg80211_pmsr_request *req) +{ + iwl_mvm_ftm_cmd_common(mvm, vif, (void *)cmd, req); +} + static int iwl_mvm_ftm_target_chandef_v1(struct iwl_mvm *mvm, struct cfg80211_pmsr_request_peer *peer, @@ -382,9 +390,10 @@ iwl_mvm_ftm_put_target_v3(struct iwl_mvm *mvm, return 0; } -static int iwl_mvm_ftm_put_target_v4(struct iwl_mvm *mvm, - struct cfg80211_pmsr_request_peer *peer, - struct iwl_tof_range_req_ap_entry *target) +static int +iwl_mvm_ftm_put_target(struct iwl_mvm *mvm, + struct cfg80211_pmsr_request_peer *peer, + struct iwl_tof_range_req_ap_entry_v4 *target) { int ret; @@ -394,7 +403,7 @@ static int iwl_mvm_ftm_put_target_v4(struct iwl_mvm *mvm, if (ret) return ret; - iwl_mvm_ftm_put_target_common(mvm, peer, target); + iwl_mvm_ftm_put_target_common(mvm, peer, (void *)target); return 0; } @@ -456,7 +465,7 @@ static int iwl_mvm_ftm_start_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif, * Versions 7 and 8 has the same structure except from the responders * list, so iwl_mvm_ftm_cmd() can be used for version 7 too. */ - iwl_mvm_ftm_cmd(mvm, vif, (void *)&cmd_v7, req); + iwl_mvm_ftm_cmd_v8(mvm, vif, (void *)&cmd_v7, req); for (i = 0; i < cmd_v7.num_of_ap; i++) { struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; @@ -472,6 +481,32 @@ static int iwl_mvm_ftm_start_v7(struct iwl_mvm *mvm, struct ieee80211_vif *vif, static int iwl_mvm_ftm_start_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct cfg80211_pmsr_request *req) { + struct iwl_tof_range_req_cmd_v8 cmd; + struct iwl_host_cmd hcmd = { + .id = iwl_cmd_id(TOF_RANGE_REQ_CMD, LOCATION_GROUP, 0), + .dataflags[0] = IWL_HCMD_DFL_DUP, + .data[0] = &cmd, + .len[0] = sizeof(cmd), + }; + u8 i; + int err; + + iwl_mvm_ftm_cmd_v8(mvm, vif, (void *)&cmd, req); + + for (i = 0; i < cmd.num_of_ap; i++) { + struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; + + err = iwl_mvm_ftm_put_target(mvm, peer, &cmd.ap[i]); + if (err) + return err; + } + + return iwl_mvm_ftm_send_cmd(mvm, &hcmd); +} + +static int iwl_mvm_ftm_start_v9(struct iwl_mvm *mvm, struct ieee80211_vif *vif, + struct cfg80211_pmsr_request *req) +{ struct iwl_tof_range_req_cmd cmd; struct iwl_host_cmd hcmd = { .id = iwl_cmd_id(TOF_RANGE_REQ_CMD, LOCATION_GROUP, 0), @@ -482,12 +517,12 @@ static int iwl_mvm_ftm_start_v8(struct iwl_mvm *mvm, struct ieee80211_vif *vif, u8 i; int err; - iwl_mvm_ftm_cmd(mvm, vif, &cmd, req); + iwl_mvm_ftm_cmd_common(mvm, vif, &cmd, req); for (i = 0; i < cmd.num_of_ap; i++) { struct cfg80211_pmsr_request_peer *peer = &req->peers[i]; - err = iwl_mvm_ftm_put_target_v4(mvm, peer, &cmd.ap[i]); + err = iwl_mvm_ftm_put_target(mvm, peer, (void *)&cmd.ap[i]); if (err) return err; } @@ -511,11 +546,17 @@ int iwl_mvm_ftm_start(struct iwl_mvm *mvm, struct ieee80211_vif *vif, u8 cmd_ver = iwl_fw_lookup_cmd_ver(mvm->fw, LOCATION_GROUP, TOF_RANGE_REQ_CMD); - if (cmd_ver == 8) + switch (cmd_ver) { + case 9: + err = iwl_mvm_ftm_start_v9(mvm, vif, req); + break; + case 8: err = iwl_mvm_ftm_start_v8(mvm, vif, req); - else + break; + default: err = iwl_mvm_ftm_start_v7(mvm, vif, req); - + break; + } } else { err = iwl_mvm_ftm_start_v5(mvm, vif, req); } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c index 164fc9e98c86..5e8d3f8c3d86 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/fw.c @@ -87,50 +87,6 @@ struct iwl_mvm_alive_data { u32 scd_base_addr; }; -/* set device type and latency */ -static int iwl_set_soc_latency(struct iwl_mvm *mvm) -{ - struct iwl_soc_configuration_cmd cmd = {}; - int ret; - - /* - * In VER_1 of this command, the discrete value is considered - * an integer; In VER_2, it's a bitmask. Since we have only 2 - * values in VER_1, this is backwards-compatible with VER_2, - * as long as we don't set any other bits. - */ - if (!mvm->trans->trans_cfg->integrated) - cmd.flags = cpu_to_le32(SOC_CONFIG_CMD_FLAGS_DISCRETE); - - BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_NONE != - SOC_FLAGS_LTR_APPLY_DELAY_NONE); - BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_200US != - SOC_FLAGS_LTR_APPLY_DELAY_200); - BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_2500US != - SOC_FLAGS_LTR_APPLY_DELAY_2500); - BUILD_BUG_ON(IWL_CFG_TRANS_LTR_DELAY_1820US != - SOC_FLAGS_LTR_APPLY_DELAY_1820); - - if (mvm->trans->trans_cfg->ltr_delay != IWL_CFG_TRANS_LTR_DELAY_NONE && - !WARN_ON(!mvm->trans->trans_cfg->integrated)) - cmd.flags |= le32_encode_bits(mvm->trans->trans_cfg->ltr_delay, - SOC_FLAGS_LTR_APPLY_DELAY_MASK); - - if (iwl_fw_lookup_cmd_ver(mvm->fw, IWL_ALWAYS_LONG_GROUP, - SCAN_REQ_UMAC) >= 2 && - mvm->trans->trans_cfg->low_latency_xtal) - cmd.flags |= cpu_to_le32(SOC_CONFIG_CMD_FLAGS_LOW_LATENCY); - - cmd.latency = cpu_to_le32(mvm->trans->trans_cfg->xtal_latency); - - ret = iwl_mvm_send_cmd_pdu(mvm, iwl_cmd_id(SOC_CONFIGURATION_CMD, - SYSTEM_GROUP, 0), 0, - sizeof(cmd), &cmd); - if (ret) - IWL_ERR(mvm, "Failed to set soc latency: %d\n", ret); - return ret; -} - static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant) { struct iwl_tx_ant_cfg_cmd tx_ant_cmd = { @@ -787,13 +743,12 @@ int iwl_mvm_sar_select_profile(struct iwl_mvm *mvm, int prof_a, int prof_b) union { struct iwl_dev_tx_power_cmd v5; struct iwl_dev_tx_power_cmd_v4 v4; - } cmd; - + } cmd = { + .v5.v3.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS), + }; int ret; u16 len = 0; - cmd.v5.v3.set_mode = cpu_to_le32(IWL_TX_POWER_MODE_SET_CHAINS); - if (fw_has_api(&mvm->fw->ucode_capa, IWL_UCODE_TLV_API_REDUCE_TX_POWER)) len = sizeof(cmd.v5); @@ -1238,7 +1193,7 @@ int iwl_mvm_up(struct iwl_mvm *mvm) if (fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_SOC_LATENCY_SUPPORT)) { - ret = iwl_set_soc_latency(mvm); + ret = iwl_set_soc_latency(&mvm->fwrt); if (ret) goto error; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c index 853ba7b8bf3f..10df77ab1a77 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mac80211.c @@ -475,23 +475,23 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) hw->wiphy->n_cipher_suites++; } - /* Enable 11w if software crypto is not enabled (as the - * firmware will interpret some mgmt packets, so enabling it - * with software crypto isn't safe). - */ - if (!iwlwifi_mod_params.swcrypto) { - ieee80211_hw_set(hw, MFP_CAPABLE); + if (iwlwifi_mod_params.swcrypto) + IWL_ERR(mvm, + "iwlmvm doesn't allow to disable HW crypto, check swcrypto module parameter\n"); + if (!iwlwifi_mod_params.bt_coex_active) + IWL_ERR(mvm, + "iwlmvm doesn't allow to disable BT Coex, check bt_coex_active module parameter\n"); + + ieee80211_hw_set(hw, MFP_CAPABLE); + mvm->ciphers[hw->wiphy->n_cipher_suites] = WLAN_CIPHER_SUITE_AES_CMAC; + hw->wiphy->n_cipher_suites++; + if (iwl_mvm_has_new_rx_api(mvm)) { mvm->ciphers[hw->wiphy->n_cipher_suites] = - WLAN_CIPHER_SUITE_AES_CMAC; + WLAN_CIPHER_SUITE_BIP_GMAC_128; + hw->wiphy->n_cipher_suites++; + mvm->ciphers[hw->wiphy->n_cipher_suites] = + WLAN_CIPHER_SUITE_BIP_GMAC_256; hw->wiphy->n_cipher_suites++; - if (iwl_mvm_has_new_rx_api(mvm)) { - mvm->ciphers[hw->wiphy->n_cipher_suites] = - WLAN_CIPHER_SUITE_BIP_GMAC_128; - hw->wiphy->n_cipher_suites++; - mvm->ciphers[hw->wiphy->n_cipher_suites] = - WLAN_CIPHER_SUITE_BIP_GMAC_256; - hw->wiphy->n_cipher_suites++; - } } /* currently FW API supports only one optional cipher scheme */ @@ -697,10 +697,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) WIPHY_WOWLAN_EAP_IDENTITY_REQ | WIPHY_WOWLAN_RFKILL_RELEASE | WIPHY_WOWLAN_NET_DETECT; - if (!iwlwifi_mod_params.swcrypto) - mvm->wowlan.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | - WIPHY_WOWLAN_GTK_REKEY_FAILURE | - WIPHY_WOWLAN_4WAY_HANDSHAKE; + mvm->wowlan.flags |= WIPHY_WOWLAN_SUPPORTS_GTK_REKEY | + WIPHY_WOWLAN_GTK_REKEY_FAILURE | + WIPHY_WOWLAN_4WAY_HANDSHAKE; mvm->wowlan.n_patterns = IWL_WOWLAN_MAX_PATTERNS; mvm->wowlan.pattern_min_len = IWL_WOWLAN_MIN_PATTERN_LEN; @@ -2180,6 +2179,15 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm, flags |= STA_CTXT_HE_PACKET_EXT; } } + + if (sta->he_cap.he_cap_elem.mac_cap_info[2] & + IEEE80211_HE_MAC_CAP2_32BIT_BA_BITMAP) + flags |= STA_CTXT_HE_32BIT_BA_BITMAP; + + if (sta->he_cap.he_cap_elem.mac_cap_info[2] & + IEEE80211_HE_MAC_CAP2_ACK_EN) + flags |= STA_CTXT_HE_ACK_ENABLED; + rcu_read_unlock(); /* Mark MU EDCA as enabled, unless none detected on some AC */ @@ -2204,11 +2212,6 @@ static void iwl_mvm_cfg_he_sta(struct iwl_mvm *mvm, cpu_to_le16(mu_edca->mu_edca_timer); } - if (vif->bss_conf.multi_sta_back_32bit) - flags |= STA_CTXT_HE_32BIT_BA_BITMAP; - - if (vif->bss_conf.ack_enabled) - flags |= STA_CTXT_HE_ACK_ENABLED; if (vif->bss_conf.uora_exists) { flags |= STA_CTXT_HE_TRIG_RND_ALLOC; @@ -3366,11 +3369,6 @@ static int __iwl_mvm_mac_set_key(struct ieee80211_hw *hw, int ret, i; u8 key_offset; - if (iwlwifi_mod_params.swcrypto) { - IWL_DEBUG_MAC80211(mvm, "leave - hwcrypto disabled\n"); - return -EOPNOTSUPP; - } - switch (key->cipher) { case WLAN_CIPHER_SUITE_TKIP: if (!mvm->trans->trans_cfg->gen2) { diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h index 9e2a0858108c..e2f7f6ec711e 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h +++ b/drivers/net/wireless/intel/iwlwifi/mvm/mvm.h @@ -5,10 +5,9 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,10 +27,9 @@ * * BSD LICENSE * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -134,12 +132,10 @@ extern const struct ieee80211_ops iwl_mvm_hw_ops; * We will register to mac80211 to have testmode working. The NIC must not * be up'ed after the INIT fw asserted. This is useful to be able to use * proprietary tools over testmode to debug the INIT fw. - * @tfd_q_hang_detect: enabled the detection of hung transmit queues * @power_scheme: one of enum iwl_power_scheme */ struct iwl_mvm_mod_params { bool init_dbg; - bool tfd_q_hang_detect; int power_scheme; }; extern struct iwl_mvm_mod_params iwlmvm_mod_params; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c index d0afc806706d..d095ff847be9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/ops.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/ops.c @@ -5,10 +5,9 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,10 +27,9 @@ * * BSD LICENSE * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -86,7 +84,7 @@ #define DRV_DESCRIPTION "The new Intel(R) wireless AGN driver for Linux" MODULE_DESCRIPTION(DRV_DESCRIPTION); -MODULE_AUTHOR(DRV_COPYRIGHT " " DRV_AUTHOR); +MODULE_AUTHOR(DRV_AUTHOR); MODULE_LICENSE("GPL"); static const struct iwl_op_mode_ops iwl_mvm_ops; @@ -94,7 +92,6 @@ static const struct iwl_op_mode_ops iwl_mvm_ops_mq; struct iwl_mvm_mod_params iwlmvm_mod_params = { .power_scheme = IWL_POWER_SCHEME_BPS, - .tfd_q_hang_detect = true /* rest of fields are 0 by default */ }; @@ -104,10 +101,6 @@ MODULE_PARM_DESC(init_dbg, module_param_named(power_scheme, iwlmvm_mod_params.power_scheme, int, 0444); MODULE_PARM_DESC(power_scheme, "power management scheme: 1-active, 2-balanced, 3-low power, default: 2"); -module_param_named(tfd_q_hang_detect, iwlmvm_mod_params.tfd_q_hang_detect, - bool, 0444); -MODULE_PARM_DESC(tfd_q_hang_detect, - "TFD queues hang detection (default: true"); /* * module init and exit functions diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c index 15d11fb72aca..6f4d241d47e9 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rs-fw.c @@ -369,14 +369,15 @@ void iwl_mvm_tlc_update_notif(struct iwl_mvm *mvm, u16 size = le32_to_cpu(notif->amsdu_size); int i; - /* - * In debug sta->max_amsdu_len < size - * so also check with orig_amsdu_len which holds the original - * data before debugfs changed the value - */ - if (WARN_ON(sta->max_amsdu_len < size && - mvmsta->orig_amsdu_len < size)) + if (sta->max_amsdu_len < size) { + /* + * In debug sta->max_amsdu_len < size + * so also check with orig_amsdu_len which holds the + * original data before debugfs changed the value + */ + WARN_ON(mvmsta->orig_amsdu_len < size); goto out; + } mvmsta->amsdu_enabled = le32_to_cpu(notif->amsdu_enabled); mvmsta->max_amsdu_len = size; diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index 56ae72debb96..44d4720b7629 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -5,10 +5,9 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved. + * Copyright(c) 2012 - 2015, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,10 +27,9 @@ * * BSD LICENSE * - * Copyright(c) 2012 - 2015 Intel Corporation. All rights reserved. + * Copyright(c) 2012 - 2015, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -751,16 +749,23 @@ static int iwl_mvm_tvqm_enable_txq(struct iwl_mvm *mvm, size = max_t(u32, IWL_MGMT_QUEUE_SIZE, mvm->trans->cfg->min_txq_size); } - queue = iwl_trans_txq_alloc(mvm->trans, - cpu_to_le16(TX_QUEUE_CFG_ENABLE_QUEUE), - sta_id, tid, SCD_QUEUE_CFG, size, timeout); - if (queue < 0) { - IWL_DEBUG_TX_QUEUES(mvm, - "Failed allocating TXQ for sta %d tid %d, ret: %d\n", - sta_id, tid, queue); + do { + __le16 enable = cpu_to_le16(TX_QUEUE_CFG_ENABLE_QUEUE); + + queue = iwl_trans_txq_alloc(mvm->trans, enable, + sta_id, tid, SCD_QUEUE_CFG, + size, timeout); + + if (queue < 0) + IWL_DEBUG_TX_QUEUES(mvm, + "Failed allocating TXQ of size %d for sta %d tid %d, ret: %d\n", + size, sta_id, tid, queue); + size /= 2; + } while (queue < 0 && size >= 16); + + if (queue < 0) return queue; - } IWL_DEBUG_TX_QUEUES(mvm, "Enabling TXQ #%d for sta %d tid %d\n", queue, sta_id, tid); @@ -1395,7 +1400,17 @@ void iwl_mvm_add_new_dqa_stream_wk(struct work_struct *wk) if (tid == IEEE80211_NUM_TIDS) tid = IWL_MAX_TID_COUNT; - iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, tid); + /* + * We can't really do much here, but if this fails we can't + * transmit anyway - so just don't transmit the frame etc. + * and let them back up ... we've tried our best to allocate + * a queue in the function itself. + */ + if (iwl_mvm_sta_alloc_queue(mvm, txq->sta, txq->ac, tid)) { + list_del_init(&mvmtxq->list); + continue; + } + list_del_init(&mvmtxq->list); local_bh_disable(); iwl_mvm_mac_itxq_xmit(mvm->hw, txq); @@ -1965,9 +1980,8 @@ void iwl_mvm_dealloc_int_sta(struct iwl_mvm *mvm, struct iwl_mvm_int_sta *sta) static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 queue, u8 sta_id, u8 fifo) { - unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? - mvm->trans->trans_cfg->base_params->wd_timeout : - IWL_WATCHDOG_DISABLED; + unsigned int wdg_timeout = + mvm->trans->trans_cfg->base_params->wd_timeout; struct iwl_trans_txq_scd_cfg cfg = { .fifo = fifo, .sta_id = sta_id, @@ -1983,9 +1997,8 @@ static void iwl_mvm_enable_aux_snif_queue(struct iwl_mvm *mvm, u16 queue, static int iwl_mvm_enable_aux_snif_queue_tvqm(struct iwl_mvm *mvm, u8 sta_id) { - unsigned int wdg_timeout = iwlmvm_mod_params.tfd_q_hang_detect ? - mvm->trans->trans_cfg->base_params->wd_timeout : - IWL_WATCHDOG_DISABLED; + unsigned int wdg_timeout = + mvm->trans->trans_cfg->base_params->wd_timeout; WARN_ON(!iwl_mvm_has_new_tx_api(mvm)); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c index a8d0d17f79fd..2f6484e0d726 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/tx.c @@ -8,7 +8,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2018 - 2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2018 - 2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -920,11 +920,8 @@ static int iwl_mvm_tx_tso(struct iwl_mvm *mvm, struct sk_buff *skb, * No need to lock amsdu_in_ampdu_allowed since it can't be modified * during an BA session. */ - if (info->flags & IEEE80211_TX_CTL_AMPDU && - !mvmsta->tid_data[tid].amsdu_in_ampdu_allowed) - return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); - - if (iwl_mvm_vif_low_latency(iwl_mvm_vif_from_mac80211(mvmsta->vif)) || + if ((info->flags & IEEE80211_TX_CTL_AMPDU && + !mvmsta->tid_data[tid].amsdu_in_ampdu_allowed) || !(mvmsta->amsdu_enabled & BIT(tid))) return iwl_mvm_tx_tso_segment(skb, 1, netdev_flags, mpdus_skb); diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c index 6096276cb0d0..be57b8391850 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/utils.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/utils.c @@ -5,10 +5,9 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright (C) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,10 +27,9 @@ * * BSD LICENSE * - * Copyright(c) 2012 - 2014 Intel Corporation. All rights reserved. + * Copyright(c) 2012 - 2014, 2018 - 2020 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2014 Intel Mobile Communications GmbH * Copyright (C) 2015 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -588,6 +586,23 @@ static void iwl_mvm_dump_lmac_error_log(struct iwl_mvm *mvm, u8 lmac_num) IWL_ERR(mvm, "0x%08X | flow_handler\n", table.flow_handler); } +static void iwl_mvm_dump_iml_error_log(struct iwl_mvm *mvm) +{ + struct iwl_trans *trans = mvm->trans; + u32 error; + + error = iwl_read_umac_prph(trans, UMAG_SB_CPU_2_STATUS); + + IWL_ERR(trans, "IML/ROM dump:\n"); + + if (error & 0xFFFF0000) + IWL_ERR(trans, "IML/ROM SYSASSERT:\n"); + + IWL_ERR(mvm, "0x%08X | IML/ROM error/state\n", error); + IWL_ERR(mvm, "0x%08X | IML/ROM data1\n", + iwl_read_umac_prph(trans, UMAG_SB_CPU_1_STATUS)); +} + void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) { if (!test_bit(STATUS_DEVICE_ENABLED, &mvm->trans->status)) { @@ -603,6 +618,9 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm) iwl_mvm_dump_umac_error_log(mvm); + if (mvm->trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) + iwl_mvm_dump_iml_error_log(mvm); + iwl_fw_error_print_fseq_regs(&mvm->fwrt); } @@ -952,8 +970,7 @@ unsigned int iwl_mvm_get_wd_timeout(struct iwl_mvm *mvm, IWL_UCODE_TLV_CAPA_STA_PM_NOTIF) && vif && vif->type == NL80211_IFTYPE_AP) return IWL_WATCHDOG_DISABLED; - return iwlmvm_mod_params.tfd_q_hang_detect ? - default_timeout : IWL_WATCHDOG_DISABLED; + return default_timeout; } trigger = iwl_fw_dbg_get_trigger(mvm->fw, FW_DBG_TRIGGER_TXQ_TIMERS); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 2083eb4f2f15..f179cd08b418 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -5,10 +5,9 @@ * * GPL LICENSE SUMMARY * - * Copyright(c) 2007 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016-2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2007 - 2014, 2018 - 2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -28,11 +27,10 @@ * * BSD LICENSE * - * Copyright(c) 2005 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * All rights reserved. * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2005 - 2014, 2018 - 2020 Intel Corporation * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -592,107 +590,72 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_DEV_INFO(0x2723, 0x1654, iwl_ax200_cfg_cc, iwl_ax200_killer_1650x_name), IWL_DEV_INFO(0x2723, IWL_CFG_ANY, iwl_ax200_cfg_cc, iwl_ax200_name), -/* Qu with Hr */ - IWL_DEV_INFO(0x43F0, 0x0044, iwl_ax101_cfg_qu_hr, NULL), + /* QnJ with Hr */ + IWL_DEV_INFO(0x2720, IWL_CFG_ANY, iwl_qnj_b0_hr_b0_cfg, iwl_ax201_name), + + /* Qu with Hr */ IWL_DEV_INFO(0x43F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x43F0, 0x0074, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x43F0, 0x0078, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x43F0, 0x007C, iwl_ax201_cfg_qu_hr, NULL), - IWL_DEV_INFO(0x43F0, 0x0244, iwl_ax101_cfg_qu_hr, NULL), - IWL_DEV_INFO(0x43F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, NULL), - IWL_DEV_INFO(0x43F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, NULL), IWL_DEV_INFO(0x43F0, 0x2074, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x43F0, 0x4070, iwl_ax201_cfg_qu_hr, NULL), - IWL_DEV_INFO(0x43F0, 0x4244, iwl_ax101_cfg_qu_hr, NULL), - IWL_DEV_INFO(0xA0F0, 0x0044, iwl_ax101_cfg_qu_hr, NULL), IWL_DEV_INFO(0xA0F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0xA0F0, 0x0074, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0xA0F0, 0x0078, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0xA0F0, 0x007C, iwl_ax201_cfg_qu_hr, NULL), - IWL_DEV_INFO(0xA0F0, 0x0244, iwl_ax101_cfg_qu_hr, NULL), IWL_DEV_INFO(0xA0F0, 0x0A10, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0xA0F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, NULL), IWL_DEV_INFO(0xA0F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, NULL), IWL_DEV_INFO(0xA0F0, 0x2074, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0xA0F0, 0x4070, iwl_ax201_cfg_qu_hr, NULL), - IWL_DEV_INFO(0xA0F0, 0x4244, iwl_ax101_cfg_qu_hr, NULL), IWL_DEV_INFO(0x02F0, 0x0070, iwl_ax201_cfg_quz_hr, NULL), IWL_DEV_INFO(0x02F0, 0x0074, iwl_ax201_cfg_quz_hr, NULL), IWL_DEV_INFO(0x02F0, 0x0078, iwl_ax201_cfg_quz_hr, NULL), IWL_DEV_INFO(0x02F0, 0x007C, iwl_ax201_cfg_quz_hr, NULL), - IWL_DEV_INFO(0x02F0, 0x0244, iwl_ax101_cfg_quz_hr, NULL), IWL_DEV_INFO(0x02F0, 0x0310, iwl_ax201_cfg_quz_hr, NULL), IWL_DEV_INFO(0x02F0, 0x1651, iwl_ax1650s_cfg_quz_hr, NULL), IWL_DEV_INFO(0x02F0, 0x1652, iwl_ax1650i_cfg_quz_hr, NULL), IWL_DEV_INFO(0x02F0, 0x2074, iwl_ax201_cfg_quz_hr, NULL), IWL_DEV_INFO(0x02F0, 0x4070, iwl_ax201_cfg_quz_hr, NULL), - IWL_DEV_INFO(0x02F0, 0x4244, iwl_ax101_cfg_quz_hr, NULL), IWL_DEV_INFO(0x06F0, 0x0070, iwl_ax201_cfg_quz_hr, NULL), IWL_DEV_INFO(0x06F0, 0x0074, iwl_ax201_cfg_quz_hr, NULL), IWL_DEV_INFO(0x06F0, 0x0078, iwl_ax201_cfg_quz_hr, NULL), IWL_DEV_INFO(0x06F0, 0x007C, iwl_ax201_cfg_quz_hr, NULL), - IWL_DEV_INFO(0x06F0, 0x0244, iwl_ax101_cfg_quz_hr, NULL), IWL_DEV_INFO(0x06F0, 0x0310, iwl_ax201_cfg_quz_hr, NULL), IWL_DEV_INFO(0x06F0, 0x1651, iwl_ax1650s_cfg_quz_hr, NULL), IWL_DEV_INFO(0x06F0, 0x1652, iwl_ax1650i_cfg_quz_hr, NULL), IWL_DEV_INFO(0x06F0, 0x2074, iwl_ax201_cfg_quz_hr, NULL), IWL_DEV_INFO(0x06F0, 0x4070, iwl_ax201_cfg_quz_hr, NULL), - IWL_DEV_INFO(0x06F0, 0x4244, iwl_ax101_cfg_quz_hr, NULL), - IWL_DEV_INFO(0x34F0, 0x0044, iwl_ax101_cfg_qu_hr, NULL), IWL_DEV_INFO(0x34F0, 0x0070, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x34F0, 0x0074, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x34F0, 0x0078, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x34F0, 0x007C, iwl_ax201_cfg_qu_hr, NULL), - IWL_DEV_INFO(0x34F0, 0x0244, iwl_ax101_cfg_qu_hr, NULL), IWL_DEV_INFO(0x34F0, 0x0310, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x34F0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, NULL), IWL_DEV_INFO(0x34F0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, NULL), IWL_DEV_INFO(0x34F0, 0x2074, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x34F0, 0x4070, iwl_ax201_cfg_qu_hr, NULL), - IWL_DEV_INFO(0x34F0, 0x4244, iwl_ax101_cfg_qu_hr, NULL), - IWL_DEV_INFO(0x3DF0, 0x0044, iwl_ax101_cfg_qu_hr, NULL), IWL_DEV_INFO(0x3DF0, 0x0070, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x3DF0, 0x0074, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x3DF0, 0x0078, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x3DF0, 0x007C, iwl_ax201_cfg_qu_hr, NULL), - IWL_DEV_INFO(0x3DF0, 0x0244, iwl_ax101_cfg_qu_hr, NULL), IWL_DEV_INFO(0x3DF0, 0x0310, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x3DF0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, NULL), IWL_DEV_INFO(0x3DF0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, NULL), IWL_DEV_INFO(0x3DF0, 0x2074, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x3DF0, 0x4070, iwl_ax201_cfg_qu_hr, NULL), - IWL_DEV_INFO(0x3DF0, 0x4244, iwl_ax101_cfg_qu_hr, NULL), - IWL_DEV_INFO(0x4DF0, 0x0044, iwl_ax101_cfg_qu_hr, NULL), IWL_DEV_INFO(0x4DF0, 0x0070, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x4DF0, 0x0074, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x4DF0, 0x0078, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x4DF0, 0x007C, iwl_ax201_cfg_qu_hr, NULL), - IWL_DEV_INFO(0x4DF0, 0x0244, iwl_ax101_cfg_qu_hr, NULL), IWL_DEV_INFO(0x4DF0, 0x0310, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x4DF0, 0x1651, killer1650s_2ax_cfg_qu_b0_hr_b0, NULL), IWL_DEV_INFO(0x4DF0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, NULL), IWL_DEV_INFO(0x4DF0, 0x2074, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x4DF0, 0x4070, iwl_ax201_cfg_qu_hr, NULL), - IWL_DEV_INFO(0x4DF0, 0x4244, iwl_ax101_cfg_qu_hr, NULL), - - IWL_DEV_INFO(0x2720, 0x0000, iwl22000_2ax_cfg_qnj_hr_b0, NULL), - IWL_DEV_INFO(0x2720, 0x0040, iwl22000_2ax_cfg_qnj_hr_b0, NULL), - IWL_DEV_INFO(0x2720, 0x0044, iwl22000_2ax_cfg_qnj_hr_b0, NULL), - IWL_DEV_INFO(0x2720, 0x0070, iwl22000_2ax_cfg_qnj_hr_b0, NULL), - IWL_DEV_INFO(0x2720, 0x0074, iwl22000_2ax_cfg_qnj_hr_b0, NULL), - IWL_DEV_INFO(0x2720, 0x0078, iwl22000_2ax_cfg_qnj_hr_b0, NULL), - IWL_DEV_INFO(0x2720, 0x007C, iwl22000_2ax_cfg_qnj_hr_b0, NULL), - IWL_DEV_INFO(0x2720, 0x0244, iwl22000_2ax_cfg_qnj_hr_b0, NULL), - IWL_DEV_INFO(0x2720, 0x0310, iwl22000_2ax_cfg_qnj_hr_b0, NULL), - IWL_DEV_INFO(0x2720, 0x0A10, iwl22000_2ax_cfg_qnj_hr_b0, NULL), - IWL_DEV_INFO(0x2720, 0x1080, iwl22000_2ax_cfg_qnj_hr_b0, NULL), - IWL_DEV_INFO(0x2720, 0x1651, iwl22000_2ax_cfg_qnj_hr_b0, NULL), - IWL_DEV_INFO(0x2720, 0x1652, iwl22000_2ax_cfg_qnj_hr_b0, NULL), - IWL_DEV_INFO(0x2720, 0x2074, iwl22000_2ax_cfg_qnj_hr_b0, NULL), - IWL_DEV_INFO(0x2720, 0x4070, iwl22000_2ax_cfg_qnj_hr_b0, NULL), - IWL_DEV_INFO(0x2720, 0x4244, iwl22000_2ax_cfg_qnj_hr_b0, NULL), _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_PU, IWL_CFG_ANY, @@ -791,7 +754,7 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_CFG_NO_160, IWL_CFG_CORES_BT, iwl9260_2ac_cfg, iwl9260_name), - /* Qu with Jf */ +/* Qu with Jf */ /* Qu B step */ _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP, @@ -967,6 +930,29 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_CFG_RF_TYPE_JF2, IWL_CFG_RF_ID_JF, IWL_CFG_NO_160, IWL_CFG_CORES_BT, iwl9560_qnj_b0_jf_b0_cfg, iwl9560_killer_1550i_name), + +/* Qu with Hr */ + /* Qu B step */ + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_QU, SILICON_B_STEP, + IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, + iwl_qu_b0_hr1_b0, iwl_ax101_name), + + /* Qu C step */ + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_QU, SILICON_C_STEP, + IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, + iwl_qu_c0_hr1_b0, iwl_ax101_name), + + /* QuZ */ + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_QUZ, IWL_CFG_ANY, + IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, + IWL_CFG_ANY, IWL_CFG_ANY, + iwl_quz_a0_hr1_b0, iwl_ax101_name), + #endif /* CONFIG_IWLMVM */ }; @@ -1064,29 +1050,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF4)) { iwl_trans->cfg = &iwlax411_2ax_cfg_so_gf4_a0; } - } else if (cfg == &iwl_ax101_cfg_qu_hr) { - if ((CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == - CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) && - iwl_trans->hw_rev == CSR_HW_REV_TYPE_QNJ_B0) || - (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == - CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR1))) { - iwl_trans->cfg = &iwl22000_2ax_cfg_qnj_hr_b0; - } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == - CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR) && - iwl_trans->hw_rev == CSR_HW_REV_TYPE_QUZ) { - iwl_trans->cfg = &iwl_ax101_cfg_quz_hr; - } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == - CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) { - iwl_trans->cfg = &iwl_ax101_cfg_qu_hr; - } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id) == - CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HRCDB)) { - IWL_ERR(iwl_trans, "RF ID HRCDB is not supported\n"); - return -EINVAL; - } else { - IWL_ERR(iwl_trans, "Unrecognized RF ID 0x%08x\n", - CSR_HW_RF_ID_TYPE_CHIP_ID(iwl_trans->hw_rf_id)); - return -EINVAL; - } } /* @@ -1096,9 +1059,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * rest must be removed once we convert Qu with Hr as well. */ if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QU_C0) { - if (iwl_trans->cfg == &iwl_ax101_cfg_qu_hr) - iwl_trans->cfg = &iwl_ax101_cfg_qu_c0_hr_b0; - else if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr) + if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr) iwl_trans->cfg = &iwl_ax201_cfg_qu_c0_hr_b0; else if (iwl_trans->cfg == &killer1650s_2ax_cfg_qu_b0_hr_b0) iwl_trans->cfg = &killer1650s_2ax_cfg_qu_c0_hr_b0; @@ -1108,9 +1069,7 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* same thing for QuZ... */ if (iwl_trans->hw_rev == CSR_HW_REV_TYPE_QUZ) { - if (iwl_trans->cfg == &iwl_ax101_cfg_qu_hr) - iwl_trans->cfg = &iwl_ax101_cfg_quz_hr; - else if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr) + if (iwl_trans->cfg == &iwl_ax201_cfg_qu_hr) iwl_trans->cfg = &iwl_ax201_cfg_quz_hr; } @@ -1162,12 +1121,6 @@ static int iwl_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* register transport layer debugfs here */ iwl_trans_pcie_dbgfs_register(iwl_trans); - /* The PCI device starts with a reference taken and we are - * supposed to release it here. But to simplify the - * interaction with the opmode, we don't do it now, but let - * the opmode release it when it's ready. - */ - return 0; out_free_trans: diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h index abe649af689c..b76c0396335a 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/internal.h @@ -189,6 +189,8 @@ struct iwl_rx_completion_desc { * @rb_stts_dma: bus address of receive buffer status * @lock: * @queue: actual rx queue. Not used for multi-rx queue. + * @next_rb_is_fragment: indicates that the previous RB that we handled set + * the fragmented flag, so the next one is still another fragment * * NOTE: rx_free and rx_used are used as a FIFO for iwl_rx_mem_buffers */ @@ -214,7 +216,7 @@ struct iwl_rxq { u32 queue_size; struct list_head rx_free; struct list_head rx_used; - bool need_update; + bool need_update, next_rb_is_fragment; void *rb_stts; dma_addr_t rb_stts_dma; spinlock_t lock; @@ -556,6 +558,7 @@ struct iwl_trans_pcie { u32 scd_base_addr; struct iwl_dma_ptr scd_bc_tbls; struct iwl_dma_ptr kw; + struct dma_pool *bc_pool; struct iwl_txq *txq_memory; struct iwl_txq *txq[IWL_MAX_TVQM_QUEUES]; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c index 8c29071cb415..72d1cf27e6a4 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/rx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/rx.c @@ -1427,7 +1427,8 @@ static void iwl_pcie_rx_handle_rb(struct iwl_trans *trans, } static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans, - struct iwl_rxq *rxq, int i) + struct iwl_rxq *rxq, int i, + bool *join) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_rx_mem_buffer *rxb; @@ -1441,10 +1442,12 @@ static struct iwl_rx_mem_buffer *iwl_pcie_get_rxb(struct iwl_trans *trans, return rxb; } - if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { vid = le16_to_cpu(rxq->cd[i].rbid); - else + *join = rxq->cd[i].flags & IWL_RX_CD_FLAGS_FRAGMENTED; + } else { vid = le32_to_cpu(rxq->bd_32[i]) & 0x0FFF; /* 12-bit VID */ + } if (!vid || vid > RX_POOL_SIZE(trans_pcie->num_rx_bufs)) goto out_err; @@ -1502,6 +1505,7 @@ restart: u32 rb_pending_alloc = atomic_read(&trans_pcie->rba.req_pending) * RX_CLAIM_REQ_ALLOC; + bool join = false; if (unlikely(rb_pending_alloc >= rxq->queue_size / 2 && !emergency)) { @@ -1514,11 +1518,29 @@ restart: IWL_DEBUG_RX(trans, "Q %d: HW = %d, SW = %d\n", rxq->id, r, i); - rxb = iwl_pcie_get_rxb(trans, rxq, i); + rxb = iwl_pcie_get_rxb(trans, rxq, i, &join); if (!rxb) goto out; - iwl_pcie_rx_handle_rb(trans, rxq, rxb, emergency, i); + if (unlikely(join || rxq->next_rb_is_fragment)) { + rxq->next_rb_is_fragment = join; + /* + * We can only get a multi-RB in the following cases: + * - firmware issue, sending a too big notification + * - sniffer mode with a large A-MSDU + * - large MTU frames (>2k) + * since the multi-RB functionality is limited to newer + * hardware that cannot put multiple entries into a + * single RB. + * + * Right now, the higher layers aren't set up to deal + * with that, so discard all of these. + */ + list_add_tail(&rxb->list, &rxq->rx_free); + rxq->free_count++; + } else { + iwl_pcie_rx_handle_rb(trans, rxq, rxb, emergency, i); + } i = (i + 1) & (rxq->queue_size - 1); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index a0daae058c1c..8ccfc7cc7348 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -3672,6 +3672,25 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, init_waitqueue_head(&trans_pcie->sx_waitq); + /* + * For gen2 devices, we use a single allocation for each byte-count + * table, but they're pretty small (1k) so use a DMA pool that we + * allocate here. + */ + if (cfg_trans->gen2) { + size_t bc_tbl_size; + + if (cfg_trans->device_family >= IWL_DEVICE_FAMILY_AX210) + bc_tbl_size = sizeof(struct iwl_gen3_bc_tbl); + else + bc_tbl_size = sizeof(struct iwlagn_scd_bc_tbl); + + trans_pcie->bc_pool = dmam_pool_create("iwlwifi:bc", &pdev->dev, + bc_tbl_size, 256, 0); + if (!trans_pcie->bc_pool) + goto out_no_pci; + } + if (trans_pcie->msix_enabled) { ret = iwl_pcie_init_msix_handler(pdev, trans_pcie); if (ret) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c index 53747ac945b8..bb55563bba68 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx-gen2.c @@ -6,7 +6,7 @@ * GPL LICENSE SUMMARY * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2018 - 2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -20,7 +20,7 @@ * BSD LICENSE * * Copyright(c) 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2018 - 2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -1224,7 +1224,9 @@ void iwl_pcie_gen2_txq_free_memory(struct iwl_trans *trans, } kfree(txq->entries); - iwl_pcie_free_dma_ptr(trans, &txq->bc_tbl); + if (txq->bc_tbl.addr) + dma_pool_free(trans_pcie->bc_pool, txq->bc_tbl.addr, + txq->bc_tbl.dma); kfree(txq); } @@ -1272,18 +1274,29 @@ int iwl_trans_pcie_dyn_txq_alloc_dma(struct iwl_trans *trans, struct iwl_txq **intxq, int size, unsigned int timeout) { + struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); + size_t bc_tbl_size, bc_tbl_entries; + struct iwl_txq *txq; int ret; - struct iwl_txq *txq; + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { + bc_tbl_size = sizeof(struct iwl_gen3_bc_tbl); + bc_tbl_entries = bc_tbl_size / sizeof(u16); + } else { + bc_tbl_size = sizeof(struct iwlagn_scd_bc_tbl); + bc_tbl_entries = bc_tbl_size / sizeof(u16); + } + + if (WARN_ON(size > bc_tbl_entries)) + return -EINVAL; + txq = kzalloc(sizeof(*txq), GFP_KERNEL); if (!txq) return -ENOMEM; - ret = iwl_pcie_alloc_dma_ptr(trans, &txq->bc_tbl, - (trans->trans_cfg->device_family >= - IWL_DEVICE_FAMILY_AX210) ? - sizeof(struct iwl_gen3_bc_tbl) : - sizeof(struct iwlagn_scd_bc_tbl)); - if (ret) { + + txq->bc_tbl.addr = dma_pool_alloc(trans_pcie->bc_pool, GFP_KERNEL, + &txq->bc_tbl.dma); + if (!txq->bc_tbl.addr) { IWL_ERR(trans, "Scheduler BC Table allocation failed\n"); kfree(txq); return -ENOMEM; diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 4582d418ba4d..9ff78bca460b 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -8,7 +8,7 @@ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2018 - 2020 Intel Corporation * * This program is free software; you can redistribute it and/or modify it * under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2003 - 2014 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 - 2019 Intel Corporation + * Copyright(c) 2018 - 2020 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -954,10 +954,10 @@ static int iwl_pcie_tx_alloc(struct iwl_trans *trans) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); u16 bc_tbls_size = trans->trans_cfg->base_params->num_of_queues; - bc_tbls_size *= (trans->trans_cfg->device_family >= - IWL_DEVICE_FAMILY_AX210) ? - sizeof(struct iwl_gen3_bc_tbl) : - sizeof(struct iwlagn_scd_bc_tbl); + if (WARN_ON(trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210)) + return -EINVAL; + + bc_tbls_size *= sizeof(struct iwlagn_scd_bc_tbl); /*It is not allowed to alloc twice, so warn when this happens. * We cannot rely on the previous allocation, so free and fail */ diff --git a/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c index b2616d61b66d..585784258c66 100644 --- a/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c +++ b/drivers/net/wireless/realtek/rtl818x/rtl8187/rtl8225.c @@ -606,10 +606,6 @@ static const u8 rtl8225z2_tx_power_cck[] = { 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03 }; -static const u8 rtl8225z2_tx_power_ofdm[] = { - 0x42, 0x00, 0x40, 0x00, 0x40 -}; - static const u8 rtl8225z2_tx_gain_cck_ofdm[] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, diff --git a/drivers/net/wireless/realtek/rtw88/Kconfig b/drivers/net/wireless/realtek/rtw88/Kconfig index 33bd7ed797ff..7a5fa68945c4 100644 --- a/drivers/net/wireless/realtek/rtw88/Kconfig +++ b/drivers/net/wireless/realtek/rtw88/Kconfig @@ -36,6 +36,16 @@ config RTW88_8822CE 802.11ac PCIe wireless network adapter +config RTW88_8723DE + bool "Realtek 8723DE PCI wireless network adapter" + depends on PCI + select RTW88_CORE + select RTW88_PCI + help + Select this option will enable support for 8723DE chipset + + 802.11n PCIe wireless network adapter + config RTW88_DEBUG bool "Realtek rtw88 debug support" depends on RTW88_CORE diff --git a/drivers/net/wireless/realtek/rtw88/Makefile b/drivers/net/wireless/realtek/rtw88/Makefile index cac148d13cf1..385facc0dd20 100644 --- a/drivers/net/wireless/realtek/rtw88/Makefile +++ b/drivers/net/wireless/realtek/rtw88/Makefile @@ -20,6 +20,7 @@ rtw88-y += main.o \ rtw88-$(CONFIG_RTW88_8822BE) += rtw8822b.o rtw8822b_table.o rtw88-$(CONFIG_RTW88_8822CE) += rtw8822c.o rtw8822c_table.o +rtw88-$(CONFIG_RTW88_8723DE) += rtw8723d.o rtw8723d_table.o obj-$(CONFIG_RTW88_PCI) += rtwpci.o rtwpci-objs := pci.o diff --git a/drivers/net/wireless/realtek/rtw88/debug.c b/drivers/net/wireless/realtek/rtw88/debug.c index b4964306de61..09f04feb8fe1 100644 --- a/drivers/net/wireless/realtek/rtw88/debug.c +++ b/drivers/net/wireless/realtek/rtw88/debug.c @@ -531,8 +531,8 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v) u8 ch = hal->current_channel; u8 regd = rtwdev->regd.txpwr_regd; - seq_printf(m, "%-4s %-10s %-3s%6s %-4s %4s (%-4s %-4s)\n", - "path", "rate", "pwr", "", "base", "", "byr", "lmt"); + seq_printf(m, "%-4s %-10s %-3s%6s %-4s %4s (%-4s %-4s) %-4s\n", + "path", "rate", "pwr", "", "base", "", "byr", "lmt", "rem"); mutex_lock(&hal->tx_power_mutex); for (path = RF_PATH_A; path <= RF_PATH_B; path++) { @@ -554,13 +554,14 @@ static int rtw_debugfs_get_tx_pwr_tbl(struct seq_file *m, void *v) seq_printf(m, "%4c ", path + 'A'); rtw_print_rate(m, rate); - seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d)\n", + seq_printf(m, " %3u(0x%02x) %4u %4d (%4d %4d) %4d\n", hal->tx_pwr_tbl[path][rate], hal->tx_pwr_tbl[path][rate], pwr_param.pwr_base, min_t(s8, pwr_param.pwr_offset, pwr_param.pwr_limit), - pwr_param.pwr_offset, pwr_param.pwr_limit); + pwr_param.pwr_offset, pwr_param.pwr_limit, + pwr_param.pwr_remnant); } } diff --git a/drivers/net/wireless/realtek/rtw88/mac.c b/drivers/net/wireless/realtek/rtw88/mac.c index e8ffeb338584..3a5cfebe5a62 100644 --- a/drivers/net/wireless/realtek/rtw88/mac.c +++ b/drivers/net/wireless/realtek/rtw88/mac.c @@ -919,31 +919,24 @@ static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues) static void __rtw_mac_flush_prio_queue(struct rtw_dev *rtwdev, u32 prio_queue, bool drop) { - u32 addr; + struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_prioq_addr *addr; + bool wsize; u16 avail_page, rsvd_page; int i; - switch (prio_queue) { - case RTW_DMA_MAPPING_EXTRA: - addr = REG_FIFOPAGE_INFO_4; - break; - case RTW_DMA_MAPPING_LOW: - addr = REG_FIFOPAGE_INFO_2; - break; - case RTW_DMA_MAPPING_NORMAL: - addr = REG_FIFOPAGE_INFO_3; - break; - case RTW_DMA_MAPPING_HIGH: - addr = REG_FIFOPAGE_INFO_1; - break; - default: + if (prio_queue >= RTW_DMA_MAPPING_MAX) return; - } + + addr = &chip->prioq_addrs->prio[prio_queue]; + wsize = chip->prioq_addrs->wsize; /* check if all of the reserved pages are available for 100 msecs */ for (i = 0; i < 5; i++) { - rsvd_page = rtw_read16(rtwdev, addr); - avail_page = rtw_read16(rtwdev, addr + 2); + rsvd_page = wsize ? rtw_read16(rtwdev, addr->rsvd) : + rtw_read8(rtwdev, addr->rsvd); + avail_page = wsize ? rtw_read16(rtwdev, addr->avail) : + rtw_read8(rtwdev, addr->avail); if (rsvd_page == avail_page) return; diff --git a/drivers/net/wireless/realtek/rtw88/main.h b/drivers/net/wireless/realtek/rtw88/main.h index e0365a70c6f7..c9156b9b532c 100644 --- a/drivers/net/wireless/realtek/rtw88/main.h +++ b/drivers/net/wireless/realtek/rtw88/main.h @@ -11,6 +11,7 @@ #include <linux/average.h> #include <linux/bitops.h> #include <linux/bitfield.h> +#include <linux/iopoll.h> #include <linux/interrupt.h> #include "util.h" @@ -518,6 +519,12 @@ struct rtw_hw_reg { u32 mask; }; +struct rtw_ltecoex_addr { + u32 ctrl; + u32 wdata; + u32 rdata; +}; + struct rtw_reg_domain { u32 addr; u32 mask; @@ -794,6 +801,7 @@ struct rtw_regulatory { struct rtw_chip_ops { int (*mac_init)(struct rtw_dev *rtwdev); + void (*shutdown)(struct rtw_dev *rtwdev); int (*read_efuse)(struct rtw_dev *rtwdev, u8 *map); void (*phy_set_param)(struct rtw_dev *rtwdev); void (*set_channel)(struct rtw_dev *rtwdev, u8 channel, @@ -943,6 +951,16 @@ struct rtw_rqpn { enum rtw_dma_mapping dma_map_hi; }; +struct rtw_prioq_addr { + u32 rsvd; + u32 avail; +}; + +struct rtw_prioq_addrs { + struct rtw_prioq_addr prio[RTW_DMA_MAPPING_MAX]; + bool wsize; +}; + struct rtw_page_table { u16 hq_num; u16 nq_num; @@ -1055,6 +1073,8 @@ struct rtw_pwr_track_tbl { const u8 *pwrtrk_2g_cckb_p; const u8 *pwrtrk_2g_ccka_n; const u8 *pwrtrk_2g_ccka_p; + const s8 *pwrtrk_xtal_n; + const s8 *pwrtrk_xtal_p; }; enum rtw_wlan_cpu { @@ -1097,6 +1117,7 @@ struct rtw_chip_info { const struct rtw_pwr_seq_cmd **pwr_on_seq; const struct rtw_pwr_seq_cmd **pwr_off_seq; const struct rtw_rqpn *rqpn_table; + const struct rtw_prioq_addrs *prioq_addrs; const struct rtw_page_table *page_table; const struct rtw_intf_phy_para_table *intf_table; @@ -1106,6 +1127,7 @@ struct rtw_chip_info { u32 rf_sipi_addr[2]; const struct rtw_rf_sipi_addr *rf_sipi_read_addr; u8 fix_rf_phy_num; + const struct rtw_ltecoex_addr *ltecoex_addr; const struct rtw_table *mac_tbl; const struct rtw_table *agc_tbl; @@ -1399,6 +1421,16 @@ struct rtw_pkt_count { DECLARE_EWMA(evm, 10, 4); DECLARE_EWMA(snr, 10, 4); +struct rtw_iqk_info { + bool done; + struct { + u32 s1_x; + u32 s1_y; + u32 s0_x; + u32 s0_y; + } result; +}; + struct rtw_dm_info { u32 cck_fa_cnt; u32 ofdm_fa_cnt; @@ -1436,6 +1468,8 @@ struct rtw_dm_info { bool pwr_trk_triggered; bool pwr_trk_init_trigger; struct ewma_thermal avg_thermal[RTW_RF_PATH_MAX]; + s8 txagc_remnant_cck; + s8 txagc_remnant_ofdm; /* backup dack results for each path and I/Q */ u32 dack_adck[RTW_RF_PATH_MAX]; @@ -1458,6 +1492,8 @@ struct rtw_dm_info { struct rtw_pkt_count last_pkt_count; struct ewma_evm ewma_evm[RTW_EVM_NUM]; struct ewma_snr ewma_snr[RTW_SNR_NUM]; + + struct rtw_iqk_info iqk; }; struct rtw_efuse { diff --git a/drivers/net/wireless/realtek/rtw88/pci.c b/drivers/net/wireless/realtek/rtw88/pci.c index a9752c34c9d8..e5ea30c04ac5 100644 --- a/drivers/net/wireless/realtek/rtw88/pci.c +++ b/drivers/net/wireless/realtek/rtw88/pci.c @@ -1573,6 +1573,22 @@ static void rtw_pci_remove(struct pci_dev *pdev) ieee80211_free_hw(hw); } +static void rtw_pci_shutdown(struct pci_dev *pdev) +{ + struct ieee80211_hw *hw = pci_get_drvdata(pdev); + struct rtw_dev *rtwdev; + struct rtw_chip_info *chip; + + if (!hw) + return; + + rtwdev = hw->priv; + chip = rtwdev->chip; + + if (chip->ops->shutdown) + chip->ops->shutdown(rtwdev); +} + static const struct pci_device_id rtw_pci_id_table[] = { #ifdef CONFIG_RTW88_8822BE { RTK_PCI_DEVICE(PCI_VENDOR_ID_REALTEK, 0xB822, rtw8822b_hw_spec) }, @@ -1593,6 +1609,7 @@ static struct pci_driver rtw_pci_driver = { .probe = rtw_pci_probe, .remove = rtw_pci_remove, .driver.pm = &rtw_pm_ops, + .shutdown = rtw_pci_shutdown, }; module_pci_driver(rtw_pci_driver); diff --git a/drivers/net/wireless/realtek/rtw88/phy.c b/drivers/net/wireless/realtek/rtw88/phy.c index 72a16eff9db3..45181f602e3f 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.c +++ b/drivers/net/wireless/realtek/rtw88/phy.c @@ -134,6 +134,8 @@ void rtw_phy_init(struct rtw_dev *rtwdev) mask = chip->dig[0].mask; dm_info->igi_history[0] = rtw_read32_mask(rtwdev, addr, mask); rtw_phy_cck_pd_init(rtwdev); + + dm_info->iqk.done = false; } void rtw_phy_dig_write(struct rtw_dev *rtwdev, u8 igi) @@ -1783,11 +1785,13 @@ void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw, u8 ch, u8 regd, struct rtw_power_params *pwr_param) { struct rtw_hal *hal = &rtwdev->hal; + struct rtw_dm_info *dm_info = &rtwdev->dm_info; struct rtw_txpwr_idx *pwr_idx; u8 group, band; u8 *base = &pwr_param->pwr_base; s8 *offset = &pwr_param->pwr_offset; s8 *limit = &pwr_param->pwr_limit; + s8 *remnant = &pwr_param->pwr_remnant; pwr_idx = &rtwdev->efuse.txpwr_idx_table[path]; group = rtw_get_channel_group(ch); @@ -1809,6 +1813,8 @@ void rtw_get_tx_power_params(struct rtw_dev *rtwdev, u8 path, u8 rate, u8 bw, *limit = rtw_phy_get_tx_power_limit(rtwdev, band, bw, path, rate, ch, regd); + *remnant = (rate <= DESC_RATE11M ? dm_info->txagc_remnant_cck : + dm_info->txagc_remnant_ofdm); } u8 @@ -1828,7 +1834,7 @@ rtw_phy_get_tx_power_index(struct rtw_dev *rtwdev, u8 rf_path, u8 rate, if (rtwdev->chip->en_dis_dpd) offset += rtw_phy_get_dis_dpd_by_rate_diff(rtwdev, rate); - tx_power += offset; + tx_power += offset + pwr_param.pwr_remnant; if (tx_power > rtwdev->chip->max_power_index) tx_power = rtwdev->chip->max_power_index; diff --git a/drivers/net/wireless/realtek/rtw88/phy.h b/drivers/net/wireless/realtek/rtw88/phy.h index 413bf7165cc0..b924ed07630a 100644 --- a/drivers/net/wireless/realtek/rtw88/phy.h +++ b/drivers/net/wireless/realtek/rtw88/phy.h @@ -141,6 +141,7 @@ struct rtw_power_params { u8 pwr_base; s8 pwr_offset; s8 pwr_limit; + s8 pwr_remnant; }; void diff --git a/drivers/net/wireless/realtek/rtw88/reg.h b/drivers/net/wireless/realtek/rtw88/reg.h index 9fdfcdc5c5cf..5a3e9cc7c400 100644 --- a/drivers/net/wireless/realtek/rtw88/reg.h +++ b/drivers/net/wireless/realtek/rtw88/reg.h @@ -69,6 +69,7 @@ #define BIT_DPDT_SEL_EN BIT(23) #define REG_LEDCFG2 0x004E #define REG_PAD_CTRL1 0x0064 +#define BIT_BT_BTG_SEL BIT(31) #define BIT_PAPE_WLBT_SEL BIT(29) #define BIT_LNAON_WLBT_SEL BIT(28) #define BIT_BTGP_JTAG_EN BIT(24) @@ -82,6 +83,7 @@ #define BIT_DBG_GNT_WL_BT BIT(27) #define BIT_LTE_MUX_CTRL_PATH BIT(26) #define REG_HCI_OPT_CTRL 0x0074 +#define BIT_USB_SUS_DIS BIT(8) #define REG_AFE_CTRL_4 0x0078 #define BIT_CK320M_AFE_EN BIT(4) @@ -611,7 +613,10 @@ #define REG_IGN_GNTBT4 0x4160 +#define RF_MODE 0x00 #define RF_MODOPT 0x01 +#define RF_WLINT 0x01 +#define RF_WLSEL 0x02 #define RF_DTXLOK 0x08 #define RF_CFGCH 0x18 #define RF_RCK 0x1d @@ -619,9 +624,15 @@ #define RF_LUTWD1 0x3e #define RF_LUTWD0 0x3f #define RF_T_METER 0x42 +#define RF_BSPAD 0x54 +#define RF_GAINTX 0x56 +#define RF_TXATANK 0x64 +#define RF_TRXIQ 0x66 +#define RF_RXIQGEN 0x8d #define RF_XTALX2 0xb8 #define RF_MALSEL 0xbe #define RF_RCKD 0xde +#define RF_TXADBG 0xde #define RF_LUTDBG 0xdf #define RF_LUTWE2 0xee #define RF_LUTWE 0xef diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.c b/drivers/net/wireless/realtek/rtw88/rtw8723d.c index 92c742d1ce6d..b517af417e0e 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.c @@ -64,6 +64,74 @@ static const struct rtw_hw_reg rtw8723d_txagc[] = { #define WLAN_LTR_CTRL1 0xCB004010 #define WLAN_LTR_CTRL2 0x01233425 +static void rtw8723d_lck(struct rtw_dev *rtwdev) +{ + u32 lc_cal; + u8 val_ctx, rf_val; + int ret; + + val_ctx = rtw_read8(rtwdev, REG_CTX); + if ((val_ctx & BIT_MASK_CTX_TYPE) != 0) + rtw_write8(rtwdev, REG_CTX, val_ctx & ~BIT_MASK_CTX_TYPE); + else + rtw_write8(rtwdev, REG_TXPAUSE, 0xFF); + lc_cal = rtw_read_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK); + + rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal | BIT_LCK); + + ret = read_poll_timeout(rtw_read_rf, rf_val, rf_val != 0x1, + 10000, 1000000, false, + rtwdev, RF_PATH_A, RF_CFGCH, BIT_LCK); + if (ret) + rtw_warn(rtwdev, "failed to poll LCK status bit\n"); + + rtw_write_rf(rtwdev, RF_PATH_A, RF_CFGCH, RFREG_MASK, lc_cal); + if ((val_ctx & BIT_MASK_CTX_TYPE) != 0) + rtw_write8(rtwdev, REG_CTX, val_ctx); + else + rtw_write8(rtwdev, REG_TXPAUSE, 0x00); +} + +static const u32 rtw8723d_ofdm_swing_table[] = { + 0x0b40002d, 0x0c000030, 0x0cc00033, 0x0d800036, 0x0e400039, 0x0f00003c, + 0x10000040, 0x11000044, 0x12000048, 0x1300004c, 0x14400051, 0x15800056, + 0x16c0005b, 0x18000060, 0x19800066, 0x1b00006c, 0x1c800072, 0x1e400079, + 0x20000080, 0x22000088, 0x24000090, 0x26000098, 0x288000a2, 0x2ac000ab, + 0x2d4000b5, 0x300000c0, 0x32c000cb, 0x35c000d7, 0x390000e4, 0x3c8000f2, + 0x40000100, 0x43c0010f, 0x47c0011f, 0x4c000130, 0x50800142, 0x55400155, + 0x5a400169, 0x5fc0017f, 0x65400195, 0x6b8001ae, 0x71c001c7, 0x788001e2, + 0x7f8001fe, +}; + +static const u32 rtw8723d_cck_swing_table[] = { + 0x0CD, 0x0D9, 0x0E6, 0x0F3, 0x102, 0x111, 0x121, 0x132, 0x144, 0x158, + 0x16C, 0x182, 0x198, 0x1B1, 0x1CA, 0x1E5, 0x202, 0x221, 0x241, 0x263, + 0x287, 0x2AE, 0x2D6, 0x301, 0x32F, 0x35F, 0x392, 0x3C9, 0x402, 0x43F, + 0x47F, 0x4C3, 0x50C, 0x558, 0x5A9, 0x5FF, 0x65A, 0x6BA, 0x720, 0x78C, + 0x7FF, +}; + +#define RTW_OFDM_SWING_TABLE_SIZE ARRAY_SIZE(rtw8723d_ofdm_swing_table) +#define RTW_CCK_SWING_TABLE_SIZE ARRAY_SIZE(rtw8723d_cck_swing_table) + +static void rtw8723d_pwrtrack_init(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u8 path; + + dm_info->default_ofdm_index = RTW_DEF_OFDM_SWING_INDEX; + + for (path = RF_PATH_A; path < rtwdev->hal.rf_path_num; path++) { + ewma_thermal_init(&dm_info->avg_thermal[path]); + dm_info->delta_power_index[path] = 0; + } + dm_info->pwr_trk_triggered = false; + dm_info->pwr_trk_init_trigger = true; + dm_info->thermal_meter_k = rtwdev->efuse.thermal_meter_k; + dm_info->txagc_remnant_cck = 0; + dm_info->txagc_remnant_ofdm = 0; +} + static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev) { u8 xtal_cap; @@ -125,8 +193,13 @@ static void rtw8723d_phy_set_param(struct rtw_dev *rtwdev) rtw_phy_init(rtwdev); rtw_write16_set(rtwdev, REG_TXDMA_OFFSET_CHK, BIT_DROP_DATA_EN); + + rtw8723d_lck(rtwdev); + rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50); rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x20); + + rtw8723d_pwrtrack_init(rtwdev); } static void rtw8723de_efuse_parsing(struct rtw_efuse *efuse, @@ -476,6 +549,11 @@ static int rtw8723d_mac_init(struct rtw_dev *rtwdev) return 0; } +static void rtw8723d_shutdown(struct rtw_dev *rtwdev) +{ + rtw_write16_set(rtwdev, REG_HCI_OPT_CTRL, BIT_USB_SUS_DIS); +} + static void rtw8723d_cfg_ldo25(struct rtw_dev *rtwdev, bool enable) { u8 ldo_pwr; @@ -603,12 +681,1247 @@ static void rtw8723d_false_alarm_statistics(struct rtw_dev *rtwdev) rtw_write32_mask(rtwdev, REG_PAGE_F_RST_11N, BIT_MASK_F_RST_ALL, 0); } +static const u32 iqk_adda_regs[] = { + 0x85c, 0xe6c, 0xe70, 0xe74, 0xe78, 0xe7c, 0xe80, 0xe84, 0xe88, 0xe8c, + 0xed0, 0xed4, 0xed8, 0xedc, 0xee0, 0xeec +}; + +static const u32 iqk_mac8_regs[] = {0x522, 0x550, 0x551}; +static const u32 iqk_mac32_regs[] = {0x40}; + +static const u32 iqk_bb_regs[] = { + 0xc04, 0xc08, 0x874, 0xb68, 0xb6c, 0x870, 0x860, 0x864, 0xa04 +}; + +#define IQK_ADDA_REG_NUM ARRAY_SIZE(iqk_adda_regs) +#define IQK_MAC8_REG_NUM ARRAY_SIZE(iqk_mac8_regs) +#define IQK_MAC32_REG_NUM ARRAY_SIZE(iqk_mac32_regs) +#define IQK_BB_REG_NUM ARRAY_SIZE(iqk_bb_regs) + +struct iqk_backup_regs { + u32 adda[IQK_ADDA_REG_NUM]; + u8 mac8[IQK_MAC8_REG_NUM]; + u32 mac32[IQK_MAC32_REG_NUM]; + u32 bb[IQK_BB_REG_NUM]; + + u32 lte_path; + u32 lte_gnt; + + u32 bb_sel_btg; + u8 btg_sel; + + u8 igia; + u8 igib; +}; + +static void rtw8723d_iqk_backup_regs(struct rtw_dev *rtwdev, + struct iqk_backup_regs *backup) +{ + int i; + + for (i = 0; i < IQK_ADDA_REG_NUM; i++) + backup->adda[i] = rtw_read32(rtwdev, iqk_adda_regs[i]); + + for (i = 0; i < IQK_MAC8_REG_NUM; i++) + backup->mac8[i] = rtw_read8(rtwdev, iqk_mac8_regs[i]); + for (i = 0; i < IQK_MAC32_REG_NUM; i++) + backup->mac32[i] = rtw_read32(rtwdev, iqk_mac32_regs[i]); + + for (i = 0; i < IQK_BB_REG_NUM; i++) + backup->bb[i] = rtw_read32(rtwdev, iqk_bb_regs[i]); + + backup->igia = rtw_read32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0); + backup->igib = rtw_read32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0); + + backup->bb_sel_btg = rtw_read32(rtwdev, REG_BB_SEL_BTG); +} + +static void rtw8723d_iqk_restore_regs(struct rtw_dev *rtwdev, + const struct iqk_backup_regs *backup) +{ + int i; + + for (i = 0; i < IQK_ADDA_REG_NUM; i++) + rtw_write32(rtwdev, iqk_adda_regs[i], backup->adda[i]); + + for (i = 0; i < IQK_MAC8_REG_NUM; i++) + rtw_write8(rtwdev, iqk_mac8_regs[i], backup->mac8[i]); + for (i = 0; i < IQK_MAC32_REG_NUM; i++) + rtw_write32(rtwdev, iqk_mac32_regs[i], backup->mac32[i]); + + for (i = 0; i < IQK_BB_REG_NUM; i++) + rtw_write32(rtwdev, iqk_bb_regs[i], backup->bb[i]); + + rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, 0x50); + rtw_write32_mask(rtwdev, REG_OFDM0_XAAGC1, MASKBYTE0, backup->igia); + + rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, 0x50); + rtw_write32_mask(rtwdev, REG_OFDM0_XBAGC1, MASKBYTE0, backup->igib); + + rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x01008c00); + rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x01008c00); +} + +static void rtw8723d_iqk_backup_path_ctrl(struct rtw_dev *rtwdev, + struct iqk_backup_regs *backup) +{ + backup->btg_sel = rtw_read8(rtwdev, REG_BTG_SEL); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] original 0x67 = 0x%x\n", + backup->btg_sel); +} + +static void rtw8723d_iqk_config_path_ctrl(struct rtw_dev *rtwdev) +{ + rtw_write32_mask(rtwdev, REG_PAD_CTRL1, BIT_BT_BTG_SEL, 0x1); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] set 0x67 = 0x%x\n", + rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3)); +} + +static void rtw8723d_iqk_restore_path_ctrl(struct rtw_dev *rtwdev, + const struct iqk_backup_regs *backup) +{ + rtw_write8(rtwdev, REG_BTG_SEL, backup->btg_sel); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] restore 0x67 = 0x%x\n", + rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3)); +} + +static void rtw8723d_iqk_backup_lte_path_gnt(struct rtw_dev *rtwdev, + struct iqk_backup_regs *backup) +{ + backup->lte_path = rtw_read32(rtwdev, REG_LTECOEX_PATH_CONTROL); + rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0x800f0038); + mdelay(1); + backup->lte_gnt = rtw_read32(rtwdev, REG_LTECOEX_READ_DATA); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] OriginalGNT = 0x%x\n", + backup->lte_gnt); +} + +static void rtw8723d_iqk_config_lte_path_gnt(struct rtw_dev *rtwdev) +{ + rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, 0x0000ff00); + rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc0020038); + rtw_write32_mask(rtwdev, REG_LTECOEX_PATH_CONTROL, BIT_LTE_MUX_CTRL_PATH, 0x1); +} + +static void rtw8723d_iqk_restore_lte_path_gnt(struct rtw_dev *rtwdev, + const struct iqk_backup_regs *bak) +{ + rtw_write32(rtwdev, REG_LTECOEX_WRITE_DATA, bak->lte_gnt); + rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0xc00f0038); + rtw_write32(rtwdev, REG_LTECOEX_PATH_CONTROL, bak->lte_path); +} + +struct rtw_8723d_iqk_cfg { + const char *name; + u32 val_bb_sel_btg; + u32 reg_lutwe; + u32 val_txiqk_pi; + u32 reg_padlut; + u32 reg_gaintx; + u32 reg_bspad; + u32 val_wlint; + u32 val_wlsel; + u32 val_iqkpts; +}; + +static const struct rtw_8723d_iqk_cfg iqk_tx_cfg[PATH_NR] = { + [PATH_S1] = { + .name = "S1", + .val_bb_sel_btg = 0x99000000, + .reg_lutwe = RF_LUTWE, + .val_txiqk_pi = 0x8214019f, + .reg_padlut = RF_LUTDBG, + .reg_gaintx = RF_GAINTX, + .reg_bspad = RF_BSPAD, + .val_wlint = 0xe0d, + .val_wlsel = 0x60d, + .val_iqkpts = 0xfa000000, + }, + [PATH_S0] = { + .name = "S0", + .val_bb_sel_btg = 0x99000280, + .reg_lutwe = RF_LUTWE2, + .val_txiqk_pi = 0x8214018a, + .reg_padlut = RF_TXADBG, + .reg_gaintx = RF_TRXIQ, + .reg_bspad = RF_TXATANK, + .val_wlint = 0xe6d, + .val_wlsel = 0x66d, + .val_iqkpts = 0xf9000000, + }, +}; + +static u8 rtw8723d_iqk_check_tx_failed(struct rtw_dev *rtwdev, + const struct rtw_8723d_iqk_cfg *iqk_cfg) +{ + s32 tx_x, tx_y; + u32 tx_fail; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xeac = 0x%x\n", + rtw_read32(rtwdev, REG_IQK_RES_RY)); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xe94 = 0x%x, 0xe9c = 0x%x\n", + rtw_read32(rtwdev, REG_IQK_RES_TX), + rtw_read32(rtwdev, REG_IQK_RES_TY)); + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] 0xe90(before IQK)= 0x%x, 0xe98(afer IQK) = 0x%x\n", + rtw_read32(rtwdev, 0xe90), + rtw_read32(rtwdev, 0xe98)); + + tx_fail = rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_IQK_TX_FAIL); + tx_x = rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX); + tx_y = rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY); + + if (!tx_fail && tx_x != IQK_TX_X_ERR && tx_y != IQK_TX_Y_ERR) + return IQK_TX_OK; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] %s TXIQK is failed\n", + iqk_cfg->name); + + return 0; +} + +static u8 rtw8723d_iqk_check_rx_failed(struct rtw_dev *rtwdev, + const struct rtw_8723d_iqk_cfg *iqk_cfg) +{ + s32 rx_x, rx_y; + u32 rx_fail; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xea4 = 0x%x, 0xeac = 0x%x\n", + rtw_read32(rtwdev, REG_IQK_RES_RX), + rtw_read32(rtwdev, REG_IQK_RES_RY)); + + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] 0xea0(before IQK)= 0x%x, 0xea8(afer IQK) = 0x%x\n", + rtw_read32(rtwdev, 0xea0), + rtw_read32(rtwdev, 0xea8)); + + rx_fail = rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_IQK_RX_FAIL); + rx_x = rtw_read32_mask(rtwdev, REG_IQK_RES_RX, BIT_MASK_RES_RX); + rx_y = rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_MASK_RES_RY); + rx_y = abs(iqkxy_to_s32(rx_y)); + + if (!rx_fail && rx_x < IQK_RX_X_UPPER && rx_x > IQK_RX_X_LOWER && + rx_y < IQK_RX_Y_LMT) + return IQK_RX_OK; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] %s RXIQK STEP2 is failed\n", + iqk_cfg->name); + + return 0; +} + +static void rtw8723d_iqk_one_shot(struct rtw_dev *rtwdev, bool tx, + const struct rtw_8723d_iqk_cfg *iqk_cfg) +{ + u32 pts = (tx ? iqk_cfg->val_iqkpts : 0xf9000000); + + /* enter IQK mode */ + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK); + rtw8723d_iqk_config_lte_path_gnt(rtwdev); + + rtw_write32(rtwdev, REG_LTECOEX_CTRL, 0x800f0054); + mdelay(1); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] GNT_BT @%s %sIQK1 = 0x%x\n", + iqk_cfg->name, tx ? "TX" : "RX", + rtw_read32(rtwdev, REG_LTECOEX_READ_DATA)); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x948 @%s %sIQK1 = 0x%x\n", + iqk_cfg->name, tx ? "TX" : "RX", + rtw_read32(rtwdev, REG_BB_SEL_BTG)); + + /* One shot, LOK & IQK */ + rtw_write32(rtwdev, REG_IQK_AGC_PTS_11N, pts); + rtw_write32(rtwdev, REG_IQK_AGC_PTS_11N, 0xf8000000); + + if (!check_hw_ready(rtwdev, REG_IQK_RES_RY, BIT_IQK_DONE, 1)) + rtw_warn(rtwdev, "%s %s IQK isn't done\n", iqk_cfg->name, + tx ? "TX" : "RX"); +} + +static void rtw8723d_iqk_txrx_path_post(struct rtw_dev *rtwdev, + const struct rtw_8723d_iqk_cfg *iqk_cfg, + const struct iqk_backup_regs *backup) +{ + rtw8723d_iqk_restore_lte_path_gnt(rtwdev, backup); + rtw_write32(rtwdev, REG_BB_SEL_BTG, backup->bb_sel_btg); + + /* leave IQK mode */ + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK); + mdelay(1); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_padlut, 0x800, 0x0); + rtw_write_rf(rtwdev, RF_PATH_A, RF_WLINT, BIT(0), 0x0); + rtw_write_rf(rtwdev, RF_PATH_A, RF_WLSEL, BIT(0), 0x0); +} + +static u8 rtw8723d_iqk_tx_path(struct rtw_dev *rtwdev, + const struct rtw_8723d_iqk_cfg *iqk_cfg, + const struct iqk_backup_regs *backup) +{ + u8 status; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path %s TXIQK!!\n", iqk_cfg->name); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x67 @%s TXIQK = 0x%x\n", + iqk_cfg->name, + rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3)); + + rtw_write32(rtwdev, REG_BB_SEL_BTG, iqk_cfg->val_bb_sel_btg); + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK); + mdelay(1); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x80000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x00004); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD1, RFREG_MASK, 0x0005d); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0xBFFE0); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x00000); + + /* IQK setting */ + rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x08008c0c); + rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x38008c1c); + rtw_write32(rtwdev, REG_TXIQK_PI_A_11N, iqk_cfg->val_txiqk_pi); + rtw_write32(rtwdev, REG_RXIQK_PI_A_11N, 0x28160200); + rtw_write32(rtwdev, REG_TXIQK_11N, 0x01007c00); + rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800); + + /* LOK setting */ + rtw_write32(rtwdev, REG_IQK_AGC_RSP_11N, 0x00462911); + + /* PA, PAD setting */ + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_padlut, 0x800, 0x1); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_gaintx, 0x600, 0x0); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_gaintx, 0x1E0, 0x3); + rtw_write_rf(rtwdev, RF_PATH_A, RF_RXIQGEN, 0x1F, 0xf); + + /* LOK setting for 8723D */ + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, 0x10, 0x1); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_bspad, 0x1, 0x1); + + rtw_write_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK, iqk_cfg->val_wlint); + rtw_write_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK, iqk_cfg->val_wlsel); + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x1 @%s TXIQK = 0x%x\n", + iqk_cfg->name, + rtw_read_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK)); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x2 @%s TXIQK = 0x%x\n", + iqk_cfg->name, + rtw_read_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK)); + + rtw8723d_iqk_one_shot(rtwdev, true, iqk_cfg); + status = rtw8723d_iqk_check_tx_failed(rtwdev, iqk_cfg); + + rtw8723d_iqk_txrx_path_post(rtwdev, iqk_cfg, backup); + + return status; +} + +static u8 rtw8723d_iqk_rx_path(struct rtw_dev *rtwdev, + const struct rtw_8723d_iqk_cfg *iqk_cfg, + const struct iqk_backup_regs *backup) +{ + u32 tx_x, tx_y; + u8 status; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path %s RXIQK Step1!!\n", + iqk_cfg->name); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x67 @%s RXIQK1 = 0x%x\n", + iqk_cfg->name, + rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3)); + rtw_write32(rtwdev, REG_BB_SEL_BTG, iqk_cfg->val_bb_sel_btg); + + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK); + + /* IQK setting */ + rtw_write32(rtwdev, REG_TXIQK_11N, 0x01007c00); + rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800); + + /* path IQK setting */ + rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x18008c1c); + rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x38008c1c); + rtw_write32(rtwdev, REG_TX_IQK_TONE_B, 0x38008c1c); + rtw_write32(rtwdev, REG_RX_IQK_TONE_B, 0x38008c1c); + rtw_write32(rtwdev, REG_TXIQK_PI_A_11N, 0x82160000); + rtw_write32(rtwdev, REG_RXIQK_PI_A_11N, 0x28160000); + + /* LOK setting */ + rtw_write32(rtwdev, REG_IQK_AGC_RSP_11N, 0x0046a911); + + /* RXIQK mode */ + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x80000); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x00006); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD1, RFREG_MASK, 0x0005f); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0xa7ffb); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x00000); + + /* PA/PAD=0 */ + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_padlut, 0x800, 0x1); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_gaintx, 0x600, 0x0); + rtw_write_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK, iqk_cfg->val_wlint); + rtw_write_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK, iqk_cfg->val_wlsel); + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x1@ path %s RXIQK1 = 0x%x\n", + iqk_cfg->name, + rtw_read_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK)); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x2@ path %s RXIQK1 = 0x%x\n", + iqk_cfg->name, + rtw_read_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK)); + + rtw8723d_iqk_one_shot(rtwdev, false, iqk_cfg); + status = rtw8723d_iqk_check_tx_failed(rtwdev, iqk_cfg); + + if (!status) + goto restore; + + /* second round */ + tx_x = rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX); + tx_y = rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY); + + rtw_write32(rtwdev, REG_TXIQK_11N, BIT_SET_TXIQK_11N(tx_x, tx_y)); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0xe40 = 0x%x u4tmp = 0x%x\n", + rtw_read32(rtwdev, REG_TXIQK_11N), + BIT_SET_TXIQK_11N(tx_x, tx_y)); + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path %s RXIQK STEP2!!\n", + iqk_cfg->name); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] 0x67 @%s RXIQK2 = 0x%x\n", + iqk_cfg->name, + rtw_read32_mask(rtwdev, REG_PAD_CTRL1, MASKBYTE3)); + + rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800); + rtw_write32(rtwdev, REG_TXIQK_TONE_A_11N, 0x38008c1c); + rtw_write32(rtwdev, REG_RXIQK_TONE_A_11N, 0x18008c1c); + rtw_write32(rtwdev, REG_TX_IQK_TONE_B, 0x38008c1c); + rtw_write32(rtwdev, REG_RX_IQK_TONE_B, 0x38008c1c); + rtw_write32(rtwdev, REG_TXIQK_PI_A_11N, 0x82170000); + rtw_write32(rtwdev, REG_RXIQK_PI_A_11N, 0x28171400); + + /* LOK setting */ + rtw_write32(rtwdev, REG_IQK_AGC_RSP_11N, 0x0046a8d1); + + /* RXIQK mode */ + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK); + mdelay(1); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, 0x80000, 0x1); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWA, RFREG_MASK, 0x00007); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD1, RFREG_MASK, 0x0005f); + rtw_write_rf(rtwdev, RF_PATH_A, RF_LUTWD0, RFREG_MASK, 0xb3fdb); + rtw_write_rf(rtwdev, RF_PATH_A, iqk_cfg->reg_lutwe, RFREG_MASK, 0x00000); + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x1 @%s RXIQK2 = 0x%x\n", + iqk_cfg->name, + rtw_read_rf(rtwdev, RF_PATH_A, RF_WLINT, RFREG_MASK)); + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] RF0x2 @%s RXIQK2 = 0x%x\n", + iqk_cfg->name, + rtw_read_rf(rtwdev, RF_PATH_A, RF_WLSEL, RFREG_MASK)); + + rtw8723d_iqk_one_shot(rtwdev, false, iqk_cfg); + status |= rtw8723d_iqk_check_rx_failed(rtwdev, iqk_cfg); + +restore: + rtw8723d_iqk_txrx_path_post(rtwdev, iqk_cfg, backup); + + return status; +} + +static +void rtw8723d_iqk_fill_s1_matrix(struct rtw_dev *rtwdev, const s32 result[]) +{ + s32 oldval_1; + s32 x, y; + s32 tx1_a, tx1_a_ext; + s32 tx1_c, tx1_c_ext; + + if (result[IQK_S1_TX_X] == 0) + return; + + oldval_1 = rtw_read32_mask(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE, + BIT_MASK_TXIQ_ELM_D); + + x = iqkxy_to_s32(result[IQK_S1_TX_X]); + tx1_a = iqk_mult(x, oldval_1, &tx1_a_ext); + rtw_write32_mask(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE, + BIT_MASK_TXIQ_ELM_A, tx1_a); + rtw_write32_mask(rtwdev, REG_OFDM_0_ECCA_THRESHOLD, + BIT_MASK_OFDM0_EXT_A, tx1_a_ext); + + y = iqkxy_to_s32(result[IQK_S1_TX_Y]); + tx1_c = iqk_mult(y, oldval_1, &tx1_c_ext); + rtw_write32_mask(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N, MASKH4BITS, + BIT_SET_TXIQ_ELM_C1(tx1_c)); + rtw_write32_mask(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE, + BIT_MASK_TXIQ_ELM_C, BIT_SET_TXIQ_ELM_C2(tx1_c)); + rtw_write32_mask(rtwdev, REG_OFDM_0_ECCA_THRESHOLD, + BIT_MASK_OFDM0_EXT_C, tx1_c_ext); + + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] X = 0x%x, TX1_A = 0x%x, oldval_1 0x%x\n", + x, tx1_a, oldval_1); + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] Y = 0x%x, TX1_C = 0x%x\n", y, tx1_c); + + if (result[IQK_S1_RX_X] == 0) + return; + + rtw_write32_mask(rtwdev, REG_A_RXIQI, BIT_MASK_RXIQ_S1_X, + result[IQK_S1_RX_X]); + rtw_write32_mask(rtwdev, REG_A_RXIQI, BIT_MASK_RXIQ_S1_Y1, + BIT_SET_RXIQ_S1_Y1(result[IQK_S1_RX_Y])); + rtw_write32_mask(rtwdev, REG_RXIQK_MATRIX_LSB_11N, BIT_MASK_RXIQ_S1_Y2, + BIT_SET_RXIQ_S1_Y2(result[IQK_S1_RX_Y])); +} + +static +void rtw8723d_iqk_fill_s0_matrix(struct rtw_dev *rtwdev, const s32 result[]) +{ + s32 oldval_0; + s32 x, y; + s32 tx0_a, tx0_a_ext; + s32 tx0_c, tx0_c_ext; + + if (result[IQK_S0_TX_X] == 0) + return; + + oldval_0 = rtw_read32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_S0); + + x = iqkxy_to_s32(result[IQK_S0_TX_X]); + tx0_a = iqk_mult(x, oldval_0, &tx0_a_ext); + + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_S0, tx0_a); + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_EXT_S0, tx0_a_ext); + + y = iqkxy_to_s32(result[IQK_S0_TX_Y]); + tx0_c = iqk_mult(y, oldval_0, &tx0_c_ext); + + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_S0, tx0_c); + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_EXT_S0, tx0_c_ext); + + if (result[IQK_S0_RX_X] == 0) + return; + + rtw_write32_mask(rtwdev, REG_RXIQ_AB_S0, BIT_MASK_RXIQ_X_S0, + result[IQK_S0_RX_X]); + rtw_write32_mask(rtwdev, REG_RXIQ_AB_S0, BIT_MASK_RXIQ_Y_S0, + result[IQK_S0_RX_Y]); +} + +static void rtw8723d_iqk_path_adda_on(struct rtw_dev *rtwdev) +{ + int i; + + for (i = 0; i < IQK_ADDA_REG_NUM; i++) + rtw_write32(rtwdev, iqk_adda_regs[i], 0x03c00016); +} + +static void rtw8723d_iqk_config_mac(struct rtw_dev *rtwdev) +{ + rtw_write8(rtwdev, REG_TXPAUSE, 0xff); +} + +static +void rtw8723d_iqk_rf_standby(struct rtw_dev *rtwdev, enum rtw_rf_path path) +{ + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path-%s standby mode!\n", + path == RF_PATH_A ? "S1" : "S0"); + + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK); + mdelay(1); + rtw_write_rf(rtwdev, path, RF_MODE, RFREG_MASK, 0x10000); + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK); +} + +static +bool rtw8723d_iqk_similarity_cmp(struct rtw_dev *rtwdev, s32 result[][IQK_NR], + u8 c1, u8 c2) +{ + u32 i, j, diff; + u32 bitmap = 0; + u8 candidate[PATH_NR] = {IQK_ROUND_INVALID, IQK_ROUND_INVALID}; + bool ret = true; + + s32 tmp1, tmp2; + + for (i = 0; i < IQK_NR; i++) { + tmp1 = iqkxy_to_s32(result[c1][i]); + tmp2 = iqkxy_to_s32(result[c2][i]); + + diff = abs(tmp1 - tmp2); + + if (diff <= MAX_TOLERANCE) + continue; + + if ((i == IQK_S1_RX_X || i == IQK_S0_RX_X) && !bitmap) { + if (result[c1][i] + result[c1][i + 1] == 0) + candidate[i / IQK_SX_NR] = c2; + else if (result[c2][i] + result[c2][i + 1] == 0) + candidate[i / IQK_SX_NR] = c1; + else + bitmap |= BIT(i); + } else { + bitmap |= BIT(i); + } + } + + if (bitmap != 0) + goto check_sim; + + for (i = 0; i < PATH_NR; i++) { + if (candidate[i] == IQK_ROUND_INVALID) + continue; + + for (j = i * IQK_SX_NR; j < i * IQK_SX_NR + 2; j++) + result[IQK_ROUND_HYBRID][j] = result[candidate[i]][j]; + ret = false; + } + + return ret; + +check_sim: + for (i = 0; i < IQK_NR; i++) { + j = i & ~1; /* 2 bits are a pair for IQ[X, Y] */ + if (bitmap & GENMASK(j + 1, j)) + continue; + + result[IQK_ROUND_HYBRID][i] = result[c1][i]; + } + + return false; +} + +static +void rtw8723d_iqk_precfg_path(struct rtw_dev *rtwdev, enum rtw8723d_path path) +{ + if (path == PATH_S0) { + rtw8723d_iqk_rf_standby(rtwdev, RF_PATH_A); + rtw8723d_iqk_path_adda_on(rtwdev); + } + + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, EN_IQK); + rtw_write32(rtwdev, REG_TXIQK_11N, 0x01007c00); + rtw_write32(rtwdev, REG_RXIQK_11N, 0x01004800); + + if (path == PATH_S1) { + rtw8723d_iqk_rf_standby(rtwdev, RF_PATH_B); + rtw8723d_iqk_path_adda_on(rtwdev); + } +} + +static +void rtw8723d_iqk_one_round(struct rtw_dev *rtwdev, s32 result[][IQK_NR], u8 t, + const struct iqk_backup_regs *backup) +{ + u32 i; + u8 s1_ok, s0_ok; + + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] IQ Calibration for 1T1R_S0/S1 for %d times\n", t); + + rtw8723d_iqk_path_adda_on(rtwdev); + rtw8723d_iqk_config_mac(rtwdev); + rtw_write32_mask(rtwdev, REG_CCK_ANT_SEL_11N, 0x0f000000, 0xf); + rtw_write32(rtwdev, REG_BB_RX_PATH_11N, 0x03a05611); + rtw_write32(rtwdev, REG_TRMUX_11N, 0x000800e4); + rtw_write32(rtwdev, REG_BB_PWR_SAV1_11N, 0x25204200); + rtw8723d_iqk_precfg_path(rtwdev, PATH_S1); + + for (i = 0; i < PATH_IQK_RETRY; i++) { + s1_ok = rtw8723d_iqk_tx_path(rtwdev, &iqk_tx_cfg[PATH_S1], backup); + if (s1_ok == IQK_TX_OK) { + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] path S1 Tx IQK Success!!\n"); + result[t][IQK_S1_TX_X] = + rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX); + result[t][IQK_S1_TX_Y] = + rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY); + break; + } + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S1 Tx IQK Fail!!\n"); + result[t][IQK_S1_TX_X] = 0x100; + result[t][IQK_S1_TX_Y] = 0x0; + } + + for (i = 0; i < PATH_IQK_RETRY; i++) { + s1_ok = rtw8723d_iqk_rx_path(rtwdev, &iqk_tx_cfg[PATH_S1], backup); + if (s1_ok == (IQK_TX_OK | IQK_RX_OK)) { + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] path S1 Rx IQK Success!!\n"); + result[t][IQK_S1_RX_X] = + rtw_read32_mask(rtwdev, REG_IQK_RES_RX, BIT_MASK_RES_RX); + result[t][IQK_S1_RX_Y] = + rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_MASK_RES_RY); + break; + } + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S1 Rx IQK Fail!!\n"); + result[t][IQK_S1_RX_X] = 0x100; + result[t][IQK_S1_RX_Y] = 0x0; + } + + if (s1_ok == 0x0) + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S1 IQK is failed!!\n"); + + rtw8723d_iqk_precfg_path(rtwdev, PATH_S0); + + for (i = 0; i < PATH_IQK_RETRY; i++) { + s0_ok = rtw8723d_iqk_tx_path(rtwdev, &iqk_tx_cfg[PATH_S0], backup); + if (s0_ok == IQK_TX_OK) { + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] path S0 Tx IQK Success!!\n"); + result[t][IQK_S0_TX_X] = + rtw_read32_mask(rtwdev, REG_IQK_RES_TX, BIT_MASK_RES_TX); + result[t][IQK_S0_TX_Y] = + rtw_read32_mask(rtwdev, REG_IQK_RES_TY, BIT_MASK_RES_TY); + break; + } + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S0 Tx IQK Fail!!\n"); + result[t][IQK_S0_TX_X] = 0x100; + result[t][IQK_S0_TX_Y] = 0x0; + } + + for (i = 0; i < PATH_IQK_RETRY; i++) { + s0_ok = rtw8723d_iqk_rx_path(rtwdev, &iqk_tx_cfg[PATH_S0], backup); + if (s0_ok == (IQK_TX_OK | IQK_RX_OK)) { + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] path S0 Rx IQK Success!!\n"); + + result[t][IQK_S0_RX_X] = + rtw_read32_mask(rtwdev, REG_IQK_RES_RX, BIT_MASK_RES_RX); + result[t][IQK_S0_RX_Y] = + rtw_read32_mask(rtwdev, REG_IQK_RES_RY, BIT_MASK_RES_RY); + break; + } + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S0 Rx IQK Fail!!\n"); + result[t][IQK_S0_RX_X] = 0x100; + result[t][IQK_S0_RX_Y] = 0x0; + } + + if (s0_ok == 0x0) + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] path S0 IQK is failed!!\n"); + + rtw_write32_mask(rtwdev, REG_FPGA0_IQK_11N, BIT_MASK_IQK_MOD, RST_IQK); + mdelay(1); + + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] back to BB mode, load original value!\n"); +} + +static void rtw8723d_phy_calibration(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + s32 result[IQK_ROUND_SIZE][IQK_NR]; + struct iqk_backup_regs backup; + u8 i, j; + u8 final_candidate = IQK_ROUND_INVALID; + bool good; + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] Start!!!\n"); + + memset(result, 0, sizeof(result)); + + rtw8723d_iqk_backup_path_ctrl(rtwdev, &backup); + rtw8723d_iqk_backup_lte_path_gnt(rtwdev, &backup); + rtw8723d_iqk_backup_regs(rtwdev, &backup); + + for (i = IQK_ROUND_0; i <= IQK_ROUND_2; i++) { + rtw8723d_iqk_config_path_ctrl(rtwdev); + rtw8723d_iqk_config_lte_path_gnt(rtwdev); + + rtw8723d_iqk_one_round(rtwdev, result, i, &backup); + + if (i > IQK_ROUND_0) + rtw8723d_iqk_restore_regs(rtwdev, &backup); + rtw8723d_iqk_restore_lte_path_gnt(rtwdev, &backup); + rtw8723d_iqk_restore_path_ctrl(rtwdev, &backup); + + for (j = IQK_ROUND_0; j < i; j++) { + good = rtw8723d_iqk_similarity_cmp(rtwdev, result, j, i); + + if (good) { + final_candidate = j; + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] cmp %d:%d final_candidate is %x\n", + j, i, final_candidate); + goto iqk_done; + } + } + } + + if (final_candidate == IQK_ROUND_INVALID) { + s32 reg_tmp = 0; + + for (i = 0; i < IQK_NR; i++) + reg_tmp += result[IQK_ROUND_HYBRID][i]; + + if (reg_tmp != 0) { + final_candidate = IQK_ROUND_HYBRID; + } else { + WARN(1, "IQK is failed\n"); + goto out; + } + } + +iqk_done: + rtw8723d_iqk_fill_s1_matrix(rtwdev, result[final_candidate]); + rtw8723d_iqk_fill_s0_matrix(rtwdev, result[final_candidate]); + + dm_info->iqk.result.s1_x = result[final_candidate][IQK_S1_TX_X]; + dm_info->iqk.result.s1_y = result[final_candidate][IQK_S1_TX_Y]; + dm_info->iqk.result.s0_x = result[final_candidate][IQK_S0_TX_X]; + dm_info->iqk.result.s0_y = result[final_candidate][IQK_S0_TX_Y]; + dm_info->iqk.done = true; + +out: + rtw_write32(rtwdev, REG_BB_SEL_BTG, backup.bb_sel_btg); + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] final_candidate is %x\n", + final_candidate); + + for (i = IQK_ROUND_0; i < IQK_ROUND_SIZE; i++) + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK] Result %u: rege94_s1=%x rege9c_s1=%x regea4_s1=%x regeac_s1=%x rege94_s0=%x rege9c_s0=%x regea4_s0=%x regeac_s0=%x %s\n", + i, + result[i][0], result[i][1], result[i][2], result[i][3], + result[i][4], result[i][5], result[i][6], result[i][7], + final_candidate == i ? "(final candidate)" : ""); + + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK]0xc80 = 0x%x 0xc94 = 0x%x 0xc14 = 0x%x 0xca0 = 0x%x\n", + rtw_read32(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE), + rtw_read32(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N), + rtw_read32(rtwdev, REG_A_RXIQI), + rtw_read32(rtwdev, REG_RXIQK_MATRIX_LSB_11N)); + rtw_dbg(rtwdev, RTW_DBG_RFK, + "[IQK]0xcd0 = 0x%x 0xcd4 = 0x%x 0xcd8 = 0x%x\n", + rtw_read32(rtwdev, REG_TXIQ_AB_S0), + rtw_read32(rtwdev, REG_TXIQ_CD_S0), + rtw_read32(rtwdev, REG_RXIQ_AB_S0)); + + rtw_dbg(rtwdev, RTW_DBG_RFK, "[IQK] finished\n"); +} + +/* for coex */ +static void rtw8723d_coex_cfg_init(struct rtw_dev *rtwdev) +{ + /* enable TBTT nterrupt */ + rtw_write8_set(rtwdev, REG_BCN_CTRL, BIT_EN_BCN_FUNCTION); + + /* BT report packet sample rate */ + /* 0x790[5:0]=0x5 */ + rtw_write8_set(rtwdev, REG_BT_TDMA_TIME, 0x05); + + /* enable BT counter statistics */ + rtw_write8(rtwdev, REG_BT_STAT_CTRL, 0x1); + + /* enable PTA (3-wire function form BT side) */ + rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_PTA_EN); + rtw_write32_set(rtwdev, REG_GPIO_MUXCFG, BIT_BT_AOD_GPIO3); + + /* enable PTA (tx/rx signal form WiFi side) */ + rtw_write8_set(rtwdev, REG_QUEUE_CTRL, BIT_PTA_WL_TX_EN); +} + +static void rtw8723d_coex_cfg_gnt_fix(struct rtw_dev *rtwdev) +{ +} + +static void rtw8723d_coex_cfg_gnt_debug(struct rtw_dev *rtwdev) +{ + rtw_write8_mask(rtwdev, REG_LEDCFG2, BIT(6), 0); + rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 3, BIT(0), 0); + rtw_write8_mask(rtwdev, REG_GPIO_INTM + 2, BIT(4), 0); + rtw_write8_mask(rtwdev, REG_GPIO_MUXCFG + 2, BIT(1), 0); + rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 3, BIT(1), 0); + rtw_write8_mask(rtwdev, REG_PAD_CTRL1 + 2, BIT(7), 0); + rtw_write8_mask(rtwdev, REG_SYS_CLKR + 1, BIT(1), 0); + rtw_write8_mask(rtwdev, REG_SYS_SDIO_CTRL + 3, BIT(3), 0); +} + +static void rtw8723d_coex_cfg_rfe_type(struct rtw_dev *rtwdev) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_rfe *coex_rfe = &coex->rfe; + bool aux = efuse->bt_setting & BIT(6); + + coex_rfe->rfe_module_type = rtwdev->efuse.rfe_option; + coex_rfe->ant_switch_polarity = 0; + coex_rfe->ant_switch_exist = false; + coex_rfe->ant_switch_with_bt = false; + coex_rfe->ant_switch_diversity = false; + coex_rfe->wlg_at_btg = true; + + /* decide antenna at main or aux */ + if (efuse->share_ant) { + if (aux) + rtw_write16(rtwdev, REG_BB_SEL_BTG, 0x80); + else + rtw_write16(rtwdev, REG_BB_SEL_BTG, 0x200); + } else { + if (aux) + rtw_write16(rtwdev, REG_BB_SEL_BTG, 0x280); + else + rtw_write16(rtwdev, REG_BB_SEL_BTG, 0x0); + } + + /* disable LTE coex in wifi side */ + rtw_coex_write_indirect_reg(rtwdev, LTE_COEX_CTRL, BIT_LTE_COEX_EN, 0x0); + rtw_coex_write_indirect_reg(rtwdev, LTE_WL_TRX_CTRL, MASKLWORD, 0xffff); + rtw_coex_write_indirect_reg(rtwdev, LTE_BT_TRX_CTRL, MASKLWORD, 0xffff); +} + +static void rtw8723d_coex_cfg_wl_tx_power(struct rtw_dev *rtwdev, u8 wl_pwr) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + static const u8 wl_tx_power[] = {0xb2, 0x90}; + u8 pwr; + + if (wl_pwr == coex_dm->cur_wl_pwr_lvl) + return; + + coex_dm->cur_wl_pwr_lvl = wl_pwr; + + if (coex_dm->cur_wl_pwr_lvl >= ARRAY_SIZE(wl_tx_power)) + coex_dm->cur_wl_pwr_lvl = ARRAY_SIZE(wl_tx_power) - 1; + + pwr = wl_tx_power[coex_dm->cur_wl_pwr_lvl]; + + rtw_write8(rtwdev, REG_ANA_PARAM1 + 3, pwr); +} + +static void rtw8723d_coex_cfg_wl_rx_gain(struct rtw_dev *rtwdev, bool low_gain) +{ + struct rtw_coex *coex = &rtwdev->coex; + struct rtw_coex_dm *coex_dm = &coex->dm; + /* WL Rx Low gain on */ + static const u32 wl_rx_low_gain_on[] = { + 0xec120101, 0xeb130101, 0xce140101, 0xcd150101, 0xcc160101, + 0xcb170101, 0xca180101, 0x8d190101, 0x8c1a0101, 0x8b1b0101, + 0x4f1c0101, 0x4e1d0101, 0x4d1e0101, 0x4c1f0101, 0x0e200101, + 0x0d210101, 0x0c220101, 0x0b230101, 0xcf240001, 0xce250001, + 0xcd260001, 0xcc270001, 0x8f280001 + }; + /* WL Rx Low gain off */ + static const u32 wl_rx_low_gain_off[] = { + 0xec120101, 0xeb130101, 0xea140101, 0xe9150101, 0xe8160101, + 0xe7170101, 0xe6180101, 0xe5190101, 0xe41a0101, 0xe31b0101, + 0xe21c0101, 0xe11d0101, 0xe01e0101, 0x861f0101, 0x85200101, + 0x84210101, 0x83220101, 0x82230101, 0x81240101, 0x80250101, + 0x44260101, 0x43270101, 0x42280101 + }; + u8 i; + + if (low_gain == coex_dm->cur_wl_rx_low_gain_en) + return; + + coex_dm->cur_wl_rx_low_gain_en = low_gain; + + if (coex_dm->cur_wl_rx_low_gain_en) { + for (i = 0; i < ARRAY_SIZE(wl_rx_low_gain_on); i++) + rtw_write32(rtwdev, REG_AGCRSSI, wl_rx_low_gain_on[i]); + } else { + for (i = 0; i < ARRAY_SIZE(wl_rx_low_gain_off); i++) + rtw_write32(rtwdev, REG_AGCRSSI, wl_rx_low_gain_off[i]); + } +} + +static u8 rtw8723d_pwrtrack_get_limit_ofdm(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + u8 tx_rate = dm_info->tx_rate; + u8 limit_ofdm = 30; + + switch (tx_rate) { + case DESC_RATE1M...DESC_RATE5_5M: + case DESC_RATE11M: + break; + case DESC_RATE6M...DESC_RATE48M: + limit_ofdm = 36; + break; + case DESC_RATE54M: + limit_ofdm = 34; + break; + case DESC_RATEMCS0...DESC_RATEMCS2: + limit_ofdm = 38; + break; + case DESC_RATEMCS3...DESC_RATEMCS4: + limit_ofdm = 36; + break; + case DESC_RATEMCS5...DESC_RATEMCS7: + limit_ofdm = 34; + break; + default: + rtw_warn(rtwdev, "pwrtrack unhandled tx_rate 0x%x\n", tx_rate); + break; + } + + return limit_ofdm; +} + +static void rtw8723d_set_iqk_matrix_by_result(struct rtw_dev *rtwdev, + u32 ofdm_swing, u8 rf_path) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + s32 ele_A, ele_D, ele_C; + s32 ele_A_ext, ele_C_ext, ele_D_ext; + s32 iqk_result_x; + s32 iqk_result_y; + s32 value32; + + switch (rf_path) { + default: + case RF_PATH_A: + iqk_result_x = dm_info->iqk.result.s1_x; + iqk_result_y = dm_info->iqk.result.s1_y; + break; + case RF_PATH_B: + iqk_result_x = dm_info->iqk.result.s0_x; + iqk_result_y = dm_info->iqk.result.s0_y; + break; + } + + /* new element D */ + ele_D = OFDM_SWING_D(ofdm_swing); + iqk_mult(iqk_result_x, ele_D, &ele_D_ext); + /* new element A */ + iqk_result_x = iqkxy_to_s32(iqk_result_x); + ele_A = iqk_mult(iqk_result_x, ele_D, &ele_A_ext); + /* new element C */ + iqk_result_y = iqkxy_to_s32(iqk_result_y); + ele_C = iqk_mult(iqk_result_y, ele_D, &ele_C_ext); + + switch (rf_path) { + case RF_PATH_A: + default: + /* write new elements A, C, D, and element B is always 0 */ + value32 = BIT_SET_TXIQ_ELM_ACD(ele_A, ele_C, ele_D); + rtw_write32(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE, value32); + value32 = BIT_SET_TXIQ_ELM_C1(ele_C); + rtw_write32_mask(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N, MASKH4BITS, + value32); + value32 = rtw_read32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD); + value32 &= ~BIT_MASK_OFDM0_EXTS; + value32 |= BIT_SET_OFDM0_EXTS(ele_A_ext, ele_C_ext, ele_D_ext); + rtw_write32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD, value32); + break; + + case RF_PATH_B: + /* write new elements A, C, D, and element B is always 0 */ + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_S0, ele_D); + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_S0, ele_C); + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_S0, ele_A); + + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_EXT_S0, + ele_D_ext); + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_EXT_S0, + ele_A_ext); + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_EXT_S0, + ele_C_ext); + break; + } +} + +static void rtw8723d_set_iqk_matrix(struct rtw_dev *rtwdev, s8 ofdm_index, + u8 rf_path) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + s32 value32; + u32 ofdm_swing; + + if (ofdm_index >= RTW_OFDM_SWING_TABLE_SIZE) + ofdm_index = RTW_OFDM_SWING_TABLE_SIZE - 1; + else if (ofdm_index < 0) + ofdm_index = 0; + + ofdm_swing = rtw8723d_ofdm_swing_table[ofdm_index]; + + if (dm_info->iqk.done) { + rtw8723d_set_iqk_matrix_by_result(rtwdev, ofdm_swing, rf_path); + return; + } + + switch (rf_path) { + case RF_PATH_A: + default: + rtw_write32(rtwdev, REG_OFDM_0_XA_TX_IQ_IMBALANCE, ofdm_swing); + rtw_write32_mask(rtwdev, REG_TXIQK_MATRIXA_LSB2_11N, MASKH4BITS, + 0x00); + value32 = rtw_read32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD); + value32 &= ~BIT_MASK_OFDM0_EXTS; + rtw_write32(rtwdev, REG_OFDM_0_ECCA_THRESHOLD, value32); + break; + + case RF_PATH_B: + /* image S1:c80 to S0:Cd0 and Cd4 */ + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_S0, + OFDM_SWING_A(ofdm_swing)); + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_B_S0, + OFDM_SWING_B(ofdm_swing)); + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_S0, + OFDM_SWING_C(ofdm_swing)); + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_S0, + OFDM_SWING_D(ofdm_swing)); + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_D_EXT_S0, 0x0); + rtw_write32_mask(rtwdev, REG_TXIQ_CD_S0, BIT_MASK_TXIQ_C_EXT_S0, 0x0); + rtw_write32_mask(rtwdev, REG_TXIQ_AB_S0, BIT_MASK_TXIQ_A_EXT_S0, 0x0); + break; + } +} + +static void rtw8723d_pwrtrack_set_ofdm_pwr(struct rtw_dev *rtwdev, s8 swing_idx, + s8 txagc_idx) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + + dm_info->txagc_remnant_ofdm = txagc_idx; + + rtw8723d_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_A); + rtw8723d_set_iqk_matrix(rtwdev, swing_idx, RF_PATH_B); +} + +static void rtw8723d_pwrtrack_set_cck_pwr(struct rtw_dev *rtwdev, s8 swing_idx, + s8 txagc_idx) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + + dm_info->txagc_remnant_cck = txagc_idx; + + rtw_write32_mask(rtwdev, 0xab4, 0x000007FF, + rtw8723d_cck_swing_table[swing_idx]); +} + +static void rtw8723d_pwrtrack_set(struct rtw_dev *rtwdev, u8 path) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_hal *hal = &rtwdev->hal; + u8 limit_ofdm; + u8 limit_cck = 40; + s8 final_ofdm_swing_index; + s8 final_cck_swing_index; + + limit_ofdm = rtw8723d_pwrtrack_get_limit_ofdm(rtwdev); + + final_ofdm_swing_index = RTW_DEF_OFDM_SWING_INDEX + + dm_info->delta_power_index[path]; + final_cck_swing_index = RTW_DEF_CCK_SWING_INDEX + + dm_info->delta_power_index[path]; + + if (final_ofdm_swing_index > limit_ofdm) + rtw8723d_pwrtrack_set_ofdm_pwr(rtwdev, limit_ofdm, + final_ofdm_swing_index - limit_ofdm); + else if (final_ofdm_swing_index < 0) + rtw8723d_pwrtrack_set_ofdm_pwr(rtwdev, 0, + final_ofdm_swing_index); + else + rtw8723d_pwrtrack_set_ofdm_pwr(rtwdev, final_ofdm_swing_index, 0); + + if (final_cck_swing_index > limit_cck) + rtw8723d_pwrtrack_set_cck_pwr(rtwdev, limit_cck, + final_cck_swing_index - limit_cck); + else if (final_cck_swing_index < 0) + rtw8723d_pwrtrack_set_cck_pwr(rtwdev, 0, + final_cck_swing_index); + else + rtw8723d_pwrtrack_set_cck_pwr(rtwdev, final_cck_swing_index, 0); + + rtw_phy_set_tx_power_level(rtwdev, hal->current_channel); +} + +static void rtw8723d_pwrtrack_set_xtal(struct rtw_dev *rtwdev, u8 therm_path, + u8 delta) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + const struct rtw_pwr_track_tbl *tbl = rtwdev->chip->pwr_track_tbl; + const s8 *pwrtrk_xtal; + s8 xtal_cap; + + if (dm_info->thermal_avg[therm_path] > + rtwdev->efuse.thermal_meter[therm_path]) + pwrtrk_xtal = tbl->pwrtrk_xtal_p; + else + pwrtrk_xtal = tbl->pwrtrk_xtal_n; + + xtal_cap = rtwdev->efuse.crystal_cap & 0x3F; + xtal_cap = clamp_t(s8, xtal_cap + pwrtrk_xtal[delta], 0, 0x3F); + rtw_write32_mask(rtwdev, REG_AFE_CTRL3, BIT_MASK_XTAL, + xtal_cap | (xtal_cap << 6)); +} + +static void rtw8723d_phy_pwrtrack(struct rtw_dev *rtwdev) +{ + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + struct rtw_swing_table swing_table; + u8 thermal_value, delta, path; + bool do_iqk = false; + + rtw_phy_config_swing_table(rtwdev, &swing_table); + + if (rtwdev->efuse.thermal_meter[0] == 0xff) + return; + + thermal_value = rtw_read_rf(rtwdev, RF_PATH_A, RF_T_METER, 0xfc00); + + rtw_phy_pwrtrack_avg(rtwdev, thermal_value, RF_PATH_A); + + do_iqk = rtw_phy_pwrtrack_need_iqk(rtwdev); + + if (do_iqk) + rtw8723d_lck(rtwdev); + + if (dm_info->pwr_trk_init_trigger) + dm_info->pwr_trk_init_trigger = false; + else if (!rtw_phy_pwrtrack_thermal_changed(rtwdev, thermal_value, + RF_PATH_A)) + goto iqk; + + delta = rtw_phy_pwrtrack_get_delta(rtwdev, RF_PATH_A); + + delta = min_t(u8, delta, RTW_PWR_TRK_TBL_SZ - 1); + + for (path = 0; path < rtwdev->hal.rf_path_num; path++) { + s8 delta_cur, delta_last; + + delta_last = dm_info->delta_power_index[path]; + delta_cur = rtw_phy_pwrtrack_get_pwridx(rtwdev, &swing_table, + path, RF_PATH_A, delta); + if (delta_last == delta_cur) + continue; + + dm_info->delta_power_index[path] = delta_cur; + rtw8723d_pwrtrack_set(rtwdev, path); + } + + rtw8723d_pwrtrack_set_xtal(rtwdev, RF_PATH_A, delta); + +iqk: + if (do_iqk) + rtw8723d_phy_calibration(rtwdev); +} + +static void rtw8723d_pwr_track(struct rtw_dev *rtwdev) +{ + struct rtw_efuse *efuse = &rtwdev->efuse; + struct rtw_dm_info *dm_info = &rtwdev->dm_info; + + if (efuse->power_track_type != 0) + return; + + if (!dm_info->pwr_trk_triggered) { + rtw_write_rf(rtwdev, RF_PATH_A, RF_T_METER, + GENMASK(17, 16), 0x03); + dm_info->pwr_trk_triggered = true; + return; + } + + rtw8723d_phy_pwrtrack(rtwdev); + dm_info->pwr_trk_triggered = false; +} + static struct rtw_chip_ops rtw8723d_ops = { .phy_set_param = rtw8723d_phy_set_param, .read_efuse = rtw8723d_read_efuse, .query_rx_desc = rtw8723d_query_rx_desc, .set_channel = rtw8723d_set_channel, .mac_init = rtw8723d_mac_init, + .shutdown = rtw8723d_shutdown, .read_rf = rtw_phy_read_rf_sipi, .write_rf = rtw_phy_write_rf_reg_sipi, .set_tx_power_index = rtw8723d_set_tx_power_index, @@ -616,9 +1929,161 @@ static struct rtw_chip_ops rtw8723d_ops = { .cfg_ldo25 = rtw8723d_cfg_ldo25, .efuse_grant = rtw8723d_efuse_grant, .false_alarm_statistics = rtw8723d_false_alarm_statistics, + .phy_calibration = rtw8723d_phy_calibration, + .pwr_track = rtw8723d_pwr_track, .config_bfee = NULL, .set_gid_table = NULL, .cfg_csi_rate = NULL, + + .coex_set_init = rtw8723d_coex_cfg_init, + .coex_set_ant_switch = NULL, + .coex_set_gnt_fix = rtw8723d_coex_cfg_gnt_fix, + .coex_set_gnt_debug = rtw8723d_coex_cfg_gnt_debug, + .coex_set_rfe_type = rtw8723d_coex_cfg_rfe_type, + .coex_set_wl_tx_power = rtw8723d_coex_cfg_wl_tx_power, + .coex_set_wl_rx_gain = rtw8723d_coex_cfg_wl_rx_gain, +}; + +/* Shared-Antenna Coex Table */ +static const struct coex_table_para table_sant_8723d[] = { + {0xffffffff, 0xffffffff}, /* case-0 */ + {0x55555555, 0x55555555}, + {0x65555555, 0x65555555}, + {0xaaaaaaaa, 0xaaaaaaaa}, + {0x5a5a5a5a, 0x5a5a5a5a}, + {0xfafafafa, 0xfafafafa}, /* case-5 */ + {0xa5555555, 0xaaaa5aaa}, + {0x6a5a5a5a, 0x5a5a5a5a}, + {0x6a5a5a5a, 0x6a5a5a5a}, + {0x65555555, 0x5a5a5a5a}, + {0x65555555, 0x6a5a5a5a}, /* case-10 */ + {0x65555555, 0xfafafafa}, + {0x65555555, 0x6a5a5aaa}, + {0x65555555, 0x5aaa5aaa}, + {0x65555555, 0xaaaa5aaa}, + {0x65555555, 0xaaaaaaaa}, /* case-15 */ + {0xffff55ff, 0xfafafafa}, + {0xffff55ff, 0x6afa5afa}, + {0xaaffffaa, 0xfafafafa}, + {0xaa5555aa, 0x5a5a5a5a}, + {0xaa5555aa, 0x6a5a5a5a}, /* case-20 */ + {0xaa5555aa, 0xaaaaaaaa}, + {0xffffffff, 0x5a5a5a5a}, + {0xffffffff, 0x6a5a5a5a}, + {0xffffffff, 0x55555555}, + {0xffffffff, 0x6a5a5aaa}, /* case-25 */ + {0x55555555, 0x5a5a5a5a}, + {0x55555555, 0xaaaaaaaa}, + {0x55555555, 0x6a6a6a6a}, + {0x656a656a, 0x656a656a} +}; + +/* Non-Shared-Antenna Coex Table */ +static const struct coex_table_para table_nsant_8723d[] = { + {0xffffffff, 0xffffffff}, /* case-100 */ + {0x55555555, 0x55555555}, + {0x65555555, 0x65555555}, + {0xaaaaaaaa, 0xaaaaaaaa}, + {0x5a5a5a5a, 0x5a5a5a5a}, + {0xfafafafa, 0xfafafafa}, /* case-105 */ + {0x5afa5afa, 0x5afa5afa}, + {0x55555555, 0xfafafafa}, + {0x65555555, 0xfafafafa}, + {0x65555555, 0x5a5a5a5a}, + {0x65555555, 0x6a5a5a5a}, /* case-110 */ + {0x65555555, 0xaaaaaaaa}, + {0xffff55ff, 0xfafafafa}, + {0xffff55ff, 0x5afa5afa}, + {0xffff55ff, 0xaaaaaaaa}, + {0xaaffffaa, 0xfafafafa}, /* case-115 */ + {0xaaffffaa, 0x5afa5afa}, + {0xaaffffaa, 0xaaaaaaaa}, + {0xffffffff, 0xfafafafa}, + {0xffffffff, 0x5afa5afa}, + {0xffffffff, 0xaaaaaaaa},/* case-120 */ + {0x55ff55ff, 0x5afa5afa}, + {0x55ff55ff, 0xaaaaaaaa}, + {0x55ff55ff, 0x55ff55ff} +}; + +/* Shared-Antenna TDMA */ +static const struct coex_tdma_para tdma_sant_8723d[] = { + { {0x08, 0x00, 0x00, 0x00, 0x00} }, /* case-0 */ + { {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-1 */ + { {0x61, 0x3a, 0x03, 0x11, 0x11} }, + { {0x61, 0x20, 0x03, 0x11, 0x11} }, + { {0x61, 0x30, 0x03, 0x11, 0x11} }, + { {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-5 */ + { {0x61, 0x48, 0x03, 0x11, 0x10} }, + { {0x61, 0x3a, 0x03, 0x11, 0x10} }, + { {0x61, 0x30, 0x03, 0x11, 0x10} }, + { {0x61, 0x20, 0x03, 0x11, 0x10} }, + { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-10 */ + { {0x61, 0x10, 0x03, 0x11, 0x14} }, + { {0x61, 0x08, 0x03, 0x10, 0x14} }, + { {0x51, 0x10, 0x03, 0x10, 0x54} }, + { {0x51, 0x10, 0x03, 0x10, 0x55} }, + { {0x51, 0x10, 0x07, 0x10, 0x54} }, /* case-15 */ + { {0x51, 0x45, 0x03, 0x10, 0x50} }, + { {0x51, 0x3a, 0x03, 0x10, 0x50} }, + { {0x51, 0x30, 0x03, 0x10, 0x50} }, + { {0x51, 0x20, 0x03, 0x10, 0x50} }, + { {0x51, 0x15, 0x03, 0x10, 0x50} }, /* case-20 */ + { {0x51, 0x4a, 0x03, 0x10, 0x50} }, + { {0x51, 0x0c, 0x03, 0x10, 0x54} }, + { {0x55, 0x08, 0x03, 0x10, 0x54} }, + { {0x65, 0x10, 0x03, 0x11, 0x11} }, + { {0x51, 0x10, 0x03, 0x10, 0x51} }, + { {0x61, 0x15, 0x03, 0x11, 0x10} } +}; + +/* Non-Shared-Antenna TDMA */ +static const struct coex_tdma_para tdma_nsant_8723d[] = { + { {0x00, 0x00, 0x00, 0x40, 0x00} }, /* case-100 */ + { {0x61, 0x45, 0x03, 0x11, 0x11} }, /* case-101 */ + { {0x61, 0x3a, 0x03, 0x11, 0x11} }, + { {0x61, 0x30, 0x03, 0x11, 0x11} }, + { {0x61, 0x20, 0x03, 0x11, 0x11} }, + { {0x61, 0x10, 0x03, 0x11, 0x11} }, /* case-105 */ + { {0x61, 0x45, 0x03, 0x11, 0x10} }, + { {0x61, 0x3a, 0x03, 0x11, 0x10} }, + { {0x61, 0x30, 0x03, 0x11, 0x10} }, + { {0x61, 0x20, 0x03, 0x11, 0x10} }, + { {0x61, 0x10, 0x03, 0x11, 0x10} }, /* case-110 */ + { {0x61, 0x08, 0x03, 0x11, 0x14} }, + { {0x61, 0x08, 0x03, 0x10, 0x14} }, + { {0x51, 0x08, 0x03, 0x10, 0x54} }, + { {0x51, 0x08, 0x03, 0x10, 0x55} }, + { {0x51, 0x08, 0x07, 0x10, 0x54} }, /* case-115 */ + { {0x51, 0x45, 0x03, 0x10, 0x50} }, + { {0x51, 0x3a, 0x03, 0x10, 0x50} }, + { {0x51, 0x30, 0x03, 0x10, 0x50} }, + { {0x51, 0x20, 0x03, 0x10, 0x50} }, + { {0x51, 0x10, 0x03, 0x10, 0x50} } +}; + +/* rssi in percentage % (dbm = % - 100) */ +static const u8 wl_rssi_step_8723d[] = {60, 50, 44, 30}; +static const u8 bt_rssi_step_8723d[] = {30, 30, 30, 30}; +static const struct coex_5g_afh_map afh_5g_8723d[] = { {0, 0, 0} }; + +/* wl_tx_dec_power, bt_tx_dec_power, wl_rx_gain, bt_rx_lna_constrain */ +static const struct coex_rf_para rf_para_tx_8723d[] = { + {0, 0, false, 7}, /* for normal */ + {0, 10, false, 7}, /* for WL-CPT */ + {1, 0, true, 4}, + {1, 2, true, 4}, + {1, 10, true, 4}, + {1, 15, true, 4} +}; + +static const struct coex_rf_para rf_para_rx_8723d[] = { + {0, 0, false, 7}, /* for normal */ + {0, 10, false, 7}, /* for WL-CPT */ + {1, 0, true, 5}, + {1, 2, true, 5}, + {1, 10, true, 5}, + {1, 15, true, 5} }; static const struct rtw_pwr_seq_cmd trans_carddis_to_cardemu_8723d[] = { @@ -1048,6 +2513,22 @@ static const struct rtw_rqpn rqpn_table_8723d[] = { RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, }; +static const struct rtw_prioq_addrs prioq_addrs_8723d = { + .prio[RTW_DMA_MAPPING_EXTRA] = { + .rsvd = REG_RQPN_NPQ + 2, .avail = REG_RQPN_NPQ + 3, + }, + .prio[RTW_DMA_MAPPING_LOW] = { + .rsvd = REG_RQPN + 1, .avail = REG_FIFOPAGE_CTRL_2 + 1, + }, + .prio[RTW_DMA_MAPPING_NORMAL] = { + .rsvd = REG_RQPN_NPQ, .avail = REG_RQPN_NPQ + 1, + }, + .prio[RTW_DMA_MAPPING_HIGH] = { + .rsvd = REG_RQPN, .avail = REG_FIFOPAGE_CTRL_2, + }, + .wsize = false, +}; + static const struct rtw_intf_phy_para pcie_gen1_param_8723d[] = { {0x0008, 0x4a22, RTW_IP_SEL_PHY, @@ -1084,11 +2565,102 @@ static const struct rtw_rf_sipi_addr rtw8723d_rf_sipi_addr[] = { .hssi_2 = 0x82c, .lssi_read_pi = 0x8bc}, }; +static const struct rtw_ltecoex_addr rtw8723d_ltecoex_addr = { + .ctrl = REG_LTECOEX_CTRL, + .wdata = REG_LTECOEX_WRITE_DATA, + .rdata = REG_LTECOEX_READ_DATA, +}; + static const struct rtw_rfe_def rtw8723d_rfe_defs[] = { [0] = { .phy_pg_tbl = &rtw8723d_bb_pg_tbl, .txpwr_lmt_tbl = &rtw8723d_txpwr_lmt_tbl,}, }; +static const u8 rtw8723d_pwrtrk_2gb_n[] = { + 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, + 6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 10 +}; + +static const u8 rtw8723d_pwrtrk_2gb_p[] = { + 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, + 7, 8, 8, 8, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10 +}; + +static const u8 rtw8723d_pwrtrk_2ga_n[] = { + 0, 0, 1, 1, 1, 2, 2, 3, 4, 4, 4, 4, 5, 5, 5, + 6, 6, 7, 7, 8, 8, 8, 9, 9, 9, 10, 10, 10, 10, 10 +}; + +static const u8 rtw8723d_pwrtrk_2ga_p[] = { + 0, 0, 1, 1, 2, 2, 2, 3, 3, 4, 4, 5, 5, 6, 7, + 7, 8, 8, 8, 9, 9, 10, 10, 10, 10, 10, 10, 10, 10, 10 +}; + +static const u8 rtw8723d_pwrtrk_2g_cck_b_n[] = { + 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11 +}; + +static const u8 rtw8723d_pwrtrk_2g_cck_b_p[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, + 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11 +}; + +static const u8 rtw8723d_pwrtrk_2g_cck_a_n[] = { + 0, 1, 1, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, + 6, 7, 7, 7, 8, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11 +}; + +static const u8 rtw8723d_pwrtrk_2g_cck_a_p[] = { + 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, + 7, 8, 9, 9, 10, 10, 11, 11, 11, 11, 11, 11, 11, 11, 11 +}; + +static const s8 rtw8723d_pwrtrk_xtal_n[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +static const s8 rtw8723d_pwrtrk_xtal_p[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, -10, -12, -14, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16, -16 +}; + +static const struct rtw_pwr_track_tbl rtw8723d_rtw_pwr_track_tbl = { + .pwrtrk_2gb_n = rtw8723d_pwrtrk_2gb_n, + .pwrtrk_2gb_p = rtw8723d_pwrtrk_2gb_p, + .pwrtrk_2ga_n = rtw8723d_pwrtrk_2ga_n, + .pwrtrk_2ga_p = rtw8723d_pwrtrk_2ga_p, + .pwrtrk_2g_cckb_n = rtw8723d_pwrtrk_2g_cck_b_n, + .pwrtrk_2g_cckb_p = rtw8723d_pwrtrk_2g_cck_b_p, + .pwrtrk_2g_ccka_n = rtw8723d_pwrtrk_2g_cck_a_n, + .pwrtrk_2g_ccka_p = rtw8723d_pwrtrk_2g_cck_a_p, + .pwrtrk_xtal_p = rtw8723d_pwrtrk_xtal_p, + .pwrtrk_xtal_n = rtw8723d_pwrtrk_xtal_n, +}; + +static const struct rtw_reg_domain coex_info_hw_regs_8723d[] = { + {0x948, MASKDWORD, RTW_REG_DOMAIN_MAC32}, + {0x67, BIT(7), RTW_REG_DOMAIN_MAC8}, + {0, 0, RTW_REG_DOMAIN_NL}, + {0x964, BIT(1), RTW_REG_DOMAIN_MAC8}, + {0x864, BIT(0), RTW_REG_DOMAIN_MAC8}, + {0xab7, BIT(5), RTW_REG_DOMAIN_MAC8}, + {0xa01, BIT(7), RTW_REG_DOMAIN_MAC8}, + {0, 0, RTW_REG_DOMAIN_NL}, + {0x430, MASKDWORD, RTW_REG_DOMAIN_MAC32}, + {0x434, MASKDWORD, RTW_REG_DOMAIN_MAC32}, + {0x42a, MASKLWORD, RTW_REG_DOMAIN_MAC16}, + {0x426, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, + {0x45e, BIT(3), RTW_REG_DOMAIN_MAC8}, + {0, 0, RTW_REG_DOMAIN_NL}, + {0x4c6, BIT(4), RTW_REG_DOMAIN_MAC8}, + {0x40, BIT(5), RTW_REG_DOMAIN_MAC8}, + {0x550, MASKDWORD, RTW_REG_DOMAIN_MAC32}, + {0x522, MASKBYTE0, RTW_REG_DOMAIN_MAC8}, + {0x953, BIT(1), RTW_REG_DOMAIN_MAC8}, +}; + struct rtw_chip_info rtw8723d_hw_spec = { .ops = &rtw8723d_ops, .id = RTW_CHIP_TYPE_8723D, @@ -1118,12 +2690,14 @@ struct rtw_chip_info rtw8723d_hw_spec = { .pwr_off_seq = card_disable_flow_8723d, .page_table = page_table_8723d, .rqpn_table = rqpn_table_8723d, + .prioq_addrs = &prioq_addrs_8723d, .intf_table = &phy_para_table_8723d, .dig = rtw8723d_dig, .dig_cck = rtw8723d_dig_cck, .rf_sipi_addr = {0x840, 0x844}, .rf_sipi_read_addr = rtw8723d_rf_sipi_addr, .fix_rf_phy_num = 2, + .ltecoex_addr = &rtw8723d_ltecoex_addr, .mac_tbl = &rtw8723d_mac_tbl, .agc_tbl = &rtw8723d_agc_tbl, .bb_tbl = &rtw8723d_bb_tbl, @@ -1131,6 +2705,37 @@ struct rtw_chip_info rtw8723d_hw_spec = { .rfe_defs = rtw8723d_rfe_defs, .rfe_defs_size = ARRAY_SIZE(rtw8723d_rfe_defs), .rx_ldpc = false, + .pwr_track_tbl = &rtw8723d_rtw_pwr_track_tbl, + .iqk_threshold = 8, + + .coex_para_ver = 0x1905302f, + .bt_desired_ver = 0x2f, + .scbd_support = true, + .new_scbd10_def = true, + .pstdma_type = COEX_PSTDMA_FORCE_LPSOFF, + .bt_rssi_type = COEX_BTRSSI_RATIO, + .ant_isolation = 15, + .rssi_tolerance = 2, + .wl_rssi_step = wl_rssi_step_8723d, + .bt_rssi_step = bt_rssi_step_8723d, + .table_sant_num = ARRAY_SIZE(table_sant_8723d), + .table_sant = table_sant_8723d, + .table_nsant_num = ARRAY_SIZE(table_nsant_8723d), + .table_nsant = table_nsant_8723d, + .tdma_sant_num = ARRAY_SIZE(tdma_sant_8723d), + .tdma_sant = tdma_sant_8723d, + .tdma_nsant_num = ARRAY_SIZE(tdma_nsant_8723d), + .tdma_nsant = tdma_nsant_8723d, + .wl_rf_para_num = ARRAY_SIZE(rf_para_tx_8723d), + .wl_rf_para_tx = rf_para_tx_8723d, + .wl_rf_para_rx = rf_para_rx_8723d, + .bt_afh_span_bw20 = 0x20, + .bt_afh_span_bw40 = 0x30, + .afh_5g_num = ARRAY_SIZE(afh_5g_8723d), + .afh_5g = afh_5g_8723d, + + .coex_info_hw_regs_num = ARRAY_SIZE(coex_info_hw_regs_8723d), + .coex_info_hw_regs = coex_info_hw_regs_8723d, }; EXPORT_SYMBOL(rtw8723d_hw_spec); diff --git a/drivers/net/wireless/realtek/rtw88/rtw8723d.h b/drivers/net/wireless/realtek/rtw88/rtw8723d.h index ac66f672bec8..31b8ed9ee652 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8723d.h +++ b/drivers/net/wireless/realtek/rtw88/rtw8723d.h @@ -5,6 +5,34 @@ #ifndef __RTW8723D_H__ #define __RTW8723D_H__ +enum rtw8723d_path { + PATH_S1, + PATH_S0, + PATH_NR, +}; + +enum rtw8723d_iqk_round { + IQK_ROUND_0, + IQK_ROUND_1, + IQK_ROUND_2, + IQK_ROUND_HYBRID, + IQK_ROUND_SIZE, + IQK_ROUND_INVALID = 0xff, +}; + +enum rtw8723d_iqk_result { + IQK_S1_TX_X, + IQK_S1_TX_Y, + IQK_S1_RX_X, + IQK_S1_RX_Y, + IQK_S0_TX_X, + IQK_S0_TX_Y, + IQK_S0_RX_X, + IQK_S0_RX_Y, + IQK_NR, + IQK_SX_NR = IQK_NR / PATH_NR, +}; + struct rtw8723de_efuse { u8 mac_addr[ETH_ALEN]; /* 0xd0 */ u8 vender_id[2]; @@ -66,6 +94,41 @@ struct rtw8723d_efuse { #define GET_PHY_STAT_P1_RXSNR_A(phy_stat) \ le32_get_bits(*((__le32 *)(phy_stat) + 0x06), GENMASK(7, 0)) +static inline s32 iqkxy_to_s32(s32 val) +{ + /* val is Q10.8 */ + return sign_extend32(val, 9); +} + +static inline s32 iqk_mult(s32 x, s32 y, s32 *ext) +{ + /* x, y and return value are Q10.8 */ + s32 t; + + t = x * y; + if (ext) + *ext = (t >> 7) & 0x1; /* Q.16 --> Q.9; get LSB of Q.9 */ + + return (t >> 8); /* Q.16 --> Q.8 */ +} + +#define OFDM_SWING_A(swing) FIELD_GET(GENMASK(9, 0), swing) +#define OFDM_SWING_B(swing) FIELD_GET(GENMASK(15, 10), swing) +#define OFDM_SWING_C(swing) FIELD_GET(GENMASK(21, 16), swing) +#define OFDM_SWING_D(swing) FIELD_GET(GENMASK(31, 22), swing) +#define RTW_DEF_OFDM_SWING_INDEX 28 +#define RTW_DEF_CCK_SWING_INDEX 28 + +#define MAX_TOLERANCE 5 +#define IQK_TX_X_ERR 0x142 +#define IQK_TX_Y_ERR 0x42 +#define IQK_RX_X_UPPER 0x11a +#define IQK_RX_X_LOWER 0xe6 +#define IQK_RX_Y_LMT 0x1a +#define IQK_TX_OK BIT(0) +#define IQK_RX_OK BIT(1) +#define PATH_IQK_RETRY 2 + #define SPUR_THRES 0x16 #define CCK_DFIR_NR 3 #define DIS_3WIRE 0xccf000c0 @@ -78,16 +141,27 @@ struct rtw8723d_efuse { #define RFCFGCH_BW_20M (BIT(11) | BIT(10)) #define RFCFGCH_BW_40M BIT(10) #define BIT_MASK_RFMOD BIT(0) +#define BIT_LCK BIT(15) +#define REG_GPIO_INTM 0x0048 +#define REG_BTG_SEL 0x0067 +#define REG_LTECOEX_PATH_CONTROL 0x0070 +#define REG_LTECOEX_CTRL 0x07c0 +#define REG_LTECOEX_WRITE_DATA 0x07c4 +#define REG_LTECOEX_READ_DATA 0x07c8 #define REG_PSDFN 0x0808 +#define REG_BB_PWR_SAV1_11N 0x0874 +#define REG_ANA_PARAM1 0x0880 #define REG_ANALOG_P4 0x088c #define REG_PSDRPT 0x08b4 #define REG_FPGA1_RFMOD 0x0900 +#define REG_BB_SEL_BTG 0x0948 #define REG_BBRX_DFIR 0x0954 #define BIT_MASK_RXBB_DFIR GENMASK(27, 24) #define BIT_RXBB_DFIR_EN BIT(19) #define REG_CCK0_SYS 0x0a00 #define BIT_CCK_SIDE_BAND BIT(4) +#define REG_CCK_ANT_SEL_11N 0x0a04 #define REG_CCK_FA_RST_11N 0x0a2c #define BIT_MASK_CCK_CNT_KEEP BIT(12) #define BIT_MASK_CCK_CNT_EN BIT(13) @@ -102,19 +176,57 @@ struct rtw8723d_efuse { #define BIT_MASK_CCK_FA_LSB GENMASK(15, 8) #define REG_OFDM_FA_HOLDC_11N 0x0c00 #define BIT_MASK_OFDM_FA_KEEP BIT(31) +#define REG_BB_RX_PATH_11N 0x0c04 +#define REG_TRMUX_11N 0x0c08 #define REG_OFDM_FA_RSTC_11N 0x0c0c #define BIT_MASK_OFDM_FA_RST BIT(31) +#define REG_A_RXIQI 0x0c14 +#define BIT_MASK_RXIQ_S1_X 0x000003FF +#define BIT_MASK_RXIQ_S1_Y1 0x0000FC00 +#define BIT_SET_RXIQ_S1_Y1(y) ((y) & 0x3F) #define REG_OFDM0_RXDSP 0x0c40 #define BIT_MASK_RXDSP GENMASK(28, 24) #define BIT_EN_RXDSP BIT(9) +#define REG_OFDM_0_ECCA_THRESHOLD 0x0c4c +#define BIT_MASK_OFDM0_EXT_A BIT(31) +#define BIT_MASK_OFDM0_EXT_C BIT(29) +#define BIT_MASK_OFDM0_EXTS (BIT(31) | BIT(29) | BIT(28)) +#define BIT_SET_OFDM0_EXTS(a, c, d) (((a) << 31) | ((c) << 29) | ((d) << 28)) #define REG_OFDM0_XAAGC1 0x0c50 #define REG_OFDM0_XBAGC1 0x0c58 +#define REG_AGCRSSI 0x0c78 +#define REG_OFDM_0_XA_TX_IQ_IMBALANCE 0x0c80 +#define BIT_MASK_TXIQ_ELM_A 0x03ff +#define BIT_SET_TXIQ_ELM_ACD(a, c, d) (((d) << 22) | (((c) & 0x3F) << 16) | \ + ((a) & 0x03ff)) +#define BIT_MASK_TXIQ_ELM_C GENMASK(21, 16) +#define BIT_SET_TXIQ_ELM_C2(c) ((c) & 0x3F) +#define BIT_MASK_TXIQ_ELM_D GENMASK(31, 22) +#define REG_TXIQK_MATRIXA_LSB2_11N 0x0c94 +#define BIT_SET_TXIQ_ELM_C1(c) (((c) & 0x000003C0) >> 6) +#define REG_RXIQK_MATRIX_LSB_11N 0x0ca0 +#define BIT_MASK_RXIQ_S1_Y2 0xF0000000 +#define BIT_SET_RXIQ_S1_Y2(y) (((y) >> 6) & 0xF) +#define REG_TXIQ_AB_S0 0x0cd0 +#define BIT_MASK_TXIQ_A_S0 0x000007FE +#define BIT_MASK_TXIQ_A_EXT_S0 BIT(0) +#define BIT_MASK_TXIQ_B_S0 0x0007E000 +#define REG_TXIQ_CD_S0 0x0cd4 +#define BIT_MASK_TXIQ_C_S0 0x000007FE +#define BIT_MASK_TXIQ_C_EXT_S0 BIT(0) +#define BIT_MASK_TXIQ_D_S0 GENMASK(22, 13) +#define BIT_MASK_TXIQ_D_EXT_S0 BIT(12) +#define REG_RXIQ_AB_S0 0x0cd8 +#define BIT_MASK_RXIQ_X_S0 0x000003FF +#define BIT_MASK_RXIQ_Y_S0 0x003FF000 #define REG_OFDM_FA_TYPE1_11N 0x0cf0 #define BIT_MASK_OFDM_FF_CNT GENMASK(15, 0) #define BIT_MASK_OFDM_SF_CNT GENMASK(31, 16) #define REG_OFDM_FA_RSTD_11N 0x0d00 #define BIT_MASK_OFDM_FA_RST1 BIT(27) #define BIT_MASK_OFDM_FA_KEEP1 BIT(31) +#define REG_CTX 0x0d03 +#define BIT_MASK_CTX_TYPE GENMASK(6, 4) #define REG_OFDM1_CFOTRK 0x0d2c #define BIT_EN_CFOTRK BIT(28) #define REG_OFDM1_CSI1 0x0d40 @@ -129,6 +241,32 @@ struct rtw8723d_efuse { #define BIT_MASK_OFDM_CRC_CNT GENMASK(31, 16) #define REG_OFDM_FA_TYPE4_11N 0x0da8 #define BIT_MASK_OFDM_MNS_CNT GENMASK(15, 0) +#define REG_FPGA0_IQK_11N 0x0e28 +#define BIT_MASK_IQK_MOD 0xffffff00 +#define EN_IQK 0x808000 +#define RST_IQK 0x000000 +#define REG_TXIQK_TONE_A_11N 0x0e30 +#define REG_RXIQK_TONE_A_11N 0x0e34 +#define REG_TXIQK_PI_A_11N 0x0e38 +#define REG_RXIQK_PI_A_11N 0x0e3c +#define REG_TXIQK_11N 0x0e40 +#define BIT_SET_TXIQK_11N(x, y) (0x80007C00 | ((x) << 16) | (y)) +#define REG_RXIQK_11N 0x0e44 +#define REG_IQK_AGC_PTS_11N 0x0e48 +#define REG_IQK_AGC_RSP_11N 0x0e4c +#define REG_TX_IQK_TONE_B 0x0e50 +#define REG_RX_IQK_TONE_B 0x0e54 +#define REG_IQK_RES_TX 0x0e94 +#define BIT_MASK_RES_TX GENMASK(25, 16) +#define REG_IQK_RES_TY 0x0e9c +#define BIT_MASK_RES_TY GENMASK(25, 16) +#define REG_IQK_RES_RX 0x0ea4 +#define BIT_MASK_RES_RX GENMASK(25, 16) +#define REG_IQK_RES_RY 0x0eac +#define BIT_IQK_TX_FAIL BIT(28) +#define BIT_IQK_RX_FAIL BIT(27) +#define BIT_IQK_DONE BIT(26) +#define BIT_MASK_RES_RY GENMASK(25, 16) #define REG_PAGE_F_RST_11N 0x0f14 #define BIT_MASK_F_RST_ALL BIT(16) #define REG_IGI_C_11N 0x0f84 diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822b.c b/drivers/net/wireless/realtek/rtw88/rtw8822b.c index 45636382dafd..18c5a5a96d90 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822b.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822b.c @@ -2057,6 +2057,12 @@ static const struct rtw_hw_reg rtw8822b_dig[] = { [1] = { .addr = 0xe50, .mask = 0x7f }, }; +static const struct rtw_ltecoex_addr rtw8822b_ltecoex_addr = { + .ctrl = LTECOEX_ACCESS_CTRL, + .wdata = LTECOEX_WRITE_DATA, + .rdata = LTECOEX_READ_DATA, +}; + static const struct rtw_page_table page_table_8822b[] = { {64, 64, 64, 64, 1}, {64, 64, 64, 64, 1}, @@ -2083,6 +2089,22 @@ static const struct rtw_rqpn rqpn_table_8822b[] = { RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, }; +static struct rtw_prioq_addrs prioq_addrs_8822b = { + .prio[RTW_DMA_MAPPING_EXTRA] = { + .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2, + }, + .prio[RTW_DMA_MAPPING_LOW] = { + .rsvd = REG_FIFOPAGE_INFO_2, .avail = REG_FIFOPAGE_INFO_2 + 2, + }, + .prio[RTW_DMA_MAPPING_NORMAL] = { + .rsvd = REG_FIFOPAGE_INFO_3, .avail = REG_FIFOPAGE_INFO_3 + 2, + }, + .prio[RTW_DMA_MAPPING_HIGH] = { + .rsvd = REG_FIFOPAGE_INFO_1, .avail = REG_FIFOPAGE_INFO_1 + 2, + }, + .wsize = true, +}; + static struct rtw_chip_ops rtw8822b_ops = { .phy_set_param = rtw8822b_phy_set_param, .read_efuse = rtw8822b_read_efuse, @@ -2433,11 +2455,13 @@ struct rtw_chip_info rtw8822b_hw_spec = { .pwr_off_seq = card_disable_flow_8822b, .page_table = page_table_8822b, .rqpn_table = rqpn_table_8822b, + .prioq_addrs = &prioq_addrs_8822b, .intf_table = &phy_para_table_8822b, .dig = rtw8822b_dig, .dig_cck = NULL, .rf_base_addr = {0x2800, 0x2c00}, .rf_sipi_addr = {0xc90, 0xe90}, + .ltecoex_addr = &rtw8822b_ltecoex_addr, .mac_tbl = &rtw8822b_mac_tbl, .agc_tbl = &rtw8822b_agc_tbl, .bb_tbl = &rtw8822b_bb_tbl, diff --git a/drivers/net/wireless/realtek/rtw88/rtw8822c.c b/drivers/net/wireless/realtek/rtw88/rtw8822c.c index 64b77a7cbffd..d697d70170af 100644 --- a/drivers/net/wireless/realtek/rtw88/rtw8822c.c +++ b/drivers/net/wireless/realtek/rtw88/rtw8822c.c @@ -3907,6 +3907,12 @@ static const struct rtw_hw_reg rtw8822c_dig[] = { [1] = { .addr = 0x1d70, .mask = 0x7f00 }, }; +static const struct rtw_ltecoex_addr rtw8822c_ltecoex_addr = { + .ctrl = LTECOEX_ACCESS_CTRL, + .wdata = LTECOEX_WRITE_DATA, + .rdata = LTECOEX_READ_DATA, +}; + static const struct rtw_page_table page_table_8822c[] = { {64, 64, 64, 64, 1}, {64, 64, 64, 64, 1}, @@ -3933,6 +3939,22 @@ static const struct rtw_rqpn rqpn_table_8822c[] = { RTW_DMA_MAPPING_EXTRA, RTW_DMA_MAPPING_HIGH}, }; +static struct rtw_prioq_addrs prioq_addrs_8822c = { + .prio[RTW_DMA_MAPPING_EXTRA] = { + .rsvd = REG_FIFOPAGE_INFO_4, .avail = REG_FIFOPAGE_INFO_4 + 2, + }, + .prio[RTW_DMA_MAPPING_LOW] = { + .rsvd = REG_FIFOPAGE_INFO_2, .avail = REG_FIFOPAGE_INFO_2 + 2, + }, + .prio[RTW_DMA_MAPPING_NORMAL] = { + .rsvd = REG_FIFOPAGE_INFO_3, .avail = REG_FIFOPAGE_INFO_3 + 2, + }, + .prio[RTW_DMA_MAPPING_HIGH] = { + .rsvd = REG_FIFOPAGE_INFO_1, .avail = REG_FIFOPAGE_INFO_1 + 2, + }, + .wsize = true, +}; + static struct rtw_chip_ops rtw8822c_ops = { .phy_set_param = rtw8822c_phy_set_param, .read_efuse = rtw8822c_read_efuse, @@ -4295,11 +4317,13 @@ struct rtw_chip_info rtw8822c_hw_spec = { .pwr_off_seq = card_disable_flow_8822c, .page_table = page_table_8822c, .rqpn_table = rqpn_table_8822c, + .prioq_addrs = &prioq_addrs_8822c, .intf_table = &phy_para_table_8822c, .dig = rtw8822c_dig, .dig_cck = NULL, .rf_base_addr = {0x3c00, 0x4c00}, .rf_sipi_addr = {0x1808, 0x4108}, + .ltecoex_addr = &rtw8822c_ltecoex_addr, .mac_tbl = &rtw8822c_mac_tbl, .agc_tbl = &rtw8822c_agc_tbl, .bb_tbl = &rtw8822c_bb_tbl, diff --git a/drivers/net/wireless/realtek/rtw88/sec.c b/drivers/net/wireless/realtek/rtw88/sec.c index d0d7fbb10d58..ce46e5b4a60a 100644 --- a/drivers/net/wireless/realtek/rtw88/sec.c +++ b/drivers/net/wireless/realtek/rtw88/sec.c @@ -44,7 +44,7 @@ void rtw_sec_write_cam(struct rtw_dev *rtwdev, write_cmd = RTW_SEC_CMD_WRITE_ENABLE | RTW_SEC_CMD_POLLING; addr = hw_key_idx << RTW_SEC_CAM_ENTRY_SHIFT; - for (i = 5; i >= 0; i--) { + for (i = 7; i >= 0; i--) { switch (i) { case 0: content = ((key->keyidx & 0x3)) | @@ -60,6 +60,10 @@ void rtw_sec_write_cam(struct rtw_dev *rtwdev, (cam->addr[4] << 16) | (cam->addr[5] << 24); break; + case 6: + case 7: + content = 0; + break; default: j = (i - 2) << 2; content = (key->key[j]) | diff --git a/drivers/net/wireless/realtek/rtw88/util.c b/drivers/net/wireless/realtek/rtw88/util.c index 10f1117c0cfb..42cf177cd445 100644 --- a/drivers/net/wireless/realtek/rtw88/util.c +++ b/drivers/net/wireless/realtek/rtw88/util.c @@ -22,22 +22,28 @@ bool check_hw_ready(struct rtw_dev *rtwdev, u32 addr, u32 mask, u32 target) bool ltecoex_read_reg(struct rtw_dev *rtwdev, u16 offset, u32 *val) { - if (!check_hw_ready(rtwdev, LTECOEX_ACCESS_CTRL, LTECOEX_READY, 1)) + struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_ltecoex_addr *ltecoex = chip->ltecoex_addr; + + if (!check_hw_ready(rtwdev, ltecoex->ctrl, LTECOEX_READY, 1)) return false; - rtw_write32(rtwdev, LTECOEX_ACCESS_CTRL, 0x800F0000 | offset); - *val = rtw_read32(rtwdev, LTECOEX_READ_DATA); + rtw_write32(rtwdev, ltecoex->ctrl, 0x800F0000 | offset); + *val = rtw_read32(rtwdev, ltecoex->rdata); return true; } bool ltecoex_reg_write(struct rtw_dev *rtwdev, u16 offset, u32 value) { - if (!check_hw_ready(rtwdev, LTECOEX_ACCESS_CTRL, LTECOEX_READY, 1)) + struct rtw_chip_info *chip = rtwdev->chip; + const struct rtw_ltecoex_addr *ltecoex = chip->ltecoex_addr; + + if (!check_hw_ready(rtwdev, ltecoex->ctrl, LTECOEX_READY, 1)) return false; - rtw_write32(rtwdev, LTECOEX_WRITE_DATA, value); - rtw_write32(rtwdev, LTECOEX_ACCESS_CTRL, 0xC00F0000 | offset); + rtw_write32(rtwdev, ltecoex->wdata, value); + rtw_write32(rtwdev, ltecoex->ctrl, 0xC00F0000 | offset); return true; } |