mirror of
https://github.com/BobTheBlinker/android_kernel_motorola_sm6375.git
synced 2026-10-09 13:49:24 -04:00
Merge tag 'LA.UM.9.14.r1-19600.01-LAHAINA.QSSI12.0' of https://git.codelinaro.org/clo/la/platform/vendor/opensource/dataipa into android12-5.4-lahaina
"LA.UM.9.14.r1-19600.01-LAHAINA.QSSI12.0" * tag 'LA.UM.9.14.r1-19600.01-LAHAINA.QSSI12.0' of https://git.codelinaro.org/clo/la/platform/vendor/opensource/dataipa: msm: ipa3: Handle race condition to avoid NULL access msm: ipa3: Reduce the QMI timeout value to avoid race condition msm: ipa: Set the logbuf NULL after destroy msm: gsi: Fix the incorrect evt ring pointer msm: ipa3: In deep sleep scenario destroy/ reinitialize uC interrupts msm: ipa3: Changes to resume only suspend operation complete msm: ipa3: Disable gsi fifo and test bus registers msm: ipa3: Fix to validate the NAT table entries during NAT table init msm: ipa3: Fix to avoid the boot up crash in non smmu targets msm: ipa3: Disable of ODL offload checksum msm: ipa3: Deepsleep enable changes msm: ipa3: enable ipa register save when device is about to crash msm: ipa3: Changes not allow ODL pipe setup during SSR msm: ipa: use lower order pages msm: ipa3: fix to cleanup the dma allocation. msm: ipa: Get device pointers if smmu is disabled msm: gsi: Read 64-bit ring RP value from registers msm: ipa3: Retry to attach smmu nodes if fails msm: ipa: add skb recycle if dma fails during replenish msm: ipa: remove initing head again if dma mapping fails msm: ipa3: Retry to attach smmu nodes if fails msm: ipa3: Adding changes to support the deep sleep mode msm: ipa3: Fix to NULL terminate the header pointer in proc header table msm: ipa3: Pointer Check and Fix overflow in Header Deletion msm: ipa3: Queue nop desc again if it fails. msm: ipa3: increasing the uC interrupt timeout value msm: ipa3: Add wait queue for the adpl msm: ipa3: Add change to not reset HOLB timer msm: ipa3: Add retry attempts for subsystem loading msm: ipa: Fix to free up all pending EOB pages msm: ipa3: Fix null pointer dereference error msm: ipa3: Reduced excessive logs from ipa msm: ipa3: Configure HOLB for WLAN2 consumer pipe Change-Id: I86cdd282a02be47a6653b009a1f400fe67160edc
This commit is contained in:
commit
8da1d33744
25 changed files with 638 additions and 107 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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(
|
||||
|
|
|
|||
|
|
@ -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 <linux/debugfs.h>
|
||||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include <linux/jiffies.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/suspend.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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) &&
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in a new issue