msm: ipa3: tx optimization - caching tx_wrapper

Caching tx_wrapper for tx DP optimization.
This change modifies tx_wrapper allocation from completely
dynamic,to partially dynamic for the WAN and LAN producer pipes.

A new list of free tx_wrapper is added,this can
dynmically decrease and grow, with a thereshold
which is initially read from the dts, and can be
changed via debugfs on runtime.

Change-Id: I60032a67f9ae87baeb42848cc312bf211c84f4e0
Acked-by: Tal Gelbard <tgelbard@qti.qualcomm.com>
Acked-by: Chemin Hsieh <cheminh@qti.qualcomm.com>
Signed-off-by: Jennifer L. Zenner <jzenner@codeaurora.org>
This commit is contained in:
Jennifer L. Zenner 2018-10-23 15:01:27 -04:00 committed by Gerrit - the friendly Code Review server
parent 683ff3e645
commit f127bb6378
4 changed files with 104 additions and 11 deletions

View File

@ -6562,6 +6562,13 @@ static inline void ipa3_enable_napi_netdev(void)
}
}
static u32 get_tx_wrapper_cache_size(u32 cache_size)
{
if (cache_size <= IPA_TX_WRAPPER_CACHE_MAX_THRESHOLD)
return cache_size;
return IPA_TX_WRAPPER_CACHE_MAX_THRESHOLD;
}
/**
* ipa3_pre_init() - Initialize the IPA Driver.
* This part contains all initialization which doesn't require IPA HW, such
@ -6672,6 +6679,8 @@ static int ipa3_pre_init(const struct ipa3_plat_drv_res *resource_p,
resource_p->do_ram_collection_on_crash;
ipa3_ctx->lan_rx_napi_enable = resource_p->lan_rx_napi_enable;
ipa3_ctx->rmnet_ctl_enable = resource_p->rmnet_ctl_enable;
ipa3_ctx->tx_wrapper_cache_max_size = get_tx_wrapper_cache_size(
resource_p->tx_wrapper_cache_max_size);
if (resource_p->gsi_fw_file_name) {
ipa3_ctx->gsi_fw_file_name =
@ -7381,6 +7390,22 @@ static int get_ipa_dts_pm_info(struct platform_device *pdev,
return 0;
}
static void get_dts_tx_wrapper_cache_size(struct platform_device *pdev,
struct ipa3_plat_drv_res *ipa_drv_res)
{
int result;
result = of_property_read_u32 (
pdev->dev.of_node,
"qcom,tx-wrapper-cache-max-size",
&ipa_drv_res->tx_wrapper_cache_max_size);
if (result)
ipa_drv_res->tx_wrapper_cache_max_size = 0;
IPADBG("tx_wrapper_cache_max_size is set to %d",
ipa_drv_res->tx_wrapper_cache_max_size);
}
static int get_ipa_dts_configuration(struct platform_device *pdev,
struct ipa3_plat_drv_res *ipa_drv_res)
{
@ -7843,6 +7868,8 @@ static int get_ipa_dts_configuration(struct platform_device *pdev,
IPADBG(": secure-debug-check-action = %d\n",
ipa_drv_res->secure_debug_check_action);
get_dts_tx_wrapper_cache_size(pdev, ipa_drv_res);
return 0;
}

View File

@ -3042,6 +3042,14 @@ void ipa3_debugfs_init(void)
goto fail;
}
file = debugfs_create_u32("tx_wrapper_cache_max_size",
IPA_READ_WRITE_MODE,
dent, &ipa3_ctx->tx_wrapper_cache_max_size);
if (!file) {
IPAERR("could not create tx_wrapper_cache_max_size file\n");
goto fail;
}
file = debugfs_create_u32("enable_napi_chain", IPA_READ_WRITE_MODE,
dent, &ipa3_ctx->enable_napi_chain);
if (!file) {

View File

@ -1,3 +1,4 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (c) 2012-2020, The Linux Foundation. All rights reserved.
@ -140,6 +141,9 @@ static void ipa3_wq_write_done_common(struct ipa3_sys_context *sys,
{
struct ipa3_tx_pkt_wrapper *next_pkt;
int i, cnt;
void *user1;
int user2;
void (*callback)(void *user1, int user2);
if (unlikely(tx_pkt == NULL)) {
IPAERR("tx_pkt is NULL\n");
@ -157,7 +161,6 @@ static void ipa3_wq_write_done_common(struct ipa3_sys_context *sys,
next_pkt = list_next_entry(tx_pkt, link);
list_del(&tx_pkt->link);
sys->len--;
spin_unlock_bh(&sys->spinlock);
if (!tx_pkt->no_unmap_dma) {
if (tx_pkt->type != IPA_DATA_DESC_SKB_PAGED) {
dma_unmap_single(ipa3_ctx->pdev,
@ -171,10 +174,22 @@ static void ipa3_wq_write_done_common(struct ipa3_sys_context *sys,
DMA_TO_DEVICE);
}
}
if (tx_pkt->callback)
tx_pkt->callback(tx_pkt->user1, tx_pkt->user2);
kmem_cache_free(ipa3_ctx->tx_pkt_wrapper_cache, tx_pkt);
callback = tx_pkt->callback;
user1 = tx_pkt->user1;
user2 = tx_pkt->user2;
if (sys->avail_tx_wrapper >=
ipa3_ctx->tx_wrapper_cache_max_size ||
sys->ep->client == IPA_CLIENT_APPS_CMD_PROD) {
kmem_cache_free(ipa3_ctx->tx_pkt_wrapper_cache,
tx_pkt);
} else {
list_add_tail(&tx_pkt->link,
&sys->avail_tx_wrapper_list);
sys->avail_tx_wrapper++;
}
spin_unlock_bh(&sys->spinlock);
if (callback)
(*callback)(user1, user2);
tx_pkt = next_pkt;
}
}
@ -239,12 +254,21 @@ static void ipa3_send_nop_desc(struct work_struct *work)
struct ipa3_tx_pkt_wrapper *tx_pkt;
IPADBG_LOW("gsi send NOP for ch: %lu\n", sys->ep->gsi_chan_hdl);
if (atomic_read(&sys->workqueue_flushed))
return;
tx_pkt = kmem_cache_zalloc(ipa3_ctx->tx_pkt_wrapper_cache, GFP_KERNEL);
spin_lock_bh(&sys->spinlock);
if (!list_empty(&sys->avail_tx_wrapper_list)) {
tx_pkt = list_first_entry(&sys->avail_tx_wrapper_list,
struct ipa3_tx_pkt_wrapper, link);
list_del(&tx_pkt->link);
sys->avail_tx_wrapper--;
memset(tx_pkt, 0, sizeof(struct ipa3_tx_pkt_wrapper));
} else {
tx_pkt = kmem_cache_zalloc(ipa3_ctx->tx_pkt_wrapper_cache,
GFP_KERNEL);
}
if (!tx_pkt) {
spin_unlock_bh(&sys->spinlock);
queue_work(sys->wq, &sys->work);
return;
}
@ -253,7 +277,6 @@ static void ipa3_send_nop_desc(struct work_struct *work)
tx_pkt->cnt = 1;
tx_pkt->no_unmap_dma = true;
tx_pkt->sys = sys;
spin_lock_bh(&sys->spinlock);
if (unlikely(!sys->nop_pending)) {
spin_unlock_bh(&sys->spinlock);
kmem_cache_free(ipa3_ctx->tx_pkt_wrapper_cache, tx_pkt);
@ -349,8 +372,18 @@ int ipa3_send(struct ipa3_sys_context *sys,
spin_lock_bh(&sys->spinlock);
for (i = 0; i < num_desc; i++) {
tx_pkt = kmem_cache_zalloc(ipa3_ctx->tx_pkt_wrapper_cache,
if (!list_empty(&sys->avail_tx_wrapper_list)) {
tx_pkt = list_first_entry(&sys->avail_tx_wrapper_list,
struct ipa3_tx_pkt_wrapper, link);
list_del(&tx_pkt->link);
sys->avail_tx_wrapper--;
memset(tx_pkt, 0, sizeof(struct ipa3_tx_pkt_wrapper));
} else {
tx_pkt = kmem_cache_zalloc(
ipa3_ctx->tx_pkt_wrapper_cache,
GFP_ATOMIC);
}
if (!tx_pkt) {
IPAERR("failed to alloc tx wrapper\n");
result = -ENOMEM;
@ -1035,6 +1068,8 @@ int ipa3_setup_sys_pipe(struct ipa_sys_connect_params *sys_in, u32 *clnt_hdl)
INIT_LIST_HEAD(&ep->sys->head_desc_list);
INIT_LIST_HEAD(&ep->sys->rcycl_list);
INIT_LIST_HEAD(&ep->sys->avail_tx_wrapper_list);
ep->sys->avail_tx_wrapper = 0;
spin_lock_init(&ep->sys->spinlock);
hrtimer_init(&ep->sys->db_timer, CLOCK_MONOTONIC,
HRTIMER_MODE_REL);
@ -1282,6 +1317,22 @@ fail_gen:
return result;
}
static void delete_avail_tx_wrapper_list(struct ipa3_ep_context *ep)
{
struct ipa3_tx_pkt_wrapper *tx_pkt_iterator = NULL;
struct ipa3_tx_pkt_wrapper *tx_pkt_temp = NULL;
spin_lock_bh(&ep->sys->spinlock);
list_for_each_entry_safe(tx_pkt_iterator, tx_pkt_temp,
&ep->sys->avail_tx_wrapper_list, link) {
list_del(&tx_pkt_iterator->link);
kmem_cache_free(ipa3_ctx->tx_pkt_wrapper_cache, tx_pkt_iterator);
ep->sys->avail_tx_wrapper--;
}
ep->sys->avail_tx_wrapper = 0;
spin_unlock_bh(&ep->sys->spinlock);
}
/**
* ipa3_teardown_sys_pipe() - Teardown the GPI pipe and cleanup IPA EP
* @clnt_hdl: [in] the handle obtained from ipa3_setup_sys_pipe
@ -1318,6 +1369,8 @@ int ipa3_teardown_sys_pipe(u32 clnt_hdl)
else
break;
} while (1);
delete_avail_tx_wrapper_list(ep);
}
/* channel stop might fail on timeout if IPA is busy */

