]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
iwlwifi: pcie: don't enable BHs with IRQs disabled
authorJohannes Berg <johannes.berg@intel.com>
Thu, 15 Apr 2021 13:48:46 +0000 (16:48 +0300)
committerKalle Valo <kvalo@codeaurora.org>
Sun, 18 Apr 2021 06:37:38 +0000 (09:37 +0300)
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 1ed08f6fb5ae
("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
drivers/net/wireless/intel/iwlwifi/pcie/internal.h
drivers/net/wireless/intel/iwlwifi/pcie/trans.c
drivers/net/wireless/intel/iwlwifi/pcie/tx.c

index d9688c7bed07c365df07b9a99f75cb027ba73d50..76a512cd2e5c803136ec800a87d4e931a9b6c7b5 100644 (file)
@@ -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
 ******************************************************/
index 861dbc03d1837a8227fb8e8896ff33c2e78f7156..239bc177a3e5c7b9324a29519bc761b338d6de37 100644 (file)
@@ -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);
index 0346505351f5bd901f1ff3b71f45d18934f4aacd..4f6c187eed69cc96a716d17e6c61e39affbd582d 100644 (file)
@@ -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;
 }