diff --git a/techpack/dataipa/config/dataipa.h b/techpack/dataipa/config/dataipa.h index 567fa2e68b6a..4e4ec61081a6 100644 --- a/techpack/dataipa/config/dataipa.h +++ b/techpack/dataipa/config/dataipa.h @@ -1,10 +1,16 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* -* Copyright (c) 2020, The Linux Foundation. All rights reserved. -*/ + * Copyright (c) 2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + */ #define CONFIG_GSI 1 #define CONFIG_GSI_REGISTER_VERSION_2 1 #define CONFIG_RMNET_IPA3 1 #define CONFIG_RNDIS_IPA 1 #define CONFIG_IPA_WDI_UNIFIED_API 1 +#define CONFIG_IPA3_REGDUMP 1 +#define CONFIG_IPA3_APPS_REGDUMP 1 +#define CONFIG_IPA3_REGDUMP_IPA_4_5 1 +#define CONFIG_IPA3_4_5_RGSTR 0 +#define CONFIG_IPA3_REGDUMP_NUM_EXTRA_ENDP_REGS 0 diff --git a/techpack/dataipa/config/dataipa_GKI.conf b/techpack/dataipa/config/dataipa_GKI.conf index 1559ef90cdca..6103d50a41c7 100644 --- a/techpack/dataipa/config/dataipa_GKI.conf +++ b/techpack/dataipa/config/dataipa_GKI.conf @@ -4,3 +4,7 @@ export CONFIG_IPA_CLIENTS_MANAGER=m export CONFIG_IPA_WDI_UNIFIED_API=y export CONFIG_RMNET_IPA3=y export CONFIG_RNDIS_IPA=m +export CONFIG_IPA3_REGDUMP=y +export CONFIG_IPA3_APPS_REGDUMP=y +export CONFIG_IPA3_REGDUMP_IPA_4_5=y +export CONFIG_IPA3_4_5_RGSTR=n diff --git a/techpack/dataipa/config/dataipa_QGKI.conf b/techpack/dataipa/config/dataipa_QGKI.conf index 5c1f8d44c450..b311ca3f3989 100644 --- a/techpack/dataipa/config/dataipa_QGKI.conf +++ b/techpack/dataipa/config/dataipa_QGKI.conf @@ -4,3 +4,7 @@ export CONFIG_IPA_CLIENTS_MANAGER=y export CONFIG_IPA_WDI_UNIFIED_API=y export CONFIG_RMNET_IPA3=y export CONFIG_RNDIS_IPA=y +export CONFIG_IPA3_REGDUMP=y +export CONFIG_IPA3_APPS_REGDUMP=y +export CONFIG_IPA3_REGDUMP_IPA_4_5=y +export CONFIG_IPA3_4_5_RGSTR=n diff --git a/techpack/dataipa/drivers/platform/msm/gsi/gsi.c b/techpack/dataipa/drivers/platform/msm/gsi/gsi.c index 6663e79dc528..2ae33a7bbb2a 100644 --- a/techpack/dataipa/drivers/platform/msm/gsi/gsi.c +++ b/techpack/dataipa/drivers/platform/msm/gsi/gsi.c @@ -1482,8 +1482,7 @@ int gsi_deregister_device(unsigned long dev_hdl, bool force) devm_free_irq(gsi_ctx->dev, gsi_ctx->per.irq, gsi_ctx); gsi_unmap_base(); - memset(gsi_ctx, 0, sizeof(*gsi_ctx)); - + gsi_ctx->per_registered = false; return GSI_STATUS_SUCCESS; } EXPORT_SYMBOL(gsi_deregister_device); @@ -1752,7 +1751,14 @@ static inline uint64_t gsi_read_event_ring_rp_ddr(struct gsi_evt_ring_props* pro static inline uint64_t gsi_read_event_ring_rp_reg(struct gsi_evt_ring_props* props, uint8_t id, int ee) { - return gsi_readl(gsi_ctx->base + GSI_EE_n_EV_CH_k_CNTXT_4_OFFS(id, ee)); + uint64_t rp; + + rp = gsi_readl(gsi_ctx->base + + GSI_EE_n_EV_CH_k_CNTXT_4_OFFS(id, ee)); + rp |= ((uint64_t)gsi_readl(gsi_ctx->base + + GSI_EE_n_EV_CH_k_CNTXT_5_OFFS(id, ee))) << 32; + + return rp; } int gsi_alloc_evt_ring(struct gsi_evt_ring_props *props, unsigned long dev_hdl, @@ -4051,7 +4057,7 @@ int gsi_poll_n_channel(unsigned long chan_hdl, /* update rp to see of we have anything new to process */ rp = ctx->evtr->props.gsi_read_event_ring_rp( &ctx->evtr->props, ctx->evtr->id, ee); - rp |= ctx->ring.rp & 0xFFFFFFFF00000000ULL; + rp |= ctx->evtr->ring.rp & 0xFFFFFFFF00000000ULL; ctx->evtr->ring.rp = rp; /* read gsi event ring rp again if last read is empty */ @@ -4063,7 +4069,7 @@ int gsi_poll_n_channel(unsigned long chan_hdl, __iowmb(); rp = ctx->evtr->props.gsi_read_event_ring_rp( &ctx->evtr->props, ctx->evtr->id, ee); - rp |= ctx->ring.rp & 0xFFFFFFFF00000000ULL; + rp |= ctx->evtr->ring.rp & 0xFFFFFFFF00000000ULL; ctx->evtr->ring.rp = rp; if (rp == ctx->evtr->ring.rp_local) { spin_unlock_irqrestore( diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c index 31bd41369d73..8eb0627c8aa3 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_clients/ipa_gsb.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved. */ #include @@ -56,6 +56,16 @@ IPA_GSB_DRV_NAME " %s:%d " fmt, ## args); \ } while (0) +#define IPA_GSB_ERR_RL(fmt, args...) \ + do { \ + pr_err_ratelimited_ipa(IPA_GSB_DRV_NAME " %s:%d " fmt, \ + __func__, __LINE__, ## args); \ + IPA_IPC_LOGGING(ipa3_get_ipc_logbuf(), \ + IPA_GSB_DRV_NAME " %s:%d " fmt, ## args); \ + IPA_IPC_LOGGING(ipa3_get_ipc_logbuf_low(), \ + IPA_GSB_DRV_NAME " %s:%d " fmt, ## args); \ + } while (0) + #define IPA_GSB_MAX_MSG_LEN 512 #ifdef CONFIG_DEBUG_FS @@ -1184,7 +1194,7 @@ static int ipa_bridge_tx_dp_internal(u32 hdl, struct sk_buff *skb, } if (unlikely(!ipa_gsb_ctx->iface[hdl]->is_resumed)) { - IPA_GSB_ERR("iface %d was suspended\n", hdl); + IPA_GSB_ERR_RL("iface %d was suspended\n", hdl); return -EFAULT; } diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa4.1/ipa_hw_common_ex.h b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa4.1/ipa_hw_common_ex.h index 5012a32b2a5a..ed31c017fc6e 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa4.1/ipa_hw_common_ex.h +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa4.1/ipa_hw_common_ex.h @@ -1,4 +1,6 @@ /* Copyright (c) 2019, 2021, The Linux Foundation. All rights reserved. + * + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and @@ -412,6 +414,20 @@ enum ipa_hw_irq_srcs_e { */ #define IPA_HW_REG_SAVE_NUM_ACTIVE_PIPES 23 + +/* + * Total number of channel contexts that need to be saved for q6 + */ + +#define IPA_HW_REG_SAVE_GSI_NUM_CH_CNTXT_Q6 11 + +/* + * Total number of event ring contexts that need to be saved for Q6 + */ + +#define IPA_HW_REG_SAVE_GSI_NUM_EVT_CNTXT_Q6 11 + + /* * Macro to set the active flag for all active pipe indexed register */ @@ -511,7 +527,29 @@ enum ipa_hw_irq_srcs_e { { GEN_2xVECTOR_REG_OFST(reg_name, IPA_REG_SAVE_HWP_GSI_EE, 3), \ (u32 *)&ipa_reg_save.gsi.ch_cntxt.uc[3].var_name }, \ { GEN_2xVECTOR_REG_OFST(reg_name, IPA_REG_SAVE_HWP_GSI_EE, 4), \ - (u32 *)&ipa_reg_save.gsi.ch_cntxt.uc[4].var_name } + (u32 *)&ipa_reg_save.gsi.ch_cntxt.uc[4].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 0), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[0].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 1), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[1].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 2), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[2].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 3), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[3].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 4), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[4].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 5), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[5].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 6), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[6].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 7), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[7].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 8), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[8].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 9), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[9].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 10), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[10].var_name } #define IPA_REG_SAVE_CFG_ENTRY_GSI_EVT_CNTXT(reg_name, var_name) \ { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_A7_EE, 0), \ @@ -545,7 +583,29 @@ enum ipa_hw_irq_srcs_e { { GEN_2xVECTOR_REG_OFST(reg_name, IPA_REG_SAVE_HWP_GSI_EE, 2), \ (u32 *)&ipa_reg_save.gsi.evt_cntxt.uc[2].var_name }, \ { GEN_2xVECTOR_REG_OFST(reg_name, IPA_REG_SAVE_HWP_GSI_EE, 3), \ - (u32 *)&ipa_reg_save.gsi.evt_cntxt.uc[3].var_name } + (u32 *)&ipa_reg_save.gsi.evt_cntxt.uc[3].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 0), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[0].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 1), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[1].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 2), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[2].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 3), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[3].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 4), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[4].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 5), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[5].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 6), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[6].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 7), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[7].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 8), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[8].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 9), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[9].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 10), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[10].var_name } /* * Macro to define a particular register cfg entry for all pipe diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa4.5/ipa_hw_common_ex.h b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa4.5/ipa_hw_common_ex.h index dfd95f7c2d5b..96e99aee4430 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa4.5/ipa_hw_common_ex.h +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa4.5/ipa_hw_common_ex.h @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019, 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. + * */ #if !defined(_IPA_HW_COMMON_EX_H_) #define _IPA_HW_COMMON_EX_H_ @@ -447,6 +449,11 @@ enum ipa_hw_irq_srcs_e { */ #define IPA_HW_REG_SAVE_GSI_NUM_CH_CNTXT_UC 2 +/* + * Total number of channel contexts that need to be saved for q6 + */ +#define IPA_HW_REG_SAVE_GSI_NUM_CH_CNTXT_Q6 11 + /* * Total number of event ring contexts that need to be saved for APPS */ @@ -456,6 +463,10 @@ enum ipa_hw_irq_srcs_e { * Total number of event ring contexts that need to be saved for UC */ #define IPA_HW_REG_SAVE_GSI_NUM_EVT_CNTXT_UC 1 +/* + * Total number of event ring contexts that need to be saved for Q6 + */ +#define IPA_HW_REG_SAVE_GSI_NUM_EVT_CNTXT_Q6 11 /* * Total number of endpoints for which ipa_reg_save.pipes[endp_number] @@ -562,7 +573,31 @@ enum ipa_hw_irq_srcs_e { { GEN_2xVECTOR_REG_OFST(reg_name, IPA_REG_SAVE_HWP_GSI_EE, 1), \ (u32 *)&ipa_reg_save.gsi.ch_cntxt.uc[0].var_name }, \ { GEN_2xVECTOR_REG_OFST(reg_name, IPA_REG_SAVE_HWP_GSI_EE, 3), \ - (u32 *)&ipa_reg_save.gsi.ch_cntxt.uc[1].var_name } + (u32 *)&ipa_reg_save.gsi.ch_cntxt.uc[1].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 0), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[0].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 1), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[1].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 2), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[2].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 3), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[3].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 4), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[4].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 5), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[5].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 6), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[6].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 7), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[7].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 8), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[8].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 9), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[9].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 10), \ + (u32 *)&ipa_reg_save.gsi.ch_cntxt.q6[10].var_name } + + #define IPA_REG_SAVE_CFG_ENTRY_GSI_EVT_CNTXT(reg_name, var_name) \ { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_A7_EE, 0), \ @@ -604,14 +639,39 @@ enum ipa_hw_irq_srcs_e { { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_A7_EE, 18), \ (u32 *)&ipa_reg_save.gsi.evt_cntxt.a7[18].var_name }, \ { GEN_2xVECTOR_REG_OFST(reg_name, IPA_REG_SAVE_HWP_GSI_EE, 1), \ - (u32 *)&ipa_reg_save.gsi.evt_cntxt.uc[0].var_name } + (u32 *)&ipa_reg_save.gsi.evt_cntxt.uc[0].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 0), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[0].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 1), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[1].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 2), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[2].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 3), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[3].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 4), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[4].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 5), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[5].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 6), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[6].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 7), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[7].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 8), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[8].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 9), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[9].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 10), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[10].var_name }, \ + { GEN_2xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE, 11), \ + (u32 *)&ipa_reg_save.gsi.evt_cntxt.q6[11].var_name } + /* * Macro to define a particular register cfg entry for all pipe * indexed register */ #define IPA_REG_SAVE_CFG_ENTRY_PIPE_ENDP(reg_name, var_name) \ - ({ GEN_1xVECTOR_REG_OFST(reg_name, 0), \ + { GEN_1xVECTOR_REG_OFST(reg_name, 0), \ (u32 *)&ipa_reg_save.ipa.pipes[0].endp.var_name }, \ { GEN_1xVECTOR_REG_OFST(reg_name, 1), \ (u32 *)&ipa_reg_save.ipa.pipes[1].endp.var_name }, \ @@ -672,7 +732,7 @@ enum ipa_hw_irq_srcs_e { { GEN_1xVECTOR_REG_OFST(reg_name, 29), \ (u32 *)&ipa_reg_save.ipa.pipes[29].endp.var_name }, \ { GEN_1xVECTOR_REG_OFST(reg_name, 30), \ - (u32 *)&ipa_reg_save.ipa.pipes[30].endp.var_name }) + (u32 *)&ipa_reg_save.ipa.pipes[30].endp.var_name } /* * Macro to define a particular register cfg entry for the remaining diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.c index d531b024b83d..78aab2747854 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2019, 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include "ipa_reg_dump.h" #include "ipa_access_control.h" @@ -306,6 +307,8 @@ static struct map_src_dst_addr_s ipa_regs_to_save_array[] = { * because the following registers are not scaler, rather * they are register arrays... */ + /* Below are accessable only by VMID0 domain. */ +#ifndef CONFIG_IPA3_APPS_REGDUMP IPA_REG_SAVE_CFG_ENTRY_GEN_EE(IPA_IRQ_STTS_EE_n, ipa_irq_stts_ee_n), IPA_REG_SAVE_CFG_ENTRY_GEN_EE(IPA_IRQ_EN_EE_n, @@ -322,6 +325,7 @@ static struct map_src_dst_addr_s ipa_regs_to_save_array[] = { ipa_suspend_irq_info_ee_n), IPA_REG_SAVE_CFG_ENTRY_GEN_EE(IPA_SUSPEND_IRQ_EN_EE_n, ipa_suspend_irq_en_ee_n), +#endif /* CONFIG_IPA3_APPS_REGDUMP */ /* Pipe Endp Registers */ IPA_REG_SAVE_CFG_ENTRY_PIPE_ENDP(IPA_ENDP_INIT_CTRL_n, @@ -370,38 +374,45 @@ static struct map_src_dst_addr_s ipa_regs_to_save_array[] = { ipa_src_rsrc_grp_01_rsrc_type_n), IPA_REG_SAVE_CFG_ENTRY_SRC_RSRC_GRP(IPA_SRC_RSRC_GRP_23_RSRC_TYPE_n, ipa_src_rsrc_grp_23_rsrc_type_n), +#ifdef CONFIG_IPA3_4_5_RGSTR #if defined(CONFIG_IPA3_REGDUMP_IPA_4_5) IPA_REG_SAVE_CFG_ENTRY_SRC_RSRC_GRP(IPA_SRC_RSRC_GRP_45_RSRC_TYPE_n, ipa_src_rsrc_grp_45_rsrc_type_n), -#endif - +#endif /* CONFIG_IPA3_REGDUMP_IPA_4_5 */ +#endif /* CONFIG_IPA3_4_5_RGSTR */ /* Destination Resource Group Config Registers */ IPA_REG_SAVE_CFG_ENTRY_DST_RSRC_GRP(IPA_DST_RSRC_GRP_01_RSRC_TYPE_n, ipa_dst_rsrc_grp_01_rsrc_type_n), IPA_REG_SAVE_CFG_ENTRY_DST_RSRC_GRP(IPA_DST_RSRC_GRP_23_RSRC_TYPE_n, ipa_dst_rsrc_grp_23_rsrc_type_n), +#ifdef CONFIG_IPA3_4_5_RGSTR #if defined(CONFIG_IPA3_REGDUMP_IPA_4_5) IPA_REG_SAVE_CFG_ENTRY_DST_RSRC_GRP(IPA_DST_RSRC_GRP_45_RSRC_TYPE_n, ipa_dst_rsrc_grp_45_rsrc_type_n), -#endif +#endif /* CONFIG_IPA3_REGDUMP_IPA_4_5 */ +#endif /* CONFIG_IPA3_4_5_RGSTR */ /* Source Resource Group Count Registers */ IPA_REG_SAVE_CFG_ENTRY_SRC_RSRC_CNT_GRP( IPA_SRC_RSRC_GRP_0123_RSRC_TYPE_CNT_n, ipa_src_rsrc_grp_0123_rsrc_type_cnt_n), +#ifdef CONFIG_IPA3_4_5_RGSTR #if defined(CONFIG_IPA3_REGDUMP_IPA_4_5) IPA_REG_SAVE_CFG_ENTRY_SRC_RSRC_CNT_GRP( IPA_SRC_RSRC_GRP_4567_RSRC_TYPE_CNT_n, ipa_src_rsrc_grp_4567_rsrc_type_cnt_n), -#endif +#endif /* CONFIG_IPA3_REGDUMP_IPA_4_5 */ +#endif /* CONFIG_IPA3_4_5_RGSTR */ /* Destination Resource Group Count Registers */ IPA_REG_SAVE_CFG_ENTRY_DST_RSRC_CNT_GRP( IPA_DST_RSRC_GRP_0123_RSRC_TYPE_CNT_n, ipa_dst_rsrc_grp_0123_rsrc_type_cnt_n), +#ifdef CONFIG_IPA3_4_5_RGSTR #if defined(CONFIG_IPA3_REGDUMP_IPA_4_5) IPA_REG_SAVE_CFG_ENTRY_DST_RSRC_CNT_GRP( IPA_DST_RSRC_GRP_4567_RSRC_TYPE_CNT_n, ipa_dst_rsrc_grp_4567_rsrc_type_cnt_n), -#endif +#endif /* CONFIG_IPA3_REGDUMP_IPA_4_5 */ +#endif /* CONFIG_IPA3_4_5_RGSTR */ /* * ===================================================================== * GSI register definitions begin here... @@ -409,6 +420,9 @@ static struct map_src_dst_addr_s ipa_regs_to_save_array[] = { */ /* GSI General Registers */ + /* Can access only through VMID_0 domain. */ + +#ifndef CONFIG_IPA3_APPS_REGDUMP GEN_SRC_DST_ADDR_MAP(GSI_CFG, gsi.gen, gsi_cfg), @@ -419,7 +433,9 @@ static struct map_src_dst_addr_s ipa_regs_to_save_array[] = { IPA_GSI_TOP_GSI_INST_RAM_n, ipa_gsi_top_gsi_inst_ram_n), + /* GSI Debug Registers */ + /* can access only through VMID_0 domain. */ GEN_SRC_DST_ADDR_MAP(IPA_GSI_TOP_GSI_DEBUG_BUSY_REG, gsi.debug, ipa_gsi_top_gsi_debug_busy_reg), @@ -449,6 +465,8 @@ static struct map_src_dst_addr_s ipa_regs_to_save_array[] = { GSI_DEBUG_QSB_LOG_LAST_MISC_IDn, qsb_log_last_misc), /* GSI IRAM pointers Registers */ + /* can access only through VMID_0 domain */ + GEN_SRC_DST_ADDR_MAP(IPA_GSI_TOP_GSI_IRAM_PTR_CH_CMD, gsi.debug.gsi_iram_ptrs, ipa_gsi_top_gsi_iram_ptr_ch_cmd), @@ -488,8 +506,10 @@ static struct map_src_dst_addr_s ipa_regs_to_save_array[] = { GEN_SRC_DST_ADDR_MAP(IPA_GSI_TOP_GSI_IRAM_PTR_INT_MOD_STOPPED, gsi.debug.gsi_iram_ptrs, ipa_gsi_top_gsi_iram_ptr_int_mod_stopped), - /* GSI SHRAM pointers Registers */ + /* can access only through VMID_0 domain */ + + GEN_SRC_DST_ADDR_MAP(IPA_GSI_TOP_GSI_SHRAM_PTR_CH_CNTXT_BASE_ADDR, gsi.debug.gsi_shram_ptrs, ipa_gsi_top_gsi_shram_ptr_ch_cntxt_base_addr), @@ -508,7 +528,6 @@ static struct map_src_dst_addr_s ipa_regs_to_save_array[] = { GEN_SRC_DST_ADDR_MAP(IPA_GSI_TOP_GSI_SHRAM_PTR_FUNC_STACK_BASE_ADDR, gsi.debug.gsi_shram_ptrs, ipa_gsi_top_gsi_shram_ptr_func_stack_base_addr), - /* * NOTE: That GEN_SRC_DST_ADDR_MAP() not used below. This is * because the following registers are not scaler, rather @@ -516,8 +535,12 @@ static struct map_src_dst_addr_s ipa_regs_to_save_array[] = { */ /* GSI General EE Registers */ + /* can access only through VMID_0 domain */ + + IPA_REG_SAVE_CFG_ENTRY_GSI_GENERAL_EE(GSI_MANAGER_EE_QOS_n, gsi_manager_ee_qos_n), +#endif /* CONFIG_IPA3_APPS_REGDUMP */ IPA_REG_SAVE_CFG_ENTRY_GSI_GENERAL_EE(EE_n_GSI_STATUS, ee_n_gsi_status), IPA_REG_SAVE_CFG_ENTRY_GSI_GENERAL_EE(EE_n_CNTXT_TYPE_IRQ, @@ -659,12 +682,17 @@ static struct map_src_dst_addr_s ipa_regs_to_save_array[] = { ipa_endp_init_rsrc_grp_n), IPA_REG_SAVE_CFG_ENTRY_PIPE_ENDP_EXTRA(IPA_ENDP_INIT_SEQ_n, ipa_endp_init_seq_n), + + /* can access only through VMID_0 domain */ +#ifndef CONFIG_IPA3_APPS_REGDUMP IPA_REG_SAVE_CFG_ENTRY_PIPE_ENDP_EXTRA(IPA_ENDP_GSI_CFG_TLV_n, ipa_endp_gsi_cfg_tlv_n), IPA_REG_SAVE_CFG_ENTRY_PIPE_ENDP_EXTRA(IPA_ENDP_GSI_CFG_AOS_n, ipa_endp_gsi_cfg_aos_n), IPA_REG_SAVE_CFG_ENTRY_PIPE_ENDP_EXTRA(IPA_ENDP_GSI_CFG1_n, ipa_endp_gsi_cfg1_n), +#endif /* CONFIG_IPA3_APPS_REGDUMP */ + IPA_REG_SAVE_CFG_ENTRY_PIPE_ENDP_EXTRA (IPA_ENDP_FILTER_ROUTER_HSH_CFG_n, ipa_endp_filter_router_hsh_cfg_n), @@ -707,7 +735,9 @@ static struct map_src_dst_addr_s ipa_uc_regs_to_save_array[] = { }; static void ipa_hal_save_regs_save_ipa_testbus(void); +#ifndef CONFIG_IPA3_APPS_REGDUMP static void ipa_reg_save_gsi_fifo_status(void); +#endif /* CONFIG_IPA3_APPS_REGDUMP */ static void ipa_reg_save_rsrc_cnts(void); static void ipa_hal_save_regs_ipa_cmdq(void); static void ipa_hal_save_regs_rsrc_db(void); @@ -837,9 +867,10 @@ void ipa_save_registers(void) num_regs += (CONFIG_IPA3_REGDUMP_NUM_EXTRA_ENDP_REGS * IPA_REG_SAVE_NUM_EXTRA_ENDP_REGS); +#ifndef CONFIG_IPA3_APPS_REGDUMP /* Saving GSI FIFO Status registers */ ipa_reg_save_gsi_fifo_status(); - +#endif /* CONFIG_IPA3_APPS_REGDUMP */ /* * On targets that support SSR, we generally want to disable * the following reg save functionality as it may cause stalls @@ -868,6 +899,7 @@ void ipa_save_registers(void) } /* GSI test bus */ +#ifndef CONFIG_IPA3_APPS_REGDUMP for (i = 0; i < ARRAY_SIZE(ipa_reg_save_gsi_ch_test_bus_selector_array); i++) { @@ -883,6 +915,7 @@ void ipa_save_registers(void) i].gsi_testbus_reg = (u32) IPA_READ_SCALER_REG(GSI_TEST_BUS_REG); } +#endif /* CONFIG_IPA3_APPS_REGDUMP */ ipa_reg_save_rsrc_cnts(); @@ -1039,6 +1072,7 @@ void ipa_save_registers(void) * * @return */ +#ifndef CONFIG_IPA3_APPS_REGDUMP static void ipa_reg_save_gsi_fifo_status(void) { union ipa_hwio_def_ipa_gsi_fifo_status_ctrl_u gsi_fifo_status_ctrl; @@ -1061,7 +1095,7 @@ static void ipa_reg_save_gsi_fifo_status(void) IPA_READ_SCALER_REG(IPA_GSI_AOS_FIFO_STATUS); } } - +#endif /* CONFIG_IPA3_APPS_REGDUMP */ /* * FUNCTION: ipa_reg_save_rsrc_cnts * @@ -1490,7 +1524,7 @@ int ipa_reg_save_init(u32 value) if (ipa3_ctx->do_testbus_collection_on_crash) { memset(ipa_testbus_mem, value, sizeof(ipa_testbus_mem)); ipa_reg_save.ipa.testbus = - (struct ipa_reg_save_ipa_testbus_s *) ipa_testbus_mem; + (struct ipa_reg_save_ipa_testbus_s *) ipa_testbus_mem; } /* setup access for register collection/dump on crash */ diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.h b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.h index 377931ecf6f3..665999423f11 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.h +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/dump/ipa_reg_dump.h @@ -1,6 +1,7 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2019, 2021, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #if !defined(_IPA_REG_DUMP_H_) #define _IPA_REG_DUMP_H_ @@ -242,18 +243,33 @@ struct map_src_dst_addr_s { #define IPA_REG_SAVE_GSI_VER(reg_name, var_name) \ { GEN_1xVECTOR_REG_OFST(reg_name, 0), \ (u32 *)&ipa_reg_save.gsi.gen.var_name } + + + /* * Macro to define a particular register cfg entry for all 3 EE * indexed register */ + + +#ifdef CONFIG_IPA3_APPS_REGDUMP + +#define IPA_REG_SAVE_CFG_ENTRY_GEN_EE(reg_name, var_name) \ + { GEN_1xVECTOR_REG_OFST(reg_name, IPA_HW_A7_EE), \ + (u32 *)&ipa_reg_save.ipa.gen_ee[IPA_HW_A7_EE].var_name } + +#else + #define IPA_REG_SAVE_CFG_ENTRY_GEN_EE(reg_name, var_name) \ - { GEN_1xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE), \ - (u32 *)&ipa_reg_save.ipa.gen_ee[IPA_HW_Q6_EE].var_name }, \ { GEN_1xVECTOR_REG_OFST(reg_name, IPA_HW_A7_EE), \ (u32 *)&ipa_reg_save.ipa.gen_ee[IPA_HW_A7_EE].var_name }, \ + { GEN_1xVECTOR_REG_OFST(reg_name, IPA_HW_Q6_EE), \ + (u32 *)&ipa_reg_save.ipa.gen_ee[IPA_HW_Q6_EE].var_name }, \ { GEN_1xVECTOR_REG_OFST(reg_name, IPA_HW_HWP_EE), \ (u32 *)&ipa_reg_save.ipa.gen_ee[IPA_HW_HWP_EE].var_name } +#endif /* CONFIG_IPA3_APPS_REGDUMP */ + #define IPA_REG_SAVE_CFG_ENTRY_GSI_FIFO(reg_name, var_name, index) \ { GEN_SCALER_REG_OFST(reg_name), \ (u32 *)&ipa_reg_save.ipa.gsi_fifo_status[index].var_name } @@ -1115,6 +1131,9 @@ struct ipa_reg_save_gsi_ch_cntxt_s { a7[IPA_HW_REG_SAVE_GSI_NUM_CH_CNTXT_A7]; struct ipa_reg_save_gsi_ch_cntxt_per_ep_s uc[IPA_HW_REG_SAVE_GSI_NUM_CH_CNTXT_UC]; + struct ipa_reg_save_gsi_ch_cntxt_per_ep_s + q6[IPA_HW_REG_SAVE_GSI_NUM_CH_CNTXT_Q6]; + }; /* GSI Event Context register save top level data struct */ @@ -1123,6 +1142,9 @@ struct ipa_reg_save_gsi_evt_cntxt_s { a7[IPA_HW_REG_SAVE_GSI_NUM_EVT_CNTXT_A7]; struct ipa_reg_save_gsi_evt_cntxt_per_ep_s uc[IPA_HW_REG_SAVE_GSI_NUM_EVT_CNTXT_UC]; + struct ipa_reg_save_gsi_evt_cntxt_per_ep_s + q6[IPA_HW_REG_SAVE_GSI_NUM_EVT_CNTXT_Q6]; + }; /* Top level IPA register save data struct */ diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa.c index cd5c4a7e7fa3..c0d813316098 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa.c @@ -41,6 +41,7 @@ #include #include #include +#include #ifdef CONFIG_ARM64 @@ -51,7 +52,7 @@ #endif #define DRV_NAME "ipa" - +#define DELAY_BEFORE_FW_LOAD 500 #define IPA_SUBSYSTEM_NAME "ipa_fws" #define IPA_UC_SUBSYSTEM_NAME "ipa_uc" @@ -124,8 +125,14 @@ static void ipa_gsi_notify_cb(struct gsi_per_notify *notify); static int ipa3_attach_to_smmu(void); static int ipa3_alloc_pkt_init(void); +#ifdef CONFIG_DEEPSLEEP +static void ipa3_deepsleep_resume(void); +static void ipa3_deepsleep_suspend(void); +#endif + static void ipa3_load_ipa_fw(struct work_struct *work); static DECLARE_WORK(ipa3_fw_loading_work, ipa3_load_ipa_fw); +static DECLARE_DELAYED_WORK(ipa3_fw_load_failure_handle, ipa3_load_ipa_fw); static void ipa_dec_clients_disable_clks_on_wq(struct work_struct *work); static DECLARE_DELAYED_WORK(ipa_dec_clients_disable_clks_on_wq_work, @@ -437,6 +444,38 @@ int ipa_smmu_free_sgt(struct sg_table **out_sgt_ptr) } EXPORT_SYMBOL(ipa_smmu_free_sgt); +/** + * ipa_pm_notify() - PM notify to listen suspend events + * + * This callback will be invoked by the pm framework to suspend + * operation is invoked. + * + * Returns NOTIFY_DONE to pm framework completed operation. + */ + +static int ipa_pm_notify(struct notifier_block *b, unsigned long event, void *p) +{ + IPAERR("Entry\n"); + switch (event) { + case PM_POST_SUSPEND: +#ifdef CONFIG_DEEPSLEEP + if (mem_sleep_current == PM_SUSPEND_MEM && ipa3_ctx->deepsleep) { + IPADBG("Enter deepsleep resume\n"); + ipa3_deepsleep_resume(); + IPADBG("Exit deepsleep resume\n"); + } +#endif + break; + } + IPAERR("Exit\n"); + return NOTIFY_DONE; +} + + +static struct notifier_block ipa_pm_notifier = { + .notifier_call = ipa_pm_notify, +}; + static const struct dev_pm_ops ipa_pm_ops = { .suspend_late = ipa3_ap_suspend, .resume_early = ipa3_ap_resume, @@ -3566,16 +3605,18 @@ static void ipa3_q6_avoid_holb(void) * setting HOLB on Q6 pipes, and from APPS perspective * they are not valid, therefore, the above function * will fail. + * Also don't reset the HOLB timer to 0 for Q6 pipes. */ - ipahal_write_reg_n_fields( - IPA_ENDP_INIT_HOL_BLOCK_TIMER_n, - ep_idx, &ep_holb); + + ipahal_write_reg_n_fields( IPA_ENDP_INIT_HOL_BLOCK_EN_n, ep_idx, &ep_holb); - /* IPA4.5 issue requires HOLB_EN to be written twice */ - if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) + /* For targets > IPA_4.0 issue requires HOLB_EN to + * be written twice. + */ + if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) ipahal_write_reg_n_fields( IPA_ENDP_INIT_HOL_BLOCK_EN_n, ep_idx, &ep_holb); @@ -5060,6 +5101,7 @@ static void ipa3_teardown_apps_pipes(void) __ipa3_del_rt_rule(ipa3_ctx->dflt_v4_rt_rule_hdl); __ipa3_del_hdr(ipa3_ctx->excp_hdr_hdl, false); ipa3_teardown_sys_pipe(ipa3_ctx->clnt_hdl_cmd); + ipa3_dealloc_common_event_ring(); } #ifdef CONFIG_COMPAT @@ -6314,6 +6356,12 @@ static inline void ipa3_enable_napi_lan_rx(void) napi_enable(&ipa3_ctx->napi_lan_rx); } +static inline void ipa3_disable_napi_lan_rx(void) +{ + if (ipa3_ctx->lan_rx_napi_enable) + napi_disable(&ipa3_ctx->napi_lan_rx); +} + static inline void ipa3_register_to_fmwk(void) { struct ipa_core_data data; @@ -6688,6 +6736,11 @@ static int ipa3_post_init(const struct ipa3_plat_drv_res *resource_p, IPADBG("register to fmwk\n"); ipa3_register_to_fmwk(); } + +#ifdef CONFIG_DEEPSLEEP + if (!ipa3_is_ready()) + ipa_fmwk_deepsleep_exit_ipa(); +#endif complete_all(&ipa3_ctx->init_completion_obj); ipa_ut_module_init(); @@ -6790,13 +6843,12 @@ static int ipa3_manual_load_ipa_fws(void) static int ipa3_pil_load_ipa_fws(const char *sub_sys) { - void *subsystem_get_retval = NULL; IPADBG("PIL FW loading process initiated sub_sys=%s\n", sub_sys); - subsystem_get_retval = subsystem_get(sub_sys); - if (IS_ERR_OR_NULL(subsystem_get_retval)) { + ipa3_ctx->subsystem_get_retval = subsystem_get(sub_sys); + if (IS_ERR_OR_NULL(ipa3_ctx->subsystem_get_retval)) { IPAERR("Unable to PIL load FW for sub_sys=%s\n", sub_sys); return -EINVAL; } @@ -6805,6 +6857,20 @@ static int ipa3_pil_load_ipa_fws(const char *sub_sys) return 0; } +#ifdef CONFIG_DEEPSLEEP +static int ipa3_pil_unload_ipa_fws(void) +{ + + IPADBG("PIL FW unloading process initiated sub_sys\n"); + + if (ipa3_ctx->subsystem_get_retval) + subsystem_put(ipa3_ctx->subsystem_get_retval); + + IPADBG("PIL FW unloading process is complete sub_sys\n"); + return 0; +} +#endif + static void ipa3_load_ipa_fw(struct work_struct *work) { int result; @@ -6812,11 +6878,14 @@ static void ipa3_load_ipa_fw(struct work_struct *work) IPADBG("Entry\n"); IPA_ACTIVE_CLIENTS_INC_SIMPLE(); - + result = ipa3_attach_to_smmu(); if (result) { IPAERR("IPA attach to smmu failed %d\n", result); IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); + queue_delayed_work(ipa3_ctx->transport_power_mgmt_wq, + &ipa3_fw_load_failure_handle, + msecs_to_jiffies(DELAY_BEFORE_FW_LOAD)); return; } @@ -6836,13 +6905,18 @@ static void ipa3_load_ipa_fw(struct work_struct *work) result = ipa3_manual_load_ipa_fws(); } - IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); if (result) { - IPAERR("IPA FW loading process has failed result=%d\n", - result); + + ipa3_ctx->ipa_pil_load++; + IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); + IPADBG("IPA firmware loading deffered to a work queue\n"); + queue_delayed_work(ipa3_ctx->transport_power_mgmt_wq, + &ipa3_fw_load_failure_handle, + msecs_to_jiffies(DELAY_BEFORE_FW_LOAD)); return; } + IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); mutex_lock(&ipa3_ctx->fw_load_data.lock); ipa3_ctx->fw_load_data.state = IPA_FW_LOAD_STATE_LOADED; mutex_unlock(&ipa3_ctx->fw_load_data.lock); @@ -6902,7 +6976,7 @@ static void ipa_fw_load_sm_handle_event(enum ipa_fw_load_event ev) if (ipa3_ctx->fw_load_data.state == IPA_FW_LOAD_STATE_INIT) { ipa3_ctx->fw_load_data.state = IPA_FW_LOAD_STATE_SMMU_DONE; - goto out; + goto sched_fw_load; } if (ipa3_ctx->fw_load_data.state == IPA_FW_LOAD_STATE_FWFILE_READY) { @@ -7873,8 +7947,10 @@ fail_mem_ctrl: kfree(ipa3_ctx->ipa_tz_unlock_reg); ipa3_ctx->ipa_tz_unlock_reg = NULL; fail_tz_unlock_reg: - if (ipa3_ctx->logbuf) + if (ipa3_ctx->logbuf) { ipc_log_context_destroy(ipa3_ctx->logbuf); + ipa3_ctx->logbuf = NULL; + } fail_uc_file_alloc: kfree(ipa3_ctx->gsi_fw_file_name); ipa3_ctx->gsi_fw_file_name = NULL; @@ -8807,6 +8883,7 @@ static int ipa_smmu_wlan_cb_probe(struct device *dev) } } + cb->done = true; return 0; } @@ -8886,10 +8963,35 @@ static int ipa_smmu_uc_cb_probe(struct device *dev) ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_UC] = (bypass != 0); ipa3_ctx->uc_pdev = dev; - + cb->done = true; return 0; } +static void ipa3_ap_iommu_unmap(struct ipa_smmu_cb_ctx *cb, const u32 *add_map, u32 add_map_size) { + + int i, res; + + /* iterate of each entry of the additional mapping array */ + for (i = 0; i < add_map_size / sizeof(u32); i += 3) { + u32 iova = be32_to_cpu(add_map[i]); + u32 pa = be32_to_cpu(add_map[i + 1]); + u32 size = be32_to_cpu(add_map[i + 2]); + unsigned long iova_p; + phys_addr_t pa_p; + u32 size_p; + + IPA_SMMU_ROUND_TO_PAGE(iova, pa, size, + iova_p, pa_p, size_p); + IPADBG_LOW("unmapping 0x%lx to 0x%pa size %d\n", + iova_p, &pa_p, size_p); + + res = iommu_unmap(cb->iommu_domain,iova_p, size_p); + if(res != size_p) { + pr_err("iommu unmap failed for AP cb\n"); + ipa_assert(); + } + } +} static int ipa_smmu_ap_cb_probe(struct device *dev) { struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_AP); @@ -9024,6 +9126,8 @@ static int ipa_smmu_ap_cb_probe(struct device *dev) if (ret < 0 && ret != -EEXIST) { IPAERR("unable to allocate smem MODEM entry\n"); cb->valid = false; + if(add_map) + ipa3_ap_iommu_unmap(cb, add_map, add_map_size); return -EFAULT; } smem_addr = qcom_smem_get(SMEM_MODEM, @@ -9032,6 +9136,8 @@ static int ipa_smmu_ap_cb_probe(struct device *dev) if (IS_ERR(smem_addr)) { IPAERR("unable to acquire smem MODEM entry\n"); cb->valid = false; + if(add_map) + ipa3_ap_iommu_unmap(cb, add_map, add_map_size); return -EFAULT; } if (smem_size != ipa_smem_size) @@ -9052,6 +9158,7 @@ static int ipa_smmu_ap_cb_probe(struct device *dev) smmu_info.present[IPA_SMMU_CB_AP] = true; + cb->done = true; ipa3_ctx->pdev = dev; cb->next_addr = cb->va_end; @@ -9104,18 +9211,26 @@ static int ipa_smmu_11ad_cb_probe(struct device *dev) IPADBG("11AD using shared CB\n"); cb->shared = true; } - + cb->done = true; return 0; } static int ipa_smmu_cb_probe(struct device *dev, enum ipa_smmu_cb_type cb_type) { + struct ipa_smmu_cb_ctx *cb = ipa3_get_smmu_ctx(cb_type); + + if((cb != NULL) && (cb->done == true)) { + IPADBG("SMMU CB type %d already initialized\n", cb_type); + return 0; + } switch (cb_type) { case IPA_SMMU_CB_AP: + ipa3_ctx->pdev = &ipa3_ctx->master_pdev->dev; return ipa_smmu_ap_cb_probe(dev); case IPA_SMMU_CB_WLAN: return ipa_smmu_wlan_cb_probe(dev); case IPA_SMMU_CB_UC: + ipa3_ctx->uc_pdev = &ipa3_ctx->master_pdev->dev; return ipa_smmu_uc_cb_probe(dev); case IPA_SMMU_CB_11AD: return ipa_smmu_11ad_cb_probe(dev); @@ -9130,18 +9245,19 @@ static int ipa3_attach_to_smmu(void) struct ipa_smmu_cb_ctx *cb; int i, result; - ipa3_ctx->pdev = &ipa3_ctx->master_pdev->dev; - ipa3_ctx->uc_pdev = &ipa3_ctx->master_pdev->dev; - if (smmu_info.arm_smmu) { IPADBG("smmu is enabled\n"); for (i = 0; i < IPA_SMMU_CB_MAX; i++) { cb = ipa3_get_smmu_ctx(i); result = ipa_smmu_cb_probe(cb->dev, i); - if (result) + if (result) { IPAERR("probe failed for cb %d\n", i); + return result; + } } } else { + ipa3_ctx->pdev = &ipa3_ctx->master_pdev->dev; + ipa3_ctx->uc_pdev = &ipa3_ctx->master_pdev->dev; IPADBG("smmu is disabled\n"); } return 0; @@ -9424,7 +9540,17 @@ int ipa3_plat_drv_probe(struct platform_device *pdev_p) return -EOPNOTSUPP; } } + /* Below update of pre init for non smmu device, As + * existing flow initialzies only for smmu + * enabled node.*/ + + result = ipa3_pre_init(&ipa3_res, pdev_p); + if (result) { + IPAERR("ipa3_init failed\n"); + return result; + } ipa_fw_load_sm_handle_event(IPA_FW_LOAD_EVNT_SMMU_DONE); + goto skip_repeat_pre_init; } /* Proceed to real initialization */ @@ -9434,6 +9560,7 @@ int ipa3_plat_drv_probe(struct platform_device *pdev_p) return result; } +skip_repeat_pre_init: result = of_platform_populate(pdev_p->dev.of_node, ipa_plat_drv_match, NULL, &pdev_p->dev); if (result) { @@ -9462,7 +9589,8 @@ int ipa3_ap_suspend(struct device *dev) int i; IPADBG("Enter...\n"); - + if (!of_device_is_compatible(dev->of_node,"qcom,ipa")) + return 0; /* In case there is a tx/rx handler in polling mode fail to suspend */ for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) { if (ipa3_ctx->ep[i].sys && @@ -9473,6 +9601,13 @@ int ipa3_ap_suspend(struct device *dev) } } +#ifdef CONFIG_DEEPSLEEP + if (mem_sleep_current == PM_SUSPEND_MEM) { + IPADBG("Enter deepsleep suspend\n"); + ipa3_deepsleep_suspend(); + IPADBG("Exit deepsleep suspend\n"); + } +#endif ipa_pm_deactivate_all_deferred(); IPADBG("Exit\n"); @@ -9505,6 +9640,59 @@ bool ipa3_get_lan_rx_napi(void) return ipa3_ctx->lan_rx_napi_enable; } + +#ifdef CONFIG_DEEPSLEEP +static void ipa3_deepsleep_suspend(void) +{ + IPADBG("Entry\n"); + IPA_ACTIVE_CLIENTS_INC_SIMPLE(); + + /* To allow default routing table delection using this flag */ + ipa3_ctx->deepsleep = true; + /*Disabling the LAN NAPI*/ + ipa3_disable_napi_lan_rx(); + /*NOt allow uC related operations until uC load again*/ + ipa3_ctx->uc_ctx.uc_loaded = false; + /*Disconnecting LAN PROD/LAN CONS/CMD PROD apps pipes*/ + ipa3_teardown_apps_pipes(); + /*Deregistering the GSI driver*/ + gsi_deregister_device(ipa3_ctx->gsi_dev_hdl, false); + /*Destroying filter table ids*/ + ipa3_destroy_flt_tbl_idrs(); + /*Disabling IPA interrupt*/ + ipa3_remove_interrupt_handler(IPA_TX_SUSPEND_IRQ); + ipa3_interrupts_destroy(ipa3_res.ipa_irq, &ipa3_ctx->master_pdev->dev); + ipa3_uc_interface_destroy(); + /*Destroy the NAT device*/ + ipa3_nat_ipv6ct_destroy_devices(); + /*Freeing memory allocated for coalesing and dma task*/ + ipa3_free_coal_close_frame(); + ipa3_free_dma_task_for_gsi(); + /*Destroying ipa hal module*/ + ipahal_destroy(); + ipa3_ctx->ipa_initialization_complete = false; + ipa3_debugfs_remove(); + /*Unloading IPA FW to allow FW load in resume*/ + ipa3_pil_unload_ipa_fws(); + /*Calling framework API to reset IPA ready flag to false*/ + ipa_fmwk_deepsleep_entry_ipa(); + IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); + IPADBG("Exit\n"); +} + +static void ipa3_deepsleep_resume(void) +{ + + IPADBG("Entry\n"); + /*After deeplseep exit we shouldn't allow delete the default routing table*/ + ipa3_ctx->deepsleep = false; + /*Scheduling WQ to load IPA FW*/ + queue_work(ipa3_ctx->transport_power_mgmt_wq, + &ipa3_fw_loading_work); + IPADBG("Exit\n"); +} +#endif + static void ipa_gsi_notify_cb(struct gsi_per_notify *notify) { /* @@ -9934,6 +10122,8 @@ static int __init ipa_module_init(void) /* Register as a PCI device driver */ return pci_register_driver(&ipa_pci_driver); } + + register_pm_notifier(&ipa_pm_notifier); /* Register as a platform device driver */ return platform_driver_register(&ipa_plat_drv); } @@ -9944,6 +10134,7 @@ static void __exit ipa_module_exit(void) if (running_emulation) pci_unregister_driver(&ipa_pci_driver); platform_driver_unregister(&ipa_plat_drv); + unregister_pm_notifier(&ipa_pm_notifier); kfree(ipa3_ctx); ipa3_ctx = NULL; } diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_client.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_client.c index 8ca62014e5cf..939a7716d54d 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_client.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_client.c @@ -67,6 +67,7 @@ int ipa3_enable_data_path(u32 clnt_hdl) holb_cfg.en = IPA_HOLB_TMR_EN; } else if (ipa3_ctx->ipa_hw_type == IPA_HW_v4_11 && (ep->client == IPA_CLIENT_WLAN1_CONS || + ep->client == IPA_CLIENT_WLAN2_CONS || ep->client == IPA_CLIENT_USB_CONS)) { holb_cfg.en = IPA_HOLB_TMR_EN; holb_cfg.tmr_val = IPA_HOLB_TMR_VAL_4_5; @@ -1497,8 +1498,10 @@ int ipa3_set_reset_client_cons_pipe_sus_holb(bool set_reset, u32 tmr_val, IPA_ENDP_INIT_HOL_BLOCK_EN_n, pipe_idx, &ep_holb); - /* IPA4.5 issue requires HOLB_EN to be written twice */ - if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) + /* For targets > IPA_4.0 issue requires HOLB_EN to be + * written twice. + */ + if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) ipahal_write_reg_n_fields( IPA_ENDP_INIT_HOL_BLOCK_EN_n, pipe_idx, &ep_holb); diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c index 51e813244211..b07fc3554ef5 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c @@ -1357,7 +1357,8 @@ static ssize_t ipa3_read_stats(struct file *file, char __user *ubuf, "lan_repl_rx_empty=%u\n" "flow_enable=%u\n" "flow_disable=%u\n" - "rx_page_drop_cnt=%u\n", + "rx_page_drop_cnt=%u\n" + "lower_order=%u\n", ipa3_ctx->stats.tx_sw_pkts, ipa3_ctx->stats.tx_hw_pkts, ipa3_ctx->stats.tx_non_linear, @@ -1374,7 +1375,8 @@ static ssize_t ipa3_read_stats(struct file *file, char __user *ubuf, ipa3_ctx->stats.lan_repl_rx_empty, ipa3_ctx->stats.flow_enable, ipa3_ctx->stats.flow_disable, - ipa3_ctx->stats.rx_page_drop_cnt + ipa3_ctx->stats.rx_page_drop_cnt, + ipa3_ctx->stats.lower_order ); cnt += nbytes; diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 83d2d1476508..3d829bedd7c4 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -345,20 +345,22 @@ static void ipa3_send_nop_desc(struct work_struct *work) return; } list_add_tail(&tx_pkt->link, &sys->head_desc_list); - sys->len++; - sys->nop_pending = false; memset(&nop_xfer, 0, sizeof(nop_xfer)); nop_xfer.type = GSI_XFER_ELEM_NOP; nop_xfer.flags = GSI_XFER_FLAG_EOT; nop_xfer.xfer_user_data = tx_pkt; if (gsi_queue_xfer(sys->ep->gsi_chan_hdl, 1, &nop_xfer, true)) { + list_del(&tx_pkt->link); + kmem_cache_free(ipa3_ctx->tx_pkt_wrapper_cache, tx_pkt); spin_unlock_bh(&sys->spinlock); IPAERR("gsi_queue_xfer for ch:%lu failed\n", sys->ep->gsi_chan_hdl); queue_work(sys->wq, &sys->work); return; } + sys->len++; + sys->nop_pending = false; spin_unlock_bh(&sys->spinlock); /* make sure TAG process is sent before clocks are gated */ @@ -2040,6 +2042,27 @@ fail_kmem_cache_alloc: } } +static struct page *ipa3_alloc_page( + gfp_t flag, u32 *page_order, bool try_lower) +{ + struct page *page = NULL; + u32 p_order = *page_order; + + page = __dev_alloc_pages(flag, p_order); + /* We will only try 1 page order lower. */ + if (unlikely(!page)) { + if (try_lower && p_order > 0) { + p_order = p_order - 1; + page = __dev_alloc_pages(flag, p_order); + if (likely(page)) + ipa3_ctx->stats.lower_order++; + } + } + *page_order = p_order; + return page; +} + + static struct ipa3_rx_pkt_wrapper *ipa3_alloc_rx_pkt_page( gfp_t flag, bool is_tmp_alloc) { @@ -2050,12 +2073,18 @@ static struct ipa3_rx_pkt_wrapper *ipa3_alloc_rx_pkt_page( flag); if (unlikely(!rx_pkt)) return NULL; - rx_pkt->len = PAGE_SIZE << IPA_WAN_PAGE_ORDER; - rx_pkt->page_data.page = __dev_alloc_pages(flag, - IPA_WAN_PAGE_ORDER); + + rx_pkt->page_data.page_order = IPA_WAN_PAGE_ORDER; + /* Try a lower order page for order 3 pages in case allocation fails. */ + rx_pkt->page_data.page = ipa3_alloc_page(flag, + &rx_pkt->page_data.page_order, + (is_tmp_alloc && rx_pkt->page_data.page_order == 3)); + if (unlikely(!rx_pkt->page_data.page)) goto fail_page_alloc; + rx_pkt->len = PAGE_SIZE << rx_pkt->page_data.page_order; + rx_pkt->page_data.dma_addr = dma_map_page(ipa3_ctx->pdev, rx_pkt->page_data.page, 0, rx_pkt->len, DMA_FROM_DEVICE); @@ -2073,7 +2102,7 @@ static struct ipa3_rx_pkt_wrapper *ipa3_alloc_rx_pkt_page( return rx_pkt; fail_dma_mapping: - __free_pages(rx_pkt->page_data.page, IPA_WAN_PAGE_ORDER); + __free_pages(rx_pkt->page_data.page, rx_pkt->page_data.page_order); fail_page_alloc: kmem_cache_free(ipa3_ctx->rx_pkt_wrapper_cache, rx_pkt); return NULL; @@ -2567,7 +2596,7 @@ static void ipa3_replenish_rx_cache_recycle(struct ipa3_sys_context *sys) spin_lock_bh(&sys->spinlock); rx_pkt = list_first_entry(&sys->rcycl_list, struct ipa3_rx_pkt_wrapper, link); - list_del(&rx_pkt->link); + list_del_init(&rx_pkt->link); spin_unlock_bh(&sys->spinlock); ptr = skb_put(rx_pkt->data.skb, sys->rx_buff_sz); rx_pkt->data.dma_addr = dma_map_single(ipa3_ctx->pdev, @@ -2608,8 +2637,8 @@ static void ipa3_replenish_rx_cache_recycle(struct ipa3_sys_context *sys) goto done; fail_dma_mapping: spin_lock_bh(&sys->spinlock); + ipa3_skb_recycle(rx_pkt->data.skb); list_add_tail(&rx_pkt->link, &sys->rcycl_list); - INIT_LIST_HEAD(&rx_pkt->link); spin_unlock_bh(&sys->spinlock); fail_kmem_cache_alloc: if (rx_len_cached == 0) { @@ -2767,8 +2796,7 @@ static void free_rx_page(void *chan_user_data, void *xfer_user_data) } dma_unmap_page(ipa3_ctx->pdev, rx_pkt->page_data.dma_addr, rx_pkt->len, DMA_FROM_DEVICE); - __free_pages(rx_pkt->page_data.page, - IPA_WAN_PAGE_ORDER); + __free_pages(rx_pkt->page_data.page, rx_pkt->page_data.page_order); kmem_cache_free(ipa3_ctx->rx_pkt_wrapper_cache, rx_pkt); } @@ -2819,8 +2847,7 @@ static void ipa3_cleanup_rx(struct ipa3_sys_context *sys) rx_pkt->page_data.dma_addr, rx_pkt->len, DMA_FROM_DEVICE); - __free_pages(rx_pkt->page_data.page, - IPA_WAN_PAGE_ORDER); + __free_pages(rx_pkt->page_data.page, rx_pkt->page_data.page_order); } kmem_cache_free(ipa3_ctx->rx_pkt_wrapper_cache, rx_pkt); @@ -2840,7 +2867,7 @@ static void ipa3_cleanup_rx(struct ipa3_sys_context *sys) rx_pkt->len, DMA_FROM_DEVICE); __free_pages(rx_pkt->page_data.page, - IPA_WAN_PAGE_ORDER); + rx_pkt->page_data.page_order); kmem_cache_free( ipa3_ctx->rx_pkt_wrapper_cache, rx_pkt); @@ -3640,8 +3667,7 @@ static struct sk_buff *handle_page_completion(struct gsi_chan_xfer_notify } else { dma_unmap_page(ipa3_ctx->pdev, rx_page.dma_addr, rx_pkt->len, DMA_FROM_DEVICE); - __free_pages(rx_pkt->page_data.page, - IPA_WAN_PAGE_ORDER); + __free_pages(rx_pkt->page_data.page, rx_pkt->page_data.page_order); } rx_pkt->sys->free_rx_wrapper(rx_pkt); IPA_STATS_INC_CNT(ipa3_ctx->stats.rx_page_drop_cnt); @@ -3658,17 +3684,21 @@ static struct sk_buff *handle_page_completion(struct gsi_chan_xfer_notify sys->ep->client == IPA_CLIENT_APPS_LAN_CONS) { rx_skb = alloc_skb(0, GFP_ATOMIC); if (unlikely(!rx_skb)) { - IPAERR("skb alloc failure\n"); - list_del(&rx_pkt->link); - if (!rx_page.is_tmp_alloc) { - init_page_count(rx_page.page); - } else { - dma_unmap_page(ipa3_ctx->pdev, rx_page.dma_addr, - rx_pkt->len, DMA_FROM_DEVICE); - __free_pages(rx_pkt->page_data.page, - IPA_WAN_PAGE_ORDER); + IPAERR("skb alloc failure, free all pending pages\n"); + list_for_each_entry_safe(rx_pkt, tmp, head, link) { + rx_page = rx_pkt->page_data; + size = rx_pkt->data_len; + list_del_init(&rx_pkt->link); + if (!rx_page.is_tmp_alloc) { + init_page_count(rx_page.page); + } else { + dma_unmap_page(ipa3_ctx->pdev, rx_page.dma_addr, + rx_pkt->len, DMA_FROM_DEVICE); + __free_pages(rx_pkt->page_data.page, + rx_pkt->page_data.page_order); + } + rx_pkt->sys->free_rx_wrapper(rx_pkt); } - rx_pkt->sys->free_rx_wrapper(rx_pkt); IPA_STATS_INC_CNT(ipa3_ctx->stats.rx_page_drop_cnt); return NULL; } @@ -3690,7 +3720,7 @@ static struct sk_buff *handle_page_completion(struct gsi_chan_xfer_notify skb_shinfo(rx_skb)->nr_frags, rx_page.page, 0, size, - PAGE_SIZE << IPA_WAN_PAGE_ORDER); + PAGE_SIZE << rx_page.page_order); } } else { return NULL; @@ -4735,6 +4765,13 @@ static void ipa_dma_gsi_irq_rx_notify_cb(struct gsi_chan_xfer_notify *notify) } } +void ipa3_dealloc_common_event_ring(void) +{ + IPA_ACTIVE_CLIENTS_INC_SIMPLE(); + gsi_dealloc_evt_ring(ipa3_ctx->gsi_evt_comm_hdl); + IPA_ACTIVE_CLIENTS_DEC_SIMPLE(); +} + int ipa3_alloc_common_event_ring(void) { struct gsi_evt_ring_props gsi_evt_ring_props; diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c index ab04374b3afe..b90ce38b505c 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include "ipa_i.h" @@ -90,6 +90,12 @@ static int ipa3_hdr_proc_ctx_to_hw_format(struct ipa_mem_buffer *mem, 0 : 1; } } + /* Check the pointer and header length to avoid dangerous overflow in HW */ + if (unlikely(!entry->hdr || !entry->hdr->offset_entry || + !entry->offset_entry || + entry->hdr->hdr_len == 0 || + entry->hdr->hdr_len > ipa_hdr_bin_sz[IPA_HDR_BIN_MAX - 1])) + return -EINVAL; ret = ipahal_cp_proc_ctx_to_hw_buff(entry->type, mem->base, entry->offset_entry->offset, @@ -184,13 +190,13 @@ int __ipa_commit_hdr_v3_0(void) if (ipa3_generate_hdr_hw_tbl(&hdr_mem)) { IPAERR("fail to generate HDR HW TBL\n"); - goto end; + goto failure_hdr; } if (ipa3_generate_hdr_proc_ctx_hw_tbl(hdr_mem.phys_base, &ctx_mem, &aligned_ctx_mem)) { IPAERR("fail to generate HDR PROC CTX HW TBL\n"); - goto end; + goto failure_hdr_proc; } /* IC to close the coal frame before HPS Clear if coal is enabled */ @@ -316,6 +322,7 @@ int __ipa_commit_hdr_v3_0(void) else rc = 0; +end: if (ipa3_ctx->hdr_tbl_lcl) { dma_free_coherent(ipa3_ctx->pdev, hdr_mem.size, hdr_mem.base, hdr_mem.phys_base); @@ -327,6 +334,9 @@ int __ipa_commit_hdr_v3_0(void) ipa3_ctx->hdr_mem.base, ipa3_ctx->hdr_mem.phys_base); ipa3_ctx->hdr_mem = hdr_mem; + } else { + dma_free_coherent(ipa3_ctx->pdev, hdr_mem.size, + hdr_mem.base,hdr_mem.phys_base); } } @@ -341,10 +351,12 @@ int __ipa_commit_hdr_v3_0(void) ipa3_ctx->hdr_proc_ctx_mem.base, ipa3_ctx->hdr_proc_ctx_mem.phys_base); ipa3_ctx->hdr_proc_ctx_mem = ctx_mem; + } else { + dma_free_coherent(ipa3_ctx->pdev, ctx_mem.size, + ctx_mem.base,ctx_mem.phys_base); } } -end: if (coal_cmd_pyld) ipahal_destroy_imm_cmd(coal_cmd_pyld); @@ -355,6 +367,12 @@ end: ipahal_destroy_imm_cmd(hdr_cmd_pyld); return rc; + +failure_hdr_proc: + dma_free_coherent(ipa3_ctx->pdev, hdr_mem.size, hdr_mem.base, + hdr_mem.phys_base); +failure_hdr: + return rc; } static int __ipa_add_hdr_proc_ctx(struct ipa_hdr_proc_ctx_add *proc_ctx, @@ -747,7 +765,7 @@ int __ipa3_del_hdr(u32 hdr_hdl, bool by_user) return 0; } - if (entry->is_hdr_proc_ctx) { + if (entry->is_hdr_proc_ctx || entry->proc_ctx) { dma_unmap_single(ipa3_ctx->pdev, entry->phys_base, entry->hdr_len, @@ -1078,6 +1096,7 @@ int ipa3_reset_hdr(bool user_only) if (ipa3_id_find(entry->id) == NULL) { mutex_unlock(&ipa3_ctx->lock); + IPAERR_RL("Invalid header ID\n"); WARN_ON_RATELIMIT_IPA(1); return -EFAULT; } @@ -1088,6 +1107,7 @@ int ipa3_reset_hdr(bool user_only) entry->phys_base, entry->hdr_len, DMA_TO_DEVICE); + entry->proc_ctx->hdr = NULL; entry->proc_ctx = NULL; } else { /* move the offset entry to free list */ @@ -1145,6 +1165,7 @@ int ipa3_reset_hdr(bool user_only) if (ipa3_id_find(ctx_entry->id) == NULL) { mutex_unlock(&ipa3_ctx->lock); + IPAERR_RL("Invalid proc header ID\n"); WARN_ON_RATELIMIT_IPA(1); return -EFAULT; } diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index a6a742fee493..10a4650c7335 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -506,11 +506,13 @@ enum ipa3_wdi_polling_mode { * @page: skb page * @dma_addr: DMA address of this Rx packet * @is_tmp_alloc: skb page from tmp_alloc or recycle_list + * @page_order: page order associated with the page. */ struct ipa_rx_page_data { struct page *page; dma_addr_t dma_addr; bool is_tmp_alloc; + u32 page_order; }; struct ipa3_active_client_htable_entry { @@ -544,6 +546,7 @@ struct ipa_smmu_cb_ctx { u32 va_end; bool shared; bool is_cache_coherent; + bool done; }; /** @@ -1445,6 +1448,7 @@ struct ipa3_stats { u32 tx_non_linear; u32 rx_page_drop_cnt; struct ipa3_page_recycle_stats page_recycle_stats[2]; + u64 lower_order; }; /* offset for each stats */ @@ -2124,6 +2128,8 @@ struct ipa3_context { bool (*get_teth_port_state[IPA_MAX_CLNT])(void); atomic_t is_ssr; + bool deepsleep; + void *subsystem_get_retval; struct IpaHwOffloadStatsAllocCmdData_t gsi_info[IPA_HW_PROTOCOL_MAX]; bool ipa_wan_skb_page; @@ -2155,6 +2161,8 @@ struct ipa3_context { bool modem_load_ipa_fw; bool fnr_stats_not_supported; bool is_device_crashed; + int ipa_pil_load; + }; struct ipa3_plat_drv_res { @@ -2503,7 +2511,6 @@ int ipa3_start_stop_client_prod_gsi_chnl(enum ipa_client_type client, bool start_chnl); void ipa3_client_prod_post_shutdown_cleanup(void); - int ipa3_set_reset_client_cons_pipe_sus_holb(bool set_reset, u32 tmr_val, enum ipa_client_type client); @@ -2971,6 +2978,7 @@ int ipa3_uc_send_cmd(u32 cmd, u32 opcode, u32 expected_status, void ipa3_uc_register_handlers(enum ipa3_hw_features feature, struct ipa3_uc_hdlrs *hdlrs); int ipa3_uc_notify_clk_state(bool enabled); +void ipa3_uc_interface_destroy(void); int ipa3_dma_setup(void); void ipa3_dma_shutdown(void); void ipa3_dma_async_memcpy_notify_cb(void *priv, @@ -3121,6 +3129,7 @@ int ipa3_get_ntn_stats(struct Ipa3HwStatsNTNInfoData_t *stats); struct dentry *ipa_debugfs_get_root(void); void ipa3_enable_dcd(void); void ipa3_disable_prefetch(enum ipa_client_type client); +void ipa3_dealloc_common_event_ring(void); int ipa3_alloc_common_event_ring(void); int ipa3_allocate_dma_task_for_gsi(void); void ipa3_free_dma_task_for_gsi(void); diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c index d52a80003b2d..a51c34fb27cd 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_interrupts.c @@ -454,7 +454,9 @@ int ipa3_remove_interrupt_handler(enum ipa_irq_type interrupt) return -EFAULT; } - kfree(ipa_interrupt_to_cb[irq_num].private_data); + /*If free ipa3_ctx pointer causing device crash during remove interrupt*/ + if(ipa_interrupt_to_cb[irq_num].private_data != ipa3_ctx) + kfree(ipa_interrupt_to_cb[irq_num].private_data); ipa_interrupt_to_cb[irq_num].deferred_flag = false; ipa_interrupt_to_cb[irq_num].handler = NULL; ipa_interrupt_to_cb[irq_num].private_data = NULL; diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c index 5edd4776669e..3c24d13e7c76 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_nat.c @@ -179,7 +179,7 @@ static int ipa3_nat_ipv6ct_mmap( /* * Check if no smmu or non dma coherent */ - if (!cb->valid || !dev_is_dma_coherent(cb->dev)) { + if (cb && cb->dev && (!cb->valid || !dev_is_dma_coherent(cb->dev))) { IPADBG("Either smmu valid=%u and/or DMA coherent=%u false\n", cb->valid, !dev_is_dma_coherent(cb->dev)); @@ -1366,8 +1366,9 @@ int ipa3_nat_init_cmd( goto bail; } - if (init->table_entries == 0) { - IPAERR_RL("Table entries is zero\n"); + if (init->table_entries == 0 || + init->table_entries == U16_MAX) { + IPAERR_RL("Table entries is %d\n", init->table_entries); result = -EPERM; goto bail; } diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c index a5dee263c49b..ba2686809ebe 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved. */ #include "ipa_i.h" @@ -250,6 +251,7 @@ int ipa3_send_adpl_msg(unsigned long skb_data) list_add_tail(&msg->link, &ipa3_odl_ctx->adpl_msg_list); atomic_inc(&ipa3_odl_ctx->stats.numer_in_queue); mutex_unlock(&ipa3_odl_ctx->adpl_msg_lock); + wake_up(&ipa3_odl_ctx->adpl_msg_waitq); IPA_STATS_INC_CNT(ipa3_odl_ctx->stats.odl_rx_pkt); return 0; @@ -283,7 +285,7 @@ int ipa_setup_odl_pipe(void) ipa_odl_ep_cfg = &ipa3_odl_ctx->odl_sys_param; IPADBG("Setting up the odl endpoint\n"); - ipa_odl_ep_cfg->ipa_ep_cfg.cfg.cs_offload_en = IPA_ENABLE_CS_OFFLOAD_DL; + ipa_odl_ep_cfg->ipa_ep_cfg.cfg.cs_offload_en = IPA_DISABLE_CS_OFFLOAD; ipa_odl_ep_cfg->ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_AGGR; ipa_odl_ep_cfg->ipa_ep_cfg.aggr.aggr_hard_byte_limit_en = 1; @@ -365,6 +367,11 @@ int ipa3_odl_pipe_open(void) return 0; } + if (atomic_read(&ipa3_ctx->is_ssr)) { + IPAERR("SSR in progress ODL pipe configuration not allowed\n"); + return 0; + } + memset(&holb_cfg, 0, sizeof(holb_cfg)); holb_cfg.tmr_val = 0; holb_cfg.en = 1; @@ -527,7 +534,9 @@ static ssize_t ipa_adpl_read(struct file *filp, char __user *buf, size_t count, int ret = 0; char __user *start = buf; struct ipa3_push_msg_odl *msg; + DEFINE_WAIT_FUNC(wait, woken_wake_function); + add_wait_queue(&ipa3_odl_ctx->adpl_msg_waitq, &wait); while (1) { IPADBG_LOW("Writing message to adpl pipe\n"); if (!ipa3_odl_ctx->odl_state.odl_open) @@ -572,9 +581,6 @@ static ssize_t ipa_adpl_read(struct file *filp, char __user *buf, size_t count, IPA_STATS_INC_CNT(ipa3_odl_ctx->stats.odl_tx_diag_pkt); kfree(msg); msg = NULL; - } else { - ret = -EAGAIN; - break; } ret = -EAGAIN; @@ -587,9 +593,9 @@ static ssize_t ipa_adpl_read(struct file *filp, char __user *buf, size_t count, if (start != buf) break; - + wait_woken(&wait, TASK_INTERRUPTIBLE, MAX_SCHEDULE_TIMEOUT); } - + remove_wait_queue(&ipa3_odl_ctx->adpl_msg_waitq, &wait); if (start != buf && ret != -EFAULT) ret = buf - start; @@ -665,6 +671,7 @@ int ipa_odl_init(void) odl_cdev = ipa3_odl_ctx->odl_cdev; INIT_LIST_HEAD(&ipa3_odl_ctx->adpl_msg_list); + init_waitqueue_head(&ipa3_odl_ctx->adpl_msg_waitq); mutex_init(&ipa3_odl_ctx->adpl_msg_lock); mutex_init(&ipa3_odl_ctx->pipe_lock); diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_odl.h b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_odl.h index c39d01dbb57f..e700b442b3ec 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_odl.h +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_odl.h @@ -58,6 +58,7 @@ struct ipa_odl_context { bool odl_ctl_msg_wq_flag; struct ipa3_odlstats stats; u32 odl_pm_hdl; + wait_queue_head_t adpl_msg_waitq; }; struct ipa3_push_msg_odl { diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c index ae02f21d11de..41544e22d2e9 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_qmi_service.c @@ -27,7 +27,7 @@ #define IPA_Q6_SERVICE_INS_ID 2 #define QMI_SEND_STATS_REQ_TIMEOUT_MS 5000 -#define QMI_SEND_REQ_TIMEOUT_MS 60000 +#define QMI_SEND_REQ_TIMEOUT_MS 10000 #define QMI_MHI_SEND_REQ_TIMEOUT_MS 1000 #define QMI_IPA_FORCE_CLEAR_DATAPATH_TIMEOUT_MS 1000 @@ -467,14 +467,22 @@ static int ipa3_qmi_send_req_wait(struct qmi_handle *client_handle, struct qmi_txn txn; int ret; + mutex_lock(&ipa3_qmi_lock); + + if (!client_handle) { + + mutex_unlock(&ipa3_qmi_lock); + return -EINVAL; + } + ret = qmi_txn_init(client_handle, &txn, resp_desc->ei_array, resp); if (ret < 0) { IPAWANERR("QMI txn init failed, ret= %d\n", ret); + mutex_unlock(&ipa3_qmi_lock); return ret; } - mutex_lock(&ipa3_qmi_lock); ret = qmi_send_request(client_handle, &ipa3_qmi_ctx->server_sq, &txn, @@ -483,19 +491,16 @@ static int ipa3_qmi_send_req_wait(struct qmi_handle *client_handle, req_desc->ei_array, req); - if (unlikely(!ipa_q6_clnt)) { - mutex_unlock(&ipa3_qmi_lock); - return -EINVAL; - } - mutex_unlock(&ipa3_qmi_lock); if (ret < 0) { qmi_txn_cancel(&txn); + mutex_unlock(&ipa3_qmi_lock); return ret; } - ret = qmi_txn_wait(&txn, msecs_to_jiffies(timeout_ms)); + ret = qmi_txn_wait(&txn, msecs_to_jiffies(timeout_ms)); + mutex_unlock(&ipa3_qmi_lock); return ret; } diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c index 81a4573b68f2..8c21090ffdab 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_rt.c @@ -1753,7 +1753,7 @@ int __ipa3_del_rt_rule(u32 rule_hdl) !strcmp(entry->tbl->name, IPA_DFLT_RT_TBL_NAME)) { IPADBG("Deleting rule from default rt table idx=%u\n", entry->tbl->idx); - if (entry->tbl->rule_cnt == 1) { + if (entry->tbl->rule_cnt == 1 && !ipa3_ctx->deepsleep) { IPAERR_RL("Default tbl last rule cannot be deleted\n"); return -EINVAL; } diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c index b50625b5d688..96a73878b3ba 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_uc.c @@ -1113,6 +1113,17 @@ remap_fail: return result; } +void ipa3_uc_interface_destroy(void) +{ + if(ipa3_ctx->uc_ctx.uc_inited) { + ipa3_remove_interrupt_handler(IPA_UC_IRQ_2); + ipa3_remove_interrupt_handler(IPA_UC_IRQ_1); + ipa3_remove_interrupt_handler(IPA_UC_IRQ_0); + iounmap(ipa3_ctx->uc_ctx.uc_sram_mmio); + ipa3_ctx->uc_ctx.uc_inited = false; + } +} + /** * ipa3_uc_send_cmd() - Send a command to the uC * @@ -1439,7 +1450,7 @@ int ipa3_uc_debug_stats_alloc( result = ipa3_uc_send_cmd((u32)(cmd.phys_base), command, IPA_HW_2_CPU_OFFLOAD_CMD_STATUS_SUCCESS, - false, 10 * HZ); + false, 20 * HZ); if (result) { IPAERR("fail to alloc offload stats\n"); goto cleanup; diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c index 0695a368e945..5c3edacfa78a 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c @@ -6332,8 +6332,8 @@ int ipa3_cfg_ep_holb(u32 clnt_hdl, const struct ipa_ep_cfg_holb *ep_holb) ipa3_ctx->ep[clnt_hdl].holb.en = IPA_HOLB_TMR_EN; ipahal_write_reg_n_fields(IPA_ENDP_INIT_HOL_BLOCK_EN_n, clnt_hdl, ep_holb); - /* IPA4.5 issue requires HOLB_EN to be written twice */ - if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_5) + /* For targets > IPA_4.0 issue requires HOLB_EN to be written twice */ + if (ipa3_ctx->ipa_hw_type >= IPA_HW_v4_0) ipahal_write_reg_n_fields(IPA_ENDP_INIT_HOL_BLOCK_EN_n, clnt_hdl, ep_holb); diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index 07c9fc828d24..96623321bbe5 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -2965,6 +2965,9 @@ static int ipa3_lcl_mdm_ssr_notifier_cb(struct notifier_block *this, } switch (code) { +#if IS_ENABLED(CONFIG_DEEPSLEEP) + case SUBSYS_BEFORE_DS_ENTRY: +#endif case SUBSYS_BEFORE_SHUTDOWN: IPAWANINFO("IPA received MPSS BEFORE_SHUTDOWN\n"); /*Stop netdev first to stop queueing pkts to Q6 */ @@ -2986,6 +2989,16 @@ static int ipa3_lcl_mdm_ssr_notifier_cb(struct notifier_block *this, ipa3_odl_pipe_cleanup(true); IPAWANINFO("IPA BEFORE_SHUTDOWN handling is complete\n"); break; +#if IS_ENABLED(CONFIG_DEEPSLEEP) + case SUBSYS_AFTER_DS_ENTRY: + IPAWANINFO("IPA Received AFTER DEEPSLEEP ENTRY\n"); + if (atomic_read(&rmnet_ipa3_ctx->is_ssr) && + ipa3_ctx_get_type(IPA_HW_TYPE) < IPA_HW_v4_0) + ipa3_q6_post_shutdown_cleanup(); + + IPAWANINFO("AFTER DEEPSLEEP ENTRY handling is complete\n"); + break; +#endif case SUBSYS_AFTER_SHUTDOWN: IPAWANINFO("IPA Received MPSS AFTER_SHUTDOWN\n"); if (atomic_read(&rmnet_ipa3_ctx->is_ssr) && @@ -2997,6 +3010,20 @@ static int ipa3_lcl_mdm_ssr_notifier_cb(struct notifier_block *this, IPAWANINFO("IPA AFTER_SHUTDOWN handling is complete\n"); break; +#if IS_ENABLED(CONFIG_DEEPSLEEP) + case SUBSYS_BEFORE_DS_EXIT: + IPAWANINFO("IPA received BEFORE DEEPSLEEP EXIT\n"); + if (atomic_read(&rmnet_ipa3_ctx->is_ssr)) { + /* clean up cached QMI msg/handlers */ + ipa3_qmi_service_exit(); + ipa3_q6_pre_powerup_cleanup(); + } + /* hold a proxy vote for the modem. */ + ipa3_proxy_clk_vote(atomic_read(&rmnet_ipa3_ctx->is_ssr)); + ipa3_reset_freeze_vote(); + IPAWANINFO("BEFORE DEEPSLEEP EXIT handling is complete\n"); + break; +#endif case SUBSYS_BEFORE_POWERUP: IPAWANINFO("IPA received MPSS BEFORE_POWERUP\n"); if (atomic_read(&rmnet_ipa3_ctx->is_ssr)) { @@ -3009,6 +3036,9 @@ static int ipa3_lcl_mdm_ssr_notifier_cb(struct notifier_block *this, ipa3_reset_freeze_vote(); IPAWANINFO("IPA BEFORE_POWERUP handling is complete\n"); break; +#if IS_ENABLED(CONFIG_DEEPSLEEP) + case SUBSYS_AFTER_DS_EXIT: +#endif case SUBSYS_AFTER_POWERUP: IPAWANINFO("IPA received MPSS AFTER_POWERUP\n"); if (!atomic_read(&rmnet_ipa3_ctx->is_initialized) && diff --git a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/teth_bridge.c b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/teth_bridge.c index 24f24c908667..965609bb4c56 100644 --- a/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/teth_bridge.c +++ b/techpack/dataipa/drivers/platform/msm/ipa/ipa_v3/teth_bridge.c @@ -215,6 +215,11 @@ int ipa3_teth_bridge_driver_init(void) { int res; + if(ipa3_teth_ctx) { + TETH_DBG("Tethering bridge already initlized\n"); + return 0; + } + TETH_DBG("Tethering bridge driver init\n"); ipa3_teth_ctx = kzalloc(sizeof(*ipa3_teth_ctx), GFP_KERNEL); if (!ipa3_teth_ctx)