Merge "msm: ipa3: Fix to avoid the boot up crash in non smmu targets"
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
index 8c3be54..bb9cf79 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_mhi_client.c
@@ -2218,6 +2218,13 @@
goto fail_pm_cons;
}
+ res = ipa_pm_associate_ipa_cons_to_client(ipa_mhi_client_ctx->pm_hdl,
+ IPA_CLIENT_MHI_LOW_LAT_CONS);
+ if (res) {
+ IPA_MHI_ERR("fail to associate low_lat_cons with PM %d\n", res);
+ goto fail_pm_cons;
+ }
+
res = ipa_pm_set_throughput(ipa_mhi_client_ctx->pm_hdl, 1000);
if (res) {
IPA_MHI_ERR("fail to set perf profile to PM %d\n", res);
diff --git a/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c b/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c
index d12bbd0..f911cc8 100644
--- a/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c
+++ b/drivers/platform/msm/ipa/ipa_clients/ipa_wdi3.c
@@ -1,7 +1,6 @@
// 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>
@@ -40,13 +39,6 @@
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;
@@ -66,68 +58,100 @@
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_list[IPA_WDI_INST_MAX];
+static struct ipa_wdi_context *ipa_wdi_ctx;
-/**
- * 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)
+static int ipa_wdi_init_internal(struct ipa_wdi_init_in_params *in,
+ struct ipa_wdi_init_out_params *out)
{
- int hdl;
+ struct ipa_wdi_uc_ready_params uc_ready_params;
+ struct ipa_smmu_in_params smmu_in;
+ struct ipa_smmu_out_params smmu_out;
- 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 (ipa_wdi_ctx) {
+ IPA_WDI_ERR("ipa_wdi_ctx was initialized before\n");
+ return -EFAULT;
}
- return hdl;
+ 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;
}
static int ipa_get_wdi_version_internal(void)
{
- if (ipa_wdi_ctx_list[0])
- return ipa_wdi_ctx_list[0]->wdi_version;
+ if (ipa_wdi_ctx)
+ return ipa_wdi_ctx->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_list[0])
- return ipa_wdi_ctx_list[0]->is_tx1_used;
+ if (ipa_wdi_ctx)
+ return ipa_wdi_ctx->is_tx1_used;
return 0;
}
-static void ipa_wdi_pm_cb(void *p, enum ipa_pm_cb_event event)
+static int ipa_wdi_cleanup_internal(void)
{
- IPA_WDI_DBG("received pm event %d\n", 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;
}
static int ipa_wdi_commit_partial_hdr(
@@ -166,114 +190,7 @@
return 0;
}
-/**
- * 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)
+static int ipa_wdi_reg_intf_internal(struct ipa_wdi_reg_intf_in_params *in)
{
struct ipa_ioc_add_hdr *hdr;
struct ipa_wdi_intf_info *new_intf;
@@ -290,32 +207,19 @@
return -EINVAL;
}
- 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]) {
+ if (!ipa_wdi_ctx) {
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_list[in->hdl]->lock);
- list_for_each_entry(entry, &ipa_wdi_ctx_list[in->hdl]->head_intf_list, link)
+ mutex_lock(&ipa_wdi_ctx->lock);
+ list_for_each_entry(entry, &ipa_wdi_ctx->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_list[in->hdl]->lock);
+ mutex_unlock(&ipa_wdi_ctx->lock);
return 0;
}
@@ -329,7 +233,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_list[in->hdl]->lock);
+ mutex_unlock(&ipa_wdi_ctx->lock);
return -ENOMEM;
}
@@ -361,16 +265,14 @@
/* 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 if (IPA_CLIENT_IS_WLAN0_INSTANCE(ipa_wdi_ctx_list[in->hdl]->inst_id))
- tx_prop[0].dst_pipe = IPA_CLIENT_WLAN2_CONS;
+ tx_prop[0].dst_pipe = IPA_CLIENT_WLAN2_CONS1;
else
- tx_prop[0].dst_pipe = IPA_CLIENT_WLAN4_CONS;
+ tx_prop[0].dst_pipe = IPA_CLIENT_WLAN2_CONS;
}
else
tx_prop[0].dst_pipe = IPA_CLIENT_WLAN1_CONS;
@@ -383,10 +285,8 @@
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 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;
+ tx_prop[1].dst_pipe = IPA_CLIENT_WLAN2_CONS;
}
else
tx_prop[1].dst_pipe = IPA_CLIENT_WLAN1_CONS;
@@ -400,14 +300,10 @@
rx.prop = rx_prop;
memset(rx_prop, 0, sizeof(rx_prop));
rx_prop[0].ip = IPA_IP_v4;
- 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 {
+ if (ipa_wdi_ctx->wdi_version == IPA_WDI_3)
+ rx_prop[0].src_pipe = IPA_CLIENT_WLAN2_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;
@@ -416,570 +312,39 @@
}
rx_prop[1].ip = IPA_IP_v6;
- 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 {
+ if (ipa_wdi_ctx->wdi_version == IPA_WDI_3)
+ rx_prop[1].src_pipe = IPA_CLIENT_WLAN2_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;
}
- 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);
+
+ list_add(&new_intf->link, &ipa_wdi_ctx->head_intf_list);
+ init_completion(&ipa_wdi_ctx->wdi_completion);
kfree(hdr);
- mutex_unlock(&ipa_wdi_ctx_list[in->hdl]->lock);
+ mutex_unlock(&ipa_wdi_ctx->lock);
return 0;
fail_commit_hdr:
kfree(hdr);
fail_alloc_hdr:
kfree(new_intf);
- mutex_unlock(&ipa_wdi_ctx_list[in->hdl]->lock);
+ mutex_unlock(&ipa_wdi_ctx->lock);
return ret;
}
-/**
- * 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;
- struct ipa_wdi_in_params in_tx;
- struct ipa_wdi_in_params in_rx;
- struct ipa_wdi_out_params out_tx;
- struct ipa_wdi_out_params out_rx;
- int ipa_ep_idx_tx1 = IPA_EP_NOT_ALLOCATED;
-
- if (!(in && out)) {
- IPA_WDI_ERR("empty parameters. in=%pK out=%pK\n", in, out);
- return -EINVAL;
- }
-
- 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_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_list[in->hdl]->is_tx1_used = in->is_tx1_used;
- } else
- 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 < in->num_sys_pipe_needed; i++) {
- ret = ipa_setup_sys_pipe(&in->sys_in[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;
- goto fail_setup_sys_pipe;
- }
- }
-
- memset(&pm_params, 0, sizeof(pm_params));
- 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_list[in->hdl]->ipa_pm_hdl)) {
- IPA_WDI_ERR("fail to register ipa pm\n");
- ret = -EFAULT;
- goto fail_setup_sys_pipe;
- }
- 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;
- }
- } else {
- memset(&in_tx, 0, sizeof(in_tx));
- memset(&in_rx, 0, sizeof(in_rx));
- 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_list[in->hdl]->wdi_notify;
-#endif
- if (in->is_smmu_enabled == false) {
- /* firsr setup rx pipe */
- in_rx.sys.ipa_ep_cfg = in->u_rx.rx.ipa_ep_cfg;
- in_rx.sys.client = in->u_rx.rx.client;
- in_rx.sys.notify = in->notify;
- in_rx.sys.priv = in->priv;
- in_rx.smmu_enabled = in->is_smmu_enabled;
- in_rx.u.ul.rdy_ring_base_pa =
- in->u_rx.rx.transfer_ring_base_pa;
- in_rx.u.ul.rdy_ring_size =
- in->u_rx.rx.transfer_ring_size;
- in_rx.u.ul.rdy_ring_rp_pa =
- in->u_rx.rx.transfer_ring_doorbell_pa;
- in_rx.u.ul.rdy_comp_ring_base_pa =
- in->u_rx.rx.event_ring_base_pa;
- in_rx.u.ul.rdy_comp_ring_wp_pa =
- in->u_rx.rx.event_ring_doorbell_pa;
- in_rx.u.ul.rdy_comp_ring_size =
- in->u_rx.rx.event_ring_size;
- in_rx.u.ul.is_txr_rn_db_pcie_addr =
- in->u_rx.rx.is_txr_rn_db_pcie_addr;
- in_rx.u.ul.is_evt_rn_db_pcie_addr =
- in->u_rx.rx.is_evt_rn_db_pcie_addr;
- if (ipa3_connect_wdi_pipe(&in_rx, &out_rx)) {
- IPA_WDI_ERR("fail to setup rx pipe\n");
- ret = -EFAULT;
- goto fail_connect_pipe;
- }
- 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);
-
- /* then setup tx pipe */
- in_tx.sys.ipa_ep_cfg = in->u_tx.tx.ipa_ep_cfg;
- in_tx.sys.client = in->u_tx.tx.client;
- in_tx.smmu_enabled = in->is_smmu_enabled;
- in_tx.u.dl.comp_ring_base_pa =
- in->u_tx.tx.transfer_ring_base_pa;
- in_tx.u.dl.comp_ring_size =
- in->u_tx.tx.transfer_ring_size;
- in_tx.u.dl.ce_ring_base_pa =
- in->u_tx.tx.event_ring_base_pa;
- in_tx.u.dl.ce_door_bell_pa =
- in->u_tx.tx.event_ring_doorbell_pa;
- in_tx.u.dl.ce_ring_size =
- in->u_tx.tx.event_ring_size;
- in_tx.u.dl.num_tx_buffers =
- in->u_tx.tx.num_pkt_buffers;
- in_tx.u.dl.is_txr_rn_db_pcie_addr =
- in->u_tx.tx.is_txr_rn_db_pcie_addr;
- in_tx.u.dl.is_evt_rn_db_pcie_addr =
- in->u_tx.tx.is_evt_rn_db_pcie_addr;
- if (ipa3_connect_wdi_pipe(&in_tx, &out_tx)) {
- IPA_WDI_ERR("fail to setup tx pipe\n");
- ret = -EFAULT;
- goto fail;
- }
- 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 */
- /* firsr setup rx pipe */
- in_rx.sys.ipa_ep_cfg = in->u_rx.rx_smmu.ipa_ep_cfg;
- in_rx.sys.client = in->u_rx.rx_smmu.client;
- in_rx.sys.notify = in->notify;
- in_rx.sys.priv = in->priv;
- in_rx.smmu_enabled = in->is_smmu_enabled;
- in_rx.u.ul_smmu.rdy_ring =
- in->u_rx.rx_smmu.transfer_ring_base;
- in_rx.u.ul_smmu.rdy_ring_size =
- in->u_rx.rx_smmu.transfer_ring_size;
- in_rx.u.ul_smmu.rdy_ring_rp_pa =
- in->u_rx.rx_smmu.transfer_ring_doorbell_pa;
- in_rx.u.ul_smmu.rdy_comp_ring =
- in->u_rx.rx_smmu.event_ring_base;
- in_rx.u.ul_smmu.rdy_comp_ring_wp_pa =
- in->u_rx.rx_smmu.event_ring_doorbell_pa;
- in_rx.u.ul_smmu.rdy_comp_ring_size =
- in->u_rx.rx_smmu.event_ring_size;
- in_rx.u.ul_smmu.is_txr_rn_db_pcie_addr =
- in->u_rx.rx_smmu.is_txr_rn_db_pcie_addr;
- in_rx.u.ul_smmu.is_evt_rn_db_pcie_addr =
- in->u_rx.rx_smmu.is_evt_rn_db_pcie_addr;
- if (ipa3_connect_wdi_pipe(&in_rx, &out_rx)) {
- IPA_WDI_ERR("fail to setup rx pipe\n");
- ret = -EFAULT;
- goto fail_connect_pipe;
- }
- 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);
-
- /* then setup tx pipe */
- in_tx.sys.ipa_ep_cfg = in->u_tx.tx_smmu.ipa_ep_cfg;
- in_tx.sys.client = in->u_tx.tx_smmu.client;
- in_tx.smmu_enabled = in->is_smmu_enabled;
- in_tx.u.dl_smmu.comp_ring =
- in->u_tx.tx_smmu.transfer_ring_base;
- in_tx.u.dl_smmu.comp_ring_size =
- in->u_tx.tx_smmu.transfer_ring_size;
- in_tx.u.dl_smmu.ce_ring =
- in->u_tx.tx_smmu.event_ring_base;
- in_tx.u.dl_smmu.ce_door_bell_pa =
- in->u_tx.tx_smmu.event_ring_doorbell_pa;
- in_tx.u.dl_smmu.ce_ring_size =
- in->u_tx.tx_smmu.event_ring_size;
- in_tx.u.dl_smmu.num_tx_buffers =
- in->u_tx.tx_smmu.num_pkt_buffers;
- in_tx.u.dl_smmu.is_txr_rn_db_pcie_addr =
- in->u_tx.tx_smmu.is_txr_rn_db_pcie_addr;
- in_tx.u.dl_smmu.is_evt_rn_db_pcie_addr =
- in->u_tx.tx_smmu.is_evt_rn_db_pcie_addr;
- if (ipa3_connect_wdi_pipe(&in_tx, &out_tx)) {
- IPA_WDI_ERR("fail to setup tx pipe\n");
- ret = -EFAULT;
- goto fail;
- }
- 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_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_list[in->hdl]->rx_pipe_hdl);
-fail_connect_pipe:
- 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_list[in->hdl]->sys_pipe_hdl[j]);
- return ret;
-}
-
-/**
- * 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 (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_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 {
- 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_ep_idx_tx <= 0 || ipa_ep_idx_rx <= 0)
- return -EFAULT;
- 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;
- }
- 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_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_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_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_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_list[hdl]->rx_pipe_hdl)) {
- IPA_WDI_ERR("fail to resume wdi rx pipe\n");
- return -EFAULT;
- }
- }
-
- return 0;
-}
-
-/**
- * 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_list[hdl]->ipa_pm_hdl,
- profile->max_supported_bw_mbps);
- }
-
- if (res) {
- IPA_WDI_ERR("fail to set pm throughput\n");
- return -EFAULT;
- }
-
- 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)
+static int ipa_wdi_dereg_intf_internal(const char *netdev_name)
{
int len, ret = 0;
struct ipa_ioc_del_hdr *hdr = NULL;
@@ -991,26 +356,13 @@
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]) {
+ if (!ipa_wdi_ctx) {
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,
+
+ 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) +
@@ -1018,7 +370,7 @@
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);
+ mutex_unlock(&ipa_wdi_ctx->lock);
return -ENOMEM;
}
@@ -1049,59 +401,255 @@
fail:
kfree(hdr);
- mutex_unlock(&ipa_wdi_ctx_list[hdl]->lock);
+ mutex_unlock(&ipa_wdi_ctx->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)
+
+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)
+{
+ int i, j, ret = 0;
+ struct ipa_pm_register_params pm_params;
+ struct ipa_wdi_in_params in_tx;
+ struct ipa_wdi_in_params in_rx;
+ struct ipa_wdi_out_params out_tx;
+ struct ipa_wdi_out_params out_rx;
+ int ipa_ep_idx_tx1 = IPA_EP_NOT_ALLOCATED;
+
+ if (!(in && out)) {
+ IPA_WDI_ERR("empty parameters. in=%pK out=%pK\n", in, out);
+ return -EINVAL;
+ }
+
+ if (!ipa_wdi_ctx) {
+ IPA_WDI_ERR("wdi ctx is not initialized\n");
+ 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_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;
+ } else
+ ipa_wdi_ctx->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++) {
+ ret = ipa_setup_sys_pipe(&in->sys_in[i],
+ &ipa_wdi_ctx->sys_pipe_hdl[i]);
+ if (ret) {
+ IPA_WDI_ERR("fail to setup sys pipe %d\n", i);
+ ret = -EFAULT;
+ goto fail_setup_sys_pipe;
+ }
+ }
+
+ memset(&pm_params, 0, sizeof(pm_params));
+ pm_params.name = "wdi";
+ 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)) {
+ 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_ERR("fail to setup wdi pipes\n");
+ ret = -EFAULT;
+ goto fail_connect_pipe;
+ }
+ } else {
+ memset(&in_tx, 0, sizeof(in_tx));
+ memset(&in_rx, 0, sizeof(in_rx));
+ 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;
+#endif
+ if (in->is_smmu_enabled == false) {
+ /* firsr setup rx pipe */
+ in_rx.sys.ipa_ep_cfg = in->u_rx.rx.ipa_ep_cfg;
+ in_rx.sys.client = in->u_rx.rx.client;
+ in_rx.sys.notify = in->notify;
+ in_rx.sys.priv = in->priv;
+ in_rx.smmu_enabled = in->is_smmu_enabled;
+ in_rx.u.ul.rdy_ring_base_pa =
+ in->u_rx.rx.transfer_ring_base_pa;
+ in_rx.u.ul.rdy_ring_size =
+ in->u_rx.rx.transfer_ring_size;
+ in_rx.u.ul.rdy_ring_rp_pa =
+ in->u_rx.rx.transfer_ring_doorbell_pa;
+ in_rx.u.ul.rdy_comp_ring_base_pa =
+ in->u_rx.rx.event_ring_base_pa;
+ in_rx.u.ul.rdy_comp_ring_wp_pa =
+ in->u_rx.rx.event_ring_doorbell_pa;
+ in_rx.u.ul.rdy_comp_ring_size =
+ in->u_rx.rx.event_ring_size;
+ in_rx.u.ul.is_txr_rn_db_pcie_addr =
+ in->u_rx.rx.is_txr_rn_db_pcie_addr;
+ in_rx.u.ul.is_evt_rn_db_pcie_addr =
+ in->u_rx.rx.is_evt_rn_db_pcie_addr;
+ if (ipa3_connect_wdi_pipe(&in_rx, &out_rx)) {
+ IPA_WDI_ERR("fail to setup rx pipe\n");
+ ret = -EFAULT;
+ goto fail_connect_pipe;
+ }
+ ipa_wdi_ctx->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);
+
+ /* then setup tx pipe */
+ in_tx.sys.ipa_ep_cfg = in->u_tx.tx.ipa_ep_cfg;
+ in_tx.sys.client = in->u_tx.tx.client;
+ in_tx.smmu_enabled = in->is_smmu_enabled;
+ in_tx.u.dl.comp_ring_base_pa =
+ in->u_tx.tx.transfer_ring_base_pa;
+ in_tx.u.dl.comp_ring_size =
+ in->u_tx.tx.transfer_ring_size;
+ in_tx.u.dl.ce_ring_base_pa =
+ in->u_tx.tx.event_ring_base_pa;
+ in_tx.u.dl.ce_door_bell_pa =
+ in->u_tx.tx.event_ring_doorbell_pa;
+ in_tx.u.dl.ce_ring_size =
+ in->u_tx.tx.event_ring_size;
+ in_tx.u.dl.num_tx_buffers =
+ in->u_tx.tx.num_pkt_buffers;
+ in_tx.u.dl.is_txr_rn_db_pcie_addr =
+ in->u_tx.tx.is_txr_rn_db_pcie_addr;
+ in_tx.u.dl.is_evt_rn_db_pcie_addr =
+ in->u_tx.tx.is_evt_rn_db_pcie_addr;
+ if (ipa3_connect_wdi_pipe(&in_tx, &out_tx)) {
+ IPA_WDI_ERR("fail to setup tx pipe\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+ ipa_wdi_ctx->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 */
+ /* firsr setup rx pipe */
+ in_rx.sys.ipa_ep_cfg = in->u_rx.rx_smmu.ipa_ep_cfg;
+ in_rx.sys.client = in->u_rx.rx_smmu.client;
+ in_rx.sys.notify = in->notify;
+ in_rx.sys.priv = in->priv;
+ in_rx.smmu_enabled = in->is_smmu_enabled;
+ in_rx.u.ul_smmu.rdy_ring =
+ in->u_rx.rx_smmu.transfer_ring_base;
+ in_rx.u.ul_smmu.rdy_ring_size =
+ in->u_rx.rx_smmu.transfer_ring_size;
+ in_rx.u.ul_smmu.rdy_ring_rp_pa =
+ in->u_rx.rx_smmu.transfer_ring_doorbell_pa;
+ in_rx.u.ul_smmu.rdy_comp_ring =
+ in->u_rx.rx_smmu.event_ring_base;
+ in_rx.u.ul_smmu.rdy_comp_ring_wp_pa =
+ in->u_rx.rx_smmu.event_ring_doorbell_pa;
+ in_rx.u.ul_smmu.rdy_comp_ring_size =
+ in->u_rx.rx_smmu.event_ring_size;
+ in_rx.u.ul_smmu.is_txr_rn_db_pcie_addr =
+ in->u_rx.rx_smmu.is_txr_rn_db_pcie_addr;
+ in_rx.u.ul_smmu.is_evt_rn_db_pcie_addr =
+ in->u_rx.rx_smmu.is_evt_rn_db_pcie_addr;
+ if (ipa3_connect_wdi_pipe(&in_rx, &out_rx)) {
+ IPA_WDI_ERR("fail to setup rx pipe\n");
+ ret = -EFAULT;
+ goto fail_connect_pipe;
+ }
+ ipa_wdi_ctx->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);
+
+ /* then setup tx pipe */
+ in_tx.sys.ipa_ep_cfg = in->u_tx.tx_smmu.ipa_ep_cfg;
+ in_tx.sys.client = in->u_tx.tx_smmu.client;
+ in_tx.smmu_enabled = in->is_smmu_enabled;
+ in_tx.u.dl_smmu.comp_ring =
+ in->u_tx.tx_smmu.transfer_ring_base;
+ in_tx.u.dl_smmu.comp_ring_size =
+ in->u_tx.tx_smmu.transfer_ring_size;
+ in_tx.u.dl_smmu.ce_ring =
+ in->u_tx.tx_smmu.event_ring_base;
+ in_tx.u.dl_smmu.ce_door_bell_pa =
+ in->u_tx.tx_smmu.event_ring_doorbell_pa;
+ in_tx.u.dl_smmu.ce_ring_size =
+ in->u_tx.tx_smmu.event_ring_size;
+ in_tx.u.dl_smmu.num_tx_buffers =
+ in->u_tx.tx_smmu.num_pkt_buffers;
+ in_tx.u.dl_smmu.is_txr_rn_db_pcie_addr =
+ in->u_tx.tx_smmu.is_txr_rn_db_pcie_addr;
+ in_tx.u.dl_smmu.is_evt_rn_db_pcie_addr =
+ in->u_tx.tx_smmu.is_evt_rn_db_pcie_addr;
+ if (ipa3_connect_wdi_pipe(&in_tx, &out_tx)) {
+ IPA_WDI_ERR("fail to setup tx pipe\n");
+ ret = -EFAULT;
+ goto fail;
+ }
+ ipa_wdi_ctx->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);
+ 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);
+ }
+ }
+
+ return 0;
+
+fail:
+ ipa3_disconnect_wdi_pipe(ipa_wdi_ctx->rx_pipe_hdl);
+fail_connect_pipe:
+ ipa_pm_deregister(ipa_wdi_ctx->ipa_pm_hdl);
+
+fail_setup_sys_pipe:
+ for (j = 0; j < i; j++)
+ ipa_teardown_sys_pipe(ipa_wdi_ctx->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 (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]) {
+ if (!ipa_wdi_ctx) {
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])) {
+ 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_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)
+ 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 {
@@ -1109,24 +657,24 @@
ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
}
- if (ipa_wdi_ctx_list[hdl]->wdi_version == IPA_WDI_3) {
+ 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_list[hdl]->tx_pipe_hdl)) {
+ 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_list[hdl]->rx_pipe_hdl)) {
+ 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_list[hdl]->ipa_pm_hdl)) {
+ if (ipa_pm_deregister(ipa_wdi_ctx->ipa_pm_hdl)) {
IPA_WDI_ERR("fail to deregister ipa pm\n");
return -EFAULT;
}
@@ -1134,49 +682,21 @@
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)
+static int ipa_wdi_enable_pipes_internal(void)
{
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]) {
+ if (!ipa_wdi_ctx) {
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)
+ 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 {
@@ -1184,32 +704,98 @@
ipa_ep_idx_tx = ipa_get_ep_mapping(IPA_CLIENT_WLAN1_CONS);
}
- if (ipa_wdi_ctx_list[hdl]->wdi_version == IPA_WDI_3) {
+ if (ipa_ep_idx_tx <= 0 || ipa_ep_idx_rx <= 0)
+ return -EFAULT;
+
+ ret = ipa_pm_activate_sync(ipa_wdi_ctx->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) {
+ 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)) {
+ IPA_WDI_ERR("pipe handle not valid\n");
+ return -EFAULT;
+ }
+ if (ipa3_enable_wdi_pipe(ipa_wdi_ctx->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)) {
+ IPA_WDI_ERR("fail to resume wdi tx pipe\n");
+ return -EFAULT;
+ }
+ if (ipa3_enable_wdi_pipe(ipa_wdi_ctx->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)) {
+ IPA_WDI_ERR("fail to resume wdi rx pipe\n");
+ return -EFAULT;
+ }
+ }
+
+ 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_list[hdl]->tx_pipe_hdl)) {
+ 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_list[hdl]->tx_pipe_hdl)) {
+ 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_list[hdl]->rx_pipe_hdl)) {
+ 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_list[hdl]->rx_pipe_hdl)) {
+ 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_list[hdl]->ipa_pm_hdl);
+ ret = ipa_pm_deactivate_sync(ipa_wdi_ctx->ipa_pm_hdl);
if (ret) {
IPA_WDI_ERR("fail to deactivate ipa pm\n");
return -EFAULT;
@@ -1218,73 +804,28 @@
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)
{
+ int res = 0;
+
if (profile == NULL) {
IPA_WDI_ERR("Invalid input\n");
return -EINVAL;
}
- return ipa_wdi_set_perf_profile_per_inst_internal(0, profile);
+ 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,
+ profile->max_supported_bw_mbps);
+ }
+
+ if (res) {
+ IPA_WDI_ERR("fail to set pm throughput\n");
+ return -EFAULT;
+ }
+
+ return res;
}
void ipa_wdi3_register(void)
@@ -1307,18 +848,6 @@
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 6a9973a..cc539a9 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa.c
@@ -6932,7 +6932,8 @@
pipe_bitmask |= bmsk;
bmsk = bmsk << 1;
- if ((i % IPA_EP_PER_REG) == (ep_per_reg - 1)) {
+ if ((i % IPA_EP_PER_REG) == (ep_per_reg - 1)
+ || (i == ipa3_ctx->ipa_num_pipes - 1)) {
IPADBG("interrupt data: %u\n", suspend_data[j]);
res = ipa_pm_handle_suspend(pipe_bitmask, j);
if (res) {
@@ -9287,7 +9288,10 @@
ipa3_clk = NULL;
fail_bus_reg:
for (i = 0; i < ipa3_ctx->icc_num_paths; i++)
- if (ipa3_ctx->ctrl->icc_path[i]) {
+ if (IS_ERR_OR_NULL(ipa3_ctx->ctrl->icc_path[i])) {
+ ipa3_ctx->ctrl->icc_path[i] = NULL;
+ break;
+ } else {
icc_put(ipa3_ctx->ctrl->icc_path[i]);
ipa3_ctx->ctrl->icc_path[i] = NULL;
}
@@ -9299,8 +9303,10 @@
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;
@@ -10705,6 +10711,8 @@
}
}
} 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;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
index 0f95e4d..a9744ff 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_hdr.c
@@ -543,12 +543,13 @@
static int __ipa_add_hdr(struct ipa_hdr_add *hdr, bool user,
struct ipa3_hdr_entry **entry_out)
{
- struct ipa3_hdr_entry *entry;
+ struct ipa3_hdr_entry *entry, *entry_t, *next;
struct ipa_hdr_offset_entry *offset = NULL;
u32 bin;
struct ipa3_hdr_tbl *htbl;
int id;
int mem_size;
+ enum hdr_tbl_storage hdr_tbl_loc;
if (hdr->hdr_len > IPA_HDR_MAX_SIZE) {
IPAERR_RL("bad param\n");
@@ -579,6 +580,26 @@
(entry->is_partial || (hdr->status == IPA_HDR_TO_DDR_PATTERN))) ||
!IPA_MEM_PART(apps_hdr_size)) ? false : true;
+ /* check to see if adding header entry with duplicate name */
+ for (hdr_tbl_loc = HDR_TBL_LCL; hdr_tbl_loc < HDR_TBLS_TOTAL; hdr_tbl_loc++) {
+ list_for_each_entry_safe(entry_t, next,
+ &ipa3_ctx->hdr_tbl[hdr_tbl_loc].head_hdr_entry_list, link) {
+
+ /* return if adding the same name */
+ if (!strcmp(entry_t->name, entry->name) && (user == true)) {
+ IPAERR("IPACM Trying to add hdr %s len=%d, duplicate entry, return old one\n",
+ entry->name, entry->hdr_len);
+
+ /* return the original entry */
+ if (entry_out)
+ *entry_out = entry_t;
+
+ kmem_cache_free(ipa3_ctx->hdr_cache, entry);
+ return 0;
+ }
+ }
+ }
+
if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN0])
bin = IPA_HDR_BIN0;
else if (hdr->hdr_len <= ipa_hdr_bin_sz[IPA_HDR_BIN1])
@@ -616,11 +637,20 @@
mem_size = IPA_MEM_PART(apps_hdr_size_ddr);
entry->is_lcl = false;
} else {
- /* if the entry is intended to be in DDR,
- and there is no space -> error */
- IPAERR("No space in DDR header buffer! Requested: %d Left: %d\n",
- ipa_hdr_bin_sz[bin], mem_size - htbl->end);
- goto bad_hdr_len;
+ /* check if DDR free list */
+ if (list_empty(&htbl->head_free_offset_list[bin])) {
+ IPAERR("No space in DDR header buffer! Requested: %d Left: %d name %s, end %d\n",
+ ipa_hdr_bin_sz[bin], mem_size - htbl->end, entry->name, htbl->end);
+ goto bad_hdr_len;
+ } else {
+ /* get the first free slot */
+ offset = list_first_entry(&htbl->head_free_offset_list[bin],
+ struct ipa_hdr_offset_entry, link);
+ list_move(&offset->link, &htbl->head_offset_list[bin]);
+ entry->offset_entry = offset;
+ offset->ipacm_installed = user;
+ goto free_list;
+ }
}
}
offset = kmem_cache_zalloc(ipa3_ctx->hdr_offset_cache,
@@ -650,6 +680,8 @@
offset->ipacm_installed = user;
}
+free_list:
+
list_add(&entry->link, &htbl->head_hdr_entry_list);
htbl->hdr_cnt++;
IPADBG("add hdr of sz=%d hdr_cnt=%d ofst=%d to %s table\n",
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c b/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c
index 3726355..2123327 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_odl.c
@@ -372,6 +372,11 @@
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;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
index 13daaac..0c56410 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_utils.c
@@ -1,7 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2012-2021, The Linux Foundation. All rights reserved.
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <net/ip.h>
@@ -4144,7 +4143,7 @@
IPA_TX_INSTANCE_NA },
[IPA_5_0][IPA_CLIENT_WLAN3_PROD] = {
true, IPA_v5_0_GROUP_UL,
- true,
+ false,
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},
@@ -8668,13 +8667,11 @@
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_WLAN3_PROD) {
+ param_in->client == IPA_CLIENT_WLAN2_PROD) {
ipa3_ctx->ep[ipa_ep_idx].cfg.meta = meta;
- 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);
+ if (param_in->client == IPA_CLIENT_WLAN2_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);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
index c16ea49..411e798 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include <linux/debugfs.h>
@@ -50,6 +51,8 @@
__stringify(IPAHAL_PKT_STATUS_EXCEPTION_NAT),
__stringify(IPAHAL_PKT_STATUS_EXCEPTION_IPV6CT),
__stringify(IPAHAL_PKT_STATUS_EXCEPTION_UCP),
+ __stringify(IPAHAL_PKT_STATUS_EXCEPTION_INVALID_PIPE),
+ __stringify(IPAHAL_PKT_STATUS_EXCEPTION_HDRI),
__stringify(IPAHAL_PKT_STATUS_EXCEPTION_CSUM),
};
@@ -1164,8 +1167,14 @@
exception_type = IPAHAL_PKT_STATUS_EXCEPTION_NAT;
break;
case 128:
- exception_type = IPAHAL_PKT_STATUS_EXCEPTION_UCP;
- break;
+ exception_type = IPAHAL_PKT_STATUS_EXCEPTION_UCP;
+ break;
+ case 129:
+ exception_type = IPAHAL_PKT_STATUS_EXCEPTION_INVALID_PIPE;
+ break;
+ case 136:
+ exception_type = IPAHAL_PKT_STATUS_EXCEPTION_HDRI;
+ break;
case 229:
exception_type = IPAHAL_PKT_STATUS_EXCEPTION_CSUM;
break;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
index db5de06..05ff186 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
+ * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#ifndef _IPAHAL_H_
@@ -522,6 +523,8 @@
IPAHAL_PKT_STATUS_EXCEPTION_NAT,
IPAHAL_PKT_STATUS_EXCEPTION_IPV6CT,
IPAHAL_PKT_STATUS_EXCEPTION_UCP,
+ IPAHAL_PKT_STATUS_EXCEPTION_INVALID_PIPE,
+ IPAHAL_PKT_STATUS_EXCEPTION_HDRI,
IPAHAL_PKT_STATUS_EXCEPTION_CSUM,
IPAHAL_PKT_STATUS_EXCEPTION_MAX,
};