mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2025-08-05 16:54:27 +00:00
iwlwifi: pcie: don't enable BHs with IRQs disabled
After the fix from Jiri that disabled local IRQs instead of
just BHs (necessary to fix an issue with submitting a command
with IRQs already disabled), there was still a situation in
which we could deep in there enable BHs, if the device config
sets the apmg_wake_up_wa configuration, which is true on all
7000 series devices.
To fix that, but not require reverting commit 1ed08f6fb5
("iwlwifi: remove flags argument for nic_access"), split up
nic access into a version with BH manipulation to use most
of the time, and without it for this specific case where the
local IRQs are already disabled.
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
Link: https://lore.kernel.org/r/iwlwifi.20210415164821.d0f2edda1651.I75f762e0bed38914d1300ea198b86dd449b4b206@changeid
This commit is contained in:
parent
fa84df7052
commit
c544d89b0d
3 changed files with 28 additions and 5 deletions
|
@ -447,6 +447,11 @@ struct iwl_trans
|
|||
const struct iwl_cfg_trans_params *cfg_trans);
|
||||
void iwl_trans_pcie_free(struct iwl_trans *trans);
|
||||
|
||||
bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans);
|
||||
#define _iwl_trans_pcie_grab_nic_access(trans) \
|
||||
__cond_lock(nic_access_nobh, \
|
||||
likely(__iwl_trans_pcie_grab_nic_access(trans)))
|
||||
|
||||
/*****************************************************
|
||||
* RX
|
||||
******************************************************/
|
||||
|
|
|
@ -1978,12 +1978,16 @@ static void iwl_trans_pcie_removal_wk(struct work_struct *wk)
|
|||
module_put(THIS_MODULE);
|
||||
}
|
||||
|
||||
static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans)
|
||||
/*
|
||||
* This version doesn't disable BHs but rather assumes they're
|
||||
* already disabled.
|
||||
*/
|
||||
bool __iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans)
|
||||
{
|
||||
int ret;
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
||||
spin_lock_bh(&trans_pcie->reg_lock);
|
||||
spin_lock(&trans_pcie->reg_lock);
|
||||
|
||||
if (trans_pcie->cmd_hold_nic_awake)
|
||||
goto out;
|
||||
|
@ -2068,7 +2072,7 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans)
|
|||
}
|
||||
|
||||
err:
|
||||
spin_unlock_bh(&trans_pcie->reg_lock);
|
||||
spin_unlock(&trans_pcie->reg_lock);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -2081,6 +2085,20 @@ out:
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
local_bh_disable();
|
||||
ret = __iwl_trans_pcie_grab_nic_access(trans);
|
||||
if (ret) {
|
||||
/* keep BHs disabled until iwl_trans_pcie_release_nic_access */
|
||||
return ret;
|
||||
}
|
||||
local_bh_enable();
|
||||
return false;
|
||||
}
|
||||
|
||||
static void iwl_trans_pcie_release_nic_access(struct iwl_trans *trans)
|
||||
{
|
||||
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
|
||||
|
|
|
@ -643,7 +643,7 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
|
|||
* returned. This needs to be done only on NICs that have
|
||||
* apmg_wake_up_wa set (see above.)
|
||||
*/
|
||||
if (!iwl_trans_grab_nic_access(trans))
|
||||
if (!_iwl_trans_pcie_grab_nic_access(trans))
|
||||
return -EIO;
|
||||
|
||||
/*
|
||||
|
@ -652,7 +652,7 @@ static int iwl_pcie_set_cmd_in_flight(struct iwl_trans *trans,
|
|||
* already true, so it's OK to unconditionally set it to true.
|
||||
*/
|
||||
trans_pcie->cmd_hold_nic_awake = true;
|
||||
spin_unlock_bh(&trans_pcie->reg_lock);
|
||||
spin_unlock(&trans_pcie->reg_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue