Loading Documentation/devicetree/bindings/platform/msm/ipa.txt +4 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,10 @@ memory allocation over a PCIe bridge control. - qcom,entire-ipa-block-size: Complete size of the ipa block in which all registers, collected upon crash, reside. - qcom,secure-debug-check-action: Drives secure memory debug check. Three values allowed: 0 (use scm call), 1 (override scm call as though it returned true), and 2 (override scm call as though it returned false) Optional properties: -qcom,ipa-pipe-mem: Specifies the base physical address and the Loading arch/arm64/boot/dts/qcom/kona.dtsi +1 −0 Original line number Diff line number Diff line Loading @@ -2263,6 +2263,7 @@ qcom,register-collection-on-crash; qcom,testbus-collection-on-crash; qcom,non-tn-collection-on-crash; qcom,secure-debug-check-action = <0>; ipa_smmu_ap: ipa_smmu_ap { compatible = "qcom,ipa-smmu-ap-cb"; Loading drivers/platform/msm/ipa/ipa_v3/Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -16,4 +16,6 @@ obj-$(CONFIG_IPA3_MHI_PROXY) += ipa_mhi_proxy.o ipat-$(CONFIG_IPA3_REGDUMP) += dump/ipa_reg_dump.o ccflags-$(CONFIG_IPA3_REGDUMP) += -Idrivers/platform/msm/ipa/ipa_v3/dump ccflags-$(CONFIG_IPA3_REGDUMP_IPA_4_5) += -Idrivers/platform/msm/ipa/ipa_v3/dump/ipa4.5 drivers/platform/msm/ipa/ipa_v3/dump/ipa4.5/ipa_access_control.h 0 → 100644 +42 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019, The Linux Foundation. All rights reserved. */ #if !defined(_IPA_ACCESS_CONTROL_H_) #define _IPA_ACCESS_CONTROL_H_ #include "ipa_reg_dump.h" /* * The following is target specific. */ static struct reg_mem_access_map_t mem_access_map[] = { /*------------------------------------------------------------*/ /* Range Use when Use when */ /* Begin End SD_ENABLED SD_DISABLED */ /*------------------------------------------------------------*/ { 0x04000, 0x05000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0x1F000, 0x27000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0x05000, 0x0f000, { &io_matrix[AA_COMBO], &io_matrix[AN_COMBO] } }, { 0x0f000, 0x10000, { &io_matrix[NN_COMBO], &io_matrix[NN_COMBO] } }, { 0x13000, 0x17000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0x17000, 0x1b000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0x1b000, 0x1f000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0x10000, 0x11000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0x11000, 0x12000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0x12000, 0x13000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0x43000, 0x44000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0x44000, 0x45000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0x45000, 0x47000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0x40000, 0x42000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0x42000, 0x43000, { &io_matrix[AA_COMBO], &io_matrix[AN_COMBO] } }, { 0x50000, 0x60000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0x60000, 0x80000, { &io_matrix[AN_COMBO], &io_matrix[NN_COMBO] } }, { 0x80000, 0x81000, { &io_matrix[NN_COMBO], &io_matrix[NN_COMBO] } }, { 0x81000, 0x83000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0xa0000, 0xc0000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0xc0000, 0xc2000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0xc2000, 0xd0000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, }; #endif /* #if !defined(_IPA_ACCESS_CONTROL_H_) */ drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.c +89 −33 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ * Copyright (c) 2019, The Linux Foundation. All rights reserved. */ #include "ipa_reg_dump.h" #include "ipa_access_control.h" /* Total size required for test bus */ #define IPA_MEM_OVERLAY_SIZE 0x66000 Loading @@ -16,8 +17,6 @@ static struct regs_save_hierarchy_s ipa_reg_save; static unsigned int ipa_testbus_mem[IPA_MEM_OVERLAY_SIZE]; static u32 gsi_ver; /* * The following data structure contains a list of the registers * (whose data are to be copied) and the locations (within Loading Loading @@ -673,6 +672,55 @@ static void ipa_hal_save_regs_ipa_cmdq(void); static void ipa_hal_save_regs_rsrc_db(void); static void ipa_reg_save_anomaly_check(void); static struct reg_access_funcs_s *get_access_funcs(u32 addr) { u32 i, asub = ipa3_ctx->sd_state; for (i = 0; i < ARRAY_SIZE(mem_access_map); i++) { if (addr >= mem_access_map[i].addr_range_begin && addr <= mem_access_map[i].addr_range_end) { return mem_access_map[i].access[asub]; } } IPAERR("Unknown register offset(0x%08X). Using dflt access methods\n", addr); return &io_matrix[AA_COMBO]; } static u32 in_dword( u32 addr) { struct reg_access_funcs_s *io = get_access_funcs(addr); return io->read(ipa3_ctx->reg_collection_base + addr); } static u32 in_dword_masked( u32 addr, u32 mask) { struct reg_access_funcs_s *io = get_access_funcs(addr); u32 val; val = io->read(ipa3_ctx->reg_collection_base + addr); if (io->read == act_read) return val & mask; return val; } static void out_dword( u32 addr, u32 val) { struct reg_access_funcs_s *io = get_access_funcs(addr); io->write(ipa3_ctx->reg_collection_base + addr, val); } /* * FUNCTION: ipa_save_gsi_ver * Loading @@ -683,7 +731,7 @@ static void ipa_reg_save_anomaly_check(void); */ void ipa_save_gsi_ver(void) { gsi_ver = ipa_reg_save.gsi.fw_ver = IPA_READ_1xVECTOR_REG(IPA_GSI_TOP_GSI_INST_RAM_n, 0) & 0x0000FFFF; } Loading @@ -702,9 +750,8 @@ void ipa_save_registers(void) /* Fetch the number of registers configured to be saved */ u32 num_regs = ARRAY_SIZE(ipa_regs_to_save_array); u32 num_uc_per_regs = ARRAY_SIZE(ipa_uc_regs_to_save_array); union ipa_hwio_def_ipa_rsrc_mngr_db_cfg_u ipa_rsrc_mngr_db_cfg; union ipa_hwio_def_ipa_rsrc_mngr_db_rsrc_read_u ipa_rsrc_mngr_db_rsrc_read; union ipa_hwio_def_ipa_rsrc_mngr_db_cfg_u for_cfg; union ipa_hwio_def_ipa_rsrc_mngr_db_rsrc_read_u for_read; if (!ipa3_ctx->do_register_collection_on_crash) return; Loading @@ -718,9 +765,8 @@ void ipa_save_registers(void) num_regs -= (CONFIG_IPA3_REGDUMP_NUM_EXTRA_ENDP_REGS * IPA_REG_SAVE_NUM_EXTRA_ENDP_REGS); memset(&ipa_rsrc_mngr_db_cfg, 0, sizeof(ipa_rsrc_mngr_db_cfg)); memset(&ipa_rsrc_mngr_db_rsrc_read, 0, sizeof(ipa_rsrc_mngr_db_rsrc_read)); memset(&for_cfg, 0, sizeof(for_cfg)); memset(&for_read, 0, sizeof(for_read)); /* Now save all the configured registers */ for (i = 0; i < num_regs; i++) { Loading Loading @@ -867,38 +913,48 @@ void ipa_save_registers(void) * true, via dtsi, and the collection will be done. */ if (ipa3_ctx->do_non_tn_collection_on_crash) { u32 ofst = GEN_2xVECTOR_REG_OFST(IPA_CTX_ID_m_CTX_NUM_n, 0, 0); struct reg_access_funcs_s *io = get_access_funcs(ofst); /* * Copy Pkt context directly from IPA_CTX_ID register space * If the memory is accessible, copy pkt context directly from * IPA_CTX_ID register space */ if (io->read == act_read) { memcpy((void *)ipa_reg_save.pkt_ctntx, (void *)((u8 *) ipa3_ctx->reg_collection_base + GEN_2xVECTOR_REG_OFST( IPA_CTX_ID_m_CTX_NUM_n, 0, 0)), (const void *) (ipa3_ctx->reg_collection_base + ofst), sizeof(ipa_reg_save.pkt_ctntx)); ipa_rsrc_mngr_db_cfg.value = for_cfg.value = IPA_READ_SCALER_REG(IPA_RSRC_MNGR_DB_CFG); ipa_rsrc_mngr_db_cfg.def.rsrc_type_sel = 0; IPA_MASKED_WRITE_SCALER_REG(IPA_RSRC_MNGR_DB_CFG, ipa_rsrc_mngr_db_cfg.value); for_cfg.def.rsrc_type_sel = 0; IPA_MASKED_WRITE_SCALER_REG( IPA_RSRC_MNGR_DB_CFG, for_cfg.value); for (i = 0; i < IPA_HW_PKT_CTNTX_MAX; i++) { ipa_rsrc_mngr_db_cfg.def.rsrc_id_sel = i; IPA_MASKED_WRITE_SCALER_REG(IPA_RSRC_MNGR_DB_CFG, ipa_rsrc_mngr_db_cfg.value); for_cfg.def.rsrc_id_sel = i; IPA_MASKED_WRITE_SCALER_REG( IPA_RSRC_MNGR_DB_CFG, for_cfg.value); ipa_rsrc_mngr_db_rsrc_read.value = for_read.value = IPA_READ_SCALER_REG( IPA_RSRC_MNGR_DB_RSRC_READ); if (ipa_rsrc_mngr_db_rsrc_read.def.rsrc_occupied) { if (for_read.def.rsrc_occupied) { ipa_reg_save.pkt_ctntx_active[i] = true; ipa_reg_save.pkt_cntxt_state[i] = (enum ipa_hw_pkt_cntxt_state_e) ipa_reg_save.pkt_ctntx[i].state; } } } else { IPAERR("IPA_CTX_ID is not currently accessible\n"); } } ipa_reg_save_anomaly_check(); Loading Loading @@ -1348,7 +1404,7 @@ static void ipa_hal_save_regs_save_ipa_testbus(void) * * @return */ int ipa_reg_save_init(u8 value) int ipa_reg_save_init(u32 value) { u32 i, num_regs = ARRAY_SIZE(ipa_regs_to_save_array); Loading Loading
Documentation/devicetree/bindings/platform/msm/ipa.txt +4 −0 Original line number Diff line number Diff line Loading @@ -102,6 +102,10 @@ memory allocation over a PCIe bridge control. - qcom,entire-ipa-block-size: Complete size of the ipa block in which all registers, collected upon crash, reside. - qcom,secure-debug-check-action: Drives secure memory debug check. Three values allowed: 0 (use scm call), 1 (override scm call as though it returned true), and 2 (override scm call as though it returned false) Optional properties: -qcom,ipa-pipe-mem: Specifies the base physical address and the Loading
arch/arm64/boot/dts/qcom/kona.dtsi +1 −0 Original line number Diff line number Diff line Loading @@ -2263,6 +2263,7 @@ qcom,register-collection-on-crash; qcom,testbus-collection-on-crash; qcom,non-tn-collection-on-crash; qcom,secure-debug-check-action = <0>; ipa_smmu_ap: ipa_smmu_ap { compatible = "qcom,ipa-smmu-ap-cb"; Loading
drivers/platform/msm/ipa/ipa_v3/Makefile +2 −0 Original line number Diff line number Diff line Loading @@ -16,4 +16,6 @@ obj-$(CONFIG_IPA3_MHI_PROXY) += ipa_mhi_proxy.o ipat-$(CONFIG_IPA3_REGDUMP) += dump/ipa_reg_dump.o ccflags-$(CONFIG_IPA3_REGDUMP) += -Idrivers/platform/msm/ipa/ipa_v3/dump ccflags-$(CONFIG_IPA3_REGDUMP_IPA_4_5) += -Idrivers/platform/msm/ipa/ipa_v3/dump/ipa4.5
drivers/platform/msm/ipa/ipa_v3/dump/ipa4.5/ipa_access_control.h 0 → 100644 +42 −0 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019, The Linux Foundation. All rights reserved. */ #if !defined(_IPA_ACCESS_CONTROL_H_) #define _IPA_ACCESS_CONTROL_H_ #include "ipa_reg_dump.h" /* * The following is target specific. */ static struct reg_mem_access_map_t mem_access_map[] = { /*------------------------------------------------------------*/ /* Range Use when Use when */ /* Begin End SD_ENABLED SD_DISABLED */ /*------------------------------------------------------------*/ { 0x04000, 0x05000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0x1F000, 0x27000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0x05000, 0x0f000, { &io_matrix[AA_COMBO], &io_matrix[AN_COMBO] } }, { 0x0f000, 0x10000, { &io_matrix[NN_COMBO], &io_matrix[NN_COMBO] } }, { 0x13000, 0x17000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0x17000, 0x1b000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0x1b000, 0x1f000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0x10000, 0x11000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0x11000, 0x12000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0x12000, 0x13000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0x43000, 0x44000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0x44000, 0x45000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0x45000, 0x47000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0x40000, 0x42000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0x42000, 0x43000, { &io_matrix[AA_COMBO], &io_matrix[AN_COMBO] } }, { 0x50000, 0x60000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0x60000, 0x80000, { &io_matrix[AN_COMBO], &io_matrix[NN_COMBO] } }, { 0x80000, 0x81000, { &io_matrix[NN_COMBO], &io_matrix[NN_COMBO] } }, { 0x81000, 0x83000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0xa0000, 0xc0000, { &io_matrix[AN_COMBO], &io_matrix[AN_COMBO] } }, { 0xc0000, 0xc2000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, { 0xc2000, 0xd0000, { &io_matrix[AA_COMBO], &io_matrix[AA_COMBO] } }, }; #endif /* #if !defined(_IPA_ACCESS_CONTROL_H_) */
drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.c +89 −33 Original line number Diff line number Diff line Loading @@ -3,6 +3,7 @@ * Copyright (c) 2019, The Linux Foundation. All rights reserved. */ #include "ipa_reg_dump.h" #include "ipa_access_control.h" /* Total size required for test bus */ #define IPA_MEM_OVERLAY_SIZE 0x66000 Loading @@ -16,8 +17,6 @@ static struct regs_save_hierarchy_s ipa_reg_save; static unsigned int ipa_testbus_mem[IPA_MEM_OVERLAY_SIZE]; static u32 gsi_ver; /* * The following data structure contains a list of the registers * (whose data are to be copied) and the locations (within Loading Loading @@ -673,6 +672,55 @@ static void ipa_hal_save_regs_ipa_cmdq(void); static void ipa_hal_save_regs_rsrc_db(void); static void ipa_reg_save_anomaly_check(void); static struct reg_access_funcs_s *get_access_funcs(u32 addr) { u32 i, asub = ipa3_ctx->sd_state; for (i = 0; i < ARRAY_SIZE(mem_access_map); i++) { if (addr >= mem_access_map[i].addr_range_begin && addr <= mem_access_map[i].addr_range_end) { return mem_access_map[i].access[asub]; } } IPAERR("Unknown register offset(0x%08X). Using dflt access methods\n", addr); return &io_matrix[AA_COMBO]; } static u32 in_dword( u32 addr) { struct reg_access_funcs_s *io = get_access_funcs(addr); return io->read(ipa3_ctx->reg_collection_base + addr); } static u32 in_dword_masked( u32 addr, u32 mask) { struct reg_access_funcs_s *io = get_access_funcs(addr); u32 val; val = io->read(ipa3_ctx->reg_collection_base + addr); if (io->read == act_read) return val & mask; return val; } static void out_dword( u32 addr, u32 val) { struct reg_access_funcs_s *io = get_access_funcs(addr); io->write(ipa3_ctx->reg_collection_base + addr, val); } /* * FUNCTION: ipa_save_gsi_ver * Loading @@ -683,7 +731,7 @@ static void ipa_reg_save_anomaly_check(void); */ void ipa_save_gsi_ver(void) { gsi_ver = ipa_reg_save.gsi.fw_ver = IPA_READ_1xVECTOR_REG(IPA_GSI_TOP_GSI_INST_RAM_n, 0) & 0x0000FFFF; } Loading @@ -702,9 +750,8 @@ void ipa_save_registers(void) /* Fetch the number of registers configured to be saved */ u32 num_regs = ARRAY_SIZE(ipa_regs_to_save_array); u32 num_uc_per_regs = ARRAY_SIZE(ipa_uc_regs_to_save_array); union ipa_hwio_def_ipa_rsrc_mngr_db_cfg_u ipa_rsrc_mngr_db_cfg; union ipa_hwio_def_ipa_rsrc_mngr_db_rsrc_read_u ipa_rsrc_mngr_db_rsrc_read; union ipa_hwio_def_ipa_rsrc_mngr_db_cfg_u for_cfg; union ipa_hwio_def_ipa_rsrc_mngr_db_rsrc_read_u for_read; if (!ipa3_ctx->do_register_collection_on_crash) return; Loading @@ -718,9 +765,8 @@ void ipa_save_registers(void) num_regs -= (CONFIG_IPA3_REGDUMP_NUM_EXTRA_ENDP_REGS * IPA_REG_SAVE_NUM_EXTRA_ENDP_REGS); memset(&ipa_rsrc_mngr_db_cfg, 0, sizeof(ipa_rsrc_mngr_db_cfg)); memset(&ipa_rsrc_mngr_db_rsrc_read, 0, sizeof(ipa_rsrc_mngr_db_rsrc_read)); memset(&for_cfg, 0, sizeof(for_cfg)); memset(&for_read, 0, sizeof(for_read)); /* Now save all the configured registers */ for (i = 0; i < num_regs; i++) { Loading Loading @@ -867,38 +913,48 @@ void ipa_save_registers(void) * true, via dtsi, and the collection will be done. */ if (ipa3_ctx->do_non_tn_collection_on_crash) { u32 ofst = GEN_2xVECTOR_REG_OFST(IPA_CTX_ID_m_CTX_NUM_n, 0, 0); struct reg_access_funcs_s *io = get_access_funcs(ofst); /* * Copy Pkt context directly from IPA_CTX_ID register space * If the memory is accessible, copy pkt context directly from * IPA_CTX_ID register space */ if (io->read == act_read) { memcpy((void *)ipa_reg_save.pkt_ctntx, (void *)((u8 *) ipa3_ctx->reg_collection_base + GEN_2xVECTOR_REG_OFST( IPA_CTX_ID_m_CTX_NUM_n, 0, 0)), (const void *) (ipa3_ctx->reg_collection_base + ofst), sizeof(ipa_reg_save.pkt_ctntx)); ipa_rsrc_mngr_db_cfg.value = for_cfg.value = IPA_READ_SCALER_REG(IPA_RSRC_MNGR_DB_CFG); ipa_rsrc_mngr_db_cfg.def.rsrc_type_sel = 0; IPA_MASKED_WRITE_SCALER_REG(IPA_RSRC_MNGR_DB_CFG, ipa_rsrc_mngr_db_cfg.value); for_cfg.def.rsrc_type_sel = 0; IPA_MASKED_WRITE_SCALER_REG( IPA_RSRC_MNGR_DB_CFG, for_cfg.value); for (i = 0; i < IPA_HW_PKT_CTNTX_MAX; i++) { ipa_rsrc_mngr_db_cfg.def.rsrc_id_sel = i; IPA_MASKED_WRITE_SCALER_REG(IPA_RSRC_MNGR_DB_CFG, ipa_rsrc_mngr_db_cfg.value); for_cfg.def.rsrc_id_sel = i; IPA_MASKED_WRITE_SCALER_REG( IPA_RSRC_MNGR_DB_CFG, for_cfg.value); ipa_rsrc_mngr_db_rsrc_read.value = for_read.value = IPA_READ_SCALER_REG( IPA_RSRC_MNGR_DB_RSRC_READ); if (ipa_rsrc_mngr_db_rsrc_read.def.rsrc_occupied) { if (for_read.def.rsrc_occupied) { ipa_reg_save.pkt_ctntx_active[i] = true; ipa_reg_save.pkt_cntxt_state[i] = (enum ipa_hw_pkt_cntxt_state_e) ipa_reg_save.pkt_ctntx[i].state; } } } else { IPAERR("IPA_CTX_ID is not currently accessible\n"); } } ipa_reg_save_anomaly_check(); Loading Loading @@ -1348,7 +1404,7 @@ static void ipa_hal_save_regs_save_ipa_testbus(void) * * @return */ int ipa_reg_save_init(u8 value) int ipa_reg_save_init(u32 value) { u32 i, num_regs = ARRAY_SIZE(ipa_regs_to_save_array); Loading