From 528d18939cfc2c8bb27db4a4cfebcd0d332ed627 Mon Sep 17 00:00:00 2001 From: Michael Adisumarta Date: Mon, 1 Feb 2021 17:45:49 -0800 Subject: [PATCH] msm: ipa3: adding new wwan extended_v2 ioctl To support setting up ingress and egress ioctl parameters from netmngr Change-Id: Ib5aa503c951e6650e34dfa6ee501390a82967ab6 Signed-off-by: Michael Adisumarta --- drivers/platform/msm/ipa/ipa_v3/ipa_dp.c | 54 +- drivers/platform/msm/ipa/ipa_v3/ipa_i.h | 14 +- .../platform/msm/ipa/ipa_v3/rmnet_ctl_ipa.c | 97 ++- drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c | 612 +++++++++++++++++- 4 files changed, 738 insertions(+), 39 deletions(-) diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c index 85dceb89a3..6061ce1437 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_dp.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-only /* - * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2021, The Linux Foundation. All rights reserved. */ #include @@ -11,6 +11,7 @@ #include #include #include +#include #include "gsi.h" #include "ipa_i.h" #include "ipa_trace.h" @@ -98,7 +99,7 @@ static void ipa3_replenish_rx_page_cache(struct ipa3_sys_context *sys); static void ipa3_wq_page_repl(struct work_struct *work); static void ipa3_replenish_rx_page_recycle(struct ipa3_sys_context *sys); static struct ipa3_rx_pkt_wrapper *ipa3_alloc_rx_pkt_page(gfp_t flag, - bool is_tmp_alloc); + bool is_tmp_alloc, struct ipa3_sys_context *sys); static void ipa3_wq_handle_rx(struct work_struct *work); static void ipa3_wq_rx_common(struct ipa3_sys_context *sys, struct gsi_chan_xfer_notify *notify); @@ -1209,6 +1210,10 @@ int ipa3_setup_sys_pipe(struct ipa_sys_connect_params *sys_in, u32 *clnt_hdl) ep->client = sys_in->client; ep->client_notify = sys_in->notify; ep->sys->napi_obj = sys_in->napi_obj; + ep->sys->ext_ioctl_v2 = sys_in->ext_ioctl_v2; + ep->sys->int_modt = sys_in->int_modt; + ep->sys->int_modc = sys_in->int_modc; + ep->sys->buff_size = sys_in->buff_size; ep->priv = sys_in->priv; ep->keep_ipa_awake = sys_in->keep_ipa_awake; atomic_set(&ep->avail_fifo_desc, @@ -1355,9 +1360,11 @@ int ipa3_setup_sys_pipe(struct ipa_sys_connect_params *sys_in, u32 *clnt_hdl) qmap_cfg.mux_id_byte_sel = IPA_QMAP_ID_BYTE; ipahal_write_reg_fields(IPA_COAL_QMAP_CFG, &qmap_cfg); - sys_in->client = IPA_CLIENT_APPS_WAN_CONS; - sys_in->ipa_ep_cfg = ep_cfg_copy; - result = ipa3_setup_sys_pipe(sys_in, &wan_handle); + if (!sys_in->ext_ioctl_v2) { + sys_in->client = IPA_CLIENT_APPS_WAN_CONS; + sys_in->ipa_ep_cfg = ep_cfg_copy; + result = ipa3_setup_sys_pipe(sys_in, &wan_handle); + } if (result) { IPAERR("failed to setup default coalescing pipe\n"); goto fail_repl; @@ -2021,7 +2028,7 @@ fail_kmem_cache_alloc: } static struct ipa3_rx_pkt_wrapper *ipa3_alloc_rx_pkt_page( - gfp_t flag, bool is_tmp_alloc) + gfp_t flag, bool is_tmp_alloc, struct ipa3_sys_context *sys) { struct ipa3_rx_pkt_wrapper *rx_pkt; @@ -2030,9 +2037,16 @@ static struct ipa3_rx_pkt_wrapper *ipa3_alloc_rx_pkt_page( flag); if (unlikely(!rx_pkt)) return NULL; - rx_pkt->len = PAGE_SIZE << IPA_WAN_PAGE_ORDER; - rx_pkt->page_data.page = __dev_alloc_pages(flag, - IPA_WAN_PAGE_ORDER); + if (sys->ext_ioctl_v2) { + rx_pkt->len = sys->buff_size; + rx_pkt->page_data.page = __dev_alloc_pages(flag, + get_order(sys->buff_size)); + } else { + rx_pkt->len = PAGE_SIZE << IPA_WAN_PAGE_ORDER; + rx_pkt->page_data.page = __dev_alloc_pages(flag, + IPA_WAN_PAGE_ORDER); + } + if (unlikely(!rx_pkt->page_data.page)) goto fail_page_alloc; @@ -2065,7 +2079,7 @@ static void ipa3_replenish_rx_page_cache(struct ipa3_sys_context *sys) u32 curr; for (curr = 0; curr < sys->page_recycle_repl->capacity; curr++) { - rx_pkt = ipa3_alloc_rx_pkt_page(GFP_KERNEL, false); + rx_pkt = ipa3_alloc_rx_pkt_page(GFP_KERNEL, false, sys); if (!rx_pkt) { IPAERR("ipa3_alloc_rx_pkt_page fails\n"); ipa_assert(); @@ -2095,7 +2109,7 @@ begin: next = (curr + 1) % sys->repl->capacity; if (unlikely(next == atomic_read(&sys->repl->head_idx))) goto fail_kmem_cache_alloc; - rx_pkt = ipa3_alloc_rx_pkt_page(GFP_KERNEL, true); + rx_pkt = ipa3_alloc_rx_pkt_page(GFP_KERNEL, true, sys); if (unlikely(!rx_pkt)) { IPAERR("ipa3_alloc_rx_pkt_page fails\n"); break; @@ -3983,8 +3997,10 @@ static int ipa3_assign_policy(struct ipa_sys_connect_params *in, in->ipa_ep_cfg.aggr.aggr = IPA_COALESCE; else in->ipa_ep_cfg.aggr.aggr = IPA_GENERIC; - in->ipa_ep_cfg.aggr.aggr_time_limit = - IPA_GENERIC_AGGR_TIME_LIMIT; + if (in->client == IPA_CLIENT_APPS_LAN_CONS || + !in->ext_ioctl_v2) + in->ipa_ep_cfg.aggr.aggr_time_limit = + IPA_GENERIC_AGGR_TIME_LIMIT; if (in->client == IPA_CLIENT_APPS_LAN_CONS) { INIT_WORK(&sys->repl_work, ipa3_wq_repl_rx); sys->pyld_hdlr = ipa3_lan_rx_pyld_hdlr; @@ -4044,8 +4060,6 @@ static int ipa3_assign_policy(struct ipa_sys_connect_params *in, IPA_CLIENT_APPS_WAN_LOW_LAT_CONS) { INIT_WORK(&sys->repl_work, ipa3_wq_repl_rx); sys->ep->status.status_en = false; - in->ipa_ep_cfg.aggr.aggr_en = IPA_BYPASS_AGGR; - in->ipa_ep_cfg.aggr.aggr_time_limit = 0; sys->rx_buff_sz = IPA_GENERIC_RX_BUFF_SZ( IPA_QMAP_RX_BUFF_BASE_SZ); sys->pyld_hdlr = ipa3_low_lat_rx_pyld_hdlr; @@ -4878,6 +4892,16 @@ static int ipa_gsi_setup_event_ring(struct ipa3_ep_context *ep, gsi_evt_ring_props.int_modc = 1; } + if (ep->sys->ext_ioctl_v2 && + ((ep->client == IPA_CLIENT_APPS_WAN_PROD) || + (ep->client == IPA_CLIENT_APPS_WAN_CONS) || + (ep->client == IPA_CLIENT_APPS_WAN_COAL_CONS) || + (ep->client == IPA_CLIENT_APPS_WAN_LOW_LAT_PROD) || + (ep->client == IPA_CLIENT_APPS_WAN_LOW_LAT_CONS))) { + gsi_evt_ring_props.int_modt = ep->sys->int_modt; + gsi_evt_ring_props.int_modc = ep->sys->int_modc; + } + IPADBG("client=%d moderation threshold cycles=%u cnt=%u\n", ep->client, gsi_evt_ring_props.int_modt, diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h index 54aef82edb..54f321da18 100644 --- a/drivers/platform/msm/ipa/ipa_v3/ipa_i.h +++ b/drivers/platform/msm/ipa/ipa_v3/ipa_i.h @@ -1061,6 +1061,10 @@ struct ipa3_repl_ctx { * @napi_tx: napi for eot write done handle (tx_complete) - to replace tasklet * @in_napi_context: an atomic variable used for non-blocking locking, * preventing from multiple napi_sched to be called. + * @int_modt: GSI event ring interrupt moderation timer + * @int_modc: GSI event ring interrupt moderation counter + * @buff_size: rx packet length + * @ext_ioctl_v2: specifies if it's new version of ingress/egress ioctl * * IPA context specific to the GPI pipes a.k.a LAN IN/OUT and WAN */ @@ -1098,6 +1102,10 @@ struct ipa3_sys_context { u32 eob_drop_cnt; struct napi_struct napi_tx; atomic_t in_napi_context; + u32 int_modt; + u32 int_modc; + u32 buff_size; + bool ext_ioctl_v2; /* ordering is important - mutable fields go above */ struct ipa3_ep_context *ep; @@ -3136,8 +3144,10 @@ int ipa3_register_rmnet_ctl_cb( void *user_data3); int ipa3_unregister_rmnet_ctl_cb(void); int ipa3_rmnet_ctl_xmit(struct sk_buff *skb); -int ipa3_setup_apps_low_lat_prod_pipe(void); -int ipa3_setup_apps_low_lat_cons_pipe(void); +int ipa3_setup_apps_low_lat_prod_pipe(bool rmnet_config, + struct rmnet_egress_param *egress_param); +int ipa3_setup_apps_low_lat_cons_pipe(bool rmnet_config, + struct rmnet_ingress_param *ingress_param); int ipa3_teardown_apps_low_lat_pipes(void); const char *ipa_hw_error_str(enum ipa3_hw_errors err_type); int ipa_gsi_ch20_wa(void); diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ctl_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ctl_ipa.c index 9262da787e..528e652b85 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ctl_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ctl_ipa.c @@ -210,7 +210,8 @@ int ipa3_unregister_rmnet_ctl_cb(void) return 0; } -int ipa3_setup_apps_low_lat_cons_pipe(void) +int ipa3_setup_apps_low_lat_cons_pipe(bool rmnet_config, + struct rmnet_ingress_param *ingress_param) { struct ipa_sys_connect_params *ipa_low_lat_ep_cfg; int ret = 0; @@ -234,12 +235,40 @@ int ipa3_setup_apps_low_lat_cons_pipe(void) } ipa_low_lat_ep_cfg = &rmnet_ctl_ipa3_ctx->ipa_to_apps_low_lat_ep_cfg; - ipa_low_lat_ep_cfg->ipa_ep_cfg.cfg.cs_offload_en = - IPA_ENABLE_CS_DL_QMAP; - ipa_low_lat_ep_cfg->ipa_ep_cfg.aggr.aggr_byte_limit = - 0; - ipa_low_lat_ep_cfg->ipa_ep_cfg.aggr.aggr_pkt_limit = - 0; + /* + * Removing bypass aggr from assign_policy + * and placing it here for future enablement + */ + ipa_low_lat_ep_cfg->ipa_ep_cfg.aggr.aggr_en = IPA_BYPASS_AGGR; + if (rmnet_config && ingress_param) { + /* Open for future cs offload disablement on low lat pipe */ + if (ingress_param->cs_offload_en) { + ipa_low_lat_ep_cfg->ipa_ep_cfg.cfg.cs_offload_en = + IPA_ENABLE_CS_DL_QMAP; + } else { + ipa_low_lat_ep_cfg->ipa_ep_cfg.cfg.cs_offload_en = + IPA_DISABLE_CS_OFFLOAD; + } + ipa_low_lat_ep_cfg->ext_ioctl_v2 = true; + ipa_low_lat_ep_cfg->int_modt = ingress_param->int_modt; + ipa_low_lat_ep_cfg->int_modc = ingress_param->int_modc; + ipa_low_lat_ep_cfg->buff_size = ingress_param->buff_size; + ipa_low_lat_ep_cfg->ipa_ep_cfg.aggr.aggr_byte_limit = + ingress_param->agg_byte_limit; + ipa_low_lat_ep_cfg->ipa_ep_cfg.aggr.aggr_pkt_limit = + ingress_param->agg_pkt_limit; + ipa_low_lat_ep_cfg->ipa_ep_cfg.aggr.aggr_time_limit = + ingress_param->agg_time_limit; + } else { + ipa_low_lat_ep_cfg->ext_ioctl_v2 = false; + ipa_low_lat_ep_cfg->ipa_ep_cfg.cfg.cs_offload_en = + IPA_ENABLE_CS_DL_QMAP; + ipa_low_lat_ep_cfg->ipa_ep_cfg.aggr.aggr_byte_limit = + 0; + ipa_low_lat_ep_cfg->ipa_ep_cfg.aggr.aggr_pkt_limit = + 0; + } + ipa_low_lat_ep_cfg->ipa_ep_cfg.hdr.hdr_len = 8; ipa_low_lat_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1; @@ -295,7 +324,8 @@ int ipa3_setup_apps_low_lat_cons_pipe(void) return 0; } -int ipa3_setup_apps_low_lat_prod_pipe(void) +int ipa3_setup_apps_low_lat_prod_pipe(bool rmnet_config, + struct rmnet_egress_param *egress_param) { struct ipa_sys_connect_params *ipa_low_lat_ep_cfg; int ret = 0; @@ -313,16 +343,47 @@ int ipa3_setup_apps_low_lat_prod_pipe(void) } ipa_low_lat_ep_cfg = &rmnet_ctl_ipa3_ctx->apps_to_ipa_low_lat_ep_cfg; - ipa_low_lat_ep_cfg->ipa_ep_cfg.hdr.hdr_len = 8; - ipa_low_lat_ep_cfg->ipa_ep_cfg.cfg.cs_offload_en = - IPA_ENABLE_CS_OFFLOAD_UL; - ipa_low_lat_ep_cfg->ipa_ep_cfg.cfg.cs_metadata_hdr_offset - = 1; - ipa_low_lat_ep_cfg->ipa_ep_cfg.aggr.aggr_en = - IPA_BYPASS_AGGR; - ipa_low_lat_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1; - /* modem want offset at 0! */ - ipa_low_lat_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_metadata = 0; + if (rmnet_config && egress_param) { + /* Open for future cs offload disablement on low lat pipe */ + IPAERR("Configuring low lat prod with rmnet config\n"); + ipa_low_lat_ep_cfg->ext_ioctl_v2 = true; + ipa_low_lat_ep_cfg->int_modt = egress_param->int_modt; + ipa_low_lat_ep_cfg->int_modc = egress_param->int_modc; + if (egress_param->cs_offload_en) { + ipa_low_lat_ep_cfg->ipa_ep_cfg.hdr.hdr_len = 8; + ipa_low_lat_ep_cfg->ipa_ep_cfg.cfg.cs_offload_en = + IPA_ENABLE_CS_OFFLOAD_UL; + ipa_low_lat_ep_cfg->ipa_ep_cfg.cfg.cs_metadata_hdr_offset + = 1; + ipa_low_lat_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid + = 1; + /* modem want offset at 0! */ + ipa_low_lat_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_metadata = 0; + } else { + ipa_low_lat_ep_cfg->ipa_ep_cfg.cfg.cs_offload_en = + IPA_DISABLE_CS_OFFLOAD; + } + + /* Open for future deaggr enablement on low lat pipe */ + if (!egress_param->aggr_en) { + ipa_low_lat_ep_cfg->ipa_ep_cfg.aggr.aggr_en = + IPA_BYPASS_AGGR; + } + } else { + IPAERR("Configuring low lat prod without rmnet config\n"); + ipa_low_lat_ep_cfg->ext_ioctl_v2 = false; + ipa_low_lat_ep_cfg->ipa_ep_cfg.hdr.hdr_len = 8; + ipa_low_lat_ep_cfg->ipa_ep_cfg.cfg.cs_offload_en = + IPA_ENABLE_CS_OFFLOAD_UL; + ipa_low_lat_ep_cfg->ipa_ep_cfg.aggr.aggr_en = + IPA_BYPASS_AGGR; + ipa_low_lat_ep_cfg->ipa_ep_cfg.cfg.cs_metadata_hdr_offset + = 1; + ipa_low_lat_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid + = 1; + /* modem want offset at 0! */ + ipa_low_lat_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_metadata = 0; + } ipa_low_lat_ep_cfg->ipa_ep_cfg.mode.dst = IPA_CLIENT_Q6_WAN_CONS; ipa_low_lat_ep_cfg->ipa_ep_cfg.mode.mode = diff --git a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c index c3bc58e7df..6f852b3f6d 100644 --- a/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c +++ b/drivers/platform/msm/ipa/ipa_v3/rmnet_ipa.c @@ -180,6 +180,16 @@ static struct rmnet_ipa3_context *rmnet_ipa3_ctx; static struct ipa3_rmnet_plat_drv_res ipa3_rmnet_res; bool ipa_net_initialized = false; +struct rmnet_ipa_pipe_setup_status { + int ep_type; + int status; +}; + +static struct rmnet_ipa_pipe_setup_status egress_pipe_status[ + RMNET_EGRESS_MAX]; +static struct rmnet_ipa_pipe_setup_status ingress_pipe_status[ + RMNET_INGRESS_MAX]; + /** * ipa3_setup_a7_qmap_hdr() - Setup default a7 qmap hdr * @@ -1509,6 +1519,7 @@ static int handle3_ingress_format(struct net_device *dev, struct ipa_sys_connect_params *ipa_wan_ep_cfg; int ep_idx; int ingress_eps_mask = IPA_AP_INGRESS_NONE; + bool rmnet_config; IPAWANDBG("Get RMNET_IOCTL_SET_INGRESS_DATA_FORMAT\n"); @@ -1575,6 +1586,7 @@ static int handle3_ingress_format(struct net_device *dev, ipa_wan_ep_cfg->client = IPA_CLIENT_APPS_WAN_COAL_CONS; ingress_eps_mask |= IPA_AP_INGRESS_EP_COALS; } + ipa_wan_ep_cfg->ext_ioctl_v2 = false; ipa_wan_ep_cfg->notify = apps_ipa_packet_receive_notify; ipa_wan_ep_cfg->priv = dev; @@ -1601,7 +1613,8 @@ static int handle3_ingress_format(struct net_device *dev, IPAWANDBG("ingress WAN pipe setup successfully\n"); if (ipa3_ctx->rmnet_ctl_enable) { - ret = ipa3_setup_apps_low_lat_cons_pipe(); + rmnet_config = false; + ret = ipa3_setup_apps_low_lat_cons_pipe(rmnet_config, NULL); if (ret) goto low_lat_fail; ingress_eps_mask |= IPA_AP_INGRESS_EP_LOW_LAT; @@ -1642,6 +1655,7 @@ static int handle3_egress_format(struct net_device *dev, int rc; struct ipa_sys_connect_params *ipa_wan_ep_cfg; int ep_idx; + bool rmnet_config; IPAWANDBG("get RMNET_IOCTL_SET_EGRESS_DATA_FORMAT %x\n", e->u.data); /* @@ -1711,6 +1725,7 @@ static int handle3_egress_format(struct net_device *dev, ipa_wan_ep_cfg->notify = apps_ipa_tx_complete_notify; ipa_wan_ep_cfg->desc_fifo_sz = IPA_SYS_TX_DATA_DESC_FIFO_SZ; ipa_wan_ep_cfg->priv = dev; + ipa_wan_ep_cfg->ext_ioctl_v2 = false; mutex_lock(&rmnet_ipa3_ctx->pipe_handle_guard); if (atomic_read(&rmnet_ipa3_ctx->is_ssr)) { @@ -1727,7 +1742,8 @@ static int handle3_egress_format(struct net_device *dev, } IPAWANDBG("engress WAN pipe setup successfully\n"); if (ipa3_ctx->rmnet_ctl_enable) { - rc = ipa3_setup_apps_low_lat_prod_pipe(); + rmnet_config = false; + rc = ipa3_setup_apps_low_lat_prod_pipe(rmnet_config, NULL); if (rc) { IPAWANERR("failed to setup egress low lat endpoint\n"); mutex_unlock(&rmnet_ipa3_ctx->pipe_handle_guard); @@ -1760,6 +1776,538 @@ low_lat_fail: return rc; } +/** + * ipa3_setup_apps_wan_cons_pipes() - wan/coal pipe config + * + * Setup IPA Ingress wan pipes and Configure them: + */ +static int ipa3_setup_apps_wan_cons_pipes( + struct rmnet_ingress_param *ingress_param, + struct rmnet_ipa_pipe_setup_status *pipe_status, + int *ingress_eps_mask, + struct net_device *dev) +{ + struct ipa_sys_connect_params *ipa_wan_ep_cfg; + int ep_idx, coal_ep_idx; + int rc = 0; + + if (ingress_param->pipe_setup_status == IPA_PIPE_SETUP_EXISTS) + return rc; + + coal_ep_idx = ipa_get_ep_mapping(IPA_CLIENT_APPS_WAN_COAL_CONS); + ep_idx = ipa_get_ep_mapping(IPA_CLIENT_APPS_WAN_CONS); + if (ep_idx == IPA_EP_NOT_ALLOCATED) { + IPAWANERR("Embedded datapath not supported\n"); + return rc; + } + + ipa_wan_ep_cfg = &rmnet_ipa3_ctx->ipa_to_apps_ep_cfg; + ipa_wan_ep_cfg->ipa_ep_cfg.cfg.cs_offload_en = + IPA_ENABLE_CS_DL_QMAP; + + if (!ipa3_disable_apps_wan_cons_deaggr( + ingress_param->agg_byte_limit, + ingress_param->agg_pkt_limit)) { + ipa_wan_ep_cfg->ipa_ep_cfg.aggr.aggr_byte_limit = + ingress_param->agg_byte_limit; + ipa_wan_ep_cfg->ipa_ep_cfg.aggr.aggr_pkt_limit = + ingress_param->agg_pkt_limit; + ipa_wan_ep_cfg->ipa_ep_cfg.aggr.aggr_time_limit = + ingress_param->agg_time_limit; + } + + if (ingress_param->cs_offload_en) { + ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_len = 8; + rmnet_ipa3_ctx->dl_csum_offload_enabled = true; + } else { + ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_len = 4; + rmnet_ipa3_ctx->dl_csum_offload_enabled = false; + } + + ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1; + ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_metadata = 1; + ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_pkt_size_valid = 1; + ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 2; + + ipa_wan_ep_cfg->ipa_ep_cfg.hdr_ext.hdr_total_len_or_pad_valid + = true; + ipa_wan_ep_cfg->ipa_ep_cfg.hdr_ext.hdr_total_len_or_pad + = 0; + ipa_wan_ep_cfg->ipa_ep_cfg.hdr_ext.hdr_payload_len_inc_padding + = true; + ipa_wan_ep_cfg->ipa_ep_cfg.hdr_ext.hdr_total_len_or_pad_offset + = 0; + ipa_wan_ep_cfg->ipa_ep_cfg.hdr_ext.hdr_little_endian + = 0; + ipa_wan_ep_cfg->ipa_ep_cfg.metadata_mask.metadata_mask + = 0xFF000000; + + if (ingress_param->ingress_ep_type == RMNET_INGRESS_DEFAULT) { + /* Reject the whole ioctl if coal pipe is not setup first */ + if (dev->features & NETIF_F_GRO_HW) { + if (coal_ep_idx == IPA_EP_NOT_ALLOCATED) { + IPAWANERR("Trying to setup def WAN before coals"); + mutex_unlock(&rmnet_ipa3_ctx->pipe_handle_guard); + return -EFAULT; + } + else if (!ipa3_ctx->ep[coal_ep_idx].valid) { + IPAWANERR("Trying to setup def WAN before coals."); + mutex_unlock(&rmnet_ipa3_ctx->pipe_handle_guard); + return -EFAULT; + } + } + + /* Setup default pipe */ + IPAWANDBG("Setting up default pipe\n"); + ipa_wan_ep_cfg->client = IPA_CLIENT_APPS_WAN_CONS; + pipe_status->ep_type = RMNET_INGRESS_DEFAULT; + *ingress_eps_mask |= IPA_AP_INGRESS_EP_DEFAULT; + } else if (ingress_param->ingress_ep_type == + RMNET_INGRESS_COALS && (dev->features & NETIF_F_GRO_HW)) { + /* Setup coalescing pipes */ + IPAWANDBG("Setting up coalescing pipe\n"); + ipa_wan_ep_cfg->client = IPA_CLIENT_APPS_WAN_COAL_CONS; + pipe_status->ep_type = RMNET_INGRESS_COALS; + *ingress_eps_mask |= IPA_AP_INGRESS_EP_COALS; + } else { + return rc; + } + + ipa_wan_ep_cfg->notify = apps_ipa_packet_receive_notify; + ipa_wan_ep_cfg->priv = dev; + + if (ipa3_rmnet_res.ipa_napi_enable) + ipa_wan_ep_cfg->napi_obj = &(rmnet_ipa3_ctx->wwan_priv->napi); + ipa_wan_ep_cfg->desc_fifo_sz = + ipa3_rmnet_res.wan_rx_desc_size * IPA_FIFO_ELEMENT_SIZE; + + if (atomic_read(&rmnet_ipa3_ctx->is_ssr)) { + IPAWANERR("In SSR sequence/recovery\n"); + return rc; + } + ipa_wan_ep_cfg->ext_ioctl_v2 = true; + ipa_wan_ep_cfg->int_modt = ingress_param->int_modt; + ipa_wan_ep_cfg->int_modc = ingress_param->int_modc; + ipa_wan_ep_cfg->buff_size = ingress_param->buff_size; + + rc = ipa_setup_sys_pipe(&rmnet_ipa3_ctx->ipa_to_apps_ep_cfg, + &rmnet_ipa3_ctx->ipa3_to_apps_hdl); + + if (rc) { + pipe_status->status = IPA_PIPE_SETUP_FAILURE; + IPAWANERR("failed to setup default/coal pipe rc = %d\n", rc); + return rc; + } + + IPAWANDBG("Ingress default/coal pipe setup successfully\n"); + + ingress_param->pipe_setup_status = IPA_PIPE_SETUP_SUCCESS; + /* caching the success status of the pipe */ + pipe_status->status = IPA_PIPE_SETUP_EXISTS; + + return rc; +} + +/** + * handle3_ingress_format_v2() - Ingress data format configuration + * + * Setup IPA Ingress system pipes and Configure them: + * + * @dev: network device + * @ioctl_ptr: Pointer to ingress pipes' config info + */ +static int handle3_ingress_format_v2(struct net_device *dev, + __u64 ioctl_ptr) +{ + struct ingress_format_v2 ingress_ioctl_v2_data; + struct rmnet_ingress_param ingress_param[RMNET_INGRESS_MAX]; + int ingress_eps_mask = IPA_AP_INGRESS_NONE; + int i, j; + bool rmnet_config; + int rc = 0; + + if(copy_from_user(&ingress_ioctl_v2_data, u64_to_user_ptr(ioctl_ptr), + sizeof(struct ingress_format_v2))) { + IPAWANERR("failed to copy ingress extended ioctl v2 data\n"); + return -EFAULT; + } + + if(ingress_ioctl_v2_data.number_of_eps > + RMNET_INGRESS_MAX) { + IPAWANERR("Ingress pipe count mismatch\n"); + return -EFAULT; + } + + if(ingress_ioctl_v2_data.ingress_param_size != + sizeof(struct rmnet_ingress_param)) { + IPAWANERR("Ingress pipe param size mismatch\n"); + return -EFAULT; + } + + if(copy_from_user(&ingress_param, u64_to_user_ptr( + ingress_ioctl_v2_data.ingress_param_ptr), + sizeof(struct rmnet_ingress_param) * + ingress_ioctl_v2_data.number_of_eps)) { + IPAWANERR("Failed to copy all ingress pipes' params\n"); + return -EFAULT; + } + + IPAWANDBG("ingress_ioctl_v2_data.number_of_eps = %d\n", + ingress_ioctl_v2_data.number_of_eps); + + mutex_lock(&rmnet_ipa3_ctx->pipe_handle_guard); + + for (i = 0; i < ingress_ioctl_v2_data.number_of_eps; i++) { + ingress_param[i].pipe_setup_status = IPA_PIPE_SETUP_FAILURE; + IPAWANDBG("pipe ep_type = %d cs_offload_en = %d buff_size =%d\n", + ingress_param[i].ingress_ep_type, + ingress_param[i].cs_offload_en, + ingress_param[i].buff_size); + IPAWANDBG("agg_limit byte =%d time =%d pkt =%d\n", + ingress_param[i].agg_byte_limit, + ingress_param[i].agg_time_limit, + ingress_param[i].agg_pkt_limit); + IPAWANDBG("int_modt = %d int_modc = %d\n", + ingress_param[i].int_modt, ingress_param[i].int_modc); + if (ingress_param[i].ingress_ep_type == RMNET_INGRESS_DEFAULT || + ingress_param[i].ingress_ep_type == RMNET_INGRESS_COALS) { + + memset(&rmnet_ipa3_ctx->ipa_to_apps_ep_cfg, 0, + sizeof(struct ipa_sys_connect_params)); + + /* Searching through the static table, if pipe exists already */ + for (j = 0; j < RMNET_INGRESS_MAX; j++) { + if (ingress_param[i].ingress_ep_type == + RMNET_INGRESS_DEFAULT && + ingress_pipe_status[j].ep_type == + RMNET_INGRESS_DEFAULT && + ingress_pipe_status[j].status == IPA_PIPE_SETUP_EXISTS) { + ingress_param[i].pipe_setup_status = + IPA_PIPE_SETUP_EXISTS; + IPAWANERR("Receiving ingress wan default ioctl again\n"); + break; + } + } + + /* Searching through the static table, if pipe exists already */ + for (j = 0; j < RMNET_INGRESS_MAX; j++) { + if (ingress_param[i].ingress_ep_type == RMNET_INGRESS_COALS && + ingress_pipe_status[j].ep_type == RMNET_INGRESS_COALS && + ingress_pipe_status[j].status == IPA_PIPE_SETUP_EXISTS) { + ingress_param[i].pipe_setup_status = + IPA_PIPE_SETUP_EXISTS; + IPAWANERR("Receiving ingress coal ioctl again\n"); + break; + } + } + + rc = ipa3_setup_apps_wan_cons_pipes(&ingress_param[i], + &ingress_pipe_status[i], + &ingress_eps_mask, + dev); + + if (rc == -EFAULT) { + IPAWANERR("Failed to setup wan/coal cons pipes\n"); + return rc; + } + + } else if (ingress_param[i].ingress_ep_type == + RMNET_INGRESS_LOW_LAT_CTRL) { + /* Searching through the static table, if pipe exists already */ + for (j = 0; j < RMNET_INGRESS_MAX; j++) { + if (ingress_pipe_status[j].ep_type == + RMNET_INGRESS_LOW_LAT_CTRL && + ingress_pipe_status[j].status == IPA_PIPE_SETUP_EXISTS) { + ingress_param[i].pipe_setup_status + = IPA_PIPE_SETUP_EXISTS; + IPAWANERR("Receiving ingress low lat ctrl ioctl again"); + break; + } + } + + if (ipa3_ctx->rmnet_ctl_enable && + (ingress_param[i].pipe_setup_status == IPA_PIPE_SETUP_EXISTS)) + continue; + + ingress_pipe_status[i].ep_type = RMNET_INGRESS_LOW_LAT_CTRL; + rmnet_config = true; + rc = ipa3_setup_apps_low_lat_cons_pipe(rmnet_config, + &ingress_param[i]); + if (rc) { + IPAWANERR("failed to setup ingress low lat endpoint\n"); + ingress_pipe_status[i].status = IPA_PIPE_SETUP_FAILURE; + continue; + } + ingress_eps_mask |= IPA_AP_INGRESS_EP_LOW_LAT; + IPAWANDBG("Ingress LOW LAT CTRL pipe setup successfully\n"); + ingress_param[i].pipe_setup_status = IPA_PIPE_SETUP_SUCCESS; + /* caching the success status of the pipe */ + ingress_pipe_status[i].status = IPA_PIPE_SETUP_EXISTS; + + } else if (ingress_param[i].ingress_ep_type == + RMNET_INGRESS_LOW_LAT_DATA) { + IPAWANERR("Ingress Low lat data pipe is not defined\n"); + continue; + } else { + IPAWANERR("Ingress ep_type not defined\n"); + } + } + + if(copy_to_user(u64_to_user_ptr(ingress_ioctl_v2_data.ingress_param_ptr), + &ingress_param, + sizeof(struct rmnet_ingress_param) * + ingress_ioctl_v2_data.number_of_eps)) { + IPAWANERR("Ingress copy to user failed\n"); + return -EFAULT; + } + + mutex_unlock(&rmnet_ipa3_ctx->pipe_handle_guard); + + /* construct default WAN RT tbl for IPACM */ + rc = ipa3_setup_a7_qmap_hdr(); + if (rc) { + IPAWANERR("A7 QMAP header setup failed\n"); + return -EFAULT; + } + + rc = ipa3_setup_dflt_wan_rt_tables(); + if (rc) + ipa3_del_a7_qmap_hdr(); + + /* Sending QMI indication message share RSC/QMAP pipe details*/ + ipa_send_wan_pipe_ind_to_modem(ingress_eps_mask); + + return 0; +} + +/** + * ipa3_setup_apps_wan_prod_pipes() - wan prod pipe config + * + * Setup IPA egress wan pipes and Configure them: + */ +static int ipa3_setup_apps_wan_prod_pipes( + struct rmnet_egress_param *egress_param, + struct rmnet_ipa_pipe_setup_status *pipe_status, + struct net_device *dev) +{ + struct ipa_sys_connect_params *ipa_wan_ep_cfg; + int ep_idx; + int rc = 0; + + if(egress_param->pipe_setup_status == IPA_PIPE_SETUP_EXISTS) + return rc; + + ep_idx = ipa_get_ep_mapping(IPA_CLIENT_APPS_WAN_PROD); + if (ep_idx == IPA_EP_NOT_ALLOCATED) { + IPAWANERR("Embedded datapath not supported\n"); + return rc; + } + + ipa_wan_ep_cfg = &rmnet_ipa3_ctx->apps_to_ipa_ep_cfg; + if (egress_param->cs_offload_en) { + IPAWANDBG("UL Chksum set\n"); + ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_len = 8; + ipa_wan_ep_cfg->ipa_ep_cfg.cfg.cs_offload_en + = IPA_ENABLE_CS_OFFLOAD_UL; + ipa_wan_ep_cfg->ipa_ep_cfg.cfg.cs_metadata_hdr_offset + = 1; + } else { + ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_len = 4; + ipa_wan_ep_cfg->ipa_ep_cfg.cfg.cs_offload_en + = IPA_DISABLE_CS_OFFLOAD; + } + + if (egress_param->aggr_en) { + IPAWANDBG("WAN UL Aggr enabled\n"); + ipa_wan_ep_cfg->ipa_ep_cfg.aggr.aggr_en = IPA_ENABLE_DEAGGR; + ipa_wan_ep_cfg->ipa_ep_cfg.aggr.aggr = IPA_QCMAP; + ipa_wan_ep_cfg->ipa_ep_cfg.deaggr.packet_offset_valid = false; + ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_pkt_size = 2; + ipa_wan_ep_cfg-> + ipa_ep_cfg.hdr_ext.hdr_total_len_or_pad_valid = true; + ipa_wan_ep_cfg-> + ipa_ep_cfg.hdr_ext.hdr_total_len_or_pad = IPA_HDR_PAD; + ipa_wan_ep_cfg->ipa_ep_cfg.hdr_ext.hdr_pad_to_alignment = 2; + ipa_wan_ep_cfg-> + ipa_ep_cfg.hdr_ext.hdr_payload_len_inc_padding = true; + ipa_wan_ep_cfg-> + ipa_ep_cfg.hdr_ext.hdr_total_len_or_pad_offset = 0; + ipa_wan_ep_cfg->ipa_ep_cfg.hdr_ext.hdr_little_endian = false; + } else { + IPAWANERR("WAN UL Aggregation disabled\n"); + ipa_wan_ep_cfg->ipa_ep_cfg.aggr.aggr_en = IPA_BYPASS_AGGR; + } + + ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_metadata_valid = 1; + /* modem want offset at 0! */ + ipa_wan_ep_cfg->ipa_ep_cfg.hdr.hdr_ofst_metadata = 0; + ipa_wan_ep_cfg->ipa_ep_cfg.mode.dst = IPA_CLIENT_APPS_WAN_PROD; + ipa_wan_ep_cfg->ipa_ep_cfg.mode.mode = IPA_BASIC; + ipa_wan_ep_cfg->client = IPA_CLIENT_APPS_WAN_PROD; + ipa_wan_ep_cfg->notify = apps_ipa_tx_complete_notify; + ipa_wan_ep_cfg->desc_fifo_sz = IPA_SYS_TX_DATA_DESC_FIFO_SZ; + ipa_wan_ep_cfg->priv = dev; + + ipa_wan_ep_cfg->ext_ioctl_v2 = true; + ipa_wan_ep_cfg->int_modt = egress_param->int_modt; + ipa_wan_ep_cfg->int_modc = egress_param->int_modc; + if (atomic_read(&rmnet_ipa3_ctx->is_ssr)) { + IPAWANERR("In SSR sequence/recovery\n"); + return rc; + } + + pipe_status->ep_type = RMNET_EGRESS_DEFAULT; + + rc = ipa_setup_sys_pipe( + ipa_wan_ep_cfg, &rmnet_ipa3_ctx->apps_to_ipa3_hdl); + + if (rc) { + IPAWANERR("failed to setup egress default pipe\n"); + pipe_status->status = IPA_PIPE_SETUP_FAILURE; + return rc; + } + + IPAWANDBG("Egress WAN pipe setup successful\n"); + egress_param->pipe_setup_status = IPA_PIPE_SETUP_SUCCESS; + /* caching the success status of the pipe */ + pipe_status->status = IPA_PIPE_SETUP_EXISTS; + + return rc; +} + +/** + * handle3_egress_format_v2() - Egress data format configuration + * + * Setup IPA egress system pipes and Configure them: + * + * @dev: network device + * @ioctl_ptr: Pointer to egress pipes' config info + */ +static int handle3_egress_format_v2(struct net_device *dev, + __u64 ioctl_ptr) +{ + struct egress_format_v2 egress_ioctl_v2_data; + struct rmnet_egress_param egress_param[RMNET_EGRESS_MAX]; + int i, j; + int rc = 0; + bool rmnet_config; + + if(copy_from_user(&egress_ioctl_v2_data, u64_to_user_ptr(ioctl_ptr), + sizeof(struct egress_format_v2))) { + IPAWANERR("failed to copy egress extended ioctl v2 data\n"); + return -EFAULT; + } + + if(egress_ioctl_v2_data.number_of_eps > + RMNET_EGRESS_MAX) { + IPAWANERR("Egress pipe count mismatch = %d\n", + egress_ioctl_v2_data.number_of_eps); + return -EFAULT; + } + + if(egress_ioctl_v2_data.egress_param_size != + sizeof(struct rmnet_egress_param)) { + IPAWANERR("Egress pipe param size mismatch\n"); + return -EFAULT; + } + + if(copy_from_user(&egress_param, u64_to_user_ptr( + egress_ioctl_v2_data.egress_param_ptr), + sizeof(struct rmnet_egress_param) * + egress_ioctl_v2_data.number_of_eps)) { + IPAWANERR("Failed to copy all egress pipes' params\n"); + return -EFAULT; + } + + IPAWANDBG("egress_ioctl_v2_data.number_of_eps = %d\n", + egress_ioctl_v2_data.number_of_eps); + + mutex_lock(&rmnet_ipa3_ctx->pipe_handle_guard); + + for (i = 0; i < egress_ioctl_v2_data.number_of_eps; i++) { + egress_param[i].pipe_setup_status = IPA_PIPE_SETUP_FAILURE; + IPAWANDBG("cs_offload_en = %d, aggr_en = %d, ulso_en = %d\n", + egress_param[i].cs_offload_en, + egress_param[i].aggr_en, + egress_param[i].ulso_en); + IPAWANDBG("ipid_min_max_idx = %d, int_modt = %d, int_modc = %d\n", + egress_param[i].ipid_min_max_idx, + egress_param[i].int_modt, + egress_param[i].int_modc); + if (egress_param[i].egress_ep_type == RMNET_EGRESS_DEFAULT) { + /* Searching through the static table, if pipe exists already */ + for (j = 0; j < RMNET_EGRESS_MAX; j++) { + if (egress_pipe_status[j].ep_type == RMNET_EGRESS_DEFAULT && + egress_pipe_status[j].status == IPA_PIPE_SETUP_EXISTS) { + IPAWANERR("Receiving egress default ioctl again"); + egress_param[i].pipe_setup_status = IPA_PIPE_SETUP_EXISTS; + break; + } + } + + rc = ipa3_setup_apps_wan_prod_pipes(&egress_param[i], + &egress_pipe_status[i], + dev); + + if (rc == -EFAULT) { + IPAWANERR("Failed to setup wan prod pipes\n"); + return rc; + } + + } else if (egress_param[i].egress_ep_type == + RMNET_EGRESS_LOW_LAT_CTRL) { + /* Searching through the static table, if pipe exists already */ + for (j = 0; j < RMNET_EGRESS_MAX; j++) { + if (egress_pipe_status[j].ep_type == + RMNET_EGRESS_LOW_LAT_CTRL && + egress_pipe_status[j].status == IPA_PIPE_SETUP_EXISTS) { + egress_param[i].pipe_setup_status = IPA_PIPE_SETUP_EXISTS; + IPAWANERR("Receiving egress low lat ioctl again"); + break; + } + } + + if (ipa3_ctx->rmnet_ctl_enable && + (egress_param[i].pipe_setup_status == IPA_PIPE_SETUP_EXISTS)) + continue; + + egress_pipe_status[i].ep_type = RMNET_EGRESS_LOW_LAT_CTRL; + + rmnet_config = true; + rc = ipa3_setup_apps_low_lat_prod_pipe( + rmnet_config, &egress_param[i]); + if (rc) { + IPAWANERR("failed to setup egress low lat endpoint\n"); + egress_pipe_status[i].status = IPA_PIPE_SETUP_FAILURE; + continue; + } + IPAWANDBG("Egress LOW LAT CTRL pipe setup successfully\n"); + egress_param[i].pipe_setup_status = IPA_PIPE_SETUP_SUCCESS; + /* caching the success status of the pipe */ + egress_pipe_status[i].status = IPA_PIPE_SETUP_EXISTS; + + } else if (egress_param[i].egress_ep_type == + RMNET_EGRESS_LOW_LAT_DATA) { + IPAWANERR("Egress Low lat data pipe is not defined yet\n"); + continue; + } else { + IPAWANERR("Egress ep type not defined"); + } + } + + if(copy_to_user(u64_to_user_ptr(egress_ioctl_v2_data.egress_param_ptr), + &egress_param, + sizeof(struct rmnet_egress_param) * egress_ioctl_v2_data.number_of_eps)) { + IPAWANERR("Egress copy to user failed\n"); + mutex_unlock(&rmnet_ipa3_ctx->pipe_handle_guard); + return -EFAULT; + } + mutex_unlock(&rmnet_ipa3_ctx->pipe_handle_guard); + rmnet_ipa3_ctx->egress_set = true; + + return 0; +} + /** * ipa3_wwan_ioctl() - I/O control for wwan network driver. * @@ -1782,6 +2330,7 @@ static int ipa3_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) struct ipa_msg_meta msg_meta; struct ipa_wan_msg *wan_msg = NULL; struct rmnet_ioctl_extended_s ext_ioctl_data; + struct rmnet_ioctl_extended_s_v2 ext_ioctl_v2_data; struct rmnet_ioctl_data_s ioctl_data; struct ipa3_rmnet_mux_val *mux_channel; int rmnet_index; @@ -2127,6 +2676,43 @@ static int ipa3_wwan_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd) rc = -EINVAL; } break; + case RMNET_IOCTL_EXTENDED_V2: + IPAWANDBG("RMNET_IOCTL_EXTENDED_V2 received\n"); + if (copy_from_user(&ext_ioctl_v2_data, + (u8 *)ifr->ifr_ifru.ifru_data, + sizeof(struct rmnet_ioctl_extended_s_v2))) { + IPAWANERR("failed to copy extended ioctl data\n"); + rc = -EFAULT; + break; + } + switch (ext_ioctl_v2_data.extended_v2_ioctl_type) { + case RMNET_IOCTL_SET_EGRESS_DATA_FORMAT_V2: + if (ext_ioctl_v2_data.ioctl_data_size != + sizeof(struct egress_format_v2)) { + IPAWANERR("Egress ioctl v2 format size mismatch\n"); + rc = -EFAULT; + break; + } + rc = handle3_egress_format_v2(dev, + ext_ioctl_v2_data.ioctl_ptr); + break; + case RMNET_IOCTL_SET_INGRESS_DATA_FORMAT_V2: + if (ext_ioctl_v2_data.ioctl_data_size != + sizeof(struct ingress_format_v2)) { + IPAWANERR("ingress ioctl v2 format size mismatch\n"); + rc = -EFAULT; + break; + } + rc = handle3_ingress_format_v2(dev, + ext_ioctl_v2_data.ioctl_ptr); + break; + default: + IPAWANERR("%d is Unsupported extended ioctl v2\n", + ext_ioctl_v2_data.extended_v2_ioctl_type); + rc = -EINVAL; + break; + } + break; default: IPAWANERR("[%s] unsupported cmd[%d]", dev->name, cmd); @@ -2509,7 +3095,7 @@ static void ipa3_wwan_deregister_netdev_pm_client(void) */ static int ipa3_wwan_probe(struct platform_device *pdev) { - int ret, i; + int ret, i, j; struct net_device *dev; int wan_cons_ep; @@ -2659,6 +3245,15 @@ static int ipa3_wwan_probe(struct platform_device *pdev) atomic_set(&rmnet_ipa3_ctx->ap_suspend, 0); ipa3_update_ssr_state(false); + for (j = 0; j < RMNET_INGRESS_MAX; j++) { + ingress_pipe_status[j].ep_type = 0; + ingress_pipe_status[j].status = 0; + } + for (j = 0; j < RMNET_EGRESS_MAX; j++) { + egress_pipe_status[j].ep_type = 0; + egress_pipe_status[j].status = 0; + } + IPAWANERR("rmnet_ipa completed initialization\n"); return 0; config_err: @@ -2684,7 +3279,7 @@ wan_ioctl_init_err: static int ipa3_wwan_remove(struct platform_device *pdev) { - int ret; + int ret, j; IPAWANINFO("rmnet_ipa started deinitialization\n"); mutex_lock(&rmnet_ipa3_ctx->pipe_handle_guard); @@ -2703,6 +3298,15 @@ static int ipa3_wwan_remove(struct platform_device *pdev) IPAWANERR("Failed to teardown APPS->IPA pipe\n"); else rmnet_ipa3_ctx->apps_to_ipa3_hdl = -1; + /* Clear pipe setup info */ + for (j = 0; j < RMNET_INGRESS_MAX; j++) { + ingress_pipe_status[j].ep_type = 0; + ingress_pipe_status[j].status = 0; + } + for (j = 0; j < RMNET_EGRESS_MAX; j++) { + egress_pipe_status[j].ep_type = 0; + egress_pipe_status[j].status = 0; + } mutex_unlock(&rmnet_ipa3_ctx->pipe_handle_guard); IPAWANINFO("rmnet_ipa unregister_netdev\n"); unregister_netdev(IPA_NETDEV());