Browse Source

ipa: FC aggregation on ICMP packets to TX LAN

In order to reduce ICMP packets latency,
use aggregation force close flag.
Since those packets are sent with the packet init IMM,
port the relevant code to use the extended packet init IMM.

Change-Id: Idba27352c0b6ce1b2b11b9c15a5ed4a847442df6
Signed-off-by: Ilia Lin <[email protected]>
Ilia Lin 4 years ago
parent
commit
9924fa7dfe

+ 77 - 30
drivers/platform/msm/ipa/ipa_v3/ipa.c

@@ -7501,7 +7501,8 @@ static int ipa_alloc_pkt_init_ex(void)
 	struct ipa_mem_buffer *mem = &ipa3_ctx->pkt_init_ex_mem;
 	struct ipahal_imm_cmd_pyld *cmd_pyld;
 	struct ipahal_imm_cmd_ip_packet_init_ex cmd = {0};
-	int i;
+	struct ipahal_imm_cmd_ip_packet_init_ex cmd_mask = {0};
+	int result = 0;
 
 	cmd_pyld = ipahal_construct_imm_cmd(IPA_IMM_CMD_IP_PACKET_INIT_EX,
 		&cmd, false);
@@ -7511,42 +7512,88 @@ static int ipa_alloc_pkt_init_ex(void)
 	}
 	ipa3_ctx->pkt_init_ex_imm_opcode = cmd_pyld->opcode;
 
-	mem->size = cmd_pyld->len * ipa3_ctx->ipa_num_pipes;
-	ipahal_destroy_imm_cmd(cmd_pyld);
+	/* one cmd for each pipe for ULSO + one common for ICMP */
+	mem->size = cmd_pyld->len * (ipa3_ctx->ipa_num_pipes + 1);
 	mem->base = dma_alloc_coherent(ipa3_ctx->pdev, mem->size,
 		&mem->phys_base, GFP_KERNEL);
 	if (!mem->base) {
 		IPAERR("failed to alloc DMA buff of size %d\n", mem->size);
-		return -ENOMEM;
+		result = -ENOMEM;
+		goto free_imm;
 	}
 
 	memset(mem->base, 0, mem->size);
