msm: ipa4: add IPv6CT support
IPAv4 HW presents new IPv6 connection tracking functionality.
This change adds SW support of this feature.
Change-Id: I7545af08f090405db80bbd8c10223ca7521080d9
Acked-by: Dmitry Kogan <dmitryk@qti.qualcomm.com>
Signed-off-by: Amir Levy <alevy@codeaurora.org>
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/Makefile b/drivers/platform/msm/ipa/ipa_v3/ipahal/Makefile
index 67e491b..869ee7e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/Makefile
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/Makefile
@@ -1,3 +1,3 @@
obj-$(CONFIG_IPA3) += ipa_hal.o
-ipa_hal-y := ipahal.o ipahal_reg.o ipahal_fltrt.o ipahal_hw_stats.o
+ipa_hal-y := ipahal.o ipahal_reg.o ipahal_fltrt.o ipahal_hw_stats.o ipahal_nat.o
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
index a8d5342..d015b22 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.c
@@ -16,7 +16,7 @@
#include "ipahal_reg_i.h"
#include "ipahal_fltrt_i.h"
#include "ipahal_hw_stats_i.h"
-
+#include "ipahal_nat_i.h"
struct ipahal_context *ipahal_ctx;
@@ -35,6 +35,7 @@
__stringify(IPA_IMM_CMD_IP_PACKET_TAG_STATUS),
__stringify(IPA_IMM_CMD_DMA_TASK_32B_ADDR),
__stringify(IPA_IMM_CMD_TABLE_DMA),
+ __stringify(IPA_IMM_CMD_IP_V6_CT_INIT)
};
static const char *ipahal_pkt_status_exception_to_str
@@ -352,8 +353,8 @@
{
struct ipahal_imm_cmd_pyld *pyld;
struct ipa_imm_cmd_hw_nat_dma *data;
- struct ipahal_imm_cmd_nat_dma *nat_params =
- (struct ipahal_imm_cmd_nat_dma *)params;
+ struct ipahal_imm_cmd_table_dma *nat_params =
+ (struct ipahal_imm_cmd_table_dma *)params;
pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
if (unlikely(!pyld)) {
@@ -519,24 +520,55 @@
pyld->len = sizeof(*data);
data = (struct ipa_imm_cmd_hw_ip_v4_nat_init *)pyld->data;
- data->ipv4_rules_addr = nat4_params->ipv4_rules_addr;
+ data->ipv4_rules_addr = nat4_params->table_init.base_table_addr;
data->ipv4_expansion_rules_addr =
- nat4_params->ipv4_expansion_rules_addr;
+ nat4_params->table_init.expansion_table_addr;
data->index_table_addr = nat4_params->index_table_addr;
data->index_table_expansion_addr =
nat4_params->index_table_expansion_addr;
- data->table_index = nat4_params->table_index;
+ data->table_index = nat4_params->table_init.table_index;
data->ipv4_rules_addr_type =
- nat4_params->ipv4_rules_addr_shared ? 1 : 0;
+ nat4_params->table_init.base_table_addr_shared ? 1 : 0;
data->ipv4_expansion_rules_addr_type =
- nat4_params->ipv4_expansion_rules_addr_shared ? 1 : 0;
+ nat4_params->table_init.expansion_table_addr_shared ? 1 : 0;
data->index_table_addr_type =
nat4_params->index_table_addr_shared ? 1 : 0;
data->index_table_expansion_addr_type =
nat4_params->index_table_expansion_addr_shared ? 1 : 0;
- data->size_base_tables = nat4_params->size_base_tables;
- data->size_expansion_tables = nat4_params->size_expansion_tables;
- data->public_ip_addr = nat4_params->public_ip_addr;
+ data->size_base_tables = nat4_params->table_init.size_base_table;
+ data->size_expansion_tables =
+ nat4_params->table_init.size_expansion_table;
+ data->public_addr_info = nat4_params->public_addr_info;
+
+ return pyld;
+}
+
+static struct ipahal_imm_cmd_pyld *ipa_imm_cmd_construct_ip_v6_ct_init(
+ enum ipahal_imm_cmd_name cmd, const void *params, bool is_atomic_ctx)
+{
+ struct ipahal_imm_cmd_pyld *pyld;
+ struct ipa_imm_cmd_hw_ip_v6_ct_init *data;
+ struct ipahal_imm_cmd_ip_v6_ct_init *ipv6ct_params =
+ (struct ipahal_imm_cmd_ip_v6_ct_init *)params;
+
+ pyld = IPAHAL_MEM_ALLOC(sizeof(*pyld) + sizeof(*data), is_atomic_ctx);
+ if (unlikely(!pyld))
+ return pyld;
+ pyld->opcode = ipahal_imm_cmd_get_opcode(cmd);
+ pyld->len = sizeof(*data);
+ data = (struct ipa_imm_cmd_hw_ip_v6_ct_init *)pyld->data;
+
+ data->table_addr = ipv6ct_params->table_init.base_table_addr;
+ data->expansion_table_addr =
+ ipv6ct_params->table_init.expansion_table_addr;
+ data->table_index = ipv6ct_params->table_init.table_index;
+ data->table_addr_type =
+ ipv6ct_params->table_init.base_table_addr_shared ? 1 : 0;
+ data->expansion_table_addr_type =
+ ipv6ct_params->table_init.expansion_table_addr_shared ? 1 : 0;
+ data->size_base_table = ipv6ct_params->table_init.size_base_table;
+ data->size_expansion_table =
+ ipv6ct_params->table_init.size_expansion_table;
return pyld;
}
@@ -685,6 +717,9 @@
[IPA_HW_v4_0][IPA_IMM_CMD_DMA_SHARED_MEM] = {
ipa_imm_cmd_construct_dma_shared_mem_v_4_0,
19},
+ [IPA_HW_v4_0][IPA_IMM_CMD_IP_V6_CT_INIT] = {
+ ipa_imm_cmd_construct_ip_v6_ct_init,
+ 23}
};
/*
@@ -1526,13 +1561,21 @@
if (ipahal_hw_stats_init(ipa_hw_type)) {
IPAHAL_ERR("failed to init ipahal hw stats\n");
result = -EFAULT;
- goto bail_free_ctx;
+ goto bail_free_fltrt;
+ }
+
+ if (ipahal_nat_init(ipa_hw_type)) {
+ IPAHAL_ERR("failed to init ipahal NAT\n");
+ result = -EFAULT;
+ goto bail_free_fltrt;
}
ipahal_debugfs_init();
return 0;
+bail_free_fltrt:
+ ipahal_fltrt_destroy();
bail_free_ctx:
kfree(ipahal_ctx);
ipahal_ctx = NULL;
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
index 56b884b..0c2697c 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal.h
@@ -37,6 +37,7 @@
IPA_IMM_CMD_IP_PACKET_TAG_STATUS,
IPA_IMM_CMD_DMA_TASK_32B_ADDR,
IPA_IMM_CMD_TABLE_DMA,
+ IPA_IMM_CMD_IP_V6_CT_INIT,
IPA_IMM_CMD_MAX,
};
@@ -46,19 +47,19 @@
* struct ipahal_imm_cmd_ip_v4_filter_init - IP_V4_FILTER_INIT cmd payload
* Inits IPv4 filter block.
* @hash_rules_addr: Addr in sys mem where ipv4 hashable flt tbl starts
+ * @nhash_rules_addr: Addr in sys mem where ipv4 non-hashable flt tbl starts
* @hash_rules_size: Size in bytes of the hashable tbl to cpy to local mem
* @hash_local_addr: Addr in shared mem where ipv4 hashable flt tbl should
* be copied to
- * @nhash_rules_addr: Addr in sys mem where ipv4 non-hashable flt tbl starts
* @nhash_rules_size: Size in bytes of the non-hashable tbl to cpy to local mem
* @nhash_local_addr: Addr in shared mem where ipv4 non-hashable flt tbl should
* be copied to
*/
struct ipahal_imm_cmd_ip_v4_filter_init {
u64 hash_rules_addr;
+ u64 nhash_rules_addr;
u32 hash_rules_size;
u32 hash_local_addr;
- u64 nhash_rules_addr;
u32 nhash_rules_size;
u32 nhash_local_addr;
};
@@ -67,79 +68,98 @@
* struct ipahal_imm_cmd_ip_v6_filter_init - IP_V6_FILTER_INIT cmd payload
* Inits IPv6 filter block.
* @hash_rules_addr: Addr in sys mem where ipv6 hashable flt tbl starts
+ * @nhash_rules_addr: Addr in sys mem where ipv6 non-hashable flt tbl starts
* @hash_rules_size: Size in bytes of the hashable tbl to cpy to local mem
* @hash_local_addr: Addr in shared mem where ipv6 hashable flt tbl should
* be copied to
- * @nhash_rules_addr: Addr in sys mem where ipv6 non-hashable flt tbl starts
* @nhash_rules_size: Size in bytes of the non-hashable tbl to cpy to local mem
* @nhash_local_addr: Addr in shared mem where ipv6 non-hashable flt tbl should
* be copied to
*/
struct ipahal_imm_cmd_ip_v6_filter_init {
u64 hash_rules_addr;
+ u64 nhash_rules_addr;
u32 hash_rules_size;
u32 hash_local_addr;
- u64 nhash_rules_addr;
u32 nhash_rules_size;
u32 nhash_local_addr;
};
/*
+ * struct ipahal_imm_cmd_nat_ipv6ct_init_common - NAT/IPv6CT table init command
+ * common part
+ * @base_table_addr: Address in sys/shared mem where base table start
+ * @expansion_table_addr: Address in sys/shared mem where expansion table
+ * starts. Entries that result in hash collision are located in this table.
+ * @base_table_addr_shared: base_table_addr in shared mem (if not, then sys)
+ * @expansion_table_addr_shared: expansion_rules_addr in
+ * shared mem (if not, then sys)
+ * @size_base_table: Num of entries in the base table
+ * @size_expansion_table: Num of entries in the expansion table
+ * @table_index: For future support of multiple tables
+ */
+struct ipahal_imm_cmd_nat_ipv6ct_init_common {
+ u64 base_table_addr;
+ u64 expansion_table_addr;
+ bool base_table_addr_shared;
+ bool expansion_table_addr_shared;
+ u16 size_base_table;
+ u16 size_expansion_table;
+ u8 table_index;
+};
+
+/*
* struct ipahal_imm_cmd_ip_v4_nat_init - IP_V4_NAT_INIT cmd payload
* Inits IPv4 NAT block. Initiate NAT table with it dimensions, location
- * cache address abd itger related parameters.
- * @table_index: For future support of multiple NAT tables
- * @ipv4_rules_addr: Addr in sys/shared mem where ipv4 NAT rules start
- * @ipv4_rules_addr_shared: ipv4_rules_addr in shared mem (if not, then sys)
- * @ipv4_expansion_rules_addr: Addr in sys/shared mem where expantion NAT
- * table starts. IPv4 NAT rules that result in NAT collision are located
- * in this table.
- * @ipv4_expansion_rules_addr_shared: ipv4_expansion_rules_addr in
- * shared mem (if not, then sys)
+ * cache address and other related parameters.
+ * @table_init: table initialization parameters
* @index_table_addr: Addr in sys/shared mem where index table, which points
* to NAT table starts
- * @index_table_addr_shared: index_table_addr in shared mem (if not, then sys)
* @index_table_expansion_addr: Addr in sys/shared mem where expansion index
* table starts
+ * @index_table_addr_shared: index_table_addr in shared mem (if not, then sys)
* @index_table_expansion_addr_shared: index_table_expansion_addr in
* shared mem (if not, then sys)
- * @size_base_tables: Num of entries in NAT tbl and idx tbl (each)
- * @size_expansion_tables: Num of entries in NAT expantion tbl and expantion
- * idx tbl (each)
- * @public_ip_addr: public IP address
+ * @public_addr_info: Public IP addresses info suitable to the IPA H/W version
+ * IPA H/W >= 4.0 - PDN config table offset in SMEM
+ * IPA H/W < 4.0 - The public IP address
*/
struct ipahal_imm_cmd_ip_v4_nat_init {
- u8 table_index;
- u64 ipv4_rules_addr;
- bool ipv4_rules_addr_shared;
- u64 ipv4_expansion_rules_addr;
- bool ipv4_expansion_rules_addr_shared;
+ struct ipahal_imm_cmd_nat_ipv6ct_init_common table_init;
u64 index_table_addr;
- bool index_table_addr_shared;
u64 index_table_expansion_addr;
+ bool index_table_addr_shared;
bool index_table_expansion_addr_shared;
- u16 size_base_tables;
- u16 size_expansion_tables;
- u32 public_ip_addr;
+ u32 public_addr_info;
+};
+
+/*
+ * struct ipahal_imm_cmd_ip_v6_ct_init - IP_V6_CONN_TRACK_INIT cmd payload
+ * Inits IPv6CT block. Initiate IPv6CT table with it dimensions, location
+ * cache address and other related parameters.
+ * @table_init: table initialization parameters
+ */
+struct ipahal_imm_cmd_ip_v6_ct_init {
+ struct ipahal_imm_cmd_nat_ipv6ct_init_common table_init;
};
/*
* struct ipahal_imm_cmd_ip_v4_routing_init - IP_V4_ROUTING_INIT cmd payload
* Inits IPv4 routing table/structure - with the rules and other related params
* @hash_rules_addr: Addr in sys mem where ipv4 hashable rt tbl starts
+ * @nhash_rules_addr: Addr in sys mem where ipv4 non-hashable rt tbl starts
* @hash_rules_size: Size in bytes of the hashable tbl to cpy to local mem
* @hash_local_addr: Addr in shared mem where ipv4 hashable rt tbl should
* be copied to
- * @nhash_rules_addr: Addr in sys mem where ipv4 non-hashable rt tbl starts
* @nhash_rules_size: Size in bytes of the non-hashable tbl to cpy to local mem
* @nhash_local_addr: Addr in shared mem where ipv4 non-hashable rt tbl should
* be copied to
*/
struct ipahal_imm_cmd_ip_v4_routing_init {
u64 hash_rules_addr;
+ u64 nhash_rules_addr;
u32 hash_rules_size;
u32 hash_local_addr;
- u64 nhash_rules_addr;
u32 nhash_rules_size;
u32 nhash_local_addr;
};
@@ -148,19 +168,19 @@
* struct ipahal_imm_cmd_ip_v6_routing_init - IP_V6_ROUTING_INIT cmd payload
* Inits IPv6 routing table/structure - with the rules and other related params
* @hash_rules_addr: Addr in sys mem where ipv6 hashable rt tbl starts
+ * @nhash_rules_addr: Addr in sys mem where ipv6 non-hashable rt tbl starts
* @hash_rules_size: Size in bytes of the hashable tbl to cpy to local mem
* @hash_local_addr: Addr in shared mem where ipv6 hashable rt tbl should
* be copied to
- * @nhash_rules_addr: Addr in sys mem where ipv6 non-hashable rt tbl starts
* @nhash_rules_size: Size in bytes of the non-hashable tbl to cpy to local mem
* @nhash_local_addr: Addr in shared mem where ipv6 non-hashable rt tbl should
* be copied to
*/
struct ipahal_imm_cmd_ip_v6_routing_init {
u64 hash_rules_addr;
+ u64 nhash_rules_addr;
u32 hash_rules_size;
u32 hash_local_addr;
- u64 nhash_rules_addr;
u32 nhash_rules_size;
u32 nhash_local_addr;
};
@@ -189,36 +209,20 @@
};
/*
- * struct ipahal_imm_cmd_nat_dma - NAT_DMA cmd payload
- * Perform DMA operation on NAT related mem addressess. Copy data into
- * different locations within NAT associated tbls. (For add/remove NAT rules)
- * @table_index: NAT tbl index. Defines the NAT tbl on which to perform DMA op.
- * @base_addr: Base addr to which the DMA operation should be performed.
- * @offset: offset in bytes from base addr to write 'data' to
- * @data: data to be written
- */
-struct ipahal_imm_cmd_nat_dma {
- u8 table_index;
- u8 base_addr;
- u32 offset;
- u16 data;
-};
-
-/*
* struct ipahal_imm_cmd_table_dma - TABLE_DMA cmd payload
* Perform DMA operation on NAT and IPV6 connection tracking related mem
- * addresses. Copy data into different locations within IPV6CT and NAT
+ * addresses. Copy data into different locations within IPv6CT and NAT
* associated tbls. (For add/remove NAT rules)
- * @table_index: NAT tbl index. Defines the tbl on which to perform DMA op.
- * @base_addr: Base addr to which the DMA operation should be performed.
* @offset: offset in bytes from base addr to write 'data' to
* @data: data to be written
+ * @table_index: NAT tbl index. Defines the tbl on which to perform DMA op.
+ * @base_addr: Base addr to which the DMA operation should be performed.
*/
struct ipahal_imm_cmd_table_dma {
- u8 table_index;
- u8 base_addr;
u32 offset;
u16 data;
+ u8 table_index;
+ u8 base_addr;
};
/*
@@ -275,6 +279,7 @@
/*
* struct ipahal_imm_cmd_dma_shared_mem - DMA_SHARED_MEM cmd payload
* Perform mem copy into or out of the SW area of IPA local mem
+ * @system_addr: Address in system memory
* @size: Size in bytes of data to copy. Expected size is up to 2K bytes
* @local_addr: Address in IPA local memory
* @clear_after_read: Clear local memory at the end of a read operation allows
@@ -282,16 +287,15 @@
* @is_read: Read operation from local memory? If not, then write.
* @skip_pipeline_clear: if to skip pipeline clear waiting (don't wait)
* @pipeline_clear_option: options for pipeline clear waiting
- * @system_addr: Address in system memory
*/
struct ipahal_imm_cmd_dma_shared_mem {
+ u64 system_addr;
u32 size;
u32 local_addr;
bool clear_after_read;
bool is_read;
bool skip_pipeline_clear;
enum ipahal_pipeline_clear_option pipeline_clear_options;
- u64 system_addr;
};
/*
@@ -515,6 +519,7 @@
* following statuses: IPA_STATUS_PACKET, IPA_STATUS_DROPPED_PACKET,
* IPA_STATUS_SUSPENDED_PACKET.
* Other statuses types has different status packet structure.
+ * @tag_info: S/W defined value provided via immediate command
* @status_opcode: The Type of the status (Opcode).
* @exception: The first exception that took place.
* In case of exception, src endp and pkt len are always valid.
@@ -522,9 +527,6 @@
* and processing it may passed at IPA. See enum ipahal_pkt_status_mask
* @pkt_len: Pkt pyld len including hdr and retained hdr if used. Does
* not include padding or checksum trailer len.
- * @endp_src_idx: Source end point index.
- * @endp_dest_idx: Destination end point index.
- * Not valid in case of exception
* @metadata: meta data value used by packet
* @flt_local: Filter table location flag: Does matching flt rule belongs to
* flt tbl that resides in lcl memory? (if not, then system mem)
@@ -535,57 +537,59 @@
* specifies to retain header?
* @flt_miss: Filtering miss flag: Was their a filtering rule miss?
* In case of miss, all flt info to be ignored
- * @flt_rule_id: The ID of the matching filter rule (if no miss).
- * This info can be combined with endp_src_idx to locate the exact rule.
* @rt_local: Route table location flag: Does matching rt rule belongs to
* rt tbl that resides in lcl memory? (if not, then system mem)
* @rt_hash: Route hash hit flag: Does matching rt rule was in hash tbl?
* @ucp: UC Processing flag
- * @rt_tbl_idx: Index of rt tbl that contains the rule on which was a match
* @rt_miss: Routing miss flag: Was their a routing rule miss?
- * @rt_rule_id: The ID of the matching rt rule. (if no miss). This info
- * can be combined with rt_tbl_idx to locate the exact rule.
* @nat_hit: NAT hit flag: Was their NAT hit?
- * @nat_entry_idx: Index of the NAT entry used of NAT processing
* @nat_type: Defines the type of the NAT operation:
- * @tag_info: S/W defined value provided via immediate command
- * @seq_num: Per source endp unique packet sequence number
* @time_of_day_ctr: running counter from IPA clock
* @hdr_local: Header table location flag: In header insertion, was the header
* taken from the table resides in local memory? (If no, then system mem)
- * @hdr_offset: Offset of used header in the header table
* @frag_hit: Frag hit flag: Was their frag rule hit in H/W frag table?
+ * @flt_rule_id: The ID of the matching filter rule (if no miss).
+ * This info can be combined with endp_src_idx to locate the exact rule.
+ * @rt_rule_id: The ID of the matching rt rule. (if no miss). This info
+ * can be combined with rt_tbl_idx to locate the exact rule.
+ * @nat_entry_idx: Index of the NAT entry used of NAT processing
+ * @hdr_offset: Offset of used header in the header table
+ * @endp_src_idx: Source end point index.
+ * @endp_dest_idx: Destination end point index.
+ * Not valid in case of exception
+ * @rt_tbl_idx: Index of rt tbl that contains the rule on which was a match
+ * @seq_num: Per source endp unique packet sequence number
* @frag_rule: Frag rule index in H/W frag table in case of frag hit
*/
struct ipahal_pkt_status {
+ u64 tag_info;
enum ipahal_pkt_status_opcode status_opcode;
enum ipahal_pkt_status_exception exception;
u32 status_mask;
u32 pkt_len;
- u8 endp_src_idx;
- u8 endp_dest_idx;
u32 metadata;
bool flt_local;
bool flt_hash;
bool flt_global;
bool flt_ret_hdr;
bool flt_miss;
- u16 flt_rule_id;
bool rt_local;
bool rt_hash;
bool ucp;
- u8 rt_tbl_idx;
bool rt_miss;
- u16 rt_rule_id;
bool nat_hit;
- u16 nat_entry_idx;
enum ipahal_pkt_status_nat_type nat_type;
- u64 tag_info;
- u8 seq_num;
u32 time_of_day_ctr;
bool hdr_local;
- u16 hdr_offset;
bool frag_hit;
+ u16 flt_rule_id;
+ u16 rt_rule_id;
+ u16 nat_entry_idx;
+ u16 hdr_offset;
+ u8 endp_src_idx;
+ u8 endp_dest_idx;
+ u8 rt_tbl_idx;
+ u8 seq_num;
u8 frag_rule;
};
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
index 5eb1aef..4ccb7e0 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_i.h
@@ -125,10 +125,10 @@
* struct ipa_imm_cmd_hw_ip_v4_nat_init - IP_V4_NAT_INIT command payload
* in H/W format.
* Inits IPv4 NAT block. Initiate NAT table with it dimensions, location
- * cache address abd itger related parameters.
+ * cache address and other related parameters.
* @ipv4_rules_addr: Addr in sys/shared mem where ipv4 NAT rules start
- * @ipv4_expansion_rules_addr: Addr in sys/shared mem where expantion NAT
- * table starts. IPv4 NAT rules that result in NAT collision are located
+ * @ipv4_expansion_rules_addr: Addr in sys/shared mem where expansion NAT
+ * table starts. IPv4 NAT rules that result in hash collision are located
* in this table.
* @index_table_addr: Addr in sys/shared mem where index table, which points
* to NAT table starts
@@ -143,11 +143,12 @@
* @index_table_expansion_addr_type: index_table_expansion_addr in
* sys or shared mem
* @size_base_tables: Num of entries in NAT tbl and idx tbl (each)
- * @size_expansion_tables: Num of entries in NAT expantion tbl and expantion
+ * @size_expansion_tables: Num of entries in NAT expansion tbl and expansion
* idx tbl (each)
* @rsvd2: reserved
- * @public_ip_addr: public IP address. for IPAv4 this is the PDN config table
- * offset in SMEM
+ * @public_addr_info: Public IP addresses info suitable to the IPA H/W version
+ * IPA H/W >= 4.0 - PDN config table offset in SMEM
+ * IPA H/W < 4.0 - The public IP address
*/
struct ipa_imm_cmd_hw_ip_v4_nat_init {
u64 ipv4_rules_addr:64;
@@ -163,7 +164,38 @@
u64 size_base_tables:12;
u64 size_expansion_tables:10;
u64 rsvd2:2;
- u64 public_ip_addr:32;
+ u64 public_addr_info:32;
+};
+
+/*
+ * struct ipa_imm_cmd_hw_ip_v6_ct_init - IP_V6_CONN_TRACK_INIT command payload
+ * in H/W format.
+ * Inits IPv6CT block. Initiate IPv6CT table with it dimensions, location
+ * cache address and other related parameters.
+ * @table_addr: Address in sys/shared mem where IPv6CT rules start
+ * @expansion_table_addr: Address in sys/shared mem where IPv6CT expansion
+ * table starts. IPv6CT rules that result in hash collision are located
+ * in this table.
+ * @table_index: For future support of multiple IPv6CT tables
+ * @rsvd1: reserved
+ * @table_addr_type: table_addr in sys or shared mem
+ * @expansion_table_addr_type: expansion_table_addr in sys or shared mem
+ * @rsvd2: reserved
+ * @size_base_tables: Number of entries in IPv6CT table
+ * @size_expansion_tables: Number of entries in IPv6CT expansion table
+ * @rsvd3: reserved
+ */
+struct ipa_imm_cmd_hw_ip_v6_ct_init {
+ u64 table_addr:64;
+ u64 expansion_table_addr:64;
+ u64 table_index:3;
+ u64 rsvd1:1;
+ u64 table_addr_type:1;
+ u64 expansion_table_addr_type:1;
+ u64 rsvd2:2;
+ u64 size_base_table:12;
+ u64 size_expansion_table:10;
+ u64 rsvd3:34;
};
/*
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c
new file mode 100644
index 0000000..d335ba6
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c
@@ -0,0 +1,360 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/debugfs.h>
+#include "ipahal_nat.h"
+#include "ipahal_nat_i.h"
+#include "ipahal_i.h"
+
+#define IPA_64_LOW_32_MASK (0xFFFFFFFF)
+#define IPA_64_HIGH_32_MASK (0xFFFFFFFF00000000ULL)
+
+static const char *ipahal_nat_type_to_str[IPA_NAT_MAX] = {
+ __stringify(IPAHAL_NAT_IPV4),
+ __stringify(IPAHAL_NAT_IPV4_INDEX),
+ __stringify(IPAHAL_NAT_IPV4_PDN),
+ __stringify(IPAHAL_NAT_IPV6CT)
+};
+
+static size_t ipa_nat_ipv4_entry_size_v_3_0(void)
+{
+ return sizeof(struct ipa_nat_hw_ipv4_entry);
+}
+
+static size_t ipa_nat_ipv4_index_entry_size_v_3_0(void)
+{
+ return sizeof(struct ipa_nat_hw_indx_entry);
+}
+
+static size_t ipa_nat_ipv4_pdn_entry_size_v_4_0(void)
+{
+ return sizeof(struct ipa_nat_hw_pdn_entry);
+}
+
+static size_t ipa_nat_ipv6ct_entry_size_v_4_0(void)
+{
+ return sizeof(struct ipa_nat_hw_ipv6ct_entry);
+}
+
+static bool ipa_nat_ipv4_is_entry_zeroed_v_3_0(const void *entry)
+{
+ struct ipa_nat_hw_ipv4_entry zero_entry = { 0 };
+
+ return (memcmp(&zero_entry, entry, sizeof(zero_entry))) ? false : true;
+}
+
+static bool ipa_nat_ipv4_is_index_entry_zeroed_v_3_0(const void *entry)
+{
+ struct ipa_nat_hw_indx_entry zero_entry = { 0 };
+
+ return (memcmp(&zero_entry, entry, sizeof(zero_entry))) ? false : true;
+}
+
+static bool ipa_nat_ipv4_is_pdn_entry_zeroed_v_4_0(const void *entry)
+{
+ struct ipa_nat_hw_pdn_entry zero_entry = { 0 };
+
+ return (memcmp(&zero_entry, entry, sizeof(zero_entry))) ? false : true;
+}
+
+static bool ipa_nat_ipv6ct_is_entry_zeroed_v_4_0(const void *entry)
+{
+ struct ipa_nat_hw_ipv6ct_entry zero_entry = { 0 };
+
+ return (memcmp(&zero_entry, entry, sizeof(zero_entry))) ? false : true;
+}
+
+static int ipa_nat_ipv4_stringify_entry_v_3_0(const void *entry,
+ char *buff, size_t buff_size)
+{
+ const struct ipa_nat_hw_ipv4_entry *nat_entry =
+ (const struct ipa_nat_hw_ipv4_entry *)entry;
+
+ return scnprintf(buff, buff_size,
+ "\t\tPrivate_IP=%pI4h Target_IP=%pI4h\n"
+ "\t\tNext_Index=%d Public_Port=%d\n"
+ "\t\tPrivate_Port=%d Target_Port=%d\n"
+ "\t\tIP_CKSM_delta=0x%x Enable=%s Redirect=%s\n"
+ "\t\tTime_stamp=0x%x Proto=%d\n"
+ "\t\tPrev_Index=%d Indx_tbl_entry=%d\n"
+ "\t\tTCP_UDP_cksum_delta=0x%x\n",
+ &nat_entry->private_ip, &nat_entry->target_ip,
+ nat_entry->next_index, nat_entry->public_port,
+ nat_entry->private_port, nat_entry->target_port,
+ nat_entry->ip_chksum,
+ (nat_entry->enable) ? "true" : "false",
+ (nat_entry->redirect) ? "Direct_To_APPS" : "Fwd_to_route",
+ nat_entry->time_stamp, nat_entry->protocol,
+ nat_entry->prev_index, nat_entry->indx_tbl_entry,
+ nat_entry->tcp_udp_chksum);
+}
+
+static int ipa_nat_ipv4_stringify_entry_v_4_0(const void *entry,
+ char *buff, size_t buff_size)
+{
+ int length;
+ const struct ipa_nat_hw_ipv4_entry *nat_entry =
+ (const struct ipa_nat_hw_ipv4_entry *)entry;
+
+ length = ipa_nat_ipv4_stringify_entry_v_3_0(entry, buff, buff_size);
+
+ length += scnprintf(buff + length, buff_size - length,
+ "\t\tPDN_Index=%d\n", nat_entry->pdn_index);
+
+ return length;
+}
+
+static int ipa_nat_ipv4_index_stringify_entry_v_3_0(const void *entry,
+ char *buff, size_t buff_size)
+{
+ const struct ipa_nat_hw_indx_entry *index_entry =
+ (const struct ipa_nat_hw_indx_entry *)entry;
+
+ return scnprintf(buff, buff_size,
+ "\t\tTable_Entry=%d Next_Index=%d\n",
+ index_entry->tbl_entry, index_entry->next_index);
+}
+
+static int ipa_nat_ipv4_pdn_stringify_entry_v_4_0(const void *entry,
+ char *buff, size_t buff_size)
+{
+ const struct ipa_nat_hw_pdn_entry *pdn_entry =
+ (const struct ipa_nat_hw_pdn_entry *)entry;
+
+ return scnprintf(buff, buff_size,
+ "ip=%pI4h src_metadata=0x%X, dst_metadata=0x%X\n",
+ &pdn_entry->public_ip,
+ pdn_entry->src_metadata, pdn_entry->dst_metadata);
+}
+
+static inline int ipa_nat_ipv6_stringify_addr(char *buff, size_t buff_size,
+ const char *msg, u64 lsb, u64 msb)
+{
+ struct in6_addr addr;
+
+ addr.s6_addr32[0] = cpu_to_be32((msb & IPA_64_HIGH_32_MASK) >> 32);
+ addr.s6_addr32[1] = cpu_to_be32(msb & IPA_64_LOW_32_MASK);
+ addr.s6_addr32[2] = cpu_to_be32((lsb & IPA_64_HIGH_32_MASK) >> 32);
+ addr.s6_addr32[3] = cpu_to_be32(lsb & IPA_64_LOW_32_MASK);
+
+ return scnprintf(buff, buff_size,
+ "\t\t%s_IPv6_Addr=%pI6c\n", msg, &addr);
+}
+
+static int ipa_nat_ipv6ct_stringify_entry_v_4_0(const void *entry,
+ char *buff, size_t buff_size)
+{
+ int length = 0;
+ const struct ipa_nat_hw_ipv6ct_entry *ipv6ct_entry =
+ (const struct ipa_nat_hw_ipv6ct_entry *)entry;
+
+ length += ipa_nat_ipv6_stringify_addr(
+ buff + length,
+ buff_size - length,
+ "Src",
+ ipv6ct_entry->src_ipv6_lsb,
+ ipv6ct_entry->src_ipv6_msb);
+
+ length += ipa_nat_ipv6_stringify_addr(
+ buff + length,
+ buff_size - length,
+ "Dest",
+ ipv6ct_entry->dest_ipv6_lsb,
+ ipv6ct_entry->dest_ipv6_msb);
+
+ length += scnprintf(buff + length, buff_size - length,
+ "\t\tEnable=%s Redirect=%s Time_Stamp=0x%x Proto=%d\n"
+ "\t\tNext_Index=%d Dest_Port=%d Src_Port=%d\n"
+ "\t\tDirection Settings: Out=%s In=%s\n"
+ "\t\tPrev_Index=%d\n",
+ (ipv6ct_entry->enable) ? "true" : "false",
+ (ipv6ct_entry->redirect) ? "Direct_To_APPS" : "Fwd_to_route",
+ ipv6ct_entry->time_stamp,
+ ipv6ct_entry->protocol,
+ ipv6ct_entry->next_index,
+ ipv6ct_entry->dest_port,
+ ipv6ct_entry->src_port,
+ (ipv6ct_entry->out_allowed) ? "Allow" : "Deny",
+ (ipv6ct_entry->in_allowed) ? "Allow" : "Deny",
+ ipv6ct_entry->prev_index);
+
+ return length;
+}
+
+/*
+ * struct ipahal_nat_obj - H/W information for specific IPA version
+ * @entry_size - CB to get the size of the entry
+ * @is_entry_zeroed - CB to determine whether an entry is definitely zero
+ * @stringify_entry - CB to create string that represents an entry
+ */
+struct ipahal_nat_obj {
+ size_t (*entry_size)(void);
+ bool (*is_entry_zeroed)(const void *entry);
+ int (*stringify_entry)(const void *entry, char *buff, size_t buff_size);
+};
+
+/*
+ * This table contains the info regard each NAT type for IPAv3 and later.
+ * Information like: get entry size and stringify entry functions.
+ * All the information on all the NAT types on IPAv3 are statically
+ * defined below. If information is missing regard some NAT type on some
+ * IPA version, the init function will fill it with the information from the
+ * previous IPA version.
+ * Information is considered missing if all of the fields are 0
+ */
+static struct ipahal_nat_obj ipahal_nat_objs[IPA_HW_MAX][IPA_NAT_MAX] = {
+ /* IPAv3 */
+ [IPA_HW_v3_0][IPAHAL_NAT_IPV4] = {
+ ipa_nat_ipv4_entry_size_v_3_0,
+ ipa_nat_ipv4_is_entry_zeroed_v_3_0,
+ ipa_nat_ipv4_stringify_entry_v_3_0
+ },
+ [IPA_HW_v3_0][IPAHAL_NAT_IPV4_INDEX] = {
+ ipa_nat_ipv4_index_entry_size_v_3_0,
+ ipa_nat_ipv4_is_index_entry_zeroed_v_3_0,
+ ipa_nat_ipv4_index_stringify_entry_v_3_0
+ },
+
+ /* IPAv4 */
+ [IPA_HW_v4_0][IPAHAL_NAT_IPV4] = {
+ ipa_nat_ipv4_entry_size_v_3_0,
+ ipa_nat_ipv4_is_entry_zeroed_v_3_0,
+ ipa_nat_ipv4_stringify_entry_v_4_0
+ },
+ [IPA_HW_v4_0][IPAHAL_NAT_IPV4_PDN] = {
+ ipa_nat_ipv4_pdn_entry_size_v_4_0,
+ ipa_nat_ipv4_is_pdn_entry_zeroed_v_4_0,
+ ipa_nat_ipv4_pdn_stringify_entry_v_4_0
+ },
+ [IPA_HW_v4_0][IPAHAL_NAT_IPV6CT] = {
+ ipa_nat_ipv6ct_entry_size_v_4_0,
+ ipa_nat_ipv6ct_is_entry_zeroed_v_4_0,
+ ipa_nat_ipv6ct_stringify_entry_v_4_0
+ }
+};
+
+static void ipahal_nat_check_obj(struct ipahal_nat_obj *obj,
+ int nat_type, int ver)
+{
+ WARN(obj->entry_size == NULL, "%s missing entry_size for version %d\n",
+ ipahal_nat_type_str(nat_type), ver);
+ WARN(obj->is_entry_zeroed == NULL,
+ "%s missing is_entry_zeroed for version %d\n",
+ ipahal_nat_type_str(nat_type), ver);
+ WARN(obj->stringify_entry == NULL,
+ "%s missing stringify_entry for version %d\n",
+ ipahal_nat_type_str(nat_type), ver);
+}
+
+/*
+ * ipahal_nat_init() - Build the NAT information table
+ * See ipahal_nat_objs[][] comments
+ */
+int ipahal_nat_init(enum ipa_hw_type ipa_hw_type)
+{
+ int i;
+ int j;
+ struct ipahal_nat_obj zero_obj, *next_obj;
+
+ IPAHAL_DBG("Entry - HW_TYPE=%d\n", ipa_hw_type);
+
+ memset(&zero_obj, 0, sizeof(zero_obj));
+
+ if ((ipa_hw_type < 0) || (ipa_hw_type >= IPA_HW_MAX)) {
+ IPAHAL_ERR("invalid IPA HW type (%d)\n", ipa_hw_type);
+ return -EINVAL;
+ }
+
+ for (i = IPA_HW_v3_0 ; i < ipa_hw_type ; ++i) {
+ for (j = 0; j < IPA_NAT_MAX; ++j) {
+ next_obj = &ipahal_nat_objs[i + 1][j];
+ if (!memcmp(next_obj, &zero_obj, sizeof(*next_obj))) {
+ memcpy(next_obj, &ipahal_nat_objs[i][j],
+ sizeof(*next_obj));
+ } else {
+ ipahal_nat_check_obj(next_obj, j, i + 1);
+ }
+ }
+ }
+
+ return 0;
+}
+
+const char *ipahal_nat_type_str(enum ipahal_nat_type nat_type)
+{
+ if (nat_type < 0 || nat_type >= IPA_NAT_MAX) {
+ IPAHAL_ERR("requested NAT type %d is invalid\n", nat_type);
+ return "Invalid NAT type";
+ }
+
+ return ipahal_nat_type_to_str[nat_type];
+}
+
+int ipahal_nat_entry_size(enum ipahal_nat_type nat_type, size_t *entry_size)
+{
+ if (WARN(entry_size == NULL, "entry_size is NULL\n"))
+ return -EINVAL;
+ if (WARN(nat_type < 0 || nat_type >= IPA_NAT_MAX,
+ "requested NAT type %d is invalid\n", nat_type))
+ return -EINVAL;
+
+ IPAHAL_DBG("Get the entry size for NAT type=%s\n",
+ ipahal_nat_type_str(nat_type));
+ *entry_size = ipahal_nat_objs[ipahal_ctx->hw_type][nat_type].
+ entry_size();
+ IPAHAL_DBG("The entry size is %zu\n", *entry_size);
+
+ return 0;
+}
+
+int ipahal_nat_is_entry_zeroed(enum ipahal_nat_type nat_type, void *entry,
+ bool *entry_zeroed)
+{
+ if (WARN(entry == NULL || entry_zeroed == NULL,
+ "NULL pointer received\n"))
+ return -EINVAL;
+ if (WARN(nat_type < 0 || nat_type >= IPA_NAT_MAX,
+ "requested NAT type %d is invalid\n", nat_type))
+ return -EINVAL;
+
+ IPAHAL_DBG("Determine whether the entry is zeroed for NAT type=%s\n",
+ ipahal_nat_type_str(nat_type));
+ *entry_zeroed = ipahal_nat_objs[ipahal_ctx->hw_type][nat_type].
+ is_entry_zeroed(entry);
+ IPAHAL_DBG("The entry is %szeroed\n", (*entry_zeroed) ? "" : "not ");
+
+ return 0;
+}
+
+int ipahal_nat_stringify_entry(enum ipahal_nat_type nat_type, void *entry,
+ char *buff, size_t buff_size)
+{
+ int result;
+
+ if (WARN(entry == NULL || buff == NULL, "NULL pointer received\n"))
+ return -EINVAL;
+ if (WARN(!buff_size, "The output buff size is zero\n"))
+ return -EINVAL;
+ if (WARN(nat_type < 0 || nat_type >= IPA_NAT_MAX,
+ "requested NAT type %d is invalid\n", nat_type))
+ return -EINVAL;
+
+ IPAHAL_DBG("Create the string for the entry of NAT type=%s\n",
+ ipahal_nat_type_str(nat_type));
+ result = ipahal_nat_objs[ipahal_ctx->hw_type][nat_type].
+ stringify_entry(entry, buff, buff_size);
+ IPAHAL_DBG("The string successfully created with length %d\n",
+ result);
+
+ return result;
+}
+
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.h
new file mode 100644
index 0000000..f99c1a0
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.h
@@ -0,0 +1,67 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _IPAHAL_NAT_H_
+#define _IPAHAL_NAT_H_
+
+/*
+ * NAT types
+ *
+ * NOTE:: Any change to this enum, need to change to ipahal_nat_to_str
+ * array as well.
+ */
+enum ipahal_nat_type {
+ IPAHAL_NAT_IPV4,
+ IPAHAL_NAT_IPV4_INDEX,
+ IPAHAL_NAT_IPV4_PDN,
+ IPAHAL_NAT_IPV6CT,
+ IPA_NAT_MAX
+};
+
+/* NAT Function APIs */
+
+/*
+ * ipahal_nat_type_str() - returns string that represent the NAT type
+ * @nat_type: [in] NAT type
+ */
+const char *ipahal_nat_type_str(enum ipahal_nat_type nat_type);
+
+/*
+ * ipahal_nat_entry_size() - Gets the size of HW NAT entry
+ * @nat_type: [in] The type of the NAT entry
+ * @entry_size: [out] The size of the HW NAT entry
+ */
+int ipahal_nat_entry_size(enum ipahal_nat_type nat_type, size_t *entry_size);
+
+/*
+ * ipahal_nat_is_entry_zeroed() - Determines whether HW NAT entry is
+ * definitely zero
+ * @nat_type: [in] The type of the NAT entry
+ * @entry: [in] The NAT entry
+ * @entry_zeroed: [out] True if the received entry is definitely zero
+ */
+int ipahal_nat_is_entry_zeroed(enum ipahal_nat_type nat_type, void *entry,
+ bool *entry_zeroed);
+
+/*
+ * ipahal_nat_stringify_entry() - Creates a string for HW NAT entry
+ * @nat_type: [in] The type of the NAT entry
+ * @entry: [in] The NAT entry
+ * @buff: [out] Output buffer for the result string
+ * @buff_size: [in] The size of the output buffer
+ * @return the number of characters written into buff not including
+ * the trailing '\0'
+ */
+int ipahal_nat_stringify_entry(enum ipahal_nat_type nat_type, void *entry,
+ char *buff, size_t buff_size);
+
+#endif /* _IPAHAL_NAT_H_ */
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat_i.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat_i.h
new file mode 100644
index 0000000..83bd0f5
--- /dev/null
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat_i.h
@@ -0,0 +1,153 @@
+/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 and
+ * only version 2 as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _IPAHAL_NAT_I_H_
+#define _IPAHAL_NAT_I_H_
+
+#include <linux/msm_ipa.h>
+
+/* ----------------------- IPv4 NAT Table Entry -------------------------
+ *
+ * -----------------------------------------------------------------------
+ * | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ * -----------------------------------------------------------------------
+ * | Target IP(4B) | Private IP(4B) |
+ * -----------------------------------------------------------------------
+ * |Target Port(2B) |Private Port(2B)| Public Port(2B) | Next Index(2B) |
+ * -----------------------------------------------------------------------
+ * |Proto| TimeStamp(3B) | Flags(2B) |IP check sum Diff|
+ * |(1B) | |EN|Redirect|Resv | (2B) |
+ * -----------------------------------------------------------------------
+ * |TCP/UDP checksum| PDN info(2B) | SW Specific Parameters(4B) |
+ * | diff (2B) |Info|Resv |index table entry| prev index |
+ * -----------------------------------------------------------------------
+ */
+struct ipa_nat_hw_ipv4_entry {
+ /* An IP address can't be bit-field, because its address is used */
+ u32 private_ip;
+ u32 target_ip;
+
+ u32 next_index : 16;
+ u32 public_port : 16;
+ u32 private_port : 16;
+ u32 target_port : 16;
+ u32 ip_chksum : 16;
+
+ u32 rsvd1 : 14;
+ u32 redirect : 1;
+ u32 enable : 1;
+
+ u32 time_stamp : 24;
+ u32 protocol : 8;
+
+ u32 prev_index : 16;
+ u32 indx_tbl_entry : 16;
+
+ u32 rsvd2 : 12;
+ u32 pdn_index : 4; /* IPA 4.0 and greater */
+
+ u32 tcp_udp_chksum : 16;
+};
+
+/*--- IPV4 NAT Index Table Entry --
+ *---------------------------------
+ *| 3 | 2 | 1 | 0 |
+ *---------------------------------
+ *|next index(2B) |table entry(2B)|
+ *---------------------------------
+ */
+struct ipa_nat_hw_indx_entry {
+ u16 tbl_entry;
+ u16 next_index;
+};
+
+/**
+ * struct ipa_nat_hw_pdn_entry - IPA PDN config table entry
+ * @public_ip: the PDN's public ip
+ * @src_metadata: the PDN's metadata to be replaced for source NAT
+ * @dst_metadata: the PDN's metadata to be replaced for destination NAT
+ * @resrvd: reserved field
+ * ---------------------------------
+ * | 3 | 2 | 1 | 0 |
+ * ---------------------------------
+ * | public_ip (4B) |
+ * ---------------------------------
+ * | src_metadata (4B) |
+ * ---------------------------------
+ * | dst_metadata (4B) |
+ * ---------------------------------
+ * | resrvd (4B) |
+ * ---------------------------------
+ */
+struct ipa_nat_hw_pdn_entry {
+ u32 public_ip;
+ u32 src_metadata;
+ u32 dst_metadata;
+ u32 resrvd;
+};
+
+/*------------------------- IPV6CT Table Entry ------------------------------
+ *-----------------------------------------------------------------------------
+ *| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
+ *-----------------------------------------------------------------------------
+ *| Outbound Src IPv6 Address (8 LSB Bytes) |
+ *-----------------------------------------------------------------------------
+ *| Outbound Src IPv6 Address (8 MSB Bytes) |
+ *-----------------------------------------------------------------------------
+ *| Outbound Dest IPv6 Address (8 LSB Bytes) |
+ *-----------------------------------------------------------------------------
+ *| Outbound Dest IPv6 Address (8 MSB Bytes) |
+ *-----------------------------------------------------------------------------
+ *|Protocol| TimeStamp (3B) | Flags (2B) |Reserved (2B) |
+ *| (1B) | |Enable|Redirect|Resv | |
+ *-----------------------------------------------------------------------------
+ *|Reserved|Direction(1B)|Src Port(2B)| Dest Port (2B) |Next Index(2B)|
+ *| (1B) |IN|OUT|Resv | | | |
+ *-----------------------------------------------------------------------------
+ *| SW Specific Parameters(4B) | Reserved (4B) |
+ *| Prev Index (2B) |Reserved(2B)| |
+ *-----------------------------------------------------------------------------
+ *| Reserved (8B) |
+ *-----------------------------------------------------------------------------
+ */
+struct ipa_nat_hw_ipv6ct_entry {
+ /* An IP address can't be bit-field, because its address is used */
+ u64 src_ipv6_lsb;
+ u64 src_ipv6_msb;
+ u64 dest_ipv6_lsb;
+ u64 dest_ipv6_msb;
+
+ u64 rsvd1 : 30;
+ u64 redirect : 1;
+ u64 enable : 1;
+
+ u64 time_stamp : 24;
+ u64 protocol : 8;
+
+ u64 next_index : 16;
+ u64 dest_port : 16;
+ u64 src_port : 16;
+ u64 rsvd2 : 6;
+ u64 out_allowed : 1;
+ u64 in_allowed : 1;
+ u64 rsvd3 : 8;
+
+ u64 rsvd4 : 48;
+ u64 prev_index : 16;
+
+ u64 rsvd5 : 64;
+};
+
+int ipahal_nat_init(enum ipa_hw_type ipa_hw_type);
+
+#endif /* _IPAHAL_NAT_I_H_ */
+