diff --git a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c index 069c3bad6f29..337e312c2f43 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/dbg.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/dbg.c @@ -103,7 +103,7 @@ static int iwl_dump_ini_prph_mac_iter_common(struct iwl_fw_runtime *fwrt, range->internal_base_addr = cpu_to_le32(addr); range->range_data_size = size; for (i = 0; i < le32_to_cpu(size); i += 4) - *val++ = cpu_to_le32(iwl_read_prph(fwrt->trans, addr + i)); + *val++ = cpu_to_le32(iwl_trans_read_prph(fwrt->trans, addr + i)); return sizeof(*range) + le32_to_cpu(range->range_data_size); } @@ -158,9 +158,6 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt, indirect_wr_addr += le32_to_cpu(offset); indirect_rd_addr += le32_to_cpu(offset); - if (!iwl_trans_grab_nic_access(fwrt->trans)) - return -EBUSY; - dphy_addr = (offset) ? WFPM_LMAC2_PS_CTL_RW : WFPM_LMAC1_PS_CTL_RW; dphy_state = iwl_read_umac_prph_no_grab(fwrt->trans, dphy_addr); @@ -194,7 +191,6 @@ static int iwl_dump_ini_prph_phy_iter_common(struct iwl_fw_runtime *fwrt, *val++ = cpu_to_le32(prph_val); } - iwl_trans_release_nic_access(fwrt->trans); return sizeof(*range) + le32_to_cpu(range->range_data_size); } @@ -283,8 +279,8 @@ static int iwl_dump_ini_dev_mem_iter(struct iwl_fw_runtime *fwrt, range->internal_base_addr = cpu_to_le32(addr); range->range_data_size = reg->dev_addr.size; - iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data, - le32_to_cpu(reg->dev_addr.size)); + iwl_trans_read_mem_bytes_no_grab(fwrt->trans, addr, range->data, + le32_to_cpu(reg->dev_addr.size)); if (reg->sub_type == IWL_FW_INI_REGION_DEVICE_MEMORY_SUBTYPE_HW_SMEM && fwrt->sanitize_ops && fwrt->sanitize_ops->frob_txf) @@ -368,8 +364,8 @@ static int iwl_dump_ini_mon_smem_iter(struct iwl_fw_runtime *fwrt, range->internal_base_addr = cpu_to_le32(addr); range->range_data_size = reg->internal_buffer.size; - iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data, - le32_to_cpu(reg->internal_buffer.size)); + iwl_trans_read_mem_bytes_no_grab(fwrt->trans, addr, range->data, + le32_to_cpu(reg->internal_buffer.size)); return sizeof(*range) + le32_to_cpu(range->range_data_size); } @@ -443,9 +439,6 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt, if (!iwl_ini_txf_iter(fwrt, reg_data, idx)) return -EIO; - if (!iwl_trans_grab_nic_access(fwrt->trans)) - return -EBUSY; - range->fifo_hdr.fifo_num = cpu_to_le32(iter->fifo); range->fifo_hdr.num_of_registers = cpu_to_le32(registers_num); range->range_data_size = cpu_to_le32(iter->fifo_size + registers_size); @@ -489,8 +482,6 @@ static int iwl_dump_ini_txf_iter(struct iwl_fw_runtime *fwrt, reg_dump, iter->fifo_size); out: - iwl_trans_release_nic_access(fwrt->trans); - return sizeof(*range) + le32_to_cpu(range->range_data_size); } @@ -511,9 +502,6 @@ iwl_dump_ini_prph_snps_dphyip_iter(struct iwl_fw_runtime *fwrt, range->internal_base_addr = cpu_to_le32(addr); range->range_data_size = reg->dev_addr.size; - if (!iwl_trans_grab_nic_access(fwrt->trans)) - return -EBUSY; - indirect_rd_wr_addr += le32_to_cpu(offset); dphy_addr = offset ? WFPM_LMAC2_PS_CTL_RW : WFPM_LMAC1_PS_CTL_RW; @@ -537,7 +525,6 @@ iwl_dump_ini_prph_snps_dphyip_iter(struct iwl_fw_runtime *fwrt, DPHYIP_INDIRECT_RD_SHIFT); } - iwl_trans_release_nic_access(fwrt->trans); return sizeof(*range) + le32_to_cpu(range->range_data_size); } @@ -626,9 +613,6 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, if (!rxf_data.size) return -EIO; - if (!iwl_trans_grab_nic_access(fwrt->trans)) - return -EBUSY; - range->fifo_hdr.fifo_num = cpu_to_le32(rxf_data.fifo_num); range->fifo_hdr.num_of_registers = cpu_to_le32(registers_num); range->range_data_size = cpu_to_le32(rxf_data.size + registers_size); @@ -668,8 +652,6 @@ static int iwl_dump_ini_rxf_iter(struct iwl_fw_runtime *fwrt, *data++ = cpu_to_le32(iwl_trans_read_prph(fwrt->trans, addr)); out: - iwl_trans_release_nic_access(fwrt->trans); - return sizeof(*range) + le32_to_cpu(range->range_data_size); } @@ -686,8 +668,8 @@ iwl_dump_ini_err_table_iter(struct iwl_fw_runtime *fwrt, range->internal_base_addr = cpu_to_le32(addr); range->range_data_size = err_table->size; - iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data, - le32_to_cpu(err_table->size)); + iwl_trans_read_mem_bytes_no_grab(fwrt->trans, addr, range->data, + le32_to_cpu(err_table->size)); return sizeof(*range) + le32_to_cpu(range->range_data_size); } @@ -707,8 +689,8 @@ iwl_dump_ini_special_mem_iter(struct iwl_fw_runtime *fwrt, range->internal_base_addr = cpu_to_le32(addr); range->range_data_size = special_mem->size; - iwl_trans_read_mem_bytes(fwrt->trans, addr, range->data, - le32_to_cpu(special_mem->size)); + iwl_trans_read_mem_bytes_no_grab(fwrt->trans, addr, range->data, + le32_to_cpu(special_mem->size)); return sizeof(*range) + le32_to_cpu(range->range_data_size); } @@ -724,9 +706,6 @@ iwl_dump_ini_dbgi_sram_iter(struct iwl_fw_runtime *fwrt, u32 prph_data; int i; - if (!iwl_trans_grab_nic_access(fwrt->trans)) - return -EBUSY; - range->range_data_size = reg->dev_addr.size; for (i = 0; i < (le32_to_cpu(reg->dev_addr.size) / 4); i++) { prph_data = @@ -734,13 +713,11 @@ iwl_dump_ini_dbgi_sram_iter(struct iwl_fw_runtime *fwrt, (i % 2) ? DBGI_SRAM_TARGET_ACCESS_RDATA_MSB : DBGI_SRAM_TARGET_ACCESS_RDATA_LSB); - if (iwl_trans_is_hw_error_value(prph_data)) { - iwl_trans_release_nic_access(fwrt->trans); + if (iwl_trans_is_hw_error_value(prph_data)) return -EBUSY; - } *val++ = cpu_to_le32(prph_data); } - iwl_trans_release_nic_access(fwrt->trans); + return sizeof(*range) + le32_to_cpu(range->range_data_size); } @@ -787,8 +764,8 @@ static int iwl_dump_ini_imr_iter(struct iwl_fw_runtime *fwrt, fwrt->trans->dbg.imr_data.imr_curr_addr = imr_curr_addr + size_to_dump; fwrt->trans->dbg.imr_data.imr2sram_remainbyte -= size_to_dump; - iwl_trans_read_mem_bytes(fwrt->trans, sram_addr, range->data, - size_to_dump); + iwl_trans_read_mem_bytes_no_grab(fwrt->trans, sram_addr, range->data, + size_to_dump); return sizeof(*range) + le32_to_cpu(range->range_data_size); } @@ -842,11 +819,6 @@ iwl_dump_ini_mon_fill_header(struct iwl_fw_runtime *fwrt, u32 alloc_id, struct iwl_fw_ini_monitor_dump *data, const struct iwl_fw_mon_regs *addrs) { - if (!iwl_trans_grab_nic_access(fwrt->trans)) { - IWL_ERR(fwrt, "Failed to get monitor header\n"); - return NULL; - } - data->write_ptr = iwl_get_mon_reg(fwrt, alloc_id, &addrs->write_ptr); if (fwrt->trans->mac_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) { @@ -859,8 +831,6 @@ iwl_dump_ini_mon_fill_header(struct iwl_fw_runtime *fwrt, u32 alloc_id, data->cur_frag = iwl_get_mon_reg(fwrt, alloc_id, &addrs->cur_frag); - iwl_trans_release_nic_access(fwrt->trans); - data->header.version = cpu_to_le32(IWL_INI_DUMP_VER); return data->data; @@ -1266,6 +1236,7 @@ iwl_dump_ini_imr_get_size(struct iwl_fw_runtime *fwrt, * the first range or NULL if failed to fill headers. * @fill_range: copies a given memory range into the dump. * Returns the size of the range or negative error value otherwise. + * @requires_nic_access: indicates to dump only if NIC access was acquired */ struct iwl_dump_ini_mem_ops { u32 (*get_num_of_ranges)(struct iwl_fw_runtime *fwrt, @@ -1278,6 +1249,7 @@ struct iwl_dump_ini_mem_ops { int (*fill_range)(struct iwl_fw_runtime *fwrt, struct iwl_dump_ini_region_data *reg_data, void *range, int idx); + bool requires_nic_access; }; struct iwl_fw_ini_dump_entry { @@ -1374,7 +1346,8 @@ static void iwl_dump_ini_mem_prep(struct iwl_fw_runtime *fwrt, } static u32 iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, - struct iwl_fw_ini_dump_entry *entry) + struct iwl_fw_ini_dump_entry *entry, + bool have_nic_access) { struct iwl_dump_ini_region_data *reg_data = &entry->reg_data; struct iwl_fw_ini_region_tlv *reg = (void *)reg_data->reg_tlv->data; @@ -1388,6 +1361,9 @@ static u32 iwl_dump_ini_mem(struct iwl_fw_runtime *fwrt, u32 free_size; u64 header_size; + if (!have_nic_access && ops->requires_nic_access) + goto out_err; + tlv = (void *)entry->data; header = (void *)tlv->data; @@ -1541,36 +1517,42 @@ static const struct iwl_dump_ini_mem_ops iwl_dump_ini_region_ops[] = { .get_size = iwl_dump_ini_mon_smem_get_size, .fill_mem_hdr = iwl_dump_ini_mon_smem_fill_header, .fill_range = iwl_dump_ini_mon_smem_iter, + .requires_nic_access = true, }, [IWL_FW_INI_REGION_DRAM_BUFFER] = { .get_num_of_ranges = iwl_dump_ini_mon_dram_ranges, .get_size = iwl_dump_ini_mon_dram_get_size, .fill_mem_hdr = iwl_dump_ini_mon_dram_fill_header, .fill_range = iwl_dump_ini_mon_dram_iter, + .requires_nic_access = true, }, [IWL_FW_INI_REGION_TXF] = { .get_num_of_ranges = iwl_dump_ini_txf_ranges, .get_size = iwl_dump_ini_txf_get_size, .fill_mem_hdr = iwl_dump_ini_mem_fill_header, .fill_range = iwl_dump_ini_txf_iter, + .requires_nic_access = true, }, [IWL_FW_INI_REGION_RXF] = { .get_num_of_ranges = iwl_dump_ini_single_range, .get_size = iwl_dump_ini_rxf_get_size, .fill_mem_hdr = iwl_dump_ini_mem_fill_header, .fill_range = iwl_dump_ini_rxf_iter, + .requires_nic_access = true, }, [IWL_FW_INI_REGION_LMAC_ERROR_TABLE] = { .get_num_of_ranges = iwl_dump_ini_single_range, .get_size = iwl_dump_ini_err_table_get_size, .fill_mem_hdr = iwl_dump_ini_err_table_fill_header, .fill_range = iwl_dump_ini_err_table_iter, + .requires_nic_access = true, }, [IWL_FW_INI_REGION_UMAC_ERROR_TABLE] = { .get_num_of_ranges = iwl_dump_ini_single_range, .get_size = iwl_dump_ini_err_table_get_size, .fill_mem_hdr = iwl_dump_ini_err_table_fill_header, .fill_range = iwl_dump_ini_err_table_iter, + .requires_nic_access = true, }, [IWL_FW_INI_REGION_RSP_OR_NOTIF] = { .get_num_of_ranges = iwl_dump_ini_single_range, @@ -1583,30 +1565,35 @@ static const struct iwl_dump_ini_mem_ops iwl_dump_ini_region_ops[] = { .get_size = iwl_dump_ini_mem_get_size, .fill_mem_hdr = iwl_dump_ini_mem_fill_header, .fill_range = iwl_dump_ini_dev_mem_iter, + .requires_nic_access = true, }, [IWL_FW_INI_REGION_PERIPHERY_MAC] = { .get_num_of_ranges = iwl_dump_ini_mem_ranges, .get_size = iwl_dump_ini_mem_get_size, .fill_mem_hdr = iwl_dump_ini_mem_fill_header, .fill_range = iwl_dump_ini_prph_mac_iter, + .requires_nic_access = true, }, [IWL_FW_INI_REGION_PERIPHERY_PHY] = { .get_num_of_ranges = iwl_dump_ini_mem_ranges, .get_size = iwl_dump_ini_mem_get_size, .fill_mem_hdr = iwl_dump_ini_mem_fill_header, .fill_range = iwl_dump_ini_prph_phy_iter, + .requires_nic_access = true, }, [IWL_FW_INI_REGION_PERIPHERY_MAC_RANGE] = { .get_num_of_ranges = iwl_dump_ini_mem_block_ranges, .get_size = iwl_dump_ini_mem_block_get_size, .fill_mem_hdr = iwl_dump_ini_mem_fill_header, .fill_range = iwl_dump_ini_prph_mac_block_iter, + .requires_nic_access = true, }, [IWL_FW_INI_REGION_PERIPHERY_PHY_RANGE] = { .get_num_of_ranges = iwl_dump_ini_mem_block_ranges, .get_size = iwl_dump_ini_mem_block_get_size, .fill_mem_hdr = iwl_dump_ini_mem_fill_header, .fill_range = iwl_dump_ini_prph_phy_block_iter, + .requires_nic_access = true, }, [IWL_FW_INI_REGION_PERIPHERY_AUX] = {}, [IWL_FW_INI_REGION_PAGING] = { @@ -1626,6 +1613,7 @@ static const struct iwl_dump_ini_mem_ops iwl_dump_ini_region_ops[] = { .get_size = iwl_dump_ini_imr_get_size, .fill_mem_hdr = iwl_dump_ini_imr_fill_header, .fill_range = iwl_dump_ini_imr_iter, + .requires_nic_access = true, }, [IWL_FW_INI_REGION_PCI_IOSF_CONFIG] = { .get_num_of_ranges = iwl_dump_ini_mem_ranges, @@ -1638,18 +1626,21 @@ static const struct iwl_dump_ini_mem_ops iwl_dump_ini_region_ops[] = { .get_size = iwl_dump_ini_special_mem_get_size, .fill_mem_hdr = iwl_dump_ini_special_mem_fill_header, .fill_range = iwl_dump_ini_special_mem_iter, + .requires_nic_access = true, }, [IWL_FW_INI_REGION_DBGI_SRAM] = { .get_num_of_ranges = iwl_dump_ini_mem_ranges, .get_size = iwl_dump_ini_mon_dbgi_get_size, .fill_mem_hdr = iwl_dump_ini_mon_dbgi_fill_header, .fill_range = iwl_dump_ini_dbgi_sram_iter, + .requires_nic_access = true, }, [IWL_FW_INI_REGION_PERIPHERY_SNPS_DPHYIP] = { .get_num_of_ranges = iwl_dump_ini_mem_ranges, .get_size = iwl_dump_ini_mem_get_size, .fill_mem_hdr = iwl_dump_ini_mem_fill_header, .fill_range = iwl_dump_ini_prph_snps_dphyip_iter, + .requires_nic_access = true, }, }; @@ -1733,8 +1724,11 @@ iwl_dump_ini_dump_entries(struct iwl_fw_runtime *fwrt, enum iwl_dump_ini_region_selector which) { struct iwl_fw_ini_dump_entry *entry, *tmp; + bool have_nic_access; u32 size = 0; + have_nic_access = iwl_trans_grab_nic_access(fwrt->trans); + list_for_each_entry_safe(entry, tmp, list, list) { u32 dp = entry->region_dump_policy; @@ -1751,9 +1745,15 @@ iwl_dump_ini_dump_entries(struct iwl_fw_runtime *fwrt, break; } - size += iwl_dump_ini_mem(fwrt, entry); + size += iwl_dump_ini_mem(fwrt, entry, have_nic_access); + + if (have_nic_access) + iwl_trans_resched_with_nic_access(fwrt->trans); } + if (have_nic_access) + iwl_trans_release_nic_access(fwrt->trans); + return size; } diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c index 0009488ca51b..73aae1125042 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.c @@ -558,6 +558,11 @@ bool iwl_trans_grab_nic_access(struct iwl_trans *trans) } IWL_EXPORT_SYMBOL(iwl_trans_grab_nic_access); +void iwl_trans_resched_with_nic_access(struct iwl_trans *trans) +{ + iwl_trans_pcie_resched_with_nic_access(trans); +} + void __releases(nic_access) iwl_trans_release_nic_access(struct iwl_trans *trans) { diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h index 3ae840e546e8..914864005704 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-trans.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-trans.h @@ -981,6 +981,17 @@ void iwl_trans_set_bits_mask(struct iwl_trans *trans, u32 reg, bool iwl_trans_grab_nic_access(struct iwl_trans *trans); +/** + * iwl_trans_resched_with_nic_access - reschedule while holding NIC access + * @trans: the transport pointer + * + * This can be called while holding NIC access, during periods where + * the lock itself isn't interesting, the NIC should remain active, + * but a lot of processing is happening and the CPU may need to be + * released. In practice, this is only during FW dump. + */ +void iwl_trans_resched_with_nic_access(struct iwl_trans *trans); + void __releases(nic_access) iwl_trans_release_nic_access(struct iwl_trans *trans); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h index abc0c831d1ca..d84c7c1efee1 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/internal.h @@ -1203,6 +1203,7 @@ void iwl_trans_pcie_set_bits_mask(struct iwl_trans *trans, u32 reg, int iwl_trans_pcie_read_config32(struct iwl_trans *trans, u32 ofs, u32 *val); bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans); +void iwl_trans_pcie_resched_with_nic_access(struct iwl_trans *trans); void __releases(nic_access_nobh) iwl_trans_pcie_release_nic_access(struct iwl_trans *trans); void iwl_pcie_alloc_fw_monitor(struct iwl_trans *trans, u8 max_power); diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c index 1c4ee76d8387..40fd5f3fdeb7 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/gen1_2/trans.c @@ -2424,7 +2424,7 @@ bool iwl_trans_pcie_grab_nic_access(struct iwl_trans *trans) return false; } -static void iwl_trans_pcie_resched_with_nic_access(struct iwl_trans *trans) +void iwl_trans_pcie_resched_with_nic_access(struct iwl_trans *trans) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);