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 05806ceae8b5..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_UC_EVENT_RING] = { + [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 8744f19c6401..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_UC_EVENT_RING] = { + [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.c b/drivers/net/ipa/ipa_mem.c index 1624125e7459..ef9fdd3b8875 100644 --- a/drivers/net/ipa/ipa_mem.c +++ b/drivers/net/ipa/ipa_mem.c @@ -99,14 +99,103 @@ 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) +/* 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) +{ + 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) { - 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; + /* 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) @@ -117,23 +206,84 @@ static bool ipa_mem_valid(struct ipa *ipa, enum ipa_mem_id mem_id) 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 return true; return false; } -#else /* !IPA_VALIDATE */ - -static bool ipa_mem_valid(struct ipa *ipa, enum ipa_mem_id mem_id) +/* 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; + + 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]; + + 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)) + 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); + } + + /* Now see if any required regions are not defined */ + 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; } -#endif /*! IPA_VALIDATE */ +/* 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 @@ -168,6 +318,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) @@ -176,19 +330,14 @@ 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. + /* 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_id)) - goto err_dma_free; - /* Skip over undefined regions */ if (!mem->offset && !mem->size) continue; @@ -457,11 +606,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) { @@ -486,10 +636,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; - ret = ipa_imem_init(ipa, mem_data->imem_addr, mem_data->imem_size); if (ret) goto err_unmap; diff --git a/drivers/net/ipa/ipa_mem.h b/drivers/net/ipa/ipa_mem.h index a422aec69e5d..effe01f7310a 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 */ @@ -54,32 +55,36 @@ 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) */ }; /** * 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;