iwlwifi: update gen3 interrupts - sw error and image response
authorGolan Ben Ami <golan.ben.ami@intel.com>
Thu, 1 Feb 2018 15:54:48 +0000 (17:54 +0200)
committerLuca Coelho <luciano.coelho@intel.com>
Thu, 26 Jul 2018 10:16:16 +0000 (13:16 +0300)
In 22560 devices the ROM sendis an interrupt to the host
once the IML reading is done.
Handle this interrupt, and indicate sw error in case the
value is fail.

Additionally, the cause for sw error in 22560 devices
have been changed, so update the cause list.

Signed-off-by: Golan Ben Ami <golan.ben.ami@intel.com>
Signed-off-by: Luca Coelho <luciano.coelho@intel.com>
drivers/net/wireless/intel/iwlwifi/iwl-context-info-gen3.h
drivers/net/wireless/intel/iwlwifi/iwl-csr.h
drivers/net/wireless/intel/iwlwifi/pcie/internal.h
drivers/net/wireless/intel/iwlwifi/pcie/rx.c
drivers/net/wireless/intel/iwlwifi/pcie/trans.c

index 8969dcc0d2db5f3d984823db4a00c3ed57af5cb0..ebea99189ca9f0bf342ab144c8c0b8b3d525aa68 100644 (file)
@@ -57,6 +57,7 @@
 #define CSR_CTXT_INFO_ADDR              0x118
 #define CSR_IML_DATA_ADDR               0x120
 #define CSR_IML_SIZE_ADDR               0x128
+#define CSR_IML_RESP_ADDR               0x12c
 
 /* Set bit for enabling automatic function boot */
 #define CSR_AUTO_FUNC_BOOT_ENA          BIT(1)
