diff options
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/pcie/trans.c')
-rw-r--r-- | drivers/net/wireless/intel/iwlwifi/pcie/trans.c | 105 |
1 files changed, 71 insertions, 34 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c index 375d8f25b886..e2579a0bcc25 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c @@ -8,7 +8,7 @@ * Copyright(c) 2007 - 2015 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * * This program is free software; you can redistribute it and/or modify * it under the terms of version 2 of the GNU General Public License as @@ -31,7 +31,7 @@ * Copyright(c) 2005 - 2015 Intel Corporation. All rights reserved. * Copyright(c) 2013 - 2015 Intel Mobile Communications GmbH * Copyright(c) 2016 - 2017 Intel Deutschland GmbH - * Copyright(c) 2018 Intel Corporation + * Copyright(c) 2018 - 2019 Intel Corporation * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -896,13 +896,13 @@ void iwl_pcie_apply_destination(struct iwl_trans *trans) if (!trans->num_blocks) return; - iwl_write_prph(trans, MON_BUFF_BASE_ADDR_VER2, - trans->fw_mon[0].physical >> - MON_BUFF_SHIFT_VER2); - iwl_write_prph(trans, MON_BUFF_END_ADDR_VER2, - (trans->fw_mon[0].physical + - trans->fw_mon[0].size - 256) >> - MON_BUFF_SHIFT_VER2); + iwl_write_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2, + trans->fw_mon[0].physical >> + MON_BUFF_SHIFT_VER2); + iwl_write_umac_prph(trans, MON_BUFF_END_ADDR_VER2, + (trans->fw_mon[0].physical + + trans->fw_mon[0].size - 256) >> + MON_BUFF_SHIFT_VER2); return; } @@ -1094,6 +1094,7 @@ static struct iwl_causes_list causes_list[] = { {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_WAKEUP, CSR_MSIX_HW_INT_MASK_AD, 0x11}, + {MSIX_HW_INT_CAUSES_REG_IML, CSR_MSIX_HW_INT_MASK_AD, 0x12}, {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}, @@ -1126,7 +1127,7 @@ 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 = - (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) ? + (trans->cfg->device_family != IWL_DEVICE_FAMILY_22560) ? ARRAY_SIZE(causes_list) : ARRAY_SIZE(causes_list_v2); /* @@ -1136,7 +1137,7 @@ static void iwl_pcie_map_non_rx_causes(struct iwl_trans *trans) */ for (i = 0; i < arr_size; i++) { struct iwl_causes_list *causes = - (trans->cfg->device_family < IWL_DEVICE_FAMILY_22560) ? + (trans->cfg->device_family != IWL_DEVICE_FAMILY_22560) ? causes_list : causes_list_v2; iwl_write8(trans, CSR_MSIX_IVAR(causes[i].addr), val); @@ -1182,8 +1183,8 @@ void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie) if (!trans_pcie->msix_enabled) { if (trans->cfg->mq_rx_supported && test_bit(STATUS_DEVICE_ENABLED, &trans->status)) - iwl_write_prph(trans, UREG_CHICK, - UREG_CHICK_MSI_ENABLE); + iwl_write_umac_prph(trans, UREG_CHICK, + UREG_CHICK_MSI_ENABLE); return; } /* @@ -1192,7 +1193,7 @@ void iwl_pcie_conf_msix_hw(struct iwl_trans_pcie *trans_pcie) * prph. */ if (test_bit(STATUS_DEVICE_ENABLED, &trans->status)) - iwl_write_prph(trans, UREG_CHICK, UREG_CHICK_MSIX_ENABLE); + iwl_write_umac_prph(trans, UREG_CHICK, UREG_CHICK_MSIX_ENABLE); /* * Each cause from the causes list above and the RX causes is @@ -1560,7 +1561,7 @@ static int iwl_trans_pcie_d3_resume(struct iwl_trans *trans, } IWL_DEBUG_POWER(trans, "WFPM value upon resume = 0x%08X\n", - iwl_read_prph(trans, WFPM_GP2)); + iwl_read_umac_prph(trans, WFPM_GP2)); val = iwl_read32(trans, CSR_RESET); if (val & CSR_RESET_REG_FLAG_NEVO_RESET) @@ -1709,15 +1710,18 @@ static int _iwl_trans_pcie_start_hw(struct iwl_trans *trans, bool low_power) return err; } - hpm = iwl_trans_read_prph(trans, HPM_DEBUG); + hpm = iwl_read_umac_prph_no_grab(trans, HPM_DEBUG); if (hpm != 0xa5a5a5a0 && (hpm & PERSISTENCE_BIT)) { - if (iwl_trans_read_prph(trans, PREG_PRPH_WPROT_0) & - PREG_WFPM_ACCESS) { + int wfpm_val = iwl_read_umac_prph_no_grab(trans, + PREG_PRPH_WPROT_0); + + if (wfpm_val & PREG_WFPM_ACCESS) { IWL_ERR(trans, "Error, can not clear persistence bit\n"); return -EPERM; } - iwl_trans_write_prph(trans, HPM_DEBUG, hpm & ~PERSISTENCE_BIT); + iwl_write_umac_prph_no_grab(trans, HPM_DEBUG, + hpm & ~PERSISTENCE_BIT); } iwl_trans_pcie_sw_reset(trans); @@ -2239,6 +2243,7 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx) struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); struct iwl_txq *txq; unsigned long now = jiffies; + bool overflow_tx; u8 wr_ptr; /* Make sure the NIC is still alive in the bus */ @@ -2250,18 +2255,37 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, int txq_idx) IWL_DEBUG_TX_QUEUES(trans, "Emptying queue %d...\n", txq_idx); txq = trans_pcie->txq[txq_idx]; + + spin_lock_bh(&txq->lock); + overflow_tx = txq->overflow_tx || + !skb_queue_empty(&txq->overflow_q); + spin_unlock_bh(&txq->lock); + wr_ptr = READ_ONCE(txq->write_ptr); - while (txq->read_ptr != READ_ONCE(txq->write_ptr) && + while ((txq->read_ptr != READ_ONCE(txq->write_ptr) || + overflow_tx) && !time_after(jiffies, now + msecs_to_jiffies(IWL_FLUSH_WAIT_MS))) { u8 write_ptr = READ_ONCE(txq->write_ptr); - if (WARN_ONCE(wr_ptr != write_ptr, + /* + * If write pointer moved during the wait, warn only + * if the TX came from op mode. In case TX came from + * trans layer (overflow TX) don't warn. + */ + if (WARN_ONCE(wr_ptr != write_ptr && !overflow_tx, "WR pointer moved while flushing %d -> %d\n", wr_ptr, write_ptr)) return -ETIMEDOUT; + wr_ptr = write_ptr; + usleep_range(1000, 2000); + + spin_lock_bh(&txq->lock); + overflow_tx = txq->overflow_tx || + !skb_queue_empty(&txq->overflow_q); + spin_unlock_bh(&txq->lock); } if (txq->read_ptr != txq->write_ptr) { @@ -2947,7 +2971,8 @@ static u32 iwl_trans_pcie_fh_regs_dump(struct iwl_trans *trans, i += sizeof(u32)) *val++ = cpu_to_le32(iwl_trans_pcie_read32(trans, i)); else - for (i = FH_MEM_LOWER_BOUND_GEN2; i < FH_MEM_UPPER_BOUND_GEN2; + for (i = iwl_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2); + i < iwl_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2); i += sizeof(u32)) *val++ = cpu_to_le32(iwl_trans_pcie_read_prph(trans, i)); @@ -2972,11 +2997,11 @@ iwl_trans_pci_dump_marbh_monitor(struct iwl_trans *trans, if (!iwl_trans_grab_nic_access(trans, &flags)) return 0; - iwl_write_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x1); + iwl_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x1); for (i = 0; i < buf_size_in_dwords; i++) - buffer[i] = iwl_read_prph_no_grab(trans, - MON_DMARB_RD_DATA_ADDR); - iwl_write_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x0); + buffer[i] = iwl_read_umac_prph_no_grab(trans, + MON_DMARB_RD_DATA_ADDR); + iwl_write_umac_prph_no_grab(trans, MON_DMARB_RD_CTL_ADDR, 0x0); iwl_trans_release_nic_access(trans, &flags); @@ -2991,9 +3016,9 @@ iwl_trans_pcie_dump_pointers(struct iwl_trans *trans, /* If there was a dest TLV - use the values from there */ if (trans->ini_valid) { - base = MON_BUFF_BASE_ADDR_VER2; - write_ptr = MON_BUFF_WRPTR_VER2; - wrap_cnt = MON_BUFF_CYCLE_CNT_VER2; + base = iwl_umac_prph(trans, MON_BUFF_BASE_ADDR_VER2); + write_ptr = iwl_umac_prph(trans, MON_BUFF_WRPTR_VER2); + wrap_cnt = iwl_umac_prph(trans, MON_BUFF_CYCLE_CNT_VER2); } else if (trans->dbg_dest_tlv) { write_ptr = le32_to_cpu(trans->dbg_dest_tlv->write_ptr_reg); wrap_cnt = le32_to_cpu(trans->dbg_dest_tlv->wrap_count); @@ -3155,8 +3180,8 @@ static struct iwl_trans_dump_data if (dump_mask & BIT(IWL_FW_ERROR_DUMP_FH_REGS)) { if (trans->cfg->gen2) len += sizeof(*data) + - (FH_MEM_UPPER_BOUND_GEN2 - - FH_MEM_LOWER_BOUND_GEN2); + (iwl_umac_prph(trans, FH_MEM_UPPER_BOUND_GEN2) - + iwl_umac_prph(trans, FH_MEM_LOWER_BOUND_GEN2)); else len += sizeof(*data) + (FH_MEM_UPPER_BOUND - @@ -3486,9 +3511,11 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, if (iwl_trans_grab_nic_access(trans, &flags)) { u32 hw_step; - hw_step = iwl_read_prph_no_grab(trans, WFPM_CTRL_REG); + hw_step = iwl_read_umac_prph_no_grab(trans, + WFPM_CTRL_REG); hw_step |= ENABLE_WFPM; - iwl_write_prph_no_grab(trans, WFPM_CTRL_REG, hw_step); + iwl_write_umac_prph_no_grab(trans, WFPM_CTRL_REG, + hw_step); hw_step = iwl_read_prph_no_grab(trans, AUX_MISC_REG); hw_step = (hw_step >> HW_STEP_LOCATION_BITS) & 0xF; if (hw_step == 0x3) @@ -3503,7 +3530,17 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev, #if IS_ENABLED(CONFIG_IWLMVM) trans->hw_rf_id = iwl_read32(trans, CSR_HW_RF_ID); - if (cfg == &iwl22560_2ax_cfg_hr) { + if (cfg == &iwlax210_2ax_cfg_so_hr_a0) { + if (trans->hw_rev == CSR_HW_REV_TYPE_TY) { + trans->cfg = &iwlax210_2ax_cfg_ty_gf_a0; + } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == + CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_JF)) { + trans->cfg = &iwlax210_2ax_cfg_so_jf_a0; + } else if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == + CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_GF)) { + trans->cfg = &iwlax210_2ax_cfg_so_gf_a0; + } + } else if (cfg == &iwl22560_2ax_cfg_hr) { if (CSR_HW_RF_ID_TYPE_CHIP_ID(trans->hw_rf_id) == CSR_HW_RF_ID_TYPE_CHIP_ID(CSR_HW_RF_ID_TYPE_HR)) { trans->cfg = &iwl22560_2ax_cfg_hr; |