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:
parent
683ff3e645
commit
f127bb6378
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
@ -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,
|
||||
GFP_ATOMIC);
|
||||
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 */
|
||||
|
@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
Loading…
Reference in New Issue
Block a user