index 3ef71c22bcaafe7a0409ddb89866802898c309ff..9019de99f077f1f069bcb37d8cbc5e51fe110c65 100644 (file)
@@ -595,6 +595,8 @@ enum msix_fh_int_causes {
 enum msix_hw_int_causes {
        MSIX_HW_INT_CAUSES_REG_ALIVE            = BIT(0),
        MSIX_HW_INT_CAUSES_REG_WAKEUP           = BIT(1),
+       MSIX_HW_INT_CAUSES_REG_IPC              = BIT(1),
+       MSIX_HW_INT_CAUSES_REG_SW_ERR_V2        = BIT(5),
        MSIX_HW_INT_CAUSES_REG_CT_KILL          = BIT(6),
        MSIX_HW_INT_CAUSES_REG_RF_KILL          = BIT(7),
        MSIX_HW_INT_CAUSES_REG_PERIODIC         = BIT(8),
index e14d2003244f72d2cdf814eb2dc5a84404dd907a..76fd3ee617205ba827dca747c5914c13f6d52b85 100644 (file)
@@ -323,6 +323,18 @@ enum iwl_shared_irq_flags {
        IWL_SHARED_IRQ_FIRST_RSS        = BIT(1),
 };
 
+/**
+ * enum iwl_image_response_code - image response values
+ * @IWL_IMAGE_RESP_DEF: the default value of the register
+ * @IWL_IMAGE_RESP_SUCCESS: iml was read successfully
+ * @IWL_IMAGE_RESP_FAIL: iml reading failed
+ */
+enum iwl_image_response_code {
+       IWL_IMAGE_RESP_DEF              = 0,
+       IWL_IMAGE_RESP_SUCCESS          = 1,
+       IWL_IMAGE_RESP_FAIL             = 2,
+};
+
 /**
  * struct iwl_dram_data
  * @physical: page phy pointer
index 24ce2d6beb0fed4a083dd4a14569ba1962c35ef0..707242f1ff0b9f4318426ef3e663f7abad6bf7bb 100644 (file)
@@ -18,8 +18,7 @@
  * more details.
  *
  * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
+ * this program.
  *
  * The full GNU General Public License is included in this distribution in the
  * file called LICENSE.
@@ -37,6 +36,7 @@
 #include "iwl-io.h"
 #include "internal.h"
 #include "iwl-op-mode.h"
+#include "iwl-context-info-gen3.h"
 
 /******************************************************************************
  *
@@ -2009,7 +2009,8 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
 
        /* Error detected by uCode */
        if ((inta_fh & MSIX_FH_INT_CAUSES_FH_ERR) ||
-           (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR)) {
+           (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR) ||
+           (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR_V2)) {
                IWL_ERR(trans,
                        "Microcode SW error detected. Restarting 0x%X.\n",
                        inta_fh);
@@ -2034,8 +2035,18 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
                }
        }
 
-       /* uCode wakes up after power-down sleep */
-       if (inta_hw & MSIX_HW_INT_CAUSES_REG_WAKEUP) {
+       if (trans->cfg->device_family >= IWL_DEVICE_FAMILY_22560 &&
+           inta_hw & MSIX_HW_INT_CAUSES_REG_IPC) {
+               /* Reflect IML transfer status */
+               int res = iwl_read32(trans, CSR_IML_RESP_ADDR);
+
+               IWL_DEBUG_ISR(trans, "IML transfer status: %d\n", res);
+               if (res == IWL_IMAGE_RESP_FAIL) {
+                       isr_stats->sw++;
+                       iwl_pcie_irq_handle_error(trans);
+               }
+       } else if (inta_hw & MSIX_HW_INT_CAUSES_REG_WAKEUP) {
+               /* uCode wakes up after power-down sleep */
                IWL_DEBUG_ISR(trans, "Wakeup interrupt\n");
                iwl_pcie_rxq_check_wrptr(trans);
                iwl_pcie_txq_check_wrptrs(trans);
index bc14227c95acad6992fe80f6f6f83858654a1859..efde21580166b4c3d051d0a8cf8bde32b3720aa5 100644 (file)
@@ -1132,21 +1132,44 @@ static struct iwl_causes_list causes_list[] = {
        {MSIX_HW_INT_CAUSES_REG_HAP,            CSR_MSIX_HW_INT_MASK_AD, 0x2E},
 };
 
+static struct iwl_causes_list causes_list_v2[] = {
+       {MSIX_FH_INT_CAUSES_D2S_CH0_NUM,        CSR_MSIX_FH_INT_MASK_AD, 0},
+       {MSIX_FH_INT_CAUSES_D2S_CH1_NUM,        CSR_MSIX_FH_INT_MASK_AD, 0x1},
+       {MSIX_FH_INT_CAUSES_S2D,                CSR_MSIX_FH_INT_MASK_AD, 0x3},
+       {MSIX_FH_INT_CAUSES_FH_ERR,             CSR_MSIX_FH_INT_MASK_AD, 0x5},
+       {MSIX_HW_INT_CAUSES_REG_ALIVE,          CSR_MSIX_HW_INT_MASK_AD, 0x10},
+       {MSIX_HW_INT_CAUSES_REG_IPC,            CSR_MSIX_HW_INT_MASK_AD, 0x11},
+       {MSIX_HW_INT_CAUSES_REG_SW_ERR_V2,      CSR_MSIX_HW_INT_MASK_AD, 0x15},
+       {MSIX_HW_INT_CAUSES_REG_CT_KILL,        CSR_MSIX_HW_INT_MASK_AD, 0x16},
+       {MSIX_HW_INT_CAUSES_REG_RF_KILL,        CSR_MSIX_HW_INT_MASK_AD, 0x17},
+       {MSIX_HW_INT_CAUSES_REG_PERIODIC,       CSR_MSIX_HW_INT_MASK_AD, 0x18},
+       {MSIX_HW_INT_CAUSES_REG_SCD,            CSR_MSIX_HW_INT_MASK_AD, 0x2A},
+       {MSIX_HW_INT_CAUSES_REG_FH_TX,          CSR_MSIX_HW_INT_MASK_AD, 0x2B},
+       {MSIX_HW_INT_CAUSES_REG_HW_ERR,         CSR_MSIX_HW_INT_MASK_AD, 0x2D},
+       {MSIX_HW_INT_CAUSES_REG_HAP,            CSR_MSIX_HW_INT_MASK_AD, 0x2E},
+};
+
 static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans)
 {
        struct iwl_trans_pcie *trans_pcie =  IWL_TRANS_GET_PCIE_TRANS(trans);
        int val = trans_pcie->def_irq | MSIX_NON_AUTO_CLEAR_CAUSE;
-       int i;
+       int i, arr_size =
+               (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) ?
+               ARRAY_SIZE(causes_list) : ARRAY_SIZE(causes_list_v2);
 
        /*
         * Access all non RX causes and map them to the default irq.
         * In case we are missing at least one interrupt vector,
         * the first interrupt vector will serve non-RX and FBQ causes.
         */
-       for (i = 0; i < ARRAY_SIZE(causes_list); i++) {
-               iwl_write8(trans, CSR_MSIX_IVAR(causes_list[i].addr), val);
-               iwl_clear_bit(trans, causes_list[i].mask_reg,
-                             causes_list[i].cause_num);
+       for (i = 0; i < arr_size; i++) {
+               struct iwl_causes_list *causes =
+                       (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) ?
+                       causes_list : causes_list_v2;
+
+               iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val);
+               iwl_clear_bit(trans, causes[i].mask_reg,
+                             causes[i].cause_num);
        }
 }