* 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.
 #include "iwl-io.h"
 #include "internal.h"
 #include "iwl-op-mode.h"
+#include "iwl-context-info-gen3.h"
 
 /******************************************************************************
  *
 
        /* 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);
                }
        }
 
-       /* 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);
 
        {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);
        }
 }