To avoid the firmware loading race between Bluetooth and WiFi on Intel 8260, load firmware exclusively when BT_INTEL is enabled. BugLink: https://bugs.launchpad.net/bugs/1832988 Signed-off-by: Kai-Heng Feng <kai.heng.feng@xxxxxxxxxxxxx> --- v2: - Add bug report link. - Rebase on latest wireless-next. .../net/wireless/intel/iwlwifi/pcie/trans.c | 37 ++++++++++++++++++- 1 file changed, 36 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 602c31b3992a..e10ff847b216 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -72,6 +72,7 @@ #include <linux/pm_runtime.h> #include <linux/module.h> #include <linux/wait.h> +#include <linux/intel-wifi-bt.h> #include "iwl-drv.h" #include "iwl-trans.h" @@ -1335,6 +1336,10 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, bool hw_rfkill; int ret; +#if IS_ENABLED(CONFIG_BT_INTEL) + void (*firmware_lock_func)(void); + void (*firmware_unlock_func)(void); +#endif /* This may fail if AMT took ownership of the device */ if (iwl_pcie_prepare_card_hw(trans)) { IWL_WARN(trans, "Exit HW not ready\n"); @@ -1394,6 +1399,7 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, * RF-Kill switch is toggled, we will find out after having loaded * the firmware and return the proper value to the caller. */ + iwl_enable_fw_load_int(trans); /* really make sure rfkill handshake bits are cleared */ @@ -1401,8 +1407,37 @@ static int iwl_trans_pcie_start_fw(struct iwl_trans *trans, iwl_write32(trans, CSR_UCODE_DRV_GP1_CLR, CSR_UCODE_SW_BIT_RFKILL); /* Load the given image to the HW */ - if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) + if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_8000) { +#if IS_ENABLED(CONFIG_BT_INTEL) + firmware_lock_func = symbol_request(btintel_firmware_lock); + firmware_unlock_func = symbol_request(btintel_firmware_unlock); + if (!firmware_lock_func || !firmware_unlock_func) { + if (firmware_lock_func) { + symbol_put(btintel_firmware_lock); + firmware_lock_func = NULL; + } + + if (firmware_unlock_func) { + symbol_put(btintel_firmware_unlock); + firmware_unlock_func = NULL; + } + } + + if (firmware_lock_func) + firmware_lock_func(); +#endif ret = iwl_pcie_load_given_ucode_8000(trans, fw); + +#if IS_ENABLED(CONFIG_BT_INTEL) + if (firmware_unlock_func) { + firmware_unlock_func(); + symbol_put(btintel_firmware_lock); + firmware_lock_func = NULL; + symbol_put(btintel_firmware_unlock); + firmware_unlock_func = NULL; + } +#endif + } else ret = iwl_pcie_load_given_ucode(trans, fw); -- 2.17.1