Merge "msm: ipa3: Ignore invalid NAT entries when counting nat rules"
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
index e88ab27..07773eb 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipa_debugfs.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2012-2018, 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
@@ -1517,6 +1517,7 @@
char *entry;
size_t entry_size;
bool entry_zeroed;
+ bool entry_valid;
u32 i, num_entries = 0, id = *rule_id, pos = 0;
IPADBG("\n");
@@ -1538,20 +1539,33 @@
&entry_zeroed);
if (result) {
IPAERR(
- "Failed to determine whether the %s entry is definitely zero",
- ipahal_nat_type_str(nat_type));
+ "Failed to determine whether the %s entry is definitely zero\n"
+ , ipahal_nat_type_str(nat_type));
goto bail;
}
if (entry_zeroed)
continue;
- pos += scnprintf(buff + pos, buff_size - pos,
- "\tEntry_Index=%d\n", id);
+ result = ipahal_nat_is_entry_valid(nat_type, entry,
+ &entry_valid);
+ if (result) {
+ IPAERR(
+ "Failed to determine whether the %s entry is valid\n"
+ , ipahal_nat_type_str(nat_type));
+ goto bail;
+ }
+
+ if (entry_valid) {
+ ++num_entries;
+ pos += scnprintf(buff + pos, buff_size - pos,
+ "\tEntry_Index=%d\n", id);
+ } else {
+ pos += scnprintf(buff + pos, buff_size - pos,
+ "\tEntry_Index=%d - Invalid Entry\n", id);
+ }
pos += ipahal_nat_stringify_entry(nat_type, entry,
buff + pos, buff_size - pos);
-
- ++num_entries;
}
if (num_entries)
@@ -1637,6 +1651,7 @@
char *pdn_entry;
size_t pdn_entry_size;
bool entry_zeroed;
+ bool entry_valid;
u32 pos = 0;
IPADBG("\n");
@@ -1654,13 +1669,25 @@
pdn_entry, &entry_zeroed);
if (result) {
IPAERR(
- "Failed to determine whether the PDN entry is definitely zero");
+ "Failed to determine whether the PDN entry is definitely zero\n");
goto bail;
}
if (entry_zeroed)
continue;
- pos += scnprintf(buff + pos, buff_size - pos, "PDN %d: ", i);
+ result = ipahal_nat_is_entry_valid(IPAHAL_NAT_IPV4_PDN,
+ pdn_entry, &entry_valid);
+ if (result) {
+ IPAERR(
+ "Failed to determine whether the PDN entry is valid\n");
+ goto bail;
+ }
+ if (entry_valid)
+ pos += scnprintf(buff + pos, buff_size - pos,
+ "PDN %d: ", i);
+ else
+ pos += scnprintf(buff + pos, buff_size - pos,
+ "PDN %d - Invalid: ", i);
pos += ipahal_nat_stringify_entry(IPAHAL_NAT_IPV4_PDN,
pdn_entry, buff + pos, buff_size - pos);
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c
index d335ba6..016b4f3 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.c
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018 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
@@ -17,6 +17,7 @@
#define IPA_64_LOW_32_MASK (0xFFFFFFFF)
#define IPA_64_HIGH_32_MASK (0xFFFFFFFF00000000ULL)
+#define IPAHAL_NAT_INVALID_PROTOCOL (0xFF)
static const char *ipahal_nat_type_to_str[IPA_NAT_MAX] = {
__stringify(IPAHAL_NAT_IPV4),
@@ -73,6 +74,40 @@
return (memcmp(&zero_entry, entry, sizeof(zero_entry))) ? false : true;
}
+static bool ipa_nat_ipv4_is_entry_valid_v_3_0(const void *entry)
+{
+ struct ipa_nat_hw_ipv4_entry *hw_entry =
+ (struct ipa_nat_hw_ipv4_entry *)entry;
+
+ return hw_entry->enable &&
+ hw_entry->protocol != IPAHAL_NAT_INVALID_PROTOCOL;
+}
+
+static bool ipa_nat_ipv4_is_index_entry_valid_v_3_0(const void *entry)
+{
+ struct ipa_nat_hw_indx_entry *hw_entry =
+ (struct ipa_nat_hw_indx_entry *)entry;
+
+ return hw_entry->tbl_entry != 0;
+}
+
+static bool ipa_nat_ipv4_is_pdn_entry_valid_v_4_0(const void *entry)
+{
+ struct ipa_nat_hw_pdn_entry *hw_entry =
+ (struct ipa_nat_hw_pdn_entry *)entry;
+
+ return hw_entry->public_ip != 0;
+}
+
+static bool ipa_nat_ipv6ct_is_entry_valid_v_4_0(const void *entry)
+{
+ struct ipa_nat_hw_ipv6ct_entry *hw_entry =
+ (struct ipa_nat_hw_ipv6ct_entry *)entry;
+
+ return hw_entry->enable &&
+ hw_entry->protocol != IPAHAL_NAT_INVALID_PROTOCOL;
+}
+
static int ipa_nat_ipv4_stringify_entry_v_3_0(const void *entry,
char *buff, size_t buff_size)
{
@@ -194,11 +229,15 @@
* 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
+ * @is_entry_valid - CB to determine whether an entry is valid
+ * Validity criterium depends on entry type. E.g. for NAT base table
+ * Entry need to be with valid protocol and enabled.
* @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);
+ bool (*is_entry_valid)(const void *entry);
int (*stringify_entry)(const void *entry, char *buff, size_t buff_size);
};
@@ -216,11 +255,13 @@
[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_is_entry_valid_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_is_index_entry_valid_v_3_0,
ipa_nat_ipv4_index_stringify_entry_v_3_0
},
@@ -228,16 +269,19 @@
[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_is_entry_valid_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_is_pdn_entry_valid_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_is_entry_valid_v_4_0,
ipa_nat_ipv6ct_stringify_entry_v_4_0
}
};
@@ -335,6 +379,25 @@
return 0;
}
+int ipahal_nat_is_entry_valid(enum ipahal_nat_type nat_type, void *entry,
+ bool *entry_valid)
+{
+ if (WARN(entry == NULL || entry_valid == 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 valid for NAT type=%s\n",
+ ipahal_nat_type_str(nat_type));
+ *entry_valid = ipahal_nat_objs[ipahal_ctx->hw_type][nat_type].
+ is_entry_valid(entry);
+ IPAHAL_DBG("The entry is %svalid\n", (*entry_valid) ? "" : "not ");
+
+ return 0;
+}
+
int ipahal_nat_stringify_entry(enum ipahal_nat_type nat_type, void *entry,
char *buff, size_t buff_size)
{
diff --git a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.h b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.h
index f99c1a0..2461d3e 100644
--- a/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.h
+++ b/drivers/platform/msm/ipa/ipa_v3/ipahal/ipahal_nat.h
@@ -1,4 +1,4 @@
-/* Copyright (c) 2017, The Linux Foundation. All rights reserved.
+/* Copyright (c) 2017-2018 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
@@ -53,6 +53,18 @@
bool *entry_zeroed);
/*
+ * ipahal_nat_is_entry_valid() - Determines whether HW NAT entry is
+ * valid.
+ * Validity criterium depends on entry type. E.g. for NAT base table
+ * Entry need to be with valid protocol and enabled.
+ * @nat_type: [in] The type of the NAT entry
+ * @entry: [in] The NAT entry
+ * @entry_valid: [out] True if the received entry is valid
+ */
+int ipahal_nat_is_entry_valid(enum ipahal_nat_type nat_type, void *entry,
+ bool *entry_valid);
+
+/*
* 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