aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/drivers
diff options
context:
space:
mode:
authorAlex Elder <elder@linaro.org>2020-10-28 14:41:48 -0500
committerJakub Kicinski <kuba@kernel.org>2020-10-30 17:20:13 -0700
commit4a0d7579d466e0e3b576a31f7f4fac16cfd06219 (patch)
tree2b73b241e63fd4b46098368793b48f04e4f16f27 /drivers
parentnet: ipa: distinguish between resource group types (diff)
downloadwireguard-linux-4a0d7579d466e0e3b576a31f7f4fac16cfd06219.tar.xz
wireguard-linux-4a0d7579d466e0e3b576a31f7f4fac16cfd06219.zip
net: ipa: avoid going past end of resource group array
The minimum and maximum limits for resources assigned to a given resource group are programmed in pairs, with the limits for two groups set in a single register. If the number of supported resource groups is odd, only half of the register that defines these limits is valid for the last group; that group has no second group in the pair. Currently we ignore this constraint, and it turns out to be harmless, but it is not guaranteed to be. This patch addresses that, and adds support for programming the 5th resource group's limits. Rework how the resource group limit registers are programmed by having a single function program all group pairs rather than having one function program each pair. Add the programming of the 4-5 resource group pair limits to this function. If a resource group is not supported, pass a null pointer to ipa_resource_config_common() for that group and have that function write zeroes in that case. Tested-by: Sujit Kautkar <sujitka@chromium.org> Signed-off-by: Alex Elder <elder@linaro.org> Acked-by: Willem de Bruijn <willemb@google.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/net/ipa/ipa_main.c89
1 files changed, 53 insertions, 36 deletions
diff --git a/drivers/net/ipa/ipa_main.c b/drivers/net/ipa/ipa_main.c
index 74b1e15ebd6b..f4dd14d9550f 100644
--- a/drivers/net/ipa/ipa_main.c
+++ b/drivers/net/ipa/ipa_main.c
@@ -370,8 +370,11 @@ static bool ipa_resource_limits_valid(struct ipa *ipa,
u32 i;
u32 j;
+ /* We program at most 6 source or destination resource group limits */
+ BUILD_BUG_ON(IPA_RESOURCE_GROUP_SRC_MAX > 6);
+
group_count = ipa_resource_group_src_count(ipa->version);
- if (!group_count)
+ if (!group_count || group_count > IPA_RESOURCE_GROUP_SRC_MAX)
return false;
/* Return an error if a non-zero resource limit is specified
@@ -387,7 +390,7 @@ static bool ipa_resource_limits_valid(struct ipa *ipa,
}
group_count = ipa_resource_group_dst_count(ipa->version);
- if (!group_count)
+ if (!group_count || group_count > IPA_RESOURCE_GROUP_DST_MAX)
return false;
for (i = 0; i < data->resource_dst_count; i++) {
@@ -421,46 +424,64 @@ ipa_resource_config_common(struct ipa *ipa, u32 offset,
val = u32_encode_bits(xlimits->min, X_MIN_LIM_FMASK);
val |= u32_encode_bits(xlimits->max, X_MAX_LIM_FMASK);
- val |= u32_encode_bits(ylimits->min, Y_MIN_LIM_FMASK);
- val |= u32_encode_bits(ylimits->max, Y_MAX_LIM_FMASK);
+ if (ylimits) {
+ val |= u32_encode_bits(ylimits->min, Y_MIN_LIM_FMASK);
+ val |= u32_encode_bits(ylimits->max, Y_MAX_LIM_FMASK);
+ }
iowrite32(val, ipa->reg_virt + offset);
}
-static void ipa_resource_config_src_01(struct ipa *ipa,
- const struct ipa_resource_src *resource)
+static void ipa_resource_config_src(struct ipa *ipa,
+ const struct ipa_resource_src *resource)
{
- u32 offset = IPA_REG_SRC_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource->type);
+ u32 group_count = ipa_resource_group_src_count(ipa->version);
+ const struct ipa_resource_limits *ylimits;
+ u32 offset;
- ipa_resource_config_common(ipa, offset,
- &resource->limits[0], &resource->limits[1]);
-}
+ offset = IPA_REG_SRC_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource->type);
+ ylimits = group_count == 1 ? NULL : &resource->limits[1];
+ ipa_resource_config_common(ipa, offset, &resource->limits[0], ylimits);
-static void ipa_resource_config_src_23(struct ipa *ipa,
- const struct ipa_resource_src *resource)
-{
- u32 offset = IPA_REG_SRC_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource->type);
+ if (group_count < 2)
+ return;
- ipa_resource_config_common(ipa, offset,
- &resource->limits[2], &resource->limits[3]);
-}
+ offset = IPA_REG_SRC_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource->type);
+ ylimits = group_count == 3 ? NULL : &resource->limits[3];
+ ipa_resource_config_common(ipa, offset, &resource->limits[2], ylimits);
-static void ipa_resource_config_dst_01(struct ipa *ipa,
- const struct ipa_resource_dst *resource)
-{
- u32 offset = IPA_REG_DST_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource->type);
+ if (group_count < 4)
+ return;
- ipa_resource_config_common(ipa, offset,
- &resource->limits[0], &resource->limits[1]);
+ offset = IPA_REG_SRC_RSRC_GRP_45_RSRC_TYPE_N_OFFSET(resource->type);
+ ylimits = group_count == 5 ? NULL : &resource->limits[5];
+ ipa_resource_config_common(ipa, offset, &resource->limits[4], ylimits);
}
-static void ipa_resource_config_dst_23(struct ipa *ipa,
- const struct ipa_resource_dst *resource)
+static void ipa_resource_config_dst(struct ipa *ipa,
+ const struct ipa_resource_dst *resource)
{
- u32 offset = IPA_REG_DST_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource->type);
+ u32 group_count = ipa_resource_group_dst_count(ipa->version);
+ const struct ipa_resource_limits *ylimits;
+ u32 offset;
- ipa_resource_config_common(ipa, offset,
- &resource->limits[2], &resource->limits[3]);
+ offset = IPA_REG_DST_RSRC_GRP_01_RSRC_TYPE_N_OFFSET(resource->type);
+ ylimits = group_count == 1 ? NULL : &resource->limits[1];
+ ipa_resource_config_common(ipa, offset, &resource->limits[0], ylimits);
+
+ if (group_count < 2)
+ return;
+
+ offset = IPA_REG_DST_RSRC_GRP_23_RSRC_TYPE_N_OFFSET(resource->type);
+ ylimits = group_count == 3 ? NULL : &resource->limits[3];
+ ipa_resource_config_common(ipa, offset, &resource->limits[2], ylimits);
+
+ if (group_count < 4)
+ return;
+
+ offset = IPA_REG_DST_RSRC_GRP_45_RSRC_TYPE_N_OFFSET(resource->type);
+ ylimits = group_count == 5 ? NULL : &resource->limits[5];
+ ipa_resource_config_common(ipa, offset, &resource->limits[4], ylimits);
}
static int
@@ -471,15 +492,11 @@ ipa_resource_config(struct ipa *ipa, const struct ipa_resource_data *data)
if (!ipa_resource_limits_valid(ipa, data))
return -EINVAL;
- for (i = 0; i < data->resource_src_count; i++) {
- ipa_resource_config_src_01(ipa, &data->resource_src[i]);
- ipa_resource_config_src_23(ipa, &data->resource_src[i]);
- }
+ for (i = 0; i < data->resource_src_count; i++)
+ ipa_resource_config_src(ipa, data->resource_src);
- for (i = 0; i < data->resource_dst_count; i++) {
- ipa_resource_config_dst_01(ipa, &data->resource_dst[i]);
- ipa_resource_config_dst_23(ipa, &data->resource_dst[i]);
- }
+ for (i = 0; i < data->resource_dst_count; i++)
+ ipa_resource_config_dst(ipa, data->resource_dst);
return 0;
}