Skip to content

Commit

Permalink
iwlwifi: pcie: don't enable BHs with IRQs disabled
Browse files Browse the repository at this point in the history
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 1ed08f6
("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
  • Loading branch information
Johannes Berg authored and Kalle Valo committed Apr 18, 2021
1 parent fa84df7 commit c544d89
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 5 deletions.
5 changes: 5 additions & 0 deletions drivers/net/wireless/intel/iwlwifi/pcie/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
******************************************************/
Expand Down
24 changes: 21 additions & 3 deletions drivers/net/wireless/intel/iwlwifi/pcie/trans.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand All @@ -2081,6 +2085,20 @@ static bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans)
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);
Expand Down
4 changes: 2 additions & 2 deletions drivers/net/wireless/intel/iwlwifi/pcie/tx.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

/*
Expand All @@ -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;
}
Expand Down

0 comments on commit c544d89

Please sign in to comment.