]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
iwlwifi: pcie: don't access periphery registers when not available
authorEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Tue, 13 Mar 2018 12:12:40 +0000 (14:12 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Wed, 19 Sep 2018 20:41:27 +0000 (22:41 +0200)
[ Upstream commit f98ad635c097c29339b7a7d6947173000485893d ]

The periphery can't be accessed before we set the
INIT_DONE bit which initializes the device.

A previous patch added a reconfiguration of the MSI-X
tables upon resume, but at that point in the flow,
INIT_DONE wasn't set. Since the reconfiguration of the
MSI-X tables require periphery access, it failed.

The difference between WoWLAN and without WoWLAN is that
in WoWLAN, iwl_trans_pcie_d3_suspend clears the INIT_DONE
without clearing the STATUS_DEVICE_ENABLED bit in the
software status. Because of that, the resume code thinks
that the device is enabled, but the INIT_DONE bit has been
cleared.

To fix this, don't reconfigure the MSI-X tables in case
WoWLAN is enabled. It will be done in
iwl_trans_pcie_d3_resume anyway.

Fixes: 52848a79b9d2 ("iwlwifi: pcie: reconfigure MSI-X HW on resume")
Signed-off-by: Emmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
Signed-off-by: Sasha Levin <alexander.levin@microsoft.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/net/wireless/intel/iwlwifi/pcie/drv.c
drivers/net/wireless/intel/iwlwifi/pcie/trans.c

index 8520523b91b40b5a0f6a00b0fe02c8ba33254aa4..d8d8443c1c933c962e4a241b9af96f55ee0bf15d 100644 (file)
@@ -1003,6 +1003,10 @@ static int iwl_pci_resume(struct device *device)
        if (!trans->op_mode)
                return 0;
 
+       /* In WOWLAN, let iwl_trans_pcie_d3_resume do the rest of the work */
+       if (test_bit(STATUS_DEVICE_ENABLED, &trans->status))
+               return 0;
+
        /* reconfigure the MSI-X mapping to get the correct IRQ for rfkill */
        iwl_pcie_conf_msix_hw(trans_pcie);
 
index 7229991ae70d4ff1d98ee9779b97ba60fd12087d..a2a98087eb41cad6e2d45b67fd600d4bfed9be3e 100644 (file)
@@ -1539,18 +1539,6 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
 
        iwl_pcie_enable_rx_wake(trans, true);
 
-       /*
-        * Reconfigure IVAR table in case of MSIX or reset ict table in
-        * MSI mode since HW reset erased it.
-        * Also enables interrupts - none will happen as
-        * the device doesn't know we're waking it up, only when
-        * the opmode actually tells it after this call.
-        */
-       iwl_pcie_conf_msix_hw(trans_pcie);
-       if (!trans_pcie->msix_enabled)
-               iwl_pcie_reset_ict(trans);
-       iwl_enable_interrupts(trans);
-
        iwl_set_bit(trans, CSR_GP_CNTRL,
                    BIT(trans->cfg->csr->flag_mac_access_req));
        iwl_set_bit(trans, CSR_GP_CNTRL,
@@ -1568,6 +1556,18 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans,
                return ret;
        }
 
+       /*
+        * Reconfigure IVAR table in case of MSIX or reset ict table in
+        * MSI mode since HW reset erased it.
+        * Also enables interrupts - none will happen as
+        * the device doesn't know we're waking it up, only when
+        * the opmode actually tells it after this call.
+        */
+       iwl_pcie_conf_msix_hw(trans_pcie);
+       if (!trans_pcie->msix_enabled)
+               iwl_pcie_reset_ict(trans);
+       iwl_enable_interrupts(trans);
+
        iwl_pcie_set_pwr(trans, false);
 
        if (!reset) {