-	for (i = 0; i < ipa3_ctx->ipa_num_pipes; i++) {
-		cmd.frag_disable = true;
-		cmd.nat_disable = true;
-		cmd.filter_disable = true;
-		cmd.route_disable = true;
-		cmd.hdr_removal_insertion_disable = false;
-		cmd.cs_disable = false;
-		cmd.flt_retain_hdr = true;
-		cmd.rt_retain_hdr = true;
-		cmd.rt_pipe_dest_idx = i;
-		cmd_pyld = ipahal_construct_imm_cmd(IPA_IMM_CMD_IP_PACKET_INIT_EX,
-			&cmd, false);
-		if (!cmd_pyld) {
-			IPAERR("failed to construct IMM cmd\n");
-			dma_free_coherent(ipa3_ctx->pdev,
-				mem->size,
-				mem->base,
-				mem->phys_base);
-			return -ENOMEM;
-		}
-		memcpy(mem->base + i * cmd_pyld->len, cmd_pyld->data, cmd_pyld->len);
-		ipa3_ctx->pkt_init_ex_imm[i] = mem->phys_base + i * cmd_pyld->len;
-		ipahal_destroy_imm_cmd(cmd_pyld);
-	}
-
-	return 0;
+	cmd.frag_disable = true;
+	cmd_mask.frag_disable = true;
+	cmd.nat_disable = true;
+	cmd_mask.nat_disable = true;
+	cmd.filter_disable = true;
+	cmd_mask.filter_disable = true;
+	cmd.route_disable = true;
+	cmd_mask.route_disable = true;
+	cmd.hdr_removal_insertion_disable = false;
+	cmd_mask.hdr_removal_insertion_disable = true;
+	cmd.cs_disable = false;
+	cmd_mask.cs_disable = true;
+	cmd.flt_retain_hdr = true;
+	cmd_mask.flt_retain_hdr = true;
+	cmd.rt_retain_hdr = true;
+	cmd_mask.rt_retain_hdr = true;
+	cmd_mask.rt_pipe_dest_idx = true;
+	for (cmd.rt_pipe_dest_idx = 0;
+	      cmd.rt_pipe_dest_idx < ipa3_ctx->ipa_num_pipes;
+	      cmd.rt_pipe_dest_idx++) {
+		result = ipahal_modify_imm_cmd(IPA_IMM_CMD_IP_PACKET_INIT_EX,
+			cmd_pyld->data, &cmd, &cmd_mask);
+		if (unlikely(result != 0)) {
+			IPAERR("failed to modify IMM cmd\n");
+			goto free_dma;
+		}
+		memcpy(mem->base + cmd.rt_pipe_dest_idx * cmd_pyld->len,
+			cmd_pyld->data, cmd_pyld->len);
+		ipa3_ctx->pkt_init_ex_imm[cmd.rt_pipe_dest_idx].phys_base =
+			mem->phys_base + cmd.rt_pipe_dest_idx * cmd_pyld->len;
+		ipa3_ctx->pkt_init_ex_imm[cmd.rt_pipe_dest_idx].base =
+			mem->base + cmd.rt_pipe_dest_idx * cmd_pyld->len;
+		ipa3_ctx->pkt_init_ex_imm[cmd.rt_pipe_dest_idx].size =
+			cmd_pyld->len;
+	}
+
+	cmd.hdr_removal_insertion_disable = true;
+	cmd.cs_disable = true;
+	cmd.flt_retain_hdr = false;
+	cmd.rt_retain_hdr = false;
+	cmd.flt_close_aggr_irq_mod = true;
+	cmd_mask.flt_close_aggr_irq_mod = true;
+	cmd.rt_close_aggr_irq_mod = true;
+	cmd_mask.rt_close_aggr_irq_mod = true;
+	/* Just a placeholder. Will be assigned in the DP, before sending. */
+	cmd.rt_pipe_dest_idx = ipa3_ctx->ipa_num_pipes;
+	result = ipahal_modify_imm_cmd(IPA_IMM_CMD_IP_PACKET_INIT_EX,
+		cmd_pyld->data, &cmd, &cmd_mask);
+	if (unlikely(result != 0)) {
+		IPAERR("failed to modify IMM cmd\n");
+		goto free_dma;
+	}
+	memcpy(mem->base + ipa3_ctx->ipa_num_pipes * cmd_pyld->len,
+		cmd_pyld->data,
+		cmd_pyld->len);
+	ipa3_ctx->pkt_init_ex_imm[ipa3_ctx->ipa_num_pipes].phys_base =
+		mem->phys_base + ipa3_ctx->ipa_num_pipes * cmd_pyld->len;
+	ipa3_ctx->pkt_init_ex_imm[ipa3_ctx->ipa_num_pipes].base =
+		mem->base + ipa3_ctx->ipa_num_pipes * cmd_pyld->len;
+	ipa3_ctx->pkt_init_ex_imm[ipa3_ctx->ipa_num_pipes].size = cmd_pyld->len;
+
+	goto free_imm;
+
+free_dma:
+	dma_free_coherent(ipa3_ctx->pdev,
+		mem->size,
+		mem->base,
+		mem->phys_base);
+free_imm:
+	ipahal_destroy_imm_cmd(cmd_pyld);
+	return result;
 }
 
 /*

+ 25 - 4
drivers/platform/msm/ipa/ipa_v3/ipa_dp.c

@@ -10,7 +10,9 @@
 #include <linux/list.h>
 #include <linux/netdevice.h>
 #include <linux/msm_gsi.h>
+#include <uapi/linux/ip.h>
 #include <net/sock.h>
+#include <net/ipv6.h>
 #include <asm/page.h>
 #include "gsi.h"
 #include "ipa_i.h"
@@ -582,7 +584,7 @@ int ipa3_send(struct ipa3_sys_context *sys,
 	return 0;
 
 failure_dma_map:
-		kmem_cache_free(ipa3_ctx->tx_pkt_wrapper_cache, tx_pkt);
+	kmem_cache_free(ipa3_ctx->tx_pkt_wrapper_cache, tx_pkt);
 
 failure:
 	ipahal_destroy_imm_cmd(tag_pyld_ret);
@@ -1810,10 +1812,14 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
 	}
 
 	if (dst_ep_idx != -1) {
+		/* SW data path */
 		int skb_idx;
+		struct iphdr *network_header;
+
+		network_header = (struct iphdr *)(skb_network_header(skb));
 
-		/* SW data path */
 		data_idx = 0;
