| From fddcca5107051adf9e4481d2a79ae0616577fd2c Mon Sep 17 00:00:00 2001 |
| From: Arnd Bergmann <arnd@arndb.de> |
| Date: Mon, 29 Feb 2016 13:20:28 +0100 |
| Subject: mtd: avoid stack overflow in MTD CFI code |
| |
| From: Arnd Bergmann <arnd@arndb.de> |
| |
| commit fddcca5107051adf9e4481d2a79ae0616577fd2c upstream. |
| |
| When map_word gets too large, we use a lot of kernel stack, and for |
| MTD_MAP_BANK_WIDTH_32, this means we use more than the recommended |
| 1024 bytes in a number of functions: |
| |
| drivers/mtd/chips/cfi_cmdset_0020.c: In function 'cfi_staa_write_buffers': |
| drivers/mtd/chips/cfi_cmdset_0020.c:651:1: warning: the frame size of 1336 bytes is larger than 1024 bytes [-Wframe-larger-than=] |
| drivers/mtd/chips/cfi_cmdset_0020.c: In function 'cfi_staa_erase_varsize': |
| drivers/mtd/chips/cfi_cmdset_0020.c:972:1: warning: the frame size of 1208 bytes is larger than 1024 bytes [-Wframe-larger-than=] |
| drivers/mtd/chips/cfi_cmdset_0001.c: In function 'do_write_buffer': |
| drivers/mtd/chips/cfi_cmdset_0001.c:1835:1: warning: the frame size of 1240 bytes is larger than 1024 bytes [-Wframe-larger-than=] |
| |
| This can be avoided if all operations on the map word are done |
| indirectly and the stack gets reused between the calls. We can |
| mostly achieve this by selecting MTD_COMPLEX_MAPPINGS whenever |
| MTD_MAP_BANK_WIDTH_32 is set, but for the case that no other |
| bank width is enabled, we also need to use a non-constant |
| map_bankwidth() to convince the compiler to use less stack. |
| |
| Signed-off-by: Arnd Bergmann <arnd@arndb.de> |
| [Brian: this patch mostly achieves its goal by forcing |
| MTD_COMPLEX_MAPPINGS (and the accompanying indirection) for 256-bit |
| mappings; the rest of the change is mostly a wash, though it helps |
| reduce stack size slightly. If we really care about supporting |
| 256-bit mappings though, we should consider rewriting some of this |
| code to avoid keeping and assigning so many 256-bit objects on the |
| stack.] |
| Signed-off-by: Brian Norris <computersforpeace@gmail.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/mtd/chips/Kconfig | 1 + |
| include/linux/mtd/map.h | 19 +++++++------------ |
| 2 files changed, 8 insertions(+), 12 deletions(-) |
| |
| --- a/drivers/mtd/chips/Kconfig |
| +++ b/drivers/mtd/chips/Kconfig |
| @@ -110,6 +110,7 @@ config MTD_MAP_BANK_WIDTH_16 |
| |
| config MTD_MAP_BANK_WIDTH_32 |
| bool "Support 256-bit buswidth" if MTD_CFI_GEOMETRY |
| + select MTD_COMPLEX_MAPPINGS if HAS_IOMEM |
| default n |
| help |
| If you wish to support CFI devices on a physical bus which is |
| --- a/include/linux/mtd/map.h |
| +++ b/include/linux/mtd/map.h |
| @@ -122,18 +122,13 @@ |
| #endif |
| |
| #ifdef CONFIG_MTD_MAP_BANK_WIDTH_32 |
| -# ifdef map_bankwidth |
| -# undef map_bankwidth |
| -# define map_bankwidth(map) ((map)->bankwidth) |
| -# undef map_bankwidth_is_large |
| -# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8) |
| -# undef map_words |
| -# define map_words(map) map_calc_words(map) |
| -# else |
| -# define map_bankwidth(map) 32 |
| -# define map_bankwidth_is_large(map) (1) |
| -# define map_words(map) map_calc_words(map) |
| -# endif |
| +/* always use indirect access for 256-bit to preserve kernel stack */ |
| +# undef map_bankwidth |
| +# define map_bankwidth(map) ((map)->bankwidth) |
| +# undef map_bankwidth_is_large |
| +# define map_bankwidth_is_large(map) (map_bankwidth(map) > BITS_PER_LONG/8) |
| +# undef map_words |
| +# define map_words(map) map_calc_words(map) |
| #define map_bankwidth_is_32(map) (map_bankwidth(map) == 32) |
| #undef MAX_MAP_BANKWIDTH |
| #define MAX_MAP_BANKWIDTH 32 |