View File

@ -210,6 +210,7 @@
#define IPA3_ACTIVE_CLIENTS_LOG_HASHTABLE_SIZE 50
#define IPA3_ACTIVE_CLIENTS_LOG_NAME_LEN 40
#define SMEM_IPA_FILTER_TABLE 497
#define IPA_TX_WRAPPER_CACHE_MAX_THRESHOLD 2000
enum {
SMEM_APPS,
@ -1066,6 +1067,8 @@ struct ipa3_sys_context {
struct ipa3_ep_context *ep;
struct list_head head_desc_list;
struct list_head rcycl_list;
struct list_head avail_tx_wrapper_list;
u32 avail_tx_wrapper;
spinlock_t spinlock;
struct hrtimer db_timer;
struct workqueue_struct *wq;
@ -2062,6 +2065,7 @@ struct ipa3_context {
u32 icc_num_paths;
u32 icc_clk[IPA_ICC_LVL_MAX][IPA_ICC_PATH_MAX][IPA_ICC_TYPE_MAX];
struct ipahal_imm_cmd_pyld *coal_cmd_pyld;
u32 tx_wrapper_cache_max_size;
struct ipa3_app_clock_vote app_clock_vote;
bool clients_registered;
bool rmnet_ctl_enable;
@ -2122,6 +2126,7 @@ struct ipa3_plat_drv_res {
bool rmnet_ctl_enable;
const char *gsi_fw_file_name;
const char *uc_fw_file_name;
u32 tx_wrapper_cache_max_size;
};
/**