Explorar el Código

Merge "ipa: FC aggregation on ICMP packets to TX LAN"

qctecmdr hace 4 años
padre
commit
1cb8ee8406

+ 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