OSDN Git Service

Merge tag 'wireless-next-2022-03-11' of git://git.kernel.org/pub/scm/linux/kernel...
[uclinux-h8/linux.git] / drivers / net / wireless / intel / iwlwifi / pcie / trans.c
index ef14584..8be3c3c 100644 (file)
@@ -1,6 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
 /*
- * Copyright (C) 2007-2015, 2018-2020 Intel Corporation
+ * Copyright (C) 2007-2015, 2018-2022 Intel Corporation
  * Copyright (C) 2013-2015 Intel Mobile Communications GmbH
  * Copyright (C) 2016-2017 Intel Deutschland GmbH
  */
@@ -745,7 +745,7 @@ static int iwl_pcie_load_section(struct iwl_trans *trans, u8 section_num,
                        iwl_set_bits_prph(trans, LMPM_CHICK,
                                          LMPM_CHICK_EXTENDED_ADDR_SPACE);
 
-               memcpy(v_addr, (u8 *)section->data + offset, copy_size);
+               memcpy(v_addr, (const u8 *)section->data + offset, copy_size);
                ret = iwl_pcie_load_firmware_chunk(trans, dst_addr, p_addr,
                                                   copy_size);
 
@@ -1112,7 +1112,7 @@ static const struct iwl_causes_list causes_list_pre_bz[] = {
 };
 
 static const struct iwl_causes_list causes_list_bz[] = {
-       {MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ,      CSR_MSIX_HW_INT_MASK_AD, 0x29},
+       {MSIX_HW_INT_CAUSES_REG_SW_ERR_BZ,      CSR_MSIX_HW_INT_MASK_AD, 0x15},
 };
 
 static void iwl_pcie_map_list(struct iwl_trans *trans,
@@ -1948,6 +1948,7 @@ static void iwl_trans_pcie_configure(struct iwl_trans *trans,
        trans->txqs.cmd.wdg_timeout = trans_cfg->cmd_q_wdg_timeout;
        trans->txqs.page_offs = trans_cfg->cb_data_offs;
        trans->txqs.dev_cmd_offs = trans_cfg->cb_data_offs + sizeof(void *);
+       trans->txqs.queue_alloc_cmd_ver = trans_cfg->queue_alloc_cmd_ver;
 
        if (WARN_ON(trans_cfg->n_no_reclaim_cmds > MAX_NO_RECLAIM_CMDS))
                trans_pcie->n_no_reclaim_cmds = 0;
@@ -2863,7 +2864,7 @@ static ssize_t iwl_dbgfs_monitor_data_read(struct file *file,
 {
        struct iwl_trans *trans = file->private_data;
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
-       void *cpu_addr = (void *)trans->dbg.fw_mon.block, *curr_buf;
+       u8 *cpu_addr = (void *)trans->dbg.fw_mon.block, *curr_buf;
        struct cont_rec *data = &trans_pcie->fw_mon_data;
        u32 write_ptr_addr, wrap_cnt_addr, write_ptr, wrap_cnt;
        ssize_t size, bytes_copied = 0;
@@ -3468,7 +3469,8 @@ static void iwl_trans_pcie_sync_nmi(struct iwl_trans *trans)
        .d3_suspend = iwl_trans_pcie_d3_suspend,                        \
        .d3_resume = iwl_trans_pcie_d3_resume,                          \
        .interrupts = iwl_trans_pci_interrupts,                         \
-       .sync_nmi = iwl_trans_pcie_sync_nmi                             \
+       .sync_nmi = iwl_trans_pcie_sync_nmi,                            \
+       .imr_dma_data = iwl_trans_pcie_copy_imr                         \
 
 static const struct iwl_trans_ops trans_ops_pcie = {
        IWL_TRANS_COMMON_OPS,
@@ -3553,6 +3555,7 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
        mutex_init(&trans_pcie->mutex);
        init_waitqueue_head(&trans_pcie->ucode_write_waitq);
        init_waitqueue_head(&trans_pcie->fw_reset_waitq);
+       init_waitqueue_head(&trans_pcie->imr_waitq);
 
        trans_pcie->rba.alloc_wq = alloc_workqueue("rb_allocator",
                                                   WQ_HIGHPRI | WQ_UNBOUND, 1);
@@ -3681,3 +3684,41 @@ out_free_trans:
        iwl_trans_free(trans);
        return ERR_PTR(ret);
 }
+
+void iwl_trans_pcie_copy_imr_fh(struct iwl_trans *trans,
+                               u32 dst_addr, u64 src_addr, u32 byte_cnt)
+{
+       iwl_write_prph(trans, IMR_UREG_CHICK,
+                      iwl_read_prph(trans, IMR_UREG_CHICK) |
+                      IMR_UREG_CHICK_HALT_UMAC_PERMANENTLY_MSK);
+       iwl_write_prph(trans, IMR_TFH_SRV_DMA_CHNL0_SRAM_ADDR, dst_addr);
+       iwl_write_prph(trans, IMR_TFH_SRV_DMA_CHNL0_DRAM_ADDR_LSB,
+                      (u32)(src_addr & 0xFFFFFFFF));
+       iwl_write_prph(trans, IMR_TFH_SRV_DMA_CHNL0_DRAM_ADDR_MSB,
+                      iwl_get_dma_hi_addr(src_addr));
+       iwl_write_prph(trans, IMR_TFH_SRV_DMA_CHNL0_BC, byte_cnt);
+       iwl_write_prph(trans, IMR_TFH_SRV_DMA_CHNL0_CTRL,
+                      IMR_TFH_SRV_DMA_CHNL0_CTRL_D2S_IRQ_TARGET_POS |
+                      IMR_TFH_SRV_DMA_CHNL0_CTRL_D2S_DMA_EN_POS |
+                      IMR_TFH_SRV_DMA_CHNL0_CTRL_D2S_RS_MSK);
+}
+
+int iwl_trans_pcie_copy_imr(struct iwl_trans *trans,
+                           u32 dst_addr, u64 src_addr, u32 byte_cnt)
+{
+       struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+       int ret = -1;
+
+       trans_pcie->imr_status = IMR_D2S_REQUESTED;
+       iwl_trans_pcie_copy_imr_fh(trans, dst_addr, src_addr, byte_cnt);
+       ret = wait_event_timeout(trans_pcie->imr_waitq,
+                                trans_pcie->imr_status !=
+                                IMR_D2S_REQUESTED, 5 * HZ);
+       if (!ret || trans_pcie->imr_status == IMR_D2S_ERROR) {
+               IWL_ERR(trans, "Failed to copy IMR Memory chunk!\n");
+               iwl_trans_pcie_dump_regs(trans);
+               return -ETIMEDOUT;
+       }
+       trans_pcie->imr_status = IMR_D2S_IDLE;
+       return 0;
+}