Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit f127bb63 authored by Jennifer L. Zenner's avatar Jennifer L. Zenner Committed by Gerrit - the friendly Code Review server
Browse files

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: default avatarTal Gelbard <tgelbard@qti.qualcomm.com>
Acked-by: default avatarChemin Hsieh <cheminh@qti.qualcomm.com>
Signed-off-by: default avatarJennifer L. Zenner <jzenner@codeaurora.org>
parent 683ff3e6
Loading
Loading
Loading
Loading
+27 −0
Original line number Diff line number Diff line
@@ -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;
}

+8 −0
Original line number Diff line number Diff line
@@ -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) {
+64 −11
Original line number Diff line number Diff line

// 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 @@ int ipa3_setup_sys_pipe(struct ipa_sys_connect_params *sys_in, u32 *clnt_hdl)
	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 */
+5 −0
Original line number Diff line number Diff line
@@ -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;
};

/**