Merge 5f4172edcd333fedba420136bacb6fd1aed8e233 on remote branch
Change-Id: If07ed0da36350ab44fc51e1c9c9bc4daa16e0794
diff --git a/config/dataipa_GKI_ipav4.conf b/config/dataipa_GKI_ipav4.conf
new file mode 100644
index 0000000..075a719
--- /dev/null
+++ b/config/dataipa_GKI_ipav4.conf
@@ -0,0 +1,5 @@
+export CONFIG_GSI=m
+export CONFIG_IPA_CLIENTS_MANAGER=m
+export CONFIG_IPA_WDI_UNIFIED_API=y
+export CONFIG_RMNET_IPA3=y
+export CONFIG_RNDIS_IPA=m
diff --git a/config/dataipa_vendor_ipav4.h b/config/dataipa_vendor_ipav4.h
new file mode 100644
index 0000000..6616a91
--- /dev/null
+++ b/config/dataipa_vendor_ipav4.h
@@ -0,0 +1,10 @@
+/*
+* Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+*/
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#define CONFIG_GSI 1
+#define CONFIG_RMNET_IPA3 1
+#define CONFIG_RNDIS_IPA 1
+#define CONFIG_IPA_WDI_UNIFIED_API 1
+#define CONFIG_IPA_VENDOR_DLKM 1
diff --git a/dataipa_dlkm_vendor_board.mk b/dataipa_dlkm_vendor_board.mk
index 63c90fa..9dc16a3 100644
--- a/dataipa_dlkm_vendor_board.mk
+++ b/dataipa_dlkm_vendor_board.mk
@@ -9,7 +9,7 @@
endif
ifeq ($(TARGET_DATAIPA_DLKM_ENABLE), true)
-DATA_DLKM_BOARD_PLATFORMS_LIST := taro kalama
+DATA_DLKM_BOARD_PLATFORMS_LIST := taro kalama bengal
ifneq ($(TARGET_BOARD_AUTO),true)
ifeq ($(call is-board-platform-in-list,$(DATA_DLKM_BOARD_PLATFORMS_LIST)),true)
BOARD_VENDOR_KERNEL_MODULES += $(KERNEL_MODULES_OUT)/gsim.ko
diff --git a/drivers/platform/msm/Android.mk b/drivers/platform/msm/Android.mk
index 230ef2b..2520e4b 100644
--- a/drivers/platform/msm/Android.mk
+++ b/drivers/platform/msm/Android.mk
@@ -1,5 +1,5 @@
ifneq ($(TARGET_BOARD_PLATFORM),qssi)
-GSI_DLKM_PLATFORMS_LIST := taro kalama
+GSI_DLKM_PLATFORMS_LIST := taro kalama bengal
ifeq ($(call is-board-platform-in-list, $(GSI_DLKM_PLATFORMS_LIST)),true)
#Make file to create GSI DLKM
diff --git a/drivers/platform/msm/Kbuild b/drivers/platform/msm/Kbuild
index 939ccea..a8eac6a 100644
--- a/drivers/platform/msm/Kbuild
+++ b/drivers/platform/msm/Kbuild
@@ -36,6 +36,16 @@
endif
endif
+ifeq ($(CONFIG_ARCH_KHAJE), y)
+DATAIPADRVTOP = $(srctree)/../../vendor/qcom/opensource/dataipa/drivers/platform/msm
+LINUXINCLUDE += -include $(srctree)/../../vendor/qcom/opensource/dataipa/config/dataipa_vendor_ipav4.h
+include $(srctree)/../../vendor/qcom/opensource/dataipa/config/dataipa_GKI_ipav4.conf
+ifeq ($(CONFIG_LOCALVERSION), "-gki-consolidate")
+include $(srctree)/../../vendor/qcom/opensource/dataipa/config/dataipa_GKI_consolidate.conf
+LINUXINCLUDE += -include $(srctree)/../../vendor/qcom/opensource/dataipa/config/dataipa_debug.h
+endif
+endif
+
#MDMs
ifeq ($(CONFIG_ARCH_SDXLEMUR), y)
LINUXINCLUDE += -include $(srctree)/techpack/dataipa/config/dataipa.h
diff --git a/drivers/platform/msm/gsi/gsi.h b/drivers/platform/msm/gsi/gsi.h
index 9432f00..1e65d0a 100644
--- a/drivers/platform/msm/gsi/gsi.h
+++ b/drivers/platform/msm/gsi/gsi.h
@@ -338,6 +338,8 @@
void *user_data;
int (*clk_status_cb)(void);
void (*enable_clk_bug_on)(void);
+ void (*vote_clk_cb)(void);
+ void (*unvote_clk_cb)(void);
bool skip_ieob_mask_wa;
bool tx_poll;
};
diff --git a/drivers/platform/msm/gsi/gsi_dbg.c b/drivers/platform/msm/gsi/gsi_dbg.c
index 7282197..ba811cd 100644
--- a/drivers/platform/msm/gsi/gsi_dbg.c
+++ b/drivers/platform/msm/gsi/gsi_dbg.c
@@ -71,6 +71,8 @@
return -EINVAL;
}
+ gsi_ctx->per.vote_clk_cb();
+
val = gsihal_read_reg_nk(GSI_EE_n_EV_CH_k_CNTXT_0,
gsi_ctx->per.ee, arg1);
TERR("EV%2d CTX0 0x%x\n", arg1, val);
@@ -120,6 +122,8 @@
gsi_ctx->per.ee, arg1);
TERR("EV%2d SCR1 0x%x\n", arg1, val);
+ gsi_ctx->per.unvote_clk_cb();
+
if (arg2) {
ctx = &gsi_ctx->evtr[arg1];
@@ -183,7 +187,9 @@
return -EINVAL;
}
+ gsi_ctx->per.vote_clk_cb();
gsi_dump_ch_info(arg1);
+ gsi_ctx->per.unvote_clk_cb();
if (arg2) {
ctx = &gsi_ctx->chan[arg1];
@@ -354,7 +360,6 @@
unsigned long missing;
char *sptr, *token;
-
if (count >= sizeof(dbg_buff))
goto error;
@@ -432,6 +437,8 @@
int ee = gsi_ctx->per.ee;
uint16_t used_hw;
+ gsi_ctx->per.vote_clk_cb();
+
rp_hw = gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_CNTXT_4,
ee, ctx->props.ch_id);
rp_hw |= ((uint64_t)gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_CNTXT_5,
@@ -442,6 +449,8 @@
wp_hw |= ((uint64_t)gsihal_read_reg_nk(GSI_EE_n_GSI_CH_k_CNTXT_7,
ee, ctx->props.ch_id)) << 32;
+ gsi_ctx->per.unvote_clk_cb();
+
start_hw = gsi_find_idx_from_addr(&ctx->ring, rp_hw);
end_hw = gsi_find_idx_from_addr(&ctx->ring, wp_hw);
@@ -590,7 +599,7 @@
char __user *buf, size_t count, loff_t *ppos)
{
struct gsi_hw_profiling_data stats;
- int nbytes, cnt = 0;
+ int ret, nbytes, cnt = 0;
u64 totalCycles = 0, util = 0;
if (gsi_ctx->per.ver < GSI_VER_2_9) {
@@ -599,7 +608,12 @@
cnt += nbytes;
goto done;
}
- if (!gsi_get_hw_profiling_stats(&stats)) {
+
+ gsi_ctx->per.vote_clk_cb();
+ ret = gsi_get_hw_profiling_stats(&stats);
+ gsi_ctx->per.unvote_clk_cb();
+
+ if (!ret) {
totalCycles = stats.mcs_busy_cnt + stats.mcs_idle_cnt +
stats.bp_and_pending_cnt;
if (totalCycles != 0)
@@ -636,7 +650,7 @@
char __user *buf, size_t count, loff_t *ppos)
{
struct gsi_fw_version ver;
- int nbytes, cnt = 0;
+ int ret, nbytes, cnt = 0;
if (gsi_ctx->per.ver < GSI_VER_2_9) {
nbytes = scnprintf(dbg_buff, GSI_MAX_MSG_LEN,
@@ -644,7 +658,12 @@
cnt += nbytes;
goto done;
}
- if (!gsi_get_fw_version(&ver)) {
+
+ gsi_ctx->per.vote_clk_cb();
+ ret = gsi_get_fw_version(&ver);
+ gsi_ctx->per.unvote_clk_cb();
+
+ if (!ret) {
nbytes = scnprintf(dbg_buff, GSI_MAX_MSG_LEN,
"hw=%d\nflavor=%d\nfw=%d\n",
ver.hw,
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c b/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c
index f911cc8..d12bbd0 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2017-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/ipa_wdi3.h>
@@ -39,6 +40,13 @@
OFFLOAD_DRV_NAME " %s:%d " fmt, ## args); \
} while (0)
+#define IPA_CLIENT_IS_WLAN0_INSTANCE(inst_id) \
+ (inst_id == 0 || inst_id == -1)
+#define IPA_CLIENT_IS_WLAN1_INSTANCE(inst_id) \
+ (inst_id == 1)
+#define DEFAULT_INSTANCE_ID (-1)
+#define INVALID_INSTANCE_ID (-2)
+
struct ipa_wdi_intf_info {
char netdev_name[IPA_RESOURCE_NAME_MAX];
u8 hdr_len;
@@ -58,100 +66,68 @@
bool is_tx1_used;
u32 sys_pipe_hdl[IPA_WDI_MAX_SUPPORTED_SYS_PIPE];
u32 ipa_pm_hdl;
+ int inst_id;
#ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN
ipa_wdi_meter_notifier_cb wdi_notify;
#endif
};
-static struct ipa_wdi_context *ipa_wdi_ctx;
+static struct ipa_wdi_context *ipa_wdi_ctx_list[IPA_WDI_INST_MAX];
-static int ipa_wdi_init_internal(struct ipa_wdi_init_in_params *in,
- struct ipa_wdi_init_out_params *out)
+/**
+ * function to Assign Handle for instance
+ *
+ * Note: If it is called for Old API then
+ * max one handle is allowed.
+ *
+ * @Return handle on success, negative on failure
+ */
+static int assign_hdl_for_inst(int inst_id)
{
- struct ipa_wdi_uc_ready_params uc_ready_params;
- struct ipa_smmu_in_params smmu_in;
- struct ipa_smmu_out_params smmu_out;
+ int hdl;
- if (ipa_wdi_ctx) {
- IPA_WDI_ERR("ipa_wdi_ctx was initialized before\n");
- return -EFAULT;
+ IPA_WDI_DBG("Assigning handle for instance id %d\n", inst_id);
+ if (inst_id <= INVALID_INSTANCE_ID) {
+ IPA_WDI_ERR("Invalid instance id %d\n", inst_id);
+ return -EINVAL;
+ }
+ else if (ipa_wdi_ctx_list[0] && (inst_id == DEFAULT_INSTANCE_ID ||
+ ipa_wdi_ctx_list[0]->inst_id == DEFAULT_INSTANCE_ID)) {
+ IPA_WDI_ERR("Invalid instance id %d\n", inst_id);
+ return -EINVAL;
+ }
+ else {
+ for (hdl = 0; hdl < IPA_WDI_INST_MAX; hdl++) {
+ if (!ipa_wdi_ctx_list[hdl])
+ break;
+ }
+ }
+ if (hdl == IPA_WDI_INST_MAX) {
+ IPA_WDI_ERR("Already Maximum Instance Registered\n");
+ return -EINVAL;
}
- if (in->wdi_version > IPA_WDI_3 || in->wdi_version < IPA_WDI_1) {
- IPA_WDI_ERR("wrong wdi version: %d\n", in->wdi_version);
- return -EFAULT;
- }
-
- ipa_wdi_ctx = kzalloc(sizeof(*ipa_wdi_ctx), GFP_KERNEL);
- if (ipa_wdi_ctx == NULL) {
- IPA_WDI_ERR("fail to alloc wdi ctx\n");
- return -ENOMEM;
- }
- mutex_init(&ipa_wdi_ctx->lock);
- init_completion(&ipa_wdi_ctx->wdi_completion);
- INIT_LIST_HEAD(&ipa_wdi_ctx->head_intf_list);
-
- ipa_wdi_ctx->wdi_version = in->wdi_version;
- uc_ready_params.notify = in->notify;
- uc_ready_params.priv = in->priv;
-#ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN
- ipa_wdi_ctx->wdi_notify = in->wdi_notify;
-#endif
-
- if (ipa3_uc_reg_rdyCB(&uc_ready_params) != 0) {
- mutex_destroy(&ipa_wdi_ctx->lock);
- kfree(ipa_wdi_ctx);
- ipa_wdi_ctx = NULL;
- return -EFAULT;
- }
-
- out->is_uC_ready = uc_ready_params.is_uC_ready;
-
- smmu_in.smmu_client = IPA_SMMU_WLAN_CLIENT;
- if (ipa3_get_smmu_params(&smmu_in, &smmu_out))
- out->is_smmu_enabled = false;
- else
- out->is_smmu_enabled = smmu_out.smmu_enable;
-
- ipa_wdi_ctx->is_smmu_enabled = out->is_smmu_enabled;
-
- if (IPA_WDI2_OVER_GSI() || (in->wdi_version == IPA_WDI_3))
- out->is_over_gsi = true;
- else
- out->is_over_gsi = false;
- return 0;
+ return hdl;
}
static int ipa_get_wdi_version_internal(void)
{
- if (ipa_wdi_ctx)
- return ipa_wdi_ctx->wdi_version;
+ if (ipa_wdi_ctx_list[0])
+ return ipa_wdi_ctx_list[0]->wdi_version;
/* default version is IPA_WDI_3 */
return IPA_WDI_3;
}
static bool ipa_wdi_is_tx1_used_internal(void)
{
- if (ipa_wdi_ctx)
- return ipa_wdi_ctx->is_tx1_used;
+ if (ipa_wdi_ctx_list[0])
+ return ipa_wdi_ctx_list[0]->is_tx1_used;
return 0;
}
-static int ipa_wdi_cleanup_internal(void)
+static void ipa_wdi_pm_cb(void *p, enum ipa_pm_cb_event event)
{
- struct ipa_wdi_intf_info *entry;
- struct ipa_wdi_intf_info *next;
-
- /* clear interface list */
- list_for_each_entry_safe(entry, next,
- &ipa_wdi_ctx->head_intf_list, link) {
- list_del(&entry->link);
- kfree(entry);
- }
- mutex_destroy(&ipa_wdi_ctx->lock);
- kfree(ipa_wdi_ctx);
- ipa_wdi_ctx = NULL;
- return 0;
+ IPA_WDI_DBG("received pm event %d\n", event);
}
static int ipa_wdi_commit_partial_hdr(
@@ -190,7 +166,114 @@
return 0;
}
-static int ipa_wdi_reg_intf_internal(struct ipa_wdi_reg_intf_in_params *in)
+/**
+ * function to know the WDI capabilities
+ *
+ * Note: Should not be called from atomic context and only
+ * after checking IPA readiness using ipa_register_ipa_ready_cb()
+ *
+ * @Return 0 on success, negative on failure
+ */
+static int ipa_wdi_get_capabilities_internal(
+ struct ipa_wdi_capabilities_out_params *out)
+{
+ if (out == NULL) {
+ IPA_WDI_ERR("invalid params out=%pK\n", out);
+ return -EINVAL;
+ }
+
+ out->num_of_instances = IPA_WDI_INST_MAX;
+ IPA_WDI_DBG("Wdi Capability: %d\n", out->num_of_instances);
+ return 0;
+}
+
+/**
+ * function to init WDI IPA offload data path
+ *
+ * Note: Should not be called from atomic context and only
+ * after checking IPA readiness using ipa_register_ipa_ready_cb()
+ *
+ * @Return 0 on success, negative on failure
+ */
+static int ipa_wdi_init_per_inst_internal(struct ipa_wdi_init_in_params *in,
+ struct ipa_wdi_init_out_params *out)
+{
+ struct ipa_wdi_uc_ready_params uc_ready_params;
+ struct ipa_smmu_in_params smmu_in;
+ struct ipa_smmu_out_params smmu_out;
+ int hdl;
+
+ if (!(in && out)) {
+ IPA_WDI_ERR("empty parameters. in=%pK out=%pK\n", in, out);
+ return -EINVAL;
+ }
+
+ if (in->wdi_version > IPA_WDI_3 || in->wdi_version < IPA_WDI_1) {
+ IPA_WDI_ERR("wrong wdi version: %d\n", in->wdi_version);
+ return -EFAULT;
+ }
+
+ hdl = assign_hdl_for_inst(in->inst_id);
+ if (hdl < 0) {
+ IPA_WDI_ERR("Error assigning hdl\n");
+ return hdl;
+ }
+
+ IPA_WDI_DBG("Assigned Handle %d\n",hdl);
+ ipa_wdi_ctx_list[hdl] = kzalloc(sizeof(struct ipa_wdi_context), GFP_KERNEL);
+ if (ipa_wdi_ctx_list[hdl] == NULL) {
+ IPA_WDI_ERR("fail to alloc wdi ctx\n");
+ return -ENOMEM;
+ }
+ mutex_init(&ipa_wdi_ctx_list[hdl]->lock);
+ init_completion(&ipa_wdi_ctx_list[hdl]->wdi_completion);
+ INIT_LIST_HEAD(&ipa_wdi_ctx_list[hdl]->head_intf_list);
+
+ ipa_wdi_ctx_list[hdl]->inst_id = in->inst_id;
+ ipa_wdi_ctx_list[hdl]->wdi_version = in->wdi_version;
+ uc_ready_params.notify = in->notify;
+ uc_ready_params.priv = in->priv;
+
+ if (ipa3_uc_reg_rdyCB(&uc_ready_params) != 0) {
+ mutex_destroy(&ipa_wdi_ctx_list[hdl]->lock);
+ kfree(ipa_wdi_ctx_list[hdl]);
+ ipa_wdi_ctx_list[hdl] = NULL;
+ return -EFAULT;
+ }
+
+ out->is_uC_ready = uc_ready_params.is_uC_ready;
+
+ if (IPA_CLIENT_IS_WLAN0_INSTANCE(ipa_wdi_ctx_list[hdl]->inst_id))
+ smmu_in.smmu_client = IPA_SMMU_WLAN_CLIENT;
+ else
+ smmu_in.smmu_client = IPA_SMMU_WLAN1_CLIENT;
+
+ if (ipa3_get_smmu_params(&smmu_in, &smmu_out))
+ out->is_smmu_enabled = false;
+ else
+ out->is_smmu_enabled = smmu_out.smmu_enable;
+
+ ipa_wdi_ctx_list[hdl]->is_smmu_enabled = out->is_smmu_enabled;
+
+ if (IPA_WDI2_OVER_GSI() || (in->wdi_version == IPA_WDI_3))
+ out->is_over_gsi = true;
+ else
+ out->is_over_gsi = false;
+
+ out->hdl = hdl;
+
+ return 0;
+}
+
+/**
+ * function to register interface
+ *
+ * Note: Should not be called from atomic context
+ *
+ * @Return 0 on success, negative on failure
+ */
+static int ipa_wdi_reg_intf_per_inst_internal(
+ struct ipa_wdi_reg_intf_in_params *in)
{
struct ipa_ioc_add_hdr *hdr;
struct ipa_wdi_intf_info *new_intf;
@@ -207,19 +290,32 @@
return -EINVAL;
}
- if (!ipa_wdi_ctx) {
+ if (in->hdl < 0 || in->hdl >=IPA_WDI_INST_MAX) {
+ IPA_WDI_ERR("Invalid handle =%d\n", in->hdl);
+ return -EINVAL;
+ }
+
+ if (!ipa_wdi_ctx_list[in->hdl]) {
IPA_WDI_ERR("wdi ctx is not initialized\n");
return -EPERM;
}
+ if (ipa_wdi_ctx_list[in->hdl]->wdi_version >= IPA_WDI_1 &&
+ ipa_wdi_ctx_list[in->hdl]->wdi_version < IPA_WDI_3 &&
+ in->hdl > 0) {
+ IPA_WDI_ERR("More than one instance not supported for WDI ver = %d\n",
+ ipa_wdi_ctx_list[in->hdl]->wdi_version);
+ return -EPERM;
+ }
+
IPA_WDI_DBG("register interface for netdev %s\n",
in->netdev_name);
- mutex_lock(&ipa_wdi_ctx->lock);
- list_for_each_entry(entry, &ipa_wdi_ctx->head_intf_list, link)
+ mutex_lock(&ipa_wdi_ctx_list[in->hdl]->lock);
+ list_for_each_entry(entry, &ipa_wdi_ctx_list[in->hdl]->head_intf_list, link)
if (strcmp(entry->netdev_name, in->netdev_name) == 0) {
IPA_WDI_DBG("intf was added before.\n");
- mutex_unlock(&ipa_wdi_ctx->lock);
+ mutex_unlock(&ipa_wdi_ctx_list[in->hdl]->lock);
return 0;
}
@@ -233,7 +329,7 @@
new_intf = kzalloc(sizeof(*new_intf), GFP_KERNEL);
if (new_intf == NULL) {
IPA_WDI_ERR("fail to alloc new intf\n");
- mutex_unlock(&ipa_wdi_ctx->lock);
+ mutex_unlock(&ipa_wdi_ctx_list[in->hdl]->lock);
return -ENOMEM;
}
@@ -265,14 +361,16 @@
/* populate tx prop */
tx.num_props = 2;
tx.prop = tx_prop;
-
+ IPA_WDI_DBG("Setting tx/rx props\n");
memset(tx_prop, 0, sizeof(tx_prop));
tx_prop[0].ip = IPA_IP_v4;
if (ipa3_get_ctx()->ipa_wdi3_over_gsi) {
if (in->is_tx1_used && ipa3_ctx->is_wdi3_tx1_needed)
- tx_prop[0].dst_pipe = IPA_CLIENT_WLAN2_CONS1;
- else
+ tx_prop[0].dst_pipe = IPA_CLIENT_WLAN2_CONS1;
+ else if (IPA_CLIENT_IS_WLAN0_INSTANCE(ipa_wdi_ctx_list[in->hdl]->inst_id))
tx_prop[0].dst_pipe = IPA_CLIENT_WLAN2_CONS;
+ else
+ tx_prop[0].dst_pipe = IPA_CLIENT_WLAN4_CONS;
}
else
tx_prop[0].dst_pipe = IPA_CLIENT_WLAN1_CONS;
@@ -285,8 +383,10 @@
if (ipa3_get_ctx()->ipa_wdi3_over_gsi) {
if (in->is_tx1_used && ipa3_ctx->is_wdi3_tx1_needed)
tx_prop[1].dst_pipe = IPA_CLIENT_WLAN2_CONS1;
- else
+ else if (IPA_CLIENT_IS_WLAN0_INSTANCE(ipa_wdi_ctx_list[in->hdl]->inst_id))
tx_prop[1].dst_pipe = IPA_CLIENT_WLAN2_CONS;
+ else
+ tx_prop[1].dst_pipe = IPA_CLIENT_WLAN4_CONS;
}
else
tx_prop[1].dst_pipe = IPA_CLIENT_WLAN1_CONS;
@@ -300,10 +400,14 @@
rx.prop = rx_prop;
memset(rx_prop, 0, sizeof(rx_prop));
rx_prop[0].ip = IPA_IP_v4;
- if (ipa_wdi_ctx->wdi_version == IPA_WDI_3)
- rx_prop[0].src_pipe = IPA_CLIENT_WLAN2_PROD;
- else
+ if (ipa_wdi_ctx_list[in->hdl]->wdi_version == IPA_WDI_3) {
+ if (IPA_CLIENT_IS_WLAN0_INSTANCE(ipa_wdi_ctx_list[in->hdl]->inst_id))
+ rx_prop[0].src_pipe = IPA_CLIENT_WLAN2_PROD;
+ else
+ rx_prop[0].src_pipe = IPA_CLIENT_WLAN3_PROD;
+ } else {
rx_prop[0].src_pipe = IPA_CLIENT_WLAN1_PROD;
+ }
rx_prop[0].hdr_l2_type = in->hdr_info[0].hdr_type;
if (in->is_meta_data_valid) {
rx_prop[0].attrib.attrib_mask |= IPA_FLT_META_DATA;
@@ -312,107 +416,52 @@
}
rx_prop[1].ip = IPA_IP_v6;
- if (ipa_wdi_ctx->wdi_version == IPA_WDI_3)
- rx_prop[1].src_pipe = IPA_CLIENT_WLAN2_PROD;
- else
+ if (ipa_wdi_ctx_list[in->hdl]->wdi_version == IPA_WDI_3) {
+ if (IPA_CLIENT_IS_WLAN0_INSTANCE(ipa_wdi_ctx_list[in->hdl]->inst_id))
+ rx_prop[1].src_pipe = IPA_CLIENT_WLAN2_PROD;
+ else
+ rx_prop[1].src_pipe = IPA_CLIENT_WLAN3_PROD;
+ } else {
rx_prop[1].src_pipe = IPA_CLIENT_WLAN1_PROD;
+ }
rx_prop[1].hdr_l2_type = in->hdr_info[1].hdr_type;
if (in->is_meta_data_valid) {
rx_prop[1].attrib.attrib_mask |= IPA_FLT_META_DATA;
rx_prop[1].attrib.meta_data = in->meta_data;
rx_prop[1].attrib.meta_data_mask = in->meta_data_mask;
}
-
if (ipa3_register_intf(in->netdev_name, &tx, &rx)) {
IPA_WDI_ERR("fail to add interface prop\n");
ret = -EFAULT;
- goto fail_commit_hdr;
}
-
- list_add(&new_intf->link, &ipa_wdi_ctx->head_intf_list);
- init_completion(&ipa_wdi_ctx->wdi_completion);
+ IPA_WDI_DBG("Done Register Interface\n");
+ list_add(&new_intf->link, &ipa_wdi_ctx_list[in->hdl]->head_intf_list);
+ init_completion(&ipa_wdi_ctx_list[in->hdl]->wdi_completion);
kfree(hdr);
- mutex_unlock(&ipa_wdi_ctx->lock);
+ mutex_unlock(&ipa_wdi_ctx_list[in->hdl]->lock);
return 0;
fail_commit_hdr:
kfree(hdr);
fail_alloc_hdr:
kfree(new_intf);
- mutex_unlock(&ipa_wdi_ctx->lock);
+ mutex_unlock(&ipa_wdi_ctx_list[in->hdl]->lock);
return ret;
}
-static int ipa_wdi_dereg_intf_internal(const char *netdev_name)
-{
- int len, ret = 0;
- struct ipa_ioc_del_hdr *hdr = NULL;
- struct ipa_wdi_intf_info *entry;
- struct ipa_wdi_intf_info *next;
-
- if (!netdev_name) {
- IPA_WDI_ERR("no netdev name.\n");
- return -EINVAL;
- }
-
- if (!ipa_wdi_ctx) {
- IPA_WDI_ERR("wdi ctx is not initialized.\n");
- return -EPERM;
- }
-
- mutex_lock(&ipa_wdi_ctx->lock);
- list_for_each_entry_safe(entry, next, &ipa_wdi_ctx->head_intf_list,
- link)
- if (strcmp(entry->netdev_name, netdev_name) == 0) {
- len = sizeof(struct ipa_ioc_del_hdr) +
- 2 * sizeof(struct ipa_hdr_del);
- hdr = kzalloc(len, GFP_KERNEL);
- if (hdr == NULL) {
- IPA_WDI_ERR("fail to alloc %d bytes\n", len);
- mutex_unlock(&ipa_wdi_ctx->lock);
- return -ENOMEM;
- }
-
- hdr->commit = 1;
- hdr->num_hdls = 2;
- hdr->hdl[0].hdl = entry->partial_hdr_hdl[0];
- hdr->hdl[1].hdl = entry->partial_hdr_hdl[1];
- IPA_WDI_DBG("IPv4 hdr hdl: %d IPv6 hdr hdl: %d\n",
- hdr->hdl[0].hdl, hdr->hdl[1].hdl);
-
- if (ipa3_del_hdr(hdr)) {
- IPA_WDI_ERR("fail to delete partial header\n");
- ret = -EFAULT;
- goto fail;
- }
-
- if (ipa3_deregister_intf(entry->netdev_name)) {
- IPA_WDI_ERR("fail to del interface props\n");
- ret = -EFAULT;
- goto fail;
- }
-
- list_del(&entry->link);
- kfree(entry);
-
- break;
- }
-
-fail:
- kfree(hdr);
- mutex_unlock(&ipa_wdi_ctx->lock);
- return ret;
-}
-
-
-static void ipa_wdi_pm_cb(void *p, enum ipa_pm_cb_event event)
-{
- IPA_WDI_DBG("received pm event %d\n", event);
-}
-
-static int ipa_wdi_conn_pipes_internal(struct ipa_wdi_conn_in_params *in,
- struct ipa_wdi_conn_out_params *out)
+/**
+ * function to connect pipes
+ *
+ * @in: [in] input parameters from client
+ * @out: [out] output params to client
+ *
+ * Note: Should not be called from atomic context
+ *
+ * @Return 0 on success, negative on failure
+ */
+static int ipa_wdi_conn_pipes_per_inst_internal(struct ipa_wdi_conn_in_params *in,
+ struct ipa_wdi_conn_out_params *out)
{
int i, j, ret = 0;
struct ipa_pm_register_params pm_params;
@@ -427,33 +476,46 @@
return -EINVAL;
}
- if (!ipa_wdi_ctx) {
+ if (in->hdl < 0 || in->hdl >= IPA_WDI_INST_MAX) {
+ IPA_WDI_ERR("Invalid handle %d \n", in->hdl);
+ return -EINVAL;
+ }
+
+ if (!ipa_wdi_ctx_list[in->hdl]) {
IPA_WDI_ERR("wdi ctx is not initialized\n");
return -EPERM;
}
+ if (ipa_wdi_ctx_list[in->hdl]->wdi_version >= IPA_WDI_1 &&
+ ipa_wdi_ctx_list[in->hdl]->wdi_version < IPA_WDI_3 &&
+ in->hdl > 0) {
+ IPA_WDI_ERR("More than one instance not supported for WDI ver = %d\n",
+ ipa_wdi_ctx_list[in->hdl]->wdi_version);
+ return -EPERM;
+ }
+
if (in->num_sys_pipe_needed > IPA_WDI_MAX_SUPPORTED_SYS_PIPE) {
IPA_WDI_ERR("ipa can only support up to %d sys pipe\n",
IPA_WDI_MAX_SUPPORTED_SYS_PIPE);
return -EINVAL;
}
- ipa_wdi_ctx->num_sys_pipe_needed = in->num_sys_pipe_needed;
+ ipa_wdi_ctx_list[in->hdl]->num_sys_pipe_needed = in->num_sys_pipe_needed;
IPA_WDI_DBG("number of sys pipe %d\n", in->num_sys_pipe_needed);
ipa_ep_idx_tx1 = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS1);
if ((ipa_ep_idx_tx1 != IPA_EP_NOT_ALLOCATED) &&
(ipa_ep_idx_tx1 < IPA3_MAX_NUM_PIPES) &&
ipa3_ctx->is_wdi3_tx1_needed) {
- ipa_wdi_ctx->is_tx1_used = in->is_tx1_used;
+ ipa_wdi_ctx_list[in->hdl]->is_tx1_used = in->is_tx1_used;
} else
- ipa_wdi_ctx->is_tx1_used = false;
+ ipa_wdi_ctx_list[in->hdl]->is_tx1_used = false;
IPA_WDI_DBG("number of sys pipe %d,Tx1 asked=%d,Tx1 supported=%d\n",
in->num_sys_pipe_needed, in->is_tx1_used,
ipa3_ctx->is_wdi3_tx1_needed);
/* setup sys pipe when needed */
- for (i = 0; i < ipa_wdi_ctx->num_sys_pipe_needed; i++) {
+ for (i = 0; i < in->num_sys_pipe_needed; i++) {
ret = ipa_setup_sys_pipe(&in->sys_in[i],
- &ipa_wdi_ctx->sys_pipe_hdl[i]);
+ &ipa_wdi_ctx_list[in->hdl]->sys_pipe_hdl[i]);
if (ret) {
IPA_WDI_ERR("fail to setup sys pipe %d\n", i);
ret = -EFAULT;
@@ -462,18 +524,21 @@
}
memset(&pm_params, 0, sizeof(pm_params));
- pm_params.name = "wdi";
+ if (IPA_CLIENT_IS_WLAN0_INSTANCE(ipa_wdi_ctx_list[in->hdl]->inst_id))
+ pm_params.name = "wdi";
+ else
+ pm_params.name = "wdi1";
pm_params.callback = ipa_wdi_pm_cb;
pm_params.user_data = NULL;
pm_params.group = IPA_PM_GROUP_DEFAULT;
- if (ipa_pm_register(&pm_params, &ipa_wdi_ctx->ipa_pm_hdl)) {
+ if (ipa_pm_register(&pm_params, &ipa_wdi_ctx_list[in->hdl]->ipa_pm_hdl)) {
IPA_WDI_ERR("fail to register ipa pm\n");
ret = -EFAULT;
goto fail_setup_sys_pipe;
}
-
- if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
- if (ipa3_conn_wdi3_pipes(in, out, ipa_wdi_ctx->wdi_notify)) {
+ IPA_WDI_DBG("PM handle Registered\n");
+ if (ipa_wdi_ctx_list[in->hdl]->wdi_version == IPA_WDI_3) {
+ if (ipa3_conn_wdi3_pipes(in, out, ipa_wdi_ctx_list[in->hdl]->wdi_notify)) {
IPA_WDI_ERR("fail to setup wdi pipes\n");
ret = -EFAULT;
goto fail_connect_pipe;
@@ -484,7 +549,7 @@
memset(&out_tx, 0, sizeof(out_tx));
memset(&out_rx, 0, sizeof(out_rx));
#ifdef IPA_WAN_MSG_IPv6_ADDR_GW_LEN
- in_rx.wdi_notify = ipa_wdi_ctx->wdi_notify;
+ in_rx.wdi_notify = ipa_wdi_ctx_list[in->hdl]->wdi_notify;
#endif
if (in->is_smmu_enabled == false) {
/* firsr setup rx pipe */
@@ -514,7 +579,7 @@
ret = -EFAULT;
goto fail_connect_pipe;
}
- ipa_wdi_ctx->rx_pipe_hdl = out_rx.clnt_hdl;
+ ipa_wdi_ctx_list[in->hdl]->rx_pipe_hdl = out_rx.clnt_hdl;
out->rx_uc_db_pa = out_rx.uc_door_bell_pa;
IPA_WDI_DBG("rx uc db pa: 0x%pad\n", &out->rx_uc_db_pa);
@@ -543,7 +608,7 @@
ret = -EFAULT;
goto fail;
}
- ipa_wdi_ctx->tx_pipe_hdl = out_tx.clnt_hdl;
+ ipa_wdi_ctx_list[in->hdl]->tx_pipe_hdl = out_tx.clnt_hdl;
out->tx_uc_db_pa = out_tx.uc_door_bell_pa;
IPA_WDI_DBG("tx uc db pa: 0x%pad\n", &out->tx_uc_db_pa);
} else { /* smmu is enabled */
@@ -574,7 +639,7 @@
ret = -EFAULT;
goto fail_connect_pipe;
}
- ipa_wdi_ctx->rx_pipe_hdl = out_rx.clnt_hdl;
+ ipa_wdi_ctx_list[in->hdl]->rx_pipe_hdl = out_rx.clnt_hdl;
out->rx_uc_db_pa = out_rx.uc_door_bell_pa;
IPA_WDI_DBG("rx uc db pa: 0x%pad\n", &out->rx_uc_db_pa);
@@ -603,100 +668,72 @@
ret = -EFAULT;
goto fail;
}
- ipa_wdi_ctx->tx_pipe_hdl = out_tx.clnt_hdl;
+ ipa_wdi_ctx_list[in->hdl]->tx_pipe_hdl = out_tx.clnt_hdl;
out->tx_uc_db_pa = out_tx.uc_door_bell_pa;
- ret = ipa_pm_associate_ipa_cons_to_client(ipa_wdi_ctx->ipa_pm_hdl,
- in_tx.sys.client);
+ ret = ipa_pm_associate_ipa_cons_to_client(ipa_wdi_ctx_list[in->hdl]->ipa_pm_hdl,
+ in_tx.sys.client);
if (ret) {
IPA_WDI_ERR("fail to associate cons with PM %d\n", ret);
goto fail;
}
IPA_WDI_DBG("tx uc db pa: 0x%pad\n", &out->tx_uc_db_pa);
}
+ IPA_WDI_DBG("conn pipes done\n");
}
return 0;
fail:
- ipa3_disconnect_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl);
+ ipa3_disconnect_wdi_pipe(ipa_wdi_ctx_list[in->hdl]->rx_pipe_hdl);
fail_connect_pipe:
- ipa_pm_deregister(ipa_wdi_ctx->ipa_pm_hdl);
+ ipa_pm_deregister(ipa_wdi_ctx_list[in->hdl]->ipa_pm_hdl);
fail_setup_sys_pipe:
for (j = 0; j < i; j++)
- ipa_teardown_sys_pipe(ipa_wdi_ctx->sys_pipe_hdl[j]);
+ ipa_teardown_sys_pipe(ipa_wdi_ctx_list[in->hdl]->sys_pipe_hdl[j]);
return ret;
}
-static int ipa_wdi_disconn_pipes_internal(void)
-{
- int i, ipa_ep_idx_rx, ipa_ep_idx_tx;
- int ipa_ep_idx_tx1 = IPA_EP_NOT_ALLOCATED;
-
- if (!ipa_wdi_ctx) {
- IPA_WDI_ERR("wdi ctx is not initialized\n");
- return -EPERM;
- }
-
- /* tear down sys pipe if needed */
- for (i = 0; i < ipa_wdi_ctx->num_sys_pipe_needed; i++) {
- if (ipa_teardown_sys_pipe(ipa_wdi_ctx->sys_pipe_hdl[i])) {
- IPA_WDI_ERR("fail to tear down sys pipe %d\n", i);
- return -EFAULT;
- }
- }
-
- if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
- ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_PROD);
- ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS);
- if (ipa_wdi_ctx->is_tx1_used)
- ipa_ep_idx_tx1 =
- ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS1);
- } else {
- ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
- ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
- }
-
- if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
- if (ipa3_disconn_wdi3_pipes(
- ipa_ep_idx_tx, ipa_ep_idx_rx, ipa_ep_idx_tx1)) {
- IPA_WDI_ERR("fail to tear down wdi pipes\n");
- return -EFAULT;
- }
- } else {
- if (ipa3_disconnect_wdi_pipe(ipa_wdi_ctx->tx_pipe_hdl)) {
- IPA_WDI_ERR("fail to tear down wdi tx pipes\n");
- return -EFAULT;
- }
- if (ipa3_disconnect_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl)) {
- IPA_WDI_ERR("fail to tear down wdi rx pipes\n");
- return -EFAULT;
- }
- }
-
- if (ipa_pm_deregister(ipa_wdi_ctx->ipa_pm_hdl)) {
- IPA_WDI_ERR("fail to deregister ipa pm\n");
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int ipa_wdi_enable_pipes_internal(void)
+/**
+ * function to enable IPA offload data path
+ *
+ * @hdl: hdl to wdi client
+ * Note: Should not be called from atomic context
+ *
+ * Returns: 0 on success, negative on failure
+ */
+static int ipa_wdi_enable_pipes_per_inst_internal(ipa_wdi_hdl_t hdl)
{
int ret;
int ipa_ep_idx_tx, ipa_ep_idx_rx;
int ipa_ep_idx_tx1 = IPA_EP_NOT_ALLOCATED;
- if (!ipa_wdi_ctx) {
+ if (hdl < 0 || hdl >= IPA_WDI_INST_MAX) {
+ IPA_WDI_ERR("Invalid handle %d\n", hdl);
+ }
+
+ if (!ipa_wdi_ctx_list[hdl]) {
IPA_WDI_ERR("wdi ctx is not initialized.\n");
return -EPERM;
}
- if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
- ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_PROD);
- ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS);
- if (ipa_wdi_ctx->is_tx1_used)
+ if (ipa_wdi_ctx_list[hdl]->wdi_version >= IPA_WDI_1 &&
+ ipa_wdi_ctx_list[hdl]->wdi_version < IPA_WDI_3 &&
+ hdl > 0) {
+ IPA_WDI_ERR("More than one instance not supported for WDI ver = %d\n",
+ ipa_wdi_ctx_list[hdl]->wdi_version);
+ return -EPERM;
+ }
+
+ if (ipa_wdi_ctx_list[hdl]->wdi_version == IPA_WDI_3) {
+ if (IPA_CLIENT_IS_WLAN0_INSTANCE(ipa_wdi_ctx_list[hdl]->inst_id)) {
+ ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_PROD);
+ ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS);
+ } else {
+ ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN3_PROD);
+ ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN4_CONS);
+ }
+ if (ipa_wdi_ctx_list[hdl]->is_tx1_used)
ipa_ep_idx_tx1 =
ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS1);
} else {
@@ -706,40 +743,39 @@
if (ipa_ep_idx_tx <= 0 || ipa_ep_idx_rx <= 0)
return -EFAULT;
-
- ret = ipa_pm_activate_sync(ipa_wdi_ctx->ipa_pm_hdl);
+ ret = ipa_pm_activate_sync(ipa_wdi_ctx_list[hdl]->ipa_pm_hdl);
if (ret) {
IPA_WDI_ERR("fail to activate ipa pm\n");
return -EFAULT;
}
-
- if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
+ IPA_WDI_DBG("Enable WDI pipes\n");
+ if (ipa_wdi_ctx_list[hdl]->wdi_version == IPA_WDI_3) {
if (ipa3_enable_wdi3_pipes(
ipa_ep_idx_tx, ipa_ep_idx_rx, ipa_ep_idx_tx1)) {
IPA_WDI_ERR("fail to enable wdi pipes\n");
return -EFAULT;
}
} else {
- if ((ipa_wdi_ctx->tx_pipe_hdl >= IPA3_MAX_NUM_PIPES) ||
- (ipa_wdi_ctx->tx_pipe_hdl < 0) ||
- (ipa_wdi_ctx->rx_pipe_hdl >= IPA3_MAX_NUM_PIPES) ||
- (ipa_wdi_ctx->rx_pipe_hdl < 0)) {
+ if ((ipa_wdi_ctx_list[hdl]->tx_pipe_hdl >= IPA3_MAX_NUM_PIPES) ||
+ (ipa_wdi_ctx_list[hdl]->tx_pipe_hdl < 0) ||
+ (ipa_wdi_ctx_list[hdl]->rx_pipe_hdl >= IPA3_MAX_NUM_PIPES) ||
+ (ipa_wdi_ctx_list[hdl]->rx_pipe_hdl < 0)) {
IPA_WDI_ERR("pipe handle not valid\n");
return -EFAULT;
}
- if (ipa3_enable_wdi_pipe(ipa_wdi_ctx->tx_pipe_hdl)) {
+ if (ipa3_enable_wdi_pipe(ipa_wdi_ctx_list[hdl]->tx_pipe_hdl)) {
IPA_WDI_ERR("fail to enable wdi tx pipe\n");
return -EFAULT;
}
- if (ipa3_resume_wdi_pipe(ipa_wdi_ctx->tx_pipe_hdl)) {
+ if (ipa3_resume_wdi_pipe(ipa_wdi_ctx_list[hdl]->tx_pipe_hdl)) {
IPA_WDI_ERR("fail to resume wdi tx pipe\n");
return -EFAULT;
}
- if (ipa3_enable_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl)) {
+ if (ipa3_enable_wdi_pipe(ipa_wdi_ctx_list[hdl]->rx_pipe_hdl)) {
IPA_WDI_ERR("fail to enable wdi rx pipe\n");
return -EFAULT;
}
- if (ipa3_resume_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl)) {
+ if (ipa3_resume_wdi_pipe(ipa_wdi_ctx_list[hdl]->rx_pipe_hdl)) {
IPA_WDI_ERR("fail to resume wdi rx pipe\n");
return -EFAULT;
}
@@ -748,75 +784,40 @@
return 0;
}
-static int ipa_wdi_disable_pipes_internal(void)
-{
- int ret;
- int ipa_ep_idx_tx, ipa_ep_idx_rx;
- int ipa_ep_idx_tx1 = IPA_EP_NOT_ALLOCATED;
-
- if (!ipa_wdi_ctx) {
- IPA_WDI_ERR("wdi ctx is not initialized.\n");
- return -EPERM;
- }
-
- if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
- ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_PROD);
- ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS);
- if (ipa_wdi_ctx->is_tx1_used)
- ipa_ep_idx_tx1 =
- ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS1);
- } else {
- ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
- ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
- }
-
- if (ipa_wdi_ctx->wdi_version == IPA_WDI_3) {
- if (ipa3_disable_wdi3_pipes(
- ipa_ep_idx_tx, ipa_ep_idx_rx, ipa_ep_idx_tx1)) {
- IPA_WDI_ERR("fail to disable wdi pipes\n");
- return -EFAULT;
- }
- } else {
- if (ipa3_suspend_wdi_pipe(ipa_wdi_ctx->tx_pipe_hdl)) {
- IPA_WDI_ERR("fail to suspend wdi tx pipe\n");
- return -EFAULT;
- }
- if (ipa3_disable_wdi_pipe(ipa_wdi_ctx->tx_pipe_hdl)) {
- IPA_WDI_ERR("fail to disable wdi tx pipe\n");
- return -EFAULT;
- }
- if (ipa3_suspend_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl)) {
- IPA_WDI_ERR("fail to suspend wdi rx pipe\n");
- return -EFAULT;
- }
- if (ipa3_disable_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl)) {
- IPA_WDI_ERR("fail to disable wdi rx pipe\n");
- return -EFAULT;
- }
- }
-
- ret = ipa_pm_deactivate_sync(ipa_wdi_ctx->ipa_pm_hdl);
- if (ret) {
- IPA_WDI_ERR("fail to deactivate ipa pm\n");
- return -EFAULT;
- }
-
- return 0;
-}
-
-static int ipa_wdi_set_perf_profile_internal(struct ipa_wdi_perf_profile *profile)
+/**
+ * set IPA clock bandwidth based on data rates
+ *
+ * @hdl: hdl to wdi client
+ * @profile: [in] BandWidth profile to use
+ *
+ * Returns: 0 on success, negative on failure
+ */
+static int ipa_wdi_set_perf_profile_per_inst_internal(ipa_wdi_hdl_t hdl,
+ struct ipa_wdi_perf_profile *profile)
{
int res = 0;
-
if (profile == NULL) {
IPA_WDI_ERR("Invalid input\n");
return -EINVAL;
}
+ if (hdl < 0 || hdl >= IPA_WDI_INST_MAX) {
+ IPA_WDI_ERR("Invalid Handle %d\n",hdl);
+ return -EFAULT;
+ }
+
+ if (ipa_wdi_ctx_list[hdl]->wdi_version >= IPA_WDI_1 &&
+ ipa_wdi_ctx_list[hdl]->wdi_version < IPA_WDI_3 &&
+ hdl > 0) {
+ IPA_WDI_ERR("More than one instance not supported for WDI ver = %d\n",
+ ipa_wdi_ctx_list[hdl]->wdi_version);
+ return -EPERM;
+ }
+
if (ipa3_ctx->use_pm_wrapper) {
res = ipa_pm_wrapper_wdi_set_perf_profile_internal(profile);
} else {
- res = ipa_pm_set_throughput(ipa_wdi_ctx->ipa_pm_hdl,
+ res = ipa_pm_set_throughput(ipa_wdi_ctx_list[hdl]->ipa_pm_hdl,
profile->max_supported_bw_mbps);
}
@@ -828,6 +829,464 @@
return res;
}
+/**
+ * function to create smmu mapping
+ *
+ * @hdl: hdl to wdi client
+ * @num_buffers: number of buffers
+ * @info: wdi buffer info
+ */
+static int ipa_wdi_create_smmu_mapping_per_inst_internal(ipa_wdi_hdl_t hdl,
+ u32 num_buffers,
+ struct ipa_wdi_buffer_info *info)
+{
+ struct ipa_smmu_cb_ctx *cb;
+ int i;
+ int ret = 0;
+ int prot = IOMMU_READ | IOMMU_WRITE;
+
+ if (!info) {
+ IPAERR_RL("info = %pK\n", info);
+ return -EINVAL;
+ }
+
+ if (hdl < 0 || hdl >= IPA_WDI_INST_MAX) {
+ IPA_WDI_ERR("Invalid Handle %d\n",hdl);
+ return -EFAULT;
+ }
+
+ if (IPA_CLIENT_IS_WLAN0_INSTANCE(ipa_wdi_ctx_list[hdl]->inst_id))
+ cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_WLAN);
+ else
+ cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_WLAN1);
+
+ if (!cb->valid) {
+ IPA_WDI_ERR("No SMMU CB setup\n");
+ return -EINVAL;
+ }
+
+ if ((IPA_CLIENT_IS_WLAN0_INSTANCE(ipa_wdi_ctx_list[hdl]->inst_id) &&
+ ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_WLAN]) ||
+ (IPA_CLIENT_IS_WLAN1_INSTANCE(ipa_wdi_ctx_list[hdl]->inst_id) &&
+ ipa3_ctx->s1_bypass_arr[IPA_SMMU_CB_WLAN1])) {
+ IPA_WDI_ERR("IPA SMMU not enabled\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < num_buffers; i++) {
+ IPA_WDI_DBG_LOW("i=%d pa=0x%pa iova=0x%lx sz=0x%zx\n", i,
+ &info[i].pa, info[i].iova, info[i].size);
+ info[i].result = ipa3_iommu_map(cb->iommu_domain,
+ rounddown(info[i].iova, PAGE_SIZE),
+ rounddown(info[i].pa, PAGE_SIZE),
+ roundup(info[i].size + info[i].pa -
+ rounddown(info[i].pa, PAGE_SIZE), PAGE_SIZE),
+ prot);
+ }
+
+ return ret;
+}
+
+
+/**
+ * function to release smmu mapping
+ *
+ * @hdl: hdl to wdi client
+ * @num_buffers: number of buffers
+ *
+ * @info: wdi buffer info
+ */
+static int ipa_wdi_release_smmu_mapping_per_inst_internal(ipa_wdi_hdl_t hdl,
+ u32 num_buffers,
+ struct ipa_wdi_buffer_info *info)
+{
+ struct ipa_smmu_cb_ctx *cb;
+ int i;
+ int ret = 0;
+
+ if (!info) {
+ IPAERR_RL("info = %pK\n", info);
+ return -EINVAL;
+ }
+
+ if (hdl < 0 || hdl >= IPA_WDI_INST_MAX) {
+ IPA_WDI_ERR("Invalid Handle %d\n",hdl);
+ return -EFAULT;
+ }
+
+ if (IPA_CLIENT_IS_WLAN0_INSTANCE(ipa_wdi_ctx_list[hdl]->inst_id))
+ cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_WLAN);
+ else
+ cb = ipa3_get_smmu_ctx(IPA_SMMU_CB_WLAN1);
+
+ if (!cb->valid) {
+ IPA_WDI_ERR("No SMMU CB setup\n");
+ return -EINVAL;
+ }
+
+ for (i = 0; i < num_buffers; i++) {
+ IPA_WDI_DBG_LOW("i=%d pa=0x%pa iova=0x%lx sz=0x%zx\n", i,
+ &info[i].pa, info[i].iova, info[i].size);
+ info[i].result = iommu_unmap(cb->iommu_domain,
+ rounddown(info[i].iova, PAGE_SIZE),
+ roundup(info[i].size + info[i].pa -
+ rounddown(info[i].pa, PAGE_SIZE), PAGE_SIZE));
+ }
+
+ return ret;
+}
+
+/**
+ * clean up WDI IPA offload data path
+ *
+ * @hdl: hdl to wdi client
+ *
+ * @Return 0 on success, negative on failure
+ */
+static int ipa_wdi_cleanup_per_inst_internal(ipa_wdi_hdl_t hdl)
+{
+ struct ipa_wdi_intf_info *entry;
+ struct ipa_wdi_intf_info *next;
+
+ IPA_WDI_DBG("client hdl = %d, Instance = %d\n", hdl,ipa_wdi_ctx_list[hdl]->inst_id);
+ if (hdl < 0 || hdl >= IPA_WDI_INST_MAX) {
+ IPA_WDI_ERR("Invalid Handle %d\n",hdl);
+ return -EFAULT;
+ }
+
+ if (ipa_wdi_ctx_list[hdl]->wdi_version >= IPA_WDI_1 &&
+ ipa_wdi_ctx_list[hdl]->wdi_version < IPA_WDI_3 &&
+ hdl > 0) {
+ IPA_WDI_ERR("More than one instance not supported for WDI ver = %d\n",
+ ipa_wdi_ctx_list[hdl]->wdi_version);
+ return -EPERM;
+ }
+
+ /* clear interface list */
+ list_for_each_entry_safe(entry, next,
+ &ipa_wdi_ctx_list[hdl]->head_intf_list, link) {
+ list_del(&entry->link);
+ kfree(entry);
+ }
+ mutex_destroy(&ipa_wdi_ctx_list[hdl]->lock);
+ kfree(ipa_wdi_ctx_list[hdl]);
+ ipa_wdi_ctx_list[hdl] = NULL;
+ return 0;
+}
+
+/**
+ * function to deregister before unload and after disconnect
+ *
+ * @Return 0 on success, negative on failure
+ */
+static int ipa_wdi_dereg_intf_per_inst_internal(const char *netdev_name,ipa_wdi_hdl_t hdl)
+{
+ int len, ret = 0;
+ struct ipa_ioc_del_hdr *hdr = NULL;
+ struct ipa_wdi_intf_info *entry;
+ struct ipa_wdi_intf_info *next;
+
+ if (!netdev_name) {
+ IPA_WDI_ERR("no netdev name.\n");
+ return -EINVAL;
+ }
+
+ if (hdl < 0 || hdl >= IPA_WDI_INST_MAX) {
+ IPA_WDI_ERR("Invalid Handle %d\n",hdl);
+ return -EFAULT;
+ }
+
+ if (ipa_wdi_ctx_list[hdl]->wdi_version >= IPA_WDI_1 &&
+ ipa_wdi_ctx_list[hdl]->wdi_version < IPA_WDI_3 &&
+ hdl > 0) {
+ IPA_WDI_ERR("More than one instance not supported for WDI ver = %d\n",
+ ipa_wdi_ctx_list[hdl]->wdi_version);
+ return -EPERM;
+ }
+
+ if (!ipa_wdi_ctx_list[hdl]) {
+ IPA_WDI_ERR("wdi ctx is not initialized.\n");
+ return -EPERM;
+ }
+ IPA_WDI_DBG("Deregister Instance hdl %d\n",hdl);
+ mutex_lock(&ipa_wdi_ctx_list[hdl]->lock);
+ list_for_each_entry_safe(entry, next, &ipa_wdi_ctx_list[hdl]->head_intf_list,
+ link)
+ if (strcmp(entry->netdev_name, netdev_name) == 0) {
+ len = sizeof(struct ipa_ioc_del_hdr) +
+ 2 * sizeof(struct ipa_hdr_del);
+ hdr = kzalloc(len, GFP_KERNEL);
+ if (hdr == NULL) {
+ IPA_WDI_ERR("fail to alloc %d bytes\n", len);
+ mutex_unlock(&ipa_wdi_ctx_list[hdl]->lock);
+ return -ENOMEM;
+ }
+
+ hdr->commit = 1;
+ hdr->num_hdls = 2;
+ hdr->hdl[0].hdl = entry->partial_hdr_hdl[0];
+ hdr->hdl[1].hdl = entry->partial_hdr_hdl[1];
+ IPA_WDI_DBG("IPv4 hdr hdl: %d IPv6 hdr hdl: %d\n",
+ hdr->hdl[0].hdl, hdr->hdl[1].hdl);
+
+ if (ipa3_del_hdr(hdr)) {
+ IPA_WDI_ERR("fail to delete partial header\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ if (ipa3_deregister_intf(entry->netdev_name)) {
+ IPA_WDI_ERR("fail to del interface props\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+
+ list_del(&entry->link);
+ kfree(entry);
+
+ break;
+ }
+
+fail:
+ kfree(hdr);
+ mutex_unlock(&ipa_wdi_ctx_list[hdl]->lock);
+ return ret;
+}
+
+/**
+ * function to disconnect pipes
+ *
+ * @hdl: hdl to wdi client
+ * Note: Should not be called from atomic context
+ *
+ * Returns: 0 on success, negative on failure
+ */
+static int ipa_wdi_disconn_pipes_per_inst_internal(ipa_wdi_hdl_t hdl)
+{
+ int i, ipa_ep_idx_rx, ipa_ep_idx_tx;
+ int ipa_ep_idx_tx1 = IPA_EP_NOT_ALLOCATED;
+
+ if (hdl < 0 || hdl >= IPA_WDI_INST_MAX) {
+ IPA_WDI_ERR("Invalid Handle %d\n",hdl);
+ return -EFAULT;
+ }
+
+ if (ipa_wdi_ctx_list[hdl]->wdi_version >= IPA_WDI_1 &&
+ ipa_wdi_ctx_list[hdl]->wdi_version < IPA_WDI_3 &&
+ hdl > 0) {
+ IPA_WDI_ERR("More than one instance not supported for WDI ver = %d\n",
+ ipa_wdi_ctx_list[hdl]->wdi_version);
+ return -EPERM;
+ }
+
+ if (!ipa_wdi_ctx_list[hdl]) {
+ IPA_WDI_ERR("wdi ctx is not initialized\n");
+ return -EPERM;
+ }
+ IPA_WDI_DBG("Disconnect pipes for hdl %d\n",hdl);
+ /* tear down sys pipe if needed */
+ for (i = 0; i < ipa_wdi_ctx_list[hdl]->num_sys_pipe_needed; i++) {
+ if (ipa_teardown_sys_pipe(ipa_wdi_ctx_list[hdl]->sys_pipe_hdl[i])) {
+ IPA_WDI_ERR("fail to tear down sys pipe %d\n", i);
+ return -EFAULT;
+ }
+ }
+
+ if (ipa_wdi_ctx_list[hdl]->wdi_version == IPA_WDI_3) {
+ if (IPA_CLIENT_IS_WLAN0_INSTANCE(ipa_wdi_ctx_list[hdl]->inst_id)) {
+ ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_PROD);
+ ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS);
+ } else {
+ ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN3_PROD);
+ ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN4_CONS);
+ }
+
+ if (ipa_wdi_ctx_list[hdl]->is_tx1_used)
+ ipa_ep_idx_tx1 =
+ ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS1);
+ } else {
+ ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
+ ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
+ }
+
+ if (ipa_wdi_ctx_list[hdl]->wdi_version == IPA_WDI_3) {
+ if (ipa3_disconn_wdi3_pipes(
+ ipa_ep_idx_tx, ipa_ep_idx_rx, ipa_ep_idx_tx1)) {
+ IPA_WDI_ERR("fail to tear down wdi pipes\n");
+ return -EFAULT;
+ }
+ } else {
+ if (ipa3_disconnect_wdi_pipe(ipa_wdi_ctx_list[hdl]->tx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to tear down wdi tx pipes\n");
+ return -EFAULT;
+ }
+ if (ipa3_disconnect_wdi_pipe(ipa_wdi_ctx_list[hdl]->rx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to tear down wdi rx pipes\n");
+ return -EFAULT;
+ }
+ }
+
+ if (ipa_pm_deregister(ipa_wdi_ctx_list[hdl]->ipa_pm_hdl)) {
+ IPA_WDI_ERR("fail to deregister ipa pm\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+/**
+ * function to disable IPA offload data path
+ *
+ * @hdl: hdl to wdi client
+ * Note: Should not be called from atomic context
+ *
+ * Returns: 0 on success, negative on failure
+ */
+static int ipa_wdi_disable_pipes_per_inst_internal(ipa_wdi_hdl_t hdl)
+{
+ int ret;
+ int ipa_ep_idx_tx, ipa_ep_idx_rx;
+ int ipa_ep_idx_tx1 = IPA_EP_NOT_ALLOCATED;
+
+
+ if (hdl < 0 || hdl >= IPA_WDI_INST_MAX) {
+ IPA_WDI_ERR("Invalid Handle %d\n",hdl);
+ return -EFAULT;
+ }
+
+ if (ipa_wdi_ctx_list[hdl]->wdi_version >= IPA_WDI_1 &&
+ ipa_wdi_ctx_list[hdl]->wdi_version < IPA_WDI_3 &&
+ hdl > 0) {
+ IPA_WDI_ERR("More than one instance not supported for WDI ver = %d\n",
+ ipa_wdi_ctx_list[hdl]->wdi_version);
+ return -EPERM;
+ }
+
+ if (!ipa_wdi_ctx_list[hdl]) {
+ IPA_WDI_ERR("wdi ctx is not initialized.\n");
+ return -EPERM;
+ }
+
+ if (ipa_wdi_ctx_list[hdl]->wdi_version == IPA_WDI_3) {
+ if (IPA_CLIENT_IS_WLAN0_INSTANCE(ipa_wdi_ctx_list[hdl]->inst_id)) {
+ ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_PROD);
+ ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS);
+ } else {
+ ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN3_PROD);
+ ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN4_CONS);
+ }
+
+ if (ipa_wdi_ctx_list[hdl]->is_tx1_used)
+ ipa_ep_idx_tx1 =
+ ipa_get_ep_mapping(IPA_CLIENT_WLAN2_CONS1);
+ } else {
+ ipa_ep_idx_rx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_PROD);
+ ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
+ }
+
+ if (ipa_wdi_ctx_list[hdl]->wdi_version == IPA_WDI_3) {
+ if (ipa3_disable_wdi3_pipes(
+ ipa_ep_idx_tx, ipa_ep_idx_rx, ipa_ep_idx_tx1)) {
+ IPA_WDI_ERR("fail to disable wdi pipes\n");
+ return -EFAULT;
+ }
+ } else {
+ if (ipa3_suspend_wdi_pipe(ipa_wdi_ctx_list[hdl]->tx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to suspend wdi tx pipe\n");
+ return -EFAULT;
+ }
+ if (ipa3_disable_wdi_pipe(ipa_wdi_ctx_list[hdl]->tx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to disable wdi tx pipe\n");
+ return -EFAULT;
+ }
+ if (ipa3_suspend_wdi_pipe(ipa_wdi_ctx_list[hdl]->rx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to suspend wdi rx pipe\n");
+ return -EFAULT;
+ }
+ if (ipa3_disable_wdi_pipe(ipa_wdi_ctx_list[hdl]->rx_pipe_hdl)) {
+ IPA_WDI_ERR("fail to disable wdi rx pipe\n");
+ return -EFAULT;
+ }
+ }
+
+ ret = ipa_pm_deactivate_sync(ipa_wdi_ctx_list[hdl]->ipa_pm_hdl);
+ if (ret) {
+ IPA_WDI_ERR("fail to deactivate ipa pm\n");
+ return -EFAULT;
+ }
+
+ return 0;
+}
+
+static int ipa_wdi_init_internal(struct ipa_wdi_init_in_params *in,
+ struct ipa_wdi_init_out_params *out)
+{
+ if (in == NULL) {
+ IPA_WDI_ERR("invalid params in=%pK\n", in);
+ return -EINVAL;
+ }
+
+ in->inst_id = DEFAULT_INSTANCE_ID;
+ return ipa_wdi_init_per_inst_internal(in, out);
+}
+
+static int ipa_wdi_cleanup_internal(void)
+{
+ return ipa_wdi_cleanup_per_inst_internal(0);
+}
+
+static int ipa_wdi_reg_intf_internal(struct ipa_wdi_reg_intf_in_params *in)
+{
+ if (in == NULL) {
+ IPA_WDI_ERR("invalid params in=%pK\n", in);
+ return -EINVAL;
+ }
+ in->hdl = 0;
+ return ipa_wdi_reg_intf_per_inst_internal(in);
+}
+
+static int ipa_wdi_dereg_intf_internal(const char *netdev_name)
+{
+ return ipa_wdi_dereg_intf_per_inst_internal(netdev_name, 0);
+}
+
+static int ipa_wdi_conn_pipes_internal(struct ipa_wdi_conn_in_params *in,
+ struct ipa_wdi_conn_out_params *out)
+{
+ if (!(in && out)) {
+ IPA_WDI_ERR("empty parameters. in=%pK out=%pK\n", in, out);
+ return -EINVAL;
+ }
+
+ in->hdl = 0;
+ return ipa_wdi_conn_pipes_per_inst_internal(in, out);
+}
+
+static int ipa_wdi_disconn_pipes_internal(void)
+{
+ return ipa_wdi_disconn_pipes_per_inst_internal(0);
+}
+
+static int ipa_wdi_enable_pipes_internal(void)
+{
+ return ipa_wdi_enable_pipes_per_inst_internal(0);
+}
+
+static int ipa_wdi_disable_pipes_internal(void)
+{
+ return ipa_wdi_disable_pipes_per_inst_internal(0);
+}
+
+static int ipa_wdi_set_perf_profile_internal(struct ipa_wdi_perf_profile *profile)
+{
+ if (profile == NULL) {
+ IPA_WDI_ERR("Invalid input\n");
+ return -EINVAL;
+ }
+
+ return ipa_wdi_set_perf_profile_per_inst_internal(0, profile);
+}
+
void ipa_wdi3_register(void)
{
struct ipa_wdi3_data funcs;
@@ -848,6 +1307,18 @@
funcs.ipa_wdi_sw_stats = ipa3_set_wlan_tx_info;
funcs.ipa_get_wdi_version = ipa_get_wdi_version_internal;
funcs.ipa_wdi_is_tx1_used = ipa_wdi_is_tx1_used_internal;
+ funcs.ipa_wdi_get_capabilities = ipa_wdi_get_capabilities_internal;
+ funcs.ipa_wdi_init_per_inst = ipa_wdi_init_per_inst_internal;
+ funcs.ipa_wdi_cleanup_per_inst = ipa_wdi_cleanup_per_inst_internal;
+ funcs.ipa_wdi_reg_intf_per_inst = ipa_wdi_reg_intf_per_inst_internal;
+ funcs.ipa_wdi_dereg_intf_per_inst = ipa_wdi_dereg_intf_per_inst_internal;
+ funcs.ipa_wdi_conn_pipes_per_inst = ipa_wdi_conn_pipes_per_inst_internal;
+ funcs.ipa_wdi_disconn_pipes_per_inst = ipa_wdi_disconn_pipes_per_inst_internal;
+ funcs.ipa_wdi_enable_pipes_per_inst = ipa_wdi_enable_pipes_per_inst_internal;
+ funcs.ipa_wdi_disable_pipes_per_inst = ipa_wdi_disable_pipes_per_inst_internal;
+ funcs.ipa_wdi_set_perf_profile_per_inst = ipa_wdi_set_perf_profile_per_inst_internal;
+ funcs.ipa_wdi_create_smmu_mapping_per_inst = ipa_wdi_create_smmu_mapping_per_inst_internal;
+ funcs.ipa_wdi_release_smmu_mapping_per_inst = ipa_wdi_release_smmu_mapping_per_inst_internal;
if (ipa_fmwk_register_ipa_wdi3(&funcs))
pr_err("failed to register ipa_wdi3 APIs\n");
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa.c b/drivers/platform/msm/ipa/ipa_v3/ipa.c
index e9d85b4..8e335e8 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -507,7 +507,7 @@
switch (event) {
case PM_POST_SUSPEND:
#ifdef CONFIG_DEEPSLEEP
- if (mem_sleep_current == PM_SUSPEND_MEM && ipa3_ctx->deepsleep) {
+ if (pm_suspend_via_firmware() && ipa3_ctx->deepsleep) {
IPADBG("Enter deepsleep resume\n");
ipa3_deepsleep_resume();
IPADBG("Exit deepsleep resume\n");
@@ -979,6 +979,7 @@
{
return &smmu_cb[cb_type];
}
+EXPORT_SYMBOL(ipa3_get_smmu_ctx);
static int ipa3_open(struct inode *inode, struct file *filp)
{
@@ -6924,17 +6925,16 @@
}
/**
- * ipa3_inc_client_enable_clks() - Increase active clients counter, and
+ * ipa3_inc_client_enable_clks_no_log() - Increase active clients counter, and
* enable ipa clocks if necessary
*
* Return codes:
* None
*/
-void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id)
+static void ipa3_inc_client_enable_clks_no_log(void)
{
int ret;
- ipa3_active_clients_log_inc(id, false);
ret = atomic_inc_not_zero(&ipa3_ctx->ipa3_active_clients.cnt);
if (ret) {
IPADBG_LOW("active clients = %d\n",
@@ -6960,6 +6960,19 @@
atomic_read(&ipa3_ctx->ipa3_active_clients.cnt));
mutex_unlock(&ipa3_ctx->ipa3_active_clients.mutex);
}
+
+/**
+ * ipa3_inc_client_enable_clks() - Increase active clients counter and
+ * enable ipa clocks if necessary, log the caller
+ *
+ * Return codes:
+ * None
+ */
+void ipa3_inc_client_enable_clks(struct ipa_active_client_logging_info *id)
+{
+ ipa3_active_clients_log_inc(id, false);
+ ipa3_inc_client_enable_clks_no_log();
+}
EXPORT_SYMBOL(ipa3_inc_client_enable_clks);
static void ipa3_handle_gsi_differ_irq(void)
@@ -7064,7 +7077,23 @@
}
/**
- * ipa3_dec_client_disable_clks() - Decrease active clients counter
+ * ipa3_dec_client_disable_clks_no_log() - Decrease active clients counter
+ *
+ * In case that there are no active clients this function also starts
+ * TAG process. When TAG progress ends ipa clocks will be gated.
+ * start_tag_process_again flag is set during this function to signal TAG
+ * process to start again as there was another client that may send data to ipa
+ *
+ * Return codes:
+ * None
+ */
+static void ipa3_dec_client_disable_clks_no_log(void)
+{
+ __ipa3_dec_client_disable_clks();
+}
+
+/**
+ * ipa3_dec_client_disable_clks() - Decrease active clients counter and log caller
*
* In case that there are no active clients this function also starts
* TAG process. When TAG progress ends ipa clocks will be gated.
@@ -8102,6 +8131,8 @@
gsi_props.rel_clk_cb = NULL;
gsi_props.clk_status_cb = ipa3_active_clks_status;
gsi_props.enable_clk_bug_on = ipa3_handle_gsi_differ_irq;
+ gsi_props.vote_clk_cb = ipa3_inc_client_enable_clks_no_log;
+ gsi_props.unvote_clk_cb = ipa3_dec_client_disable_clks_no_log;
if (ipa3_ctx->ipa_config_is_mhi) {
gsi_props.mhi_er_id_limits_valid = true;
@@ -11708,7 +11739,7 @@
}
#ifdef CONFIG_DEEPSLEEP
- if (mem_sleep_current == PM_SUSPEND_MEM) {
+ if (pm_suspend_via_firmware()) {
IPADBG("Enter deepsleep suspend\n");
ipa3_deepsleep_suspend();
IPADBG("Exit deepsleep suspend\n");
@@ -11902,6 +11933,7 @@
return iommu_map(domain, iova, paddr, size, prot);
}
+EXPORT_SYMBOL(ipa3_iommu_map);
/**
* ipa3_get_smmu_params()- Return the ipa3 smmu related params.
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
index 470ebda..baf3c7b 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c
@@ -5467,7 +5467,9 @@
/* disable ipa_status */
sys->ep->status.status_en = false;
- if (in->client == IPA_CLIENT_APPS_WAN_COAL_CONS)
+ if (in->client == IPA_CLIENT_APPS_WAN_COAL_CONS ||
+ (in->client == IPA_CLIENT_APPS_WAN_CONS &&
+ ipa3_ctx->ipa_hw_type <= IPA_HW_v4_2))
in->ipa_ep_cfg.aggr.aggr_hard_byte_limit_en = 1;
IPADBG("set aggr_limit %lu\n", (unsigned long) *aggr_byte_limit);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 5a93158..fd44782 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -4186,7 +4186,7 @@
IPA_TX_INSTANCE_NA },
[IPA_5_0][IPA_CLIENT_WLAN3_PROD] = {
true, IPA_v5_0_GROUP_UL,
- false,
+ true,
IPA_DPS_HPS_SEQ_TYPE_2ND_PKT_PROCESS_PASS_NO_DEC_UCP,
QMB_MASTER_SELECT_DDR,
{ 1 , 0, 8, 16, IPA_EE_AP, GSI_SMART_PRE_FETCH, 2},
@@ -9362,11 +9362,13 @@
param_in->client == IPA_CLIENT_RTK_ETHERNET_PROD) {
result = ipa3_cfg_ep_metadata(ipa_ep_idx, &meta);
} else if (param_in->client == IPA_CLIENT_WLAN1_PROD ||
- param_in->client == IPA_CLIENT_WLAN2_PROD) {
+ param_in->client == IPA_CLIENT_WLAN2_PROD ||
+ param_in->client == IPA_CLIENT_WLAN3_PROD) {
ipa3_ctx->ep[ipa_ep_idx].cfg.meta = meta;
- if (param_in->client == IPA_CLIENT_WLAN2_PROD)
- result = ipa3_write_qmapid_wdi3_gsi_pipe(
- ipa_ep_idx, meta.qmap_id);
+ if (param_in->client == IPA_CLIENT_WLAN2_PROD ||
+ param_in->client == IPA_CLIENT_WLAN3_PROD)
+ result = ipa3_write_qmapid_wdi3_gsi_pipe(
+ ipa_ep_idx, meta.qmap_id);
else
result = ipa3_write_qmapid_wdi_pipe(
ipa_ep_idx, meta.qmap_id);