Commit 571836a0 authored by Mike Golant's avatar Mike Golant Committed by Luca Coelho
Browse files

iwlwifi: pcie: update sw error interrupt for BZ family

parent f06bc8af
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -605,6 +605,7 @@ enum msix_hw_int_causes {
	MSIX_HW_INT_CAUSES_REG_WAKEUP		= BIT(1),
	MSIX_HW_INT_CAUSES_REG_IML              = BIT(1),
	MSIX_HW_INT_CAUSES_REG_RESET_DONE	= BIT(2),
	MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ	= 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),
+7 −2
Original line number Diff line number Diff line
@@ -2149,6 +2149,7 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
	u32 inta_fh_msk = ~MSIX_FH_INT_CAUSES_DATA_QUEUE;
	u32 inta_fh, inta_hw;
	bool polling = false;
	bool sw_err;

	if (trans_pcie->shared_vec_mask & IWL_SHARED_IRQ_NON_RX)
		inta_fh_msk |= MSIX_FH_INT_CAUSES_Q0;
@@ -2221,9 +2222,13 @@ irqreturn_t iwl_pcie_irq_msix_handler(int irq, void *dev_id)
		wake_up(&trans_pcie->ucode_write_waitq);
	}

	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
		sw_err = inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ;
	else
		sw_err = inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR;

	/* Error detected by uCode */
	if ((inta_fh & MSIX_FH_INT_CAUSES_FH_ERR) ||
	    (inta_hw & MSIX_HW_INT_CAUSES_REG_SW_ERR)) {
	if ((inta_fh & MSIX_FH_INT_CAUSES_FH_ERR) || sw_err) {
		IWL_ERR(trans,
			"Microcode SW error detected. Restarting 0x%X.\n",
			inta_fh);
+34 −11
Original line number Diff line number Diff line
@@ -1062,7 +1062,7 @@ struct iwl_causes_list {
	u8 addr;
};

static struct iwl_causes_list causes_list[] = {
static const struct iwl_causes_list causes_list_common[] = {
	{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},
@@ -1073,30 +1073,50 @@ static struct iwl_causes_list causes_list[] = {
	{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_SW_ERR,		CSR_MSIX_HW_INT_MASK_AD, 0x29},
	{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 const struct iwl_causes_list causes_list_pre_bz[] = {
	{MSIX_HW_INT_CAUSES_REG_SW_ERR,		CSR_MSIX_HW_INT_MASK_AD, 0x29},
};

static const struct iwl_causes_list causes_list_bz[] = {
	{MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ,	CSR_MSIX_HW_INT_MASK_AD, 0x29},
};

static void iwl_pcie_map_list(struct iwl_trans *trans,
			      const struct iwl_causes_list *causes,
			      int arr_size, int val)
{
	int i;

	for (i = 0; i < arr_size; i++) {
		iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val);
		iwl_clear_bit(trans, causes[i].mask_reg,
			      causes[i].cause_num);
	}
}

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, arr_size = ARRAY_SIZE(causes_list);
	struct iwl_causes_list *causes = causes_list;

	/*
	 * 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 < arr_size; i++) {
		iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val);
		iwl_clear_bit(trans, causes[i].mask_reg,
			      causes[i].cause_num);
	}
	iwl_pcie_map_list(trans, causes_list_common,
			  ARRAY_SIZE(causes_list_common), val);
	if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
		iwl_pcie_map_list(trans, causes_list_bz,
				  ARRAY_SIZE(causes_list_bz), val);
	else
		iwl_pcie_map_list(trans, causes_list_pre_bz,
				  ARRAY_SIZE(causes_list_pre_bz), val);
}

static void iwl_pcie_map_rx_causes(struct iwl_trans *trans)
@@ -3384,6 +3404,9 @@ static void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)

	if (trans_pcie->msix_enabled) {
		inta_addr = CSR_MSIX_HW_INT_CAUSES_AD;
		if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
			sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ;
		else
			sw_err_bit = MSIX_HW_INT_CAUSES_REG_SW_ERR;
	} else {
		inta_addr = CSR_INT;