diff options
author | Alex Elder <elder@linaro.org> | 2021-02-12 17:34:00 +0300 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2021-02-13 03:54:17 +0300 |
commit | 2d65ed76924bc772d3974b0894d870b1aa63b34a (patch) | |
tree | ceecafa621693cc3763ae3c4aeb9cdbf90fcb98e | |
parent | 4c7ccfcd09fdc7f9edd1e453340be188f4044d8c (diff) | |
download | linux-2d65ed76924bc772d3974b0894d870b1aa63b34a.tar.xz |
net: ipa: fix register write command validation
In ipa_cmd_register_write_valid() we verify that values we will
supply to a REGISTER_WRITE IPA immediate command will fit in
the fields that need to hold them. This patch fixes some issues
in that function and ipa_cmd_register_write_offset_valid().
The dev_err() call in ipa_cmd_register_write_offset_valid() has
some printf format errors:
- The name of the register (corresponding to the string format
specifier) was not supplied.
- The IPA base offset and offset need to be supplied separately to
match the other format specifiers.
Also make the ~0 constant used there to compute the maximum
supported offset value explicitly unsigned.
There are two other issues in ipa_cmd_register_write_valid():
- There's no need to check the hash flush register for platforms
(like IPA v4.2) that do not support hashed tables
- The highest possible endpoint number, whose status register
offset is computed, is COUNT - 1, not COUNT.
Fix these problems, and add some additional commentary.
Signed-off-by: Alex Elder <elder@linaro.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ipa/ipa_cmd.c | 32 |
1 files changed, 24 insertions, 8 deletions
diff --git a/drivers/net/ipa/ipa_cmd.c b/drivers/net/ipa/ipa_cmd.c index 97b50fee6008..fd8bf6468d31 100644 --- a/drivers/net/ipa/ipa_cmd.c +++ b/drivers/net/ipa/ipa_cmd.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 /* Copyright (c) 2012-2018, The Linux Foundation. All rights reserved. - * Copyright (C) 2019-2020 Linaro Ltd. + * Copyright (C) 2019-2021 Linaro Ltd. */ #include <linux/types.h> @@ -244,11 +244,15 @@ static bool ipa_cmd_register_write_offset_valid(struct ipa *ipa, if (ipa->version != IPA_VERSION_3_5_1) bit_count += hweight32(REGISTER_WRITE_FLAGS_OFFSET_HIGH_FMASK); BUILD_BUG_ON(bit_count > 32); - offset_max = ~0 >> (32 - bit_count); + offset_max = ~0U >> (32 - bit_count); + /* Make sure the offset can be represented by the field(s) + * that holds it. Also make sure the offset is not outside + * the overall IPA memory range. + */ if (offset > offset_max || ipa->mem_offset > offset_max - offset) { dev_err(dev, "%s offset too large 0x%04x + 0x%04x > 0x%04x)\n", - ipa->mem_offset + offset, offset_max); + name, ipa->mem_offset, offset, offset_max); return false; } @@ -261,12 +265,24 @@ static bool ipa_cmd_register_write_valid(struct ipa *ipa) const char *name; u32 offset; - offset = ipa_reg_filt_rout_hash_flush_offset(ipa->version); - name = "filter/route hash flush"; - if (!ipa_cmd_register_write_offset_valid(ipa, name, offset)) - return false; + /* If hashed tables are supported, ensure the hash flush register + * offset will fit in a register write IPA immediate command. + */ + if (ipa->version != IPA_VERSION_4_2) { + offset = ipa_reg_filt_rout_hash_flush_offset(ipa->version); + name = "filter/route hash flush"; + if (!ipa_cmd_register_write_offset_valid(ipa, name, offset)) + return false; + } - offset = IPA_REG_ENDP_STATUS_N_OFFSET(IPA_ENDPOINT_COUNT); + /* Each endpoint can have a status endpoint associated with it, + * and this is recorded in an endpoint register. If the modem + * crashes, we reset the status endpoint for all modem endpoints + * using a register write IPA immediate command. Make sure the + * worst case (highest endpoint number) offset of that endpoint + * fits in the register write command field(s) that must hold it. + */ + offset = IPA_REG_ENDP_STATUS_N_OFFSET(IPA_ENDPOINT_COUNT - 1); name = "maximal endpoint status"; if (!ipa_cmd_register_write_offset_valid(ipa, name, offset)) return false; |