Loading drivers/platform/msm/ipa/ipa.c +1 −1 Original line number Diff line number Diff line Loading @@ -1445,7 +1445,7 @@ static int ipa_init_sram(void) IPA_SRAM_SET(IPA_v2_RAM_MODEM_HDR_OFST, IPA_CANARY_VAL); IPA_SRAM_SET(IPA_v2_RAM_MODEM_OFST, IPA_CANARY_VAL); IPA_SRAM_SET(IPA_v2_RAM_APPS_V4_FLT_OFST, IPA_CANARY_VAL); IPA_SRAM_SET(IPA_v2_RAM_END_OFST, IPA_CANARY_VAL); IPA_SRAM_SET(IPA_v2_RAM_UC_INFO_OFST, IPA_CANARY_VAL); iounmap(ipa_sram_mmio); Loading drivers/platform/msm/ipa/ipa_client.c +218 −0 Original line number Diff line number Diff line Loading @@ -171,8 +171,11 @@ enum ipa_hw_2_cpu_responses { enum ipa_hw_2_cpu_events { IPA_HW_2_CPU_EVENT_ERROR = FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 1), IPA_HW_2_CPU_EVENT_LOG_INFO = FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 2), IPA_HW_2_CPU_EVENT_WDI_ERROR = FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 0), }; /** Loading Loading @@ -439,6 +442,216 @@ union IpaHwWdiErrorEventData_t { u32 raw32b; } __packed; /** * union IpaHwFeatureInfoData_t - parameters for stats/config blob * * @offset : Location of a feature within the EventInfoData * @size : Size of the feature */ union IpaHwFeatureInfoData_t { struct IpaHwFeatureInfoParams_t { u32 offset:16; u32 size:16; } __packed params; u32 raw32b; } __packed; /** * struct IpaHwEventInfoData_t - Structure holding the parameters for * statistics and config info * * @baseAddrOffset : Base Address Offset of the statistics or config * structure from IPA_WRAPPER_BASE * @IpaHwFeatureInfoData_t : Location and size of each feature within * the statistics or config structure * * @note Information about each feature in the featureInfo[] * array is populated at predefined indices per the IPA_HW_FEATURES * enum definition */ struct IpaHwEventInfoData_t { u32 baseAddrOffset; union IpaHwFeatureInfoData_t featureInfo[IPA_HW_NUM_FEATURES]; } __packed; /** * struct IpaHwEventLogInfoData_t - Structure holding the parameters for * IPA_HW_2_CPU_EVENT_LOG_INFO Event * * @featureMask : Mask indicating the features enabled in HW. * Refer IPA_HW_FEATURE_MASK * @circBuffBaseAddrOffset : Base Address Offset of the Circular Event * Log Buffer structure * @statsInfo : Statistics related information * @configInfo : Configuration related information * * @note The offset location of this structure from IPA_WRAPPER_BASE * will be provided as Event Params for the IPA_HW_2_CPU_EVENT_LOG_INFO * Event */ struct IpaHwEventLogInfoData_t { u32 featureMask; u32 circBuffBaseAddrOffset; struct IpaHwEventInfoData_t statsInfo; struct IpaHwEventInfoData_t configInfo; } __packed; /** * ipa_get_wdi_stats() - Query WDI statistics from uc * @stats: [inout] stats blob from client populated by driver * * Returns: 0 on success, negative on failure * * @note Cannot be called from atomic context * */ int ipa_get_wdi_stats(struct IpaHwStatsWDIInfoData_t *stats) { #define TX_STATS(y) stats->tx_ch_stats.y = \ ipa_ctx->wdi.uc_wdi_stats_mmio->tx_ch_stats.y #define RX_STATS(y) stats->rx_ch_stats.y = \ ipa_ctx->wdi.uc_wdi_stats_mmio->rx_ch_stats.y if (!stats || !ipa_ctx->wdi.uc_top_mmio || !ipa_ctx->wdi.uc_wdi_stats_mmio) { IPAERR("bad parms stats=%p uc_top=%p wdi_stats=%p\n", stats, ipa_ctx->wdi.uc_top_mmio, ipa_ctx->wdi.uc_wdi_stats_mmio); return -EINVAL; } ipa_inc_client_enable_clks(); TX_STATS(num_pkts_processed); TX_STATS(copy_engine_doorbell_value); TX_STATS(num_db_fired); TX_STATS(tx_comp_ring_stats.ringFull); TX_STATS(tx_comp_ring_stats.ringEmpty); TX_STATS(tx_comp_ring_stats.ringUsageHigh); TX_STATS(tx_comp_ring_stats.ringUsageLow); TX_STATS(bam_stats.bamFifoFull); TX_STATS(bam_stats.bamFifoEmpty); TX_STATS(bam_stats.bamFifoUsageHigh); TX_STATS(bam_stats.bamFifoUsageLow); TX_STATS(num_db); TX_STATS(num_unexpected_db); TX_STATS(num_bam_int_handled); TX_STATS(num_bam_int_in_non_runnning_state); TX_STATS(num_qmb_int_handled); RX_STATS(max_outstanding_pkts); RX_STATS(num_pkts_processed); RX_STATS(rx_ring_rp_value); RX_STATS(rx_ind_ring_stats.ringFull); RX_STATS(rx_ind_ring_stats.ringEmpty); RX_STATS(rx_ind_ring_stats.ringUsageHigh); RX_STATS(rx_ind_ring_stats.ringUsageLow); RX_STATS(bam_stats.bamFifoFull); RX_STATS(bam_stats.bamFifoEmpty); RX_STATS(bam_stats.bamFifoUsageHigh); RX_STATS(bam_stats.bamFifoUsageLow); RX_STATS(num_bam_int_handled); RX_STATS(num_db); RX_STATS(num_unexpected_db); RX_STATS(reserved1); RX_STATS(reserved2); ipa_dec_client_disable_clks(); return 0; } EXPORT_SYMBOL(ipa_get_wdi_stats); /* TODO: add support for IPA_HW_v2_5 */ static void ipa_log_evt_hdlr(void) { if (!ipa_ctx->wdi.uc_top_ofst) { ipa_ctx->wdi.uc_top_ofst = ipa_ctx->wdi.ipa_sram_mmio->common.eventParams; if (ipa_ctx->wdi.uc_top_ofst + sizeof(struct IpaHwEventLogInfoData_t) >= ipa_ctx->ctrl->ipa_reg_base_ofst + IPA_SRAM_DIRECT_ACCESS_N_OFST_v2_0(0) + ipa_ctx->smem_sz) { IPAERR("uc_top 0x%x outside SRAM\n", ipa_ctx->wdi.uc_top_ofst); goto bad_uc_top_ofst; } ipa_ctx->wdi.uc_top_mmio = ioremap(ipa_ctx->ipa_wrapper_base + ipa_ctx->wdi.uc_top_ofst, sizeof(struct IpaHwEventLogInfoData_t)); if (!ipa_ctx->wdi.uc_top_mmio) { IPAERR("fail to ioremap uc top\n"); goto bad_uc_top_ofst; } if ((ipa_ctx->wdi.uc_top_mmio->featureMask & (1 << IPA_HW_FEATURE_WDI)) == 0) { IPAERR("WDI feature missing 0x%x\n", ipa_ctx->wdi.uc_top_mmio->featureMask); goto feat_miss; } if (ipa_ctx->wdi.uc_top_mmio->statsInfo. featureInfo[IPA_HW_FEATURE_WDI].params.size != sizeof(struct IpaHwStatsWDIInfoData_t)) { IPAERR("wdi stats size invalid exp=%zu is=%u\n", sizeof(struct IpaHwStatsWDIInfoData_t), ipa_ctx->wdi.uc_top_mmio->statsInfo. featureInfo[IPA_HW_FEATURE_WDI]. params.size); goto feat_miss; } ipa_ctx->wdi.uc_wdi_stats_ofst = ipa_ctx->wdi. uc_top_mmio->statsInfo.baseAddrOffset + ipa_ctx->wdi.uc_top_mmio->statsInfo. featureInfo[IPA_HW_FEATURE_WDI].params.offset; IPAERR("WDI stats ofst=0x%x\n", ipa_ctx->wdi.uc_wdi_stats_ofst); if (ipa_ctx->wdi.uc_wdi_stats_ofst + sizeof(struct IpaHwStatsWDIInfoData_t) >= ipa_ctx->ctrl->ipa_reg_base_ofst + IPA_SRAM_DIRECT_ACCESS_N_OFST_v2_0(0) + ipa_ctx->smem_sz) { IPAERR("uc_wdi_stats 0x%x outside SRAM\n", ipa_ctx->wdi.uc_wdi_stats_ofst); goto bad_stats_ofst; } ipa_ctx->wdi.uc_wdi_stats_mmio = ioremap(ipa_ctx->ipa_wrapper_base + ipa_ctx->wdi.uc_wdi_stats_ofst, sizeof(struct IpaHwStatsWDIInfoData_t)); if (!ipa_ctx->wdi.uc_wdi_stats_mmio) { IPAERR("fail to ioremap uc wdi stats\n"); goto bad_stats_ofst; } } else { if (ipa_ctx->wdi.ipa_sram_mmio->common.eventParams != ipa_ctx->wdi.uc_top_ofst) { IPAERR("uc top ofst changed new=%u cur=%u\n", ipa_ctx->wdi.uc_top_mmio->statsInfo. featureInfo[IPA_HW_FEATURE_WDI].params.size, ipa_ctx->wdi.uc_top_ofst); } } return; bad_stats_ofst: ipa_ctx->wdi.uc_wdi_stats_ofst = 0; feat_miss: iounmap(ipa_ctx->wdi.uc_top_mmio); bad_uc_top_ofst: ipa_ctx->wdi.uc_top_ofst = 0; return; } static void ipa_wdi_evt_handler(enum ipa_irq_type interrupt, void *private_data, void *interrupt_data) Loading Loading @@ -467,6 +680,11 @@ static void ipa_wdi_evt_handler(enum ipa_irq_type interrupt, ipa_ctx->wdi.ipa_sram_mmio->wdi_tx_ch_0_state, ipa_ctx->wdi.ipa_sram_mmio->wdi_rx_ch_0_state); } else if (ipa_ctx->wdi.ipa_sram_mmio->common.eventOp == IPA_HW_2_CPU_EVENT_LOG_INFO) { IPAERR("WDI evt log info ofst=0x%x\n", ipa_ctx->wdi.ipa_sram_mmio->common.eventParams); ipa_log_evt_hdlr(); } else { IPAERR("unsupported WDI evt opcode=%u\n", ipa_ctx->wdi.ipa_sram_mmio->common.eventOp); Loading drivers/platform/msm/ipa/ipa_debugfs.c +97 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ static struct dentry *dfile_ip4_flt; static struct dentry *dfile_ip6_flt; static struct dentry *dfile_stats; static struct dentry *dfile_wstats; static struct dentry *dfile_wdi_stats; static struct dentry *dfile_dbg_cnt; static struct dentry *dfile_msg; static struct dentry *dfile_ip4_nat; Loading Loading @@ -933,6 +934,91 @@ nxt_clnt_cons: return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt); } static ssize_t ipa_read_wdi(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct IpaHwStatsWDIInfoData_t stats; int nbytes; int cnt = 0; if (!ipa_get_wdi_stats(&stats)) { nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN, "TX num_pkts_processed=%u\n" "TX copy_engine_doorbell_value=%u\n" "TX num_db_fired=%u\n" "TX ringFull=%u\n" "TX ringEmpty=%u\n" "TX ringUsageHigh=%u\n" "TX ringUsageLow=%u\n" "TX bamFifoFull=%u\n" "TX bamFifoEmpty=%u\n" "TX bamFifoUsageHigh=%u\n" "TX bamFifoUsageLow=%u\n" "TX num_db=%u\n" "TX num_unexpected_db=%u\n" "TX num_bam_int_handled=%u\n" "TX num_bam_int_in_non_runnning_state=%u\n" "TX num_qmb_int_handled=%u\n", stats.tx_ch_stats.num_pkts_processed, stats.tx_ch_stats.copy_engine_doorbell_value, stats.tx_ch_stats.num_db_fired, stats.tx_ch_stats.tx_comp_ring_stats.ringFull, stats.tx_ch_stats.tx_comp_ring_stats.ringEmpty, stats.tx_ch_stats.tx_comp_ring_stats.ringUsageHigh, stats.tx_ch_stats.tx_comp_ring_stats.ringUsageLow, stats.tx_ch_stats.bam_stats.bamFifoFull, stats.tx_ch_stats.bam_stats.bamFifoEmpty, stats.tx_ch_stats.bam_stats.bamFifoUsageHigh, stats.tx_ch_stats.bam_stats.bamFifoUsageLow, stats.tx_ch_stats.num_db, stats.tx_ch_stats.num_unexpected_db, stats.tx_ch_stats.num_bam_int_handled, stats.tx_ch_stats.num_bam_int_in_non_runnning_state, stats.tx_ch_stats.num_qmb_int_handled); cnt += nbytes; nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN - cnt, "RX max_outstanding_pkts=%u\n" "RX num_pkts_processed=%u\n" "RX rx_ring_rp_value=%u\n" "RX ringFull=%u\n" "RX ringEmpty=%u\n" "RX ringUsageHigh=%u\n" "RX ringUsageLow=%u\n" "RX bamFifoFull=%u\n" "RX bamFifoEmpty=%u\n" "RX bamFifoUsageHigh=%u\n" "RX bamFifoUsageLow=%u\n" "RX num_bam_int_handled=%u\n" "RX num_db=%u\n" "RX num_unexpected_db=%u\n" "RX reserved1=%u\n" "RX reserved2=%u\n", stats.rx_ch_stats.max_outstanding_pkts, stats.rx_ch_stats.num_pkts_processed, stats.rx_ch_stats.rx_ring_rp_value, stats.rx_ch_stats.rx_ind_ring_stats.ringFull, stats.rx_ch_stats.rx_ind_ring_stats.ringEmpty, stats.rx_ch_stats.rx_ind_ring_stats.ringUsageHigh, stats.rx_ch_stats.rx_ind_ring_stats.ringUsageLow, stats.rx_ch_stats.bam_stats.bamFifoFull, stats.rx_ch_stats.bam_stats.bamFifoEmpty, stats.rx_ch_stats.bam_stats.bamFifoUsageHigh, stats.rx_ch_stats.bam_stats.bamFifoUsageLow, stats.rx_ch_stats.num_bam_int_handled, stats.rx_ch_stats.num_db, stats.rx_ch_stats.num_unexpected_db, stats.rx_ch_stats.reserved1, stats.rx_ch_stats.reserved2); cnt += nbytes; } else { nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN, "Fail to read WDI stats\n"); cnt += nbytes; } return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt); } void _ipa_write_dbg_cnt_v1(int option) { if (option == 1) Loading Loading @@ -1249,6 +1335,10 @@ const struct file_operations ipa_wstats_ops = { .read = ipa_read_wstats, }; const struct file_operations ipa_wdi_ops = { .read = ipa_read_wdi, }; const struct file_operations ipa_msg_ops = { .read = ipa_read_msg, }; Loading Loading @@ -1358,6 +1448,13 @@ void ipa_debugfs_init(void) goto fail; } dfile_wdi_stats = debugfs_create_file("wdi", read_only_mode, dent, 0, &ipa_wdi_ops); if (!dfile_wdi_stats || IS_ERR(dfile_wdi_stats)) { IPAERR("fail to create file for debug_fs wdi stats\n"); goto fail; } dfile_dbg_cnt = debugfs_create_file("dbg_cnt", read_write_mode, dent, 0, &ipa_dbg_cnt_ops); if (!dfile_dbg_cnt || IS_ERR(dfile_dbg_cnt)) { Loading drivers/platform/msm/ipa/ipa_i.h +4 −0 Original line number Diff line number Diff line Loading @@ -645,6 +645,10 @@ struct ipa_wdi_ctx { u32 pending_cmd; u32 last_resp; struct dma_pool *dma_pool; u32 uc_top_ofst; struct IpaHwEventLogInfoData_t *uc_top_mmio; u32 uc_wdi_stats_ofst; struct IpaHwStatsWDIInfoData_t *uc_wdi_stats_mmio; }; /** Loading drivers/platform/msm/ipa/ipa_ram_mmap.h +5 −2 Original line number Diff line number Diff line Loading @@ -80,9 +80,12 @@ #define IPA_v2_RAM_APPS_V4_FLT_SIZE 2176 #define IPA_v2_RAM_APPS_V6_FLT_OFST (IPA_v2_RAM_APPS_V4_FLT_OFST + \ IPA_v2_RAM_APPS_V4_FLT_SIZE) #define IPA_v2_RAM_APPS_V6_FLT_SIZE 1664 #define IPA_v2_RAM_END_OFST (IPA_v2_RAM_APPS_V6_FLT_OFST + \ #define IPA_v2_RAM_APPS_V6_FLT_SIZE 1372 #define IPA_v2_RAM_UC_INFO_OFST (IPA_v2_RAM_APPS_V6_FLT_OFST + \ IPA_v2_RAM_APPS_V6_FLT_SIZE + IPA_CANARY_SIZE) #define IPA_v2_RAM_UC_INFO_SIZE 292 #define IPA_v2_RAM_END_OFST (IPA_v2_RAM_UC_INFO_OFST + \ IPA_v2_RAM_UC_INFO_SIZE) #define IPA_v2_RAM_APPS_V4_RT_OFST IPA_v2_RAM_END_OFST #define IPA_v2_RAM_APPS_V4_RT_SIZE 0 #define IPA_v2_RAM_APPS_V6_RT_OFST IPA_v2_RAM_END_OFST Loading Loading
drivers/platform/msm/ipa/ipa.c +1 −1 Original line number Diff line number Diff line Loading @@ -1445,7 +1445,7 @@ static int ipa_init_sram(void) IPA_SRAM_SET(IPA_v2_RAM_MODEM_HDR_OFST, IPA_CANARY_VAL); IPA_SRAM_SET(IPA_v2_RAM_MODEM_OFST, IPA_CANARY_VAL); IPA_SRAM_SET(IPA_v2_RAM_APPS_V4_FLT_OFST, IPA_CANARY_VAL); IPA_SRAM_SET(IPA_v2_RAM_END_OFST, IPA_CANARY_VAL); IPA_SRAM_SET(IPA_v2_RAM_UC_INFO_OFST, IPA_CANARY_VAL); iounmap(ipa_sram_mmio); Loading
drivers/platform/msm/ipa/ipa_client.c +218 −0 Original line number Diff line number Diff line Loading @@ -171,8 +171,11 @@ enum ipa_hw_2_cpu_responses { enum ipa_hw_2_cpu_events { IPA_HW_2_CPU_EVENT_ERROR = FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 1), IPA_HW_2_CPU_EVENT_LOG_INFO = FEATURE_ENUM_VAL(IPA_HW_FEATURE_COMMON, 2), IPA_HW_2_CPU_EVENT_WDI_ERROR = FEATURE_ENUM_VAL(IPA_HW_FEATURE_WDI, 0), }; /** Loading Loading @@ -439,6 +442,216 @@ union IpaHwWdiErrorEventData_t { u32 raw32b; } __packed; /** * union IpaHwFeatureInfoData_t - parameters for stats/config blob * * @offset : Location of a feature within the EventInfoData * @size : Size of the feature */ union IpaHwFeatureInfoData_t { struct IpaHwFeatureInfoParams_t { u32 offset:16; u32 size:16; } __packed params; u32 raw32b; } __packed; /** * struct IpaHwEventInfoData_t - Structure holding the parameters for * statistics and config info * * @baseAddrOffset : Base Address Offset of the statistics or config * structure from IPA_WRAPPER_BASE * @IpaHwFeatureInfoData_t : Location and size of each feature within * the statistics or config structure * * @note Information about each feature in the featureInfo[] * array is populated at predefined indices per the IPA_HW_FEATURES * enum definition */ struct IpaHwEventInfoData_t { u32 baseAddrOffset; union IpaHwFeatureInfoData_t featureInfo[IPA_HW_NUM_FEATURES]; } __packed; /** * struct IpaHwEventLogInfoData_t - Structure holding the parameters for * IPA_HW_2_CPU_EVENT_LOG_INFO Event * * @featureMask : Mask indicating the features enabled in HW. * Refer IPA_HW_FEATURE_MASK * @circBuffBaseAddrOffset : Base Address Offset of the Circular Event * Log Buffer structure * @statsInfo : Statistics related information * @configInfo : Configuration related information * * @note The offset location of this structure from IPA_WRAPPER_BASE * will be provided as Event Params for the IPA_HW_2_CPU_EVENT_LOG_INFO * Event */ struct IpaHwEventLogInfoData_t { u32 featureMask; u32 circBuffBaseAddrOffset; struct IpaHwEventInfoData_t statsInfo; struct IpaHwEventInfoData_t configInfo; } __packed; /** * ipa_get_wdi_stats() - Query WDI statistics from uc * @stats: [inout] stats blob from client populated by driver * * Returns: 0 on success, negative on failure * * @note Cannot be called from atomic context * */ int ipa_get_wdi_stats(struct IpaHwStatsWDIInfoData_t *stats) { #define TX_STATS(y) stats->tx_ch_stats.y = \ ipa_ctx->wdi.uc_wdi_stats_mmio->tx_ch_stats.y #define RX_STATS(y) stats->rx_ch_stats.y = \ ipa_ctx->wdi.uc_wdi_stats_mmio->rx_ch_stats.y if (!stats || !ipa_ctx->wdi.uc_top_mmio || !ipa_ctx->wdi.uc_wdi_stats_mmio) { IPAERR("bad parms stats=%p uc_top=%p wdi_stats=%p\n", stats, ipa_ctx->wdi.uc_top_mmio, ipa_ctx->wdi.uc_wdi_stats_mmio); return -EINVAL; } ipa_inc_client_enable_clks(); TX_STATS(num_pkts_processed); TX_STATS(copy_engine_doorbell_value); TX_STATS(num_db_fired); TX_STATS(tx_comp_ring_stats.ringFull); TX_STATS(tx_comp_ring_stats.ringEmpty); TX_STATS(tx_comp_ring_stats.ringUsageHigh); TX_STATS(tx_comp_ring_stats.ringUsageLow); TX_STATS(bam_stats.bamFifoFull); TX_STATS(bam_stats.bamFifoEmpty); TX_STATS(bam_stats.bamFifoUsageHigh); TX_STATS(bam_stats.bamFifoUsageLow); TX_STATS(num_db); TX_STATS(num_unexpected_db); TX_STATS(num_bam_int_handled); TX_STATS(num_bam_int_in_non_runnning_state); TX_STATS(num_qmb_int_handled); RX_STATS(max_outstanding_pkts); RX_STATS(num_pkts_processed); RX_STATS(rx_ring_rp_value); RX_STATS(rx_ind_ring_stats.ringFull); RX_STATS(rx_ind_ring_stats.ringEmpty); RX_STATS(rx_ind_ring_stats.ringUsageHigh); RX_STATS(rx_ind_ring_stats.ringUsageLow); RX_STATS(bam_stats.bamFifoFull); RX_STATS(bam_stats.bamFifoEmpty); RX_STATS(bam_stats.bamFifoUsageHigh); RX_STATS(bam_stats.bamFifoUsageLow); RX_STATS(num_bam_int_handled); RX_STATS(num_db); RX_STATS(num_unexpected_db); RX_STATS(reserved1); RX_STATS(reserved2); ipa_dec_client_disable_clks(); return 0; } EXPORT_SYMBOL(ipa_get_wdi_stats); /* TODO: add support for IPA_HW_v2_5 */ static void ipa_log_evt_hdlr(void) { if (!ipa_ctx->wdi.uc_top_ofst) { ipa_ctx->wdi.uc_top_ofst = ipa_ctx->wdi.ipa_sram_mmio->common.eventParams; if (ipa_ctx->wdi.uc_top_ofst + sizeof(struct IpaHwEventLogInfoData_t) >= ipa_ctx->ctrl->ipa_reg_base_ofst + IPA_SRAM_DIRECT_ACCESS_N_OFST_v2_0(0) + ipa_ctx->smem_sz) { IPAERR("uc_top 0x%x outside SRAM\n", ipa_ctx->wdi.uc_top_ofst); goto bad_uc_top_ofst; } ipa_ctx->wdi.uc_top_mmio = ioremap(ipa_ctx->ipa_wrapper_base + ipa_ctx->wdi.uc_top_ofst, sizeof(struct IpaHwEventLogInfoData_t)); if (!ipa_ctx->wdi.uc_top_mmio) { IPAERR("fail to ioremap uc top\n"); goto bad_uc_top_ofst; } if ((ipa_ctx->wdi.uc_top_mmio->featureMask & (1 << IPA_HW_FEATURE_WDI)) == 0) { IPAERR("WDI feature missing 0x%x\n", ipa_ctx->wdi.uc_top_mmio->featureMask); goto feat_miss; } if (ipa_ctx->wdi.uc_top_mmio->statsInfo. featureInfo[IPA_HW_FEATURE_WDI].params.size != sizeof(struct IpaHwStatsWDIInfoData_t)) { IPAERR("wdi stats size invalid exp=%zu is=%u\n", sizeof(struct IpaHwStatsWDIInfoData_t), ipa_ctx->wdi.uc_top_mmio->statsInfo. featureInfo[IPA_HW_FEATURE_WDI]. params.size); goto feat_miss; } ipa_ctx->wdi.uc_wdi_stats_ofst = ipa_ctx->wdi. uc_top_mmio->statsInfo.baseAddrOffset + ipa_ctx->wdi.uc_top_mmio->statsInfo. featureInfo[IPA_HW_FEATURE_WDI].params.offset; IPAERR("WDI stats ofst=0x%x\n", ipa_ctx->wdi.uc_wdi_stats_ofst); if (ipa_ctx->wdi.uc_wdi_stats_ofst + sizeof(struct IpaHwStatsWDIInfoData_t) >= ipa_ctx->ctrl->ipa_reg_base_ofst + IPA_SRAM_DIRECT_ACCESS_N_OFST_v2_0(0) + ipa_ctx->smem_sz) { IPAERR("uc_wdi_stats 0x%x outside SRAM\n", ipa_ctx->wdi.uc_wdi_stats_ofst); goto bad_stats_ofst; } ipa_ctx->wdi.uc_wdi_stats_mmio = ioremap(ipa_ctx->ipa_wrapper_base + ipa_ctx->wdi.uc_wdi_stats_ofst, sizeof(struct IpaHwStatsWDIInfoData_t)); if (!ipa_ctx->wdi.uc_wdi_stats_mmio) { IPAERR("fail to ioremap uc wdi stats\n"); goto bad_stats_ofst; } } else { if (ipa_ctx->wdi.ipa_sram_mmio->common.eventParams != ipa_ctx->wdi.uc_top_ofst) { IPAERR("uc top ofst changed new=%u cur=%u\n", ipa_ctx->wdi.uc_top_mmio->statsInfo. featureInfo[IPA_HW_FEATURE_WDI].params.size, ipa_ctx->wdi.uc_top_ofst); } } return; bad_stats_ofst: ipa_ctx->wdi.uc_wdi_stats_ofst = 0; feat_miss: iounmap(ipa_ctx->wdi.uc_top_mmio); bad_uc_top_ofst: ipa_ctx->wdi.uc_top_ofst = 0; return; } static void ipa_wdi_evt_handler(enum ipa_irq_type interrupt, void *private_data, void *interrupt_data) Loading Loading @@ -467,6 +680,11 @@ static void ipa_wdi_evt_handler(enum ipa_irq_type interrupt, ipa_ctx->wdi.ipa_sram_mmio->wdi_tx_ch_0_state, ipa_ctx->wdi.ipa_sram_mmio->wdi_rx_ch_0_state); } else if (ipa_ctx->wdi.ipa_sram_mmio->common.eventOp == IPA_HW_2_CPU_EVENT_LOG_INFO) { IPAERR("WDI evt log info ofst=0x%x\n", ipa_ctx->wdi.ipa_sram_mmio->common.eventParams); ipa_log_evt_hdlr(); } else { IPAERR("unsupported WDI evt opcode=%u\n", ipa_ctx->wdi.ipa_sram_mmio->common.eventOp); Loading
drivers/platform/msm/ipa/ipa_debugfs.c +97 −0 Original line number Diff line number Diff line Loading @@ -73,6 +73,7 @@ static struct dentry *dfile_ip4_flt; static struct dentry *dfile_ip6_flt; static struct dentry *dfile_stats; static struct dentry *dfile_wstats; static struct dentry *dfile_wdi_stats; static struct dentry *dfile_dbg_cnt; static struct dentry *dfile_msg; static struct dentry *dfile_ip4_nat; Loading Loading @@ -933,6 +934,91 @@ nxt_clnt_cons: return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt); } static ssize_t ipa_read_wdi(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) { struct IpaHwStatsWDIInfoData_t stats; int nbytes; int cnt = 0; if (!ipa_get_wdi_stats(&stats)) { nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN, "TX num_pkts_processed=%u\n" "TX copy_engine_doorbell_value=%u\n" "TX num_db_fired=%u\n" "TX ringFull=%u\n" "TX ringEmpty=%u\n" "TX ringUsageHigh=%u\n" "TX ringUsageLow=%u\n" "TX bamFifoFull=%u\n" "TX bamFifoEmpty=%u\n" "TX bamFifoUsageHigh=%u\n" "TX bamFifoUsageLow=%u\n" "TX num_db=%u\n" "TX num_unexpected_db=%u\n" "TX num_bam_int_handled=%u\n" "TX num_bam_int_in_non_runnning_state=%u\n" "TX num_qmb_int_handled=%u\n", stats.tx_ch_stats.num_pkts_processed, stats.tx_ch_stats.copy_engine_doorbell_value, stats.tx_ch_stats.num_db_fired, stats.tx_ch_stats.tx_comp_ring_stats.ringFull, stats.tx_ch_stats.tx_comp_ring_stats.ringEmpty, stats.tx_ch_stats.tx_comp_ring_stats.ringUsageHigh, stats.tx_ch_stats.tx_comp_ring_stats.ringUsageLow, stats.tx_ch_stats.bam_stats.bamFifoFull, stats.tx_ch_stats.bam_stats.bamFifoEmpty, stats.tx_ch_stats.bam_stats.bamFifoUsageHigh, stats.tx_ch_stats.bam_stats.bamFifoUsageLow, stats.tx_ch_stats.num_db, stats.tx_ch_stats.num_unexpected_db, stats.tx_ch_stats.num_bam_int_handled, stats.tx_ch_stats.num_bam_int_in_non_runnning_state, stats.tx_ch_stats.num_qmb_int_handled); cnt += nbytes; nbytes = scnprintf(dbg_buff + cnt, IPA_MAX_MSG_LEN - cnt, "RX max_outstanding_pkts=%u\n" "RX num_pkts_processed=%u\n" "RX rx_ring_rp_value=%u\n" "RX ringFull=%u\n" "RX ringEmpty=%u\n" "RX ringUsageHigh=%u\n" "RX ringUsageLow=%u\n" "RX bamFifoFull=%u\n" "RX bamFifoEmpty=%u\n" "RX bamFifoUsageHigh=%u\n" "RX bamFifoUsageLow=%u\n" "RX num_bam_int_handled=%u\n" "RX num_db=%u\n" "RX num_unexpected_db=%u\n" "RX reserved1=%u\n" "RX reserved2=%u\n", stats.rx_ch_stats.max_outstanding_pkts, stats.rx_ch_stats.num_pkts_processed, stats.rx_ch_stats.rx_ring_rp_value, stats.rx_ch_stats.rx_ind_ring_stats.ringFull, stats.rx_ch_stats.rx_ind_ring_stats.ringEmpty, stats.rx_ch_stats.rx_ind_ring_stats.ringUsageHigh, stats.rx_ch_stats.rx_ind_ring_stats.ringUsageLow, stats.rx_ch_stats.bam_stats.bamFifoFull, stats.rx_ch_stats.bam_stats.bamFifoEmpty, stats.rx_ch_stats.bam_stats.bamFifoUsageHigh, stats.rx_ch_stats.bam_stats.bamFifoUsageLow, stats.rx_ch_stats.num_bam_int_handled, stats.rx_ch_stats.num_db, stats.rx_ch_stats.num_unexpected_db, stats.rx_ch_stats.reserved1, stats.rx_ch_stats.reserved2); cnt += nbytes; } else { nbytes = scnprintf(dbg_buff, IPA_MAX_MSG_LEN, "Fail to read WDI stats\n"); cnt += nbytes; } return simple_read_from_buffer(ubuf, count, ppos, dbg_buff, cnt); } void _ipa_write_dbg_cnt_v1(int option) { if (option == 1) Loading Loading @@ -1249,6 +1335,10 @@ const struct file_operations ipa_wstats_ops = { .read = ipa_read_wstats, }; const struct file_operations ipa_wdi_ops = { .read = ipa_read_wdi, }; const struct file_operations ipa_msg_ops = { .read = ipa_read_msg, }; Loading Loading @@ -1358,6 +1448,13 @@ void ipa_debugfs_init(void) goto fail; } dfile_wdi_stats = debugfs_create_file("wdi", read_only_mode, dent, 0, &ipa_wdi_ops); if (!dfile_wdi_stats || IS_ERR(dfile_wdi_stats)) { IPAERR("fail to create file for debug_fs wdi stats\n"); goto fail; } dfile_dbg_cnt = debugfs_create_file("dbg_cnt", read_write_mode, dent, 0, &ipa_dbg_cnt_ops); if (!dfile_dbg_cnt || IS_ERR(dfile_dbg_cnt)) { Loading
drivers/platform/msm/ipa/ipa_i.h +4 −0 Original line number Diff line number Diff line Loading @@ -645,6 +645,10 @@ struct ipa_wdi_ctx { u32 pending_cmd; u32 last_resp; struct dma_pool *dma_pool; u32 uc_top_ofst; struct IpaHwEventLogInfoData_t *uc_top_mmio; u32 uc_wdi_stats_ofst; struct IpaHwStatsWDIInfoData_t *uc_wdi_stats_mmio; }; /** Loading
drivers/platform/msm/ipa/ipa_ram_mmap.h +5 −2 Original line number Diff line number Diff line Loading @@ -80,9 +80,12 @@ #define IPA_v2_RAM_APPS_V4_FLT_SIZE 2176 #define IPA_v2_RAM_APPS_V6_FLT_OFST (IPA_v2_RAM_APPS_V4_FLT_OFST + \ IPA_v2_RAM_APPS_V4_FLT_SIZE) #define IPA_v2_RAM_APPS_V6_FLT_SIZE 1664 #define IPA_v2_RAM_END_OFST (IPA_v2_RAM_APPS_V6_FLT_OFST + \ #define IPA_v2_RAM_APPS_V6_FLT_SIZE 1372 #define IPA_v2_RAM_UC_INFO_OFST (IPA_v2_RAM_APPS_V6_FLT_OFST + \ IPA_v2_RAM_APPS_V6_FLT_SIZE + IPA_CANARY_SIZE) #define IPA_v2_RAM_UC_INFO_SIZE 292 #define IPA_v2_RAM_END_OFST (IPA_v2_RAM_UC_INFO_OFST + \ IPA_v2_RAM_UC_INFO_SIZE) #define IPA_v2_RAM_APPS_V4_RT_OFST IPA_v2_RAM_END_OFST #define IPA_v2_RAM_APPS_V4_RT_SIZE 0 #define IPA_v2_RAM_APPS_V6_RT_OFST IPA_v2_RAM_END_OFST Loading