+
 		if (sys->policy == IPA_POLICY_NOINTR_MODE) {
 			/*
 			 * For non-interrupt mode channel (where there is no
@@ -1824,9 +1830,24 @@ int ipa3_tx_dp(enum ipa_client_type dst, struct sk_buff *skb,
 			desc[data_idx].is_tag_status = true;
 			data_idx++;
 		}
-		desc[data_idx].opcode = ipa3_ctx->pkt_init_imm_opcode;
+
+		if ((network_header->version == 4 &&
+		     network_header->protocol == IPPROTO_ICMP) ||
+		    (((struct ipv6hdr *)network_header)->version == 6 &&
+		     ((struct ipv6hdr *)network_header)->nexthdr == NEXTHDR_ICMP)) {
+			ipa_imm_cmd_modify_ip_packet_init_ex_dest_pipe(
+				ipa3_ctx->pkt_init_ex_imm[ipa3_ctx->ipa_num_pipes].base,
+				dst_ep_idx);
+			desc[data_idx].opcode =
+				ipa3_ctx->pkt_init_ex_imm_opcode;
+			desc[data_idx].dma_address =
+				ipa3_ctx->pkt_init_ex_imm[ipa3_ctx->ipa_num_pipes].phys_base;
+		} else {
+			desc[data_idx].opcode = ipa3_ctx->pkt_init_imm_opcode;
+			desc[data_idx].dma_address =
+				ipa3_ctx->pkt_init_imm[dst_ep_idx];
+		}
 		desc[data_idx].dma_address_valid = true;
-		desc[data_idx].dma_address = ipa3_ctx->pkt_init_imm[dst_ep_idx];
 		desc[data_idx].type = IPA_IMM_CMD_DESC;
 		desc[data_idx].callback = NULL;
 		data_idx++;

+ 3 - 1
drivers/platform/msm/ipa/ipa_v3/ipa_i.h

@@ -72,6 +72,8 @@
 #define IPA_HOLB_TMR_DIS 0x0
 #define IPA_HOLB_TMR_EN 0x1
 #define IPA_HOLB_TMR_VAL_4_5 31
+#define IPA_IMM_IP_PACKET_INIT_EX_CMD_NUM (IPA5_MAX_NUM_PIPES + 1)
+
 /*
  * The transport descriptor size was changed to GSI_CHAN_RE_SIZE_16B, but
  * IPA users still use sps_iovec size as FIFO element size.
@@ -2200,10 +2202,10 @@ struct ipa3_context {
 	u32 ipa_wdi3_5g_holb_timeout;
 	bool is_wdi3_tx1_needed;
 	bool ipa_endp_delay_wa_v2;
-	dma_addr_t pkt_init_ex_imm[IPA5_MAX_NUM_PIPES];
 	u32 pkt_init_ex_imm_opcode;
 	struct ipa_mem_buffer pkt_init_mem;
 	struct ipa_mem_buffer pkt_init_ex_mem;
+	struct ipa_mem_buffer pkt_init_ex_imm[IPA_IMM_IP_PACKET_INIT_EX_CMD_NUM];
 };
 
 struct ipa3_plat_drv_res {

+ 8 - 0
drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c

@@ -461,6 +461,14 @@ int ipa_imm_cmd_modify_ip_packet_init_ex(
 	return 0;
 }
 
+inline void ipa_imm_cmd_modify_ip_packet_init_ex_dest_pipe(
+	const void *cmd_data,
+	u64 pipe_dest_idx)
+{
+	((struct ipa_imm_cmd_hw_ip_packet_init_ex *)cmd_data)->rt_pipe_dest_idx
+		= pipe_dest_idx;
+}
+
 static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_nat_dma(
 	enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
 {

+ 11 - 0
drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h

@@ -426,6 +426,17 @@ int ipahal_modify_imm_cmd(
 	const void *params,
 	const void *params_mask);
 
+/*
+ * ipa_imm_cmd_modify_ip_packet_init_ex_dest_pipe() -
+ *   Modify ip_packet_init_ex immdiate command pipe_dest_idx field
+ * This function modifies an existing imm cmd buffer
+ * @cmd_data: [in] Constructed immediate command buffer data
+ * @pipe_dest_idx: [in] destination pipe index to set
+ */
+void ipa_imm_cmd_modify_ip_packet_init_ex_dest_pipe(
+	const void *cmd_data,
+	u64 pipe_dest_idx);
+
 /*
  * ipahal_construct_nop_imm_cmd() - Construct immediate comamnd for NO-Op
  * Core driver may want functionality to inject NOP commands to IPA