summaryrefslogtreecommitdiff
path: root/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/intel/iwlwifi/pcie/trans.c')
-rw-r--r--drivers/net/wireless/intel/iwlwifi/pcie/trans.c69
1 files changed, 45 insertions, 24 deletions
diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
index b281850fbf7a..eacbbdbffb5e 100644
--- a/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
/*
- * Copyright (C) 2007-2015, 2018-2022 Intel Corporation
+ * Copyright (C) 2007-2015, 2018-2023 Intel Corporation
* Copyright (C) 2013-2015 Intel Mobile Communications GmbH
* Copyright (C) 2016-2017 Intel Deutschland GmbH
*/
@@ -131,13 +131,15 @@ static int iwl_trans_pcie_sw_reset(struct iwl_trans *trans,
bool retake_ownership)
{
/* Reset entire device - do controller reset (results in SHRD_HW_RST) */
- if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ)
+ if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_BZ) {
iwl_set_bit(trans, CSR_GP_CNTRL,
CSR_GP_CNTRL_REG_FLAG_SW_RESET);
- else
+ usleep_range(10000, 20000);
+ } else {
iwl_set_bit(trans, CSR_RESET,
CSR_RESET_REG_FLAG_SW_RESET);
- usleep_range(5000, 6000);
+ usleep_range(5000, 6000);
+ }
if (retake_ownership)
return iwl_pcie_prepare_card_hw(trans);
@@ -161,7 +163,7 @@ static void iwl_pcie_free_fw_monitor(struct iwl_trans *trans)
}
static void iwl_pcie_alloc_fw_monitor_block(struct iwl_trans *trans,
- u8 max_power, u8 min_power)
+ u8 max_power)
{
struct iwl_dram_data *fw_mon = &trans->dbg.fw_mon;
void *block = NULL;
@@ -169,10 +171,13 @@ static void iwl_pcie_alloc_fw_monitor_block(struct iwl_trans *trans,
u32 size = 0;
u8 power;
- if (fw_mon->size)
+ if (fw_mon->size) {
+ memset(fw_mon->block, 0, fw_mon->size);
return;
+ }
- for (power = max_power; power >= min_power; power--) {
+ /* need at least 2 KiB, so stop at 11 */
+ for (power = max_power; power >= 11; power--) {
size = BIT(power);
block = dma_alloc_coherent(trans->dev, size, &physical,
GFP_KERNEL | __GFP_NOWARN);
@@ -213,10 +218,7 @@ void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power)
max_power))
return;
- if (trans->dbg.fw_mon.size)
- return;
-
- iwl_pcie_alloc_fw_monitor_block(trans, max_power, 11);
+ iwl_pcie_alloc_fw_monitor_block(trans, max_power);
}
static u32 iwl_trans_pcie_read_shr(struct iwl_trans *trans, u32 reg)
@@ -475,7 +477,7 @@ void iwl_pcie_apm_stop_master(struct iwl_trans *trans)
CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
CSR_GP_CNTRL_REG_FLAG_BUS_MASTER_DISABLE_STATUS,
100);
- msleep(100);
+ usleep_range(10000, 20000);
} else {
iwl_set_bit(trans, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER);
@@ -1786,7 +1788,7 @@ static int iwl_trans_pcie_clear_persistence_bit(struct iwl_trans *trans)
}
hpm = iwl_read_umac_prph_no_grab(trans, HPM_DEBUG);
- if (hpm != 0xa5a5a5a0 && (hpm & PERSISTENCE_BIT)) {
+ if (!iwl_trans_is_hw_error_value(hpm) && (hpm & PERSISTENCE_BIT)) {
u32 wprot_val = iwl_read_umac_prph_no_grab(trans, wprot);
if (wprot_val & PREG_WFPM_ACCESS) {
@@ -1993,6 +1995,29 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
trans_pcie->fw_reset_handshake = trans_cfg->fw_reset_handshake;
}
+void iwl_trans_pcie_free_pnvm_dram_regions(struct iwl_dram_regions *dram_regions,
+ struct device *dev)
+{
+ u8 i;
+ struct iwl_dram_data *desc_dram = &dram_regions->prph_scratch_mem_desc;
+
+ /* free DRAM payloads */
+ for (i = 0; i < dram_regions->n_regions; i++) {
+ dma_free_coherent(dev, dram_regions->drams[i].size,
+ dram_regions->drams[i].block,
+ dram_regions->drams[i].physical);
+ }
+ dram_regions->n_regions = 0;
+
+ /* free DRAM addresses array */
+ if (desc_dram->block) {
+ dma_free_coherent(dev, desc_dram->size,
+ desc_dram->block,
+ desc_dram->physical);
+ }
+ memset(desc_dram, 0, sizeof(*desc_dram));
+}
+
void iwl_trans_pcie_free(struct iwl_trans *trans)
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
@@ -2025,16 +2050,10 @@ void iwl_trans_pcie_free(struct iwl_trans *trans)
iwl_pcie_free_fw_monitor(trans);
- if (trans_pcie->pnvm_dram.size)
- dma_free_coherent(trans->dev, trans_pcie->pnvm_dram.size,
- trans_pcie->pnvm_dram.block,
- trans_pcie->pnvm_dram.physical);
-
- if (trans_pcie->reduce_power_dram.size)
- dma_free_coherent(trans->dev,
- trans_pcie->reduce_power_dram.size,
- trans_pcie->reduce_power_dram.block,
- trans_pcie->reduce_power_dram.physical);
+ iwl_trans_pcie_free_pnvm_dram_regions(&trans_pcie->pnvm_data,
+ trans->dev);
+ iwl_trans_pcie_free_pnvm_dram_regions(&trans_pcie->reduced_tables_data,
+ trans->dev);
mutex_destroy(&trans_pcie->mutex);
iwl_trans_free(trans);
@@ -3534,7 +3553,9 @@ static const struct iwl_trans_ops trans_ops_pcie_gen2 = {
.txq_free = iwl_txq_dyn_free,
.wait_txq_empty = iwl_trans_pcie_wait_txq_empty,
.rxq_dma_data = iwl_trans_pcie_rxq_dma_data,
+ .load_pnvm = iwl_trans_pcie_ctx_info_gen3_load_pnvm,
.set_pnvm = iwl_trans_pcie_ctx_info_gen3_set_pnvm,
+ .load_reduce_power = iwl_trans_pcie_ctx_info_gen3_load_reduce_power,
.set_reduce_power = iwl_trans_pcie_ctx_info_gen3_set_reduce_power,
#ifdef CONFIG_IWLWIFI_DEBUGFS
.debugfs_cleanup = iwl_trans_pcie_debugfs_cleanup,
@@ -3576,7 +3597,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
init_waitqueue_head(&trans_pcie->imr_waitq);
trans_pcie->rba.alloc_wq = alloc_workqueue("rb_allocator",
- WQ_HIGHPRI | WQ_UNBOUND, 1);
+ WQ_HIGHPRI | WQ_UNBOUND, 0);
if (!trans_pcie->rba.alloc_wq) {
ret = -ENOMEM;
goto out_free_trans;