From f636a83662ffdc3e05526770e73628485f4a53de Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 9 Jun 2021 17:34:53 -0500 Subject: net: ipa: define IPA_MEM_END_MARKER Define a new pseudo memory region identifer that specifies the offset at the end of IPA resident memory. Use it instead of IPA_MEM_UC_EVENT_RING in places where the size of that region was defined to be 0. The size of the IPA_MEM_END_MARKER pseudo region must be zero. Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_data-v4.11.c | 2 +- drivers/net/ipa/ipa_data-v4.2.c | 2 +- drivers/net/ipa/ipa_mem.c | 2 ++ drivers/net/ipa/ipa_mem.h | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/net/ipa/ipa_data-v4.11.c b/drivers/net/ipa/ipa_data-v4.11.c index 05806ceae8b5..e7bdb8b4400e 100644 --- a/drivers/net/ipa/ipa_data-v4.11.c +++ b/drivers/net/ipa/ipa_data-v4.11.c @@ -325,7 +325,7 @@ static const struct ipa_mem ipa_mem_local_data[] = { .size = 0x100c, .canary_count = 2, }, - [IPA_MEM_UC_EVENT_RING] = { + [IPA_MEM_END_MARKER] = { .offset = 0x3000, .size = 0x0000, .canary_count = 1, diff --git a/drivers/net/ipa/ipa_data-v4.2.c b/drivers/net/ipa/ipa_data-v4.2.c index 8744f19c6401..95f75dbc3c3b 100644 --- a/drivers/net/ipa/ipa_data-v4.2.c +++ b/drivers/net/ipa/ipa_data-v4.2.c @@ -304,7 +304,7 @@ static const struct ipa_mem ipa_mem_local_data[] = { .size = 0x140c, .canary_count = 0, }, - [IPA_MEM_UC_EVENT_RING] = { + [IPA_MEM_END_MARKER] = { .offset = 0x2000, .size = 0, .canary_count = 1, diff --git a/drivers/net/ipa/ipa_mem.c b/drivers/net/ipa/ipa_mem.c index 1624125e7459..e3c43cf6e441 100644 --- a/drivers/net/ipa/ipa_mem.c +++ b/drivers/net/ipa/ipa_mem.c @@ -120,6 +120,8 @@ static bool ipa_mem_valid(struct ipa *ipa, enum ipa_mem_id mem_id) else if (mem->offset + mem->size > ipa->mem_size) dev_err(dev, "region %u ends beyond memory limit (0x%08x)\n", mem_id, ipa->mem_size); + else if (mem_id == IPA_MEM_END_MARKER && mem->size) + dev_err(dev, "non-zero end marker region size\n"); else return true; diff --git a/drivers/net/ipa/ipa_mem.h b/drivers/net/ipa/ipa_mem.h index a422aec69e5d..5a4f865a45af 100644 --- a/drivers/net/ipa/ipa_mem.h +++ b/drivers/net/ipa/ipa_mem.h @@ -70,6 +70,7 @@ enum ipa_mem_id { IPA_MEM_STATS_DROP, /* 0 canaries (IPA v4.0 and above) */ IPA_MEM_MODEM, /* 0/2 canaries */ IPA_MEM_UC_EVENT_RING, /* 1 canary */ + IPA_MEM_END_MARKER, /* 1 canary (not a real region) */ IPA_MEM_COUNT, /* Number of regions (not an index) */ }; -- cgit v1.2.3 From 14ab6a208c11dcb7b91fda3e0866c7e6188dc553 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 9 Jun 2021 17:34:54 -0500 Subject: net: ipa: store memory region id in descriptor Store the memory region ID in the memory descriptor structure. This is a move toward *not* indexing the array by the ID, but for now we must still specify those index values. Define an explicitly undefined region ID, value 0, so uninitialized entries in the array won't use an otherwise valid ID. Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_data-v3.5.1.c | 15 +++++++++++++++ drivers/net/ipa/ipa_data-v4.11.c | 22 ++++++++++++++++++++++ drivers/net/ipa/ipa_data-v4.2.c | 18 ++++++++++++++++++ drivers/net/ipa/ipa_data-v4.5.c | 23 +++++++++++++++++++++++ drivers/net/ipa/ipa_data-v4.9.c | 26 +++++++++++++++++++++++++- drivers/net/ipa/ipa_mem.h | 3 +++ 6 files changed, 106 insertions(+), 1 deletion(-) diff --git a/drivers/net/ipa/ipa_data-v3.5.1.c b/drivers/net/ipa/ipa_data-v3.5.1.c index ead1a82f32f5..945d45b72b24 100644 --- a/drivers/net/ipa/ipa_data-v3.5.1.c +++ b/drivers/net/ipa/ipa_data-v3.5.1.c @@ -272,76 +272,91 @@ static const struct ipa_resource_data ipa_resource_data = { /* IPA-resident memory region data for an SoC having IPA v3.5.1 */ static const struct ipa_mem ipa_mem_local_data[] = { [IPA_MEM_UC_SHARED] = { + .id = IPA_MEM_UC_SHARED, .offset = 0x0000, .size = 0x0080, .canary_count = 0, }, [IPA_MEM_UC_INFO] = { + .id = IPA_MEM_UC_INFO, .offset = 0x0080, .size = 0x0200, .canary_count = 0, }, [IPA_MEM_V4_FILTER_HASHED] = { + .id = IPA_MEM_V4_FILTER_HASHED, .offset = 0x0288, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V4_FILTER] = { + .id = IPA_MEM_V4_FILTER, .offset = 0x0308, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_FILTER_HASHED] = { + .id = IPA_MEM_V6_FILTER_HASHED, .offset = 0x0388, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_FILTER] = { + .id = IPA_MEM_V6_FILTER, .offset = 0x0408, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V4_ROUTE_HASHED] = { + .id = IPA_MEM_V4_ROUTE_HASHED, .offset = 0x0488, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V4_ROUTE] = { + .id = IPA_MEM_V4_ROUTE, .offset = 0x0508, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_ROUTE_HASHED] = { + .id = IPA_MEM_V6_ROUTE_HASHED, .offset = 0x0588, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_ROUTE] = { + .id = IPA_MEM_V6_ROUTE, .offset = 0x0608, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_MODEM_HEADER] = { + .id = IPA_MEM_MODEM_HEADER, .offset = 0x0688, .size = 0x0140, .canary_count = 2, }, [IPA_MEM_MODEM_PROC_CTX] = { + .id = IPA_MEM_MODEM_PROC_CTX, .offset = 0x07d0, .size = 0x0200, .canary_count = 2, }, [IPA_MEM_AP_PROC_CTX] = { + .id = IPA_MEM_AP_PROC_CTX, .offset = 0x09d0, .size = 0x0200, .canary_count = 0, }, [IPA_MEM_MODEM] = { + .id = IPA_MEM_MODEM, .offset = 0x0bd8, .size = 0x1024, .canary_count = 0, }, [IPA_MEM_UC_EVENT_RING] = { + .id = IPA_MEM_UC_EVENT_RING, .offset = 0x1c00, .size = 0x0400, .canary_count = 1, diff --git a/drivers/net/ipa/ipa_data-v4.11.c b/drivers/net/ipa/ipa_data-v4.11.c index e7bdb8b4400e..2ff3fcf4e21f 100644 --- a/drivers/net/ipa/ipa_data-v4.11.c +++ b/drivers/net/ipa/ipa_data-v4.11.c @@ -221,111 +221,133 @@ static const struct ipa_resource_data ipa_resource_data = { /* IPA-resident memory region data for an SoC having IPA v4.11 */ static const struct ipa_mem ipa_mem_local_data[] = { [IPA_MEM_UC_SHARED] = { + .id = IPA_MEM_UC_SHARED, .offset = 0x0000, .size = 0x0080, .canary_count = 0, }, [IPA_MEM_UC_INFO] = { + .id = IPA_MEM_UC_INFO, .offset = 0x0080, .size = 0x0200, .canary_count = 0, }, [IPA_MEM_V4_FILTER_HASHED] = { + .id = IPA_MEM_V4_FILTER_HASHED, .offset = 0x0288, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V4_FILTER] = { + .id = IPA_MEM_V4_FILTER, .offset = 0x0308, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_FILTER_HASHED] = { + .id = IPA_MEM_V6_FILTER_HASHED, .offset = 0x0388, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_FILTER] = { + .id = IPA_MEM_V6_FILTER, .offset = 0x0408, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V4_ROUTE_HASHED] = { + .id = IPA_MEM_V4_ROUTE_HASHED, .offset = 0x0488, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V4_ROUTE] = { + .id = IPA_MEM_V4_ROUTE, .offset = 0x0508, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_ROUTE_HASHED] = { + .id = IPA_MEM_V6_ROUTE_HASHED, .offset = 0x0588, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_ROUTE] = { + .id = IPA_MEM_V6_ROUTE, .offset = 0x0608, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_MODEM_HEADER] = { + .id = IPA_MEM_MODEM_HEADER, .offset = 0x0688, .size = 0x0240, .canary_count = 2, }, [IPA_MEM_AP_HEADER] = { + .id = IPA_MEM_AP_HEADER, .offset = 0x08c8, .size = 0x0200, .canary_count = 0, }, [IPA_MEM_MODEM_PROC_CTX] = { + .id = IPA_MEM_MODEM_PROC_CTX, .offset = 0x0ad0, .size = 0x0200, .canary_count = 2, }, [IPA_MEM_AP_PROC_CTX] = { + .id = IPA_MEM_AP_PROC_CTX, .offset = 0x0cd0, .size = 0x0200, .canary_count = 0, }, [IPA_MEM_NAT_TABLE] = { + .id = IPA_MEM_NAT_TABLE, .offset = 0x0ee0, .size = 0x0d00, .canary_count = 4, }, [IPA_MEM_PDN_CONFIG] = { + .id = IPA_MEM_PDN_CONFIG, .offset = 0x1be8, .size = 0x0050, .canary_count = 0, }, [IPA_MEM_STATS_QUOTA_MODEM] = { + .id = IPA_MEM_STATS_QUOTA_MODEM, .offset = 0x1c40, .size = 0x0030, .canary_count = 4, }, [IPA_MEM_STATS_QUOTA_AP] = { + .id = IPA_MEM_STATS_QUOTA_AP, .offset = 0x1c70, .size = 0x0048, .canary_count = 0, }, [IPA_MEM_STATS_TETHERING] = { + .id = IPA_MEM_STATS_TETHERING, .offset = 0x1cb8, .size = 0x0238, .canary_count = 0, }, [IPA_MEM_STATS_DROP] = { + .id = IPA_MEM_STATS_DROP, .offset = 0x1ef0, .size = 0x0020, .canary_count = 0, }, [IPA_MEM_MODEM] = { + .id = IPA_MEM_MODEM, .offset = 0x1f18, .size = 0x100c, .canary_count = 2, }, [IPA_MEM_END_MARKER] = { + .id = IPA_MEM_END_MARKER, .offset = 0x3000, .size = 0x0000, .canary_count = 1, diff --git a/drivers/net/ipa/ipa_data-v4.2.c b/drivers/net/ipa/ipa_data-v4.2.c index 95f75dbc3c3b..f06eb07a7895 100644 --- a/drivers/net/ipa/ipa_data-v4.2.c +++ b/drivers/net/ipa/ipa_data-v4.2.c @@ -220,91 +220,109 @@ static const struct ipa_resource_data ipa_resource_data = { /* IPA-resident memory region data for an SoC having IPA v4.2 */ static const struct ipa_mem ipa_mem_local_data[] = { [IPA_MEM_UC_SHARED] = { + .id = IPA_MEM_UC_SHARED, .offset = 0x0000, .size = 0x0080, .canary_count = 0, }, [IPA_MEM_UC_INFO] = { + .id = IPA_MEM_UC_INFO, .offset = 0x0080, .size = 0x0200, .canary_count = 0, }, [IPA_MEM_V4_FILTER_HASHED] = { + .id = IPA_MEM_V4_FILTER_HASHED, .offset = 0x0288, .size = 0, .canary_count = 2, }, [IPA_MEM_V4_FILTER] = { + .id = IPA_MEM_V4_FILTER, .offset = 0x0290, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_FILTER_HASHED] = { + .id = IPA_MEM_V6_FILTER_HASHED, .offset = 0x0310, .size = 0, .canary_count = 2, }, [IPA_MEM_V6_FILTER] = { + .id = IPA_MEM_V6_FILTER, .offset = 0x0318, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V4_ROUTE_HASHED] = { + .id = IPA_MEM_V4_ROUTE_HASHED, .offset = 0x0398, .size = 0, .canary_count = 2, }, [IPA_MEM_V4_ROUTE] = { + .id = IPA_MEM_V4_ROUTE, .offset = 0x03a0, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_ROUTE_HASHED] = { + .id = IPA_MEM_V6_ROUTE_HASHED, .offset = 0x0420, .size = 0, .canary_count = 2, }, [IPA_MEM_V6_ROUTE] = { + .id = IPA_MEM_V6_ROUTE, .offset = 0x0428, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_MODEM_HEADER] = { + .id = IPA_MEM_MODEM_HEADER, .offset = 0x04a8, .size = 0x0140, .canary_count = 2, }, [IPA_MEM_MODEM_PROC_CTX] = { + .id = IPA_MEM_MODEM_PROC_CTX, .offset = 0x05f0, .size = 0x0200, .canary_count = 2, }, [IPA_MEM_AP_PROC_CTX] = { + .id = IPA_MEM_AP_PROC_CTX, .offset = 0x07f0, .size = 0x0200, .canary_count = 0, }, [IPA_MEM_PDN_CONFIG] = { + .id = IPA_MEM_PDN_CONFIG, .offset = 0x09f8, .size = 0x0050, .canary_count = 2, }, [IPA_MEM_STATS_QUOTA_MODEM] = { + .id = IPA_MEM_STATS_QUOTA_MODEM, .offset = 0x0a50, .size = 0x0060, .canary_count = 2, }, [IPA_MEM_STATS_TETHERING] = { + .id = IPA_MEM_STATS_TETHERING, .offset = 0x0ab0, .size = 0x0140, .canary_count = 0, }, [IPA_MEM_MODEM] = { + .id = IPA_MEM_MODEM, .offset = 0x0bf0, .size = 0x140c, .canary_count = 0, }, [IPA_MEM_END_MARKER] = { + .id = IPA_MEM_END_MARKER, .offset = 0x2000, .size = 0, .canary_count = 1, diff --git a/drivers/net/ipa/ipa_data-v4.5.c b/drivers/net/ipa/ipa_data-v4.5.c index 5f67a3a909ee..1c8a9099639a 100644 --- a/drivers/net/ipa/ipa_data-v4.5.c +++ b/drivers/net/ipa/ipa_data-v4.5.c @@ -266,116 +266,139 @@ static const struct ipa_resource_data ipa_resource_data = { /* IPA-resident memory region data for an SoC having IPA v4.5 */ static const struct ipa_mem ipa_mem_local_data[] = { [IPA_MEM_UC_SHARED] = { + .id = IPA_MEM_UC_SHARED, .offset = 0x0000, .size = 0x0080, .canary_count = 0, }, [IPA_MEM_UC_INFO] = { + .id = IPA_MEM_UC_INFO, .offset = 0x0080, .size = 0x0200, .canary_count = 0, }, [IPA_MEM_V4_FILTER_HASHED] = { + .id = IPA_MEM_V4_FILTER_HASHED, .offset = 0x0288, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V4_FILTER] = { + .id = IPA_MEM_V4_FILTER, .offset = 0x0308, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_FILTER_HASHED] = { + .id = IPA_MEM_V6_FILTER_HASHED, .offset = 0x0388, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_FILTER] = { + .id = IPA_MEM_V6_FILTER, .offset = 0x0408, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V4_ROUTE_HASHED] = { + .id = IPA_MEM_V4_ROUTE_HASHED, .offset = 0x0488, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V4_ROUTE] = { + .id = IPA_MEM_V4_ROUTE, .offset = 0x0508, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_ROUTE_HASHED] = { + .id = IPA_MEM_V6_ROUTE_HASHED, .offset = 0x0588, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_ROUTE] = { + .id = IPA_MEM_V6_ROUTE, .offset = 0x0608, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_MODEM_HEADER] = { + .id = IPA_MEM_MODEM_HEADER, .offset = 0x0688, .size = 0x0240, .canary_count = 2, }, [IPA_MEM_AP_HEADER] = { + .id = IPA_MEM_AP_HEADER, .offset = 0x08c8, .size = 0x0200, .canary_count = 0, }, [IPA_MEM_MODEM_PROC_CTX] = { + .id = IPA_MEM_MODEM_PROC_CTX, .offset = 0x0ad0, .size = 0x0b20, .canary_count = 2, }, [IPA_MEM_AP_PROC_CTX] = { + .id = IPA_MEM_AP_PROC_CTX, .offset = 0x15f0, .size = 0x0200, .canary_count = 0, }, [IPA_MEM_NAT_TABLE] = { + .id = IPA_MEM_NAT_TABLE, .offset = 0x1800, .size = 0x0d00, .canary_count = 4, }, [IPA_MEM_STATS_QUOTA_MODEM] = { + .id = IPA_MEM_STATS_QUOTA_MODEM, .offset = 0x2510, .size = 0x0030, .canary_count = 4, }, [IPA_MEM_STATS_QUOTA_AP] = { + .id = IPA_MEM_STATS_QUOTA_AP, .offset = 0x2540, .size = 0x0048, .canary_count = 0, }, [IPA_MEM_STATS_TETHERING] = { + .id = IPA_MEM_STATS_TETHERING, .offset = 0x2588, .size = 0x0238, .canary_count = 0, }, [IPA_MEM_STATS_FILTER_ROUTE] = { + .id = IPA_MEM_STATS_FILTER_ROUTE, .offset = 0x27c0, .size = 0x0800, .canary_count = 0, }, [IPA_MEM_STATS_DROP] = { + .id = IPA_MEM_STATS_DROP, .offset = 0x2fc0, .size = 0x0020, .canary_count = 0, }, [IPA_MEM_MODEM] = { + .id = IPA_MEM_MODEM, .offset = 0x2fe8, .size = 0x0800, .canary_count = 2, }, [IPA_MEM_UC_EVENT_RING] = { + .id = IPA_MEM_UC_EVENT_RING, .offset = 0x3800, .size = 0x1000, .canary_count = 1, }, [IPA_MEM_PDN_CONFIG] = { + .id = IPA_MEM_PDN_CONFIG, .offset = 0x4800, .size = 0x0050, .canary_count = 0, diff --git a/drivers/net/ipa/ipa_data-v4.9.c b/drivers/net/ipa/ipa_data-v4.9.c index e41be790f45e..f77169709eb2 100644 --- a/drivers/net/ipa/ipa_data-v4.9.c +++ b/drivers/net/ipa/ipa_data-v4.9.c @@ -264,115 +264,139 @@ static const struct ipa_resource_data ipa_resource_data = { /* IPA-resident memory region data for an SoC having IPA v4.9 */ static const struct ipa_mem ipa_mem_local_data[] = { [IPA_MEM_UC_SHARED] = { + .id = IPA_MEM_UC_SHARED, .offset = 0x0000, .size = 0x0080, .canary_count = 0, }, [IPA_MEM_UC_INFO] = { + .id = IPA_MEM_UC_INFO, .offset = 0x0080, .size = 0x0200, .canary_count = 0, }, - [IPA_MEM_V4_FILTER_HASHED] = { .offset = 0x0288, + [IPA_MEM_V4_FILTER_HASHED] = { + .id = IPA_MEM_V4_FILTER_HASHED, + .offset = 0x0288, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V4_FILTER] = { + .id = IPA_MEM_V4_FILTER, .offset = 0x0308, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_FILTER_HASHED] = { + .id = IPA_MEM_V6_FILTER_HASHED, .offset = 0x0388, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_FILTER] = { + .id = IPA_MEM_V6_FILTER, .offset = 0x0408, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V4_ROUTE_HASHED] = { + .id = IPA_MEM_V4_ROUTE_HASHED, .offset = 0x0488, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V4_ROUTE] = { + .id = IPA_MEM_V4_ROUTE, .offset = 0x0508, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_ROUTE_HASHED] = { + .id = IPA_MEM_V6_ROUTE_HASHED, .offset = 0x0588, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_V6_ROUTE] = { + .id = IPA_MEM_V6_ROUTE, .offset = 0x0608, .size = 0x0078, .canary_count = 2, }, [IPA_MEM_MODEM_HEADER] = { + .id = IPA_MEM_MODEM_HEADER, .offset = 0x0688, .size = 0x0240, .canary_count = 2, }, [IPA_MEM_AP_HEADER] = { + .id = IPA_MEM_AP_HEADER, .offset = 0x08c8, .size = 0x0200, .canary_count = 0, }, [IPA_MEM_MODEM_PROC_CTX] = { + .id = IPA_MEM_MODEM_PROC_CTX, .offset = 0x0ad0, .size = 0x0b20, .canary_count = 2, }, [IPA_MEM_AP_PROC_CTX] = { + .id = IPA_MEM_AP_PROC_CTX, .offset = 0x15f0, .size = 0x0200, .canary_count = 0, }, [IPA_MEM_NAT_TABLE] = { + .id = IPA_MEM_NAT_TABLE, .offset = 0x1800, .size = 0x0d00, .canary_count = 4, }, [IPA_MEM_STATS_QUOTA_MODEM] = { + .id = IPA_MEM_STATS_QUOTA_MODEM, .offset = 0x2510, .size = 0x0030, .canary_count = 4, }, [IPA_MEM_STATS_QUOTA_AP] = { + .id = IPA_MEM_STATS_QUOTA_AP, .offset = 0x2540, .size = 0x0048, .canary_count = 0, }, [IPA_MEM_STATS_TETHERING] = { + .id = IPA_MEM_STATS_TETHERING, .offset = 0x2588, .size = 0x0238, .canary_count = 0, }, [IPA_MEM_STATS_FILTER_ROUTE] = { + .id = IPA_MEM_STATS_FILTER_ROUTE, .offset = 0x27c0, .size = 0x0800, .canary_count = 0, }, [IPA_MEM_STATS_DROP] = { + .id = IPA_MEM_STATS_DROP, .offset = 0x2fc0, .size = 0x0020, .canary_count = 0, }, [IPA_MEM_MODEM] = { + .id = IPA_MEM_MODEM, .offset = 0x2fe8, .size = 0x0800, .canary_count = 2, }, [IPA_MEM_UC_EVENT_RING] = { + .id = IPA_MEM_UC_EVENT_RING, .offset = 0x3800, .size = 0x1000, .canary_count = 1, }, [IPA_MEM_PDN_CONFIG] = { + .id = IPA_MEM_PDN_CONFIG, .offset = 0x4800, .size = 0x0050, .canary_count = 0, diff --git a/drivers/net/ipa/ipa_mem.h b/drivers/net/ipa/ipa_mem.h index 5a4f865a45af..ce692f948d59 100644 --- a/drivers/net/ipa/ipa_mem.h +++ b/drivers/net/ipa/ipa_mem.h @@ -43,6 +43,7 @@ struct ipa_mem_data; /* IPA-resident memory region ids */ enum ipa_mem_id { + IPA_MEM_UNDEFINED = 0, /* undefined region */ IPA_MEM_UC_SHARED, /* 0 canaries */ IPA_MEM_UC_INFO, /* 0 canaries */ IPA_MEM_V4_FILTER_HASHED, /* 2 canaries */ @@ -76,11 +77,13 @@ enum ipa_mem_id { /** * struct ipa_mem - IPA local memory region description + * @id: memory region identifier * @offset: offset in IPA memory space to base of the region * @size: size in bytes base of the region * @canary_count: Number of 32-bit "canary" values that precede region */ struct ipa_mem { + enum ipa_mem_id id; u32 offset; u16 size; u16 canary_count; -- cgit v1.2.3 From 0300df2d9d249c3dd8e0ad1b7dd5b7da1b8d0e37 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 9 Jun 2021 17:34:55 -0500 Subject: net: ipa: validate memory regions unconditionally Do memory region descriptor validation unconditionally, rather than having it depend on IPA_VALIDATION being defined. Pass the address of a memory region descriptor rather than a memory ID to ipa_mem_valid(). Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_mem.c | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/drivers/net/ipa/ipa_mem.c b/drivers/net/ipa/ipa_mem.c index e3c43cf6e441..effaa745a406 100644 --- a/drivers/net/ipa/ipa_mem.c +++ b/drivers/net/ipa/ipa_mem.c @@ -99,12 +99,10 @@ int ipa_mem_setup(struct ipa *ipa) return 0; } -#ifdef IPA_VALIDATE - -static bool ipa_mem_valid(struct ipa *ipa, enum ipa_mem_id mem_id) +static bool ipa_mem_valid(struct ipa *ipa, const struct ipa_mem *mem) { - const struct ipa_mem *mem = &ipa->mem[mem_id]; struct device *dev = &ipa->pdev->dev; + enum ipa_mem_id mem_id = mem->id; u16 size_multiple; /* Other than modem memory, sizes must be a multiple of 8 */ @@ -128,15 +126,6 @@ static bool ipa_mem_valid(struct ipa *ipa, enum ipa_mem_id mem_id) return false; } -#else /* !IPA_VALIDATE */ - -static bool ipa_mem_valid(struct ipa *ipa, enum ipa_mem_id mem_id) -{ - return true; -} - -#endif /*! IPA_VALIDATE */ - /** * ipa_mem_config() - Configure IPA shared memory * @ipa: IPA pointer @@ -188,7 +177,7 @@ int ipa_mem_config(struct ipa *ipa) __le32 *canary; /* Validate all regions (even undefined ones) */ - if (!ipa_mem_valid(ipa, mem_id)) + if (!ipa_mem_valid(ipa, mem)) goto err_dma_free; /* Skip over undefined regions */ -- cgit v1.2.3 From 98334d2a3ba4c79947650710ac06434e25824a35 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 9 Jun 2021 17:34:56 -0500 Subject: net: ipa: separate memory validation from initialization Currently, memory regions are validated in the loop that initializes them. Instead, validate them separately. Rename ipa_mem_valid() to be ipa_mem_valid_one(). Define a *new* function named ipa_mem_valid() that performs validation of the array of memory regions provided. This function calls ipa_mem_valid_one() for each region in turn. Skip validation for any "empty" region descriptors, which have zero size and are not preceded by any canary values. Issue a warning for such descriptors if the offset is non-zero. Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_mem.c | 40 ++++++++++++++++++++++++++++++++-------- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/drivers/net/ipa/ipa_mem.c b/drivers/net/ipa/ipa_mem.c index effaa745a406..62e1b8280d98 100644 --- a/drivers/net/ipa/ipa_mem.c +++ b/drivers/net/ipa/ipa_mem.c @@ -99,7 +99,7 @@ int ipa_mem_setup(struct ipa *ipa) return 0; } -static bool ipa_mem_valid(struct ipa *ipa, const struct ipa_mem *mem) +static bool ipa_mem_valid_one(struct ipa *ipa, const struct ipa_mem *mem) { struct device *dev = &ipa->pdev->dev; enum ipa_mem_id mem_id = mem->id; @@ -126,6 +126,31 @@ static bool ipa_mem_valid(struct ipa *ipa, const struct ipa_mem *mem) return false; } +/* Verify each defined memory region is valid. */ +static bool ipa_mem_valid(struct ipa *ipa) +{ + struct device *dev = &ipa->pdev->dev; + enum ipa_mem_id mem_id; + + for (mem_id = 0; mem_id < ipa->mem_count; mem_id++) { + const struct ipa_mem *mem = &ipa->mem[mem_id]; + + /* Defined regions have non-zero size and/or canary count */ + if (mem->size || mem->canary_count) { + if (ipa_mem_valid_one(ipa, mem)) + continue; + return false; + } + + /* It's harmless, but warn if an offset is provided */ + if (mem->offset) + dev_warn(dev, "empty region %u has non-zero offset\n", + mem_id); + } + + return true; +} + /** * ipa_mem_config() - Configure IPA shared memory * @ipa: IPA pointer @@ -167,19 +192,18 @@ int ipa_mem_config(struct ipa *ipa) ipa->zero_virt = virt; ipa->zero_size = IPA_MEM_MAX; - /* Verify each defined memory region is valid, and if indicated - * for the region, write "canary" values in the space prior to - * the region's base address. + /* Make sure all defined memory regions are valid */ + if (!ipa_mem_valid(ipa)) + goto err_dma_free; + + /* For each region, write "canary" values in the space prior to + * the region's base address if indicated. */ for (mem_id = 0; mem_id < ipa->mem_count; mem_id++) { const struct ipa_mem *mem = &ipa->mem[mem_id]; u16 canary_count; __le32 *canary; - /* Validate all regions (even undefined ones) */ - if (!ipa_mem_valid(ipa, mem)) - goto err_dma_free; - /* Skip over undefined regions */ if (!mem->offset && !mem->size) continue; -- cgit v1.2.3 From 5e57c6c5a349ed8026e63c9ef70e4655fe171b09 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 9 Jun 2021 17:34:57 -0500 Subject: net: ipa: separate region range check from other validation The only thing done by ipa_mem_valid_one() that requires hardware access is the check for whether all regions fit within the size of IPA local memory specified by an IPA register. Introduce ipa_mem_size_valid() to implement this verification and stop doing so in ipa_mem_valid_one(). Call the new function from ipa_mem_config() (which is also the caller of ipa_mem_valid()). Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_mem.c | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/drivers/net/ipa/ipa_mem.c b/drivers/net/ipa/ipa_mem.c index 62e1b8280d98..f245e1a60a44 100644 --- a/drivers/net/ipa/ipa_mem.c +++ b/drivers/net/ipa/ipa_mem.c @@ -115,9 +115,6 @@ static bool ipa_mem_valid_one(struct ipa *ipa, const struct ipa_mem *mem) else if (mem->offset < mem->canary_count * sizeof(__le32)) dev_err(dev, "region %u offset too small for %hu canaries\n", mem_id, mem->canary_count); - else if (mem->offset + mem->size > ipa->mem_size) - dev_err(dev, "region %u ends beyond memory limit (0x%08x)\n", - mem_id, ipa->mem_size); else if (mem_id == IPA_MEM_END_MARKER && mem->size) dev_err(dev, "non-zero end marker region size\n"); else @@ -151,6 +148,28 @@ static bool ipa_mem_valid(struct ipa *ipa) return true; } +/* Do all memory regions fit within the IPA local memory? */ +static bool ipa_mem_size_valid(struct ipa *ipa) +{ + struct device *dev = &ipa->pdev->dev; + u32 limit = ipa->mem_size; + enum ipa_mem_id mem_id; + + for (mem_id = 0; mem_id < ipa->mem_count; mem_id++) { + const struct ipa_mem *mem = &ipa->mem[mem_id]; + + if (mem->offset + mem->size <= limit) + continue; + + dev_err(dev, "region %u ends beyond memory limit (0x%08x)\n", + mem_id, limit); + + return false; + } + + return true; +} + /** * ipa_mem_config() - Configure IPA shared memory * @ipa: IPA pointer @@ -184,6 +203,10 @@ int ipa_mem_config(struct ipa *ipa) mem_size); } + /* We know our memory size; make sure regions are all in range */ + if (!ipa_mem_size_valid(ipa)) + return -EINVAL; + /* Prealloc DMA memory for zeroing regions */ virt = dma_alloc_coherent(dev, IPA_MEM_MAX, &addr, GFP_KERNEL); if (!virt) -- cgit v1.2.3 From 2f9be1e90860e8acb43dc164e25c0d0be60f6a7b Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 9 Jun 2021 17:34:58 -0500 Subject: net: ipa: validate memory regions at init time Move the memory region validation check so it happens earlier when initializing the driver, at init time rather than config time (i.e., before access to hardware is required). Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_mem.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ipa/ipa_mem.c b/drivers/net/ipa/ipa_mem.c index f245e1a60a44..b2d149e7c5f0 100644 --- a/drivers/net/ipa/ipa_mem.c +++ b/drivers/net/ipa/ipa_mem.c @@ -215,10 +215,6 @@ int ipa_mem_config(struct ipa *ipa) ipa->zero_virt = virt; ipa->zero_size = IPA_MEM_MAX; - /* Make sure all defined memory regions are valid */ - if (!ipa_mem_valid(ipa)) - goto err_dma_free; - /* For each region, write "canary" values in the space prior to * the region's base address if indicated. */ @@ -528,6 +524,10 @@ int ipa_mem_init(struct ipa *ipa, const struct ipa_mem_data *mem_data) ipa->mem_count = mem_data->local_count; ipa->mem = mem_data->local; + /* Make sure all defined memory regions are valid */ + if (!ipa_mem_valid(ipa)) + goto err_unmap; + ret = ipa_imem_init(ipa, mem_data->imem_addr, mem_data->imem_size); if (ret) goto err_unmap; -- cgit v1.2.3 From 1eec767746e5fe4e4376ad511558de3c77f49d82 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 9 Jun 2021 17:34:59 -0500 Subject: net: ipa: pass memory configuration data to ipa_mem_valid() Pass the memory configuration data array to ipa_mem_valid() for validation, and use that rather than assuming it's already been recorded in the IPA structure. Move the memory data array size check into ipa_mem_valid(). Call ipa_mem_valid() early in ipa_mem_init(), and only proceed with assigning the memory array pointer and size if it is found to be valid. Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_mem.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/drivers/net/ipa/ipa_mem.c b/drivers/net/ipa/ipa_mem.c index b2d149e7c5f0..cb70f063320c 100644 --- a/drivers/net/ipa/ipa_mem.c +++ b/drivers/net/ipa/ipa_mem.c @@ -124,13 +124,19 @@ static bool ipa_mem_valid_one(struct ipa *ipa, const struct ipa_mem *mem) } /* Verify each defined memory region is valid. */ -static bool ipa_mem_valid(struct ipa *ipa) +static bool ipa_mem_valid(struct ipa *ipa, const struct ipa_mem_data *mem_data) { struct device *dev = &ipa->pdev->dev; enum ipa_mem_id mem_id; - for (mem_id = 0; mem_id < ipa->mem_count; mem_id++) { - const struct ipa_mem *mem = &ipa->mem[mem_id]; + if (mem_data->local_count > IPA_MEM_COUNT) { + dev_err(dev, "too many memory regions (%u > %u)\n", + mem_data->local_count, IPA_MEM_COUNT); + return false; + } + + for (mem_id = 0; mem_id < mem_data->local_count; mem_id++) { + const struct ipa_mem *mem = &mem_data->local[mem_id]; /* Defined regions have non-zero size and/or canary count */ if (mem->size || mem->canary_count) { @@ -491,11 +497,12 @@ int ipa_mem_init(struct ipa *ipa, const struct ipa_mem_data *mem_data) struct resource *res; int ret; - if (mem_data->local_count > IPA_MEM_COUNT) { - dev_err(dev, "to many memory regions (%u > %u)\n", - mem_data->local_count, IPA_MEM_COUNT); + /* Make sure the set of defined memory regions is valid */ + if (!ipa_mem_valid(ipa, mem_data)) return -EINVAL; - } + + ipa->mem_count = mem_data->local_count; + ipa->mem = mem_data->local; ret = dma_set_mask_and_coherent(&ipa->pdev->dev, DMA_BIT_MASK(64)); if (ret) { @@ -520,14 +527,6 @@ int ipa_mem_init(struct ipa *ipa, const struct ipa_mem_data *mem_data) ipa->mem_addr = res->start; ipa->mem_size = resource_size(res); - /* The ipa->mem[] array is indexed by enum ipa_mem_id values */ - ipa->mem_count = mem_data->local_count; - ipa->mem = mem_data->local; - - /* Make sure all defined memory regions are valid */ - if (!ipa_mem_valid(ipa)) - goto err_unmap; - ret = ipa_imem_init(ipa, mem_data->imem_addr, mem_data->imem_size); if (ret) goto err_unmap; -- cgit v1.2.3 From d39ffb97079b3f97f4f9d7cc633c78a1f69d3264 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 9 Jun 2021 17:35:00 -0500 Subject: net: ipa: introduce ipa_mem_id_optional() Introduce a new function that indicates whether a given memory region is required for a given version of IPA hardware. Use it to verify that all required regions are present during initialization. Reorder the definitions of the memory region IDs to be based on the version in which they're first defined. Use "+" rather than "and above" where defining the IPA versions in which memory IDs are used, and indicate which regions are optional (many are not). Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_mem.c | 42 ++++++++++++++++++++++++++++++++++++++++++ drivers/net/ipa/ipa_mem.h | 21 +++++++++++---------- 2 files changed, 53 insertions(+), 10 deletions(-) diff --git a/drivers/net/ipa/ipa_mem.c b/drivers/net/ipa/ipa_mem.c index cb70f063320c..29c626c46abf 100644 --- a/drivers/net/ipa/ipa_mem.c +++ b/drivers/net/ipa/ipa_mem.c @@ -99,6 +99,36 @@ int ipa_mem_setup(struct ipa *ipa) return 0; } +/* Must the given memory region be present in the configuration? */ +static bool ipa_mem_id_required(struct ipa *ipa, enum ipa_mem_id mem_id) +{ + switch (mem_id) { + case IPA_MEM_UC_SHARED: + case IPA_MEM_UC_INFO: + case IPA_MEM_V4_FILTER_HASHED: + case IPA_MEM_V4_FILTER: + case IPA_MEM_V6_FILTER_HASHED: + case IPA_MEM_V6_FILTER: + case IPA_MEM_V4_ROUTE_HASHED: + case IPA_MEM_V4_ROUTE: + case IPA_MEM_V6_ROUTE_HASHED: + case IPA_MEM_V6_ROUTE: + case IPA_MEM_MODEM_HEADER: + case IPA_MEM_MODEM_PROC_CTX: + case IPA_MEM_AP_PROC_CTX: + case IPA_MEM_MODEM: + return true; + + case IPA_MEM_PDN_CONFIG: + case IPA_MEM_STATS_QUOTA_MODEM: + case IPA_MEM_STATS_TETHERING: + return ipa->version >= IPA_VERSION_4_0; + + default: + return false; /* Anything else is optional */ + } +} + static bool ipa_mem_valid_one(struct ipa *ipa, const struct ipa_mem *mem) { struct device *dev = &ipa->pdev->dev; @@ -149,8 +179,20 @@ static bool ipa_mem_valid(struct ipa *ipa, const struct ipa_mem_data *mem_data) if (mem->offset) dev_warn(dev, "empty region %u has non-zero offset\n", mem_id); + + if (ipa_mem_id_required(ipa, mem_id)) { + dev_err(dev, "required memory region %u missing\n", + mem_id); + return false; + } } + /* Now see if any required regions are not defined */ + while (mem_id < IPA_MEM_COUNT) + if (ipa_mem_id_required(ipa, mem_id++)) + dev_err(dev, "required memory region %u missing\n", + mem_id); + return true; } diff --git a/drivers/net/ipa/ipa_mem.h b/drivers/net/ipa/ipa_mem.h index ce692f948d59..effe01f7310a 100644 --- a/drivers/net/ipa/ipa_mem.h +++ b/drivers/net/ipa/ipa_mem.h @@ -55,22 +55,23 @@ enum ipa_mem_id { IPA_MEM_V6_ROUTE_HASHED, /* 2 canaries */ IPA_MEM_V6_ROUTE, /* 2 canaries */ IPA_MEM_MODEM_HEADER, /* 2 canaries */ - IPA_MEM_AP_HEADER, /* 0 canaries */ + IPA_MEM_AP_HEADER, /* 0 canaries, optional */ IPA_MEM_MODEM_PROC_CTX, /* 2 canaries */ IPA_MEM_AP_PROC_CTX, /* 0 canaries */ - IPA_MEM_NAT_TABLE, /* 4 canaries (IPA v4.5 and above) */ - IPA_MEM_PDN_CONFIG, /* 0/2 canaries (IPA v4.0 and above) */ - IPA_MEM_STATS_QUOTA_MODEM, /* 2/4 canaries (IPA v4.0 and above) */ - IPA_MEM_STATS_QUOTA_AP, /* 0 canaries (IPA v4.0 and above) */ - IPA_MEM_STATS_TETHERING, /* 0 canaries (IPA v4.0 and above) */ + IPA_MEM_MODEM, /* 0/2 canaries */ + IPA_MEM_UC_EVENT_RING, /* 1 canary, optional */ + IPA_MEM_PDN_CONFIG, /* 0/2 canaries (IPA v4.0+) */ + IPA_MEM_STATS_QUOTA_MODEM, /* 2/4 canaries (IPA v4.0+) */ + IPA_MEM_STATS_QUOTA_AP, /* 0 canaries, optional (IPA v4.0+) */ + IPA_MEM_STATS_TETHERING, /* 0 canaries (IPA v4.0+) */ + IPA_MEM_STATS_DROP, /* 0 canaries, optional (IPA v4.0+) */ + /* The next 5 filter and route statistics regions are optional */ IPA_MEM_STATS_V4_FILTER, /* 0 canaries (IPA v4.0-v4.2) */ IPA_MEM_STATS_V6_FILTER, /* 0 canaries (IPA v4.0-v4.2) */ IPA_MEM_STATS_V4_ROUTE, /* 0 canaries (IPA v4.0-v4.2) */ IPA_MEM_STATS_V6_ROUTE, /* 0 canaries (IPA v4.0-v4.2) */ - IPA_MEM_STATS_FILTER_ROUTE, /* 0 canaries (IPA v4.5 and above) */ - IPA_MEM_STATS_DROP, /* 0 canaries (IPA v4.0 and above) */ - IPA_MEM_MODEM, /* 0/2 canaries */ - IPA_MEM_UC_EVENT_RING, /* 1 canary */ + IPA_MEM_STATS_FILTER_ROUTE, /* 0 canaries (IPA v4.5+) */ + IPA_MEM_NAT_TABLE, /* 4 canaries, optional (IPA v4.5+) */ IPA_MEM_END_MARKER, /* 1 canary (not a real region) */ IPA_MEM_COUNT, /* Number of regions (not an index) */ }; -- cgit v1.2.3 From 75bcfde6c1131371adc2388b9226db7b2465e4c1 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 9 Jun 2021 17:35:01 -0500 Subject: net: ipa: validate memory regions based on version Introduce ipa_mem_id_valid(), and use it to check defined memory regions to ensure they are valid for a given version of IPA. Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_mem.c | 61 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) diff --git a/drivers/net/ipa/ipa_mem.c b/drivers/net/ipa/ipa_mem.c index 29c626c46abf..e5ca6a2ac626 100644 --- a/drivers/net/ipa/ipa_mem.c +++ b/drivers/net/ipa/ipa_mem.c @@ -99,6 +99,61 @@ int ipa_mem_setup(struct ipa *ipa) return 0; } +/* Is the given memory region ID is valid for the current IPA version? */ +static bool ipa_mem_id_valid(struct ipa *ipa, enum ipa_mem_id mem_id) +{ + enum ipa_version version = ipa->version; + + switch (mem_id) { + case IPA_MEM_UC_SHARED: + case IPA_MEM_UC_INFO: + case IPA_MEM_V4_FILTER_HASHED: + case IPA_MEM_V4_FILTER: + case IPA_MEM_V6_FILTER_HASHED: + case IPA_MEM_V6_FILTER: + case IPA_MEM_V4_ROUTE_HASHED: + case IPA_MEM_V4_ROUTE: + case IPA_MEM_V6_ROUTE_HASHED: + case IPA_MEM_V6_ROUTE: + case IPA_MEM_MODEM_HEADER: + case IPA_MEM_AP_HEADER: + case IPA_MEM_MODEM_PROC_CTX: + case IPA_MEM_AP_PROC_CTX: + case IPA_MEM_MODEM: + case IPA_MEM_UC_EVENT_RING: + case IPA_MEM_PDN_CONFIG: + case IPA_MEM_STATS_QUOTA_MODEM: + case IPA_MEM_STATS_QUOTA_AP: + case IPA_MEM_END_MARKER: /* pseudo region */ + break; + + case IPA_MEM_STATS_TETHERING: + case IPA_MEM_STATS_DROP: + if (version < IPA_VERSION_4_0) + return false; + break; + + case IPA_MEM_STATS_V4_FILTER: + case IPA_MEM_STATS_V6_FILTER: + case IPA_MEM_STATS_V4_ROUTE: + case IPA_MEM_STATS_V6_ROUTE: + if (version < IPA_VERSION_4_0 || version > IPA_VERSION_4_2) + return false; + break; + + case IPA_MEM_NAT_TABLE: + case IPA_MEM_STATS_FILTER_ROUTE: + if (version < IPA_VERSION_4_5) + return false; + break; + + default: + return false; + } + + return true; +} + /* Must the given memory region be present in the configuration? */ static bool ipa_mem_id_required(struct ipa *ipa, enum ipa_mem_id mem_id) { @@ -135,6 +190,12 @@ static bool ipa_mem_valid_one(struct ipa *ipa, const struct ipa_mem *mem) enum ipa_mem_id mem_id = mem->id; u16 size_multiple; + /* Make sure the memory region is valid for this version of IPA */ + if (!ipa_mem_id_valid(ipa, mem_id)) { + dev_err(dev, "region id %u not valid\n", mem_id); + return false; + } + /* Other than modem memory, sizes must be a multiple of 8 */ size_multiple = mem_id == IPA_MEM_MODEM ? 4 : 8; if (mem->size % size_multiple) -- cgit v1.2.3 From eadf7f9376145a2827010f1775570cfe009afc70 Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 9 Jun 2021 17:35:02 -0500 Subject: net: ipa: flag duplicate memory regions Add a test in ipa_mem_valid() to ensure no memory region is defined more than once, using a bitmap to record each defined memory region. Skip over undefined regions when checking (we can have any number of those). Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_mem.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/drivers/net/ipa/ipa_mem.c b/drivers/net/ipa/ipa_mem.c index e5ca6a2ac626..7b79aeb5f68f 100644 --- a/drivers/net/ipa/ipa_mem.c +++ b/drivers/net/ipa/ipa_mem.c @@ -217,6 +217,7 @@ static bool ipa_mem_valid_one(struct ipa *ipa, const struct ipa_mem *mem) /* Verify each defined memory region is valid. */ static bool ipa_mem_valid(struct ipa *ipa, const struct ipa_mem_data *mem_data) { + DECLARE_BITMAP(regions, IPA_MEM_COUNT) = { }; struct device *dev = &ipa->pdev->dev; enum ipa_mem_id mem_id; @@ -229,6 +230,14 @@ static bool ipa_mem_valid(struct ipa *ipa, const struct ipa_mem_data *mem_data) for (mem_id = 0; mem_id < mem_data->local_count; mem_id++) { const struct ipa_mem *mem = &mem_data->local[mem_id]; + if (mem_id == IPA_MEM_UNDEFINED) + continue; + + if (__test_and_set_bit(mem->id, regions)) { + dev_err(dev, "duplicate memory region %u\n", mem->id); + return false; + } + /* Defined regions have non-zero size and/or canary count */ if (mem->size || mem->canary_count) { if (ipa_mem_valid_one(ipa, mem)) -- cgit v1.2.3 From 6857b02392ab89ffc4235de991b544ef22375e6e Mon Sep 17 00:00:00 2001 From: Alex Elder Date: Wed, 9 Jun 2021 17:35:03 -0500 Subject: net: ipa: use bitmap to check for missing regions In ipa_mem_valid(), wait until regions have been marked in the memory region bitmap, and check all that are not found there to ensure they are not required. Signed-off-by: Alex Elder Signed-off-by: David S. Miller --- drivers/net/ipa/ipa_mem.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/drivers/net/ipa/ipa_mem.c b/drivers/net/ipa/ipa_mem.c index 7b79aeb5f68f..ef9fdd3b8875 100644 --- a/drivers/net/ipa/ipa_mem.c +++ b/drivers/net/ipa/ipa_mem.c @@ -249,19 +249,16 @@ static bool ipa_mem_valid(struct ipa *ipa, const struct ipa_mem_data *mem_data) if (mem->offset) dev_warn(dev, "empty region %u has non-zero offset\n", mem_id); - - if (ipa_mem_id_required(ipa, mem_id)) { - dev_err(dev, "required memory region %u missing\n", - mem_id); - return false; - } } /* Now see if any required regions are not defined */ - while (mem_id < IPA_MEM_COUNT) - if (ipa_mem_id_required(ipa, mem_id++)) + for (mem_id = find_first_zero_bit(regions, IPA_MEM_COUNT); + mem_id < IPA_MEM_COUNT; + mem_id = find_next_zero_bit(regions, IPA_MEM_COUNT, mem_id + 1)) { + if (ipa_mem_id_required(ipa, mem_id)) dev_err(dev, "required memory region %u missing\n", mem_id); + } return true; } -- cgit v1.2.3